ai-chat-ui/docs/CHANGELOG-2026-03-06.md

7.2 KiB
Raw Blame History

开发日志 - 2026-03-06

修复:深度思考内容不显示

问题描述

启用深度思考后,后端日志显示已启用深度思考功能,但前端没有显示深度思考内容。

根本原因

前端 src/services/api.ts 中的 streamChat 方法只处理了普通 content,完全忽略了后端返回的 reasoning_content(深度思考内容)。

解决方案

1. 前端 src/services/api.ts

添加 StreamChunk 接口,区分内容类型:

// 流式响应块类型
export interface StreamChunk {
  type: "content" | "reasoning";
  text: string;
}

修改 streamChat 方法同时处理两种内容:

const delta = data.choices?.[0]?.delta;

// 处理深度思考内容reasoning_content
const reasoningContent = delta?.reasoning_content;
if (reasoningContent) {
  yield { type: "reasoning", text: reasoningContent };
}

// 处理普通内容
const content = delta?.content;
if (content) {
  yield { type: "content", text: content };
}

2. 前端 src/components/chat/ChatMain.vue

修改流式处理逻辑,将 reasoning 类型内容包装成 <think> 标签:

let isInReasoning = false;

for await (const chunk of stream) {
  if (chunk.type === "reasoning") {
    if (!isInReasoning) {
      isInReasoning = true;
      fullText += "<think>\n";
    }
    fullText += chunk.text;
  } else {
    if (isInReasoning) {
      isInReasoning = false;
      fullText += "\n</think>\n";
    }
    fullText += chunk.text;
  }
}

// 如果最后还在深度思考块中,关闭它
if (isInReasoning) {
  fullText += "\n</think>";
}

<think> 标签会被 markstream-vue 库识别,并由 ThinkingNode 组件渲染。


功能:图片/文件附件自动切换模型

需求

当用户上传图片或文件PDF、DOCX等无论前端选择了什么模型后端都应强制使用 glm-4.6v 模型(支持多模态)。

解决方案

后端 server/adapters/glm_adapter.py

修改 _build_messages 方法

返回值从 (messages, has_vision) 改为 (messages, has_vision, has_files)

def _build_messages(
    self, request: ChatCompletionRequest
) -> tuple[List[Dict], bool, bool]:
    """
    构建 GLM 格式的消息
    返回:(消息列表, 是否包含图片, 是否包含文件附件)
    """
    messages = []
    has_vision = False
    has_files = bool(request.files)  # 检查是否有文件附件
    # ... 处理消息 ...
    return messages, has_vision, has_files

修改 _resolve_model 方法

def _resolve_model(self, model: str, has_vision: bool, has_files: bool = False) -> str:
    """解析实际使用的模型"""
    model_lower = model.lower()
    # 如果有图片或文件附件,强制使用 glm-4.6v(支持多模态)
    if (has_vision or has_files) and model_lower not in VISION_MODELS:
        logger.info(
            f"[GLM] 检测到图片或文件附件,强制切换模型: {model} -> glm-4.6v"
        )
        return "glm-4.6v"
    return model

修改 chat 方法调用

glm_messages, has_vision, has_files = self._build_messages(request)
actual_model = self._resolve_model(request.model, has_vision, has_files)

功能DeepSeek 深度思考支持

需求

为 DeepSeek 的 deepseek-reasoner 模型添加深度思考支持,通过 extra_body 参数启用。

解决方案

后端 server/adapters/openai_adapter.py

添加支持深度思考的模型列表

# DeepSeek 支持深度思考的模型
DEEPSEEK_THINKING_MODELS = {"deepseek-reasoner"}

修改 chat 方法

# DeepSeek 深度思考支持
extra_body = None
if self._provider_type == "deepseek" and request.deep_thinking:
    if self._supports_thinking(request.model):
        extra_body = {"thinking": {"type": "enabled"}}
        kwargs["extra_body"] = extra_body
        logger.info(f"[{provider_name}] 深度思考已启用: extra_body = {extra_body}")

添加 _supports_thinking 方法

def _supports_thinking(self, model: str) -> bool:
    """检查模型是否支持深度思考"""
    return model.lower() in DEEPSEEK_THINKING_MODELS

修改 _stream_chat_sync_chat 方法

  • 添加 extra_body 参数
  • 增强 reasoning_content 日志输出

功能:模型列表从后端动态获取

需求

前端模型选择器中的模型列表改为从后端 API 获取,而非硬编码。

解决方案

前端 src/services/api.ts

修改 getModels 方法,调用后端 API

async getModels(): Promise<ModelInfo[]> {
  try {
    const response = await fetch(`${this.baseUrl}${API_ENDPOINTS.MODELS}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });

    if (!response.ok) {
      throw new Error(`获取模型列表失败: HTTP ${response.status}`);
    }

    const data = await response.json();
    // 后端返回格式: { object: "list", data: [...] }
    return data.data || [];
  } catch (error) {
    console.error("获取模型列表失败:", error);
    // 返回默认模型列表作为降级
    return [...];
  }
}

后端 server/main.py

已有 /api/chat-ui/models 端点:

@app.get("/api/chat-ui/models")
async def get_models():
    """模型列表(聚合所有可用平台的模型)"""
    from adapters import get_all_adapters

    all_models = []
    for provider, adapter in get_all_adapters().items():
        if adapter.is_available():
            models = adapter.list_models()
            all_models.extend([m.to_dict() for m in models])

    return {"object": "list", "data": all_models}

特点

  • 动态聚合:自动聚合所有已配置 API Key 的平台模型
  • 按需显示:只有配置了 API Key 的平台才会显示模型
  • 降级处理API 获取失败时返回默认模型列表

涉及文件

文件 修改类型
src/services/api.ts 新增 StreamChunk 接口,修改 streamChat 方法,修改 getModels 方法
src/components/chat/ChatMain.vue 修改流式处理逻辑,支持 reasoning 类型
server/adapters/glm_adapter.py 修改 _build_messages_resolve_model 方法
server/adapters/openai_adapter.py 添加 DeepSeek 深度思考支持

测试建议

  1. GLM 深度思考测试

    • 选择支持深度思考的模型(如 glm-4.6v
    • 开启深度思考开关
    • 发送问题,确认前端显示深度思考内容块
  2. DeepSeek 深度思考测试

    • 选择 deepseek-reasoner 模型
    • 开启深度思考开关
    • 发送问题,确认后端日志显示 extra_body = {'thinking': {'type': 'enabled'}}
    • 确认前端显示深度思考内容块
  3. 模型自动切换测试

    • 选择非多模态模型(如 glm-4-flash
    • 上传图片或 PDF 文件
    • 确认后端日志显示模型切换为 glm-4.6v
    • 确认多模态内容正确处理
  4. 模型列表动态获取测试

    • 检查前端控制台,确认调用了 /api/chat-ui/models
    • 确认模型选择器显示后端返回的模型列表
    • 停止后端服务,确认降级模型列表正常显示