Skip to content

Laravel AI SDK

簡介

Laravel AI SDK 為與 OpenAI、Anthropic、Gemini 等 AI 提供者互動提供了一個統一且富有表現力的 API。透過 AI SDK,您可以使用一致且對 Laravel 友善的介面來構建具有工具和結構化輸出的智能 Agents、生成圖片、合成與轉錄音訊、建立向量嵌入 (Embeddings) 等等。

安裝

您可以使用 Composer 安裝 Laravel AI SDK:

shell
composer require laravel/ai

接著,您應該使用 vendor:publish Artisan 指令發布 AI SDK 的設定與遷移 (Migration) 檔案:

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

最後,您應該執行應用程式的資料庫遷移。這將會建立 agent_conversationsagent_conversation_messages 資料表,AI SDK 使用這些資料表來驅動其對話存儲:

shell
php artisan migrate

設定

您可以在應用程式的 config/ai.php 設定檔中定義 AI 提供者的憑證,或是在應用程式的 .env 檔案中定義為環境變數:

ini
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 端點。然而,您可能需要透過不同的端點來路由請求——例如,當使用代理服務來集中管理 API 金鑰、實施速率限制,或透過企業閘道路由流量時。

您可以透過在提供者設定中加入 url 參數來設定自訂基礎 URL:

php
'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
TTSOpenAI, ElevenLabs
STTOpenAI, ElevenLabs, Mistral
向量嵌入 (Embeddings)OpenAI, Gemini, Azure, Cohere, Mistral, Jina, VoyageAI
重新排名 (Reranking)Cohere, Jina
檔案OpenAI, Anthropic, Gemini

Laravel\Ai\Enums\Lab 列舉可用於在整個程式碼中引用提供者,而不是使用純字串:

php
use Laravel\Ai\Enums\Lab;

Lab::Anthropic;
Lab::OpenAI;
Lab::Gemini;
// ...

Agents

Agents 是在 Laravel AI SDK 中與 AI 提供者互動的基本構建塊。每個 agent 都是一個專屬的 PHP 類別,封裝了與大型語言模型互動所需的指令、對話上下文、工具和輸出結構 (schema)。可以將 agent 想像成一個專門的助手 —— 例如銷售教練、文件分析師或支援機器人 —— 您只需設定一次,即可在整個應用程式中根據需要進行提示。

您可以使用 make:agent Artisan 指令建立 agent:

shell
php artisan make:agent SalesCoach

php artisan make:agent SalesCoach --structured

在產生的 agent 類別中,您可以定義系統提示 (System Prompt) / 指令、訊息上下文、可用工具以及輸出結構 (schema)(如果適用):

php
<?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(),
        ];
    }
}

提示

若要提示 agent,請先使用 make 方法或標準實例化建立一個執行個體,然後呼叫 prompt

php
$response = (new SalesCoach)
    ->prompt('Analyze this sales transcript...');

return (string) $response;

make 方法會從容器中解析您的 agent,從而允許自動依賴注入。您也可以將參數傳遞給 agent 的建構函式:

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

透過向 prompt 方法傳遞額外的參數,您可以在進行提示時覆蓋預設的提供者、模型或 HTTP 逾時:

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

對話上下文

如果您的 agent 實作了 Conversational 介面,您可以使用 messages 方法來回傳先前的對話上下文(如果適用):

php
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();
}

記住對話

注意: 在使用 RemembersConversations trait 之前,您應該使用 vendor:publish Artisan 指令發佈並執行 AI SDK 遷移。這些遷移將建立儲存對話所需的資料庫表。

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

php
<?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 方法:

php
$response = (new SalesCoach)->forUser($user)->prompt('Hello!');

$conversationId = $response->conversationId;

對話 ID 會在回應中回傳,並可儲存供日後參考,或者您可以直接從 agent_conversations 資料表檢索使用者的所有對話。

若要繼續現有對話,請使用 continue 方法:

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

當使用 RemembersConversations trait 時,先前的訊息會在提示時自動載入並包含在對話上下文中。新的訊息(包括使用者和助手)會在每次互動後自動儲存。

結構化輸出

如果您希望您的 agent 回傳結構化輸出,請實作 HasStructuredOutput 介面,這要求您的 agent 定義一個 schema 方法:

php
<?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

php
$response = (new SalesCoach)->prompt('Analyze this sales transcript...');

return $response['score'];

附件

在提示時,您也可以隨提示內容傳遞附件,讓模型檢查圖片和文件:

php
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 類別可用於將圖片附加到提示中:

php
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):

php
use App\Ai\Agents\SalesCoach;

Route::get('/coach', function () {
    return (new SalesCoach)->stream('Analyze this sales transcript...');
});

then 方法可用於提供一個閉包 (Closure),該閉包將在完整回應串流至用戶端時被呼叫:

php
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...
        });
});

或者,您可以手動遍歷串流事件:

php
$stream = (new SalesCoach)->stream('Analyze this sales transcript...');

foreach ($stream as $event) {
    // ...
}

使用 Vercel AI SDK 協定進行串流

您可以透過在串流回應上呼叫 usingVercelDataProtocol 方法,使用 Vercel AI SDK 串流協定 (stream protocol) 來串流事件:

php
use App\Ai\Agents\SalesCoach;

Route::get('/coach', function () {
    return (new SalesCoach)
        ->stream('Analyze this sales transcript...')
        ->usingVercelDataProtocol();
});

廣播

您可以用幾種不同的方式來廣播串流事件。首先,您可以簡單地在串流事件上呼叫 broadcastbroadcastNow 方法:

php
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 操作排入佇列,並在串流事件可用時進行廣播:

php
(new SalesCoach)->broadcastOnQueue(
    'Analyze this sales transcript...'
    new Channel('channel-name'),
);

佇列

透過使用 Agent 的 queue 方法,您可以提示 Agent,但允許它在背景處理回應,從而讓您的應用程式保持快速且即時的回應。thencatch 方法可用於註冊閉包,這些閉包將在回應可用或發生例外時被呼叫:

php
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();
});

工具

工具可用於為 Agents 提供額外的功能,供其在回應提示時使用。可以使用 make:tool Artisan 指令來建立工具:

shell
php artisan make:tool RandomNumberGenerator

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

php
<?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 方法中回傳它:

php
use App\Ai\Tools\RandomNumberGenerator;

/**
 * Get the tools available to the agent.
 *
 * @return Tool[]
 */
public function tools(): iterable
{
    return [
        new RandomNumberGenerator,
    ];
}

相似性搜尋

SimilaritySearch 工具允許 Agents 使用存儲在資料庫中的向量嵌入 (Vector Embeddings) 來搜尋與給定查詢相似的檔案。這在您想讓 Agents 能夠搜尋應用程式資料的檢索增強生成 (RAG) 場景中非常有用。

建立相似性搜尋工具最簡單的方法是搭配具有向量嵌入的 Eloquent 模型使用 usingModel 方法:

php
use App\Models\Document;
use Laravel\Ai\Tools\SimilaritySearch;

public function tools(): iterable
{
    return [
        SimilaritySearch::usingModel(Document::class, 'embedding'),
    ];
}

第一個參數是 Eloquent 模型類別,第二個參數是包含向量嵌入的欄位。

您還可以提供 0.01.0 之間的最低相似性門檻值,以及一個用來自訂查詢的閉包:

php
SimilaritySearch::usingModel(
    model: Document::class,
    column: 'embedding',
    minSimilarity: 0.7,
    limit: 10,
    query: fn ($query) => $query->where('published', true),
),

為了獲得更多控制,您可以建立一個帶有自訂閉包的相似性搜尋工具,該閉包會回傳搜尋結果:

php
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 方法自訂工具的描述:

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

提供者工具

提供者工具 (Provider Tools) 是由 AI 提供者原生實現的特殊工具,提供網頁搜尋、URL 抓取和檔案搜尋等功能。與一般工具不同,提供者工具是由提供者本身執行,而非您的應用程式。

提供者工具可以透過您的 Agent 的 tools 方法回傳。

WebSearch 提供者工具允許 Agents 搜尋網頁以獲取即時資訊。這對於回答有關時事、近期數據或模型訓練截止後可能發生變化的主題非常有用。

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

php
use Laravel\Ai\Providers\Tools\WebSearch;

public function tools(): iterable
{
    return [
        new WebSearch,
    ];
}

您可以設定網頁搜尋工具以限制搜尋次數或將結果限制在特定網域:

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

要根據使用者位置優化搜尋結果,請使用 location 方法:

php
(new WebSearch)->location(
    city: 'New York',
    region: 'NY',
    country: 'US'
);

網頁抓取 (Web Fetch)

WebFetch 提供者工具允許 Agents 抓取並讀取網頁內容。當您需要 Agent 分析特定的 URL 或從已知網頁獲取詳細資訊時,這非常有用。

支援的提供者: Anthropic, Gemini

php
use Laravel\Ai\Providers\Tools\WebFetch;

public function tools(): iterable
{
    return [
        new WebFetch,
    ];
}

您可以設定網頁抓取工具以限制抓取次數或限制在特定網域:

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

FileSearch 提供者工具允許 Agents 搜尋儲存在 向量存儲 (Vector Stores) 中的 檔案。這藉由允許 Agent 在您上傳的檔案中搜尋相關資訊,實現了檢索增強生成 (RAG)。

支援的提供者: OpenAI, Gemini

php
use Laravel\Ai\Providers\Tools\FileSearch;

public function tools(): iterable
{
    return [
        new FileSearch(stores: ['store_id']),
    ];
}

您可以提供多個向量存儲 ID 以在多個存儲中進行搜尋:

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

如果您的檔案具有 Metadata,您可以透過提供 where 參數來過濾搜尋結果。對於簡單的等值過濾,請傳遞一個陣列:

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

對於更複雜的過濾,您可以傳遞一個接收 FileSearchQuery 實例的閉包:

php
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 支援中介層,讓您能在提示發送到提供者之前攔截並修改它們。可以使用 make:agent-middleware Artisan 指令建立中介層:

shell
php artisan make:agent-middleware LogPrompts

產生的中介層將放置在應用程式的 app/Ai/Middleware 目錄中。要為 Agent 新增中介層,請實作 HasMiddleware 介面並定義一個回傳中介層類別陣列的 middleware 方法:

php
<?php

namespace App\Ai\Agents;

use App\Ai\Middleware\LogPrompts;
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
<?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 完成處理後執行程式碼。這適用於同步和串流回應:

php
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:

php
use function Laravel\Ai\{agent};

$response = agent(
    instructions: 'You are an expert at software development.',
    messages: [],
    tools: [],
)->prompt('Tell me about Laravel')

匿名 Agents 也可以產生結構化輸出:

php
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 屬性設定 Agent 的文字生成選項。以下屬性可供使用:

  • MaxSteps: Agent 在使用工具時可以執行的最大步驟數。
  • MaxTokens: 模型可以生成的最大 Token 數。
  • Model: Agent 應該使用的模型。
  • Provider: Agent 要使用的 AI 提供者 (或用於容錯移轉的多個提供者)。
  • Temperature: 用於生成的取樣溫度 (0.0 到 1.0)。
  • Timeout: Agent 請求的 HTTP 超時秒數 (預設:60)。
  • UseCheapestModel: 使用提供者最便宜的文字模型進行成本最佳化。
  • UseSmartestModel: 使用提供者功能最強的文字模型處理複雜任務。
php
<?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;

    // ...
}

UseCheapestModelUseSmartestModel 屬性允許您自動為特定提供者選擇最具成本效益或功能最強的模型,而無需指定模型名稱。當您想要在不同的提供者之間優化成本或功能時,這非常有用:

php
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)...
}

提供者選項

如果您的 Agent 需要傳遞特定提供者的選項(例如 OpenAI 的推理強度或懲罰設定),請實作 HasProviderOptions 合約並定義 providerOptions 方法:

php
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasProviderOptions;
use Laravel\Ai\Enums\Lab;
use Laravel\Ai\Promptable;

class SalesCoach implements Agent, HasProviderOptions
{
    use Promptable;

    // ...

    /**
     * Get provider-specific generation options.
     */
    public function providerOptions(Lab|string $provider): array
    {
        return match ($provider) {
            Lab::OpenAI => [
                'reasoning' => ['effort' => 'low'],
                'frequency_penalty' => 0.5,
                'presence_penalty' => 0.3,
            ],
            Lab::Anthropic => [
                'thinking' => ['budget_tokens' => 1024],
            ],
            default => [],
        };
    }
}

providerOptions 方法會接收目前正在使用的提供者(Lab 列舉或字串),讓你能夠針對每個提供者回傳不同的選項。這在搭配 容錯移轉 使用時特別有用,因為每個備援提供者都可以接收其專屬的設定。

圖片

Laravel\Ai\Image 類別可用於透過 openaigeminixai 提供者來生成圖片:

php
use Laravel\Ai\Image;

$image = Image::of('A donut sitting on the kitchen counter')->generate();

$rawContent = (string) $image;

squareportraitlandscape 方法可用於控制圖片的長寬比,而 quality 方法可用於指導模型最終的圖片品質 (highmediumlow)。timeout 方法可用於指定 HTTP 超時秒數:

php
use Laravel\Ai\Image;

$image = Image::of('A donut sitting on the kitchen counter')
    ->quality('high')
    ->landscape()
    ->timeout(120)
    ->generate();

您可以使用 attachments 方法來附加參考圖片:

php
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 設定檔中定義的預設磁碟:

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');

圖片生成也可以進入佇列處理:

php
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 類別可用於根據給定的文字生成音訊:

php
use Laravel\Ai\Audio;

$audio = Audio::of('I love coding with Laravel.')->generate();

$rawContent = (string) $audio;

malefemalevoice 方法可用於決定生成的音訊聲音:

php
$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 方法可以用來動態指導模型生成的音訊聽起來應該像什麼:

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

產生的音訊可以輕鬆地儲存到您應用程式 config/filesystems.php 設定檔中定義的預設磁碟:

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');

音訊生成也可以進入佇列處理:

php
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 類別可用於為給定的音訊生成轉錄文字:

php
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 方法可以用來指示您希望回應中除了原始文字轉錄外,還包含語者辨識轉錄,讓您可以按說話者來存取分段後的轉錄內容:

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

轉錄生成也可以進入佇列處理:

php
use Laravel\Ai\Transcription;
use Laravel\Ai\Responses\TranscriptionResponse;

Transcription::fromStorage('audio.mp3')
    ->queue()
    ->then(function (TranscriptionResponse $transcript) {
        // ...
    });

向量嵌入 (Embeddings)

您可以使用 Laravel 的 Stringable 類別中提供的全新 toEmbeddings 方法,輕鬆地為任何給定字串產生向量嵌入 (Vector Embeddings):

php
use Illuminate\Support\Str;

$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings();

或者,您可以使用 Embeddings 類別同時為多個輸入產生嵌入:

php
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, ...]]

您可以為這些嵌入指定維度與提供者:

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

查詢向量嵌入

產生向量嵌入後,您通常會將它們儲存在資料庫的 vector 欄位中,以便稍後進行查詢。Laravel 透過 pgvector 擴充功能為 PostgreSQL 的向量欄位提供原生支援。若要開始使用,請在您的遷移 (Migration) 中定義一個 vector 欄位,並指定維度數量:

php
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 索引:

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

在您的 Eloquent 模型中,您應該將向量欄位轉型 (Cast) 為 array

php
protected function casts(): array
{
    return [
        'embedding' => 'array',
    ];
}

若要查詢相似的紀錄,請使用 whereVectorSimilarTo 方法。此方法會根據最小餘弦相似度(介於 0.01.0 之間,其中 1.0 為完全相同)過濾結果,並依相似度排序結果:

php
use App\Models\Document;

$documents = Document::query()
    ->whereVectorSimilarTo('embedding', $queryEmbedding, minSimilarity: 0.4)
    ->limit(10)
    ->get();

$queryEmbedding 可以是浮點數陣列或純字串。如果提供的是字串,Laravel 將自動為其產生向量嵌入:

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

如果您需要更多控制權,可以獨立使用較低階的 whereVectorDistanceLessThanselectVectorDistanceorderByVectorDistance 方法:

php
$documents = Document::query()
    ->select('*')
    ->selectVectorDistance('embedding', $queryEmbedding, as: 'distance')
    ->whereVectorDistanceLessThan('embedding', $queryEmbedding, maxDistance: 0.3)
    ->orderByVectorDistance('embedding', $queryEmbedding)
    ->limit(10)
    ->get();

如果您想賦予 Agent 執行相似性搜尋作為工具的能力,請參考 相似性搜尋 工具文件。

📌 備註

向量查詢目前僅支援使用 pgvector 擴充功能的 PostgreSQL 連線。

快取向量嵌入

向量嵌入的產生可以被快取,以避免對相同的輸入進行多餘的 API 呼叫。若要啟用快取,請將 ai.caching.embeddings.cache 設定選項設為 true

php
'caching' => [
    'embeddings' => [
        'cache' => true,
        'store' => env('CACHE_STORE', 'database'),
        // ...
    ],
],

啟用快取時,向量嵌入將被快取 30 天。快取鍵值是基於提供者、模型、維度和輸入內容生成的,確保相同的請求會回傳快取的結果,而不同的設定則會產生新的向量嵌入。

即使全域快取已停用,您也可以使用 cache 方法為特定請求啟用快取:

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

您可以指定自訂的快取持續時間(秒):

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

toEmbeddings Stringable 方法也接受 cache 參數:

php
// 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 類別來對文件進行重新排名:

php
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 方法限制回傳的結果數量:

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

重新排名集合

為了方便起見,可以使用 rerank 巨集 (Macro) 對 Laravel 集合 (Collections) 進行重新排名。第一個參數指定用於重新排名的欄位,第二個參數則是查詢:

php
// 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'
);

您也可以限制結果數量並指定提供者:

php
$reranked = $posts->rerank(
    by: 'content',
    query: 'Laravel tutorials',
    limit: 10,
    provider: Lab::Cohere
);

檔案

Laravel\Ai\Files 類別或個別的檔案類別可用於將檔案儲存至您的 AI 提供者,以便之後在對話中使用。這對於大型文件或您想要多次引用而不需要重新上傳的檔案非常有用:

php
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;

您也可以儲存原始內容或上傳的檔案:

php
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 生成文本時引用該檔案,而不需要重新上傳檔案:

php
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 方法:

php
use Laravel\Ai\Files\Document;

$file = Document::fromId('file-id')->get();

$file->id;
$file->mimeType();

若要從提供者中刪除檔案,請使用 delete 方法:

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

預設情況下,Files 類別使用您應用程式 config/ai.php 設定檔中設定的預設 AI 提供者。對於大多數操作,您可以使用 provider 參數指定不同的提供者:

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

在對話中使用已儲存的檔案

一旦檔案儲存到提供者後,您可以在 Agent 對話中使用 DocumentImage 類別的 fromId 方法來引用它:

php
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 類別來引用:

php
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)

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

php
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 方法:

php
use Laravel\Ai\Stores;

$store = Stores::get('store_id');

$store->id;
$store->name;
$store->fileCounts;
$store->ready;

若要刪除向量存儲,請在 Stores 類別或存儲實例上使用 delete 方法:

php
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 方法將 檔案 新增至其中。新增至存儲的檔案會自動進行索引,以便使用 提供者檔案搜尋工具 進行語義搜尋:

php
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 以供日後參考。

您可以將元數據 (Metadata) 附加到檔案中,然後將其新增至存儲。稍後在使用 提供者檔案搜尋工具 時,可以使用這些元數據來過濾搜尋結果:

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

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

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

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

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

容錯移轉 (Failover)

在進行提示或生成其他媒體時,您可以提供提供者/模型的陣列,以便在主要提供者遇到服務中斷或速率限制時,自動容錯移轉到備用的提供者/模型:

php
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 方法。您可以選擇提供回應陣列或閉包:

php
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 後,您可以針對收到的提示進行斷言:

php
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 調用,請使用佇列斷言方法:

php
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 但沒有定義模擬回應,系統將會拋出例外:

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

圖片

可以透過調用 Image 類別上的 fake 方法來模擬圖片生成。一旦模擬了圖片生成,就可以對記錄的圖片生成提示進行各種斷言:

php
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('...');
});

生成圖片後,您可以針對收到的提示進行斷言:

php
Image::assertGenerated(function (ImagePrompt $prompt) {
    return $prompt->contains('sunset') && $prompt->isLandscape();
});

Image::assertNotGenerated('Missing prompt');

Image::assertNothingGenerated();

對於佇列中的圖片生成,請使用佇列斷言方法:

php
Image::assertQueued(
    fn (QueuedImagePrompt $prompt) => $prompt->contains('sunset')
);

Image::assertNotQueued('Missing prompt');

Image::assertNothingQueued();

若要確保所有圖片生成都有對應的模擬回應,您可以使用 preventStrayImages。如果生成了圖片但沒有定義模擬回應,系統將會拋出例外:

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

音訊

可以透過調用 Audio 類別上的 fake 方法來模擬音訊生成。一旦模擬了音訊生成,就可以對記錄的音訊生成提示進行各種斷言:

php
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('...');
});

生成音訊後,您可以針對收到的提示進行斷言:

php
Audio::assertGenerated(function (AudioPrompt $prompt) {
    return $prompt->contains('Hello') && $prompt->isFemale();
});

Audio::assertNotGenerated('Missing prompt');

Audio::assertNothingGenerated();

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

php
Audio::assertQueued(
    fn (QueuedAudioPrompt $prompt) => $prompt->contains('Hello')
);

Audio::assertNotQueued('Missing prompt');

Audio::assertNothingQueued();

若要確保所有音訊生成都有對應的模擬回應,您可以使用 preventStrayAudio。如果生成了音訊但沒有定義模擬回應,系統將會拋出例外:

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

轉錄

可以透過調用 Transcription 類別上的 fake 方法來模擬轉錄生成。一旦模擬了轉錄生成,就可以對記錄的轉錄生成提示進行各種斷言:

php
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...';
});

生成轉錄後,您可以針對收到的提示進行斷言:

php
Transcription::assertGenerated(function (TranscriptionPrompt $prompt) {
    return $prompt->language === 'en' && $prompt->isDiarized();
});

Transcription::assertNotGenerated(
    fn (TranscriptionPrompt $prompt) => $prompt->language === 'fr'
);

Transcription::assertNothingGenerated();

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

php
Transcription::assertQueued(
    fn (QueuedTranscriptionPrompt $prompt) => $prompt->isDiarized()
);

Transcription::assertNotQueued(
    fn (QueuedTranscriptionPrompt $prompt) => $prompt->language === 'fr'
);

Transcription::assertNothingQueued();

若要確保所有轉錄生成都有對應的模擬回應,您可以使用 preventStrayTranscriptions。如果生成了轉錄但沒有定義模擬回應,系統將會拋出例外:

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

向量嵌入

向量嵌入 (Embeddings) 的生成可以透過調用 Embeddings 類別上的 fake 方法來模擬。一旦模擬了向量嵌入,就可以針對記錄的向量嵌入生成提示進行各種斷言:

php
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
    );
});

生成向量嵌入後,您可以對收到的提示進行斷言:

php
Embeddings::assertGenerated(function (EmbeddingsPrompt $prompt) {
    return $prompt->contains('Laravel') && $prompt->dimensions === 1536;
});

Embeddings::assertNotGenerated(
    fn (EmbeddingsPrompt $prompt) => $prompt->contains('Other')
);

Embeddings::assertNothingGenerated();

對於已佇列的向量嵌入生成,請使用佇列斷言方法:

php
Embeddings::assertQueued(
    fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Laravel')
);

Embeddings::assertNotQueued(
    fn (QueuedEmbeddingsPrompt $prompt) => $prompt->contains('Other')
);

Embeddings::assertNothingQueued();

為了確保所有的向量嵌入生成都有對應的模擬回應,您可以使用 preventStrayEmbeddings。如果生成的向量嵌入沒有定義模擬回應,則會拋出異常:

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

重新排名

重新排名 (Reranking) 操作可以透過調用 Reranking 類別上的 fake 方法來模擬:

php
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),
    ],
]);

重新排名後,您可以對執行的操作進行斷言:

php
Reranking::assertReranked(function (RerankingPrompt $prompt) {
    return $prompt->contains('Laravel') && $prompt->limit === 5;
});

Reranking::assertNotReranked(
    fn (RerankingPrompt $prompt) => $prompt->contains('Django')
);

Reranking::assertNothingReranked();

檔案

檔案操作可以透過調用 Files 類別上的 fake 方法來模擬:

php
use Laravel\Ai\Files;

Files::fake();

模擬檔案操作後,您可以對發生的上傳和刪除進行斷言:

php
use Laravel\Ai\Contracts\Files\StorableFile;
use Laravel\Ai\Files\Document;

// Store files...
Document::fromString('Hello, Laravel!', mimeType: '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:

php
Files::assertDeleted('file-id');
Files::assertNotDeleted('file-id');
Files::assertNothingDeleted();

向量存儲

向量存儲 (Vector store) 的操作可以透過調用 Stores 類別上的 fake 方法來模擬。模擬存儲也會自動模擬 檔案操作

php
use Laravel\Ai\Stores;

Stores::fake();

模擬存儲操作後,您可以對建立或刪除的存儲進行斷言:

php
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:

php
Stores::assertDeleted('store_id');
Stores::assertNotDeleted('other_store_id');
Stores::assertNothingDeleted();

若要斷言檔案已從存儲中新增或移除,請使用給定 Store 實例上的斷言方法:

php
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。在這種情況下,您可以向 assertAdded 方法傳遞一個閉包 (closure) 來針對新增檔案的內容進行斷言:

php
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!');

事件

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 的使用資訊。