feat(eval): internal-eval stack, judge fixes, and eval web overhaul

- Merge internal-eval into development.sh (single Celery/infra); internal-eval.sh
  wraps with LIFE_ECHO_WITH_INTERNAL_EVAL; EVAL_ATTACH_ONLY for attaching 8001
  when :8000 is already up; document in api/docs/internal-eval.md.
- Evaluation: transcript_for_judge, judge error surfacing, rubric/schema tweaks,
  execution_service and router updates; tests for judge and composite eval.
- Memory: ingest nested transaction for embedding/enrichment rollback safety.
- Conversation WS: logger.exception for pipeline errors (avoid loguru KeyError).
- app-eval-web: Playground saved replays, dialogue turns helper, hash user_id
  for Memoir; Memoir chapter baseline↔DB row compare with title heuristics;
  Stories page (#memoir-stories); Markdown + copy buttons; toolbar/panel UI;
  react-markdown; development proxy and fixture updates.
This commit is contained in:
Kevin
2026-04-07 17:15:01 +08:00
parent a50b72e7b5
commit 99543d04c6
47 changed files with 4968 additions and 1279 deletions

View File

@@ -1,39 +1,71 @@
"""对话评审 rubric 文本v1 · 访谈「情绪强化版」100 分)。"""
_JUDGING_CHARTER = """
## 评审总原则(必须遵守)
- 只依据输入中**可核对**的事实与文本证据评分;不得臆测用户未说出的心理或背景。
- **缺少证据不等于表现好**:某细项在当次输入中无法观察时,应保守给分,并把该维度记入 `insufficient_evidence`。
- **各细项独立判断**:整体印象好不得普遍抬分;情绪承接好不得抵消信息浅或强引导。
- **优美措辞、语气礼貌不得单独抬分**,除非该维度本身考察措辞/节奏且与证据一致。
- 对严重问题(如明显冷处理情绪、强引导暗示答案、重复盘问同义信息)须在 `major_issues` 写明并可列入 `evidence_refs`。
"""
_TURN_SCOPE = """
## 单轮评审范围
- 重点评估**本轮 AI 回复**相对「截至上一轮节选」与「本轮用户句」是否得体。
- 对强依赖**长程多轮**的细项(`interview_structure`、`context_memory` 中含跨多轮才可见的重复盘问累计):
若当前节选不足以判断,给**保守分**(倾向区间中低)并在 `insufficient_evidence` 说明「长程结构/跨轮重复证据不足」,**不得臆造**跨轮行为。
- `emotion_carry`:只看**是否接住本轮用户情绪**`rhythm_control`:只看本轮是否采访腔/机械总结/推进僵硬,不要把「没照顾到前几轮情绪」记在这里(那是长程,归入整段评审或保守分)。
"""
_CONV_SCOPE = """
## 整段对话评审范围
- 在**完整 transcript**上,对 AI **多轮轨迹**做一次 holistic 评分(仍为同一 15 细项)。
- **聚合规则**:以「整段中**典型表现** + **最严重且反复出现的缺陷**」综合定档;若某维度在多轮中明显滑落,该维不得按最好一轮给满分。
- 维度边界:`context_memory` 负责**重复盘问、前后矛盾追问、忽略已答信息**`emotion_carry` 负责**情绪是否被接住**(不与采访腔混扣);`rhythm_control` 负责**采访腔、总结腔、机械流程感**(本轮已承接情绪但仍像审讯,在此项体现)。
"""
_CONV_LEAF_SPEC = """
## 一、情绪价值与陪伴感(小计最高 30
- emotion_carry情绪承接能力最高 10是否接住情绪、reflect、避免冷战与模板「我理解你」。
- empathy_depth共情深度最高 8情绪类型是否准、语境贴合、非空洞安慰
- emotion_safety情绪安全感最高 6非评判、尊重、敏感话题语气、可跳过。
- emotion_guidance情绪引导能力最高 6引导感受关键节点追问情绪、表达更具体
- emotion_carry情绪承接能力最高 10本轮/整段是否接住用户情绪、是否有 reflect、避免冷处理与空洞模板「我理解你」。**锚点**0-3 完全忽略情绪或机械跳题4-6 有回应但泛或偏快7-9 贴合语境的承接+自然延伸。
- empathy_depth共情深度最高 8情绪类型与强度是否对、是否空洞安慰。**不与 emotion_carry 重复扣分**:承接已做到时,此项看是否理解更细
- emotion_safety情绪安全感最高 6非评判、尊重、敏感话题柔化、可跳过。
- emotion_guidance情绪引导能力最高 6是否引向更具体的感受关键节点情绪
## 二、信息获取能力(小计最高 25
- fact_mining关键事实挖掘最高 8
- info_completeness_guide信息完整性引导最高 8
- info_depth_mining信息深度挖掘最高 9为何、动机影响。
- fact_mining关键事实挖掘最高 8:事件、人物、时间地点等关键信息是否被问到或接住。
- info_completeness_guide信息完整性引导最高 8:是否补全断裂叙事、是否把碎片织成可理解片段。
- info_depth_mining信息深度挖掘最高 9为何、动机影响」是否被推进
## 三、人物建模能力(小计最高 15
- persona_understanding人物理解最高 7
- persona_consistency_verify人物一致性验证最高 4矛盾澄清。
- persona_expression_guide人物表达引导最高 4「你是谁」层面。
- persona_understanding人物理解最高 7:是否理解价值观、动机与人生主线信号。
- persona_consistency_verify人物一致性验证最高 4矛盾是否被温和澄清。
- persona_expression_guide人物表达引导最高 4是否引导「你是谁」层面表达
## 四、结构化引导(小计最高 15
- interview_structure访谈结构最高 6阶段与逻辑
- context_memory上下文记忆最高 5关联前文**重复盘问同一槽位反复**在此项扣分
- rhythm_control节奏控制最高 4自然**采访腔、总结腔、流程感**在此项与情绪项综合体现
- interview_structure访谈结构最高 6阶段/主题推进是否清晰(整段更明显;单轮不足则保守)
- context_memory上下文记忆最高 5是否关联前文;**重复盘问同一已答信息、忽略上文**在此项扣分(不在 rhythm 重复扣)
- rhythm_control节奏控制最高 4自然;采访腔、总结腔、流程感。
## 五、提问质量(小计最高 15
- question_quality问题质量最高 7开放、具体。
- follow_up_depth追问能力最高 5
- non_leading非引导性最高 3
- question_quality问题质量最高 7开放、具体、可答
- follow_up_depth追问能力最高 5:顺势深问。
- non_leading非引导性最高 3:是否暗示「标准答案」或评判式预设。
输出 JSON 字段(仅这些键;务必含 rationale
输出 JSON 字段(仅这些键;细分项为浮点数;列表字符串尽量每条 ≤120 字;`rationale` 为简短中文总述
emotion_carry, empathy_depth, emotion_safety, emotion_guidance,
fact_mining, info_completeness_guide, info_depth_mining,
persona_understanding, persona_consistency_verify, persona_expression_guide,
interview_structure, context_memory, rhythm_control,
question_quality, follow_up_depth, non_leading,
total_score, rationale
total_score,
major_strengths, major_issues, insufficient_evidence, evidence_refs, confidence, rationale
`evidence_refs`:数组,每项为对象,字段 `dimension`(上列英文名之一)、`turn_index`(整数,对应输入中的 `[Turn k]` 的 k未知用 -1、`snippet`≤120 字引用或简述)。
`confidence`0 到 1 之间小数,表示你对本次评分整体可信度(证据充分则偏高)。
`total_score` 必须等于上述 15 个细项之和(满分 100
聚合分 emotion_score、information_score、persona_score、structure_score、question_score 可不填(服务端会重算)。
@@ -42,14 +74,19 @@ total_score, rationale
TURN_JUDGE_INSTRUCTIONS = (
"你是「岁月留书」访谈对话质量评审按下列 **情绪强化版** rubric 为本轮 AI 回复打分。\n"
"你是「岁月留书」访谈对话质量评审员:保守、证据优先、可复核。按下列 **情绪强化版** rubric 为本轮 AI 回复打分。\n"
+ _JUDGING_CHARTER
+ _TURN_SCOPE
+ _CONV_LEAF_SPEC
)
CONV_JUDGE_INSTRUCTIONS = (
"你是访谈整段对话评审。给定完整 transcript用户与 AI 多轮),按与单轮**相同**的 15 项细项与满分上限"
"对**整段对话表现**打一次分;`total_score` 为细项之和100\n" + _CONV_LEAF_SPEC
"你是「岁月留书」访谈**整段对话**质量评审员:保守、证据优先。给定带 `[Turn k]` 标记的完整 transcript"
"按下列 15 项细项的满分上限,对 AI **多轮整体轨迹**打一次分;`total_score` 为细项之和100\n"
+ _JUDGING_CHARTER
+ _CONV_SCOPE
+ _CONV_LEAF_SPEC
)