WIP: memory system improvements (in progress)

Interview/chat prompt layers, reply planner, style profiles, memory
injection, interview meta store, and related tests. Work not finished.

Made-with: Cursor
This commit is contained in:
Kevin
2026-04-22 16:56:28 +08:00
parent e848f26354
commit 3121d1384d
28 changed files with 2790 additions and 452 deletions

View File

@@ -16,6 +16,8 @@ from app.agents.state_schema import KnownFact, MemoirStateSchema, PersonaThread
_QUESTION_SPLIT_RE = re.compile(r"[?]+")
_SENTENCE_SPLIT_RE = re.compile(r"(?<=[。!?!?])")
_PUNCT_RE = re.compile(r"[\s、“”()《》【】\\[\\],.!?:;\"'`~·…-]+")
# 「我演罗密欧」等扮演亲历,但排除「我演示…」类口癖
_AUTOBIO_IYAN_NOT_DEMO_RE = re.compile(r"我演(?!示)")
_TRAIT_HINTS: tuple[tuple[str, tuple[str, ...]], ...] = (
("执着坚持", ("坚持", "执着", "咬牙", "熬过", "顶住", "训练", "反复")),
@@ -337,6 +339,91 @@ def segments_are_only_duplicate_guard_fallback(segments: Iterable[str]) -> bool:
return len(parts) == 1 and parts[0] == DUPLICATE_QUESTION_GUARD_FALLBACK_ZH
# 助手可见回复中,明显声称「我本人有过某种人生经历」的高置信子串(偏保守、宁可漏网不误伤泛化共情)。
_AUTOBIOGRAPHICAL_MARKERS_ZH: tuple[str, ...] = (
"我小时候",
"我小学",
"我中学",
"我初中",
"我高中",
"我大学",
"我上学那",
"我念书",
"我读书那",
"我暗恋",
"我当时暗恋",
"我爸妈",
"我父亲",
"我母亲",
"我爹",
"我妈",
"我爷爷",
"我奶奶",
"我外公",
"我外婆",
"我前任",
"我老公",
"我老婆",
"我丈夫",
"我妻子",
"我男友",
"我女友",
"我对象",
"我儿子",
"我女儿",
"我孩子",
"我以前也",
"我当时也",
"我那时候也",
"我也经历过",
"我也有过",
"我也演过",
"我也上台",
"我演过",
"我饰演",
"我演出",
"我演的是",
"我演的",
"我扮演",
"感觉我熟",
"这我熟",
)
AUTOBIOGRAPHICAL_BOUNDARY_FALLBACK_ZH = (
"你刚说的这段很有画面,我想多听你讲讲那时候你心里是什么感觉。"
)
def _segment_has_autobiographical_claim_zh(text: str) -> bool:
s = (text or "").strip()
if not s:
return False
if _AUTOBIO_IYAN_NOT_DEMO_RE.search(s):
return True
return any(m and m in s for m in _AUTOBIOGRAPHICAL_MARKERS_ZH)
def apply_autobiographical_boundary_guard(
segments: Iterable[str],
) -> tuple[list[str], bool]:
"""将明显带有「助手自传式经历」的段落替换为中性承接,避免身份越界。"""
cleaned: list[str] = []
touched = False
for seg in segments:
text = str(seg or "").strip()
if not text:
continue
if _segment_has_autobiographical_claim_zh(text):
cleaned.append(AUTOBIOGRAPHICAL_BOUNDARY_FALLBACK_ZH)
touched = True
else:
cleaned.append(text)
if not cleaned:
cleaned = [AUTOBIOGRAPHICAL_BOUNDARY_FALLBACK_ZH]
touched = True
return cleaned, touched
def stage_slot_hint_lines(stage: str) -> list[str]:
keys = STAGE_SLOT_KEYS.get(stage, ())
stage_zh = STAGE_DISPLAY_ZH.get(stage, stage)