symfony/ai-gemini-platform
Google Gemini platform bridge for Symfony AI, letting your PHP apps call Gemini's generateContent and streaming endpoints plus batchEmbedContents embeddings through a consistent Symfony AI interface.
Provider strategy that stays reversible. The package is one implementation of Symfony AI's Platform contract, which is the real asset here: Gemini becomes a configuration choice rather than a codebase commitment. Decisions this unlocks include committing a roadmap to Gemini capabilities while retaining the option to run a second provider in parallel for fallback, or for a price/quality bake-off, without a rewrite. In a Laravel codebase this matters more than it sounds — the alternative is a bespoke GeminiService with Google's payload shapes leaking into controllers, jobs, and tests, and every future provider conversation starting from "how much of that do we rip out?"
AI unit economics, for the first time as a real number. Since v0.14.0, TokenUsage carries the model identifier alongside token counts. That turns "AI spend" from one opaque invoice line into a per-feature, per-model, per-tenant signal. Concretely it supports gross-margin analysis on AI-backed features before usage-based pricing is published, internal showback by team or customer, and a defensible answer to "is the premium tier worth it?" by attributing cost to the tier that actually served the request. Caveat for the decision record: this yields raw usage, not a price sheet. The rate table, aggregation job, and any invoicing logic are yours to build — budget them as a separate line item, not a freebie of the integration.
Routing as a measurable cost lever. The provider/model-routing layer plus per-model usage means "Flash for this intent, Pro for that one" becomes an A/B test with cost and quality readings rather than an architectural assertion. That converts a cost-reduction initiative into an experiment with a number attached, which is far easier to prioritise and to defend in a roadmap review.
Capability bets that are now week-scale spikes. Multimodal ingestion (images, audio, PDF), embeddings via batchEmbedContents with task types for semantic search or RAG, SSE streaming for latency-sensitive UI, and tool/function calling including server tools such as Google Maps. Each is cheap enough to prototype in discovery rather than needing a committed epic, which changes what legitimately belongs on the exploration backlog.
Build vs. buy, drawn cleanly. Buy the transport: authentication, streaming framing, retryable 5xx handling, rate-limit surfacing, context-size exceptions, UTF-8 sanitisation, model catalogue upkeep. The changelog is visibly composed of exactly those small correctness bugs — evidence that someone else is absorbing the long tail. Own the product logic: prompts, tool definitions, evaluation harness, cost model, caching, guardrails. The package deliberately does none of that.
Reduced roadmap volatility from catalogue automation. Model catalogues refresh on release cadence via automation, which removes the recurring "our model IDs are stale or deprecated" ticket that otherwise lands unplanned mid-sprint.
What this decision does not settle: whether Gemini is the right provider. Choose Gemini on capability fit — multimodal, long context, embeddings — and on price; then adopt this so that choice stays reversible. It also doesn't give you evaluation, observability dashboards, or prompt versioning. Those are still your product surface.
Adopt if all of these hold:
TokenUsage is the difference between an answerable question and a quarterly project.Look elsewhere if:
Maturity signals to weigh honestly. Five GitHub stars and zero dependents means essentially no production battle-testing outside Symfony's own work — a genuine risk. It's partly offset by the maintainers being recognisable Symfony core contributors, and by the code living inside the symfony/ai monorepo with its issue tracker and review flow: the organisation's reputation is underwriting this more than the popularity metrics are. The changelog is a positive signal too — dense with small, specific correctness fixes (streaming crashes on multi-part responses, empty tool-call roundtrips, JSON-Schema $schema stripping, protobuf wrapping of function_response) rather than signs of abandonment. Net read: technically healthy, socially unproven. Treat it as a dependency adopted behind an internal interface, never one that leaks into domain code.
For executives. "We can add Gemini's multimodal, streaming, and embedding capabilities to our PHP stack without building or maintaining a custom API integration. The strategic value isn't the Gemini call itself — it's that Gemini sits behind a provider interface, so we can switch or run a second provider without rewriting the feature. As of the current release, every response also reports which model handled it, which means we can state what an AI feature costs per document or per customer instead of reporting one blended AI number. That's the difference between pricing an AI feature confidently and guessing. The risks are honest: this is a young, community-maintained package with no vendor SLA, so I recommend adopting it behind our own thin interface, pinned to a version, with the expectation of periodic maintenance. I'd also flag that the package gives us usage data, not a billing system — the rate table and reporting are ours to build."
For engineering leads. "It's a bridge, not a framework. It implements Symfony AI's platform contract against Gemini's generateContent and batchEmbedContents endpoints and inherits the ecosystem's shared error handling: ModelNotFoundException on 404s, ExceedContextSizeException, a retryable ServerException for transient 5xx, and uniform API error surfacing via a shared trait. Streaming is SSE-based and emits semantic DeltaInterface deltas rather than untyped chunks, which keeps stream handling out of our controllers. Tool support covers multi-part results and server tools. Recent work has stabilised the sharp edges — multi-part streaming crashes, empty tool-call roundtrips, $schema stripping from tool parameters. Costs: pinned to Symfony AI's release cadence, no async story so background work is ours to queue, and pre-1.0 semver means minor bumps can carry behaviour changes. Mitigation: wrap it in an internal client interface, pin the version, read changelogs before upgrading, and keep a smoke test per capability — text, stream, embeddings, tool call — running against a pinned model. In Laravel terms, bind it in a service provider and inject an interface; nothing above the adapter should know the word 'Gemini.'"
How can I help you explore Laravel packages today?