Files
hunjing/backend/app/models/xirang.py
T

81 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""息壤(记忆域)模型(data-model.md §3)。
- 三级:微痕 trace(短期)/ 明忆 explicit(低敏长期)/ 重忆 sensitive(须确认);
- 双源:user_explicit / self_inferred;
- 版本链:正影=新行 prev_version_id 指旧行,旧行 superseded 停止普通召回,内容不改写;
- 删除:tombstoned 墓碑不承载原文,主存储/检索/上下文全链路停用。
"""
from datetime import datetime
from sqlalchemy import DateTime, Float, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.ids import new_factual_record_id, new_memory_id, new_memory_trigger_id
from app.core.time import utc_now
from app.db.base import Base
class Memory(Base):
"""统一记忆表:三级 × 类型 × 状态 × 双源(契约词典 §10)。"""
__tablename__ = "memories"
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=new_memory_id)
character_id: Mapped[str] = mapped_column(String(80), index=True, nullable=False)
# trace / explicit / sensitive(§10.1)
tier: Mapped[str] = mapped_column(String(20), nullable=False, index=True)
# persona / episodic / instruction / relationship_view / fact_candidate(§10.2)
type: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
# candidate / pending / active / superseded / tombstoned(§10.3)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="candidate", index=True)
# user_explicit / self_inferred(§10.4)
source: Mapped[str] = mapped_column(String(20), nullable=False, default="self_inferred")
content: Mapped[str] = mapped_column(Text, nullable=False)
# 可解释性:指向镜树节点/事件(撤销与来源展开的依据)
source_refs_json: Mapped[str] = mapped_column(Text, nullable=False, default="[]")
sensitivity: Mapped[str] = mapped_column(String(20), nullable=False, default="none")
priority: Mapped[int] = mapped_column(Integer, nullable=False, default=50)
confidence: Mapped[float] = mapped_column(Float, nullable=False, default=0.5)
# 活力值:2^(-Δdays/半衰期) 衰减、命中强化(§6.2)
vitality: Mapped[float] = mapped_column(Float, nullable=False, default=1.0)
# 微痕有效期;空表示不过期
valid_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
# 记忆界域:境界记忆不进真界上下文(§5)
realm: Mapped[str] = mapped_column(String(40), nullable=False, default="reality")
prev_version_id: Mapped[str | None] = mapped_column(String(80), index=True)
# 召回统计(召回透明)
recall_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
last_recalled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=utc_now, onupdate=utc_now
)
class MemoryTrigger(Base):
"""记忆触发条件:keyword(微痕激活管线共用)与 disclosure(单一触发)。"""
__tablename__ = "memory_triggers"
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=new_memory_trigger_id)
memory_id: Mapped[str] = mapped_column(String(80), ForeignKey("memories.id"), index=True)
# keyword / disclosure / vector(§10.5)
kind: Mapped[str] = mapped_column(String(20), nullable=False)
pattern: Mapped[str] = mapped_column(String(200), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
class FactualRecord(Base):
"""实录(不可变):发生了什么 + 证据引用;与心痕(relationship_view)分离。"""
__tablename__ = "factual_records"
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=new_factual_record_id)
character_id: Mapped[str] = mapped_column(String(80), index=True, nullable=False)
canonization_id: Mapped[str] = mapped_column(String(80), index=True)
# 证据:路径节点引用 + 摘要
evidence_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
summary: Mapped[str] = mapped_column(Text, nullable=False, default="")
occurred_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)