1. 项目概述与核心价值
如果你正在用 Laravel 框架开发应用,并且想集成当下最热门的 AI 大模型能力,那么deepseek-php/deepseek-laravel这个开源包绝对值得你花时间研究。简单来说,它是一个专门为 Laravel 定制的 SDK,让你能像调用本地服务一样,轻松地在你的 Laravel 应用中接入 DeepSeek 的各类 AI 模型,比如对话、文本生成、代码补全等功能。
我最初接触它,是因为厌倦了在每个需要 AI 能力的控制器里,重复编写 HTTP 客户端代码、处理认证、解析响应和异常。这个包把所有这些繁琐的细节都封装了起来,提供了一套符合 Laravel 优雅哲学(Eloquent)的 API。你只需要几行配置和代码,就能让 AI 能力成为你应用基础设施的一部分,无论是构建一个智能客服、一个内容创作助手,还是一个能理解用户意图的复杂工作流,都变得异常简单。
它的核心价值在于“无缝集成”和“开发者体验”。它不是一个简单的 API 包装器,而是深度拥抱了 Laravel 的 Service Container、Facades、Config 等核心概念。这意味着你可以用你熟悉的 Laravel 方式来使用 AI 服务,例如通过依赖注入来获取客户端实例,通过配置文件来管理不同环境的 API Key,甚至利用 Laravel 的队列(Queue)来异步处理耗时的 AI 生成任务,避免阻塞主请求。对于已经熟悉 Laravel 生态的开发者来说,学习成本几乎为零,上手就能用,这极大地加速了 AI 功能的落地和迭代。
2. 核心设计思路与架构拆解
2.1 为什么选择专用 SDK 而非通用 HTTP 客户端?
在项目初期,很多人可能会想:我直接用 Guzzle 或 Laravel 的 HTTP Client 去调用 DeepSeek 的 API 不就行了?为什么还需要一个专门的包?这里面的区别,正是deepseek-laravel设计的精妙之处。
首先,标准化与一致性。DeepSeek API 有其特定的请求格式、认证方式(Bearer Token)、错误码体系和响应结构。如果每个开发者都自己实现一遍,不仅容易出错,而且代码风格各异,后期维护成本高。这个 SDK 将这些细节统一封装,提供了如chat()->create([...])这样语义清晰的方法,让团队协作和代码审查变得更容易。
其次,功能增强与最佳实践集成。一个优秀的 SDK 不会止步于简单的“请求-响应”映射。deepseek-laravel通常内置了重试机制(当遇到网络波动或 API 限流时)、请求超时控制、以及符合 Laravel 日志系统的结构化日志记录。这意味着你的 AI 调用会自动具备生产环境所需的健壮性和可观测性,而这些功能如果自己从零实现,需要大量的额外工作。
最后,面向未来的可扩展性。AI 服务提供商的 API 可能会迭代,增加新的参数或端点。一个维护良好的 SDK 会同步更新这些变化,你只需要更新 Composer 包版本,而无需修改自己的业务代码。同时,SDK 的设计往往预留了扩展点,比如允许你自定义 HTTP 处理器、添加中间件来修改请求或响应,为应对复杂场景提供了可能。
2.2 包的核心架构:服务提供者、门面与管理配置
这个包遵循了 Laravel 扩展包的标准开发模式,其架构清晰且易于理解。
1. 服务提供者 (ServiceProvider)这是包与 Laravel 应用连接的桥梁。在DeepSeekServiceProvider中,主要完成两件事:
- 注册绑定:将核心的
DeepSeekClient类注册到 Laravel 的服务容器中。这样,你就可以通过app(DeepSeekClient::class)或依赖注入来获取实例。 - 发布配置:通过
publishes方法,允许开发者使用php artisan vendor:publish命令将包的配置文件复制到项目的config目录下,方便进行个性化修改。
2. 门面 (Facade)包很可能提供了一个DeepSeek门面。门面提供了静态调用的语法糖,让你可以像DeepSeek::chat()->create(...)这样使用,非常简洁。背后实际上是门面代理到了服务容器中绑定的DeepSeekClient实例。这符合 Laravel 开发者的一贯习惯。
3. 配置文件通常是一个deepseek.php文件,放置在config目录下。这是控制包行为的核心。里面最重要的配置项就是api_key,你的 DeepSeek 账户密钥就放在这里。此外,可能还包括:
base_uri: API 的基础地址,方便在开发、测试和生产环境切换,或者使用代理。timeout: 请求超时时间。retry: 重试次数和重试间隔配置。http_options: 传递给底层 HTTP 客户端的其他选项。
4. 核心客户端 (Client)这是包的心脏,一个封装了所有业务逻辑的类。它内部会使用一个 HTTP 客户端(如 Guzzle)来发起请求。它的方法通常与 DeepSeek 官方的 API 端点一一对应,例如:
chat(): 处理聊天补全。embeddings(): 生成文本嵌入向量。models()->list(): 列出可用模型。
每个方法都会负责构建符合 API 要求的请求体,发送请求,并处理响应,将 JSON 数据转化为更易用的 PHP 数组或对象,同时统一捕获并抛出有意义的异常。
注意:在查看包的源码时,重点关注
Client类和它的方法,这是理解其工作原理和进行自定义扩展的关键。
3. 从零开始的完整集成与配置指南
3.1 环境准备与安装
首先,确保你的 Laravel 项目环境符合要求。通常这类包需要 PHP 8.1+ 和 Laravel 9.x 或 10.x。你可以通过以下命令检查:
php --version php artisan --version接下来,通过 Composer 安装包。打开终端,进入你的 Laravel 项目根目录,执行:
composer require deepseek-php/deepseek-laravel这个命令会从 Packagist 仓库拉取包及其依赖(主要是 HTTP 客户端和 PSR 规范相关的包)到你的vendor目录。
安装完成后,Laravel 的包自动发现机制通常会自动注册服务提供者。但为了确保无误,你可以检查config/app.php中的providers数组,确认DeepSeek\Laravel\DeepSeekServiceProvider::class是否已存在(现代包一般通过composer.json中的extra.laravel部分自动注册,无需手动添加)。
3.2 获取并配置 API 密钥
使用任何云端 AI 服务的第一步都是获取认证密钥。
- 访问 DeepSeek 的官方平台(通常是其官网的开发者部分)。
- 注册并登录账户。
- 在控制台中找到 API Keys 管理页面,创建一个新的密钥。务必妥善保管这个密钥,它代表你的账户身份和计费凭证。一旦泄露,应立即在平台撤销。
有了 API 密钥后,我们需要在 Laravel 项目中配置它。使用 Artisan 命令发布包的配置文件:
php artisan vendor:publish --provider="DeepSeek\Laravel\DeepSeekServiceProvider"执行后,你会在config目录下找到deepseek.php文件。打开它,最重要的配置就是api_key:
return [ 'api_key' => env('DEEPSEEK_API_KEY', 'your-api-key-here'), // ... 其他配置 ];绝对不要将真实的 API 密钥直接硬编码在这个配置文件中。正确的做法是使用 Laravel 的.env环境变量文件。打开项目根目录下的.env文件,添加一行:
DEEPSEEK_API_KEY=sk-your-actual-secret-key-here然后,在config/deepseek.php中,通过env('DEEPSEEK_API_KEY')来读取。这样,你的密钥就不会被提交到代码仓库(记得将.env添加到.gitignore),并且可以方便地为不同环境(本地、测试、生产)设置不同的密钥。
3.3 基础使用:发起你的第一个 AI 对话
配置完成后,就可以在代码中使用了。这里介绍几种常用的调用方式。
方式一:使用依赖注入(推荐)在控制器或服务类中,通过构造函数或方法注入DeepSeekClient。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use DeepSeek\Laravel\DeepSeekClient; use Illuminate\Http\Request; class AIChatController extends Controller { protected $deepSeek; public function __construct(DeepSeekClient $deepSeek) { $this->deepSeek = $deepSeek; } public function chat(Request $request) { $userMessage = $request->input('message', '你好,请介绍一下你自己。'); try { $response = $this->deepSeek->chat()->create([ 'model' => 'deepseek-chat', // 指定模型 'messages' => [ ['role' => 'user', 'content' => $userMessage] ], 'max_tokens' => 500, 'temperature' => 0.7, ]); // $response 通常是一个数组,包含API返回的全部信息 $aiReply = $response['choices'][0]['message']['content'] ?? '未收到回复'; return response()->json(['reply' => $aiReply]); } catch (\Exception $e) { // 处理异常,例如记录日志并返回友好错误信息 \Log::error('DeepSeek API 调用失败', ['error' => $e->getMessage()]); return response()->json(['error' => 'AI服务暂时不可用'], 503); } } }方式二:使用门面 (Facade)如果包提供了DeepSeek门面,使用起来会更简洁。
use DeepSeek\Laravel\Facades\DeepSeek; // 在路由或控制器中直接使用 $response = DeepSeek::chat()->create([...]);方式三:使用辅助函数 (如果提供)有些包也会提供一个全局辅助函数,比如deepseek()。
$response = deepseek()->chat()->create([...]);我个人最推荐依赖注入的方式,因为它更符合 Laravel 的 IoC 理念,使得代码更容易测试(你可以轻松地注入一个 Mock 客户端),也清晰地表明了类的依赖关系。
4. 核心功能深度解析与高级用法
4.1 聊天补全 (Chat Completions) 的参数调优
聊天补全是使用最频繁的功能。除了基本的model和messages,理解其他参数对生成结果的影响至关重要。
messages数组的构建:这是对话的历史记录。一个典型的对话轮次包括role为system(设定助手行为)、user(用户输入)和assistant(助手回复)的消息。保持对话上下文的连贯性靠的就是正确维护这个数组。对于多轮对话,你需要将历史消息一并传入。$messages = [ ['role' => 'system', 'content' => '你是一个专业的编程助手,回答要简洁准确。'], ['role' => 'user', 'content' => '如何用 Laravel 定义一个资源控制器?'], ['role' => 'assistant', 'content' => '可以使用 `php artisan make:controller PostController --resource` 命令。'], ['role' => 'user', 'content' => '那对应的路由要怎么定义呢?'] // AI 会基于上文理解这个问题 ];temperature(温度,0~2):控制输出的随机性。值越低(如0.1),输出越确定、保守、重复性高;值越高(如1.2),输出越随机、有创意、可能不连贯。对于代码生成或事实问答,建议较低(0.1-0.5);对于创意写作,可以调高(0.7-1.0)。max_tokens(最大令牌数):限制生成回复的最大长度。注意,这个数字是输入和输出 tokens 的总和上限。你需要根据模型上下文长度(如 4096、8192、32768)来合理设置,预留足够的空间给输出。估算不准可能导致生成被截断。top_p(核采样,0~1):另一种控制随机性的方式,与temperature通常二选一。它考虑概率质量最高的前 p% 的 tokens。例如,0.1 意味着只考虑构成前10%概率质量的 tokens。通常设置 0.9-0.95 能获得不错的效果。stream(流式输出):布尔值。设置为true时,API 会返回一个 SSE (Server-Sent Events) 流,允许你逐字逐句地接收回复,极大提升用户体验,避免长时间等待。deepseek-laravel包需要提供相应的方法来处理流式响应。// 伪代码,具体流式处理取决于SDK的实现 $streamResponse = $this->deepSeek->chat()->createStreamed([...]); foreach ($streamResponse as $chunk) { echo $chunk['choices'][0]['delta']['content'] ?? ''; ob_flush(); // 即时输出到浏览器 flush(); }
4.2 异步处理与队列集成
AI API 调用可能耗时数百毫秒甚至数秒,如果在 Web 请求中同步执行,会导致用户界面卡顿,影响体验并增加 Web 服务器超时风险。Laravel 的队列系统是解决此问题的完美方案。
我们可以创建一个 Laravel Job 来封装 AI 调用:
<?php namespace App\Jobs; use DeepSeek\Laravel\DeepSeekClient; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; class ProcessAIChat implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries = 3; // 重试次数 public $timeout = 120; // 任务超时时间(秒) protected $prompt; protected $userId; public function __construct(string $prompt, int $userId) { $this->prompt = $prompt; $this->userId = $userId; // 可以设置队列连接、延迟等 // $this->onConnection('redis'); // $this->delay(now()->addMinutes(1)); } public function handle(DeepSeekClient $deepSeek) { // 这里是实际的 AI 调用 $response = $deepSeek->chat()->create([ 'model' => 'deepseek-chat', 'messages' => [['role' => 'user', 'content' => $this->prompt]], 'max_tokens' => 1000, ]); $aiReply = $response['choices'][0]['message']['content']; // 处理结果:存入数据库、发送通知等 \App\Models\AIConversation::create([ 'user_id' => $this->userId, 'prompt' => $this->prompt, 'reply' => $aiReply, ]); // 或者通过广播、WebSocket 推送给前端 // broadcast(new AIChatCompleted($this->userId, $aiReply)); } public function failed(\Throwable $exception) { // 任务失败后的处理逻辑,例如记录日志、发送警报 \Log::error('AI 处理任务失败', [ 'user_id' => $this->userId, 'prompt' => $this->prompt, 'error' => $exception->getMessage() ]); } }在控制器中,你只需要分发任务,立即返回响应给用户:
public function askAsync(Request $request) { $validated = $request->validate(['message' => 'required|string']); ProcessAIChat::dispatch($validated['message'], auth()->id()); return response()->json(['status' => '已提交处理,请稍后查看结果']); }这样,耗时的 AI 调用被转移到后台队列 worker 处理,Web 响应速度极快。用户可以通过轮询、长连接或通知来获取最终结果。
4.3 文件上传与视觉模型调用
DeepSeek 的某些模型(如deepseek-vl)支持多模态输入,可以处理图像。API 允许在消息中上传文件。deepseek-laravel包需要提供便捷的方式来处理本地文件或网络图片。
假设 API 支持以下格式,SDK 应该提供相应的方法:
// 假设的用法,具体取决于SDK实现 $response = $this->deepSeek->chat()->create([ 'model' => 'deepseek-vl', 'messages' => [ [ 'role' => 'user', 'content' => [ ['type' => 'text', 'text' => '请描述这张图片的内容。'], [ 'type' => 'image_url', 'image_url' => [ // SDK 内部可能需要将本地文件转换为 base64 或可访问的 URL 'url' => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($pathToImage)) ] ] ] ] ] ]);对于生产环境,更常见的做法是先将用户上传的图片存储到云存储(如 S3、OSS),然后将其公开可访问的 URL 传递给 API。SDK 应该能优雅地处理这两种情况。
实操心得:处理图片时,务必注意图片大小和格式限制。API 通常对 base64 编码后的字符串长度或图片分辨率有要求。在上传前,最好在服务端对图片进行压缩和格式转换(例如,使用 Intervention Image 库),以避免不必要的 API 调用失败和费用浪费。
5. 生产环境配置、优化与监控
5.1 配置管理与多环境策略
在真实的项目开发中,我们会有本地开发、测试、预发布和生产等多个环境。API 密钥、请求超时等配置可能各不相同。
环境变量管理:坚持使用
.env文件。为每个环境创建对应的.env文件(如.env.production),并通过部署脚本或服务器环境变量来设置DEEPSEEK_API_KEY。永远不要在代码仓库中提交包含真实密钥的.env文件。配置覆盖:你可以在
config/deepseek.php中使用env()函数读取环境变量,并设置合理的默认值。此外,Laravel 允许你在服务提供者中动态修改配置。例如,你可以在AppServiceProvider的boot方法中,根据当前环境调整超时时间:public function boot() { if (app()->environment('production')) { config(['deepseek.timeout' => 30]); // 生产环境超时设为30秒 config(['deepseek.retry.times' => 2]); // 生产环境重试2次 } else { config(['deepseek.timeout' => 60]); // 开发环境可以宽松些 } }多密钥与客户端实例:如果你的应用需要访问不同 DeepSeek 账户(例如为不同租户隔离资源),或者需要同时调用不同模型,可能需要配置多个客户端实例。这需要更高级的包设计支持,或者你可以自行在服务容器中绑定多个不同配置的客户端。
// 在 AppServiceProvider 中注册多个客户端 $this->app->bind('deepseek.client.main', function ($app) { return new DeepSeekClient(config('deepseek.main')); // 对应 config/deepseek.main }); $this->app->bind('deepseek.client.backup', function ($app) { return new DeepSeekClient(config('deepseek.backup')); // 对应 config/deepseek.backup });
5.2 性能优化与缓存策略
AI API 调用是按 token 收费且有速率限制的。优化性能就是优化成本和用户体验。
实现请求缓存:对于某些相对静态或可重复的提示词(例如,“将以下英文翻译成中文:{text}”),如果
{text}相同,结果在短时间内是确定的。可以为这些请求结果添加缓存。use Illuminate\Support\Facades\Cache; public function getCachedTranslation($text) { $cacheKey = 'deepseek:translation:' . md5($text); $cacheTtl = now()->addHours(6); // 缓存6小时 return Cache::remember($cacheKey, $cacheTtl, function () use ($text) { return $this->deepSeek->chat()->create([ 'model' => 'deepseek-chat', 'messages' => [['role' => 'user', 'content' => "Translate to Chinese: $text"]], 'temperature' => 0.1, // 低随机性确保翻译稳定 ]); }); }批处理请求:如果应用场景允许,可以将多个独立的、非顺序依赖的请求合并处理(虽然 DeepSeek Chat API 本身可能不支持原生批处理,但你可以使用并发请求)。利用 Laravel 的 Promise 或 Guzzle 的异步并发,可以显著减少总等待时间。
精简输入与输出:
max_tokens不要设置得过大,够用即可。在发送给 API 前,检查用户输入是否包含不必要的信息,可以尝试在业务逻辑层进行预处理和清洗。
5.3 日志记录、监控与告警
清晰的日志是排查问题的生命线。deepseek-laravel包应该集成 Laravel 的日志系统。
启用详细日志:在
config/deepseek.php中,确保日志级别设置得当。生产环境可以记录INFO和ERROR,开发环境可以记录DEBUG。记录关键信息:每次 API 调用,至少应该记录:
- 请求的模型和参数摘要(注意不要记录完整的包含敏感信息的提示词)。
- 请求耗时。
- 消耗的 token 数量(输入/输出)。
- 响应状态码。
- 如果失败,记录详细的错误信息。
这能帮你分析使用模式、定位性能瓶颈和追踪异常费用。
设置监控与告警:
- 错误率监控:监控 API 调用失败(非 2xx 状态)的比例。如果错误率突然升高,可能意味着服务端问题或你的密钥异常。
- 延迟监控:记录 P95、P99 响应时间。延迟异常增加可能影响用户体验。
- 额度监控:定期通过 API 查询账户余额或使用量,并设置预警。可以在 Laravel 中创建一个计划任务(Scheduled Command),每天检查用量,并在达到阈值时通过邮件、Slack 等渠道发送通知。
- 业务指标监控:根据你的应用场景,监控有意义的数据,如“平均每会话 AI 调用次数”、“最常使用的模型”等。
6. 常见问题排查与实战技巧
在实际集成和使用deepseek-laravel的过程中,你几乎一定会遇到下面这些问题。这里我把踩过的坑和解决方案整理出来,希望能帮你节省大量时间。
6.1 认证失败与密钥问题
问题现象:调用 API 时返回401 Unauthorized或类似的认证错误。
排查步骤:
- 检查
.env文件:首先确认DEEPSEEK_API_KEY环境变量已正确设置,并且没有拼写错误。可以通过php artisan tinker然后执行echo env('DEEPSEEK_API_KEY');来验证 Laravel 是否读取到了正确的值。 - 检查缓存:如果你修改了
.env文件,记得运行php artisan config:clear和php artisan cache:clear来清除配置和缓存,确保新值生效。 - 验证密钥有效性:有时密钥可能因过期、被手动撤销或在平台被禁用而失效。最简单的方法是通过一个极简的 curl 命令或在 DeepSeek 平台的控制台测试密钥。
- 检查 IP 白名单:某些云服务商允许为 API 密钥设置 IP 白名单。如果你的生产服务器 IP 不在白名单内,请求会被拒绝。请到 DeepSeek 控制台检查相关安全设置。
- 查看包源码:检查
DeepSeekClient是如何构建请求头的。确认Authorization头的格式是否正确(通常是Bearer {api_key})。
注意:永远不要在客户端(浏览器 JavaScript)中硬编码或暴露你的 API 密钥。所有 AI 调用必须通过你的后端服务器进行,密钥只保存在服务器环境变量中。
6.2 网络超时与稳定性处理
问题现象:请求长时间无响应,最终抛出GuzzleHttp\Exception\ConnectException或超时异常。
解决方案:
- 调整超时配置:在
config/deepseek.php中合理设置timeout(连接超时)和read_timeout(读取超时)。对于生成长文本,read_timeout需要设置得足够大(例如 60 秒或更长)。 - 实现重试机制:一个健壮的 SDK 应该内置指数退避的重试逻辑,应对暂时的网络抖动或 API 限流(429 状态码)。检查包的配置,看是否支持配置重试次数和等待时间。
- 使用连接池:确保你的 HTTP 客户端(通常是 Guzzle)启用了连接池,这可以避免频繁建立 TCP 连接的开销。
- 设置备用端点或降级方案:对于关键业务,可以考虑配置一个备用的 API 基础地址(如果提供),或者在 AI 服务不可用时,提供降级方案,比如返回一个缓存的默认答案或友好的错误提示。
6.3 速率限制与配额管理
问题现象:请求返回429 Too Many Requests错误,或者控制台显示配额已用尽。
理解限制:你需要清楚 DeepSeek API 的两类限制:
- RPM (Requests Per Minute)/RPD (Requests Per Day):每分钟/每天请求数上限。
- TPM (Tokens Per Minute):每分钟处理的 tokens 总数上限(包括输入和输出)。
应对策略:
- 客户端限流:在应用层面实现请求队列和速率控制。例如,使用 Laravel 的速率限制器(Rate Limiter)或一个简单的令牌桶算法,确保发送请求的速度不会超过限制。
- 优化请求:合并请求、缓存结果、精简提示词,都是减少请求次数和 token 消耗的有效方法。
- 监控与告警:如前所述,设置用量监控,在接近限制时提前告警。
- 处理 429 错误:当收到 429 响应时,正确的做法是解析响应头(如
Retry-After),然后等待指定的时间后再重试。你的 SDK 或重试逻辑应该能正确处理这种情况。
6.4 响应解析与错误处理
问题现象:API 调用看似成功(返回 200),但解析响应数据时出错,或者业务逻辑无法处理 AI 返回的内容。
最佳实践:
防御性编程:永远不要假设 API 响应结构完全符合预期。使用
isset()、??空合并运算符或 Laravel 的data_get()助手函数来安全地访问嵌套数组。// 不安全的写法 $reply = $response['choices'][0]['message']['content']; // 安全的写法 $reply = $response['choices'][0]['message']['content'] ?? '默认回复或空'; // 或使用 data_get $reply = data_get($response, 'choices.0.message.content', '默认回复');结构化错误处理:将 AI 调用封装在一个服务类中,统一进行异常捕获和转换。将网络错误、API 错误、业务逻辑错误区分开,并抛出具有明确含义的自定义异常。
try { $response = $this->client->chat()->create($params); // ... 解析响应 } catch (\GuzzleHttp\Exception\RequestException $e) { // 网络层异常 throw new AIServiceUnavailableException('AI 服务网络异常', 0, $e); } catch (\DeepSeek\Exceptions\ApiException $e) { // SDK 封装的 API 业务异常 throw new AIRequestFailedException($e->getMessage(), $e->getCode(), $e); } catch (\Exception $e) { // 其他未知异常 throw new AIUnexpectedException('AI 处理发生未知错误', 0, $e); }验证与清洗 AI 输出:AI 生成的内容可能包含不期望的格式、标记或甚至有害信息。在将内容展示给用户或存入数据库前,务必进行必要的清洗、转义和内容安全审核。
6.5 实战技巧:构建一个可维护的 AI 服务层
不要将 AI 调用代码直接散落在各个控制器中。我强烈建议抽象出一个专门的 Service 层。
1. 创建AIService类:
<?php namespace App\Services; use DeepSeek\Laravel\DeepSeekClient; use App\Exceptions\AIServiceException; use Illuminate\Support\Facades\Log; class AIService { protected $client; protected $defaultModel; public function __construct(DeepSeekClient $client) { $this->client = $client; $this->defaultModel = config('deepseek.default_model', 'deepseek-chat'); } public function chatCompletion(array $messages, array $options = []) { $params = array_merge([ 'model' => $this->defaultModel, 'messages' => $messages, 'max_tokens' => 1000, 'temperature' => 0.7, ], $options); try { Log::info('Sending request to DeepSeek API', ['model' => $params['model']]); $start = microtime(true); $response = $this->client->chat()->create($params); $elapsed = round((microtime(true) - $start) * 1000, 2); Log::info('Received response from DeepSeek API', [ 'model' => $params['model'], 'time_ms' => $elapsed, 'usage' => $response['usage'] ?? null ]); return data_get($response, 'choices.0.message.content'); } catch (\Exception $e) { Log::error('DeepSeek API call failed', [ 'error' => $e->getMessage(), 'params' => $params // 注意:生产环境不要记录完整的 messages,可能包含用户隐私 ]); throw new AIServiceException('AI 服务处理失败,请稍后重试', 0, $e); } } // 可以继续添加其他方法,如 embeddings, moderation 等 public function createEmbedding(string $text) { ... } }2. 在控制器中注入并使用:
public function ask(AIService $aiService, Request $request) { $message = $request->input('message'); $reply = $aiService->chatCompletion([ ['role' => 'user', 'content' => $message] ]); return response()->json(['reply' => $reply]); }这样做的好处非常明显:关注点分离、代码复用、统一错误和日志处理、便于单元测试(你可以 MockAIService),以及未来切换 AI 供应商(比如从 DeepSeek 换到其他模型)时,只需要修改这一个服务类,而无需改动所有控制器。
集成deepseek-php/deepseek-laravel不仅仅是安装一个包,更是将强大的 AI 能力以优雅、健壮的方式融入你的 Laravel 应用架构。从配置管理、基础调用,到高级的队列处理、缓存策略和监控告警,每一步都需要结合 Laravel 的特性和生产环境的最佳实践来考量。这个包提供了一个坚实的起点,而真正的价值在于你如何利用它构建出稳定、高效且用户体验出色的智能功能。