feat(api)!: memory single chain — async MemoryService, strict eval closure
Route all memory ingest/retrieve/enrichment/compaction through async MemoryService. Remove legacy sync memory implementations (ingest/retrieve/compaction); Celery and memoir Phase2 call asyncio.run into MemoryService-backed helpers. Memoir Phase1 batch ingest uses MemoryService.ingest_transcripts_batch; drop chapters. evidence_bundle_json mirror (Alembic 0015). Evaluation uses snapshot/link-only bundles; raise EvidenceClosureMissing instead of partial/fallback lineage tiers. Split memoir state into NarrativeCoverageState and InterviewControlState; delete the _interview_meta_store adapter layer. Remove rolling-query and recent-fact fallback settings from config and evidence assembly. Update judges, docs, tests, and PlaygroundPage alignment. Made-with: Cursor
This commit is contained in:
@@ -31,7 +31,11 @@ from app.agents.chat.reply_limits import (
|
||||
)
|
||||
from app.agents.chat.reply_planner import maybe_refine_turn_plan_with_llm
|
||||
from app.agents.chat.stage_detection import keyword_fallback_primary_stage
|
||||
from app.agents.state_schema import MemoirStateSchema
|
||||
from app.agents.state_schema import (
|
||||
MemoirStateSchema,
|
||||
interview_control_state,
|
||||
narrative_coverage_state,
|
||||
)
|
||||
from app.core.agent_logging import (
|
||||
agent_span,
|
||||
log_agent_payload,
|
||||
@@ -154,14 +158,14 @@ class InterviewAgent:
|
||||
text_for_model = self._resolve_text_for_model(
|
||||
user_message, normalized_user_message
|
||||
)
|
||||
empty_slots = memoir_state.prompt_empty_slots_for_current_stage()
|
||||
filled_slots = {
|
||||
key: value.snippet
|
||||
for key, value in memoir_state.slots.get(
|
||||
memoir_state.current_stage, {}
|
||||
).items()
|
||||
if value.snippet
|
||||
}
|
||||
narrative_state = narrative_coverage_state(memoir_state)
|
||||
control_state = interview_control_state(memoir_state)
|
||||
empty_slots = control_state.prompt_empty_slots_for_stage(
|
||||
narrative_state, memoir_state.current_stage
|
||||
)
|
||||
filled_slots = narrative_state.filled_slots_for_stage(
|
||||
memoir_state.current_stage
|
||||
)
|
||||
if detected_user_stage is not None:
|
||||
du = detected_user_stage
|
||||
else:
|
||||
@@ -173,7 +177,7 @@ class InterviewAgent:
|
||||
)
|
||||
recent_questions = extract_recent_questions(hw.window)
|
||||
conversation_turn_total = hw.turn_total
|
||||
all_stages_coverage = memoir_state.all_stages_coverage()
|
||||
all_stages_coverage = narrative_state.all_stages_coverage()
|
||||
persona = normalize_interview_persona(settings.chat_interview_persona)
|
||||
max_segments = int(settings.chat_interview_max_segments)
|
||||
max_tokens = int(settings.chat_interview_max_tokens)
|
||||
@@ -406,7 +410,11 @@ class InterviewAgent:
|
||||
if not self.llm:
|
||||
return ["你好呀~ 又见面了。今天想从人生里哪一小段回忆开始聊聊?"]
|
||||
try:
|
||||
empty_slots = memoir_state.prompt_empty_slots_for_current_stage()
|
||||
narrative_state = narrative_coverage_state(memoir_state)
|
||||
control_state = interview_control_state(memoir_state)
|
||||
empty_slots = control_state.prompt_empty_slots_for_stage(
|
||||
narrative_state, memoir_state.current_stage
|
||||
)
|
||||
empty_slots_readable = [SLOT_NAME_MAP.get(s, s) for s in empty_slots]
|
||||
persona = normalize_interview_persona(settings.chat_interview_persona)
|
||||
prompt = get_opening_prompt(
|
||||
|
||||
Reference in New Issue
Block a user