Files
nl-admin-api/app/Service/common/ai/DeepSeekAiAgent.php
2026-08-10 15:51:00 +08:00

96 lines
3.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Service\common\ai;
use App\BaseApp\BaseService;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Throwable;
/**
* DeepSeek AgentOpenAI 兼容协议)
* 每次调用从 AiRuntimeConfigService 取最新平台/密钥/模型
*/
class DeepSeekAiAgent extends BaseService implements AiAgentInterface
{
public function __construct()
{
// Agent 本身不读用户态,避免工厂链路强制鉴权
$this->isAuth = false;
parent::__construct();
}
public function provider(): string
{
return 'deepseek';
}
/**
* 调用 DeepSeek chat completions
*/
public function chatCompletions(array $messages, array $options = []): AiChatResult
{
$cfg = AiRuntimeConfigService::getInstance()->resolve($this->provider());
$apiUrl = (string) ($cfg['api_url'] ?? '');
$apiKey = (string) ($cfg['api_key'] ?? '');
$defaultModel = (string) ($cfg['model'] ?? 'deepseek-chat');
$timeout = (float) ($cfg['timeout'] ?? 60);
if ($apiKey === '') {
$this->utils->errorThrow('DeepSeek 暂未开通请在「AI密钥管理」或 .env DEEPSEEK_API_KEY 配置)');
}
if ($apiUrl === '') {
$this->utils->errorThrow('未配置 DeepSeek 接口地址');
}
if (empty($messages)) {
$this->utils->errorThrow('AI 对话消息不能为空');
}
$model = (string) ($options['model'] ?? $defaultModel);
$body = [
'model' => $model,
'messages' => array_values($messages),
'stream' => false,
];
foreach (['temperature', 'max_tokens', 'top_p'] as $key) {
if (array_key_exists($key, $options)) {
$body[$key] = $options[$key];
}
}
try {
$client = new Client([
'timeout' => $timeout,
'connect_timeout' => min(10.0, $timeout),
]);
$response = $client->request('POST', $apiUrl, [
'headers' => [
'Authorization' => 'Bearer ' . $apiKey,
'Content-Type' => 'application/json',
],
'json' => $body,
]);
$raw = json_decode((string) $response->getBody(), true);
if (!is_array($raw)) {
$this->utils->errorThrow('DeepSeek 返回非 JSON');
}
$content = (string) data_get($raw, 'choices.0.message.content', '');
if ($content === '') {
$errMsg = (string) ($raw['error']['message'] ?? '');
$this->utils->errorThrow($errMsg !== '' ? ('DeepSeek 调用失败:' . $errMsg) : 'DeepSeek 未返回有效内容');
}
$usage = is_array($raw['usage'] ?? null) ? $raw['usage'] : [];
return new AiChatResult(
$content,
$raw,
$this->provider(),
$model,
$usage,
(int) ($cfg['api_key_id'] ?? 0)
);
} catch (Throwable $e) {
if ($e instanceof GuzzleException) {
$this->utils->errorThrow('DeepSeek 请求失败:' . $e->getMessage());
}
throw $e;
}
}
}