70 lines
4.0 KiB
Python
70 lines
4.0 KiB
Python
"""管理会计OS — 知识摘要模块
|
||
|
||
仿 OpenCode 的持久记忆机制(summarizer + SummaryMessageID),但做了三处改进:
|
||
1. 分层压缩(日→周→月→全部),不是一次性全量压缩
|
||
2. 结构化存储(MySQL 关系表),不是 SQLite JSON 消息
|
||
3. 保留版本链,不是覆盖式压缩
|
||
|
||
参考:OpenCode SummarizeProvider 的 prompt 框架 + CMA OperationLog 的审计日志
|
||
"""
|
||
|
||
from sqlalchemy import Column, Integer, String, Text, DateTime, JSON, ForeignKey, Float, func
|
||
from app.database import Base
|
||
|
||
|
||
class KnowledgeEvent(Base):
|
||
"""关键事件记录
|
||
|
||
自动从 OperationLog 和其他数据源抽取的"值得记住"的事件。
|
||
每个事件是一个结构化记录,包含类型、级别、关联对象、摘要描述。
|
||
这是增量压缩的输入——摘要 agent 只处理"未摘要过"的新事件。
|
||
"""
|
||
__tablename__ = "knowledge_events"
|
||
|
||
id = Column(Integer, primary_key=True, index=True)
|
||
event_type = Column(String(30), nullable=False, comment="事件类型: kpi_change/alert/decision/plan/map/import/user_action")
|
||
event_level = Column(String(20), default="info", comment="info/warning/important/critical")
|
||
source = Column(String(50), nullable=True, comment="来源: operation_log/api/erp_sync/manual")
|
||
source_id = Column(Integer, nullable=True, comment="源记录ID(如 operation_log.id)")
|
||
target_type = Column(String(50), nullable=True, comment="关联对象类型: kpi/map/budget/alert/plan")
|
||
target_id = Column(Integer, nullable=True, comment="关联对象ID")
|
||
title = Column(String(300), nullable=False, comment="事件标题(一句话概括)")
|
||
description = Column(Text, nullable=True, comment="事件详细描述")
|
||
delta = Column(JSON, nullable=True, comment="变更字段和前后值: {field: {old: X, new: Y}}")
|
||
occurred_at = Column(DateTime, nullable=False, comment="事件发生时间")
|
||
created_at = Column(DateTime, server_default=func.now())
|
||
|
||
# 摘要追踪——记录该事件被哪些摘要(id列表)包含
|
||
summarized_in = Column(JSON, nullable=True, comment="包含此事件的摘要ID列表")
|
||
|
||
|
||
class KnowledgeSummary(Base):
|
||
"""知识摘要
|
||
|
||
分层存储:daily/weekly/monthly/cumulative
|
||
参考 OpenCode 的 summary_message_id 机制,但用结构化字段代替 message 指针。
|
||
"""
|
||
__tablename__ = "knowledge_summaries"
|
||
|
||
id = Column(Integer, primary_key=True, index=True)
|
||
level = Column(String(20), nullable=False, comment="摘要层级: daily/weekly/monthly/cumulative")
|
||
period_key = Column(String(20), nullable=False, comment="期间标识: 2026-06-12 / 2026-W24 / 2026-06 / cumulative")
|
||
title = Column(String(300), nullable=False, comment="摘要标题")
|
||
content = Column(Text, nullable=False, comment="摘要正文(纯文本/Markdown)")
|
||
event_ids = Column(JSON, nullable=True, comment="包含的事件ID列表")
|
||
|
||
# 核心指标变化(精简提取,用于快速问答)
|
||
kpi_changes = Column(JSON, nullable=True, comment="摘要期内的KPI变化统计: [{kpi_code, kpi_name, old_value, new_value, direction, alert_level}]")
|
||
decision_points = Column(JSON, nullable=True, comment="决策点: [{time, action, actor, result}]")
|
||
key_metrics = Column(JSON, nullable=True, comment="摘要期内的关键指标快照: {kpi_code: value}")
|
||
|
||
# 元信息
|
||
prev_summary_id = Column(Integer, nullable=True, comment="上一级摘要ID(如 daily→weekly 的链路)")
|
||
next_compressed_by = Column(Integer, nullable=True, comment="被哪个更高层摘要包含")
|
||
token_estimate = Column(Integer, default=0, comment="估算token数(用于触发压缩阈值判断)")
|
||
|
||
model = Column(String(50), nullable=True, comment="生成摘要使用的模型名")
|
||
generated_by = Column(String(100), nullable=True, comment="生成方式: auto_scheduler/manual_trigger")
|
||
is_stale = Column(Integer, default=0, comment="0=最新 1=已被上层摘要覆盖")
|
||
created_at = Column(DateTime, server_default=func.now())
|