feat: LLM 调用日志 + ModelSelector 优化 + devtools.bat 编码修复
- 新增 call_log.go: 全局环形缓冲区记录每次 LLM 调用(模型/Token/耗时/错误) - OpenAIProvider.doChat/ChatStreamWithTools 自动记录调用日志 - ai-core 暴露 GET /api/v1/llm-calls 端点, DevTools 代理 + UI 面板 - ModelSelector.envProvider 改为单例缓存, 避免重复创建 HTTP Client - 新增 PurposeToolCalling 适配器, 后台思考工具调用走专用路由 - envFallback 超时 120s→180s, 显式设置 MaxRetries - devtools.bat 全英文, 解决 Windows CMD GBK 编码乱码问题 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -67,7 +67,8 @@ func main() {
|
||||
APIKey: cfg.LLMAPIKey,
|
||||
Model: cfg.LLMModel,
|
||||
FallbackModel: cfg.LLMFallbackModel,
|
||||
Timeout: 120 * time.Second,
|
||||
MaxRetries: 3,
|
||||
Timeout: 180 * time.Second,
|
||||
}
|
||||
|
||||
// 创建 ModelSelector (优先使用 models.json,回退到 .env)
|
||||
@@ -82,10 +83,12 @@ func main() {
|
||||
thinkerAdapter := llm.NewAdapter(provider)
|
||||
provider, _ = modelSelector.Select(context.Background(), llm.PurposeMemoryExtraction)
|
||||
memoryAdapter := llm.NewAdapter(provider)
|
||||
provider, _ = modelSelector.Select(context.Background(), llm.PurposeToolCalling)
|
||||
toolAdapter := llm.NewAdapter(provider)
|
||||
|
||||
if configLoader != nil && configLoader.HasConfig() {
|
||||
log.Printf("LLM适配器已就绪: models.json 驱动 (chat=%s, intent=%s, think=%s, memory=%s)",
|
||||
chatAdapter.ModelName(), intentAdapter.ModelName(), thinkerAdapter.ModelName(), memoryAdapter.ModelName())
|
||||
log.Printf("LLM适配器已就绪: models.json 驱动 (chat=%s, intent=%s, think=%s, memory=%s, tool=%s)",
|
||||
chatAdapter.ModelName(), intentAdapter.ModelName(), thinkerAdapter.ModelName(), memoryAdapter.ModelName(), toolAdapter.ModelName())
|
||||
} else {
|
||||
log.Printf("LLM适配器已就绪: .env 驱动 (模型=%s)", chatAdapter.ModelName())
|
||||
}
|
||||
@@ -193,6 +196,7 @@ func main() {
|
||||
personaLoader,
|
||||
memRetriever,
|
||||
thinkerAdapter,
|
||||
toolAdapter,
|
||||
iotClient,
|
||||
memStore,
|
||||
toolRegistry,
|
||||
@@ -311,6 +315,22 @@ func main() {
|
||||
w.Write([]byte(`{"status":"ok","service":"ai-core","model":"` + chatAdapter.ModelName() + `"}`))
|
||||
})
|
||||
|
||||
// LLM 调用日志(调试用)
|
||||
mux.HandleFunc("/api/v1/llm-calls", func(w http.ResponseWriter, r *http.Request) {
|
||||
limit := 50
|
||||
if n, err := fmt.Sscanf(r.URL.Query().Get("limit"), "%d", &limit); n != 1 || err != nil || limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
if limit > 500 {
|
||||
limit = 500
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"calls": llm.GetCalls(limit),
|
||||
"total": len(llm.GetCalls(0)),
|
||||
})
|
||||
})
|
||||
|
||||
// 启动HTTP服务
|
||||
srv := &http.Server{
|
||||
Addr: ":" + cfg.Port,
|
||||
|
||||
Reference in New Issue
Block a user