Important
PHP LLM becomes Symfony AI - this project moved to github.com/symfony/ai. Please use the new repository for all future development, issues, and contributions. Thanks for your contributions - we hope to see you at Symfony AI!
PHP library for building LLM-based and AI-based features and applications.
This library is not stable yet, but still rather experimental. Feel free to try it out, give feedback, ask questions, contribute, or share your use cases. Abstractions, concepts, and interfaces are not final and potentially subject of change.
- PHP 8.2 or higher
The recommended way to install LLM Chain is through Composer:
composer require php-llm/llm-chainWhen using Symfony Framework, check out the integration bundle php-llm/llm-chain-bundle.
See the examples folder to run example implementations using this library.
Depending on the example you need to export different environment variables
for API keys or deployment configurations or create a .env.local based on .env file.
To run all examples, use make run-examples or php example - to run a subgroup like all HuggingFace related examples
use php example huggingface.
For a more sophisticated demo, see the Symfony Demo Application.
LLM Chain categorizes two main types of models: Language Models and Embeddings Models. On top of that, there are other models, like text-to-speech, image generation, or classification models that are also supported.
Language Models, like GPT, Claude, and Llama, as essential centerpiece of LLM applications and Embeddings Models as supporting models to provide vector representations of a text.
Those models are provided by different platforms, like OpenAI, Azure, Google, Replicate, and others.
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\Embeddings;
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\GPT;
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\PlatformFactory;
// Platform: OpenAI$platform = PlatformFactory::create($_ENV['OPENAI_API_KEY']);
// Language Model: GPT (OpenAI)$llm = newGPT(GPT::GPT_4O_MINI);
// Embeddings Model: Embeddings (OpenAI)$embeddings = newEmbeddings();- Language Models
- OpenAI's GPT with OpenAI and Azure as Platform
- Anthropic's Claude with Anthropic and AWS as Platform
- Meta's Llama with Azure, Ollama, Replicate and AWS as Platform
- Google's Gemini with Google and OpenRouter as Platform
- DeepSeek's R1 with OpenRouter as Platform
- Amazon's Nova with AWS as Platform
- Mistral's Mistral with Mistral as Platform
- Albert API models with Albert as Platform (French government's sovereign AI gateway)
- Embeddings Models
- OpenAI's Text Embeddings with OpenAI and Azure as Platform
- Voyage's Embeddings with Voyage as Platform
- Mistral Embed with Mistral as Platform
- Other Models
- OpenAI's Dall·E with OpenAI as Platform
- OpenAI's Whisper with OpenAI and Azure as Platform
- All models provided by HuggingFace can be listed with
make huggingface-modelsAnd more filtered withphp examples/huggingface/_model-listing.php --provider=hf-inference --task=object-detection
See issue #28 for planned support of other models and platforms.
The core feature of LLM Chain is to interact with language models via messages. This interaction is done by sending a MessageBag to a Chain, which takes care of LLM invocation and response handling.
Messages can be of different types, most importantly UserMessage, SystemMessage, or AssistantMessage, and can also
have different content types, like Text, Image or Audio.
Each message automatically receives a unique identifier (UUID v7) upon creation. This provides several benefits:
- Traceability: Track individual messages through your application
- Time-ordered: UUIDs are naturally sortable by creation time
- Timestamp extraction: Get the exact creation time from the ID
- Database-friendly: Sequential nature improves index performance
usePhpLlm\LlmChain\Platform\Message\Message;
$message = Message::ofUser('Hello, AI!');
// Access the unique ID$id = $message->getId(); // Returns Symfony\Component\Uid\Uuid instance// Extract creation timestamp$createdAt = $id->getDateTime(); // Returns \DateTimeImmutableecho$createdAt->format('Y-m-d H:i:s.u'); // e.g., "2025-06-29 15:30:45.123456"// Get string representationecho$id->toRfc4122(); // e.g., "01928d1f-6f2e-7123-a456-123456789abc"usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
// Platform & LLM instantiation$chain = newChain($platform, $model);
$messages = newMessageBag(
Message::forSystem('You are a helpful chatbot answering questions about LLM Chain.'),
Message::ofUser('Hello, how are you?'),
);
$response = $chain->call($messages);
echo$response->getContent(); // "I'm fine, thank you. How can I help you today?"The MessageInterface and Content interface help to customize this process if needed, e.g. additional state handling.
The second parameter of the call method is an array of options, which can be used to configure the behavior of the
chain, like stream, output_structure, or response_format. This behavior is a combination of features provided by
the underlying model and platform, or additional features provided by processors registered to the chain.
Options designed for additional features provided by LLM Chain can be found in this documentation. For model- and platform-specific options, please refer to the respective documentation.
// Chain and MessageBag instantiation$response = $chain->call($messages, [
'temperature' => 0.5, // example option controlling the randomness of the response, e.g. GPT and Claude'n' => 3, // example option controlling the number of responses generated, e.g. GPT
]);- Anthropic's Claude
- OpenAI's GPT with Azure
- OpenAI's GPT
- OpenAI's o1
- Meta's Llama with Azure
- Meta's Llama with Ollama
- Meta's Llama with Replicate
- Google's Gemini with Google
- Google's Gemini with OpenRouter
- Mistral's Mistral with Mistral
- Albert API (French Sovereign AI)
To integrate LLMs with your application, LLM Chain supports tool calling out of the box. Tools are services that can be called by the LLM to provide additional features or process data.
Some platforms provide built-in server-side tools for enhanced capabilities without custom implementations:
- Google Gemini - URL Context, Google Search, Code Execution
Tool calling can be enabled by registering the processors in the chain:
usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Chain\Toolbox\ChainProcessor;
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
// Platform & LLM instantiation$yourTool = newYourTool();
$toolbox = Toolbox::create($yourTool);
$toolProcessor = newChainProcessor($toolbox);
$chain = newChain($platform, $model, inputProcessors: [$toolProcessor], outputProcessors: [$toolProcessor]);Custom tools can basically be any class, but must configure by the #[AsTool] attribute.
usePhpLlm\LlmChain\Toolbox\Attribute\AsTool;
#[AsTool('company_name', 'Provides the name of your company')]
finalclass CompanyName
{
publicfunction__invoke(): string
{
return'ACME Corp.';
}
}In the end, the tool's response needs to be a string, but LLM Chain converts arrays and objects, that implement the
JsonSerializable interface, to JSON strings for you. So you can return arrays or objects directly from your tool.
You can configure the method to be called by the LLM with the #[AsTool] attribute and have multiple tools per class:
usePhpLlm\LlmChain\Toolbox\Attribute\AsTool;
#[AsTool(
name: 'weather_current',
description: 'get current weather for a location',
method: 'current',
)]
#[AsTool(
name: 'weather_forecast',
description: 'get weather forecast for a location',
method: 'forecast',
)]
finalreadonlyclass OpenMeteo
{
publicfunctioncurrent(float$latitude, float$longitude): array
{
// ...
}
publicfunctionforecast(float$latitude, float$longitude): array
{
// ...
}
}LLM Chain generates a JSON Schema representation for all tools in the Toolbox based on the #[AsTool] attribute and
method arguments and param comments in the doc block. Additionally, JSON Schema support validation rules, which are
partially support by LLMs like GPT.
To leverage this, configure the #[With] attribute on the method arguments of your tool:
usePhpLlm\LlmChain\Chain\Toolbox\Attribute\AsTool;
usePhpLlm\LlmChain\Platform\Contract\JsonSchema\Attribute\With;
#[AsTool('my_tool', 'Example tool with parameters requirements.')]
finalclass MyTool
{
/** * @param string $name The name of an object * @param int $number The number of an object */publicfunction__invoke(
#[With(pattern: '/([a-z0-1]){5}/')]
string$name,
#[With(minimum: 0, maximum: 10)]
int$number,
): string {
// ...
}
}See attribute class With for all available options.
Note
Please be aware, that this is only converted in a JSON Schema for the LLM to respect, but not validated by LLM Chain.
In some cases you might want to use third-party tools, which are not part of your application. Adding the #[AsTool]
attribute to the class is not possible in those cases, but you can explicitly register the tool in the MemoryFactory:
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
usePhpLlm\LlmChain\Chain\Toolbox\ToolFactory\MemoryToolFactory;
useSymfony\Component\Clock\Clock;
$metadataFactory = (newMemoryToolFactory())
->addTool(Clock::class, 'clock', 'Get the current date and time', 'now');
$toolbox = newToolbox($metadataFactory, [newClock()]);Note
Please be aware that not all return types are supported by the toolbox, so a decorator might still be needed.
This can be combined with the ChainFactory which enables you to use explicitly registered tools and #[AsTool] tagged
tools in the same chain - which even enables you to overwrite the pre-existing configuration of a tool:
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
usePhpLlm\LlmChain\Chain\Toolbox\ToolFactory\ChainFactory;
usePhpLlm\LlmChain\Chain\Toolbox\ToolFactory\MemoryToolFactory;
usePhpLlm\LlmChain\Chain\Toolbox\ToolFactory\ReflectionToolFactory;
$reflectionFactory = newReflectionToolFactory(); // Register tools with #[AsTool] attribute$metadataFactory = (newMemoryToolFactory()) // Register or overwrite tools explicitly
->addTool(...);
$toolbox = newToolbox(newChainFactory($metadataFactory, $reflectionFactory), [...]);Note
The order of the factories in the ChainFactory matters, as the first factory has the highest priority.
Similar to third-party tools, you can also use a chain as a tool in another chain. This can be useful to encapsulate complex logic or to reuse a chain in multiple places or hide sub-chains from the LLM.
usePhpLlm\LlmChain\Chain\Toolbox\ToolFactory\MemoryToolFactory;
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
usePhpLlm\LlmChain\Chain\Toolbox\Tool\Chain;
// Chain was initialized before$chainTool = newChain($chain);
$metadataFactory = (newMemoryToolFactory())
->addTool($chainTool, 'research_agent', 'Meaningful description for sub-chain');
$toolbox = newToolbox($metadataFactory, [$chainTool]);To gracefully handle errors that occur during tool calling, e.g. wrong tool names or runtime errors, you can use the
FaultTolerantToolbox as a decorator for the Toolbox. It will catch the exceptions and return readable error messages
to the LLM.
usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Chain\Toolbox\ChainProcessor;
usePhpLlm\LlmChain\Chain\Toolbox\FaultTolerantToolbox;
// Platform, LLM & Toolbox instantiation$toolbox = newFaultTolerantToolbox($innerToolbox);
$toolProcessor = newChainProcessor($toolbox);
$chain = newChain($platform, $model, inputProcessor: [$toolProcessor], outputProcessor: [$toolProcessor]);To limit the tools provided to the LLM in a specific chain call to a subset of the configured tools, you can use the
tools option with a list of tool names:
$this->chain->call($messages, ['tools' => ['tavily_search']]);To react to the result of a tool, you can implement an EventListener or EventSubscriber, that listens to the
ToolCallsExecuted event. This event is dispatched after the Toolbox executed all current tool calls and enables
you to skip the next LLM call by setting a response yourself:
$eventDispatcher->addListener(ToolCallsExecuted::class, function (ToolCallsExecuted$event): void {
foreach ($event->toolCallResultsas$toolCallResult) {
if (str_starts_with($toolCallResult->toolCall->name, 'weather_')) {
$event->response = newStructuredResponse($toolCallResult->result);
}
}
});Sometimes you might wish to keep the tool messages (AssistantMessage containing the toolCalls and ToolCallMessage containing the response) in the context.
Enable the keepToolMessages flag of the toolbox' ChainProcessor to ensure those messages will be added to your MessageBag.
usePhpLlm\LlmChain\Chain\Toolbox\ChainProcessor;
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
// Platform & LLM instantiation$messages = newMessageBag(
Message::forSystem(<<<PROMPT Please answer all user questions only using the similary_search tool. Do not add information and if you cannot find an answer, say so. PROMPT),
Message::ofUser('...') // The user's question.
);
$yourTool = newYourTool();
$toolbox = Toolbox::create($yourTool);
$toolProcessor = newChainProcessor($toolbox, keepToolMessages: true);
$chain = newChain($platform, $llm, inputProcessor: [$toolProcessor], outputProcessor: [$toolProcessor]);
$response = $chain->call($messages);
// $messages will now include the tool messages- Brave Tool
- Clock Tool
- Crawler Tool
- SerpAPI Tool
- Tavily Tool
- Weather Tool with Event Listener
- Wikipedia Tool
- YouTube Transcriber Tool
LLM Chain supports document embedding and similarity search using vector stores like ChromaDB, Azure AI Search, MongoDB Atlas Search, or Pinecone.
For populating a vector store, LLM Chain provides the service Indexer, which requires an instance of an
EmbeddingsModel and one of StoreInterface, and works with a collection of Document objects as input:
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\Embeddings;
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\PlatformFactory;
usePhpLlm\LlmChain\Store\Bridge\Pinecone\Store;
usePhpLlm\LlmChain\Store\Indexer;
useProbots\Pinecone\Pinecone;
$indexer = newIndexer(
PlatformFactory::create($_ENV['OPENAI_API_KEY']),
newEmbeddings(),
newStore(Pinecone::client($_ENV['PINECONE_API_KEY'], $_ENV['PINECONE_HOST']),
);
$indexer->index($documents);The collection of Document instances is usually created by text input of your domain entities:
usePhpLlm\LlmChain\Store\Document\Metadata;
usePhpLlm\LlmChain\Store\Document\TextDocument;
foreach ($entitiesas$entity) {
$documents[] = newTextDocument(
id: $entity->getId(), // UUID instance
content: $entity->toString(), // Text representation of relevant data for embedding
metadata: newMetadata($entity->toArray()), // Array representation of an entity to be stored additionally
);
}Note
Not all data needs to be stored in the vector store, but you could also hydrate the original data entry based on the ID or metadata after retrieval from the store.*
In the end the chain is used in combination with a retrieval tool on top of the vector store, e.g. the built-in
SimilaritySearch tool provided by the library:
usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Chain\Toolbox\ChainProcessor;
usePhpLlm\LlmChain\Chain\Toolbox\Tool\SimilaritySearch;
usePhpLlm\LlmChain\Chain\Toolbox\Toolbox;
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
// Initialize Platform & Models$similaritySearch = newSimilaritySearch($model, $store);
$toolbox = Toolbox::create($similaritySearch);
$processor = newChain($toolbox);
$chain = newChain($platform, $model, [$processor], [$processor]);
$messages = newMessageBag(
Message::forSystem(<<<PROMPT Please answer all user questions only using the similary_search tool. Do not add information and if you cannot find an answer, say so. PROMPT),
Message::ofUser('...') // The user's question.
);
$response = $chain->call($messages);- Azure AI Search
- ChromaDB (requires
codewithkyrian/chromadb-phpas additional dependency) - MariaDB (requires
ext-pdo) - MongoDB Atlas Search (requires
mongodb/mongodbas additional dependency) - Pinecone (requires
probots-io/pinecone-phpas additional dependency)
See issue #28 for planned support of other models and platforms.
A typical use-case of LLMs is to classify and extract data from unstructured sources, which is supported by some models by features like Structured Output or providing a Response Format.
LLM Chain supports that use-case by abstracting the hustle of defining and providing schemas to the LLM and converting the response back to PHP objects.
To achieve this, a specific chain processor needs to be registered:
usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Chain\StructuredOutput\ChainProcessor;
usePhpLlm\LlmChain\Chain\StructuredOutput\ResponseFormatFactory;
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
usePhpLlm\LlmChain\Tests\Chain\StructuredOutput\Data\MathReasoning;
useSymfony\Component\Serializer\Encoder\JsonEncoder;
useSymfony\Component\Serializer\Normalizer\ObjectNormalizer;
useSymfony\Component\Serializer\Serializer;
// Initialize Platform and LLM$serializer = newSerializer([newObjectNormalizer()], [newJsonEncoder()]);
$processor = newChainProcessor(newResponseFormatFactory(), $serializer);
$chain = newChain($platform, $model, [$processor], [$processor]);
$messages = newMessageBag(
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
Message::ofUser('how can I solve 8x + 7 = -23'),
);
$response = $chain->call($messages, ['output_structure' => MathReasoning::class]);
dump($response->getContent()); // returns an instance of `MathReasoning` classAlso PHP array structures as response_format are supported, which also requires the chain processor mentioned above:
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
// Initialize Platform, LLM and Chain with processors and Clock tool$messages = newMessageBag(Message::ofUser('What date and time is it?'));
$response = $chain->call($messages, ['response_format' => [
'type' => 'json_schema',
'json_schema' => [
'name' => 'clock',
'strict' => true,
'schema' => [
'type' => 'object',
'properties' => [
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
],
'required' => ['date', 'time'],
'additionalProperties' => false,
],
],
]]);
dump($response->getContent()); // returns an arraySince LLMs usually generate a response word by word, most of them also support streaming the response using Server Side Events. LLM Chain supports that by abstracting the conversion and returning a Generator as content of the response.
usePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Message\Message;
usePhpLlm\LlmChain\Message\MessageBag;
// Initialize Platform and LLM$chain = newChain($model);
$messages = newMessageBag(
Message::forSystem('You are a thoughtful philosopher.'),
Message::ofUser('What is the purpose of an ant?'),
);
$response = $chain->call($messages, [
'stream' => true, // enable streaming of response text
]);
foreach ($response->getContent() as$word) {
echo$word;
}In a terminal application this generator can be used directly, but with a web app an additional layer like Mercure needs to be used.
Some LLMs also support images as input, which LLM Chain supports as Content type within the UserMessage:
usePhpLlm\LlmChain\Platform\Message\Content\Image;
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
// Initialize Platform, LLM & Chain$messages = newMessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__).'/tests/Fixture/image.jpg'), // Path to an image file
Image::fromDataUrl('data:image/png;base64,...'), // Data URL of an imagenewImageUrl('https://foo.com/bar.png'), // URL to an image
),
);
$response = $chain->call($messages);Similar to images, some LLMs also support audio as input, which is just another Content type within the UserMessage:
usePhpLlm\LlmChain\Platform\Message\Content\Audio;
usePhpLlm\LlmChain\Platform\Message\Message;
usePhpLlm\LlmChain\Platform\Message\MessageBag;
// Initialize Platform, LLM & Chain$messages = newMessageBag(
Message::ofUser(
'What is this recording about?',
Audio::fromFile(dirname(__DIR__).'/tests/Fixture/audio.mp3'), // Path to an audio file
),
);
$response = $chain->call($messages);Creating embeddings of word, sentences, or paragraphs is a typical use case around the interaction with LLMs, and
therefore LLM Chain implements a EmbeddingsModel interface with various models, see above.
The standalone usage results in an Vector instance:
usePhpLlm\LlmChain\Platform\Bridge\OpenAI\Embeddings;
// Initialize Platform$embeddings = newEmbeddings($platform, Embeddings::TEXT_3_SMALL);
$vectors = $platform->request($embeddings, $textInput)->asVectors();
dump($vectors[0]->getData()); // Array of float valuesPlatform supports multiple model calls in parallel, which can be useful to speed up the processing:
// Initialize Platform & Modelforeach ($inputsas$input) {
$responses[] = $platform->request($model, $input);
}
foreach ($responsesas$response) {
echo$response->asText().PHP_EOL;
}Note
This requires cURL and the ext-curl extension to be installed.
Note
Please be aware that some embedding models also support batch processing out of the box.
The behavior of the Chain is extendable with services that implement InputProcessor and/or OutputProcessor
interface. They are provided while instantiating the Chain instance:
usePhpLlm\LlmChain\Chain\Chain;
// Initialize Platform, LLM and processors$chain = newChain($platform, $model, $inputProcessors, $outputProcessors);InputProcessor instances are called in the chain before handing over the MessageBag and the $options array to the LLM and are
able to mutate both on top of the Input instance provided.
usePhpLlm\LlmChain\Chain\Input;
usePhpLlm\LlmChain\Chain\InputProcessorInterface;
usePhpLlm\LlmChain\Platform\Message\AssistantMessage;
finalclass MyProcessor implements InputProcessorInterface
{
publicfunctionprocessInput(Input$input): void
{
// mutate options$options = $input->getOptions();
$options['foo'] = 'bar';
$input->setOptions($options);
// mutate MessageBag$input->messages->append(newAssistantMessage(sprintf('Please answer using the locale %s', $this->locale)));
}
}OutputProcessor instances are called after the LLM provided a response and can - on top of options and messages -
mutate or replace the given response:
usePhpLlm\LlmChain\Chain\Output;
usePhpLlm\LlmChain\Chain\OutputProcessorInterface;
finalclass MyProcessor implements OutputProcessorInterface
{
publicfunctionprocessOutput(Output$out): void
{
// mutate responseif (str_contains($output->response->getContent, self::STOP_WORD)) {
$output->reponse = new TextReponse('Sorry, we were unable to find relevant information.')
}
}
}Both, Input and Output instances, provide access to the LLM used by the Chain, but the chain itself is only
provided, in case the processor implemented the ChainAwareProcessor interface, which can be combined with using the
ChainAwareTrait:
usePhpLlm\LlmChain\Chain\ChainAwareInterface;
usePhpLlm\LlmChain\Chain\ChainAwareTrait;
usePhpLlm\LlmChain\Chain\Output;
usePhpLlm\LlmChain\Chain\OutputProcessorInterface;
finalclass MyProcessor implements OutputProcessorInterface, ChainAwareInterface
{
use ChainAwareTrait;
publicfunctionprocessOutput(Output$out): void
{
// additional chain interaction$response = $this->chain->call(...);
}
}LLM Chain supports adding contextual memory to your conversations, which allows the model to recall past interactions or relevant information from different sources. Memory providers inject information into the system prompt, providing the model with context without changing your application logic.
Memory integration is handled through the MemoryInputProcessor and one or more MemoryProviderInterface implementations. Here's how to set it up:
<?phpusePhpLlm\LlmChain\Chain\Chain;
usePhpLlm\LlmChain\Chain\Memory\MemoryInputProcessor;
usePhpLlm\LlmChain\Chain\Memory\StaticMemoryProvider;
// Platform & LLM instantiation$personalFacts = newStaticMemoryProvider(
'My name is Wilhelm Tell',
'I wish to be a swiss national hero',
'I am struggling with hitting apples but want to be professional with the bow and arrow',
);
$memoryProcessor = newMemoryInputProcessor($personalFacts);
$chain = newChain($platform, $model, [$memoryProcessor]);
$messages = newMessageBag(Message::ofUser('What do we do today?'));
$response = $chain->call($messages);The library includes some implementations that are usable out of the box.
The static memory can be utilized to provide static information form, for example, user settings, basic knowledge of your application or any other thing that should be remembered als always there without the need of having it statically added to the system prompt by yourself.
usePhpLlm\LlmChain\Chain\Memory\StaticMemoryProvider;
$staticMemory = newStaticMemoryProvider(
'The user is allergic to nuts',
'The user prefers brief explanations',
);Based on an embedding storage the given user message is utilized to inject knowledge from the storage. This could be general knowledge that was stored there and could fit the users input without the need for tools or past conversation pieces that should be recalled for the current message bag.
usePhpLlm\LlmChain\Chain\Memory\EmbeddingProvider;
$embeddingsMemory = newEmbeddingProvider(
$platform,
$embeddings, // Your embeddings model to use for vectorizing the users message$store// Your vector store to query for fitting context
);The memory configuration is globally given for the chain. Sometimes there is the need to explicit disable the memory when it is not needed for some calls or calls are not in the wanted context for a call. So there is the option use_memory that is enabled by default but can be disabled on premise.
$response = $chain->call($messages, [
'use_memory' => false,
]);LLM Chain comes out of the box with an integration for HuggingFace which is a platform for hosting and sharing all kinds of models, including LLMs, embeddings, image generation, and classification models.
You can just instantiate the Platform with the corresponding HuggingFace bridge and use it with the task option:
usePhpLlm\LlmChain\Bridge\HuggingFace\Model;
usePhpLlm\LlmChain\Platform\Bridge\HuggingFace\PlatformFactory;
usePhpLlm\LlmChain\Platform\Bridge\HuggingFace\Task;
usePhpLlm\LlmChain\Platform\Message\Content\Image;
$platform = PlatformFactory::create($apiKey);
$model = newModel('facebook/detr-resnet-50');
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
$response = $platform->request($model, $image, [
'task' => Task::OBJECT_DETECTION, // defining a task is mandatory for internal request & response handling
]);
dump($response->asObject());- Audio Classification
- Automatic Speech Recognition
- Chat Completion
- Feature Extraction (Embeddings)
- Fill Mask
- Image Classification
- Image Segmentation.php
- Image-to-Text
- Object Detection
- Question Answering
- Sentence Similarity
- Summarization
- Table Question Answering
- Text Classification
- Text Generation
- Text-to-Image
- Token Classification
- Translation
- Zero-shot Classification
With installing the library codewithkyrian/transformers it is possible to run ONNX models locally
without the need of an extra tool like Ollama or a cloud service. This requires FFI
and comes with an extra setup, see TransformersPHP's Getting Starter.
The usage with LLM Chain is similar to the HuggingFace integration, and also requires the task option to be set:
useCodewithkyrian\Transformers\Pipelines\Task;
usePhpLlm\LlmChain\Bridge\TransformersPHP\Model;
usePhpLlm\LlmChain\Platform\Bridge\TransformersPHP\PlatformFactory;
$platform = PlatformFactory::create();
$model = newModel('Xenova/LaMini-Flan-T5-783M');
$response = $platform->request($model, 'How many continents are there in the world?', [
'task' => Task::Text2TextGeneration,
]);
echo$response->asText().PHP_EOL;Contributions are always welcome, so feel free to join the development of this library. To get started, please read the contribution guidelines.
Made with contrib.rocks.
For testing multi-modal features, the repository contains binary media content, with the following owners and licenses:
tests/Fixture/image.jpg: Chris F., Creative Commons, see pexels.comtests/Fixture/audio.mp3: davidbain, Creative Commons, see freesound.orgtests/Fixture/document.pdf: Chem8240ja, Public Domain, see Wikipedia