feat(memoir): 路由阶段不要求标题,按正文字数门闸延迟 LLM 标题

- 从 story 路由 prompt/校验中移除 new_story_title,改由叙事管线在正文足够长时生成
- 新增 story_title_min_body_chars;短正文使用章节类别占位标题
- CATEGORY_TO_CHAT_STAGE 对齐访谈 state.slots 的 stage 键
- 删除相对口述长度的叙事回退,仅保留 merge JSON 极端缩水类 fallback
- evidence_format:解析 object_json 并优化事实条目标点符号
- 更新 narrative / experience 相关单测
This commit is contained in:
Kevin
2026-04-02 14:38:40 +08:00
parent bb16d3a5c9
commit 3ae39838c0
8 changed files with 125 additions and 132 deletions

View File

@@ -4,6 +4,7 @@
from __future__ import annotations
import json
import re
@@ -46,6 +47,25 @@ def dedupe_evidence_chunk_rows(chunks: list) -> list:
return [x[1] for x in kept]
def _flatten_object_json(obj_raw: object) -> str:
"""Extract readable text from fact object_json (may be dict, JSON string, or plain str)."""
if isinstance(obj_raw, dict):
return str(obj_raw.get("value", "")) or ", ".join(
f"{k}={v}" for k, v in obj_raw.items() if v
)
if isinstance(obj_raw, str):
s = obj_raw.strip()
if s.startswith("{"):
try:
parsed = json.loads(s)
if isinstance(parsed, dict):
return str(parsed.get("value", s)) or s
except (json.JSONDecodeError, TypeError):
pass
return s
return str(obj_raw) if obj_raw else ""
def format_evidence_chunks_for_prompt(evidence: dict) -> str:
"""将 retrieve_evidence / retrieve_evidence_sync 结果格式化为简短文本,供叙事与访谈 prompt 使用。
@@ -75,11 +95,15 @@ def format_evidence_chunks_for_prompt(evidence: dict) -> str:
if isinstance(f, dict):
subj = f.get("subject", "")
pred = f.get("predicate", "")
obj = f.get("object_json", "")
obj_raw = f.get("object_json", "")
obj = _flatten_object_json(obj_raw)
if subj or pred:
parts.append(f"{subj} {pred} {obj}")
if obj:
parts.append(f"{subj}{pred}{obj}")
else:
parts.append(f"{subj}{pred}")
else:
parts.append(f"{getattr(f, 'subject', '')} {getattr(f, 'predicate', '')}")
parts.append(f"{getattr(f, 'subject', '')}{getattr(f, 'predicate', '')}")
for t in timeline[:5]:
if isinstance(t, dict):
title = (t.get("title") or "").strip()