|
@@ -33,6 +33,7 @@ class DeepSeekService
|
|
|
private $valid_text_models;
|
|
private $valid_text_models;
|
|
|
private $gpt_text_models;
|
|
private $gpt_text_models;
|
|
|
private $gemini_text_models;
|
|
private $gemini_text_models;
|
|
|
|
|
+ private $baidu_glm_text_models;
|
|
|
protected $aiImageGenerationService;
|
|
protected $aiImageGenerationService;
|
|
|
protected $pointsService;
|
|
protected $pointsService;
|
|
|
|
|
|
|
@@ -51,6 +52,8 @@ class DeepSeekService
|
|
|
$this->gpt_text_models = BaseConst::GPT_TEXT_MODELS;
|
|
$this->gpt_text_models = BaseConst::GPT_TEXT_MODELS;
|
|
|
// Gemini文本模型列表
|
|
// Gemini文本模型列表
|
|
|
$this->gemini_text_models = BaseConst::GEMINI_TEXT_MODELS;
|
|
$this->gemini_text_models = BaseConst::GEMINI_TEXT_MODELS;
|
|
|
|
|
+ // 百度 AI 网关 GLM 文本模型列表
|
|
|
|
|
+ $this->baidu_glm_text_models = BaseConst::BAIDU_GLM_TEXT_MODELS;
|
|
|
$this->sys_message = [
|
|
$this->sys_message = [
|
|
|
'role' => 'system',
|
|
'role' => 'system',
|
|
|
'content' => "你是一个专业的文档分析助手及资深编剧,请根据用户提供的文档内容完成示例格式的内容输出(需通过以下几个板块进行回复: <故事梗概><剧本亮点><人物关系><核心矛盾><主体列表><美术风格><场景列表><分集剧本>,每个板块之间必须使用###分隔,#不能多也不能少;同时板块之间需满足以下要求:\n
|
|
'content' => "你是一个专业的文档分析助手及资深编剧,请根据用户提供的文档内容完成示例格式的内容输出(需通过以下几个板块进行回复: <故事梗概><剧本亮点><人物关系><核心矛盾><主体列表><美术风格><场景列表><分集剧本>,每个板块之间必须使用###分隔,#不能多也不能少;同时板块之间需满足以下要求:\n
|
|
@@ -315,22 +318,8 @@ class DeepSeekService
|
|
|
$post_data['response_format'] = $data['response_format'];
|
|
$post_data['response_format'] = $data['response_format'];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 根据模型类型选择调用方法
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else if (in_array($model, $this->valid_text_models)) {
|
|
|
|
|
- // 火山引擎支持的模型使用火山引擎 API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- Utils::throwError('20003:不支持的模型: ' . $model);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 根据模型类型选择流式实现
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
if ($chargePoints > 0) {
|
|
if ($chargePoints > 0) {
|
|
|
return $this->wrapGenerateTextCharge($streamGenerator, $uid, $model, $chargePoints, $chargeModality);
|
|
return $this->wrapGenerateTextCharge($streamGenerator, $uid, $model, $chargePoints, $chargeModality);
|
|
@@ -982,18 +971,8 @@ class DeepSeekService
|
|
|
$this->pointsService->checkUserPointsEnough($this->pointsService->getChatChargePoints((string)$model), $uid);
|
|
$this->pointsService->checkUserPointsEnough($this->pointsService->getChatChargePoints((string)$model), $uid);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 根据模型类型选择流式调用方法
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } elseif (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } elseif (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } elseif (in_array($model, $this->valid_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- Utils::throwError('20003:不支持的模型: ' . $model);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 根据模型类型选择流式实现
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 流式输出包装:done 时更新任务状态、扣费并保存对话记录
|
|
// 流式输出包装:done 时更新任务状态、扣费并保存对话记录
|
|
|
return $this->wrapNewGenerateTextStream($streamGenerator, [
|
|
return $this->wrapNewGenerateTextStream($streamGenerator, [
|
|
@@ -1696,72 +1675,20 @@ class DeepSeekService
|
|
|
$this->pointsService->checkUserPointsEnough($this->pointsService->getChatChargePoints((string)$model), $uid);
|
|
$this->pointsService->checkUserPointsEnough($this->pointsService->getChatChargePoints((string)$model), $uid);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 根据模型类型选择调用方法(复用现有的chatOnly方法)
|
|
|
|
|
|
|
+ // 统一分模型调用非流式实现
|
|
|
try {
|
|
try {
|
|
|
$aiResult = null;
|
|
$aiResult = null;
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用现有的 chatOnly 方法
|
|
|
|
|
- $result = $this->chatOnly($post_data);
|
|
|
|
|
-
|
|
|
|
|
- // 记录实际使用的模型
|
|
|
|
|
- dLog('deepseek')->info('newGenerateText使用DeepSeek模型', ['requested_model' => $model, 'actual_model' => $model]);
|
|
|
|
|
-
|
|
|
|
|
- $aiResult = [
|
|
|
|
|
- 'content' => $result['fullContent'],
|
|
|
|
|
- 'reasoning_content' => $result['fullReasoningContent'],
|
|
|
|
|
- 'usage' => $result['usage'],
|
|
|
|
|
- 'model' => $model,
|
|
|
|
|
- 'finish_reason' => 'stop'
|
|
|
|
|
- ];
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT 模型使用现有的 gpt54ChatOnly 方法
|
|
|
|
|
- $result = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
-
|
|
|
|
|
- dLog('deepseek')->info('newGenerateText使用GPT模型', ['requested_model' => $model]);
|
|
|
|
|
-
|
|
|
|
|
- $aiResult = [
|
|
|
|
|
- 'content' => $result['fullContent'],
|
|
|
|
|
- 'reasoning_content' => '',
|
|
|
|
|
- 'usage' => $result['usage'],
|
|
|
|
|
- 'model' => $model,
|
|
|
|
|
- 'finish_reason' => 'stop'
|
|
|
|
|
- ];
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API(非流式)
|
|
|
|
|
- $result = $this->geminiChatOnly($post_data, $model);
|
|
|
|
|
|
|
+ $result = $this->dispatchChatOnlyByModel($post_data);
|
|
|
|
|
|
|
|
- dLog('deepseek')->info('newGenerateText使用Gemini模型', ['requested_model' => $model]);
|
|
|
|
|
|
|
+ dLog('deepseek')->info('newGenerateText模型调用完成', ['requested_model' => $model]);
|
|
|
|
|
|
|
|
- $aiResult = [
|
|
|
|
|
- 'content' => $result['fullContent'],
|
|
|
|
|
- 'reasoning_content' => $result['fullReasoningContent'] ?? '',
|
|
|
|
|
- 'usage' => $result['usage'],
|
|
|
|
|
- 'model' => $model,
|
|
|
|
|
- 'finish_reason' => $result['finish_reason'] ?? 'stop'
|
|
|
|
|
- ];
|
|
|
|
|
- } else if (in_array($model, $this->valid_text_models)) {
|
|
|
|
|
- // 火山引擎支持的模型使用火山引擎 API(非流式)
|
|
|
|
|
- $post_data['stream'] = false;
|
|
|
|
|
- $result = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
-
|
|
|
|
|
- dLog('deepseek')->info('newGenerateText使用火山引擎模型', [
|
|
|
|
|
- 'requested_model' => $model,
|
|
|
|
|
- 'result_keys' => array_keys($result),
|
|
|
|
|
- 'has_fullContent' => isset($result['fullContent']),
|
|
|
|
|
- 'has_content' => isset($result['content'])
|
|
|
|
|
- ]);
|
|
|
|
|
-
|
|
|
|
|
- // 火山引擎返回的数据结构使用 fullContent 和 fullReasoningContent
|
|
|
|
|
- $aiResult = [
|
|
|
|
|
- 'content' => $result['fullContent'] ?? $result['content'] ?? '',
|
|
|
|
|
- 'reasoning_content' => $result['fullReasoningContent'] ?? $result['reasoning_content'] ?? '',
|
|
|
|
|
- 'usage' => $result['usage'] ?? [],
|
|
|
|
|
- 'model' => $model,
|
|
|
|
|
- 'finish_reason' => $result['finish_reason'] ?? 'stop'
|
|
|
|
|
- ];
|
|
|
|
|
- } else {
|
|
|
|
|
- Utils::throwError('20003:不支持的模型: ' . $model);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $aiResult = [
|
|
|
|
|
+ 'content' => $result['fullContent'] ?? $result['content'] ?? '',
|
|
|
|
|
+ 'reasoning_content' => $result['fullReasoningContent'] ?? $result['reasoning_content'] ?? '',
|
|
|
|
|
+ 'usage' => $result['usage'] ?? [],
|
|
|
|
|
+ 'model' => $model,
|
|
|
|
|
+ 'finish_reason' => $result['finish_reason'] ?? 'stop'
|
|
|
|
|
+ ];
|
|
|
} catch (\Exception $e) {
|
|
} catch (\Exception $e) {
|
|
|
// 生成失败,更新任务状态
|
|
// 生成失败,更新任务状态
|
|
|
if ($generateTaskId) {
|
|
if ($generateTaskId) {
|
|
@@ -3358,6 +3285,366 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
return $content;
|
|
return $content;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 流式文生文统一分发:根据模型路由到对应提供商的流式实现
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $post_data 请求参数(含 model / messages / stream 等)
|
|
|
|
|
+ * @return \Generator
|
|
|
|
|
+ */
|
|
|
|
|
+ public function dispatchStreamByModel($post_data) {
|
|
|
|
|
+ // 强制按流式模式分发
|
|
|
|
|
+ $post_data['stream'] = true;
|
|
|
|
|
+
|
|
|
|
|
+ $model = (string)getProp($post_data, 'model', '');
|
|
|
|
|
+
|
|
|
|
|
+ if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
+ // DeepSeek 官方模型
|
|
|
|
|
+ return $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
+ // GPT 模型
|
|
|
|
|
+ return $this->gpt54StreamResponse($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
+ // Gemini 模型
|
|
|
|
|
+ return $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
+ } else if (in_array($model, $this->baidu_glm_text_models)) {
|
|
|
|
|
+ // 百度 AI 网关 GLM 模型
|
|
|
|
|
+ return $this->baiduGLMStreamResponse($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->valid_text_models)) {
|
|
|
|
|
+ // 火山引擎等其他模型
|
|
|
|
|
+ return $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Utils::throwError('20003:不支持的模型: ' . $model);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 非流式文生文统一分发:根据模型路由到对应提供商的非流式实现
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $post_data 请求参数(含 model / messages / stream 等)
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ public function dispatchChatOnlyByModel($post_data) {
|
|
|
|
|
+ // 强制按非流式模式分发
|
|
|
|
|
+ $post_data['stream'] = false;
|
|
|
|
|
+
|
|
|
|
|
+ $model = (string)getProp($post_data, 'model', '');
|
|
|
|
|
+
|
|
|
|
|
+ if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
+ // DeepSeek 官方模型
|
|
|
|
|
+ return $this->chatOnly($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
+ // GPT 模型
|
|
|
|
|
+ return $this->gpt54ChatOnly($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
+ // Gemini 模型
|
|
|
|
|
+ return $this->geminiChatOnly($post_data, $model);
|
|
|
|
|
+ } else if (in_array($model, $this->baidu_glm_text_models)) {
|
|
|
|
|
+ // 百度 AI 网关 GLM 模型
|
|
|
|
|
+ return $this->baiduGLMChatOnly($post_data);
|
|
|
|
|
+ } else if (in_array($model, $this->valid_text_models)) {
|
|
|
|
|
+ // 火山引擎等其他模型
|
|
|
|
|
+ return $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Utils::throwError('20003:不支持的模型: ' . $model);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 百度 AI 网关 GLM 流式实现(OpenAI Chat Completions 协议)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $post_data 请求参数(前端模型名 baidu-glm-5.2 / baidu-glm-5.3)
|
|
|
|
|
+ * @return \Generator
|
|
|
|
|
+ */
|
|
|
|
|
+ private function baiduGLMStreamResponse($post_data) {
|
|
|
|
|
+ $payload = $this->buildBaiduGLMPayload($post_data, true);
|
|
|
|
|
+ $client = new Client(['timeout' => 1800, 'verify' => false]);
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $response = $client->post('https://ai-gateway.baidubce.com/v1/chat/completions', [
|
|
|
|
|
+ 'json' => $payload,
|
|
|
|
|
+ 'headers' => $this->baiduGLMHeaders(),
|
|
|
|
|
+ 'stream' => true,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ $errorDetail = $this->extractBaiduGLMErrorDetail($e);
|
|
|
|
|
+ dLog('deepseek')->error('百度GLM流式请求建立失败: ' . $e->getMessage(), [
|
|
|
|
|
+ 'payload' => $payload,
|
|
|
|
|
+ 'detail' => $errorDetail,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ Utils::throwError('20003:百度GLM流式请求失败: ' . $errorDetail);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $body = $response->getBody();
|
|
|
|
|
+ $buffer = '';
|
|
|
|
|
+ $fullContent = '';
|
|
|
|
|
+ $fullReasoning = '';
|
|
|
|
|
+ $usage = [];
|
|
|
|
|
+
|
|
|
|
|
+ dLog('deepseek')->info('开始读取百度GLM流式响应');
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ while (!$body->eof()) {
|
|
|
|
|
+ $chunk = $body->read(1024);
|
|
|
|
|
+ $buffer .= $chunk;
|
|
|
|
|
+
|
|
|
|
|
+ $lines = explode("\n", $buffer);
|
|
|
|
|
+ $buffer = array_pop($lines);
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($lines as $line) {
|
|
|
|
|
+ $line = trim($line);
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($line)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (strpos($line, 'data: ') !== 0) {
|
|
|
|
|
+ dLog('deepseek')->warning('百度GLM非SSE数据行', ['line' => $line]);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $data = substr($line, 6);
|
|
|
|
|
+
|
|
|
|
|
+ if ($data === '[DONE]') {
|
|
|
|
|
+ dLog('deepseek')->info('百度GLM收到结束标记');
|
|
|
|
|
+ break 2;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $json = json_decode($data, true);
|
|
|
|
|
+
|
|
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
|
|
+ dLog('deepseek')->warning('百度GLM JSON解析错误: ' . json_last_error_msg(), ['data' => $data]);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isset($json['choices'][0]['delta'])) {
|
|
|
|
|
+ $delta = $json['choices'][0]['delta'];
|
|
|
|
|
+
|
|
|
|
|
+ // 思考链内容(兼容 reasoning_content / reasoning 两种字段)
|
|
|
|
|
+ $reasoningDelta = '';
|
|
|
|
|
+ if (isset($delta['reasoning_content']) && is_string($delta['reasoning_content'])) {
|
|
|
|
|
+ $reasoningDelta = $delta['reasoning_content'];
|
|
|
|
|
+ } elseif (isset($delta['reasoning']) && is_string($delta['reasoning'])) {
|
|
|
|
|
+ $reasoningDelta = $delta['reasoning'];
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($reasoningDelta !== '') {
|
|
|
|
|
+ $fullReasoning .= $reasoningDelta;
|
|
|
|
|
+ yield [
|
|
|
|
|
+ 'type' => 'reasoning',
|
|
|
|
|
+ 'content' => $reasoningDelta,
|
|
|
|
|
+ 'full_reasoning' => $fullReasoning,
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 正文内容
|
|
|
|
|
+ if (isset($delta['content']) && is_string($delta['content'])) {
|
|
|
|
|
+ $fullContent .= $delta['content'];
|
|
|
|
|
+ yield [
|
|
|
|
|
+ 'type' => 'content',
|
|
|
|
|
+ 'content' => $delta['content'],
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isset($json['usage'])) {
|
|
|
|
|
+ $usage = $json['usage'];
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ dLog('deepseek')->error('百度GLM解析流式响应失败: ' . $e->getMessage(), ['line' => $line]);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ dLog('deepseek')->error('百度GLM流式读取中断: ' . $e->getMessage());
|
|
|
|
|
+ throw $e;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dLog('deepseek')->info('百度GLM流式读取完成', [
|
|
|
|
|
+ 'content_length' => strlen($fullContent),
|
|
|
|
|
+ 'reasoning_length' => strlen($fullReasoning),
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ yield [
|
|
|
|
|
+ 'type' => 'done',
|
|
|
|
|
+ 'full_content' => $fullContent,
|
|
|
|
|
+ 'full_reasoning' => $fullReasoning,
|
|
|
|
|
+ 'usage' => $usage,
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 百度 AI 网关 GLM 非流式实现(OpenAI Chat Completions 协议)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $post_data 请求参数(前端模型名 baidu-glm-5.2 / baidu-glm-5.3)
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function baiduGLMChatOnly($post_data) {
|
|
|
|
|
+ $payload = $this->buildBaiduGLMPayload($post_data, false);
|
|
|
|
|
+ $client = new Client(['timeout' => 1800, 'verify' => false]);
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $result = $client->post('https://ai-gateway.baidubce.com/v1/chat/completions', [
|
|
|
|
|
+ 'json' => $payload,
|
|
|
|
|
+ 'headers' => $this->baiduGLMHeaders(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $response_arr = json_decode($result->getBody()->getContents(), true);
|
|
|
|
|
+ dLog('deepseek')->info('百度GLM非流式请求完成', ['response' => $response_arr]);
|
|
|
|
|
+
|
|
|
|
|
+ $fullContent = '';
|
|
|
|
|
+ $fullReasoningContent = '';
|
|
|
|
|
+ $usage = isset($response_arr['usage']) ? $response_arr['usage'] : [];
|
|
|
|
|
+
|
|
|
|
|
+ if (isset($response_arr['choices'][0]['message'])) {
|
|
|
|
|
+ $message = $response_arr['choices'][0]['message'];
|
|
|
|
|
+ if (isset($message['content']) && is_string($message['content'])) {
|
|
|
|
|
+ $fullContent = $message['content'];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isset($message['reasoning_content']) && is_string($message['reasoning_content'])) {
|
|
|
|
|
+ $fullReasoningContent = $message['reasoning_content'];
|
|
|
|
|
+ } elseif (isset($message['reasoning']) && is_string($message['reasoning'])) {
|
|
|
|
|
+ $fullReasoningContent = $message['reasoning'];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'fullContent' => $fullContent,
|
|
|
|
|
+ 'fullReasoningContent' => $fullReasoningContent,
|
|
|
|
|
+ 'usage' => $usage,
|
|
|
|
|
+ ];
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ $errorDetail = $this->extractBaiduGLMErrorDetail($e);
|
|
|
|
|
+ dLog('deepseek')->error('百度GLM非流式请求失败: ' . $e->getMessage(), [
|
|
|
|
|
+ 'payload' => $payload,
|
|
|
|
|
+ 'detail' => $errorDetail,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ Utils::throwError('20003:百度GLM请求失败: ' . $errorDetail);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 组装百度 AI 网关 GLM 请求参数
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $data 请求参数
|
|
|
|
|
+ * @param bool $stream 是否流式
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function buildBaiduGLMPayload(array $data, bool $stream): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty(env('BAIDU_GLM_AK'))) {
|
|
|
|
|
+ Utils::throwError('20003:百度GLM API Key未配置,请检查环境变量BAIDU_GLM_AK');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $frontModel = (string)getProp($data, 'model', '');
|
|
|
|
|
+ $externalModel = isset(BaseConst::BAIDU_GLM_MODEL_MAP[$frontModel])
|
|
|
|
|
+ ? BaseConst::BAIDU_GLM_MODEL_MAP[$frontModel]
|
|
|
|
|
+ : '';
|
|
|
|
|
+ if ($externalModel === '') {
|
|
|
|
|
+ Utils::throwError('20003:不支持的百度GLM模型: ' . $frontModel);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $messages = getProp($data, 'messages', []);
|
|
|
|
|
+ if (empty($messages)) {
|
|
|
|
|
+ Utils::throwError('20003:请提供有效的对话内容');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // OpenAI Chat Completions 标准参数白名单。
|
|
|
|
|
+ // 注意:百度 GLM-5.x 始终思考,不支持 thinking 开关(传 disabled 会报 400),
|
|
|
|
|
+ // 因此不转发 thinking;仅透传网关原生支持的 reasoning_effort(low/high/max)。
|
|
|
|
|
+ $allowedKeys = [
|
|
|
|
|
+ 'temperature',
|
|
|
|
|
+ 'top_p',
|
|
|
|
|
+ 'max_tokens',
|
|
|
|
|
+ 'max_completion_tokens',
|
|
|
|
|
+ 'reasoning_effort',
|
|
|
|
|
+ 'frequency_penalty',
|
|
|
|
|
+ 'presence_penalty',
|
|
|
|
|
+ 'stop',
|
|
|
|
|
+ 'response_format',
|
|
|
|
|
+ 'stream_options',
|
|
|
|
|
+ 'tools',
|
|
|
|
|
+ 'tool_choice',
|
|
|
|
|
+ 'user',
|
|
|
|
|
+ 'seed',
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ $payload = [
|
|
|
|
|
+ 'model' => $externalModel,
|
|
|
|
|
+ 'messages' => $messages,
|
|
|
|
|
+ 'stream' => $stream,
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($allowedKeys as $key) {
|
|
|
|
|
+ if (array_key_exists($key, $data) && $data[$key] !== null && $data[$key] !== '') {
|
|
|
|
|
+ $payload[$key] = $data[$key];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 百度网关只接受 low / high / max;其它取值(如 none)会导致 400
|
|
|
|
|
+ if (isset($payload['reasoning_effort']) && !in_array($payload['reasoning_effort'], ['low', 'high', 'max'], true)) {
|
|
|
|
|
+ unset($payload['reasoning_effort']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($stream && !isset($payload['stream_options'])) {
|
|
|
|
|
+ $payload['stream_options'] = ['include_usage' => true];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!isset($payload['max_tokens']) && !isset($payload['max_completion_tokens'])) {
|
|
|
|
|
+ // GLM-5.x 输出上限较高,给长文生成留足空间
|
|
|
|
|
+ $payload['max_tokens'] = 100000;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $payload;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 百度 AI 网关 GLM 鉴权请求头
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function baiduGLMHeaders(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'Authorization' => 'Bearer ' . env('BAIDU_GLM_AK'),
|
|
|
|
|
+ 'Content-Type' => 'application/json; charset=UTF-8',
|
|
|
|
|
+ 'Accept' => 'text/event-stream',
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从 Guzzle 异常响应体中提取百度 AI 网关返回的错误信息
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param \Exception $e
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ private function extractBaiduGLMErrorDetail(\Exception $e): string
|
|
|
|
|
+ {
|
|
|
|
|
+ $detail = $e->getMessage();
|
|
|
|
|
+
|
|
|
|
|
+ if ($e instanceof \GuzzleHttp\Exception\BadResponseException && $e->getResponse()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ $responseBody = (string)$e->getResponse()->getBody();
|
|
|
|
|
+ $decoded = json_decode($responseBody, true);
|
|
|
|
|
+ if (is_array($decoded)) {
|
|
|
|
|
+ if (isset($decoded['error']['message']) && $decoded['error']['message'] !== '') {
|
|
|
|
|
+ $detail = $decoded['error']['message'];
|
|
|
|
|
+ } elseif (isset($decoded['message']) && $decoded['message'] !== '') {
|
|
|
|
|
+ $detail = $decoded['message'];
|
|
|
|
|
+ } elseif (isset($decoded['error']) && is_string($decoded['error'])) {
|
|
|
|
|
+ $detail = $decoded['error'];
|
|
|
|
|
+ }
|
|
|
|
|
+ } elseif ($responseBody !== '') {
|
|
|
|
|
+ $detail = $responseBody;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (\Throwable $parseError) {
|
|
|
|
|
+ // 保留原始异常信息
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return mb_substr($detail, 0, 500);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private function deepSeekStreamResponse($post_data) {
|
|
private function deepSeekStreamResponse($post_data) {
|
|
|
// 设置最大输出tokens
|
|
// 设置最大输出tokens
|
|
|
$post_data['max_tokens'] = 300000;
|
|
$post_data['max_tokens'] = 300000;
|
|
@@ -3870,16 +4157,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $chatResult = $this->chatOnly($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $chatResult = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $chatResult = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $chatResult = $this->dispatchChatOnlyByModel($post_data);
|
|
|
|
|
|
|
|
if (is_array($chatResult)) {
|
|
if (is_array($chatResult)) {
|
|
|
$fullContent = $chatResult['fullContent'];
|
|
$fullContent = $chatResult['fullContent'];
|
|
@@ -4887,19 +5165,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$fullReasoningContent = '';
|
|
$fullReasoningContent = '';
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 处理流式输出
|
|
// 处理流式输出
|
|
|
foreach ($streamGenerator as $chunk) {
|
|
foreach ($streamGenerator as $chunk) {
|
|
@@ -5186,19 +5452,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$fullReasoningContent = '';
|
|
$fullReasoningContent = '';
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 处理流式输出
|
|
// 处理流式输出
|
|
|
foreach ($streamGenerator as $chunk) {
|
|
foreach ($streamGenerator as $chunk) {
|
|
@@ -5418,16 +5672,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $chatResult = $this->chatOnly($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $chatResult = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $chatResult = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $chatResult = $this->dispatchChatOnlyByModel($post_data);
|
|
|
|
|
|
|
|
if (is_array($chatResult)) {
|
|
if (is_array($chatResult)) {
|
|
|
$fullContent = $chatResult['fullContent'];
|
|
$fullContent = $chatResult['fullContent'];
|
|
@@ -6340,19 +6585,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -7209,17 +7442,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
// dd($post_data);
|
|
// dd($post_data);
|
|
|
// dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
|
|
// dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -8092,19 +8315,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -8944,19 +9155,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -9269,15 +9468,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$post_data['messages'] = $messages;
|
|
$post_data['messages'] = $messages;
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
|
$fullReasoningContent = '';
|
|
$fullReasoningContent = '';
|
|
@@ -10362,17 +10553,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
// dd($post_data);
|
|
// dd($post_data);
|
|
|
// dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
|
|
// dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -10611,15 +10792,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$post_data['messages'] = $messages;
|
|
$post_data['messages'] = $messages;
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
|
$fullReasoningContent = '';
|
|
$fullReasoningContent = '';
|
|
@@ -11989,19 +12162,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 验证返回值类型
|
|
// 验证返回值类型
|
|
|
if (!is_iterable($streamGenerator)) {
|
|
if (!is_iterable($streamGenerator)) {
|
|
@@ -12208,16 +12369,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
|
|
|
|
|
// 重新调用API
|
|
// 重新调用API
|
|
|
try {
|
|
try {
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- $streamGenerator = $this->deepSeekStreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- $streamGenerator = $this->gpt54StreamResponse($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gemini_text_models)) {
|
|
|
|
|
- // Gemini 模型使用 Gemini API
|
|
|
|
|
- $streamGenerator = $this->geminiStreamResponse($post_data, $model);
|
|
|
|
|
- } else {
|
|
|
|
|
- $streamGenerator = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
|
|
// 处理流式输出
|
|
// 处理流式输出
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
@@ -13686,16 +13838,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
// 根据模型类型选择调用方法
|
|
// 根据模型类型选择调用方法
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $chatResult = $this->chatOnly($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT 模型使用 TokenRouter API
|
|
|
|
|
- $chatResult = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $chatResult = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $chatResult = $this->dispatchChatOnlyByModel($post_data);
|
|
|
|
|
|
|
|
if (is_array($chatResult)) {
|
|
if (is_array($chatResult)) {
|
|
|
$fullContent = $chatResult['fullContent'] ?? '';
|
|
$fullContent = $chatResult['fullContent'] ?? '';
|
|
@@ -16012,16 +16155,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
'stream' => false // 是否启用流式输出
|
|
'stream' => false // 是否启用流式输出
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $chatResult = $this->chatOnly($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $chatResult = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $chatResult = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $chatResult = $this->dispatchChatOnlyByModel($post_data);
|
|
|
if (is_array($chatResult)) {
|
|
if (is_array($chatResult)) {
|
|
|
extract($chatResult);
|
|
extract($chatResult);
|
|
|
}else {
|
|
}else {
|
|
@@ -16569,16 +16703,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$fullContent = '';
|
|
$fullContent = '';
|
|
|
$usage = [];
|
|
$usage = [];
|
|
|
|
|
|
|
|
- if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
|
|
|
|
|
- // DeepSeek 官方模型使用 DeepSeek API
|
|
|
|
|
- $chatResult = $this->chatOnly($post_data);
|
|
|
|
|
- } else if (in_array($model, $this->gpt_text_models)) {
|
|
|
|
|
- // GPT-5.4 模型使用 TokenRouter API
|
|
|
|
|
- $chatResult = $this->gpt54ChatOnly($post_data);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 其他模型使用火山引擎API
|
|
|
|
|
- $chatResult = $this->volcEngineChatCompletion($post_data);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $chatResult = $this->dispatchChatOnlyByModel($post_data);
|
|
|
|
|
|
|
|
if (is_array($chatResult)) {
|
|
if (is_array($chatResult)) {
|
|
|
$fullContent = $chatResult['fullContent'];
|
|
$fullContent = $chatResult['fullContent'];
|
|
@@ -16685,6 +16810,12 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
*/
|
|
*/
|
|
|
public function volcEngineChatCompletion(array $params)
|
|
public function volcEngineChatCompletion(array $params)
|
|
|
{
|
|
{
|
|
|
|
|
+ // 百度 GLM 已由 dispatchStreamByModel / dispatchChatOnlyByModel 统一分发,此处不再转发
|
|
|
|
|
+ $frontModel = getProp($params, 'model', '');
|
|
|
|
|
+ if (in_array($frontModel, $this->baidu_glm_text_models, true)) {
|
|
|
|
|
+ Utils::throwError('20003:百度GLM模型请使用统一分发方法dispatchStreamByModel/dispatchChatOnlyByModel调用');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$apiKey = env('VOLC_AI_API_KEY');
|
|
$apiKey = env('VOLC_AI_API_KEY');
|
|
|
|
|
|
|
|
if (empty($apiKey)) {
|
|
if (empty($apiKey)) {
|