Просмотр исходного кода

1.新增百度版glm-5.2和glm-5.3大模型2.新增公共调用方法,分发大模型到指定请求接口

lh 1 неделя назад
Родитель
Сommit
834b068377
2 измененных файлов с 406 добавлено и 268 удалено
  1. 7 0
      app/Consts/BaseConst.php
  2. 399 268
      app/Services/DeepSeek/DeepSeekService.php

+ 7 - 0
app/Consts/BaseConst.php

@@ -93,6 +93,13 @@ class BaseConst
         'gemini-3.1-flash-image-preview-t',
         'gemini-3.6-flash'
     ];
+    // 百度 AI 网关 GLM 文生文模型(前端入参名)
+    const BAIDU_GLM_TEXT_MODELS = ['baidu-glm-5.2', 'baidu-glm-5.3'];
+    // 百度 AI 网关 GLM 模型映射:前端名 -> 网关真实模型名
+    const BAIDU_GLM_MODEL_MAP = [
+        'baidu-glm-5.2' => 'glm-5.2',
+        'baidu-glm-5.3' => 'glm-5.3',
+    ];
     // 火山写作奖励计划接入点(使用该接入点可在第二天根据前一天使用量获取免费额度)
     const MODELS_MAP = [
         'doubao-seed-2-0-pro-260215'        => 'ep-20260422093628-pv5vj',

+ 399 - 268
app/Services/DeepSeek/DeepSeekService.php

@@ -33,6 +33,7 @@ class DeepSeekService
     private $valid_text_models;
     private $gpt_text_models;
     private $gemini_text_models;
+    private $baidu_glm_text_models;
     protected $aiImageGenerationService;
     protected $pointsService;
 
@@ -51,6 +52,8 @@ class DeepSeekService
         $this->gpt_text_models = BaseConst::GPT_TEXT_MODELS;
         // Gemini文本模型列表
         $this->gemini_text_models = BaseConst::GEMINI_TEXT_MODELS;
+        // 百度 AI 网关 GLM 文本模型列表
+        $this->baidu_glm_text_models = BaseConst::BAIDU_GLM_TEXT_MODELS;
         $this->sys_message = [
                 'role'    => 'system',
                 'content' => "你是一个专业的文档分析助手及资深编剧,请根据用户提供的文档内容完成示例格式的内容输出(需通过以下几个板块进行回复: <故事梗概><剧本亮点><人物关系><核心矛盾><主体列表><美术风格><场景列表><分集剧本>,每个板块之间必须使用###分隔,#不能多也不能少;同时板块之间需满足以下要求:\n
@@ -315,22 +318,8 @@ class DeepSeekService
             $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) {
             return $this->wrapGenerateTextCharge($streamGenerator, $uid, $model, $chargePoints, $chargeModality);
@@ -982,18 +971,8 @@ class DeepSeekService
             $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 时更新任务状态、扣费并保存对话记录
         return $this->wrapNewGenerateTextStream($streamGenerator, [
@@ -1696,72 +1675,20 @@ class DeepSeekService
             $this->pointsService->checkUserPointsEnough($this->pointsService->getChatChargePoints((string)$model), $uid);
         }
 
-        // 根据模型类型选择调用方法(复用现有的chatOnly方法)
+        // 统一分模型调用非流式实现
         try {
             $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) {
             // 生成失败,更新任务状态
             if ($generateTaskId) {
@@ -3358,6 +3285,366 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         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) {
         // 设置最大输出tokens
         $post_data['max_tokens'] = 300000;
@@ -3870,16 +4157,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $fullContent = '';
         $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)) {
             $fullContent = $chatResult['fullContent'];
@@ -4887,19 +5165,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $fullReasoningContent = '';
         $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) {
@@ -5186,19 +5452,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $fullReasoningContent = '';
         $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) {
@@ -5418,16 +5672,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $fullContent = '';
         $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)) {
             $fullContent = $chatResult['fullContent'];
@@ -6340,19 +6585,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $usage = [];
         
         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)) {
@@ -7209,17 +7442,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         // dd($post_data);
         // dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
         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)) {
@@ -8092,19 +8315,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $usage = [];
         
         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)) {
@@ -8944,19 +9155,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $usage = [];
         
         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)) {
@@ -9269,15 +9468,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                 $post_data['messages'] = $messages;
 
                 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 = '';
                     $fullReasoningContent = '';
@@ -10362,17 +10553,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         // dd($post_data);
         // dLog('deepseek')->info('请求参数: '.json_encode($post_data, 256));
         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)) {
@@ -10611,15 +10792,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                 $post_data['messages'] = $messages;
 
                 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 = '';
                     $fullReasoningContent = '';
@@ -11989,19 +12162,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $usage = [];
         
         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)) {
@@ -12208,16 +12369,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
 
             // 重新调用API
             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 = '';
@@ -13686,16 +13838,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             $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)) {
                 $fullContent = $chatResult['fullContent'] ?? '';
@@ -16012,16 +16155,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             '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)) {
             extract($chatResult);
         }else {
@@ -16569,16 +16703,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $fullContent = '';
         $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)) {
             $fullContent = $chatResult['fullContent'];
@@ -16685,6 +16810,12 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
      */
     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');
         
         if (empty($apiKey)) {