feat(llm): 每个 LLM 配置支持自定义会话头

新增 session_header_key:非空时每次 LLM 请求带上该 HTTP 头,头值为当前
运行的 session id(chat 会话=conv-<id>,worker=exp<x>-worker-i<intent>
等)。用于某些按 session-id 头做提示缓存/粘性路由的网关。

实现:在已有的 quotaAwareTransport 里从请求 context 读取 session id
(transcript.WithSessionID 挂上的)并注入,无需改 norma;同一共享 provider
也能按会话发出不同头值。DB 加 session_header_key 列(带旧库迁移),前端
LLM 配置弹窗新增输入框。
This commit is contained in:
Autumn-27 committed 2026-09-07 11:21:50 -04:00
1 parent b513b656aa
commit 4319fe413f
10 files changed
+166 -36

No files matched your search

+22 -18
View File
@@ -587,28 +587,32 @@ type LLMProfileDTO struct {
// (''=max_tokens | 'max_completion_tokens',仅 openai 格式有意义)。
MaxTokens int `json:"max_tokens"`
MaxTokensField string `json:"max_tokens_field"`
// 自定义会话头名:非空时每次请求带该 HTTP 头,头值=当前会话/意图的 session id。
// ''=不发送。用于按 session-id 头做提示缓存/粘性路由的网关。
SessionHeaderKey string `json:"session_header_key"`
}
func llmProfileDTO(p *db.LLMProfile) LLMProfileDTO {
return LLMProfileDTO{
ID: i64s(p.ID),
Name: p.Name,
Format: p.Format,
BaseURL: p.BaseURL,
Proxy: p.Proxy,
Model: p.Model,
APIKeyHint: p.APIKeyHint,
RatePerSecond: p.RatePerSecond,
RatePerMinute: p.RatePerMinute,
ContextWindowK: p.ContextWindowK,
ThinkingType: p.ThinkingType,
ReasoningEffort: p.ReasoningEffort,
IsDefault: p.IsDefault,
Priority: p.Priority,
PoolExclude: p.PoolExclude,
Streaming: p.Streaming,
MaxTokens: p.MaxTokens,
MaxTokensField: p.MaxTokensField,
ID: i64s(p.ID),
Name: p.Name,
Format: p.Format,
BaseURL: p.BaseURL,
Proxy: p.Proxy,
Model: p.Model,
APIKeyHint: p.APIKeyHint,
RatePerSecond: p.RatePerSecond,
RatePerMinute: p.RatePerMinute,
ContextWindowK: p.ContextWindowK,
ThinkingType: p.ThinkingType,
ReasoningEffort: p.ReasoningEffort,
IsDefault: p.IsDefault,
Priority: p.Priority,
PoolExclude: p.PoolExclude,
Streaming: p.Streaming,
MaxTokens: p.MaxTokens,
MaxTokensField: p.MaxTokensField,
SessionHeaderKey: p.SessionHeaderKey,
}
}