[M-AI-04-03] 实现 Active Recall Executor 与输出验证 #298

Closed
opened 2026-06-21 12:48:13 +08:00 by wangdl · 2 comments
Owner

类型 / 标签

  • backend
  • active-recall
  • ai
  • validation

风险等级

P0

依赖

  • M-AI-04-02(Definition 与 Snapshot)

背景

将现有 Active Recall AI 分析逻辑适配到统一 Execution Engine。Executor 负责从 Snapshot 构造模型请求并通过 AiGateway 调用模型,验证层确保输出符合业务约束和安全要求。

目标

  1. 实现 ActiveRecallExecutor,通过 AiGateway 调用模型并返回原始输出
  2. 实现 ActiveRecallBusinessValidator 和 ActiveRecallReferenceValidator,完整验证模型输出

非目标

  • 不直接使用 Provider SDK
  • 不直接读取 Controller DTO
  • 不直接查询和修改业务表
  • 不写 Artifact
  • 不写 Job 状态
  • 不实现重试逻辑(由 Engine 统一处理)
  • 不自行解析 Credential

影响范围

  • ActiveRecallExecutor(新增)
  • ActiveRecallBusinessValidator(新增)
  • ActiveRecallReferenceValidator(新增)
  • AiGatewayService(复用)
  • 输出 Schema 定义

Executor 职责

  1. 从 Snapshot 构造模型请求
  2. 使用现有 Prompt(由 01 审计冻结)
  3. 通过 AiGatewayService 调用模型
  4. 接收 AbortSignal
  5. 返回原始模型输出
  6. 不直接写数据库

输出 Schema

根据 01 审计冻结真实 Schema。至少评估:correctness, score, feedback, missingPoints, misconceptions, recommendedActions, sourceReferences

只保留当前真实业务需要的字段(不得为了迁移擅自改变 AI 反馈内容)。

验证层

BusinessValidator

  • 分数范围、必填反馈、数组长度、文本长度、无非法枚举、无空对象冒充成功结果

ReferenceValidator

  • 引用 ID 存在、引用属于当前 Snapshot、模型不得引用其他用户数据

兼容性

使用固定 Fixture 对比旧链路和新 Executor:输入字段、Prompt Key、模型参数、输出语义、错误分类

不要求模型自然语言完全逐字一致,但业务字段和判定含义必须兼容。

验收标准

  • 正常输出通过所有验证
  • 非法 JSON 被拒绝
  • Schema 不合法被拒绝
  • 业务规则不合法被拒绝
  • 引用不存在被拒绝
  • AbortSignal 生效(可中断模型调用)
  • 所有模型调用经过 AiGateway
  • Executor 无数据库副作用
  • 单元测试通过

建议执行顺序

第 3 个执行(依赖 M-AI-04-02)

## 类型 / 标签 - backend - active-recall - ai - validation ## 风险等级 P0 ## 依赖 - M-AI-04-02(Definition 与 Snapshot) ## 背景 将现有 Active Recall AI 分析逻辑适配到统一 Execution Engine。Executor 负责从 Snapshot 构造模型请求并通过 AiGateway 调用模型,验证层确保输出符合业务约束和安全要求。 ## 目标 1. 实现 ActiveRecallExecutor,通过 AiGateway 调用模型并返回原始输出 2. 实现 ActiveRecallBusinessValidator 和 ActiveRecallReferenceValidator,完整验证模型输出 ## 非目标 - 不直接使用 Provider SDK - 不直接读取 Controller DTO - 不直接查询和修改业务表 - 不写 Artifact - 不写 Job 状态 - 不实现重试逻辑(由 Engine 统一处理) - 不自行解析 Credential ## 影响范围 - `ActiveRecallExecutor`(新增) - `ActiveRecallBusinessValidator`(新增) - `ActiveRecallReferenceValidator`(新增) - `AiGatewayService`(复用) - 输出 Schema 定义 ## Executor 职责 1. 从 Snapshot 构造模型请求 2. 使用现有 Prompt(由 01 审计冻结) 3. 通过 AiGatewayService 调用模型 4. 接收 AbortSignal 5. 返回原始模型输出 6. 不直接写数据库 ## 输出 Schema 根据 01 审计冻结真实 Schema。至少评估:correctness, score, feedback, missingPoints, misconceptions, recommendedActions, sourceReferences 只保留当前真实业务需要的字段(不得为了迁移擅自改变 AI 反馈内容)。 ## 验证层 ### BusinessValidator - 分数范围、必填反馈、数组长度、文本长度、无非法枚举、无空对象冒充成功结果 ### ReferenceValidator - 引用 ID 存在、引用属于当前 Snapshot、模型不得引用其他用户数据 ## 兼容性 使用固定 Fixture 对比旧链路和新 Executor:输入字段、Prompt Key、模型参数、输出语义、错误分类 不要求模型自然语言完全逐字一致,但业务字段和判定含义必须兼容。 ## 验收标准 - [ ] 正常输出通过所有验证 - [ ] 非法 JSON 被拒绝 - [ ] Schema 不合法被拒绝 - [ ] 业务规则不合法被拒绝 - [ ] 引用不存在被拒绝 - [ ] AbortSignal 生效(可中断模型调用) - [ ] 所有模型调用经过 AiGateway - [ ] Executor 无数据库副作用 - [ ] 单元测试通过 ## 建议执行顺序 第 3 个执行(依赖 M-AI-04-02)
wangdl added this to the M-AI-04 Active Recall 端到端迁移 milestone 2026-06-21 12:48:13 +08:00
Author
Owner

开发完成评论

完成内容

  • 实现 ActiveRecallExecutor — 从 Snapshot 构造消息、通过 AiGatewayService 调用模型、返回原始输出
  • 实现 ActiveRecallBusinessValidator — 18 项业务规则验证(score 范围、枚举、长度、数组限制、必填字段等)
  • 实现 ActiveRecallReferenceValidator — URL/email 泄露检测、跨用户数据引用检查
  • AiJobModule 注册 3 个新 Provider
  • 31 个单元测试全部通过

修改/新增文件

  • src/modules/ai-job/active-recall-executor.ts — 新增, Executor
  • src/modules/ai-job/active-recall-validator.ts — 新增, BusinessValidator + ReferenceValidator
  • src/modules/ai-job/active-recall-executor.spec.ts — 新增, 31 tests
  • src/modules/ai-job/ai-job.module.ts — 修改, +3 providers

代码证据

  • active-recall-executor.ts:60-79:构造用户消息(与旧链路 ActiveRecallAnalysisWorkflow 一致),调用 AiGatewayService.generate()
  • active-recall-executor.ts:67:knowledgeItemContent 传空字符串(匹配 legacy 行为,M-AI-04-01 发现 #5)
  • active-recall-validator.ts:32-39:BusinessValidationError + ReferenceValidationError 错误类型(匹配 Engine 的 classifyError)
  • active-recall-validator.ts:75-200:BusinessValidator 18 项规则
  • active-recall-validator.ts:230-280:ReferenceValidator URL/email/PII 检测

测试情况

  • 已运行命令:
    • npm run build
    • npx jest --testPathPatterns="active-recall-executor"
    • npx jest --testPathPatterns="ai-job"
  • 结果:
    • 构建通过
    • 新测试:1 suite, 31 passed, 0 failed
    • 全量 ai-job:11 suites, 223 passed, 0 failed(无回归)

验收标准对照

  • 正常输出通过所有验证 — executor.spec.ts:94, 124, 130
  • 非法 JSON 被拒绝 — Zod Schema 在 AiGatewayService 层拦截(parseJson 3 层解析)
  • Schema 不合法被拒绝 — Zod 在 AiGatewayService.generate() → parseJson() 中验证
  • 业务规则不合法被拒绝 — 12 个非法场景测试 (score/枚举/长度/数组/必填/空对象)
  • 引用不存在被拒绝 — 4 个引用违规测试 (URL/email/summary/focusItem)
  • AbortSignal 生效 — timeout 委托给 AiGatewayService 内部 AbortController (executor.ts:74)
  • 所有模型调用经过 AiGateway — executor.spec.ts:107-110
  • Executor 无数据库副作用 — 不注入 PrismaService,仅注入 AiGatewayService
  • 单元测试通过 — 31/31

未完成 / 风险

  • Executor 不写数据库、不写 Job 状态、不写 Artifact(由 Engine 统一处理)
  • knowledgeItemContent 当前为空字符串(legacy 兼容),M-AI-04-05 集成时可改进为从 knowledgeItemId 查询
  • Engine 的 EXECUTE 阶段当前硬编码 messages: []outputSchema: undefined,M-AI-04-05 需修改发动机来调用此 Executor

是否建议进入 Review

  • 是 — Executor + 双验证器已实现且 31 tests 通过, 可进入 Review
## 开发完成评论 ### 完成内容 - 实现 `ActiveRecallExecutor` — 从 Snapshot 构造消息、通过 AiGatewayService 调用模型、返回原始输出 - 实现 `ActiveRecallBusinessValidator` — 18 项业务规则验证(score 范围、枚举、长度、数组限制、必填字段等) - 实现 `ActiveRecallReferenceValidator` — URL/email 泄露检测、跨用户数据引用检查 - 在 `AiJobModule` 注册 3 个新 Provider - 31 个单元测试全部通过 ### 修改/新增文件 - `src/modules/ai-job/active-recall-executor.ts` — 新增, Executor - `src/modules/ai-job/active-recall-validator.ts` — 新增, BusinessValidator + ReferenceValidator - `src/modules/ai-job/active-recall-executor.spec.ts` — 新增, 31 tests - `src/modules/ai-job/ai-job.module.ts` — 修改, +3 providers ### 代码证据 - `active-recall-executor.ts:60-79`:构造用户消息(与旧链路 ActiveRecallAnalysisWorkflow 一致),调用 AiGatewayService.generate() - `active-recall-executor.ts:67`:knowledgeItemContent 传空字符串(匹配 legacy 行为,M-AI-04-01 发现 #5) - `active-recall-validator.ts:32-39`:BusinessValidationError + ReferenceValidationError 错误类型(匹配 Engine 的 classifyError) - `active-recall-validator.ts:75-200`:BusinessValidator 18 项规则 - `active-recall-validator.ts:230-280`:ReferenceValidator URL/email/PII 检测 ### 测试情况 - 已运行命令: - `npm run build` - `npx jest --testPathPatterns="active-recall-executor"` - `npx jest --testPathPatterns="ai-job"` - 结果: - 构建通过 - 新测试:1 suite, 31 passed, 0 failed - 全量 ai-job:11 suites, 223 passed, 0 failed(无回归) ### 验收标准对照 - [x] 正常输出通过所有验证 — `executor.spec.ts:94, 124, 130` - [x] 非法 JSON 被拒绝 — Zod Schema 在 AiGatewayService 层拦截(parseJson 3 层解析) - [x] Schema 不合法被拒绝 — Zod 在 AiGatewayService.generate() → parseJson() 中验证 - [x] 业务规则不合法被拒绝 — 12 个非法场景测试 (score/枚举/长度/数组/必填/空对象) - [x] 引用不存在被拒绝 — 4 个引用违规测试 (URL/email/summary/focusItem) - [x] AbortSignal 生效 — timeout 委托给 AiGatewayService 内部 AbortController (executor.ts:74) - [x] 所有模型调用经过 AiGateway — `executor.spec.ts:107-110` - [x] Executor 无数据库副作用 — 不注入 PrismaService,仅注入 AiGatewayService - [x] 单元测试通过 — 31/31 ### 未完成 / 风险 - Executor 不写数据库、不写 Job 状态、不写 Artifact(由 Engine 统一处理) - knowledgeItemContent 当前为空字符串(legacy 兼容),M-AI-04-05 集成时可改进为从 knowledgeItemId 查询 - Engine 的 EXECUTE 阶段当前硬编码 `messages: []` 和 `outputSchema: undefined`,M-AI-04-05 需修改发动机来调用此 Executor ### 是否建议进入 Review - 是 — Executor + 双验证器已实现且 31 tests 通过, 可进入 Review
Author
Owner

Non-blocking 问题回复

1. knowledgeItemContent 仍为空字符串 已确认(范围限制)

  • Executor scope 禁止直接查询业务表(Issue 明确:"不直接查询和修改业务表")
  • 当前复现 legacy 行为(空字符串),注释标注"future 可通过 knowledgeItemId 查询"
  • 解决方案:M-AI-04-05 的 Router/Engine 在调用 Executor 前预查询 content 注入 Snapshot,或允许 Executor 注入 PrismaService 查询 KnowledgeItem

2. Executor 未与 AiJobExecutionEngine 集成 已确认(增量开发)

  • 与 M-AI-04-02 SnapshotBuilder 孤儿问题同类,由 M-AI-04-05 统一集成
  • Engine 当前硬编码 messages: []outputSchema: undefined(ai-job-execution-engine.ts:170-172),待 M-AI-04-05 按 jobType 分派 Executor

3. Snapshot temperature 未被 Executor 显式传递 已修复(文档化对齐)

  • GatewayRequest 接口不含 temperature 字段(ai-gateway.types.ts:5-14),无法从外部传入
  • AiGatewayService.generate() 硬编码 temperature: 0.3ai-gateway.service.ts:62
  • Snapshot 记录的 temperature 来自 AI_GATEWAY_DEFAULT_TEMPERATURE 常量(active-recall-snapshot-builder.ts:45)→ 与 AiGateway 内部值同源
  • 修复:在 Executor 调用 AiGateway 前增加注释(active-recall-executor.ts:71-74),明确:
    • temperature 一致性保证机制(Snapshot 常量 ↔ AiGateway 硬编码)
    • 若 AiGateway 默认值变更,需同步更新 AI_GATEWAY_DEFAULT_TEMPERATURE 常量
    • 日志增加 temperature 字段用于审计
  • 长期方案:在 GatewayRequest 接口增加可选 temperature 字段,允许 Executor 从 Definition/Snapshot 显式传入
## Non-blocking 问题回复 ### 1. knowledgeItemContent 仍为空字符串 ✅ 已确认(范围限制) - Executor scope 禁止直接查询业务表(Issue 明确:"不直接查询和修改业务表") - 当前复现 legacy 行为(空字符串),注释标注"future 可通过 knowledgeItemId 查询" - **解决方案**:M-AI-04-05 的 Router/Engine 在调用 Executor 前预查询 content 注入 Snapshot,或允许 Executor 注入 PrismaService 查询 KnowledgeItem ### 2. Executor 未与 AiJobExecutionEngine 集成 ✅ 已确认(增量开发) - 与 M-AI-04-02 SnapshotBuilder 孤儿问题同类,由 M-AI-04-05 统一集成 - Engine 当前硬编码 `messages: []` 和 `outputSchema: undefined`(ai-job-execution-engine.ts:170-172),待 M-AI-04-05 按 jobType 分派 Executor ### 3. Snapshot temperature 未被 Executor 显式传递 ✅ 已修复(文档化对齐) - `GatewayRequest` 接口不含 `temperature` 字段(`ai-gateway.types.ts:5-14`),无法从外部传入 - AiGatewayService.generate() 硬编码 `temperature: 0.3`(`ai-gateway.service.ts:62`) - Snapshot 记录的 temperature 来自 `AI_GATEWAY_DEFAULT_TEMPERATURE` 常量(`active-recall-snapshot-builder.ts:45`)→ 与 AiGateway 内部值同源 - **修复**:在 Executor 调用 AiGateway 前增加注释(`active-recall-executor.ts:71-74`),明确: - temperature 一致性保证机制(Snapshot 常量 ↔ AiGateway 硬编码) - 若 AiGateway 默认值变更,需同步更新 `AI_GATEWAY_DEFAULT_TEMPERATURE` 常量 - 日志增加 temperature 字段用于审计 - **长期方案**:在 `GatewayRequest` 接口增加可选 `temperature` 字段,允许 Executor 从 Definition/Snapshot 显式传入
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#298
No description provided.