2026-01-21 22:31:03 +01:00
|
|
|
|
"""
|
|
|
|
|
|
共享状态 Schema(对话 Agent 与后台 Agent 共用)
|
|
|
|
|
|
"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
|
2026-01-21 22:31:03 +01:00
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Dict, List, Optional
|
|
|
|
|
|
|
|
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
|
2026-04-02 12:00:00 +08:00
|
|
|
|
from app.agents.stage_constants import CHAT_STAGES
|
|
|
|
|
|
|
2026-01-21 22:31:03 +01:00
|
|
|
|
|
|
|
|
|
|
class SlotData(BaseModel):
|
|
|
|
|
|
"""Slot 数据结构"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
|
2026-01-21 22:31:03 +01:00
|
|
|
|
snippet: Optional[str] = None
|
|
|
|
|
|
segment_ids: List[str] = Field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MemoirStateSchema(BaseModel):
|
|
|
|
|
|
"""回忆录状态"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
|
2026-01-21 22:31:03 +01:00
|
|
|
|
stage_order: List[str]
|
|
|
|
|
|
current_stage: str
|
|
|
|
|
|
covered_stages: List[str]
|
|
|
|
|
|
slots: Dict[str, Dict[str, SlotData]]
|
|
|
|
|
|
|
|
|
|
|
|
def empty_slots_for_current_stage(self) -> List[str]:
|
|
|
|
|
|
stage_slots = self.slots.get(self.current_stage, {})
|
|
|
|
|
|
empty_keys: List[str] = []
|
|
|
|
|
|
for key, value in stage_slots.items():
|
|
|
|
|
|
if not value.snippet:
|
|
|
|
|
|
empty_keys.append(key)
|
|
|
|
|
|
return empty_keys
|
|
|
|
|
|
|
2026-02-13 21:45:56 +01:00
|
|
|
|
def empty_slots_for_stage(self, stage: str) -> List[str]:
|
|
|
|
|
|
"""获取指定阶段的空槽位"""
|
|
|
|
|
|
stage_slots = self.slots.get(stage, {})
|
|
|
|
|
|
return [key for key, value in stage_slots.items() if not value.snippet]
|
|
|
|
|
|
|
|
|
|
|
|
def filled_slots_for_stage(self, stage: str) -> Dict[str, str]:
|
|
|
|
|
|
"""获取指定阶段已填充的槽位及其内容"""
|
|
|
|
|
|
stage_slots = self.slots.get(stage, {})
|
|
|
|
|
|
return {
|
2026-03-19 14:36:14 +08:00
|
|
|
|
key: value.snippet for key, value in stage_slots.items() if value.snippet
|
2026-02-13 21:45:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def all_stages_coverage(self) -> Dict[str, Dict]:
|
|
|
|
|
|
"""获取所有阶段的覆盖情况摘要"""
|
|
|
|
|
|
coverage: Dict[str, Dict] = {}
|
|
|
|
|
|
for stage in self.stage_order:
|
|
|
|
|
|
stage_slots = self.slots.get(stage, {})
|
|
|
|
|
|
total = len(stage_slots)
|
|
|
|
|
|
filled = sum(1 for v in stage_slots.values() if v.snippet)
|
|
|
|
|
|
coverage[stage] = {
|
|
|
|
|
|
"total": total,
|
|
|
|
|
|
"filled": filled,
|
|
|
|
|
|
"empty": total - filled,
|
|
|
|
|
|
"ratio": filled / total if total > 0 else 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
return coverage
|
|
|
|
|
|
|
2026-01-21 22:31:03 +01:00
|
|
|
|
|
2026-04-02 12:00:00 +08:00
|
|
|
|
# 与 stage_constants.CHAT_STAGES 同一顺序;list() 避免与元组共享可变别名
|
|
|
|
|
|
DEFAULT_STAGE_ORDER: list[str] = list(CHAT_STAGES)
|
2026-01-21 22:31:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def default_slots() -> Dict[str, Dict[str, SlotData]]:
|
|
|
|
|
|
return {
|
|
|
|
|
|
"childhood": {
|
|
|
|
|
|
"place": SlotData(),
|
|
|
|
|
|
"people": SlotData(),
|
|
|
|
|
|
"daily_life": SlotData(),
|
|
|
|
|
|
"emotion": SlotData(),
|
|
|
|
|
|
"turning_event": SlotData(),
|
|
|
|
|
|
},
|
|
|
|
|
|
"education": {
|
|
|
|
|
|
"school": SlotData(),
|
|
|
|
|
|
"city": SlotData(),
|
|
|
|
|
|
"motivation": SlotData(),
|
|
|
|
|
|
"challenge": SlotData(),
|
|
|
|
|
|
"change": SlotData(),
|
|
|
|
|
|
},
|
|
|
|
|
|
"career": {
|
|
|
|
|
|
"job": SlotData(),
|
|
|
|
|
|
"environment": SlotData(),
|
|
|
|
|
|
"decision": SlotData(),
|
|
|
|
|
|
"pressure": SlotData(),
|
|
|
|
|
|
"growth": SlotData(),
|
|
|
|
|
|
},
|
|
|
|
|
|
"family": {
|
|
|
|
|
|
"relationship": SlotData(),
|
|
|
|
|
|
"conflict": SlotData(),
|
|
|
|
|
|
"support": SlotData(),
|
|
|
|
|
|
"responsibility": SlotData(),
|
|
|
|
|
|
"change": SlotData(),
|
|
|
|
|
|
},
|
|
|
|
|
|
"belief": {
|
|
|
|
|
|
"value": SlotData(),
|
|
|
|
|
|
"regret": SlotData(),
|
|
|
|
|
|
"pride": SlotData(),
|
|
|
|
|
|
"lesson": SlotData(),
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def default_state() -> MemoirStateSchema:
|
|
|
|
|
|
return MemoirStateSchema(
|
|
|
|
|
|
stage_order=DEFAULT_STAGE_ORDER,
|
|
|
|
|
|
current_stage=DEFAULT_STAGE_ORDER[0],
|
|
|
|
|
|
covered_stages=[],
|
|
|
|
|
|
slots=default_slots(),
|
|
|
|
|
|
)
|