Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Llm Chain Laravel Package

php-llm/llm-chain

php-llm/llm-chain is a Laravel/PHP package for composing multi-step LLM workflows, chaining prompts and model calls into reusable pipelines with a fluent API. Build reliable AI features with structured, maintainable chains.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is a rebrand with a breaking change. php-llm/llm-chain 0.25.0 is now Symfony AI (PR #390, marked chore!). Before anything else, confirm the new Composer package name and namespace root on Packagist/GitHub — the PhpLlm\LlmChain\... namespace is not expected to survive, and every use statement in your app will need updating. If you are mid-project, pin to 0.24.1 until you can do the migration in one pass.

Minimal steps after upgrading:

  1. composer require the new Symfony AI package(s) — the project is a monorepo, so you will likely pull a core package plus a platform bridge (OpenAI, Anthropic, Albert, Ollama, etc.).
  2. Publish/verify config. Credentials are resolved from platform-specific env vars; set them in .env rather than in code.
  3. Register the platform + a chat model in a service provider or a small dedicated AiServiceProvider, and bind it to an interface so tests can swap in a fake.
  4. Run one prompt end-to-end from php artisan tinker before wiring it into a controller.

First use case: a single non-streaming Chat call behind a queued job — this exercises the credential path, the HTTP client, and the message/response objects with the least surface area. Add streaming and tools only once that is green.

If you are on Laravel 11+, the HTTP client and Http::fake() integration is the fastest debugging lever you have; make sure your first call goes through Laravel's HTTP client factory so you can assert on requests in tests.

Implementation Patterns

Wrap the platform in a container binding. Do not new up model objects in controllers. Bind a configured chat model (or a small wrapper around it) as a singleton and inject it. This is the difference between a package you can test and one you cannot.

$this->app->singleton(ChatModel::class, fn () => /* platform factory */);

Chain as a pipeline, not a god-object. The package's core abstraction is a chain of inputs → model call → output processors. Keep each processor single-purpose (e.g. "inject RAG context", "inject memory", "format as JSON") so you can reorder and test them independently. Compose chains in a dedicated class per feature rather than assembling them inline.

Memory injection now reaches the system prompt. 0.25.0 adds basic setup for injecting memory into the system prompt (PR #387). This is the right place for durable facts about the user or tenant. Keep the injected block small and deterministic — system prompt memory competes with your instructions for the model's attention, and it is the easiest thing to accidentally make non-cacheable.

Message IDs are now AbstractUid&TimeBasedUidInterface. PR #384 loosens the type so any time-ordered UID works. In practice: stop asserting on a concrete UID class in your tests, and stop assuming UUIDv4. If you persist message IDs to the database, confirm your column type accepts the new format before deploying.

Use tool calling for side effects, not for data fetching. Tools that mutate state (create a ticket, send a mail) should be dispatched as jobs from inside the tool so a retried or hallucinated call is at least idempotent and observable. Read-only tools can run inline.

Queue everything user-facing. Streaming from a queue is awkward; the pragmatic split is: synchronous + streamed for interactive chat UI, queued + non-streamed for summaries, classification, embeddings, and anything triggered by a model event.

Fake at the HTTP layer in tests, and additionally provide a stub chat model for unit tests of your own chain/processor logic. Two layers, two purposes: HTTP fakes catch payload regressions, stub models keep processor tests fast.

Albert API support (PR #366) is a French government LLM gateway — useful if you need EU-hosted inference for compliance. It follows the same platform interface as the others, so your abstraction should already accommodate it; if it does not, your abstraction is too thin.

Gotchas and Tips

  • The rename is the migration. chore!: PHP LLM becomes Symfony AI is a hard break. Search-and-replace PhpLlm\ across your codebase, config, and any serialized class names in queues (failed_jobs, jobs payloads) — in-flight queued jobs referencing old class names will fail after deploy. Drain the queue before switching.
  • Composer suggests were replaced with runtime checks (PR #385). Missing optional dependencies now surface as exceptions at call time rather than as Composer hints. If you only installed the core package, an optional feature (a platform bridge, a vector store, a tokenizer) will fail at runtime, not at composer install. Install every optional package you actually intend to use, and add a boot-time smoke test.
  • Config caching hides env changes. php artisan config:cache in deploy, and remember that credentials resolved inside a package constructor may be read before your config is finalized. Resolve lazily, inside the binding closure.
  • Streaming + Laravel response lifecycle. Use a streamed response and disable output buffering; middleware that inspects or re-wraps the response body will break or buffer streams. Keep streaming routes out of body-inspecting middleware groups.
  • Token/error handling is not free. Rate limits and context-length errors come back as exceptions from the platform layer. Catch them at the job level, retry with backoff on 429, and never retry on context-length — truncate or fail loudly instead.
  • Extension points to reach for first: custom OutputProcessors (post-processing, validation, JSON repair), custom Toolbox/tool definitions (wrap your existing Laravel actions), and a custom platform implementation if you are on an internal gateway — the platform interface is the smallest thing to implement.
  • Debugging: log the full request/response payloads behind a config flag in non-production. Provider errors are frequently caused by a silently reordered message list or a stray empty system message, and neither is visible from the exception message.
  • Pin the minor version. Pre-1.0 with a breaking rename already shipped, this package is moving fast. "~0.25.0" with a scheduled review beats "^0.25" for anything in production.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings