grok2api / app /dataplane /reverse /protocol /xai_chat_reasoning.py
FUCAT's picture
Deploy grok2api to HF Spaces (Docker)
7e55e53
Raw
History Blame Contribute Delete
27.2 kB
"""Reasoning normalization and aggregation for XAI app-chat streams."""
from __future__ import annotations
import re
from dataclasses import dataclass
from typing import Any
_GENERIC_HEADERS = {
"",
"thinking about your request",
}
_PROGRESSIVE_HINTS = (
"正在", "准备", "计划", "查找", "搜索", "浏览", "确认", "核对", "整合", "挖掘", "比对",
"checking", "browsing", "verifying", "integrating", "digging", "cross-checking", "searching", "planning",
)
_FINDING_HINTS = (
"尚未", "已经", "已", "确认", "表明", "说明", "显示", "主要", "通常", "支持", "出现", "启动",
"持续", "提升", "更新", "灰度", "发布", "上线", "多模态", "视觉", "专家", "context", "token",
"参数", "每天", "大潮", "小潮", "半日潮", "引力", "周期", "模式", "confirmed", "launched",
"released", "rollout", "testing", "native multimodal", "widely believed", "latest",
)
_LOW_VALUE_PREFIXES = (
"用户", "user", "i can", "我可以", "我收集", "建议", "need", "需要", "应该", "since instructions",
"proposed", "mermaid", "可以用", "我建议",
)
_TRACK_RULES: tuple[tuple[str, tuple[str, ...]], ...] = (
("latest_updates", ("最新", "latest", "today", "recent", "最近", "update", "news", "本周", "4月", "april")),
("release_status", ("release date", "released", "release", "launch", "上线", "发布", "正式发布", "current status")),
("gray_rollout", ("灰度", "grayscale", "gray release", "灰度测试", "内测", "rollout")),
("official_confirmation", ("official", "官网", "official site", "site:", "platform.deepseek.com", "deepseek.ai")),
("ui_modes", ("vision", "视觉", "expert", "专家模式", "fast", "default", "ui", "界面", "mode")),
("v4_lite", ("v4 lite", "sealion", "sealion-lite", "海狮")),
("specs_architecture", ("specs", "parameters", "architecture", "engram", "mhc", "moe", "context", "benchmarks", "规格", "参数", "架构", "万亿")),
("definition_basics", ("定义", "解释", "什么是", "what is", "phenomenon", "现象")),
("causes_mechanism", ("成因", "原因", "cause", "causes", "gravity", "引力", "机制")),
("categories_types", ("春潮", "小潮", "半日潮", "全日潮", "类型", "分类")),
("impacts_applications", ("影响", "应用", "发电", "航运", "生活", "生态")),
)
_ZH_LABELS = {
"understanding": "理解问题",
"scope": "检索范围",
"evidence": "核验与证据",
"finding": "关键发现",
"latest_updates": "最新动态",
"release_status": "发布状态与上线节奏",
"gray_rollout": "灰度进展",
"official_confirmation": "官方渠道确认",
"ui_modes": "Expert / Vision 模式关联",
"v4_lite": "V4 Lite 与 Sealion 线索",
"specs_architecture": "规格、架构与上下文能力",
"definition_basics": "定义与基础解释",
"causes_mechanism": "成因与机制",
"categories_types": "分类与相关类型",
"impacts_applications": "影响与应用",
}
_EN_LABELS = {
"understanding": "Understanding",
"scope": "Research Scope",
"evidence": "Verification",
"finding": "Key Findings",
"latest_updates": "latest updates",
"release_status": "release status and rollout timing",
"gray_rollout": "gray rollout progress",
"official_confirmation": "official confirmation",
"ui_modes": "Expert / Vision mode signals",
"v4_lite": "V4 Lite and Sealion clues",
"specs_architecture": "specs, architecture, and context capability",
"definition_basics": "definition and basic explanation",
"causes_mechanism": "causes and mechanism",
"categories_types": "categories and related types",
"impacts_applications": "impacts and applications",
}
@dataclass(slots=True)
class ReasoningEvent:
section: str
text: str
track: str = ""
evidence_level: int = 0
dedupe_key: str = ""
class ReasoningAggregator:
"""Normalize raw stream fragments into enterprise-style reasoning output."""
__slots__ = (
"_language",
"_en_votes",
"_zh_votes",
"_agent_search_started",
"_emitted_keys",
"_seen_tracks",
"_seen_findings",
"_pending_events",
"_section_started",
"_track_best_level",
"_track_emit_counts",
)
def __init__(self) -> None:
self._language: str | None = None
self._en_votes = 0
self._zh_votes = 0
self._agent_search_started = False
self._emitted_keys: set[str] = set()
self._seen_tracks: set[str] = set()
self._seen_findings: set[str] = set()
self._pending_events: list[ReasoningEvent] = []
self._section_started: set[str] = set()
self._track_best_level: dict[tuple[str, str], int] = {}
self._track_emit_counts: dict[tuple[str, str], int] = {}
def on_thinking(
self,
token: str,
*,
tag: str | None,
rollout: str | None,
step_id: int | None,
) -> list[str]:
self._observe_language(token)
tag_name = str(tag or "").strip()
text = str(token or "").strip()
if not text:
return []
if tag_name == "header":
event = self._normalize_header(text, step_id=step_id)
return self._dispatch(event) if event else []
if tag_name == "summary":
event = self._normalize_summary(text, step_id=step_id)
return self._dispatch(event) if event else []
event = self._normalize_summary(text, step_id=step_id)
return self._dispatch(event) if event else []
def on_tool_usage(
self,
tool_name: str,
args: dict[str, Any],
*,
rollout: str | None,
step_id: int | None,
) -> list[str]:
lines: list[str] = []
self._observe_language(str(args.get("query") or args.get("message") or args.get("instructions") or ""))
if tool_name == "web_search":
query = str(args.get("query") or args.get("q") or "").strip()
if not query:
return []
if str(rollout or "").startswith("Agent") and not self._agent_search_started:
self._agent_search_started = True
lines.extend(self._dispatch(ReasoningEvent(
"scope",
self._localized_line("agents_started"),
dedupe_key="scope:agents_started",
)))
track = self._infer_track(query)
if not track:
return lines
lines.extend(self._dispatch(ReasoningEvent(
"scope",
self._localized_track_line(track),
track=track,
evidence_level=1,
dedupe_key=f"scope:web:{track}",
)))
return lines
if tool_name in {"x_search", "x_keyword_search", "x_semantic_search"}:
query = str(args.get("query") or "").strip()
track = self._infer_track(query)
if not track:
return []
return self._dispatch(ReasoningEvent(
"evidence",
self._localized_social_line(track),
track=track,
evidence_level=2,
dedupe_key=f"evidence:social:{track}",
))
if tool_name == "browse_page":
url = str(args.get("url") or "").strip()
source_kind, track = self._classify_page_source(url, args)
if not source_kind:
return []
return self._dispatch(ReasoningEvent(
"evidence",
self._localized_browse_line(source_kind, track),
track=track or source_kind,
evidence_level=4 if source_kind in {"official", "product"} else 3,
dedupe_key=f"evidence:browse:{source_kind}:{track or ''}",
))
if tool_name in {"search_images", "image_search"}:
description = str(args.get("image_description") or args.get("imageDescription") or "").strip()
if not description:
return []
topic = self._classify_image_topic(description)
if not topic:
return []
return self._dispatch(ReasoningEvent(
"scope",
self._localized_image_line(topic),
track="visual_assets",
evidence_level=1,
dedupe_key=f"scope:image:{topic}",
))
if tool_name == "chatroom_send":
message = str(args.get("message") or "").strip()
if not message:
return []
lines = []
for section, text, track, level in self._extract_report_events(message):
lines.extend(self._dispatch(ReasoningEvent(
section,
text,
track=track,
evidence_level=level,
dedupe_key=f"{section}:report:{track}:{self._normalize_key(text)}",
)))
return lines
if tool_name == "code_execution":
return self._dispatch(ReasoningEvent(
"evidence",
self._localized_line("code_execution"),
dedupe_key="evidence:code_execution",
))
return []
def finalize(self) -> list[str]:
if not self._pending_events:
return []
if self._language is None:
self._language = "en" if self._en_votes > 0 and self._zh_votes == 0 else "zh"
return self._flush_pending()
def _normalize_header(self, text: str, *, step_id: int | None) -> ReasoningEvent | None:
stripped = text.strip()
if stripped.lower() in _GENERIC_HEADERS:
return None
section = "understanding" if not self._looks_like_verification(stripped) and (step_id or 0) <= 1 else "evidence"
return ReasoningEvent(section, self._to_bullet_text(stripped), dedupe_key=f"{section}:header:{self._normalize_key(stripped)}")
def _normalize_summary(self, text: str, *, step_id: int | None) -> ReasoningEvent | None:
summary = text.lstrip("- ").strip()
if not summary:
return None
if summary.startswith(("建议搜索", "正在调用工具搜索")):
return None
track = self._infer_track(summary)
if self._looks_like_progress(summary):
section = "evidence" if self._looks_like_verification(summary) else "scope"
return ReasoningEvent(section, self._to_bullet_text(summary), track=track, evidence_level=2 if section == "evidence" else 1, dedupe_key=f"{section}:summary:{self._normalize_key(summary)}")
if self._looks_like_finding(summary):
if self._is_unconfirmed_signal(summary):
return ReasoningEvent("evidence", self._to_bullet_text(summary), track=track, evidence_level=2, dedupe_key=f"evidence:summary:{self._normalize_key(summary)}")
if not self._agent_search_started and (step_id or 0) <= 1:
return ReasoningEvent("understanding", self._to_bullet_text(summary), track=track, evidence_level=2, dedupe_key=f"understanding:summary:{self._normalize_key(summary)}")
return ReasoningEvent("finding", self._to_bullet_text(summary), track=track, evidence_level=3, dedupe_key=f"finding:summary:{self._normalize_key(summary)}")
section = "understanding" if (step_id or 0) <= 1 else "scope"
return ReasoningEvent(section, self._to_bullet_text(summary), track=track, evidence_level=1, dedupe_key=f"{section}:summary:{self._normalize_key(summary)}")
def _extract_report_events(self, message: str) -> list[tuple[str, str, str, int]]:
parts = re.split(r"(?:\n+|[。!?!?;;]+|\s+-\s+)", message.replace("\\n", "\n"))
candidates: list[tuple[int, str]] = []
for raw_part in parts:
clause = self._clean_report_clause(raw_part)
if not clause:
continue
if self._language == "zh" and not re.search(r"[\u4e00-\u9fff]", clause):
continue
if self._language == "en" and re.search(r"[\u4e00-\u9fff]", clause):
continue
score = self._score_report_clause(clause)
if score <= 0:
continue
candidates.append((score, clause))
candidates.sort(key=lambda item: (-item[0], len(item[1])))
results: list[tuple[str, str, str, int]] = []
seen_local: set[str] = set()
seen_track_counts: dict[tuple[str, str], int] = {}
for _, clause in candidates:
key = self._normalize_key(clause)
if key in seen_local:
continue
seen_local.add(key)
track = self._infer_track(clause)
section = "finding" if self._looks_like_finding(clause) else "evidence"
if self._is_unconfirmed_signal(clause):
section = "evidence"
track_key = (section, track or "_")
current_track_count = seen_track_counts.get(track_key, 0)
max_track_count = 2 if section == "finding" else 1
if current_track_count >= max_track_count:
continue
seen_track_counts[track_key] = current_track_count + 1
level = self._infer_evidence_level(clause, default=3 if section == "finding" else 2)
results.append((section, self._to_bullet_text(clause), track, level))
if len(results) >= 6:
break
results.sort(key=lambda item: (0 if item[0] == "evidence" else 1, item[2], -item[3]))
return results
def _dispatch(self, event: ReasoningEvent) -> list[str]:
if self._language is None:
self._pending_events.append(event)
if self._zh_votes > 0:
self._language = "zh"
elif self._en_votes >= 3:
self._language = "en"
elif len(self._pending_events) < 4:
return []
else:
self._language = "en"
return self._flush_pending()
lines: list[str] = []
if self._pending_events:
lines.extend(self._flush_pending())
lines.extend(self._emit(event))
return lines
def _flush_pending(self) -> list[str]:
lines: list[str] = []
pending = self._pending_events
self._pending_events = []
for event in pending:
lines.extend(self._emit(event))
return lines
def _emit(self, event: ReasoningEvent) -> list[str]:
text = event.text.strip()
if not text:
return []
if event.section == "scope" and ("evidence" in self._section_started or "finding" in self._section_started):
return []
if event.section == "evidence" and "finding" in self._section_started:
if event.evidence_level >= 4 or event.track in {
"latest_updates",
"release_status",
"official_confirmation",
"specs_architecture",
"v4_lite",
}:
promoted_key = event.dedupe_key or f"evidence:{self._normalize_key(text)}"
event = ReasoningEvent(
"finding",
text,
track=event.track,
evidence_level=event.evidence_level,
dedupe_key=f"finding:promoted:{promoted_key}",
)
else:
return []
dedupe_key = event.dedupe_key or f"{event.section}:{self._normalize_key(text)}"
if dedupe_key in self._emitted_keys:
return []
if event.track:
count_key = (event.section, event.track)
emitted_count = self._track_emit_counts.get(count_key, 0)
max_per_track = 1 if event.section in {"scope", "evidence"} else 2
if emitted_count >= max_per_track and not dedupe_key.endswith("agents_started"):
return []
best_key = (event.section, event.track)
best_level = self._track_best_level.get(best_key, -1)
if best_level > event.evidence_level:
return []
self._track_best_level[best_key] = max(best_level, event.evidence_level)
self._track_emit_counts[count_key] = emitted_count + 1
self._emitted_keys.add(dedupe_key)
lines: list[str] = []
if event.section not in self._section_started:
self._section_started.add(event.section)
lines.append(self._section_title(event.section) + "\n")
lines.append(text + "\n")
return lines
def _observe_language(self, text: str) -> None:
if not text:
return
cjk_count = len(re.findall(r"[\u4e00-\u9fff]", text))
en_count = len(re.findall(r"[A-Za-z]", text))
if cjk_count >= 4 or cjk_count > max(2, en_count // 2):
self._zh_votes += 1
if self._language is None:
self._language = "zh"
return
if en_count >= 4:
self._en_votes += 1
def _section_title(self, section: str) -> str:
labels = _ZH_LABELS if self._language != "en" else _EN_LABELS
return labels.get(section, section)
def _localized_line(self, key: str) -> str:
zh_map = {
"agents_started": "- 已启动并行代理进行交叉检索与核验。",
"code_execution": "- 正在执行代码或生成可运行内容。",
}
en_map = {
"agents_started": "- Parallel agents have started cross-checking the topic.",
"code_execution": "- Executing code or generating runnable content.",
}
mapping = zh_map if self._language != "en" else en_map
return mapping[key]
def _localized_track_line(self, track: str) -> str:
label = self._track_label(track)
if self._language == "en":
return f"- Parallel research: {label}."
return f"- 并行检索:{label}。"
def _localized_social_line(self, track: str) -> str:
label = self._track_label(track)
if self._language == "en":
return f"- Social cross-check: {label}."
return f"- 社媒交叉核验:{label}。"
def _localized_browse_line(self, source_kind: str, track: str) -> str:
track_label = self._track_label(track) if track else ""
if self._language == "en":
mapping = {
"official": "Page verification: official site and official pages",
"product": "Page verification: product page and live UI",
"community": "Page verification: public reports and community write-ups",
}
else:
mapping = {
"official": "页面核对:官网与官方页面",
"product": "页面核对:产品页面与实际界面",
"community": "页面核对:公开报道与社区文章",
}
base = mapping[source_kind]
if track_label:
connector = ", focusing on " if self._language == "en" else ",重点核对"
return f"- {base}{connector}{track_label}{'.' if self._language == 'en' else '。'}"
return f"- {base}{'.' if self._language == 'en' else '。'}"
def _localized_image_line(self, topic: str) -> str:
if self._language == "en":
mapping = {
"diagram": "- Visual asset search: diagrams and explanatory graphics.",
"photo": "- Visual asset search: real-world comparison photos.",
"generic": "- Visual asset search: supporting image references.",
}
else:
mapping = {
"diagram": "- 视觉素材检索:示意图与结构说明素材。",
"photo": "- 视觉素材检索:实景对比图片。",
"generic": "- 视觉素材检索:补充说明图片。",
}
return mapping[topic]
def _track_label(self, track: str) -> str:
labels = _ZH_LABELS if self._language != "en" else _EN_LABELS
return labels.get(track, track)
def _infer_track(self, text: str) -> str:
lowered = self._compact_query(text).lower()
if not lowered:
return ""
for track, keywords in _TRACK_RULES:
if any(keyword in lowered for keyword in keywords):
return track
return ""
def _classify_page_source(self, url: str, args: dict[str, Any]) -> tuple[str, str]:
lowered = url.lower()
instructions = str(args.get("instructions") or "")
track = self._pick_browse_track(f"{url} {instructions}")
if any(domain in lowered for domain in ("deepseek.ai", "deepseek.com")):
if "chat.deepseek.com" in lowered or "platform.deepseek.com" in lowered:
return "product", track or "ui_modes"
return "official", track or "official_confirmation"
if url:
return "community", track
return "", track
def _pick_browse_track(self, text: str) -> str:
lowered = self._compact_query(text).lower()
priority = (
("ui_modes", ("expert", "vision", "mode", "界面", "ui")),
("release_status", ("release", "released", "launch", "发布", "上线", "status")),
("specs_architecture", ("spec", "parameter", "architecture", "context", "engram", "moe", "规格", "参数", "架构", "上下文")),
("v4_lite", ("v4 lite", "sealion", "sealion-lite", "海狮")),
("official_confirmation", ("official", "官网", "current models", "offering")),
)
for track, keywords in priority:
if any(keyword in lowered for keyword in keywords):
return track
return self._infer_track(text)
def _classify_image_topic(self, text: str) -> str:
lowered = text.lower()
if any(token in lowered for token in ("diagram", "示意图", "bulge")):
return "diagram"
if any(token in lowered for token in ("photo", "照片", "real", "high tide", "low tide", "高潮", "低潮")):
return "photo"
return "generic"
def _looks_like_progress(self, text: str) -> bool:
lowered = text.lower()
return any(hint in lowered for hint in _PROGRESSIVE_HINTS)
def _looks_like_verification(self, text: str) -> bool:
lowered = text.lower()
return any(token in lowered for token in ("确认", "核对", "浏览", "整合", "比对", "check", "verify", "browse", "integrat"))
def _looks_like_finding(self, text: str) -> bool:
lowered = text.lower()
if self._looks_like_progress(text):
return False
return any(hint in lowered for hint in _FINDING_HINTS)
def _clean_report_clause(self, raw_part: str) -> str:
clause = re.sub(r"\s+", " ", raw_part).strip(" -•\t")
if not clause:
return ""
delimiter = ":" if ":" in clause else ":" if ":" in clause else ""
if delimiter:
head, tail = clause.split(delimiter, 1)
head_lower = head.strip().lower()
if len(head.strip()) <= 18 or any(token in head_lower for token in ("总结", "最新", "关键", "补充", "latest", "summary", "note")):
clause = tail.strip()
clause = clause.strip(" -•\t")
clause = re.sub(r"^(?:我知道|我收集了可靠信息|我收集到的?信息|从搜索结果总结|详细解释要点(?:([^)]+))?|补充)\s*", "", clause)
clause = re.sub(r"^(?:that|it shows|it seems)\s+", "", clause, flags=re.IGNORECASE)
if len(clause) < 8:
return ""
lowered = clause.lower()
if any(lowered.startswith(prefix) for prefix in _LOW_VALUE_PREFIXES):
return ""
if "?" in clause or "?" in clause:
return ""
return self._compact_text(clause, limit=120)
def _score_report_clause(self, clause: str) -> int:
lowered = clause.lower()
score = 0
if any(hint in lowered for hint in _FINDING_HINTS):
score += 3
if re.search(r"\b\d+(?:\.\d+)?\b", clause):
score += 2
if any(token in clause for token in ("月", "日", "年", "小时", "分钟")):
score += 1
if any(token in clause for token in ("重要", "航运", "渔业", "发电", "生态", "模式", "视觉")):
score += 1
if any(token in lowered for token in ("可能", "rumor", "传闻", "widely believed", "believed")):
score -= 1
if any(token in lowered for token in ("可以", "suggest", "建议", "should", "friendly", "reply")):
score -= 2
if len(clause) > 150:
score -= 1
return score
def _infer_evidence_level(self, clause: str, *, default: int) -> int:
lowered = clause.lower()
if any(token in lowered for token in ("官网", "official", "chat ui", "界面更新", "页面")):
return 4
if any(token in lowered for token in ("x平台", "x posts", "社区", "widely believed", "传闻", "rumor")):
return max(2, default - 1)
return default
def _is_unconfirmed_signal(self, clause: str) -> bool:
lowered = clause.lower()
return any(
token in lowered
for token in (
"x平台", "x posts", "社区", "community", "widely believed", "believed",
"传闻", "rumor", "曝光", "泄露",
)
)
def _to_bullet_text(self, text: str) -> str:
stripped = text.strip()
if stripped.startswith("- "):
stripped = stripped[2:].strip()
stripped = self._ensure_terminal_punctuation(stripped)
return f"- {stripped}"
def _ensure_terminal_punctuation(self, text: str) -> str:
stripped = text.strip()
if not stripped:
return ""
if stripped.endswith(("。", "!", "?", ".", "!", "?")):
return stripped
if re.search(r"[\u4e00-\u9fff]", stripped):
return stripped + "。"
return stripped + "."
def _compact_query(self, text: str) -> str:
cleaned = re.sub(r"\b(?:or|and|site:[^\s]+|since:\S+|from:\S+|date:\S+)\b", " ", text, flags=re.IGNORECASE)
cleaned = re.sub(r"[()\"']", " ", cleaned)
cleaned = re.sub(r"\s+", " ", cleaned).strip()
return cleaned
def _compact_text(self, text: str, *, limit: int) -> str:
compact = re.sub(r"\s+", " ", text).strip()
if len(compact) <= limit:
return compact
return compact[: limit - 3].rstrip() + "..."
def _normalize_key(self, text: str) -> str:
lowered = text.lower()
lowered = re.sub(r"https?://\S+", "", lowered)
lowered = re.sub(r"[^\w\u4e00-\u9fff]+", "", lowered)
return lowered
__all__ = ["ReasoningAggregator", "ReasoningEvent"]