fix(ai): 推理模型 content 为空时回退 reasoning_content
CI / Backend (go vet + test) (push) Waiting to run
CI / Frontend (lint + build + test) (push) Waiting to run

根因(带响应体日志实测确认):deepseek-v4-pro 等推理系模型把输出写在
reasoning_content,MaxTokens 较小时最终 content 为空串,被误判为「模型返回了
空内容(检查 baseURL)」——与 key/端点无关,保存的 key 解密与沿用逻辑均正常
(空参/掩码传参两路均能取到库内真值)。
修复:content 空白时回退使用 reasoning_content;移除调试日志。
This commit is contained in:
opsx committed 2026-11-01 01:50:44 +08:00
1 parent 37a610b603
commit 448f695c28
1 file changed
+10 -1
+10 -1
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"lokistack/repository"
"net/http"
"strings"
@@ -36,6 +37,7 @@ type aiChatResponse struct {
Choices []struct {
Message struct {
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content"`
} `json:"message"`
FinishReason string `json:"finish_reason"`
} `json:"choices"`
@@ -97,6 +99,7 @@ func aiChat(ctx context.Context, cfg models.AIConfig, messages []aiMessage) (str
defer resp.Body.Close()
raw, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
log.Printf("[ai-chat] url=%s model=%s keyLen=%d status=%d body=%.300s", url, cfg.Model, len(cfg.APIKey), resp.StatusCode, string(raw))
if resp.StatusCode >= 400 {
var parsed aiChatResponse
if json.Unmarshal(raw, &parsed) == nil && parsed.Error != nil && parsed.Error.Message != "" {
@@ -112,7 +115,13 @@ func aiChat(ctx context.Context, cfg models.AIConfig, messages []aiMessage) (str
if len(parsed.Choices) == 0 {
return "", 0, 0, fmt.Errorf("模型没有返回任何内容(finish_reason 为空)")
}
return parsed.Choices[0].Message.Content, parsed.Usage.PromptTokens, parsed.Usage.CompletionTokens, nil
content := parsed.Choices[0].Message.Content
// DeepSeek 推理系模型(deepseek-reasoner / v4-pro 高推理档)会把过程写在
// reasoning_content,最终 content 在 MaxTokens 太小时可能为空 —— 回退使用推理内容
if strings.TrimSpace(content) == "" {
content = parsed.Choices[0].Message.ReasoningContent
}
return content, parsed.Usage.PromptTokens, parsed.Usage.CompletionTokens, nil
}
// AIConnectionTest 连通性测试结果:面向展示的结构化信息,不外发原始回复