跳轉至內容

Laravel AI SDK

簡介

Laravel AI SDK 提供了一個統一且富有表現力的 API,用於與 OpenAI、Anthropic、Gemini 等 AI 提供商進行互動。利用 AI SDK,你可以構建具備工具呼叫和結構化輸出能力的智慧體、生成影像、合成及轉錄音訊、建立向量嵌入等等——所有這些都透過一個統一且符合 Laravel 習慣的介面實現。

安裝

你可以透過 Composer 安裝 Laravel AI SDK:

1composer require laravel/ai

接下來,你應該使用 vendor:publish Artisan 命令釋出 AI SDK 的配置檔案和遷移檔案:

1php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"

最後,你應該執行應用程式的資料庫遷移。這將建立 agent_conversationsagent_conversation_messages 資料表,AI SDK 使用它們來驅動其對話儲存功能。

1php artisan migrate

配置

你可以在應用程式的 config/ai.php 配置檔案中定義 AI 提供商憑據,或者將其作為環境變數存放在應用程式的 .env 檔案中。

1ANTHROPIC_API_KEY=
2COHERE_API_KEY=
3ELEVENLABS_API_KEY=
4GEMINI_API_KEY=
5MISTRAL_API_KEY=
6OLLAMA_API_KEY=
7OPENAI_API_KEY=
8JINA_API_KEY=
9VOYAGEAI_API_KEY=
10XAI_API_KEY=

用於文字、影像、音訊、轉錄和嵌入的預設模型也可以在應用程式的 config/ai.php 配置檔案中進行配置。

自定義基礎 URL

預設情況下,Laravel AI SDK 直接連線到每個提供商的公共 API 端點。然而,你可能需要透過不同的端點路由請求——例如,當使用代理服務來集中管理 API 金鑰、實施速率限制或透過企業閘道器路由流量時。

你可以透過在提供商配置中新增 url 引數來配置自定義基礎 URL。

1'providers' => [
2 'openai' => [
3 'driver' => 'openai',
4 'key' => env('OPENAI_API_KEY'),
5 'url' => env('OPENAI_BASE_URL'),
6 ],
7 
8 'anthropic' => [
9 'driver' => 'anthropic',
10 'key' => env('ANTHROPIC_API_KEY'),
11 'url' => env('ANTHROPIC_BASE_URL'),
12 ],
13],

這在透過代理服務(如 LiteLLM 或 Azure OpenAI Gateway)路由請求或使用備用端點時非常有用。

以下提供商支援自定義基礎 URL:OpenAI、Anthropic、Gemini、Groq、Cohere、DeepSeek、xAI 和 OpenRouter。

提供商支援

AI SDK 在其各項功能中支援多種提供商。下表總結了每個功能可用的提供商:

功能 提供商
文字 OpenAI, Anthropic, Gemini, Azure, Groq, xAI, DeepSeek, Mistral, Ollama
影像 OpenAI, Gemini, xAI
TTS OpenAI, ElevenLabs
STT OpenAI, ElevenLabs, Mistral
嵌入 (Embeddings) OpenAI, Gemini, Azure, Cohere, Mistral, Jina, VoyageAI
重排序 (Reranking) Cohere, Jina
檔案 OpenAI, Anthropic, Gemini

Laravel\Ai\Enums\Lab 列舉可以在程式碼中引用提供商,而無需直接使用字串。

1use Laravel\Ai\Enums\Lab;
2 
3Lab::Anthropic;
4Lab::OpenAI;
5Lab::Gemini;
6// ...

智慧體 (Agents)

智慧體(Agents)是 Laravel AI SDK 中與 AI 提供商互動的基礎構建塊。每個智慧體都是一個專門的 PHP 類,封裝了與大語言模型互動所需的指令、對話上下文、工具和輸出模式。可以將智慧體視為一個專業助手——如銷售教練、文件分析師或客服機器人——你在應用程式中配置一次,即可根據需要隨時呼叫。

你可以透過 make:agent Artisan 命令建立智慧體。

1php artisan make:agent SalesCoach
2 
3php artisan make:agent SalesCoach --structured

在生成的智慧體類中,你可以定義系統提示詞(指令)、訊息上下文、可用工具以及輸出模式(如果適用)。

1<?php
2 
3namespace App\Ai\Agents;
4 
5use App\Ai\Tools\RetrievePreviousTranscripts;
6use App\Models\History;
7use App\Models\User;
8use Illuminate\Contracts\JsonSchema\JsonSchema;
9use Laravel\Ai\Contracts\Agent;
10use Laravel\Ai\Contracts\Conversational;
11use Laravel\Ai\Contracts\HasStructuredOutput;
12use Laravel\Ai\Contracts\HasTools;
13use Laravel\Ai\Messages\Message;
14use Laravel\Ai\Promptable;
15use Stringable;
16 
17class SalesCoach implements Agent, Conversational, HasTools, HasStructuredOutput
18{
19 use Promptable;
20 
21 public function __construct(public User $user) {}
22 
23 /**
24 * Get the instructions that the agent should follow.
25 */
26 public function instructions(): Stringable|string
27 {
28 return 'You are a sales coach, analyzing transcripts and providing feedback and an overall sales strength score.';
29 }
30 
31 /**
32 * Get the list of messages comprising the conversation so far.
33 */
34 public function messages(): iterable
35 {
36 return History::where('user_id', $this->user->id)
37 ->latest()
38 ->limit(50)
39 ->get()
40 ->reverse()
41 ->map(function ($message) {
42 return new Message($message->role, $message->content);
43 })->all();
44 }
45 
46 /**
47 * Get the tools available to the agent.
48 *
49 * @return Tool[]
50 */
51 public function tools(): iterable
52 {
53 return [
54 new RetrievePreviousTranscripts,
55 ];
56 }
57 
58 /**
59 * Get the agent's structured output schema definition.
60 */
61 public function schema(JsonSchema $schema): array
62 {
63 return [
64 'feedback' => $schema->string()->required(),
65 'score' => $schema->integer()->min(1)->max(10)->required(),
66 ];
67 }
68}

提示詞 (Prompting)

要向智慧體傳送提示詞,首先使用 make 方法或常規例項化建立一個例項,然後呼叫 prompt 方法。

1$response = (new SalesCoach)
2 ->prompt('Analyze this sales transcript...');
3 
4return (string) $response;

make 方法從容器中解析你的智慧體,允許自動依賴注入。你也可以向智慧體的建構函式傳遞引數。

1$agent = SalesCoach::make(user: $user);

透過向 prompt 方法傳遞額外引數,你可以在傳送提示詞時覆蓋預設的提供商、模型或 HTTP 超時設定。

1$response = (new SalesCoach)->prompt(
2 'Analyze this sales transcript...',
3 provider: Lab::Anthropic,
4 model: 'claude-haiku-4-5-20251001',
5 timeout: 120,
6);

對話上下文

如果你的智慧體實現了 Conversational 介面,你可以使用 messages 方法返回之前的對話上下文(如果適用)。

1use App\Models\History;
2use Laravel\Ai\Messages\Message;
3 
4/**
5 * Get the list of messages comprising the conversation so far.
6 */
7public function messages(): iterable
8{
9 return History::where('user_id', $this->user->id)
10 ->latest()
11 ->limit(50)
12 ->get()
13 ->reverse()
14 ->map(function ($message) {
15 return new Message($message->role, $message->content);
16 })->all();
17}

記憶對話

在使用 RemembersConversations trait 之前,你應該使用 vendor:publish Artisan 命令釋出並執行 AI SDK 的遷移。這些遷移將建立儲存對話所需的資料庫表。

如果你希望 Laravel 自動為你的智慧體儲存和檢索對話歷史,可以使用 RemembersConversations trait。此 trait 提供了一種簡單的方法將對話訊息持久化到資料庫中,而無需手動實現 Conversational 介面。

1<?php
2 
3namespace App\Ai\Agents;
4 
5use Laravel\Ai\Concerns\RemembersConversations;
6use Laravel\Ai\Contracts\Agent;
7use Laravel\Ai\Contracts\Conversational;
8use Laravel\Ai\Promptable;
9 
10class SalesCoach implements Agent, Conversational
11{
12 use Promptable, RemembersConversations;
13 
14 /**
15 * Get the instructions that the agent should follow.
16 */
17 public function instructions(): string
18 {
19 return 'You are a sales coach...';
20 }
21}

要為使用者開始新的對話,請在傳送提示詞前呼叫 forUser 方法。

1$response = (new SalesCoach)->forUser($user)->prompt('Hello!');
2 
3$conversationId = $response->conversationId;

對話 ID 會在響應中返回,可以儲存以備日後參考;或者你也可以直接從 agent_conversations 表中檢索使用者的所有對話。

要繼續現有的對話,請使用 continue 方法。

1$response = (new SalesCoach)
2 ->continue($conversationId, as: $user)
3 ->prompt('Tell me more about that.');

使用 RemembersConversations trait 時,之前的訊息會自動載入幷包含在提示詞的對話上下文中。新訊息(無論是使用者還是助手)會在每次互動後自動儲存。

結構化輸出

如果你希望智慧體返回結構化輸出,請實現 HasStructuredOutput 介面,該介面要求智慧體定義一個 schema 方法。

1<?php
2 
3namespace App\Ai\Agents;
4 
5use Illuminate\Contracts\JsonSchema\JsonSchema;
6use Laravel\Ai\Contracts\Agent;
7use Laravel\Ai\Contracts\HasStructuredOutput;
8use Laravel\Ai\Promptable;
9 
10class SalesCoach implements Agent, HasStructuredOutput
11{
12 use Promptable;
13 
14 // ...
15 
16 /**
17 * Get the agent's structured output schema definition.
18 */
19 public function schema(JsonSchema $schema): array
20 {
21 return [
22 'score' => $schema->integer()->required(),
23 ];
24 }
25}

當提示一個返回結構化輸出的智慧體時,你可以像訪問陣列一樣訪問返回的 StructuredAgentResponse

1$response = (new SalesCoach)->prompt('Analyze this sales transcript...');
2 
3return $response['score'];

附件

傳送提示詞時,你也可以隨附附件,以便模型檢查影像和文件。

1use App\Ai\Agents\SalesCoach;
2use Laravel\Ai\Files;
3 
4$response = (new SalesCoach)->prompt(
5 'Analyze the attached sales transcript...',
6 attachments: [
7 Files\Document::fromStorage('transcript.pdf') // Attach a document from a filesystem disk...
8 Files\Document::fromPath('/home/laravel/transcript.md') // Attach a document from a local path...
9 $request->file('transcript'), // Attach an uploaded file...
10 ]
11);

同樣,Laravel\Ai\Files\Image 類可用於將影像附加到提示詞中。

1use App\Ai\Agents\ImageAnalyzer;
2use Laravel\Ai\Files;
3 
4$response = (new ImageAnalyzer)->prompt(
5 'What is in this image?',
6 attachments: [
7 Files\Image::fromStorage('photo.jpg') // Attach an image from a filesystem disk...
8 Files\Image::fromPath('/home/laravel/photo.jpg') // Attach an image from a local path...
9 $request->file('photo'), // Attach an uploaded file...
10 ]
11);

流式傳輸

你可以透過呼叫 stream 方法流式傳輸智慧體的響應。返回的 StreamableAgentResponse 可以從路由返回,從而自動向客戶端傳送流式響應 (SSE)。

1use App\Ai\Agents\SalesCoach;
2 
3Route::get('/coach', function () {
4 return (new SalesCoach)->stream('Analyze this sales transcript...');
5});

可以使用 then 方法提供一個閉包,該閉包將在整個響應流式傳輸到客戶端後被呼叫。

1use App\Ai\Agents\SalesCoach;
2use Laravel\Ai\Responses\StreamedAgentResponse;
3 
4Route::get('/coach', function () {
5 return (new SalesCoach)
6 ->stream('Analyze this sales transcript...')
7 ->then(function (StreamedAgentResponse $response) {
8 // $response->text, $response->events, $response->usage...
9 });
10});

或者,你可以手動遍歷流式事件。

1$stream = (new SalesCoach)->stream('Analyze this sales transcript...');
2 
3foreach ($stream as $event) {
4 // ...
5}

使用 Vercel AI SDK 協議進行流式傳輸

你可以透過在可流式響應上呼叫 usingVercelDataProtocol 方法,使用 Vercel AI SDK 流協議來流式傳輸事件。

1use App\Ai\Agents\SalesCoach;
2 
3Route::get('/coach', function () {
4 return (new SalesCoach)
5 ->stream('Analyze this sales transcript...')
6 ->usingVercelDataProtocol();
7});

廣播

你可以通過幾種不同的方式廣播流式事件。首先,可以直接在流式事件上呼叫 broadcastbroadcastNow 方法。

1use App\Ai\Agents\SalesCoach;
2use Illuminate\Broadcasting\Channel;
3 
4$stream = (new SalesCoach)->stream('Analyze this sales transcript...');
5 
6foreach ($stream as $event) {
7 $event->broadcast(new Channel('channel-name'));
8}

或者,你可以呼叫智慧體的 broadcastOnQueue 方法,將智慧體操作放入佇列,並在流式事件可用時進行廣播。

1(new SalesCoach)->broadcastOnQueue(
2 'Analyze this sales transcript...'
3 new Channel('channel-name'),
4);

佇列處理 (Queueing)

使用智慧體的 queue 方法,你可以傳送提示詞並允許其在後臺處理響應,從而保持應用程式的快速響應。thencatch 方法可用於註冊閉包,分別在響應可用或發生異常時被呼叫。

1use Illuminate\Http\Request;
2use Laravel\Ai\Responses\AgentResponse;
3use Throwable;
4 
5Route::post('/coach', function (Request $request) {
6 return (new SalesCoach)
7 ->queue($request->input('transcript'))
8 ->then(function (AgentResponse $response) {
9 // ...
10 })
11 ->catch(function (Throwable $e) {
12 // ...
13 });
14 
15 return back();
16});

工具

工具可以賦予智慧體額外的功能,以便在響應提示詞時使用。可以使用 make:tool Artisan 命令建立工具。

1php artisan make:tool RandomNumberGenerator

生成的工具將放置在應用程式的 app/Ai/Tools 目錄中。每個工具都包含一個 handle 方法,當智慧體需要使用該工具時,它會被呼叫。

1<?php
2 
3namespace App\Ai\Tools;
4 
5use Illuminate\Contracts\JsonSchema\JsonSchema;
6use Laravel\Ai\Contracts\Tool;
7use Laravel\Ai\Tools\Request;
8use Stringable;
9 
10class RandomNumberGenerator implements Tool
11{
12 /**
13 * Get the description of the tool's purpose.
14 */
15 public function description(): Stringable|string
16 {
17 return 'This tool may be used to generate cryptographically secure random numbers.';
18 }
19 
20 /**
21 * Execute the tool.
22 */
23 public function handle(Request $request): Stringable|string
24 {
25 return (string) random_int($request['min'], $request['max']);
26 }
27 
28 /**
29 * Get the tool's schema definition.
30 */
31 public function schema(JsonSchema $schema): array
32 {
33 return [
34 'min' => $schema->integer()->min(0)->required(),
35 'max' => $schema->integer()->required(),
36 ];
37 }
38}

一旦定義了工具,就可以在任何智慧體的 tools 方法中返回它。

1use App\Ai\Tools\RandomNumberGenerator;
2 
3/**
4 * Get the tools available to the agent.
5 *
6 * @return Tool[]
7 */
8public function tools(): iterable
9{
10 return [
11 new RandomNumberGenerator,
12 ];
13}

SimilaritySearch 工具允許智慧體使用資料庫中儲存的向量嵌入來搜尋與給定查詢相似的文件。這對於檢索增強生成 (RAG) 非常有用,當你希望智慧體能夠搜尋應用程式的資料時。

建立相似度搜索工具最簡單的方法是使用 usingModel 方法,並傳入一個具有向量嵌入的 Eloquent 模型。

1use App\Models\Document;
2use Laravel\Ai\Tools\SimilaritySearch;
3 
4public function tools(): iterable
5{
6 return [
7 SimilaritySearch::usingModel(Document::class, 'embedding'),
8 ];
9}

第一個引數是 Eloquent 模型類,第二個引數是包含向量嵌入的列名。

你還可以提供 0.01.0 之間的最小相似度閾值,以及一個自定義查詢的閉包。

1SimilaritySearch::usingModel(
2 model: Document::class,
3 column: 'embedding',
4 minSimilarity: 0.7,
5 limit: 10,
6 query: fn ($query) => $query->where('published', true),
7),

為了獲得更多控制權,你可以透過一個返回搜尋結果的自定義閉包來建立相似度搜索工具。

1use App\Models\Document;
2use Laravel\Ai\Tools\SimilaritySearch;
3 
4public function tools(): iterable
5{
6 return [
7 new SimilaritySearch(using: function (string $query) {
8 return Document::query()
9 ->where('user_id', $this->user->id)
10 ->whereVectorSimilarTo('embedding', $query)
11 ->limit(10)
12 ->get();
13 }),
14 ];
15}

你可以使用 withDescription 方法自定義工具的描述。

1SimilaritySearch::usingModel(Document::class, 'embedding')
2 ->withDescription('Search the knowledge base for relevant articles.'),

提供商工具

提供商工具是 AI 提供商原生實現的特殊工具,提供諸如網頁搜尋、URL 獲取和檔案搜尋等功能。與常規工具不同,提供商工具由提供商本身執行,而不是由你的應用程式執行。

提供商工具可以透過智慧體的 tools 方法返回。

WebSearch 提供商工具允許智慧體搜尋網頁以獲取即時資訊。這對於回答關於時事、最新資料或在模型訓練截止日期後發生變化的主題非常有用。

支援的提供商: Anthropic, OpenAI, Gemini

1use Laravel\Ai\Providers\Tools\WebSearch;
2 
3public function tools(): iterable
4{
5 return [
6 new WebSearch,
7 ];
8}

你可以配置網頁搜尋工具以限制搜尋次數或將結果限制在特定域名內。

1(new WebSearch)->max(5)->allow(['laravel.com', 'php.net']),

若要根據使用者位置最佳化搜尋結果,請使用 location 方法。

1(new WebSearch)->location(
2 city: 'New York',
3 region: 'NY',
4 country: 'US'
5);

網頁獲取

WebFetch 提供商工具允許智慧體獲取並讀取網頁內容。當你需要智慧體分析特定 URL 或從已知網頁檢索詳細資訊時,這非常有用。

支援的提供商: Anthropic, Gemini

1use Laravel\Ai\Providers\Tools\WebFetch;
2 
3public function tools(): iterable
4{
5 return [
6 new WebFetch,
7 ];
8}

你可以配置網頁獲取工具以限制獲取數量或限制在特定域名內。

1(new WebFetch)->max(3)->allow(['docs.laravel.com']),

FileSearch 提供商工具允許智慧體搜尋儲存在 向量儲存 中的 檔案。這透過允許智慧體搜尋上傳的文件以獲取相關資訊,從而實現檢索增強生成 (RAG)。

支援的提供商: OpenAI, Gemini

1use Laravel\Ai\Providers\Tools\FileSearch;
2 
3public function tools(): iterable
4{
5 return [
6 new FileSearch(stores: ['store_id']),
7 ];
8}

你可以提供多個向量儲存 ID 以跨多個儲存進行搜尋。

1new FileSearch(stores: ['store_1', 'store_2']);

如果你的檔案具有 元資料,你可以透過提供 where 引數來過濾搜尋結果。對於簡單的相等過濾,傳遞一個數組即可。

1new FileSearch(stores: ['store_id'], where: [
2 'author' => 'Taylor Otwell',
3 'year' => 2026,
4]);

對於更復雜的過濾,你可以傳遞一個接收 FileSearchQuery 例項的閉包。

1use Laravel\Ai\Providers\Tools\FileSearchQuery;
2 
3new FileSearch(stores: ['store_id'], where: fn (FileSearchQuery $query) =>
4 $query->where('author', 'Taylor Otwell')
5 ->whereNot('status', 'draft')
6 ->whereIn('category', ['news', 'updates'])
7);

中介軟體

智慧體支援中介軟體,允許你在提示詞傳送給提供商之前對其進行攔截和修改。可以使用 make:agent-middleware Artisan 命令建立中介軟體。

1php artisan make:agent-middleware LogPrompts

生成的中介軟體將放置在應用程式的 app/Ai/Middleware 目錄中。要將中介軟體新增到智慧體,需實現 HasMiddleware 介面並定義一個 middleware 方法,該方法返回中介軟體類陣列。

1<?php
2 
3namespace App\Ai\Agents;
4 
5use App\Ai\Middleware\LogPrompts;
6use Laravel\Ai\Contracts\Agent;
7use Laravel\Ai\Contracts\HasMiddleware;
8use Laravel\Ai\Promptable;
9 
10class SalesCoach implements Agent, HasMiddleware
11{
12 use Promptable;
13 
14 // ...
15 
16 /**
17 * Get the agent's middleware.
18 */
19 public function middleware(): array
20 {
21 return [
22 new LogPrompts,
23 ];
24 }
25}

每個中介軟體類應定義一個 handle 方法,該方法接收 AgentPrompt 和一個用於將提示詞傳遞給下一個中介軟體的 Closure

1<?php
2 
3namespace App\Ai\Middleware;
4 
5use Closure;
6use Laravel\Ai\Prompts\AgentPrompt;
7 
8class LogPrompts
9{
10 /**
11 * Handle the incoming prompt.
12 */
13 public function handle(AgentPrompt $prompt, Closure $next)
14 {
15 Log::info('Prompting agent', ['prompt' => $prompt->prompt]);
16 
17 return $next($prompt);
18 }
19}

你可以在響應上使用 then 方法,在智慧體完成處理後執行程式碼。這適用於同步和流式響應。

1public function handle(AgentPrompt $prompt, Closure $next)
2{
3 return $next($prompt)->then(function (AgentResponse $response) {
4 Log::info('Agent responded', ['text' => $response->text]);
5 });
6}

匿名智慧體

有時你可能想在不建立專門智慧體類的情況下快速與模型互動。你可以使用 agent 函式建立一個臨時(匿名)智慧體。

1use function Laravel\Ai\{agent};
2 
3$response = agent(
4 instructions: 'You are an expert at software development.',
5 messages: [],
6 tools: [],
7)->prompt('Tell me about Laravel')

匿名智慧體也可以產生結構化輸出。

1use Illuminate\Contracts\JsonSchema\JsonSchema;
2 
3use function Laravel\Ai\{agent};
4 
5$response = agent(
6 schema: fn (JsonSchema $schema) => [
7 'number' => $schema->integer()->required(),
8 ],
9)->prompt('Generate a random number less than 100')

智慧體配置

你可以使用 PHP 屬性配置智慧體的文字生成選項。以下是可用屬性:

  • MaxSteps:使用工具時智慧體可以採取的最大步驟數。
  • MaxTokens:模型可以生成的最大 Token 數。
  • Model:智慧體應使用的模型。
  • Provider:智慧體使用的 AI 提供商(或用於故障轉移的提供商列表)。
  • Temperature:用於生成的取樣溫度(0.0 到 1.0)。
  • Timeout:智慧體請求的 HTTP 超時時間(秒,預設:60)。
  • UseCheapestModel:使用提供商最便宜的文字模型以進行成本最佳化。
  • UseSmartestModel:使用提供商最強大的文字模型以處理複雜任務。
1<?php
2 
3namespace App\Ai\Agents;
4 
5use Laravel\Ai\Attributes\MaxSteps;
6use Laravel\Ai\Attributes\MaxTokens;
7use Laravel\Ai\Attributes\Model;
8use Laravel\Ai\Attributes\Provider;
9use Laravel\Ai\Attributes\Temperature;
10use Laravel\Ai\Attributes\Timeout;
11use Laravel\Ai\Contracts\Agent;
12use Laravel\Ai\Enums\Lab;
13use Laravel\Ai\Promptable;
14 
15#[Provider(Lab::Anthropic)]
16#[Model('claude-haiku-4-5-20251001')]
17#[MaxSteps(10)]
18#[MaxTokens(4096)]
19#[Temperature(0.7)]
20#[Timeout(120)]
21class SalesCoach implements Agent
22{
23 use Promptable;
24 
25 // ...
26}

UseCheapestModelUseSmartestModel 屬性允許你無需指定模型名稱,即可自動為特定提供商選擇最具成本效益或最強大的模型。當你希望在不同提供商之間最佳化成本或能力時,這非常有用。

1use Laravel\Ai\Attributes\UseCheapestModel;
2use Laravel\Ai\Attributes\UseSmartestModel;
3use Laravel\Ai\Contracts\Agent;
4use Laravel\Ai\Promptable;
5 
6#[UseCheapestModel]
7class SimpleSummarizer implements Agent
8{
9 use Promptable;
10 
11 // Will use the cheapest model (e.g., Haiku)...
12}
13 
14#[UseSmartestModel]
15class ComplexReasoner implements Agent
16{
17 use Promptable;
18 
19 // Will use the most capable model (e.g., Opus)...
20}

提供商選項

如果你的智慧體需要傳遞提供商特定的選項(如 OpenAI 的推理工作量或懲罰設定),請實現 HasProviderOptions 契約並定義 providerOptions 方法。

1<?php
2 
3namespace App\Ai\Agents;
4 
5use Laravel\Ai\Contracts\Agent;
6use Laravel\Ai\Contracts\HasProviderOptions;
7use Laravel\Ai\Enums\Lab;
8use Laravel\Ai\Promptable;
9 
10class SalesCoach implements Agent, HasProviderOptions
11{
12 use Promptable;
13 
14 // ...
15 
16 /**
17 * Get provider-specific generation options.
18 */
19 public function providerOptions(Lab|string $provider): array
20 {
21 return match ($provider) {
22 Lab::OpenAI => [
23 'reasoning' => ['effort' => 'low'],
24 'frequency_penalty' => 0.5,
25 'presence_penalty' => 0.3,
26 ],
27 Lab::Anthropic => [
28 'thinking' => ['budget_tokens' => 1024],
29 ],
30 default => [],
31 };
32 }
33}

providerOptions 方法接收當前使用的提供商(Lab 列舉或字串),允許你按提供商返回不同的選項。在使用 故障轉移 時,這尤其有用,因為每個備用提供商都可以接收其各自的配置。

影像

Laravel\Ai\Image 類可用於使用 openaigeminixai 提供商生成影像。

1use Laravel\Ai\Image;
2 
3$image = Image::of('A donut sitting on the kitchen counter')->generate();
4 
5$rawContent = (string) $image;

squareportraitlandscape 方法可用於控制影像的長寬比,quality 方法可用於引導模型實現最終影像質量(highmediumlow)。timeout 方法可用於指定 HTTP 超時時間(秒)。

1use Laravel\Ai\Image;
2 
3$image = Image::of('A donut sitting on the kitchen counter')
4 ->quality('high')
5 ->landscape()
6 ->timeout(120)
7 ->generate();

你可以使用 attachments 方法附加參考影像。

1use Laravel\Ai\Files;
2use Laravel\Ai\Image;
3 
4$image = Image::of('Update this photo of me to be in the style of an impressionist painting.')
5 ->attachments([
6 Files\Image::fromStorage('photo.jpg'),
7 // Files\Image::fromPath('/home/laravel/photo.jpg'),
8 // Files\Image::fromUrl('https://example.com/photo.jpg'),
9 // $request->file('photo'),
10 ])
11 ->landscape()
12 ->generate();

生成的影像可以輕鬆儲存在應用程式 config/filesystems.php 配置檔案中配置的預設磁碟上。

1$image = Image::of('A donut sitting on the kitchen counter');
2 
3$path = $image->store();
4$path = $image->storeAs('image.jpg');
5$path = $image->storePublicly();
6$path = $image->storePubliclyAs('image.jpg');

影像生成也可以放入佇列。

1use Laravel\Ai\Image;
2use Laravel\Ai\Responses\ImageResponse;
3 
4Image::of('A donut sitting on the kitchen counter')
5 ->portrait()
6 ->queue()
7 ->then(function (ImageResponse $image) {
8 $path = $image->store();
9 
10 // ...
11 });

音訊

Laravel\Ai\Audio 類可用於根據給定的文字生成音訊。

1use Laravel\Ai\Audio;
2 
3$audio = Audio::of('I love coding with Laravel.')->generate();
4 
5$rawContent = (string) $audio;

malefemalevoice 方法可用於確定生成音訊的音色。

1$audio = Audio::of('I love coding with Laravel.')
2 ->female()
3 ->generate();
4 
5$audio = Audio::of('I love coding with Laravel.')
6 ->voice('voice-id-or-name')
7 ->generate();

類似地,instructions 方法可用於動態指導模型生成音訊的聽感效果。

1$audio = Audio::of('I love coding with Laravel.')
2 ->female()
3 ->instructions('Said like a pirate')
4 ->generate();

生成的音訊可以輕鬆儲存在應用程式 config/filesystems.php 配置檔案中配置的預設磁碟上。

1$audio = Audio::of('I love coding with Laravel.')->generate();
2 
3$path = $audio->store();
4$path = $audio->storeAs('audio.mp3');
5$path = $audio->storePublicly();
6$path = $audio->storePubliclyAs('audio.mp3');

音訊生成也可以放入佇列。

1use Laravel\Ai\Audio;
2use Laravel\Ai\Responses\AudioResponse;
3 
4Audio::of('I love coding with Laravel.')
5 ->queue()
6 ->then(function (AudioResponse $audio) {
7 $path = $audio->store();
8 
9 // ...
10 });

轉錄

Laravel\Ai\Transcription 類可用於根據給定的音訊生成轉錄文字。

1use Laravel\Ai\Transcription;
2 
3$transcript = Transcription::fromPath('/home/laravel/audio.mp3')->generate();
4$transcript = Transcription::fromStorage('audio.mp3')->generate();
5$transcript = Transcription::fromUpload($request->file('audio'))->generate();
6 
7return (string) $transcript;

diarize 方法可用於指示你希望響應包含帶有說話人識別的轉錄,從而使你能夠按說話人訪問分段轉錄。

1$transcript = Transcription::fromStorage('audio.mp3')
2 ->diarize()
3 ->generate();

轉錄生成也可以放入佇列。

1use Laravel\Ai\Transcription;
2use Laravel\Ai\Responses\TranscriptionResponse;
3 
4Transcription::fromStorage('audio.mp3')
5 ->queue()
6 ->then(function (TranscriptionResponse $transcript) {
7 // ...
8 });

嵌入 (Embeddings)

你可以使用 Laravel Stringable 類中新增的 toEmbeddings 方法,輕鬆為任何給定的字串生成向量嵌入。

1use Illuminate\Support\Str;
2 
3$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings();

或者,你可以使用 Embeddings 類一次性為多個輸入生成嵌入。

1use Laravel\Ai\Embeddings;
2 
3$response = Embeddings::for([
4 'Napa Valley has great wine.',
5 'Laravel is a PHP framework.',
6])->generate();
7 
8$response->embeddings; // [[0.123, 0.456, ...], [0.789, 0.012, ...]]

你可以指定嵌入的維度和提供商。

1$response = Embeddings::for(['Napa Valley has great wine.'])
2 ->dimensions(1536)
3 ->generate(Lab::OpenAI, 'text-embedding-3-small');

查詢嵌入

生成嵌入後,通常會將它們儲存在資料庫的 vector 列中以備後續查詢。Laravel 透過 pgvector 擴充套件對 PostgreSQL 上的向量列提供了原生支援。開始之前,請在遷移中定義一個 vector 列,並指定維度數。

1Schema::ensureVectorExtensionExists();
2 
3Schema::create('documents', function (Blueprint $table) {
4 $table->id();
5 $table->string('title');
6 $table->text('content');
7 $table->vector('embedding', dimensions: 1536);
8 $table->timestamps();
9});

你還可以新增向量索引以加速相似度搜索。當在向量列上呼叫 index 時,Laravel 會自動建立一個帶有餘弦距離的 HNSW 索引。

1$table->vector('embedding', dimensions: 1536)->index();

在 Eloquent 模型上,你應該將向量列轉換為 array

1protected function casts(): array
2{
3 return [
4 'embedding' => 'array',
5 ];
6}

要查詢相似記錄,請使用 whereVectorSimilarTo 方法。該方法透過最小余弦相似度(0.01.0,其中 1.0 表示完全相同)過濾結果,並按相似度對結果進行排序。

1use App\Models\Document;
2 
3$documents = Document::query()
4 ->whereVectorSimilarTo('embedding', $queryEmbedding, minSimilarity: 0.4)
5 ->limit(10)
6 ->get();

$queryEmbedding 可以是浮點數陣列或純字串。當給定字串時,Laravel 會自動為其生成嵌入。

1$documents = Document::query()
2 ->whereVectorSimilarTo('embedding', 'best wineries in Napa Valley')
3 ->limit(10)
4 ->get();

如果需要更多控制權,你可以獨立使用底層方法:whereVectorDistanceLessThanselectVectorDistanceorderByVectorDistance

1$documents = Document::query()
2 ->select('*')
3 ->selectVectorDistance('embedding', $queryEmbedding, as: 'distance')
4 ->whereVectorDistanceLessThan('embedding', $queryEmbedding, maxDistance: 0.3)
5 ->orderByVectorDistance('embedding', $queryEmbedding)
6 ->limit(10)
7 ->get();

如果你希望賦予智慧體作為工具執行相似度搜索的能力,請查閱 相似度搜索 工具文件。

向量查詢目前僅在支援 pgvector 擴充套件的 PostgreSQL 連線上受支援。

快取嵌入

嵌入生成可以被快取,以避免對相同輸入進行冗餘 API 呼叫。要啟用快取,請將 ai.caching.embeddings.cache 配置選項設定為 true

1'caching' => [
2 'embeddings' => [
3 'cache' => true,
4 'store' => env('CACHE_STORE', 'database'),
5 // ...
6 ],
7],

啟用快取後,嵌入會被快取 30 天。快取鍵基於提供商、模型、維度和輸入內容,確保相同的請求返回快取結果,而不同的配置會生成新的嵌入。

即使全域性快取被停用,你也可以使用 cache 方法為特定請求啟用快取。

1$response = Embeddings::for(['Napa Valley has great wine.'])
2 ->cache()
3 ->generate();

你可以指定自定義的快取時長(秒)。

1$response = Embeddings::for(['Napa Valley has great wine.'])
2 ->cache(seconds: 3600) // Cache for 1 hour
3 ->generate();

toEmbeddings Stringable 方法也接受一個 cache 引數。

1// Cache with default duration...
2$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: true);
3 
4// Cache for a specific duration...
5$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: 3600);

重排序 (Reranking)

重排序(Reranking)允許你根據文件與給定查詢的相關性對其進行重新排序。這對於透過語義理解改進搜尋結果非常有用。

Laravel\Ai\Reranking 類可用於重排序文件。

1use Laravel\Ai\Reranking;
2 
3$response = Reranking::of([
4 'Django is a Python web framework.',
5 'Laravel is a PHP web application framework.',
6 'React is a JavaScript library for building user interfaces.',
7])->rerank('PHP frameworks');
8 
9// Access the top result...
10$response->first()->document; // "Laravel is a PHP web application framework."
11$response->first()->score; // 0.95
12$response->first()->index; // 1 (original position)

limit 方法可用於限制返回的結果數量。

1$response = Reranking::of($documents)
2 ->limit(5)
3 ->rerank('search query');

重排序集合

為方便起見,可以使用 rerank 宏對 Laravel 集合進行重排序。第一個引數指定用於重排序的欄位,第二個引數是查詢語句。

1// Rerank by a single field...
2$posts = Post::all()
3 ->rerank('body', 'Laravel tutorials');
4 
5// Rerank by multiple fields (sent as JSON)...
6$reranked = $posts->rerank(['title', 'body'], 'Laravel tutorials');
7 
8// Rerank using a closure to build the document...
9$reranked = $posts->rerank(
10 fn ($post) => $post->title.': '.$post->body,
11 'Laravel tutorials'
12);

你還可以限制結果數量並指定提供商。

1$reranked = $posts->rerank(
2 by: 'content',
3 query: 'Laravel tutorials',
4 limit: 10,
5 provider: Lab::Cohere
6);

檔案

Laravel\Ai\Files 類或單獨的檔案類可用於將檔案儲存在你的 AI 提供商處,以供後續對話使用。這對於大檔案或你希望多次引用而不必重新上傳的檔案非常有用。

1use Laravel\Ai\Files\Document;
2use Laravel\Ai\Files\Image;
3 
4// Store a file from a local path...
5$response = Document::fromPath('/home/laravel/document.pdf')->put();
6$response = Image::fromPath('/home/laravel/photo.jpg')->put();
7 
8// Store a file that is stored on a filesystem disk...
9$response = Document::fromStorage('document.pdf', disk: 'local')->put();
10$response = Image::fromStorage('photo.jpg', disk: 'local')->put();
11 
12// Store a file that is stored on a remote URL...
13$response = Document::fromUrl('https://example.com/document.pdf')->put();
14$response = Image::fromUrl('https://example.com/photo.jpg')->put();
15 
16return $response->id;

你也可以儲存原始內容或上傳的檔案。

1use Laravel\Ai\Files;
2use Laravel\Ai\Files\Document;
3 
4// Store raw content...
5$stored = Document::fromString('Hello, World!', 'text/plain')->put();
6 
7// Store an uploaded file...
8$stored = Document::fromUpload($request->file('document'))->put();

一旦檔案儲存完畢,在透過智慧體生成文字時,可以直接引用該檔案,而無需重新上傳。

1use App\Ai\Agents\SalesCoach;
2use Laravel\Ai\Files;
3 
4$response = (new SalesCoach)->prompt(
5 'Analyze the attached sales transcript...'
6 attachments: [
7 Files\Document::fromId('file-id') // Attach a stored document...
8 ]
9);

要檢索之前儲存的檔案,請在檔案例項上使用 get 方法。

1use Laravel\Ai\Files\Document;
2 
3$file = Document::fromId('file-id')->get();
4 
5$file->id;
6$file->mimeType();

要從提供商處刪除檔案,請使用 delete 方法。

1Document::fromId('file-id')->delete();

預設情況下,Files 類使用應用程式 config/ai.php 配置檔案中配置的預設 AI 提供商。對於大多數操作,你可以使用 provider 引數指定不同的提供商。

1$response = Document::fromPath(
2 '/home/laravel/document.pdf'
3)->put(provider: Lab::Anthropic);

在對話中使用儲存的檔案

一旦檔案儲存在提供商處,你就可以使用 DocumentImage 類上的 fromId 方法在智慧體對話中引用它。

1use App\Ai\Agents\DocumentAnalyzer;
2use Laravel\Ai\Files;
3use Laravel\Ai\Files\Document;
4 
5$stored = Document::fromPath('/path/to/report.pdf')->put();
6 
7$response = (new DocumentAnalyzer)->prompt(
8 'Summarize this document.',
9 attachments: [
10 Document::fromId($stored->id),
11 ],
12);

同樣,儲存的影像可以使用 Image 類進行引用。

1use Laravel\Ai\Files;
2use Laravel\Ai\Files\Image;
3 
4$stored = Image::fromPath('/path/to/photo.jpg')->put();
5 
6$response = (new ImageAnalyzer)->prompt(
7 'What is in this image?',
8 attachments: [
9 Image::fromId($stored->id),
10 ],
11);

向量儲存

向量儲存允許你建立可搜尋的檔案集合,可用於檢索增強生成 (RAG)。Laravel\Ai\Stores 類提供了建立、檢索和刪除向量儲存的方法。

1use Laravel\Ai\Stores;
2 
3// Create a new vector store...
4$store = Stores::create('Knowledge Base');
5 
6// Create a store with additional options...
7$store = Stores::create(
8 name: 'Knowledge Base',
9 description: 'Documentation and reference materials.',
10 expiresWhenIdleFor: days(30),
11);
12 
13return $store->id;

要按 ID 檢索現有的向量儲存,請使用 get 方法。

1use Laravel\Ai\Stores;
2 
3$store = Stores::get('store_id');
4 
5$store->id;
6$store->name;
7$store->fileCounts;
8$store->ready;

要刪除向量儲存,請在 Stores 類或儲存例項上使用 delete 方法。

1use Laravel\Ai\Stores;
2 
3// Delete by ID...
4Stores::delete('store_id');
5 
6// Or delete via a store instance...
7$store = Stores::get('store_id');
8 
9$store->delete();

向儲存中新增檔案

擁有向量儲存後,可以使用 add 方法向其中新增 檔案。新增到儲存中的檔案會自動索引,以便使用 檔案搜尋提供商工具 進行語義搜尋。

1use Laravel\Ai\Files\Document;
2use Laravel\Ai\Stores;
3 
4$store = Stores::get('store_id');
5 
6// Add a file that has already been stored with the provider...
7$document = $store->add('file_id');
8$document = $store->add(Document::fromId('file_id'));
9 
10// Or, store and add a file in one step...
11$document = $store->add(Document::fromPath('/path/to/document.pdf'));
12$document = $store->add(Document::fromStorage('manual.pdf'));
13$document = $store->add($request->file('document'));
14 
15$document->id;
16$document->fileId;

通常,當向向量儲存新增之前儲存的檔案時,返回的文件 ID 會與檔案之前分配的 ID 匹配;但某些向量儲存提供商可能會返回一個新的、不同的“文件 ID”。因此,建議你在資料庫中同時儲存這兩個 ID 以供日後參考。

新增檔案到儲存時,可以為其附加元資料。這些元資料稍後可在使用 檔案搜尋提供商工具 時用於過濾搜尋結果。

1$store->add(Document::fromPath('/path/to/document.pdf'), metadata: [
2 'author' => 'Taylor Otwell',
3 'department' => 'Engineering',
4 'year' => 2026,
5]);

要從儲存中移除檔案,請使用 remove 方法。

1$store->remove('file_id');

從向量儲存中移除檔案不會將其從提供商的 檔案儲存 中移除。要從向量儲存中移除檔案並將其從檔案儲存中永久刪除,請使用 deleteFile 引數。

1$store->remove('file_abc123', deleteFile: true);

故障轉移 (Failover)

在傳送提示詞或生成其他媒體時,你可以提供一個提供商/模型陣列,以便在主要提供商遇到服務中斷或速率限制時,自動故障轉移到備份提供商/模型。

1use App\Ai\Agents\SalesCoach;
2use Laravel\Ai\Image;
3 
4$response = (new SalesCoach)->prompt(
5 'Analyze this sales transcript...',
6 provider: [Lab::OpenAI, Lab::Anthropic],
7);
8 
9$image = Image::of('A donut sitting on the kitchen counter')
10 ->generate(provider: [Lab::Gemini, Lab::xAI]);

測試

智慧體 (Agents)

要在測試中偽造智慧體的響應,請在智慧體類上呼叫 fake 方法。你可以選擇提供響應陣列或閉包。

1use App\Ai\Agents\SalesCoach;
2use Laravel\Ai\Prompts\AgentPrompt;
3 
4// Automatically generate a fixed response for every prompt...
5SalesCoach::fake();
6 
7// Provide a list of prompt responses...
8SalesCoach::fake([
9 'First response',
10 'Second response',
11]);
12 
13// Dynamically handle prompt responses based on the incoming prompt...
14SalesCoach::fake(function (AgentPrompt $prompt) {
15 return 'Response for: '.$prompt->prompt;
16});

當對返回結構化輸出的智慧體呼叫 Agent::fake() 時,Laravel 會自動生成符合你定義的輸出模式的偽造資料。

傳送提示詞後,你可以對接收到的提示詞進行斷言。

1use Laravel\Ai\Prompts\AgentPrompt;
2 
3SalesCoach::assertPrompted('Analyze this...');
4 
5SalesCoach::assertPrompted(function (AgentPrompt $prompt) {
6 return $prompt->contains('Analyze');
7});
8 
9SalesCoach::assertNotPrompted('Missing prompt');
10 
11SalesCoach::assertNeverPrompted();

對於佇列化的智慧體呼叫,請使用佇列斷言方法。

1use Laravel\Ai\QueuedAgentPrompt;
2 
3SalesCoach::assertQueued('Analyze this...');
4 
5SalesCoach::assertQueued(function (QueuedAgentPrompt $prompt) {
6 return $prompt->contains('Analyze');
7});
8 
9SalesCoach::assertNotQueued('Missing prompt');
10 
11SalesCoach::assertNeverQueued();

要確保所有智慧體呼叫都有對應的偽造響應,你可以使用 preventStrayPrompts。如果呼叫了沒有定義偽造響應的智慧體,將丟擲異常。

1SalesCoach::fake()->preventStrayPrompts();

影像

影像生成可以透過在 Image 類上呼叫 fake 方法進行偽造。一旦偽造,就可以對記錄的影像生成提示詞執行各種斷言。

1use Laravel\Ai\Image;
2use Laravel\Ai\Prompts\ImagePrompt;
3use Laravel\Ai\Prompts\QueuedImagePrompt;
4 
5// Automatically generate a fixed response for every prompt...
6Image::fake();
7 
8// Provide a list of prompt responses...
9Image::fake([
10 base64_encode($firstImage),
11 base64_encode($secondImage),
12]);
13 
14// Dynamically handle prompt responses based on the incoming prompt...
15Image::fake(function (ImagePrompt $prompt) {
16 return base64_encode('...');
17});

生成影像後,你可以對接收到的提示詞進行斷言。

1Image::assertGenerated(function (ImagePrompt $prompt) {
2 return $prompt->contains('sunset') && $prompt->isLandscape();
3});
4 
5Image::assertNotGenerated('Missing prompt');
6 
7Image::assertNothingGenerated();

對於佇列化的影像生成,請使用佇列斷言方法。

1Image::assertQueued(
2 fn (QueuedImagePrompt $prompt) => $prompt->contains('sunset')
3);
4 
5Image::assertNotQueued('Missing prompt');
6 
7Image::assertNothingQueued();

要確保所有影像生成都有對應的偽造響應,你可以使用 preventStrayImages。如果生成影像時沒有定義偽造響應,將丟擲異常。

1Image::fake()->preventStrayImages();

音訊

音訊生成可以透過在 Audio 類上呼叫 fake 方法進行偽造。一旦偽造,就可以對記錄的音訊生成提示詞執行各種斷言。

1use Laravel\Ai\Audio;
2use Laravel\Ai\Prompts\AudioPrompt;
3use Laravel\Ai\Prompts\QueuedAudioPrompt;
4 
5// Automatically generate a fixed response for every prompt...
6Audio::fake();
7 
8// Provide a list of prompt responses...
9Audio::fake([
10 base64_encode($firstAudio),
11 base64_encode($secondAudio),
12]);
13 
14// Dynamically handle prompt responses based on the incoming prompt...
15Audio::fake(function (AudioPrompt $prompt) {
16 return base64_encode('...');
17});

生成音訊後,你可以對接收到的提示詞進行斷言。

1Audio::assertGenerated(function (AudioPrompt $prompt) {
2 return $prompt->contains('Hello') && $prompt->isFemale();
3});
4 
5Audio::assertNotGenerated('Missing prompt');
6 
7Audio::assertNothingGenerated();

對於佇列化的音訊生成,請使用佇列斷言方法。

1Audio::assertQueued(
2 fn (QueuedAudioPrompt $prompt) => $prompt->contains('Hello')
3);
4 
5Audio::assertNotQueued('Missing prompt');
6 
7Audio::assertNothingQueued();

要確保所有音訊生成都有對應的偽造響應,你可以使用 preventStrayAudio。如果生成音訊時沒有定義偽造響應,將丟擲異常。

1Audio::fake()->preventStrayAudio();

轉錄

轉錄生成可以透過在 Transcription 類上呼叫 fake 方法進行偽造。一旦偽造,就可以對記錄的轉錄生成提示詞執行各種斷言。

1use Laravel\Ai\Transcription;
2use Laravel\Ai\Prompts\TranscriptionPrompt;
3use Laravel\Ai\Prompts\QueuedTranscriptionPrompt;
4 
5// Automatically generate a fixed response for every prompt...
6Transcription::fake();
7 
8// Provide a list of prompt responses...
9Transcription::fake([
10 'First transcription text.',
11 'Second transcription text.',
12]);
13 
14// Dynamically handle prompt responses based on the incoming prompt...
15Transcription::fake(function (TranscriptionPrompt $prompt) {
16 return 'Transcribed text...';
17});

生成轉錄後,你可以對接收到的提示詞進行斷言。

1Transcription::assertGenerated(function (TranscriptionPrompt $prompt) {
2 return $prompt->language === 'en' && $prompt->isDiarized();
3});
4 
5Transcription::assertNotGenerated(
6 fn (TranscriptionPrompt $prompt) => $prompt->language === 'fr'
7);
8 
9Transcription::assertNothingGenerated();

對於佇列化的轉錄生成,請使用佇列斷言方法。

1Transcription::assertQueued(
2 fn (QueuedTranscriptionPrompt $prompt) => $prompt->isDiarized()
3);
4 
5Transcription::assertNotQueued(
6 fn (QueuedTranscriptionPrompt $prompt) => $prompt->language === 'fr'
7);
8 
9Transcription::assertNothingQueued();

要確保所有轉錄生成都有對應的偽造響應,你可以使用 preventStrayTranscriptions。如果生成轉錄時沒有定義偽造響應,將丟擲異常。

1Transcription::fake()->preventStrayTranscriptions();

嵌入 (Embeddings)

嵌入生成可以透過在 Embeddings 類上呼叫 fake 方法進行偽造。一旦偽造,就可以對記錄的嵌入生成提示詞執行各種斷言。

1use Laravel\Ai\Embeddings;
2use Laravel\Ai\Prompts\EmbeddingsPrompt;
3use Laravel\Ai\Prompts\QueuedEmbeddingsPrompt;
4 
5// Automatically generate fake embeddings of the proper dimensions for every prompt...
6Embeddings::fake();
7 
8// Provide a list of prompt responses...
9Embeddings::fake([
10 [$firstEmbeddingVector],
11 [$secondEmbeddingVector],
12]);
13 
14// Dynamically handle prompt responses based on the incoming prompt...
15Embeddings::fake(function (EmbeddingsPrompt $prompt) {
16 return array_map(
17 fn () => Embeddings::fakeEmbedding($prompt->dimensions),
18 $prompt->inputs
19 );
20});

生成嵌入後,你可以對接收到的提示詞進行斷言。

1Embeddings::assertGenerated(function (EmbeddingsPrompt $prompt) {
2 return $prompt->contains('Laravel') && $prompt->dimensions === 1536;
3});
4 
5Embeddings::assertNotGenerated(
6 fn (EmbeddingsPrompt $prompt) => $prompt->contains('Other')
7);
8 
9Embeddings::assertNothingGenerated();

對於佇列化的嵌入生成,請使用佇列斷言方法。

1Embeddings::assertQueued(
2 fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Laravel')
3);
4 
5Embeddings::assertNotQueued(
6 fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Other')
7);
8 
9Embeddings::assertNothingQueued();

要確保所有嵌入生成都有對應的偽造響應,你可以使用 preventStrayEmbeddings。如果生成嵌入時沒有定義偽造響應,將丟擲異常。

1Embeddings::fake()->preventStrayEmbeddings();

重排序 (Reranking)

重排序操作可以透過在 Reranking 類上呼叫 fake 方法進行偽造。

1use Laravel\Ai\Reranking;
2use Laravel\Ai\Prompts\RerankingPrompt;
3use Laravel\Ai\Responses\Data\RankedDocument;
4 
5// Automatically generate a fake reranked responses...
6Reranking::fake();
7 
8// Provide custom responses...
9Reranking::fake([
10 [
11 new RankedDocument(index: 0, document: 'First', score: 0.95),
12 new RankedDocument(index: 1, document: 'Second', score: 0.80),
13 ],
14]);

重排序後,你可以對執行的操作進行斷言。

1Reranking::assertReranked(function (RerankingPrompt $prompt) {
2 return $prompt->contains('Laravel') && $prompt->limit === 5;
3});
4 
5Reranking::assertNotReranked(
6 fn (RerankingPrompt $prompt) => $prompt->contains('Django')
7);
8 
9Reranking::assertNothingReranked();

檔案

檔案操作可以透過在 Files 類上呼叫 fake 方法進行偽造。

1use Laravel\Ai\Files;
2 
3Files::fake();

一旦檔案操作被偽造,你就可以對發生的上傳和刪除操作進行斷言。

1use Laravel\Ai\Contracts\Files\StorableFile;
2use Laravel\Ai\Files\Document;
3 
4// Store files...
5Document::fromString('Hello, Laravel!', mimeType: 'text/plain')
6 ->as('hello.txt')
7 ->put();
8 
9// Make assertions...
10Files::assertStored(fn (StorableFile $file) =>
11 (string) $file === 'Hello, Laravel!' &&
12 $file->mimeType() === 'text/plain';
13);
14 
15Files::assertNotStored(fn (StorableFile $file) =>
16 (string) $file === 'Hello, World!'
17);
18 
19Files::assertNothingStored();

對於刪除檔案的斷言,可以傳遞一個檔案 ID。

1Files::assertDeleted('file-id');
2Files::assertNotDeleted('file-id');
3Files::assertNothingDeleted();

向量儲存

向量儲存操作可以透過在 Stores 類上呼叫 fake 方法進行偽造。偽造儲存時,也會自動偽造 檔案操作

1use Laravel\Ai\Stores;
2 
3Stores::fake();

一旦儲存操作被偽造,你就可以對建立或刪除的儲存進行斷言。

1use Laravel\Ai\Stores;
2 
3// Create store...
4$store = Stores::create('Knowledge Base');
5 
6// Make assertions...
7Stores::assertCreated('Knowledge Base');
8 
9Stores::assertCreated(fn (string $name, ?string $description) =>
10 $name === 'Knowledge Base'
11);
12 
13Stores::assertNotCreated('Other Store');
14 
15Stores::assertNothingCreated();

對於刪除儲存的斷言,可以提供儲存 ID。

1Stores::assertDeleted('store_id');
2Stores::assertNotDeleted('other_store_id');
3Stores::assertNothingDeleted();

要斷言檔案已新增到儲存或從儲存中移除,請在給定的 Store 例項上使用斷言方法。

1Stores::fake();
2 
3$store = Stores::get('store_id');
4 
5// Add / remove files...
6$store->add('added_id');
7$store->remove('removed_id');
8 
9// Make assertions...
10$store->assertAdded('added_id');
11$store->assertRemoved('removed_id');
12 
13$store->assertNotAdded('other_file_id');
14$store->assertNotRemoved('other_file_id');

如果檔案儲存在提供商的 檔案儲存 中,並在同一請求中新增到向量儲存,你可能不知道該檔案的提供商 ID。在這種情況下,你可以向 assertAdded 方法傳遞一個閉包,以根據新增檔案的內容進行斷言。

1use Laravel\Ai\Contracts\Files\StorableFile;
2use Laravel\Ai\Files\Document;
3 
4$store->add(Document::fromString('Hello, World!', 'text/plain')->as('hello.txt'));
5 
6$store->assertAdded(fn (StorableFile $file) => $file->name() === 'hello.txt');
7$store->assertAdded(fn (StorableFile $file) => $file->content() === 'Hello, World!');

活動

Laravel AI SDK 分發了多種 事件,包括:

  • AddingFileToStore
  • AgentPrompted
  • AgentStreamed
  • AudioGenerated
  • CreatingStore
  • EmbeddingsGenerated
  • FileAddedToStore
  • FileDeleted
  • FileRemovedFromStore
  • FileStored
  • GeneratingAudio
  • GeneratingEmbeddings
  • GeneratingImage
  • GeneratingTranscription
  • ImageGenerated
  • InvokingTool
  • PromptingAgent
  • RemovingFileFromStore
  • Reranked
  • 重排序 (Reranking)
  • StoreCreated
  • StoringFile
  • StreamingAgent
  • ToolInvoked
  • TranscriptionGenerated

你可以監聽這些事件來記錄或儲存 AI SDK 的使用資訊。