Der vollständige Leitfaden zum Laravel AI SDK, das mehrere KI-Anbieter wie OpenAI, Anthropic und Gemini über eine einheitliche Schnittstelle bereitstellt. Behandelt werden Agenten, Bildgenerierung, Audio, Embeddings und das Testen.
Das Laravel AI SDK bietet eine einheitliche und ausdrucksstarke API zur Interaktion mit KI-Anbietern wie OpenAI, Anthropic und Gemini. Mit dem AI SDK können Sie intelligente Agenten mit Tools und strukturierten Ausgaben erstellen, Bilder generieren, Sprache synthetisieren und transkribieren, Vektor-Embeddings erzeugen und viele weitere KI-Funktionen über eine konsistente, Laravel-typische Schnittstelle nutzen.
Das Laravel AI SDK ist ein offizielles Paket, das in Laravel 13 hinzugefügt wurde. Es wird als laravel/ai bereitgestellt und ermöglicht die Nutzung mehrerer KI-Anbieter über eine einheitliche API.
Führen Sie die Datenbankmigrationen aus. Dabei werden die Tabellen agent_conversations und agent_conversation_messages erstellt, in denen der Gesprächsverlauf gespeichert wird.
Wenn Sie eine OpenAI-kompatible API verwenden – zum Beispiel LM Studio, vLLM, Together, Fireworks oder ein lokales Gateway – können Sie einen Anbieter mit dem Treiber openai-compatible konfigurieren. url ist erforderlich; wenn Sie key angeben, wird er als Bearer-Token gesendet.
Der OpenAI-kompatible Anbieter unterstützt Textgenerierung, Streaming, Tools, strukturierte Ausgaben und Bildanhänge. Wenn Ihr Endpunkt zusätzliche Felder im Request-Body benötigt, verwenden Sie die Anbieteroptionen.
Die erzeugten Agenten werden im Verzeichnis app/Ai/Agents/ abgelegt. Nachfolgend sehen Sie einen Agenten, der alle wichtigen Schnittstellen implementiert.
<?phpnamespace App\Ai\Agents;use App\Ai\Tools\RetrievePreviousTranscripts;use App\Models\History;use App\Models\User;use Illuminate\Contracts\JsonSchema\JsonSchema;use Laravel\Ai\Contracts\Agent;use Laravel\Ai\Contracts\Conversational;use Laravel\Ai\Contracts\HasStructuredOutput;use Laravel\Ai\Contracts\HasTools;use Laravel\Ai\Messages\Message;use Laravel\Ai\Promptable;use Stringable;class SalesCoach implements Agent, Conversational, HasTools, HasStructuredOutput{ use Promptable; public function __construct(public User $user) {} public function instructions(): Stringable|string { return 'You are a sales coach, analyzing transcripts and providing feedback and an overall sales strength score.'; } public function messages(): iterable { return History::where('user_id', $this->user->id) ->latest() ->limit(50) ->get() ->reverse() ->map(function ($message) { return new Message($message->role, $message->content); })->all(); } public function tools(): iterable { return [new RetrievePreviousTranscripts]; } public function schema(JsonSchema $schema): array { return [ 'feedback' => $schema->string()->required(), 'score' => $schema->integer()->min(1)->max(10)->required(), ]; }}
Wenn Sie das Conversational-Interface implementieren und eine Methode messages() definieren, wird der bisherige Gesprächsverlauf an die KI übergeben.Das Trait RemembersConversations speichert und lädt den Gesprächsverlauf automatisch aus der Datenbank.
use Laravel\Ai\Concerns\RemembersConversations;class SalesCoach implements Agent, Conversational{ use Promptable, RemembersConversations; public function instructions(): string { return 'You are a sales coach...'; }}
Beginnen Sie eine Unterhaltung mit forUser() und setzen Sie sie mit continue() fort, indem Sie die zurückgegebene conversationId verwenden.
$response = (new SalesCoach)->forUser($user)->prompt('Hello!');$conversationId = $response->conversationId;$response = (new SalesCoach)->continue($conversationId, as: $user)->prompt('Tell me more about that.');
Implementieren Sie das HasStructuredOutput-Interface und definieren Sie in der Methode schema() ein JSON-Schema, um die Antwort der KI als strukturierte Daten zu erhalten.
public function schema(JsonSchema $schema): array{ return ['score' => $schema->integer()->required()];}$response = (new SalesCoach)->prompt('Analyze this...');return $response['score'];
Über das Argument attachments können Sie dem Agenten Dokumente oder Bilder übergeben.
use Laravel\Ai\Files;$response = (new SalesCoach)->prompt( 'Analyze the attached sales transcript...', attachments: [ Files\Document::fromStorage('transcript.pdf'), Files\Document::fromPath('/home/laravel/transcript.md'), $request->file('transcript'), ]);
Bilder lassen sich auf gleiche Weise anhängen.
$response = (new ImageAnalyzer)->prompt('What is in this image?', attachments: [ Files\Image::fromStorage('photo.jpg'), Files\Image::fromPath('/home/laravel/photo.jpg'), $request->file('photo'),]);
Ereignisse aus dem Stream können an Broadcast-Kanäle, etwa Laravel Echo, gesendet werden.
use Illuminate\Broadcasting\Channel;$stream = (new SalesCoach)->stream('Analyze this sales transcript...');foreach ($stream as $event) { $event->broadcast(new Channel('channel-name'));}
Mit broadcastOnQueue() erfolgt das Broadcasten über eine Queue.
(new SalesCoach)->broadcastOnQueue( 'Analyze this sales transcript...', new Channel('channel-name'),);
Manche Broadcast-Plattformen begrenzen WebSocket-Nachrichten auf etwa 10 KB. Datenintensive Stream-Ereignisse wie große Tool-Ergebnisse können diese Grenze überschreiten und beim Broadcasten fehlschlagen. Mit dem Attribut WithoutBroadcasting können Sie bestimmte Ereignistypen vom Broadcast ausschließen.
Ausgeschlossene Ereignisse werden nicht per Broadcast versendet, aber weiterhin in der Tabelle agent_conversation_messages gespeichert. Dadurch kann das Frontend nach Abschluss des Streams weiterhin auf die vollständigen Tool-Daten zugreifen. Dies funktioniert sowohl über die Queue (broadcastOnQueue) als auch synchron (broadcast / broadcastNow).
Mit Tools kann die KI Funktionen in Ihrem Code aufrufen. Mit dem Befehl make:tool erzeugen Sie eine Toolklasse.
php artisan make:tool RandomNumberGenerator
<?phpnamespace App\Ai\Tools;use Illuminate\Contracts\JsonSchema\JsonSchema;use Laravel\Ai\Contracts\Tool;use Laravel\Ai\Tools\Request;use Stringable;class RandomNumberGenerator implements Tool{ public function description(): Stringable|string { return 'This tool may be used to generate cryptographically secure random numbers.'; } public function handle(Request $request): Stringable|string { return (string) random_int($request['min'], $request['max']); } public function schema(JsonSchema $schema): array { return [ 'min' => $schema->integer()->min(0)->required(), 'max' => $schema->integer()->required(), ]; }}
Registrieren Sie Tools in der Methode tools() des Agenten.
public function tools(): iterable{ return [new RandomNumberGenerator];}
Mit der Fabrik FileStorage können Sie Ihrem Agenten Zugriff auf Filesystem-Disks von Laravel geben. Die Methode all gibt einen Satz von Tools zurück, mit denen der Agent Dateien auf der angegebenen Disk auflisten, lesen, URLs erzeugen, schreiben, löschen und kopieren kann.
use Laravel\Ai\Tools\FileStorage;public function tools(): iterable{ return FileStorage::all('local');}
Wenn Sie nur Lesezugriff gewähren möchten, verwenden Sie die Methode readOnly.
return FileStorage::readOnly('local');
Diese Methoden liefern eine Illuminate\Support\Collection zurück, sodass Sie die bereitgestellten Tools weiter filtern können.
use Laravel\Ai\Tools\Filesystem\DeleteFile;return FileStorage::all('s3') ->reject(fn ($tool) => $tool instanceof DeleteFile);
Wenn Ihre Anwendung Laravel MCP verwendet, können Sie Ihrem Agenten die Tools bereitstellen, die ein Model-Context-Protocol-Server veröffentlicht. Mit dem Laravel-MCP-Client können Sie sich mit entfernten oder lokalen MCP-Servern verbinden und deren Tools direkt an den Agenten übergeben.
Für die Nutzung von MCP-Tools muss das Paket Laravel MCP in Ihrer Anwendung installiert sein.
Die Methode tools des MCP-Clients liefert eine Collection zurück, die Sie mit dem Spread-Operator ... in das tools-Array des Agenten einfügen.
use App\Ai\Tools\RandomNumberGenerator;use Laravel\Mcp\Client;/** * Get the tools available to the agent. * * @return Tool[] */public function tools(): iterable{ return [ ...Client::web('https://mcp.example.com') ->withToken($token) ->tools(), new RandomNumberGenerator, ];}
Das AI SDK umschließt jedes MCP-Tool automatisch, sodass der Agent es wie jedes andere Tool aufrufen kann. Sie können auch benannte MCP-Clients verwenden.
use Laravel\Mcp\Facades\Mcp;public function tools(): iterable{ return [ ...Mcp::client('github')->tools(), ];}
Agenten können auch aus der tools()-Methode eines anderen Agenten zurückgegeben werden. Wenn Sie einen Agenten als Tool registrieren, kann der übergeordnete Agent bestimmte Aufgaben an einen Subagenten delegieren und dessen Ergebnis in die ursprüngliche Antwort einbetten. Das ist nützlich, wenn ein Allzweck-Agent auf spezialisierte Agenten mit eigenen Anweisungen, Tools, Modell- oder Anbietereinstellungen zugreifen soll.Ein Beispiel: Ein Kundenservice-Agent delegiert Fragen zur Rückerstattungsrichtlinie an einen spezialisierten Erstattungsagenten.
<?phpnamespace App\Ai\Agents;use Laravel\Ai\Contracts\Agent;use Laravel\Ai\Contracts\HasTools;use Laravel\Ai\Promptable;class CustomerSupportAgent implements Agent, HasTools{ use Promptable; public function instructions(): string { return 'You help customers with account, order, and billing questions. Delegate refund policy questions to the refunds specialist.'; } public function tools(): iterable { return [ new RefundsAgent, ]; }}
Um festzulegen, wie der Subagent gegenüber dem übergeordneten Agenten erscheint, implementieren Sie das Interface CanActAsTool und definieren einen Namen und eine Beschreibung für das Tool.
<?phpnamespace App\Ai\Agents;use App\Ai\Tools\LookupOrder;use Laravel\Ai\Attributes\Provider;use Laravel\Ai\Contracts\Agent;use Laravel\Ai\Contracts\CanActAsTool;use Laravel\Ai\Contracts\HasTools;use Laravel\Ai\Enums\Lab;use Laravel\Ai\Promptable;#[Provider(Lab::Anthropic)]class RefundsAgent implements Agent, CanActAsTool, HasTools{ use Promptable; public function instructions(): string { return 'You are a refunds specialist. Use order details and the refund policy to give concise eligibility guidance.'; } public function name(): string { return 'refunds_specialist'; } public function description(): string { return 'Determine whether an order is eligible for a refund and explain the next step.'; } public function tools(): iterable { return [ new LookupOrder, ]; }}
Wenn ein Subagent CanActAsTool nicht implementiert, verwendet Laravel den Klassennamen als Tool-Namen und generiert automatisch eine allgemeine Beschreibung. Jeder Aufruf eines Subagenten erfolgt unabhängig; der Gesprächsverlauf des übergeordneten Agenten wird nicht übernommen.
Ohne eine eigene Klasse zu definieren, können Sie mit dem Helper agent() anonyme Agenten verwenden.
use function Laravel\Ai\{agent};$response = agent( instructions: 'You are an expert at software development.', messages: [], tools: [],)->prompt('Tell me about Laravel');
Auch anonyme Agenten mit strukturierter Ausgabe sind möglich.
use Illuminate\Contracts\JsonSchema\JsonSchema;$response = agent( schema: fn (JsonSchema $schema) => ['number' => $schema->integer()->required()],)->prompt('Generate a random number less than 100');
Für die Modellauswahl gibt es Abkürzungsattribute.
// Verwende das günstigste Modell#[UseCheapestModel]class SimpleSummarizer implements Agent{ use Promptable;}// Verwende das leistungsfähigste Modell#[UseSmartestModel]class ComplexReasoner implements Agent{ use Promptable;}
Mit der Klasse Image können Sie Bilder generieren. Unterstützt werden die Anbieter OpenAI, Gemini und xAI.
use Laravel\Ai\Image;$image = Image::of('A donut sitting on the kitchen counter')->generate();$rawContent = (string) $image;
Sie können Qualität, Seitenverhältnis und Timeout angeben.
$image = Image::of('A donut sitting on the kitchen counter') ->quality('high') ->landscape() ->timeout(120) ->generate();
Auch das Bearbeiten anhand eines Referenzbildes ist möglich.
use Laravel\Ai\Files;$image = Image::of('Update this photo to be in the style of an impressionist painting.') ->attachments([Files\Image::fromStorage('photo.jpg')]) ->landscape() ->generate();
Mit der Klasse Audio können Sie Text in Sprache umwandeln. Unterstützt werden die Anbieter OpenAI und ElevenLabs.
use Laravel\Ai\Audio;$audio = Audio::of('I love coding with Laravel.')->generate();$rawContent = (string) $audio;
Sie können das Geschlecht der Stimme, eine konkrete Voice-ID sowie Anweisungen für den Sprechstil angeben.
$audio = Audio::of('I love coding with Laravel.')->female()->generate();$audio = Audio::of('I love coding with Laravel.')->voice('voice-id-or-name')->generate();$audio = Audio::of('I love coding with Laravel.')->female()->instructions('Said like a pirate')->generate();
use Laravel\Ai\Responses\AudioResponse;Audio::of('I love coding with Laravel.') ->queue() ->then(function (AudioResponse $audio) { $path = $audio->store(); });
Wandeln Sie Text in eine Vektor-Repräsentation um, die sich zum Beispiel für die Ähnlichkeitssuche nutzen lässt.
use Illuminate\Support\Str;// Über Stringable$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings();
use Laravel\Ai\Embeddings;// Mehrere Texte in einem Schritt verarbeiten$response = Embeddings::for(['Napa Valley has great wine.', 'Laravel is a PHP framework.'])->generate();$response->embeddings; // [[0.123, 0.456, ...], [0.789, 0.012, ...]]
Anbieter, Modell und Anzahl der Dimensionen lassen sich ebenfalls angeben.
$response = Embeddings::for(['Napa Valley has great wine.']) ->dimensions(1536) ->generate(Lab::OpenAI, 'text-embedding-3-small');
Sie können Embeddings zwischenspeichern, um denselben Text nicht mehrfach zu berechnen.Die Standardeinstellungen für den Cache legen Sie in config/ai.php fest.
$response = Embeddings::for(['Napa Valley has great wine.'])->cache()->generate();$response = Embeddings::for(['Napa Valley has great wine.'])->cache(seconds: 3600)->generate();// Ebenso über Stringable$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: true);$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: 3600);
Suchergebnisse können anhand ihrer Relevanz zu einer Anfrage neu sortiert werden (Reranking). Unterstützt werden die Anbieter Cohere und Jina.
use Laravel\Ai\Reranking;$response = Reranking::of([ 'Django is a Python web framework.', 'Laravel is a PHP web application framework.', 'React is a JavaScript library for building user interfaces.',])->rerank('PHP frameworks');$response->first()->document; // "Laravel is a PHP web application framework."$response->first()->score; // 0.95$response->first()->index; // 1
Mit limit() schränken Sie die Anzahl der zurückgegebenen Ergebnisse ein.
Sie können Dateien zu einem KI-Anbieter hochladen und später darauf verweisen.
use Laravel\Ai\Files\Document;use Laravel\Ai\Files\Image;// Aus einem Pfad$response = Document::fromPath('/home/laravel/document.pdf')->put();$response = Image::fromPath('/home/laravel/photo.jpg')->put();// Aus dem Storage$response = Document::fromStorage('document.pdf', disk: 'local')->put();$response = Image::fromStorage('photo.jpg', disk: 'local')->put();// Aus einer URL$response = Document::fromUrl('https://example.com/document.pdf')->put();$response = Image::fromUrl('https://example.com/photo.jpg')->put();return $response->id;
Bereits hochgeladene Dateien können Sie über ihre ID an einen Agenten anhängen.
use Laravel\Ai\Files;$response = (new SalesCoach)->prompt( 'Analyze the attached sales transcript...', attachments: [Files\Document::fromId('file-id')]);
Über die Methode withProviderOptions können Sie anbieterspezifische Upload-Optionen übergeben. So können Sie zum Beispiel den purpose-Wert für OpenAI-Dateien setzen.
use Laravel\Ai\Files\Document;$response = Document::fromPath('/home/laravel/knowledge.txt') ->withProviderOptions(['purpose' => 'assistants']) ->put();
Wenn Sie pro Anbieter unterschiedliche Optionen angeben möchten, übergeben Sie eine Closure.
Wenn Sie mehrere Anbieter als Array angeben, wird bei einem Fehlschlag des ersten Anbieters automatisch auf den nächsten umgeschaltet.
use App\Ai\Agents\SalesCoach;use Laravel\Ai\Image;// Failover bei Agenten$response = (new SalesCoach)->prompt( 'Analyze this sales transcript...', provider: [Lab::OpenAI, Lab::Anthropic],);// Failover bei der Bildgenerierung$image = Image::of('A donut sitting on the kitchen counter') ->generate(provider: [Lab::Gemini, Lab::xAI]);
use App\Ai\Agents\SalesCoach;use Laravel\Ai\Prompts\AgentPrompt;// Fake mit festen AntwortenSalesCoach::fake();SalesCoach::fake(['First response', 'Second response']);// Dynamische Antworten per ClosureSalesCoach::fake(function (AgentPrompt $prompt) { return 'Response for: '.$prompt->prompt;});// ZusicherungenSalesCoach::assertPrompted('Analyze this...');SalesCoach::assertPrompted(function (AgentPrompt $prompt) { return $prompt->contains('Analyze');});SalesCoach::assertNotPrompted('Missing prompt');SalesCoach::assertNeverPrompted();
Auch für die Queue stehen Zusicherungen zur Verfügung.
use Laravel\Ai\QueuedAgentPrompt;SalesCoach::assertQueued('Analyze this...');SalesCoach::assertQueued(function (QueuedAgentPrompt $prompt) { return $prompt->contains('Analyze');});SalesCoach::assertNotQueued('Missing prompt');SalesCoach::assertNeverQueued();
Mit preventStrayPrompts() wird eine Ausnahme ausgelöst, wenn ein Prompt aufgerufen wird, der nicht als Fake definiert wurde.
SalesCoach::fake()->preventStrayPrompts();
Wenn Sie einen Agenten mit strukturierter Ausgabe faken, können Sie die Antwort als Array angeben. Der Agent liefert dann eine strukturierte Antwort mit den angegebenen Daten zurück.
SalesCoach::fake([ ['score' => 87],]);
Wenn fake() bei einem Agenten mit strukturierter Ausgabe ohne explizit angegebene Fake-Daten aufgerufen wird, generiert Laravel automatisch Fake-Daten, die dem vom Agenten definierten Schema entsprechen.
Zum Testen anonymer Agenten verwenden Sie AnonymousAgent::fake().
use Laravel\Ai\AnonymousAgent;AnonymousAgent::fake(['Test response']);