feat: 同步知识库与工作台相关改动

This commit is contained in:
Jackzhou
2026-08-24 10:40:15 +08:00
parent 8d0588827d
commit 4f33b036d1
50 changed files with 8034 additions and 273 deletions
+103 -12
View File
@@ -44,12 +44,12 @@ type ChatResult struct {
// Client 低层 HTTP 客户端(基于 RouteConfig)
type Client struct {
baseURL string
apiKey string
model string
maxTokens int
baseURL string
apiKey string
model string
maxTokens int
temperature float64
hc *http.Client
hc *http.Client
}
// NewClient 从 RouteConfig 创建客户端
@@ -100,7 +100,45 @@ func (c *Client) post(path string, body any) (*http.Response, error) {
for k, v := range c.headers() {
req.Header.Set(k, v)
}
return c.hc.Do(req)
// #region debug-point C:llm-post
if payload, err := json.Marshal(map[string]any{
"sessionId": "knowledge-chat-401",
"runId": "pre-fix",
"hypothesisId": "C",
"location": "backend-go/internal/ai/llm.go:Client.post:request",
"msg": "[DEBUG] llm client request",
"data": map[string]any{
"url": c.url(path),
"model": c.model,
"hasAPIKey": c.apiKey != "",
"authHeader": req.Header.Get("Authorization") != "",
},
"ts": time.Now().UnixMilli(),
}); err == nil {
go http.Post("http://127.0.0.1:7777/event", "application/json", strings.NewReader(string(payload)))
}
// #endregion
resp, err := c.hc.Do(req)
if err != nil {
return nil, err
}
// #region debug-point C:llm-response
if payload, err := json.Marshal(map[string]any{
"sessionId": "knowledge-chat-401",
"runId": "pre-fix",
"hypothesisId": "C",
"location": "backend-go/internal/ai/llm.go:Client.post:response",
"msg": "[DEBUG] llm client response",
"data": map[string]any{
"url": c.url(path),
"status": resp.StatusCode,
},
"ts": time.Now().UnixMilli(),
}); err == nil {
go http.Post("http://127.0.0.1:7777/event", "application/json", strings.NewReader(string(payload)))
}
// #endregion
return resp, nil
}
// ──────────────────────────────────────────────
@@ -222,6 +260,24 @@ func (c *Client) GenerateStream(messages []Message, onChunk func(string)) error
if resp.StatusCode != http.StatusOK {
data, _ := io.ReadAll(resp.Body)
// #region debug-point C:llm-non200
if payload, err := json.Marshal(map[string]any{
"sessionId": "knowledge-chat-401",
"runId": "pre-fix",
"hypothesisId": "C",
"location": "backend-go/internal/ai/llm.go:GenerateStream:non200",
"msg": "[DEBUG] llm stream non-200",
"data": map[string]any{
"status": resp.StatusCode,
"bodyPreview": truncate(string(data), 240),
"model": c.model,
"baseURL": c.baseURL,
},
"ts": time.Now().UnixMilli(),
}); err == nil {
go http.Post("http://127.0.0.1:7777/event", "application/json", strings.NewReader(string(payload)))
}
// #endregion
return fmt.Errorf("LLM 返回 %d: %s", resp.StatusCode, truncate(string(data), 200))
}
@@ -335,6 +391,41 @@ func GenerateFullWithFallback(primary *config.RouteConfig, messages []Message) (
return nil, nil, fmt.Errorf("所有路由均失败: %w", lastErr)
}
// GenerateStreamWithFallback 流式 + 回退链:返回实际命中的路由
func GenerateStreamWithFallback(primary *config.RouteConfig, messages []Message, onChunk func(string)) (*config.RouteConfig, error) {
chain := []*config.RouteConfig{primary}
if fallbacks, err := config.GetFallbackRoutes(primary.RouteID); err == nil && len(fallbacks) > 0 {
chain = append(chain, fallbacks...)
}
var lastErr error
for _, route := range chain {
if requiresAPIKey(route) && strings.TrimSpace(route.APIKey) == "" {
lastErr = fmt.Errorf("[%s] 未配置 API Key", route.RouteID)
continue
}
client := NewClient(route)
if err := client.GenerateStream(messages, onChunk); err == nil {
return route, nil
} else {
lastErr = fmt.Errorf("[%s] %w", route.RouteID, err)
}
}
return nil, fmt.Errorf("所有路由均失败: %w", lastErr)
}
func requiresAPIKey(route *config.RouteConfig) bool {
if route == nil {
return false
}
baseURL := strings.ToLower(strings.TrimSpace(route.BaseURL))
if strings.Contains(baseURL, "openrouter.ai") || strings.Contains(baseURL, "openai.com") {
return true
}
provider := strings.ToLower(strings.TrimSpace(route.Provider))
return provider == "openrouter" || provider == "openai"
}
// ──────────────────────────────────────────────
// 配置解析(兼容旧接口)
// ──────────────────────────────────────────────
@@ -375,11 +466,11 @@ func ResolveLLM(cfg *config.Config) (LLMConfig, bool) {
}
c := LLMConfig{
BaseURL: baseURL,
APIKey: apiKey,
Model: modelName,
EmbedModel: embedModel,
MaxTokens: 2048,
BaseURL: baseURL,
APIKey: apiKey,
Model: modelName,
EmbedModel: embedModel,
MaxTokens: 2048,
Temperature: 0.7,
}
if c.BaseURL == "" || c.Model == "" {
@@ -394,4 +485,4 @@ func truncate(s string, n int) string {
return s
}
return string(r[:n]) + "..."
}
}