feat(evaluation): memoir readiness, judge/replay updates, eval web playground

Add memoir_readiness_service and router tests; extend judge schemas/services, replay_service, and conversation rubric; align story route agent, payload, prompts, and story_pipeline_sync; update agent logging, config, and DI. Document internal-eval; add replayDraft util and PlaygroundPage changes in app-eval-web.
This commit is contained in:
Kevin
2026-04-08 09:38:07 +08:00
parent 99543d04c6
commit 6772e1269c
26 changed files with 1255 additions and 124 deletions

View File

@@ -425,8 +425,9 @@ def story_route_merge_hint_for_category(chapter_category: str) -> str:
if cc == "family":
return (
"### 本章类别路由倾向(家庭)\n"
"- 原则性反思、关系模式、相处之道的补充 → **倾向 append_story**。\n"
"- **明确的新事件链**(新场景、新时间线、不同人物组合的新经历)→ 可 new_story。"
"- **默认 append_story**:同一家庭成员、同一居住环境、婚姻育儿、节日团聚、童年与父母的回忆等,"
"只要仍围绕已出现的人物或关系网络补充细节,一律并入最匹配的候选,不要因为换了个场景就 new_story。\n"
"- 仅当口述出现**完全新的人物组合 + 可独立成篇的新事件链**(与所有候选正文都接不上)时,才 new_story。"
)
if cc in (
"childhood",
@@ -435,6 +436,13 @@ def story_route_merge_hint_for_category(chapter_category: str) -> str:
"career_achievement",
"career_challenge",
):
if cc in ("childhood", "education"):
return (
"### 本章类别路由倾向(童年 / 求学 — 少拆分)\n"
"- **默认 append_story**:同一成长阶段里,地点(老家、学校)、父母职业、玩伴、游戏影视、"
"怀旧细节等**主题延续**的补充,即使分段讲述,也应并入已有童年/求学故事,避免多篇开头重复交代背景。\n"
"- **仅当**口述出现**另一条清晰可辨的事件链**(时间/地点/人物线换了且与候选明显不是同一脉络)时,才 new_story。"
)
return (
"### 本章类别路由倾向(经历叙事)\n"
"- 以具体事件链为主:**不同事件 / 时期 / 地点** → 可 new_story。\n"
@@ -473,7 +481,7 @@ def get_story_route_prompt(
**路由边界(必须遵守)**:仅根据下方「本批口述合并文本」判断;不得将系统检索摘要、记忆摘录等当作本批口述内容来匹配候选。
**候选故事说明**:列表项可能含 `summary``body_for_route`(正文摘要);仅含 `preview` 者为索引项,信息不全。**append 时优先匹配带 summary body 的条目**;索引项仅作候选 id 备忘。
**候选故事说明**:列表项可能含 `summary``body_for_route`(正文摘要)或 `opening_snippet`(无 summary 时的纯文本开头提要);仅含 `preview` 者为索引项,信息不全。**append 时优先匹配带 summary / body / opening_snippet 的条目**;索引项仅作候选 id 备忘。
当前章节(写作容器):
- category: {chapter_category}
@@ -495,6 +503,7 @@ def get_story_route_prompt(
规则:
- **不要**只因「不太确定」就选 new_story在主题可并入某一候选时应 append_story。
- 仅当口述与**所有**候选在两层标准下都明显不兼容时,才选 new_story。
- 若已有候选故事(列表非空)且口述是对同一人生阶段的**补述**,却找不到精确 id仍应 **append_story** 到最相近的一条,而不是 new_story。
"""
@@ -525,7 +534,7 @@ def get_story_batch_plan_prompt(
- **append_story**:与某一候选在两层标准下可合并,且能对应到具体 candidate id
- **new_story**:该块与**所有**候选都明显不兼容,或确认为独立新经历
**候选故事说明**:条目可能含 `summary`/`body_for_route`;仅 `preview` 者为索引项。**优先用带摘要/正文的条目做 append 目标**。
**候选故事说明**:条目可能含 `summary` / `body_for_route` / `opening_snippet`;仅 `preview` 者为索引项。**优先用带摘要正文摘要或开头提要的条目做 append 目标**。
当前章节(写作容器):
- category: {chapter_category}
@@ -552,6 +561,8 @@ def get_story_batch_plan_prompt(
规则:
- `units` 中所有 `segment_ids` 拼接后,必须**不重不漏**地覆盖本批全部 id且顺序与【本批口述片段】数组一致
- **不要**仅因不确定就对整块选 new_story能并入候选时应 append_story
- **同一批里 new_story 单元至多 1 个**:除非口述中同时存在**至少两条**与所有候选都不兼容、且彼此也明显无关的独立长经历,否则禁止拆成多个 new_story连续多段若都在补充同一主题应合并为**一块 append_story**。
- 候选列表非空时,优先把本批当作「加厚已有篇章」,而不是再开新篇。
"""