Laravel AI SDK
- 簡介
- 安裝
- Agents
- 圖片
- 音訊 (TTS)
- 轉錄 (STT)
- 嵌入 (Embeddings)
- 重排 (Reranking)
- 檔案
- 向量儲存 (Vector Stores)
- 故障轉移 (Failover)
- 測試
- 事件 (Events)
簡介
Laravel AI SDK 提供了一個統一且具表達力的 API,用於與 OpenAI、Anthropic、Gemini 等 AI 服務商進行互動。透過 AI SDK,您可以建構具有工具和結構化輸出的智慧 Agents、生成圖片、合成與轉錄音訊、建立向量嵌入 (Embeddings) 等等 — 所有的這一切都使用了統一且對 Laravel 友好的介面。
安裝
您可以透過 Composer 安裝 Laravel AI SDK:
composer require laravel/ai接著,您應該使用 vendor:publish Artisan 指令來發佈 AI SDK 的設定檔與遷移 (Migration) 檔案:
php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"最後,您應該執行應用程式的資料庫遷移。這將會建立 agent_conversations 與 agent_conversation_messages 資料表,AI SDK 使用這些資料表來支援其對話儲存功能:
php artisan migrate設定
您可以在應用程式的 config/ai.php 設定檔中定義 AI 服務商的憑證,或是作為環境變數定義在應用程式的 .env 檔案中:
ANTHROPIC_API_KEY=
COHERE_API_KEY=
ELEVENLABS_API_KEY=
GEMINI_API_KEY=
MISTRAL_API_KEY=
OLLAMA_API_KEY=
OPENAI_API_KEY=
JINA_API_KEY=
VOYAGEAI_API_KEY=
XAI_API_KEY=用於文字、圖片、音訊、轉錄與嵌入的預設模型也可以在您應用程式的 config/ai.php 設定檔中進行設定。
自定義基礎 URL
預設情況下,Laravel AI SDK 會直接連接到各個服務商的公開 API 端點 (Endpoint)。然而,您可能需要透過不同的端點來路由請求 — 例如,當使用代理服務來集中管理 API 金鑰、實施速率限制,或透過企業閘道路由流量時。
您可以透過在服務商設定中加入 url 參數來設定自定義基礎 URL:
'providers' => [
'openai' => [
'driver' => 'openai',
'key' => env('OPENAI_API_KEY'),
'url' => env('OPENAI_BASE_URL'),
],
'anthropic' => [
'driver' => 'anthropic',
'key' => env('ANTHROPIC_API_KEY'),
'url' => env('ANTHROPIC_BASE_URL'),
],
],這在透過代理服務(如 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 |
| 嵌入 | OpenAI, Gemini, Azure, Cohere, Mistral, Jina, VoyageAI |
| 重排 | Cohere, Jina |
| 檔案 | OpenAI, Anthropic, Gemini |
Laravel\Ai\Enums\Lab 列舉 (Enum) 可用於在整個程式碼中引用服務商,而不需要使用純字串:
use Laravel\Ai\Enums\Lab;
Lab::Anthropic;
Lab::OpenAI;
Lab::Gemini;
// ...Agents
Agents 是在 Laravel AI SDK 中與 AI 服務商互動的基本構建塊。每個 Agent 都是一個專用的 PHP 類別,封裝了與大型語言模型互動所需的指令、對話上下文、工具和輸出架構 (Schema)。將 Agent 視為一個專業助理 —— 例如銷售教練、文件分析師、支援機器人 —— 您只需設定一次,便可在整個應用程式中根據需要進行提示 (Prompt)。
您可以透過 make:agent Artisan 指令建立 Agent:
php artisan make:agent SalesCoach
php artisan make:agent SalesCoach --structured在產生的 Agent 類別中,您可以定義系統提示 / 指令、訊息上下文、可用工具以及輸出架構(如果適用):
<?php
namespace 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) {}
/**
* Get the instructions that the agent should follow.
*/
public function instructions(): Stringable|string
{
return 'You are a sales coach, analyzing transcripts and providing feedback and an overall sales strength score.';
}
/**
* Get the list of messages comprising the conversation so far.
*/
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();
}
/**
* Get the tools available to the agent.
*
* @return Tool[]
*/
public function tools(): iterable
{
return [
new RetrievePreviousTranscripts,
];
}
/**
* Get the agent's structured output schema definition.
*/
public function schema(JsonSchema $schema): array
{
return [
'feedback' => $schema->string()->required(),
'score' => $schema->integer()->min(1)->max(10)->required(),
];
}
}提示 (Prompting)
要提示 Agent,請先使用 make 方法或標準實例化建立一個實例,然後呼叫 prompt:
$response = (new SalesCoach)
->prompt('Analyze this sales transcript...');
$response = SalesCoach::make()
->prompt('Analyze this sales transcript...');
return (string) $response;make 方法會從容器中解析您的 Agent,從而允許自動依賴注入。您也可以向 Agent 的建構函式傳遞參數:
$agent = SalesCoach::make(user: $user);藉由向 prompt 方法傳遞額外的參數,您可以在提示時覆寫預設的服務商、模型或 HTTP 逾時時間:
$response = (new SalesCoach)->prompt(
'Analyze this sales transcript...',
provider: Lab::Anthropic,
model: 'claude-haiku-4-5-20251001',
timeout: 120,
);對話上下文
如果您的 Agent 實作了 Conversational 介面,您可以使用 messages 方法來回傳先前的對話上下文(如果適用):
use App\Models\History;
use Laravel\Ai\Messages\Message;
/**
* Get the list of messages comprising the conversation so far.
*/
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();
}記住對話
注意: 在使用
RemembersConversationstrait 之前,您應該使用vendor:publishArtisan 指令發布並執行 AI SDK 遷移。這些遷移將建立儲存對話所需的資料庫資料表。
如果您希望 Laravel 自動為您的 Agent 儲存和檢索對話記錄,您可以使用 RemembersConversations trait。此 trait 提供了一種簡單的方法,可以將對話訊息持久化到資料庫中,而無需手動實作 Conversational 介面:
<?php
namespace App\Ai\Agents;
use Laravel\Ai\Concerns\RemembersConversations;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent, Conversational
{
use Promptable, RemembersConversations;
/**
* Get the instructions that the agent should follow.
*/
public function instructions(): string
{
return 'You are a sales coach...';
}
}要為使用者開始新的對話,請在提示前呼叫 forUser 方法:
$response = (new SalesCoach)->forUser($user)->prompt('Hello!');
$conversationId = $response->conversationId;對話 ID 會包含在回應中並可儲存以供日後參考,或者您可以直接從 agent_conversations 資料表中檢索使用者的所有對話。
要繼續現有的對話,請使用 continue 方法:
$response = (new SalesCoach)
->continue($conversationId, as: $user)
->prompt('Tell me more about that.');當使用 RemembersConversations trait 時,先前的訊息會在提示時自動載入並包含在對話上下文中。新的訊息(包括使用者和助理)會在每次互動後自動儲存。
結構化輸出
如果您希望您的 Agent 回傳結構化輸出,請實作 HasStructuredOutput 介面,這要求您的 Agent 定義一個 schema 方法:
<?php
namespace App\Ai\Agents;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent, HasStructuredOutput
{
use Promptable;
// ...
/**
* Get the agent's structured output schema definition.
*/
public function schema(JsonSchema $schema): array
{
return [
'score' => $schema->integer()->required(),
];
}
}當提示一個回傳結構化輸出的 Agent 時,您可以像存取陣列一樣存取回傳的 StructuredAgentResponse:
$response = (new SalesCoach)->prompt('Analyze this sales transcript...');
return $response['score'];附件
提示時,您也可以隨提示傳遞附件,讓模型檢查圖片和文件:
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Files;
$response = (new SalesCoach)->prompt(
'Analyze the attached sales transcript...',
attachments: [
Files\Document::fromStorage('transcript.pdf') // Attach a document from a filesystem disk...
Files\Document::fromPath('/home/laravel/transcript.md') // Attach a document from a local path...
$request->file('transcript'), // Attach an uploaded file...
]
);同樣地,Laravel\Ai\Files\Image 類別可用於將圖片附加到提示中:
use App\Ai\Agents\ImageAnalyzer;
use Laravel\Ai\Files;
$response = (new ImageAnalyzer)->prompt(
'What is in this image?',
attachments: [
Files\Image::fromStorage('photo.jpg') // Attach an image from a filesystem disk...
Files\Image::fromPath('/home/laravel/photo.jpg') // Attach an image from a local path...
$request->file('photo'), // Attach an uploaded file...
]
);串流
您可以透過呼叫 stream 方法來串流 Agent 的回應。回傳的 StreamableAgentResponse 可以從路由中回傳,以自動向客戶端發送串流回應 (SSE):
use App\Ai\Agents\SalesCoach;
Route::get('/coach', function () {
return (new SalesCoach)->stream('Analyze this sales transcript...');
});then 方法可用於提供一個閉包 (Closure),該閉包將在整個回應都已串流至客戶端時被呼叫:
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Responses\StreamedAgentResponse;
Route::get('/coach', function () {
return (new SalesCoach)
->stream('Analyze this sales transcript...')
->then(function (StreamedAgentResponse $response) {
// $response->text, $response->events, $response->usage...
});
});或者,您可以手動遍歷串流事件:
$stream = (new SalesCoach)->stream('Analyze this sales transcript...');
foreach ($stream as $event) {
// ...
}使用 Vercel AI SDK 協定進行串流
您可以透過在可串流回應上呼叫 usingVercelDataProtocol 方法,來使用 Vercel AI SDK 串流協定 串流事件:
use App\Ai\Agents\SalesCoach;
Route::get('/coach', function () {
return (new SalesCoach)
->stream('Analyze this sales transcript...')
->usingVercelDataProtocol();
});廣播
您可以透過幾種不同的方式來廣播串流事件。首先,您可以簡單地對串流事件呼叫 broadcast 或 broadcastNow 方法:
use App\Ai\Agents\SalesCoach;
use Illuminate\Broadcasting\Channel;
$stream = (new SalesCoach)->stream('Analyze this sales transcript...');
foreach ($stream as $event) {
$event->broadcast(new Channel('channel-name'));
}或者,您可以呼叫 Agent 的 broadcastOnQueue 方法來將 Agent 操作排入佇列,並在串流事件可用時進行廣播:
(new SalesCoach)->broadcastOnQueue(
'Analyze this sales transcript...'
new Channel('channel-name'),
);佇列
使用 Agent 的 queue 方法,您可以對 Agent 進行提示,但允許它在背景處理回應,從而保持您的應用程式反應迅速。then 和 catch 方法可用於註冊閉包,這些閉包將在回應可用或發生例外狀況時被呼叫:
use Illuminate\Http\Request;
use Laravel\Ai\Responses\AgentResponse;
use Throwable;
Route::post('/coach', function (Request $request) {
return (new SalesCoach)
->queue($request->input('transcript'))
->then(function (AgentResponse $response) {
// ...
})
->catch(function (Throwable $e) {
// ...
});
return back();
});工具
工具可用於賦予 Agent 額外的功能,讓它們在回應提示時可以使用。可以使用 make:tool Artisan 指令建立工具:
php artisan make:tool RandomNumberGenerator生成的工具將被放置在應用程式的 app/Ai/Tools 目錄中。每個工具都包含一個 handle 方法,當 Agent 需要使用該工具時會呼叫此方法:
<?php
namespace App\Ai\Tools;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;
use Stringable;
class RandomNumberGenerator implements Tool
{
/**
* Get the description of the tool's purpose.
*/
public function description(): Stringable|string
{
return 'This tool may be used to generate cryptographically secure random numbers.';
}
/**
* Execute the tool.
*/
public function handle(Request $request): Stringable|string
{
return (string) random_int($request['min'], $request['max']);
}
/**
* Get the tool's schema definition.
*/
public function schema(JsonSchema $schema): array
{
return [
'min' => $schema->integer()->min(0)->required(),
'max' => $schema->integer()->required(),
];
}
}定義好工具後,您可以從任何 Agent 的 tools 方法中回傳它:
use App\Ai\Tools\RandomNumberGenerator;
/**
* Get the tools available to the agent.
*
* @return Tool[]
*/
public function tools(): iterable
{
return [
new RandomNumberGenerator,
];
}相似度搜尋
SimilaritySearch 工具允許 Agent 使用儲存在資料庫中的向量嵌入 (Vector Embeddings) 搜尋與給定查詢相似的文檔。當您想讓 Agent 存取並搜尋應用程式的資料以進行檢索增強生成 (RAG) 時,這非常有用。
建立相似度搜尋工具最簡單的方法是搭配具有向量嵌入的 Eloquent 模型使用 usingModel 方法:
use App\Models\Document;
use Laravel\Ai\Tools\SimilaritySearch;
public function tools(): iterable
{
return [
SimilaritySearch::usingModel(Document::class, 'embedding'),
];
}第一個參數是 Eloquent 模型類別,第二個參數是包含向量嵌入的欄位。
您也可以提供介於 0.0 與 1.0 之間的最低相似度門檻,以及一個用於自定義查詢的閉包:
SimilaritySearch::usingModel(
model: Document::class,
column: 'embedding',
minSimilarity: 0.7,
limit: 10,
query: fn ($query) => $query->where('published', true),
),若要進行更多控制,您可以建立一個帶有自定義閉包的相似度搜尋工具,該閉包會回傳搜尋結果:
use App\Models\Document;
use Laravel\Ai\Tools\SimilaritySearch;
public function tools(): iterable
{
return [
new SimilaritySearch(using: function (string $query) {
return Document::query()
->where('user_id', $this->user->id)
->whereVectorSimilarTo('embedding', $query)
->limit(10)
->get();
}),
];
}您可以使用 withDescription 方法來自定義工具的描述:
SimilaritySearch::usingModel(Document::class, 'embedding')
->withDescription('Search the knowledge base for relevant articles.'),服務商工具
服務商工具是由 AI 服務商原生提供的特殊工具,具有網頁搜尋、URL 擷取和檔案搜尋等功能。與一般工具不同,服務商工具是由服務商本身執行,而非由您的應用程式執行。
服務商工具可以透過您的 Agent 的 tools 方法回傳。
網頁搜尋
WebSearch 服務商工具允許 Agents 搜尋網路以獲取即時資訊。這對於回答有關時事、近期數據或在模型訓練截止後可能已變更的主題非常有用。
支援的服務商: Anthropic, OpenAI, Gemini
use Laravel\Ai\Providers\Tools\WebSearch;
public function tools(): iterable
{
return [
new WebSearch,
];
}您可以設定網頁搜尋工具,以限制搜尋次數或將結果限制在特定網域:
(new WebSearch)->max(5)->allow(['laravel.com', 'php.net']),若要根據使用者位置精確化搜尋結果,請使用 location 方法:
(new WebSearch)->location(
city: 'New York',
region: 'NY',
country: 'US'
);網頁擷取
WebFetch 服務商工具允許 Agents 擷取並讀取網頁內容。當您需要 Agent 分析特定的 URL 或從已知網頁獲取詳細資訊時,這非常有用。
支援的服務商: Anthropic, Gemini
use Laravel\Ai\Providers\Tools\WebFetch;
public function tools(): iterable
{
return [
new WebFetch,
];
}您可以設定網頁擷取工具,以限制擷取次數或限制在特定網域:
(new WebFetch)->max(3)->allow(['docs.laravel.com']),檔案搜尋
FileSearch 服務商工具允許 Agents 搜尋儲存在向量儲存 (vector stores)中的檔案。這透過允許 Agent 在您上傳的檔案中搜尋相關資訊,來實現檢索增強生成 (RAG)。
支援的服務商: OpenAI, Gemini
use Laravel\Ai\Providers\Tools\FileSearch;
public function tools(): iterable
{
return [
new FileSearch(stores: ['store_id']),
];
}您可以提供多個向量儲存 ID 以在多個儲存空間中搜尋:
new FileSearch(stores: ['store_1', 'store_2']);如果您的檔案具有 metadata,您可以透過提供 where 參數來篩選搜尋結果。對於簡單的等值篩選,請傳遞一個陣列:
new FileSearch(stores: ['store_id'], where: [
'author' => 'Taylor Otwell',
'year' => 2026,
]);對於更複雜的篩選條件,您可以傳遞一個接收 FileSearchQuery 實例的閉包:
use Laravel\Ai\Providers\Tools\FileSearchQuery;
new FileSearch(stores: ['store_id'], where: fn (FileSearchQuery $query) =>
$query->where('author', 'Taylor Otwell')
->whereNot('status', 'draft')
->whereIn('category', ['news', 'updates'])
);中介層
Agents 支援中介層,允許您在提示 (Prompt) 發送到服務商之前攔截並修改它們。若要為 Agent 新增中介層,請實作 HasMiddleware 介面並定義一個回傳中介層類別陣列的 middleware 方法:
<?php
namespace App\Ai\Agents;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasMiddleware;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent, HasMiddleware
{
use Promptable;
// ...
/**
* Get the agent's middleware.
*/
public function middleware(): array
{
return [
new LogPrompts,
];
}
}每個中介層類別都應定義一個 handle 方法,該方法接收 AgentPrompt 和一個用於將提示傳遞給下一個中介層的 Closure:
<?php
namespace App\Ai\Middleware;
use Closure;
use Laravel\Ai\Prompts\AgentPrompt;
class LogPrompts
{
/**
* Handle the incoming prompt.
*/
public function handle(AgentPrompt $prompt, Closure $next)
{
Log::info('Prompting agent', ['prompt' => $prompt->prompt]);
return $next($prompt);
}
}您可以在回應上使用 then 方法,在 Agent 完成處理後執行程式碼。這適用於同步和串流回應:
public function handle(AgentPrompt $prompt, Closure $next)
{
return $next($prompt)->then(function (AgentResponse $response) {
Log::info('Agent responded', ['text' => $response->text]);
});
}匿名 Agents
有時您可能想快速與模型互動,而不想建立專用的 Agent 類別。您可以使用 agent 函式建立一個臨時的匿名 Agent:
use function Laravel\Ai\{agent};
$response = agent(
instructions: 'You are an expert at software development.',
messages: [],
tools: [],
)->prompt('Tell me about Laravel')匿名 Agents 也可以產生結構化輸出:
use Illuminate\Contracts\JsonSchema\JsonSchema;
use function Laravel\Ai\{agent};
$response = agent(
schema: fn (JsonSchema $schema) => [
'number' => $schema->integer()->required(),
],
)->prompt('Generate a random number less than 100')Agent 設定
您可以使用 PHP 屬性 (Attributes) 為 Agent 設定文字生成選項。以下是可用的屬性:
MaxSteps: Agent 使用工具時可以執行的最大步驟數。MaxTokens: 模型可以生成的最大 Token 數量。Model: Agent 應使用的模型。Provider: Agent 使用的 AI 服務商 (或用於故障轉移的服務商)。Temperature: 用於生成的取樣溫度 (0.0 到 1.0)。Timeout: Agent 請求的 HTTP 超時秒數 (預設:60)。UseCheapestModel: 使用服務商最便宜的文字模型以進行成本優化。UseSmartestModel: 使用服務商能力最強的文字模型以處理複雜任務。
<?php
namespace App\Ai\Agents;
use Laravel\Ai\Attributes\MaxSteps;
use Laravel\Ai\Attributes\MaxTokens;
use Laravel\Ai\Attributes\Model;
use Laravel\Ai\Attributes\Provider;
use Laravel\Ai\Attributes\Temperature;
use Laravel\Ai\Attributes\Timeout;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Enums\Lab;
use Laravel\Ai\Promptable;
#[Provider(Lab::Anthropic)]
#[Model('claude-haiku-4-5-20251001')]
#[MaxSteps(10)]
#[MaxTokens(4096)]
#[Temperature(0.7)]
#[Timeout(120)]
class SalesCoach implements Agent
{
use Promptable;
// ...
}UseCheapestModel 和 UseSmartestModel 屬性允許您自動為特定服務商選擇最具成本效益或能力最強的模型,而無需指定模型名稱。當您想要在不同的服務商之間優化成本或能力時,這非常有用:
use Laravel\Ai\Attributes\UseCheapestModel;
use Laravel\Ai\Attributes\UseSmartestModel;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;
#[UseCheapestModel]
class SimpleSummarizer implements Agent
{
use Promptable;
// Will use the cheapest model (e.g., Haiku)...
}
#[UseSmartestModel]
class ComplexReasoner implements Agent
{
use Promptable;
// Will use the most capable model (e.g., Opus)...
}圖片
Laravel\Ai\Image 類別可用於透過 openai、gemini 或 xai 服務商來產生圖片:
use Laravel\Ai\Image;
$image = Image::of('A donut sitting on the kitchen counter')->generate();
$rawContent = (string) $image;square、portrait 與 landscape 方法可用於控制圖片的長寬比,而 quality 方法則可用於引導模型決定最終圖片的品質 (high、medium、low)。timeout 方法可用於指定 HTTP 超時時間(以秒為單位):
use Laravel\Ai\Image;
$image = Image::of('A donut sitting on the kitchen counter')
->quality('high')
->landscape()
->timeout(120)
->generate();您可以使用 attachments 方法附加參考圖片:
use Laravel\Ai\Files;
use Laravel\Ai\Image;
$image = Image::of('Update this photo of me to be in the style of an impressionist painting.')
->attachments([
Files\Image::fromStorage('photo.jpg'),
// Files\Image::fromPath('/home/laravel/photo.jpg'),
// Files\Image::fromUrl('https://example.com/photo.jpg'),
// $request->file('photo'),
])
->landscape()
->generate();產生的圖片可以輕鬆儲存在應用程式 config/filesystems.php 設定檔中設定的預設磁碟:
$image = Image::of('A donut sitting on the kitchen counter');
$path = $image->store();
$path = $image->storeAs('image.jpg');
$path = $image->storePublicly();
$path = $image->storePubliclyAs('image.jpg');圖片產生也可以加入佇列:
use Laravel\Ai\Image;
use Laravel\Ai\Responses\ImageResponse;
Image::of('A donut sitting on the kitchen counter')
->portrait()
->queue()
->then(function (ImageResponse $image) {
$path = $image->store();
// ...
});音訊 (TTS)
Laravel\Ai\Audio 類別可用於從指定的文字產生音訊:
use Laravel\Ai\Audio;
$audio = Audio::of('I love coding with Laravel.')->generate();
$rawContent = (string) $audio;male、female 與 voice 方法可用於決定所產生音訊的聲音:
$audio = Audio::of('I love coding with Laravel.')
->female()
->generate();
$audio = Audio::of('I love coding with Laravel.')
->voice('voice-id-or-name')
->generate();同樣地,instructions 方法可用於動態地指導模型所產生的音訊聽起來應該如何:
$audio = Audio::of('I love coding with Laravel.')
->female()
->instructions('Said like a pirate')
->generate();產生的音訊可以輕鬆儲存在應用程式 config/filesystems.php 設定檔中設定的預設磁碟:
$audio = Audio::of('I love coding with Laravel.')->generate();
$path = $audio->store();
$path = $audio->storeAs('audio.mp3');
$path = $audio->storePublicly();
$path = $audio->storePubliclyAs('audio.mp3');音訊產生也可以加入佇列:
use Laravel\Ai\Audio;
use Laravel\Ai\Responses\AudioResponse;
Audio::of('I love coding with Laravel.')
->queue()
->then(function (AudioResponse $audio) {
$path = $audio->store();
// ...
});轉錄 (STT)
Laravel\Ai\Transcription 類別可用於為指定的音訊產生轉錄文字:
use Laravel\Ai\Transcription;
$transcript = Transcription::fromPath('/home/laravel/audio.mp3')->generate();
$transcript = Transcription::fromStorage('audio.mp3')->generate();
$transcript = Transcription::fromUpload($request->file('audio'))->generate();
return (string) $transcript;diarize 方法可用於指示您希望回應除了包含原始文字轉錄外,還包含語音標記 (Diarized) 轉錄,讓您可以根據說話者來存取分段後的轉錄內容:
$transcript = Transcription::fromStorage('audio.mp3')
->diarize()
->generate();轉錄產生也可以加入佇列:
use Laravel\Ai\Transcription;
use Laravel\Ai\Responses\TranscriptionResponse;
Transcription::fromStorage('audio.mp3')
->queue()
->then(function (TranscriptionResponse $transcript) {
// ...
});嵌入 (Embeddings)
您可以使用 Laravel 的 Stringable 類別中新增的 toEmbeddings 方法,輕鬆地為任何給定的字串生成向量嵌入 (Vector Embeddings):
use Illuminate\Support\Str;
$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings();或者,您也可以使用 Embeddings 類別一次為多個輸入生成嵌入:
use Laravel\Ai\Embeddings;
$response = Embeddings::for([
'Napa Valley has great wine.',
'Laravel is a PHP framework.',
])->generate();
$response->embeddings; // [[0.123, 0.456, ...], [0.789, 0.012, ...]]您可以為嵌入指定維度 (Dimensions) 與服務商:
$response = Embeddings::for(['Napa Valley has great wine.'])
->dimensions(1536)
->generate(Lab::OpenAI, 'text-embedding-3-small');查詢嵌入
生成嵌入後,您通常會將它們儲存在資料庫的 vector 欄位中,以便稍後查詢。Laravel 透過 pgvector 擴充功能為 PostgreSQL 的向量欄位提供原生支援。要開始使用,請在您的遷移 (Migration) 中定義一個 vector 欄位,並指定維度數量:
Schema::ensureVectorExtensionExists();
Schema::create('documents', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->vector('embedding', dimensions: 1536);
$table->timestamps();
});您還可以新增向量索引以加速相似度搜尋。當在向量欄位上呼叫 index 時,Laravel 會自動建立一個使用餘弦距離 (Cosine Distance) 的 HNSW 索引:
$table->vector('embedding', dimensions: 1536)->index();在您的 Eloquent 模型上,您應該將向量欄位轉換為 array:
protected function casts(): array
{
return [
'embedding' => 'array',
];
}要查詢相似的記錄,請使用 whereVectorSimilarTo 方法。此方法會根據最小餘弦相似度(介於 0.0 與 1.0 之間,1.0 為完全相同)過濾結果,並按相似度排序結果:
use App\Models\Document;
$documents = Document::query()
->whereVectorSimilarTo('embedding', $queryEmbedding, minSimilarity: 0.4)
->limit(10)
->get();$queryEmbedding 可以是浮點數陣列或純字串。當提供字串時,Laravel 將自動為其生成嵌入:
$documents = Document::query()
->whereVectorSimilarTo('embedding', 'best wineries in Napa Valley')
->limit(10)
->get();如果您需要更多控制,可以獨立使用底層的 whereVectorDistanceLessThan、selectVectorDistance 以及 orderByVectorDistance 方法:
$documents = Document::query()
->select('*')
->selectVectorDistance('embedding', $queryEmbedding, as: 'distance')
->whereVectorDistanceLessThan('embedding', $queryEmbedding, maxDistance: 0.3)
->orderByVectorDistance('embedding', $queryEmbedding)
->limit(10)
->get();如果您想讓 Agent 能夠執行相似度搜尋作為一項工具,請查看 相似度搜尋 (Similarity Search) 工具文件。
📌 備註
向量查詢目前僅支援使用 pgvector 擴充功能的 PostgreSQL 連線。
快取嵌入
嵌入生成可以進行快取,以避免對相同輸入進行多餘的 API 呼叫。要啟用快取,請將 ai.caching.embeddings.cache 設定選項設為 true:
'caching' => [
'embeddings' => [
'cache' => true,
'store' => env('CACHE_STORE', 'database'),
// ...
],
],啟用快取時,嵌入將會被快取 30 天。快取鍵 (Cache Key) 是根據服務商、模型、維度和輸入內容生成的,確保相同的請求會回傳快取的結果,而不同的設定則會生成新的嵌入。
即使全域快取已停用,您也可以使用 cache 方法為特定請求啟用快取:
$response = Embeddings::for(['Napa Valley has great wine.'])
->cache()
->generate();您可以指定自定義的快取持續時間(以秒為單位):
$response = Embeddings::for(['Napa Valley has great wine.'])
->cache(seconds: 3600) // Cache for 1 hour
->generate();toEmbeddings Stringable 方法也接受一個 cache 引數:
// Cache with default duration...
$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: true);
// Cache for a specific duration...
$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings(cache: 3600);重排 (Reranking)
重排 (Reranking) 允許您根據文件與給定查詢的相關性重新排序文件列表。這對於透過語義理解來改善搜尋結果非常有用:
Laravel\Ai\Reranking 類別可用於重排文件:
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');
// Access the top result...
$response->first()->document; // "Laravel is a PHP web application framework."
$response->first()->score; // 0.95
$response->first()->index; // 1 (original position)limit 方法可用於限制回傳的結果數量:
$response = Reranking::of($documents)
->limit(5)
->rerank('search query');重排集合 (Collections)
為了方便起見,可以使用 rerank 巨集對 Laravel 集合 (Collections) 進行重排。第一個引數指定用於重排的欄位,第二個引數則是查詢:
// Rerank by a single field...
$posts = Post::all()
->rerank('body', 'Laravel tutorials');
// Rerank by multiple fields (sent as JSON)...
$reranked = $posts->rerank(['title', 'body'], 'Laravel tutorials');
// Rerank using a closure to build the document...
$reranked = $posts->rerank(
fn ($post) => $post->title.': '.$post->body,
'Laravel tutorials'
);您也可以限制結果數量並指定服務商:
$reranked = $posts->rerank(
by: 'content',
query: 'Laravel tutorials',
limit: 10,
provider: Lab::Cohere
);檔案
Laravel\Ai\Files 類別或個別的檔案類別可用於將檔案儲存在您的 AI 服務商中,以便稍後在對話中使用。這對於大型文件或您想要多次引用而不想重複上傳的檔案非常有用:
use Laravel\Ai\Files\Document;
use Laravel\Ai\Files\Image;
// Store a file from a local path...
$response = Document::fromPath('/home/laravel/document.pdf')->put();
$response = Image::fromPath('/home/laravel/photo.jpg')->put();
// Store a file that is stored on a filesystem disk...
$response = Document::fromStorage('document.pdf', disk: 'local')->put();
$response = Image::fromStorage('photo.jpg', disk: 'local')->put();
// Store a file that is stored on a remote URL...
$response = Document::fromUrl('https://example.com/document.pdf')->put();
$response = Image::fromUrl('https://example.com/photo.jpg')->put();
return $response->id;您也可以儲存原始內容或上傳的檔案:
use Laravel\Ai\Files;
use Laravel\Ai\Files\Document;
// Store raw content...
$stored = Document::fromString('Hello, World!', 'text/plain')->put();
// Store an uploaded file...
$stored = Document::fromUpload($request->file('document'))->put();檔案儲存後,您可以在透過 Agents 生成文字時引用該檔案,而不需要重新上傳:
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Files;
$response = (new SalesCoach)->prompt(
'Analyze the attached sales transcript...'
attachments: [
Files\Document::fromId('file-id') // Attach a stored document...
]
);若要擷取先前儲存的檔案,請在檔案實例上使用 get 方法:
use Laravel\Ai\Files\Document;
$file = Document::fromId('file-id')->get();
$file->id;
$file->mimeType();若要從服務商刪除檔案,請使用 delete 方法:
Document::fromId('file-id')->delete();預設情況下,Files 類別會使用您應用程式的 config/ai.php 設定檔中所設定的預設 AI 服務商。對於大多數操作,您可以使用 provider 引數指定不同的服務商:
$response = Document::fromPath(
'/home/laravel/document.pdf'
)->put(provider: Lab::Anthropic);在對話中使用儲存的檔案
檔案儲存在服務商後,您可以在 Agent 對話中使用 Document 或 Image 類別的 fromId 方法來引用它:
use App\Ai\Agents\DocumentAnalyzer;
use Laravel\Ai\Files;
use Laravel\Ai\Files\Document;
$stored = Document::fromPath('/path/to/report.pdf')->put();
$response = (new DocumentAnalyzer)->prompt(
'Summarize this document.',
attachments: [
Document::fromId($stored->id),
],
);同樣地,儲存的圖片可以使用 Image 類別來引用:
use Laravel\Ai\Files;
use Laravel\Ai\Files\Image;
$stored = Image::fromPath('/path/to/photo.jpg')->put();
$response = (new ImageAnalyzer)->prompt(
'What is in this image?',
attachments: [
Image::fromId($stored->id),
],
);向量儲存 (Vector Stores)
向量儲存允許您建立可搜尋的檔案集合,這些集合可用於檢索增強生成 (RAG)。Laravel\Ai\Stores 類別提供了建立、擷取和刪除向量儲存的方法:
use Laravel\Ai\Stores;
// Create a new vector store...
$store = Stores::create('Knowledge Base');
// Create a store with additional options...
$store = Stores::create(
name: 'Knowledge Base',
description: 'Documentation and reference materials.',
expiresWhenIdleFor: days(30),
);
return $store->id;若要透過 ID 擷取現有的向量儲存,請使用 get 方法:
use Laravel\Ai\Stores;
$store = Stores::get('store_id');
$store->id;
$store->name;
$store->fileCounts;
$store->ready;若要刪除向量儲存,請在 Stores 類別或儲存實例上使用 delete 方法:
use Laravel\Ai\Stores;
// Delete by ID...
Stores::delete('store_id');
// Or delete via a store instance...
$store = Stores::get('store_id');
$store->delete();將檔案新增至儲存空間
擁有向量儲存後,您可以使用 add 方法將 檔案 新增至其中。新增到儲存空間的檔案會自動建立索引,以便使用 服務商檔案搜尋工具 進行語義搜尋:
use Laravel\Ai\Files\Document;
use Laravel\Ai\Stores;
$store = Stores::get('store_id');
// Add a file that has already been stored with the provider...
$document = $store->add('file_id');
$document = $store->add(Document::fromId('file_id'));
// Or, store and add a file in one step...
$document = $store->add(Document::fromPath('/path/to/document.pdf'));
$document = $store->add(Document::fromStorage('manual.pdf'));
$document = $store->add($request->file('document'));
$document->id;
$document->fileId;注意: 通常,在將先前儲存的檔案新增到向量儲存時,回傳的文件 ID 會與檔案先前分配的 ID 一致;然而,某些向量儲存服務商可能會回傳一個新的、不同的「文件 ID」。因此,建議您始終在資料庫中儲存這兩個 ID 以供將來引用。
將檔案新增到儲存空間時,您可以為其附加元資料。稍後使用 服務商檔案搜尋工具 時,這些元資料可用於過濾搜尋結果:
$store->add(Document::fromPath('/path/to/document.pdf'), metadata: [
'author' => 'Taylor Otwell',
'department' => 'Engineering',
'year' => 2026,
]);若要從儲存空間中移除檔案,請使用 remove 方法:
$store->remove('file_id');從向量儲存中移除檔案並不會從服務商的 檔案儲存 中移除它。若要從向量儲存中移除檔案並從檔案儲存中永久刪除它,請使用 deleteFile 引數:
$store->remove('file_abc123', deleteFile: true);故障轉移 (Failover)
當進行提示或生成其他媒體時,您可以提供一個服務商 / 模型的陣列,以便在主要服務商遇到服務中斷或速率限制時,自動故障轉移到備用服務商 / 模型:
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Image;
$response = (new SalesCoach)->prompt(
'Analyze this sales transcript...',
provider: [Lab::OpenAI, Lab::Anthropic],
);
$image = Image::of('A donut sitting on the kitchen counter')
->generate(provider: [Lab::Gemini, Lab::xAI]);測試
Agents
若要在測試期間模擬 Agent 的回應,請在 Agent 類別上呼叫 fake 方法。您可以選擇性地提供一個回應陣列或一個閉包 (Closure):
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Prompts\AgentPrompt;
// Automatically generate a fixed response for every prompt...
SalesCoach::fake();
// Provide a list of prompt responses...
SalesCoach::fake([
'First response',
'Second response',
]);
// Dynamically handle prompt responses based on the incoming prompt...
SalesCoach::fake(function (AgentPrompt $prompt) {
return 'Response for: '.$prompt->prompt;
});注意: 當在回傳結構化輸出的 Agent 上呼叫
Agent::fake()時,Laravel 將會自動產生符合您 Agent 定義的輸出結構 (Schema) 的假資料。
在對 Agent 進行提示後,您可以對收到的提示進行斷言:
use Laravel\Ai\Prompts\AgentPrompt;
SalesCoach::assertPrompted('Analyze this...');
SalesCoach::assertPrompted(function (AgentPrompt $prompt) {
return $prompt->contains('Analyze');
});
SalesCoach::assertNotPrompted('Missing prompt');
SalesCoach::assertNeverPrompted();對於已排入佇列的 Agent 調用,請使用佇列斷言方法:
use Laravel\Ai\QueuedAgentPrompt;
SalesCoach::assertQueued('Analyze this...');
SalesCoach::assertQueued(function (QueuedAgentPrompt $prompt) {
return $prompt->contains('Analyze');
});
SalesCoach::assertNotQueued('Missing prompt');
SalesCoach::assertNeverQueued();為了確保所有 Agent 調用都有對應的模擬回應,您可以使用 preventStrayPrompts。如果調用 Agent 時沒有定義模擬回應,系統將會拋出一個例外狀況:
SalesCoach::fake()->preventStrayPrompts();圖片
可以透過在 Image 類別上呼叫 fake 方法來模擬圖片生成。一旦圖片被模擬後,就可以針對記錄的圖片生成提示進行各種斷言:
use Laravel\Ai\Image;
use Laravel\Ai\Prompts\ImagePrompt;
use Laravel\Ai\Prompts\QueuedImagePrompt;
// Automatically generate a fixed response for every prompt...
Image::fake();
// Provide a list of prompt responses...
Image::fake([
base64_encode($firstImage),
base64_encode($secondImage),
]);
// Dynamically handle prompt responses based on the incoming prompt...
Image::fake(function (ImagePrompt $prompt) {
return base64_encode('...');
});在產生圖片後,您可以對收到的提示進行斷言:
Image::assertGenerated(function (ImagePrompt $prompt) {
return $prompt->contains('sunset') && $prompt->isLandscape();
});
Image::assertNotGenerated('Missing prompt');
Image::assertNothingGenerated();對於已排入佇列的圖片生成,請使用佇列斷言方法:
Image::assertQueued(
fn (QueuedImagePrompt $prompt) => $prompt->contains('sunset')
);
Image::assertNotQueued('Missing prompt');
Image::assertNothingQueued();為了確保所有產生的圖片都有對應的模擬回應,您可以使用 preventStrayImages。如果生成圖片時沒有定義模擬回應,系統將會拋出一個例外狀況:
Image::fake()->preventStrayImages();音訊
可以透過在 Audio 類別上呼叫 fake 方法來模擬音訊生成。一旦音訊被模擬後,就可以針對記錄的音訊生成提示進行各種斷言:
use Laravel\Ai\Audio;
use Laravel\Ai\Prompts\AudioPrompt;
use Laravel\Ai\Prompts\QueuedAudioPrompt;
// Automatically generate a fixed response for every prompt...
Audio::fake();
// Provide a list of prompt responses...
Audio::fake([
base64_encode($firstAudio),
base64_encode($secondAudio),
]);
// Dynamically handle prompt responses based on the incoming prompt...
Audio::fake(function (AudioPrompt $prompt) {
return base64_encode('...');
});在產生音訊後,您可以對收到的提示進行斷言:
Audio::assertGenerated(function (AudioPrompt $prompt) {
return $prompt->contains('Hello') && $prompt->isFemale();
});
Audio::assertNotGenerated('Missing prompt');
Audio::assertNothingGenerated();對於已排入佇列的音訊生成,請使用佇列斷言方法:
Audio::assertQueued(
fn (QueuedAudioPrompt $prompt) => $prompt->contains('Hello')
);
Audio::assertNotQueued('Missing prompt');
Audio::assertNothingQueued();為了確保所有產生的音訊都有對應的模擬回應,您可以使用 preventStrayAudio。如果生成音訊時沒有定義模擬回應,系統將會拋出一個例外狀況:
Audio::fake()->preventStrayAudio();轉錄
可以透過在 Transcription 類別上呼叫 fake 方法來模擬轉錄產生。一旦轉錄被模擬後,就可以針對記錄的轉錄產生提示進行各種斷言:
use Laravel\Ai\Transcription;
use Laravel\Ai\Prompts\TranscriptionPrompt;
use Laravel\Ai\Prompts\QueuedTranscriptionPrompt;
// Automatically generate a fixed response for every prompt...
Transcription::fake();
// Provide a list of prompt responses...
Transcription::fake([
'First transcription text.',
'Second transcription text.',
]);
// Dynamically handle prompt responses based on the incoming prompt...
Transcription::fake(function (TranscriptionPrompt $prompt) {
return 'Transcribed text...';
});在產生轉錄後,您可以對收到的提示進行斷言:
Transcription::assertGenerated(function (TranscriptionPrompt $prompt) {
return $prompt->language === 'en' && $prompt->isDiarized();
});
Transcription::assertNotGenerated(
fn (TranscriptionPrompt $prompt) => $prompt->language === 'fr'
);
Transcription::assertNothingGenerated();對於已排入佇列的轉錄生成,請使用佇列斷言方法:
Transcription::assertQueued(
fn (QueuedTranscriptionPrompt $prompt) => $prompt->isDiarized()
);
Transcription::assertNotQueued(
fn (QueuedTranscriptionPrompt $prompt) => $prompt->language === 'fr'
);
Transcription::assertNothingQueued();為了確保所有產生的轉錄都有對應的模擬回應,您可以使用 preventStrayTranscriptions。如果產生轉錄時沒有定義模擬回應,系統將會拋出一個例外狀況:
Transcription::fake()->preventStrayTranscriptions();嵌入
嵌入生成可以透過在 Embeddings 類別上呼叫 fake 方法來模擬。一旦模擬了嵌入,就可以對記錄的嵌入生成提示進行各種斷言:
use Laravel\Ai\Embeddings;
use Laravel\Ai\Prompts\EmbeddingsPrompt;
use Laravel\Ai\Prompts\QueuedEmbeddingsPrompt;
// Automatically generate fake embeddings of the proper dimensions for every prompt...
Embeddings::fake();
// Provide a list of prompt responses...
Embeddings::fake([
[$firstEmbeddingVector],
[$secondEmbeddingVector],
]);
// Dynamically handle prompt responses based on the incoming prompt...
Embeddings::fake(function (EmbeddingsPrompt $prompt) {
return array_map(
fn () => Embeddings::fakeEmbedding($prompt->dimensions),
$prompt->inputs
);
});在生成嵌入之後,您可以對收到的提示進行斷言:
Embeddings::assertGenerated(function (EmbeddingsPrompt $prompt) {
return $prompt->contains('Laravel') && $prompt->dimensions === 1536;
});
Embeddings::assertNotGenerated(
fn (EmbeddingsPrompt $prompt) => $prompt->contains('Other')
);
Embeddings::assertNothingGenerated();對於進入佇列的嵌入生成,請使用佇列斷言方法:
Embeddings::assertQueued(
fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Laravel')
);
Embeddings::assertNotQueued(
fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Other')
);
Embeddings::assertNothingQueued();為了確保所有嵌入生成都有對應的模擬回應,您可以使用 preventStrayEmbeddings。如果生成嵌入時沒有定義模擬回應,則會拋出異常:
Embeddings::fake()->preventStrayEmbeddings();重排
重排操作可以透過在 Reranking 類別上呼叫 fake 方法來模擬:
use Laravel\Ai\Reranking;
use Laravel\Ai\Prompts\RerankingPrompt;
use Laravel\Ai\Responses\Data\RankedDocument;
// Automatically generate a fake reranked responses...
Reranking::fake();
// Provide custom responses...
Reranking::fake([
[
new RankedDocument(index: 0, document: 'First', score: 0.95),
new RankedDocument(index: 1, document: 'Second', score: 0.80),
],
]);在重排之後,您可以對執行的操作進行斷言:
Reranking::assertReranked(function (RerankingPrompt $prompt) {
return $prompt->contains('Laravel') && $prompt->limit === 5;
});
Reranking::assertNotReranked(
fn (RerankingPrompt $prompt) => $prompt->contains('Django')
);
Reranking::assertNothingReranked();檔案
檔案操作可以透過在 Files 類別上呼叫 fake 方法來模擬:
use Laravel\Ai\Files;
Files::fake();一旦模擬了檔案操作,您就可以對發生的上傳與刪除進行斷言:
use Laravel\Ai\Contracts\Files\StorableFile;
use Laravel\Ai\Files\Document;
// Store files...
Document::fromString('Hello, Laravel!', mime: 'text/plain')
->as('hello.txt')
->put();
// Make assertions...
Files::assertStored(fn (StorableFile $file) =>
(string) $file === 'Hello, Laravel!' &&
$file->mimeType() === 'text/plain';
);
Files::assertNotStored(fn (StorableFile $file) =>
(string) $file === 'Hello, World!'
);
Files::assertNothingStored();若要針對檔案刪除進行斷言,您可以傳遞一個檔案 ID:
Files::assertDeleted('file-id');
Files::assertNotDeleted('file-id');
Files::assertNothingDeleted();向量儲存
向量儲存操作可以透過在 Stores 類別上呼叫 fake 方法來模擬。模擬儲存也會自動模擬 檔案操作:
use Laravel\Ai\Stores;
Stores::fake();一旦模擬了儲存操作,您就可以對建立或刪除的儲存空間進行斷言:
use Laravel\Ai\Stores;
// Create store...
$store = Stores::create('Knowledge Base');
// Make assertions...
Stores::assertCreated('Knowledge Base');
Stores::assertCreated(fn (string $name, ?string $description) =>
$name === 'Knowledge Base'
);
Stores::assertNotCreated('Other Store');
Stores::assertNothingCreated();若要針對儲存空間刪除進行斷言,您可以提供儲存空間 ID:
Stores::assertDeleted('store_id');
Stores::assertNotDeleted('other_store_id');
Stores::assertNothingDeleted();若要斷言檔案是否已新增至儲存空間或從中移除,請在給定的 Store 執行個體上使用斷言方法:
Stores::fake();
$store = Stores::get('store_id');
// Add / remove files...
$store->add('added_id');
$store->remove('removed_id');
// Make assertions...
$store->assertAdded('added_id');
$store->assertRemoved('removed_id');
$store->assertNotAdded('other_file_id');
$store->assertNotRemoved('other_file_id');如果檔案儲存在服務商的 檔案儲存 中,並在同一個請求中新增到向量儲存,您可能不知道檔案的服務商 ID。在這種情況下,您可以將一個閉包 (Closure) 傳遞給 assertAdded 方法,以針對新增檔案的內容進行斷言:
use Laravel\Ai\Contracts\Files\StorableFile;
use Laravel\Ai\Files\Document;
$store->add(Document::fromString('Hello, World!', 'text/plain')->as('hello.txt'));
$store->assertAdded(fn (StorableFile $file) => $file->name() === 'hello.txt');
$store->assertAdded(fn (StorableFile $file) => $file->content() === 'Hello, World!');事件 (Events)
Laravel AI SDK 會發送多種 事件 (events),包含:
AddingFileToStoreAgentPromptedAgentStreamedAudioGeneratedCreatingStoreEmbeddingsGeneratedFileAddedToStoreFileDeletedFileRemovedFromStoreFileStoredGeneratingAudioGeneratingEmbeddingsGeneratingImageGeneratingTranscriptionImageGeneratedInvokingToolPromptingAgentRemovingFileFromStoreRerankedRerankingStoreCreatedStoringFileStreamingAgentToolInvokedTranscriptionGenerated
您可以監聽這些事件中的任何一個,以記錄或儲存 AI SDK 的使用資訊。