44
55namespace PhpLlm \LlmChainBundle \DependencyInjection ;
66
7+ use PhpLlm \LlmChain \Bridge \Anthropic \Claude ;
8+ use PhpLlm \LlmChain \Bridge \Azure \Store \SearchStore as AzureSearchStore ;
9+ use PhpLlm \LlmChain \Bridge \ChromaDB \Store as ChromaDBStore ;
10+ use PhpLlm \LlmChain \Bridge \Meta \Llama ;
11+ use PhpLlm \LlmChain \Bridge \MongoDB \Store as MongoDBStore ;
12+ use PhpLlm \LlmChain \Bridge \OpenAI \Embeddings ;
13+ use PhpLlm \LlmChain \Bridge \OpenAI \Embeddings \ModelClient as OpenAIEmbeddingsModelClient ;
14+ use PhpLlm \LlmChain \Bridge \OpenAI \GPT ;
15+ use PhpLlm \LlmChain \Bridge \OpenAI \GPT \ModelClient as OpenAIGPTModelClient ;
16+ use PhpLlm \LlmChain \Bridge \Pinecone \Store as PineconeStore ;
17+ use PhpLlm \LlmChain \Bridge \Voyage \Voyage ;
18+ use PhpLlm \LlmChain \Chain ;
719use PhpLlm \LlmChain \Chain \InputProcessor ;
820use PhpLlm \LlmChain \Chain \OutputProcessor ;
9- use PhpLlm \LlmChain \EmbeddingsModel ;
10- use PhpLlm \LlmChain \LanguageModel ;
11- use PhpLlm \LlmChain \OpenAI \Model \Embeddings ;
12- use PhpLlm \LlmChain \OpenAI \Model \Gpt ;
13- use PhpLlm \LlmChain \OpenAI \Platform ;
14- use PhpLlm \LlmChain \OpenAI \Platform \Azure as AzurePlatform ;
15- use PhpLlm \LlmChain \OpenAI \Platform \OpenAI as OpenAIPlatform ;
16- use PhpLlm \LlmChain \Store \Azure \SearchStore as AzureSearchStore ;
17- use PhpLlm \LlmChain \Store \ChromaDB \Store as ChromaDBStore ;
18- use PhpLlm \LlmChain \Store \MongoDB \Store as MongoDBStore ;
19- use PhpLlm \LlmChain \Store \Pinecone \Store as PineconeStore ;
21+ use PhpLlm \LlmChain \Chain \ToolBox \Attribute \AsTool ;
22+ use PhpLlm \LlmChain \Embedder ;
23+ use PhpLlm \LlmChain \Platform \ModelClient ;
24+ use PhpLlm \LlmChain \Platform \ResponseConverter ;
2025use PhpLlm \LlmChain \Store \StoreInterface ;
2126use PhpLlm \LlmChain \Store \VectorStoreInterface ;
22- use PhpLlm \LlmChain \ToolBox \Attribute \AsTool ;
2327use PhpLlm \LlmChainBundle \Profiler \DataCollector ;
24- use PhpLlm \LlmChainBundle \Profiler \TraceableLanguageModel ;
2528use PhpLlm \LlmChainBundle \Profiler \TraceableToolBox ;
2629use Symfony \Component \Config \FileLocator ;
2730use Symfony \Component \DependencyInjection \ChildDefinition ;
@@ -41,25 +44,27 @@ public function load(array $configs, ContainerBuilder $container): void
4144 $ configuration = new Configuration ();
4245 $ config = $ this ->processConfiguration ($ configuration , $ configs );
4346
44- foreach ($ config ['platforms ' ] as $ platformName => $ platform ) {
45- $ this ->processPlatformConfig ($ platformName , $ platform , $ container );
46- }
47- if (1 === count ($ config ['platforms ' ]) && isset ($ platformName )) {
48- $ container ->setAlias (Platform::class, 'llm_chain.platform. ' .$ platformName );
47+ if (isset ($ config ['platform ' ])) {
48+ if (1 !== count ($ config ['platform ' ])) {
49+ throw new \InvalidArgumentException ('Only one platform at a time is supported. ' );
50+ }
51+
52+ $ type = array_keys ($ config ['platform ' ]);
53+ $ this ->processPlatformConfig ($ type [0 ], $ config ['platform ' ][$ type [0 ]], $ container );
4954 }
5055
51- foreach ($ config ['llms ' ] as $ llmName => $ llm ) {
52- $ this ->processLlmConfig ( $ llmName , $ llm , $ container );
56+ foreach ($ config ['chains ' ] as $ chainName => $ chain ) {
57+ $ this ->processChainConfig ( $ chainName , $ chain , $ container );
5358 }
54- if (1 === count ($ config ['llms ' ]) && isset ($ llmName )) {
55- $ container ->setAlias (LanguageModel ::class, 'llm_chain.llm . ' .$ llmName );
59+ if (1 === count ($ config ['chains ' ]) && isset ($ chainName )) {
60+ $ container ->setAlias (Chain ::class, 'llm_chain.chain . ' .$ chainName );
5661 }
5762
58- foreach ($ config ['embeddings ' ] as $ embeddingsName => $ embeddings ) {
59- $ this ->processEmbeddingsConfig ( $ embeddingsName , $ embeddings , $ container );
63+ foreach ($ config ['embedder ' ] as $ embedderName => $ embedder ) {
64+ $ this ->processEmbedderConfig ( $ embedderName , $ embedder , $ container );
6065 }
61- if (1 === count ($ config ['embeddings ' ]) && isset ($ embeddingsName )) {
62- $ container ->setAlias (EmbeddingsModel ::class, 'llm_chain.embeddings . ' .$ embeddingsName );
66+ if (1 === count ($ config ['embedder ' ]) && isset ($ embedderName )) {
67+ $ container ->setAlias (Embedder ::class, 'llm_chain.embedder . ' .$ chainName );
6368 }
6469
6570 foreach ($ config ['stores ' ] as $ storeName => $ store ) {
@@ -82,6 +87,10 @@ public function load(array $configs, ContainerBuilder $container): void
8287 ->addTag ('llm_chain.chain.input_processor ' );
8388 $ container ->registerForAutoconfiguration (OutputProcessor::class)
8489 ->addTag ('llm_chain.chain.output_processor ' );
90+ $ container ->registerForAutoconfiguration (ModelClient::class)
91+ ->addTag ('llm_chain.platform.model_client ' );
92+ $ container ->registerForAutoconfiguration (ResponseConverter::class)
93+ ->addTag ('llm_chain.platform.response_converter ' );
8594
8695 if (false === $ container ->getParameter ('kernel.debug ' )) {
8796 $ container ->removeDefinition (DataCollector::class);
@@ -92,63 +101,65 @@ public function load(array $configs, ContainerBuilder $container): void
92101 /**
93102 * @param array<string, mixed> $platform
94103 */
95- private function processPlatformConfig (string $ name , array $ platform , ContainerBuilder $ container ): void
104+ private function processPlatformConfig (string $ type , array $ platform , ContainerBuilder $ container ): void
96105 {
97- if ('openai ' === $ platform ['type ' ]) {
98- $ definition = new ChildDefinition (OpenAIPlatform::class);
99- $ definition
106+ if ('openai ' === $ type ) {
107+ $ container ->getDefinition (OpenAIEmbeddingsModelClient::class)
100108 ->replaceArgument ('$apiKey ' , $ platform ['api_key ' ]);
101109
102- $ container ->setDefinition ('llm_chain.platform. ' .$ name , $ definition );
110+ $ container ->getDefinition (OpenAIGPTModelClient::class)
111+ ->replaceArgument ('$apiKey ' , $ platform ['api_key ' ]);
103112
104113 return ;
105114 }
106115
107- if ('azure ' === $ platform ['type ' ]) {
108- $ definition = new ChildDefinition (AzurePlatform::class);
109- $ definition
110- ->replaceArgument ('$baseUrl ' , $ platform ['base_url ' ])
111- ->replaceArgument ('$deployment ' , $ platform ['deployment ' ])
112- ->replaceArgument ('$apiKey ' , $ platform ['api_key ' ])
113- ->replaceArgument ('$apiVersion ' , $ platform ['version ' ]);
114-
115- $ container ->setDefinition ('llm_chain.platform. ' .$ name , $ definition );
116- }
116+ // TODO: Azure, Replicate, Ollama, etc.
117+ throw new \InvalidArgumentException (sprintf ('Platform "%s" is not supported for configuration via bundle at this point. ' , $ type ));
117118 }
118119
119- /**
120- * @param array<string, mixed> $llm
121- */
122- private function processLlmConfig (string $ name , array $ llm , ContainerBuilder $ container ): void
120+ private function processChainConfig (string $ name , array $ config , ContainerBuilder $ container ): void
123121 {
124- $ platform = isset ($ llm ['platform ' ]) ? 'llm_chain.platform. ' .$ llm ['platform ' ] : Platform::class;
125-
126- $ definition = new ChildDefinition (Gpt::class);
127- $ definition ->replaceArgument ('$platform ' , new Reference ($ platform ));
122+ ['name ' => $ modelName , 'version ' => $ version , 'options ' => $ options ] = $ config ['model ' ];
123+
124+ $ llmClass = match (strtolower ($ modelName )) {
125+ 'gpt ' => GPT ::class,
126+ 'claude ' => Claude::class,
127+ 'llama ' => Llama::class,
128+ default => throw new \InvalidArgumentException (sprintf ('Model "%s" is not supported. ' , $ modelName )),
129+ };
130+ $ llmDefinition = (new Definition ($ llmClass ))
131+ ->setArguments ([
132+ '$version ' => $ version ,
133+ '$options ' => $ options ,
134+ ]);
135+ $ container ->setDefinition ('llm_chain.chain. ' .$ name .'.llm ' , $ llmDefinition );
128136
129- $ container ->setDefinition ('llm_chain.llm. ' .$ name , $ definition );
137+ $ definition = (new ChildDefinition ('llm_chain.chain.abstract ' ))
138+ ->replaceArgument ('$llm ' , new Reference ('llm_chain.chain. ' .$ name .'.llm ' ));
130139
131- if ($ container ->getParameter ('kernel.debug ' )) {
132- $ traceable = new Definition (TraceableLanguageModel::class);
133- $ traceable ->setDecoratedService ('llm_chain.llm. ' .$ name );
134- $ traceable ->addTag ('llm_chain.traceable_llm ' );
135- $ traceable ->setArgument ('$llm ' , new Reference ('llm_chain.llm. ' .$ name .'.debug.inner ' ));
136- $ traceable ->setArgument ('$name ' , $ name );
137- $ container ->setDefinition ('llm_chain.llm. ' .$ name .'.debug ' , $ traceable );
138- }
140+ $ container ->setDefinition ('llm_chain.chain. ' .$ name , $ definition );
139141 }
140142
141- /**
142- * @param array<string, mixed> $embeddings
143- */
144- private function processEmbeddingsConfig (string $ name , array $ embeddings , ContainerBuilder $ container ): void
143+ private function processEmbedderConfig (int |string $ name , mixed $ config , ContainerBuilder $ container )
145144 {
146- $ platform = isset ($ embeddings ['platform ' ]) ? 'llm_chain.platform. ' .$ embeddings ['platform ' ] : Platform::class;
145+ ['name ' => $ modelName , 'version ' => $ version , 'options ' => $ options ] = $ config ['model ' ];
146+
147+ $ modelClass = match (strtolower ($ modelName )) {
148+ 'openai ' => Embeddings::class,
149+ 'voyage ' => Voyage::class,
150+ default => throw new \InvalidArgumentException (sprintf ('Model "%s" is not supported. ' , $ modelName )),
151+ };
152+ $ modelDefinition = (new Definition ($ modelClass ))
153+ ->setArguments ([
154+ '$version ' => $ version ,
155+ '$options ' => $ options ,
156+ ]);
157+ $ container ->setDefinition ('llm_chain.embedder. ' .$ name .'.embeddings ' , $ modelDefinition );
147158
148- $ definition = new ChildDefinition (Embeddings::class);
149- $ definition ->replaceArgument ('$platform ' , new Reference ($ platform ));
159+ $ definition = ( new ChildDefinition (' llm_chain.embedder.abstract ' ))
160+ ->replaceArgument ('$embeddings ' , new Reference (' llm_chain.embedder. ' . $ name . ' .embeddings ' ));
150161
151- $ container ->setDefinition ('llm_chain.embeddings . ' .$ name , $ definition );
162+ $ container ->setDefinition ('llm_chain.embedder . ' .$ name , $ definition );
152163 }
153164
154165 /**
0 commit comments