Skip to content

Phase 2: 叙事发现引擎 — 审查与遗留问题

审查日期:2026-05-26 状态:核心功能已完成,以下为遗留改进项

审查结果

Phase 2 实现了 spec 04-engine-design.md 中 Narrative Discovery 引擎的全部 4 个子系统:

  1. 叙事提取 — LLM 结构化输出 + Pydantic 校验
  2. 语义匹配 — pgvector 三档阈值(0.85/0.6)
  3. 状态机 — candidate→active→fading→archived + rejected
  4. 合并/分裂检测 — 语义聚类 + 情绪标准差

测试覆盖:44 单元 + 10 集成 = 54 测试全部通过

审查中已修复的问题

#问题修复
1active→fading 缺 trend 检查新增 is_weakening = ewma < latest 条件
2合并检测未过滤 strengthening新增 strength_latest > strength_ewma 过滤
3缺 EWMA 计算逻辑orchestrator 新增 _compute_ewma_updates(),create 时初始化,update 时递推
4search_similar 丢失 sources 字段重建 NarrativeRow 时赋值 sources=row.sources
5::vector 语法与 asyncpg 参数冲突改用 CAST(:param AS vector)
6Protocol 签名过时同步 get_by_statusadd_edgeembedding 参数
7未使用 import清理 fieldcombinationsNarrativeRelationTypeSequence
8集成测试 pgvector 扩展未安装CREATE EXTENSION IF NOT EXISTS vector
9集成测试 event loop 不匹配fixture 重置 module-level 单例

遗留改进项(不阻塞 Phase 3)

中优先级

#问题影响建议
M1process_article 中 embedding 重复调用matcher.embed() 和 create_candidate 时各调一次,浪费 token 和延迟将 matcher 返回的 embedding 传递给 create,避免二次调用
M2Vector 列维度硬编码 1536换 embedding 模型(如 3-large=3072)需改 ORM + 重建表EmbeddingProvider 已有 dimension 属性,ORM 应动态读取或使用迁移
M3process_articles 纯串行多篇文章逐条处理,高吞吐场景成瓶颈改为 asyncio.gather + 幂等去重

低优先级

#问题影响建议
L1单元测试多为 happy pathLLM 失败、DB 异常等 error path 未覆盖Phase 3 稳定后补充 error path 测试
L2FeedReader 默认 RSS 源可能失效部分源 URL 可能变更data_sources.yaml 动态加载 feed 配置
L3状态机 rejected 不在 NarrativeStatus 枚举中使用字符串 "rejected" 而非枚举考虑加入枚举或保持当前设计(rejected 只是临时状态)

测试矩阵

测试类型数量覆盖范围
单元 — narrative_models7Pydantic 模型校验、边界值
单元 — state_machine10全部状态转换 + 边界条件
单元 — merge_split6cosine similarity、聚类、标准差
单元 — feed_reader3FeedSource、HTML 清理
集成 — db2pgembed + ORM CRUD
集成 — narrative_engine8完整 pipeline(mock LLM + real DB)
总计54

基于 VitePress 构建