标题生成强制关闭 think 模式,回答速度指示器默认开启
- TitleMiddleware 给模型实例注入 extra_body 关 think(覆盖 Zhipu GLM 与 Qwen/vLLM 两套写法),并兜底剥离不闭合/残留的 <think> 标签,避免 GLM5 起标题时长时间思考与标签泄漏。 - 前端 streamSpeedMeterEnabled 默认改为 true,设置项描述同步为"默认开启"。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f8e3a3e5b4
commit
67d5e43ec4
3 files changed
+44
-5
No files matched your search
@@ -122,7 +122,7 @@ export function AppearanceSettingsPage() {
|
|||||||
<div className="text-sm font-medium">回答速度指示器</div>
|
<div className="text-sm font-medium">回答速度指示器</div>
|
||||||
<p className="text-muted-foreground mt-1 max-w-md text-xs leading-relaxed">
|
<p className="text-muted-foreground mt-1 max-w-md text-xs leading-relaxed">
|
||||||
在生成回答时显示一个小胶囊,实时估算当前 token/s
|
在生成回答时显示一个小胶囊,实时估算当前 token/s
|
||||||
并用绿到红的渐变条直观反映快慢。默认关闭。
|
并用绿到红的渐变条直观反映快慢。默认开启。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const DEFAULT_LOCAL_SETTINGS: LocalSettings = {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
display: {
|
display: {
|
||||||
streamSpeedMeterEnabled: false,
|
streamSpeedMeterEnabled: true,
|
||||||
},
|
},
|
||||||
context: {
|
context: {
|
||||||
model_name: undefined,
|
model_name: undefined,
|
||||||
@@ -29,7 +29,7 @@ export interface LocalSettings {
|
|||||||
display: {
|
display: {
|
||||||
/**
|
/**
|
||||||
* Whether to render a small token/s speed meter while a streaming
|
* Whether to render a small token/s speed meter while a streaming
|
||||||
* AI reply is in flight. Default off; controlled by the user from
|
* AI reply is in flight. Default on; controlled by the user from
|
||||||
* the appearance settings page.
|
* the appearance settings page.
|
||||||
*/
|
*/
|
||||||
streamSpeedMeterEnabled: boolean;
|
streamSpeedMeterEnabled: boolean;
|
||||||
|
|||||||
+41
-2
@@ -105,8 +105,16 @@ class TitleMiddleware(AgentMiddleware[TitleMiddlewareState]):
|
|||||||
return prompt, user_msg
|
return prompt, user_msg
|
||||||
|
|
||||||
def _strip_think_tags(self, text: str) -> str:
|
def _strip_think_tags(self, text: str) -> str:
|
||||||
"""Remove <think>...</think> blocks emitted by reasoning models (e.g. minimax, DeepSeek-R1)."""
|
"""Remove <think>...</think> blocks emitted by reasoning models (e.g. minimax, GLM, DeepSeek-R1).
|
||||||
return re.sub(r"<think>[\s\S]*?</think>", "", text, flags=re.IGNORECASE).strip()
|
|
||||||
|
Also handles malformed cases: an unclosed `<think>` (response truncated mid-reasoning)
|
||||||
|
or a stray `</think>` (open tag eaten by upstream parsing) — both can otherwise leak
|
||||||
|
raw reasoning into the title.
|
||||||
|
"""
|
||||||
|
text = re.sub(r"<think>[\s\S]*?</think>", "", text, flags=re.IGNORECASE)
|
||||||
|
text = re.sub(r"<think>[\s\S]*$", "", text, flags=re.IGNORECASE)
|
||||||
|
text = re.sub(r"^[\s\S]*?</think>", "", text, flags=re.IGNORECASE)
|
||||||
|
return text.strip()
|
||||||
|
|
||||||
def _parse_title(self, content: object) -> str:
|
def _parse_title(self, content: object) -> str:
|
||||||
"""Normalize model output into a clean title string."""
|
"""Normalize model output into a clean title string."""
|
||||||
@@ -146,6 +154,36 @@ class TitleMiddleware(AgentMiddleware[TitleMiddlewareState]):
|
|||||||
_, user_msg = self._build_title_prompt(state)
|
_, user_msg = self._build_title_prompt(state)
|
||||||
return {"title": self._fallback_title(user_msg)}
|
return {"title": self._fallback_title(user_msg)}
|
||||||
|
|
||||||
|
def _force_disable_thinking(self, model: object) -> None:
|
||||||
|
"""Force-disable thinking on the title model via `extra_body` overrides.
|
||||||
|
|
||||||
|
Title generation never needs reasoning. The model factory only emits
|
||||||
|
disable params when the model config declares `when_thinking_disabled`
|
||||||
|
or a matching `when_thinking_enabled` shape — many user-added reasoning
|
||||||
|
models (e.g. GLM-4.5/5) only set `supports_thinking: true` and would
|
||||||
|
otherwise keep thinking on, which is slow and leaks <think> tags into
|
||||||
|
the title prompt response. Injecting both common OpenAI-compatible
|
||||||
|
disable shapes covers Zhipu GLM (`thinking.type`) and Qwen/vLLM
|
||||||
|
(`chat_template_kwargs.enable_thinking`); other providers ignore
|
||||||
|
unknown body fields.
|
||||||
|
"""
|
||||||
|
if not hasattr(model, "extra_body"):
|
||||||
|
return
|
||||||
|
current = getattr(model, "extra_body", None) or {}
|
||||||
|
merged_chat_template_kwargs = {
|
||||||
|
**(current.get("chat_template_kwargs") or {}),
|
||||||
|
"enable_thinking": False,
|
||||||
|
}
|
||||||
|
merged = {
|
||||||
|
**current,
|
||||||
|
"thinking": {**(current.get("thinking") or {}), "type": "disabled"},
|
||||||
|
"chat_template_kwargs": merged_chat_template_kwargs,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
model.extra_body = merged
|
||||||
|
except Exception:
|
||||||
|
logger.debug("Could not override extra_body to disable thinking on title model", exc_info=True)
|
||||||
|
|
||||||
async def _agenerate_title_result(self, state: TitleMiddlewareState) -> dict | None:
|
async def _agenerate_title_result(self, state: TitleMiddlewareState) -> dict | None:
|
||||||
"""Generate a title asynchronously and fall back locally on failure."""
|
"""Generate a title asynchronously and fall back locally on failure."""
|
||||||
if not self._should_generate_title(state):
|
if not self._should_generate_title(state):
|
||||||
@@ -162,6 +200,7 @@ class TitleMiddleware(AgentMiddleware[TitleMiddlewareState]):
|
|||||||
model = create_chat_model(name=config.model_name, **model_kwargs)
|
model = create_chat_model(name=config.model_name, **model_kwargs)
|
||||||
else:
|
else:
|
||||||
model = create_chat_model(**model_kwargs)
|
model = create_chat_model(**model_kwargs)
|
||||||
|
self._force_disable_thinking(model)
|
||||||
response = await model.ainvoke(prompt, config=self._get_runnable_config())
|
response = await model.ainvoke(prompt, config=self._get_runnable_config())
|
||||||
title = self._parse_title(response.content)
|
title = self._parse_title(response.content)
|
||||||
if title:
|
if title:
|
||||||
|
|||||||
Reference in new issue
Block a user