Lesen Sie den Quellcode des Laravel AI SDK und erfahren Sie, wie Sie einen eigenen Provider für einen KI-Dienst implementieren, der nicht standardmäßig unterstützt wird.
Das Laravel AI SDK unterstützt OpenAI, Anthropic, Gemini, Mistral und andere zentrale KI-Dienste out of the box. In folgenden Fällen reichen die Standard-Provider aber nicht:
Ein aufstrebender KI-Dienst, der noch nicht offiziell unterstützt wird.
Sie möchten über ein internes Modell-Gateway oder eine Abrechnungsschicht laufen.
Ein On-Prem-Inferenzserver mit eigenem Protokoll oder Auth-Verfahren.
In solchen Fällen implementieren Sie einen eigenen Provider und registrieren ihn am AiManager des SDK. Die Nutzung ist dann identisch zu den Standard-Providern.
Für OpenAI-kompatible APIs den eingebauten Driver nutzenAb SDK 0.9 ist der Treiber openai-compatible standardmäßig verfügbar. Für interne OpenAI-kompatible Inferenzserver (etwa den OpenAI-kompatiblen Endpoint von Ollama) genügt eine Ergänzung in config/ai.php — eine eigene Provider-Implementierung ist nicht nötig.
Das Laravel AI SDK besteht aus zwei Schichten: Provider und Gateway.
Schicht
Aufgabe
Beispiel
Provider
Schnittstelle Richtung Anwendung; Modellauflösung, Konfigurationshaltung
OpenAiProvider, AnthropicProvider
Gateway
Sendet den eigentlichen einzelnen API-Request
AnthropicGateway, OpenAiCompatibleGateway
Alle Provider erben von der abstrakten Klasse Laravel\Ai\Providers\Provider und implementieren feature-spezifische Contracts. Die mehrstufige Schleife mit Tool-Aufrufen läuft in TextGenerationLoop, das das Gateway wiederholt aufruft.
Das ist das Interface, das ein Text-Provider implementiert (src/Contracts/Providers/TextProvider.php).
interface TextProvider extends Provider{ public function prompt(AgentPrompt $prompt): AgentResponse; public function stream(AgentPrompt $prompt): StreamableAgentResponse; public function useTextGateway(StepTextGateway $gateway): self; public function textGenerationLoop(): TextGenerationLoop; public function defaultTextModel(): string; public function cheapestTextModel(): string; public function smartestTextModel(): string;}
Die Implementierung von prompt() und stream() können Sie an vorhandene Traits (GeneratesText, StreamsText) abgeben — Sie müssen also nur drei Methoden für die Modellnamen und zusätzlich textGateway() implementieren (insgesamt vier). Die mehrstufige Tool-Schleife übernimmt TextGenerationLoop; das Gateway verarbeitet nur den Request eines einzelnen Schritts.
Beispiel: Ein Inferenzdienst mit eigener API wird als Provider my-inference registriert.
1
Provider-Klasse anlegen
Legen Sie app/Ai/Providers/MyInferenceProvider.php an.
<?phpdeclare(strict_types=1);namespace App\Ai\Providers;use Illuminate\Contracts\Events\Dispatcher;use Laravel\Ai\Contracts\Gateway\StepTextGateway;use Laravel\Ai\Contracts\Providers\TextProvider;use Laravel\Ai\Providers\Concerns\GeneratesText;use Laravel\Ai\Providers\Concerns\HasTextGateway;use Laravel\Ai\Providers\Concerns\StreamsText;use Laravel\Ai\Providers\Provider;class MyInferenceProvider extends Provider implements TextProvider{ use GeneratesText; use HasTextGateway; use StreamsText; public function __construct(protected array $config, protected Dispatcher $events) { // } /** * Get the credentials for the provider. */ public function providerCredentials(): array { return ['key' => $this->config['key'] ?? null]; } /** * Get the provider's text gateway. */ public function textGateway(): StepTextGateway { return $this->textGateway ??= new \App\Ai\Gateway\MyInferenceGateway($this->events); } public function defaultTextModel(): string { return $this->config['models']['text']['default'] ?? 'my-model-v1'; } public function cheapestTextModel(): string { return $this->config['models']['text']['cheapest'] ?? 'my-model-v1'; } public function smartestTextModel(): string { return $this->config['models']['text']['smartest'] ?? 'my-model-v1'; }}
2
Im AppServiceProvider registrieren
Registrieren Sie den Provider in der boot-Methode Ihres App\Providers\AppServiceProvider per extend().
<?phpnamespace App\Providers;use App\Ai\Providers\MyInferenceProvider;use Illuminate\Contracts\Events\Dispatcher;use Illuminate\Support\ServiceProvider;use Laravel\Ai\AiManager;class AppServiceProvider extends ServiceProvider{ public function boot(): void { $this->app->make(AiManager::class)->extend( 'my-inference', fn (array $config) => new MyInferenceProvider( $config, $this->app->make(Dispatcher::class) ) ); }}
Definiert in src/Contracts/Gateway/StepTextGateway.php. Das Gateway verarbeitet einen einzelnen Schritt der Konversation und gibt eine StepResponse zurück. Die Tool-Schleife übernimmt der aufrufende TextGenerationLoop.
Der ältere TextGateway-Contract (generateText(), stream(), onToolInvocation()) aus 0.8 wurde in 0.9 entfernt. Bestehende eigene Gateways müssen auf StepTextGateway migriert werden. Das onToolInvocation() bei Tool-Aufrufen ist in den TextGenerationLoop gewandert.
Für Tool-Aufrufe (Function Calling) legen Sie in generateTextStep() das Ergebnis der Tool-Auswertung in toolCalls ab und setzen finishReason auf FinishReason::ToolCalls. Die Tool-Ausführung und den nächsten Schritt übernimmt TextGenerationLoop. Referenzimplementierung: AnthropicGateway.php.
In Tests der Agent-Klasse mit Ihrem eigenen Provider verwenden Sie die fake()-Methode der Agent-Klasse. Sie setzt unabhängig vom Provider ein Fake-Gateway.
<?phpnamespace Tests\Feature;use App\Ai\Agents\SummaryAgent;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase;class SummaryAgentTest extends TestCase{ use RefreshDatabase; public function test_summary_agent_returns_text(): void { SummaryAgent::fake(['Dies ist die Zusammenfassung.']); $response = SummaryAgent::make()->prompt('Sehr langer Artikeltext …', provider: 'my-inference'); $this->assertEquals('Dies ist die Zusammenfassung.', $response->text); SummaryAgent::assertPrompted('Sehr langer Artikeltext …'); }}
Ab 0.9 laufen Agent::fake()-Responses durch denselben TextGenerationLoop wie echte Provider. Definieren Sie Fake-Tool-Aufrufe bei einem Agenten ohne Tools, wird eine NoSuchToolException geworfen.