[M-AI-04-04] 实现 Active Recall Projector、Artifact 与幂等结果写入 #299
Closed
opened 2026-06-21 12:48:14 +08:00 by wangdl
·
2 comments
Labels
Clear labels
adr
Area: adr
architecture
Area: architecture
area:activity
活动/统计
area:admin
管理后台
area:admin-api
area:ai
AI/RAG
area:ai-runtime
AI Runtime / AI 分析体系相关
area:analytics
area:api
API 接口
area:auth
认证与授权
area:cos
对象存储
area:database
数据库/Migration
area:import
文件导入/解析
area:knowledge
知识库/知识点
area:learning-info
area:learning-session
area:quiz
测验/自测
area:reading-event
area:reading-progress
area:review
复习系统
area:security
安全相关
audit
Area: audit
audit:api-admin-info
audit:api-info
audit:planned
已完成宏观规划,尚未代码审查
audit:reviewed
backend
Area: backend
billing
Area: billing
blocked-by:api-info-aggregation
blocked-by:api-info-core
blocked-by:api-info-ops
blocked-by:api-info-schema
blocked-by:processor
blocked-by:schema
compatibility
Area: compatibility
gate
Area: gate
infrastructure
Area: infrastructure
priority:p0
最高优先级,阻塞发布
priority:p1
高优先级,里程碑必需
priority:p2
中优先级,后续版本
prisma
Area: prisma
release
Area: release
repo:api
API 仓库 Issue
status:blocked
被阻塞
status:done
已完成
status:partial
status:todo
type:aggregation
type:bug
缺陷修复
type:design
设计
type:docs
文档
type:feature
新功能
type:migration
type:refactor
重构
type:test
work:admin-api
work:aggregation
work:api
work:artifact
题目/卡片产物
work:audit
work:circuit-breaker
熔断
work:contract
work:design
架构/协议设计工作
work:docs
work:export
work:extend-existing
work:internal-api
Runtime 内部接口
work:job
Job 调度相关
work:new-module
work:new-table
work:ops
work:query
work:quota
额度/限流
work:schema
Prisma Schema 设计
work:security
work:service
Service 层实现
work:snapshot
Snapshot 构建
work:test
No Label
Milestone
No items
No Milestone
M-AI-04 Active Recall 端到端迁移
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: wangdl/api-server#299
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
类型 / 标签
风险等级
P0
依赖
背景
将验证后的 Active Recall 输出原子投影到现有业务模型,建立 Job Artifact 关联。Projector 必须保证事务原子性和幂等性,杜绝部分业务结果。
目标
非目标
影响范围
ActiveRecallProjector(新增)AiJobArtifact表(写入)Projector
新增
ActiveRecallProjector输入:
{ job, snapshot, validatedOutput, transactionClient }事务范围(必须在同一 Transaction 中完成)
Artifact
类型以 01 审计为准,可能包括:analysis_result, focus_item, review_card
不得创建审计未确认的产物。
幂等
重复消费同一 Job 时:
优先使用:数据库唯一约束、稳定业务主键、Repository createMany(skipDuplicates)、事务内 upsert
禁止仅采用
先 find 再 create作为并发幂等保证。失败回滚
必须验证:
验收标准
建议执行顺序
第 4 个执行(依赖 M-AI-04-03)
开发完成评论
完成内容
ActiveRecallProjector(ResultProjector接口,key=active_recall_projector)reviewSuggestion创建(无二次 AI 调用,优于旧链路的 EventBus+AI 异步模式)RESULT_PROJECTORSmulti-provider 注册修改/新增文件
src/modules/ai-job/active-recall-projector.ts— 新增, Projector 实现src/modules/ai-job/active-recall-projector.spec.ts— 新增, 18 testssrc/modules/ai-job/ai-job.module.ts— 修改, +import +provider +RESULT_PROJECTORS factory 更新代码证据
active-recall-projector.ts:58-60:入口幂等检查(已有 Artifact → 直接返回)active-recall-projector.ts:68-90:AiAnalysisResult upsert by deterministic ID(ar_<jobId>)active-recall-projector.ts:96-130:FocusItem per weakness + upsertArtifact P2002 catchactive-recall-projector.ts:136-170:ReviewCard from reviewSuggestion(无 AI 调用)active-recall-projector.ts:191-205:upsertArtifact helper(P2002 幂等)ai-job.module.ts:39:RESULT_PROJECTORS factory 注入 ActiveRecallProjector测试情况
npm run buildnpx jest --testPathPatterns="active-recall-projector"npx jest --testPathPatterns="ai-job"验收标准对照
active-recall-projector.spec.ts:104-120(写入失败 → 异常传播 → tx 回滚)active-recall-projector.spec.ts:139-170(4 个幂等测试)active-recall-projector.spec.ts:180-203(artifactId 关联实体)ar_<jobId>未完成 / 风险
是否建议进入 Review
Non-blocking 问题回复
1. ReviewCard 幂等检查依赖业务内容而非 Job 关联 ✅ 已确认
2. FocusItem reason/suggestion 被丢弃 ✅ 已修复
reason和suggestion均为String? @db.Text(可写入)FocusItemsService.create()只传 userId/title/source/status)validatedOutput.focusItems(结构化数据)创建 FocusItem,写入 reason/suggestion/priorityfocusItems替代weaknesses作为 FocusItem 数据源(前者更丰富,含完整分析)FocusItem reason/suggestion 从 AI 输出写入3. ReviewCard difficulty 硬编码 'normal' ✅ 已确认
4. FocusItem.knowledgeBaseId 未设置 ✅ 已确认
knowledgeBaseId String?→ 可为 null,无约束冲突风险'unknown'(M-AI-04-01 发现 #3)测试