AI连接解析器

针对 Laravel AI 的 PHP 扩展包,将业务用途映射为命名 AI 连接,并管理模型故障转移、推理强度、流式响应、提示词缓存与嵌入向量元数据,适用于需要可靠调用与切换多 AI 提供商的 Laravel 项目。

  • by brunocfalcao
  • PHP
  • 本地部署
  • 更新于
在 GitHub 查看 brunocfalcao/ai-bridge

使用说明

ai-bridge

Changes in v2.2.0

Anthropic requests from an agent that carries history or tools now ask for automatic prompt caching, so resent conversation and tool-loop prefixes are billed at the cache-read rate. One-off prompts and other providers are unchanged. A configured cache_control still wins.

Changes in v2.1.1

Embedding fallback chains now preserve exact provider:model keys containing dots, such as voyageai:voyage-3.5, across every hop. Exact identity mappings still take precedence over provider-wide fallbacks, and provider-wide fallback configuration remains compatible.

Changes in v2.1.0

A development-only report parser now serves this package and owned consumer quality gates. Require tools/QualityReports.php directly when building a gate; it is outside runtime autoloading. Each consumer keeps its own commands, score floors, source paths and advisory policy. Named AI connections are unchanged.

Named AI connections for Laravel AI: one config layer that maps a business use to a provider:model, walks its failover chain, applies its reasoning effort, and reports which model produced an embedding.

Everything else Laravel AI already does — agents, streaming, structured output, tools, MCP — is used directly. This package does not wrap it.

Changes in v2.0.0

Everything that duplicated Laravel AI, or served a use nobody kept, is gone: the Prism-backed chat providers, the Claude CLI and OpenClaw providers, the knowledge/MCP server, the browser sidecar, the agent tools, the conversation and API-config models with their migrations, and the Anthropic OAuth plumbing. What remains is the resolver, its configured agents, and AiResolver::stream(), which replaces ChatManager on Laravel AI's own streaming. prism-php/prism and laravel/mcp are no longer required, and laravel/ai is pinned to ^1.0.

Requirements

Installation

composer require brunocfalcao/ai-bridge
php artisan vendor:publish --tag=ai-bridge-config

Named connections

A connection is named after the use, not the model behind it, so swapping a model never reaches a call site:

// config/ai-bridge.php
'resolver' => [
    'connections' => [
        'survey'  => 'openai:gpt-4.1-mini',
        'analyst' => 'openai:gpt-4.1',
    ],
    'fallbacks' => [
        'openai' => 'gemini:gemini-3.1-pro-preview',
    ],
    'efforts' => [
        'analyst' => ['openai' => 'high'],
    ],
],
use BrunoCFalcao\AiBridge\Resolver\AiResolver;

$resolver = app(AiResolver::class);

// An agent carrying the connection's reasoning effort, prompted over its
// failover chain.
$response = $resolver->agent('analyst', instructions: 'Answer in JSON.')
    ->prompt($text, provider: $resolver->using('analyst'));

// Streaming, from an OpenAI-shaped message list.
foreach ($resolver->stream($messages, 'analyst') as $event) {
    // ['type' => 'delta', 'content' => '…'] … ['type' => 'done', 'content' => null]
}

using() returns the ordered provider map Laravel AI's withModelFailover() consumes: a rate-limit, overload or insufficient-credit response retries the same call on the next provider.

Reasoning effort

efforts.{connection}.{provider} takes low, medium or high and is translated into each provider's own request shape — OpenAI and OpenRouter reasoning.effort, Gemini thinking_level, Anthropic output_config.effort. Providers without an effort setting keep their default. options passes raw Laravel AI provider options for anything the mapping does not cover.

Prompt caching

An agent carrying history or tools asks Anthropic for automatic prompt caching, so a resent conversation or tool-loop prefix is billed at the cache-read rate. One-off prompts stay uncached, since a cache write costs more than plain input. Set options.{connection}.anthropic.cache_control to override, for example to use a one-hour TTL.

Embeddings

A vector is only comparable within the model that produced it, so embedWithMeta() returns the producing provider:model alongside the vector. Persist that identity with the vector and refuse to compare across it.

embedding_fallbacks is walked candidate-by-candidate rather than handed to Laravel AI, which keys its own failover by provider name and so collapses two models of one provider into a single entry. Each switch re-emits ProviderFailedOver, so host alerting sees embedding failures exactly as it sees text ones.

Documentation

License

MIT