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:
1 parent
b513b656aa
commit
4319fe413f
10 files changed
+166
-36
No files matched your search
@@ -324,6 +324,7 @@ function ProfileSheet({
|
||||
const [streaming, setStreaming] = React.useState(true); // true=流式(默认);false=非流式
|
||||
const [maxTokens, setMaxTokens] = React.useState("0"); // 单次回复输出上限;0=不发送
|
||||
const [maxTokensField, setMaxTokensField] = React.useState(NONE); // 上限用哪个字段名;NONE=max_tokens
|
||||
const [sessionHeaderKey, setSessionHeaderKey] = React.useState(""); // 自定义会话头名;空=不发送
|
||||
const [testing, setTesting] = React.useState(false);
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
const [models, setModels] = React.useState<string[]>([]);
|
||||
@@ -351,6 +352,7 @@ function ProfileSheet({
|
||||
setStreaming(profile?.streaming ?? true);
|
||||
setMaxTokens(String(profile?.max_tokens ?? 0));
|
||||
setMaxTokensField(fromStore(profile?.max_tokens_field));
|
||||
setSessionHeaderKey(profile?.session_header_key ?? "");
|
||||
setApiKey("");
|
||||
setKeyHint(profile?.api_key_hint ?? "");
|
||||
setModels([]);
|
||||
@@ -437,6 +439,7 @@ function ProfileSheet({
|
||||
// 字段名开关只对 openai(Chat Completions) 有意义,其它格式一律回落到默认;
|
||||
// 后端也会再做一次同样的归一化,这里只是别让 UI 送出自相矛盾的值。
|
||||
max_tokens_field: format === "openai" ? toStore(maxTokensField) : "",
|
||||
session_header_key: sessionHeaderKey.trim(),
|
||||
});
|
||||
if (isNew) toast.success(`已新建:${name.trim()}(在卡片上「设为激活」以启用)`);
|
||||
else toast.success(profile?.is_default ? "已保存,激活配置即时生效,无需重启" : "已保存");
|
||||
@@ -570,6 +573,22 @@ function ProfileSheet({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="p-session-header">自定义会话头(可选)</Label>
|
||||
<Input
|
||||
id="p-session-header"
|
||||
className="font-mono"
|
||||
placeholder="如 x-session-id(留空=不发送)"
|
||||
value={sessionHeaderKey}
|
||||
onChange={(e) => setSessionHeaderKey(e.target.value)}
|
||||
/>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
填写头名后,每次请求都会带上这个 HTTP 头,头值自动填为{" "}
|
||||
<b>当前会话的 session id</b>(chat 会话如 conv-12、worker 如 exp3-worker-i87)。用于按 session-id
|
||||
头做提示缓存 / 粘性路由的网关;同一会话多轮稳定、不同会话互不相同。留空则不发送。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="p-api-key">API Key</Label>
|
||||
<Input
|
||||
|
||||
@@ -723,6 +723,7 @@ export const api = {
|
||||
streaming?: boolean; // true(默认)=流式 | false=非流式
|
||||
max_tokens?: number; // 单次回复输出上限;0=不发送,由服务端默认值决定
|
||||
max_tokens_field?: string; // ""=max_tokens(默认) | "max_completion_tokens"(仅 openai 格式)
|
||||
session_header_key?: string; // 非空=每次请求带该 HTTP 头,头值=当前会话 session id;""=不发送
|
||||
}) => post<{ id: number }>("/llm/profiles", p),
|
||||
deleteLLMProfile: (id: string) => del<{ deleted: number }>(`/llm/profiles/${id}`),
|
||||
activateLLMProfile: (id: string) => post<{ ok: boolean }>("/llm/profiles/active", { id: Number(id) }),
|
||||
|
||||
@@ -913,6 +913,9 @@ export interface LLMProfile {
|
||||
// 上限用哪个请求字段名,仅 format="openai" 有意义:
|
||||
// ""=max_tokens(默认) | "max_completion_tokens"(OpenAI 推理模型只认它)
|
||||
max_tokens_field?: string;
|
||||
// 自定义会话头名:非空时每次请求带该 HTTP 头,头值=当前会话/意图的 session id。
|
||||
// ""=不发送。用于按 session-id 头做提示缓存/粘性路由的网关。
|
||||
session_header_key?: string;
|
||||
}
|
||||
|
||||
// ---- LLM 轮询(故障转移)----
|
||||
|
||||
Reference in new issue
Block a user