Files
Neo 70324d8542 chore: 文档与 IDE 配置整理
- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro)
- CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/
- 新增 /spec-close、/pre-change 两个工作流命令
- DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表)
- BD_Manual → BD_manual 命名统一(48 个文件)
- 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数)
- 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表)
- 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档)
- docs/database/README.md 索引更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:02:37 +08:00

18 KiB
Raw Permalink Blame History

实施计划NS2 AI Prompt 细化

概述

按照设计文档,将实施拆分为:共享数据获取层 → 应用 3/4/5/6/7 Prompt 拼接 → 应用 1 页面上下文 → 前端筛选参数 → 集成联调。每个任务增量构建确保无孤立代码。属性测试Hypothesis和单元测试作为可选子任务紧跟实现步骤。

后端使用 PythonFastAPI + asyncio测试使用 Hypothesis + pytest。

任务

  • 1. 创建共享数据获取层基础结构

    • 1.1 创建 apps/backend/app/ai/data_fetchers/ 模块骨架
      • 创建 __init__.py,导出 fetch_member_consumption_datafetch_assistant_infofetch_service_historyfetch_member_notesbuild_page_text
      • 创建 member_data.pyassistant_data.pypage_context.py 空文件
      • 需求: 1.1, 2.1, 8.1
  • 2. 实现客户消费数据获取member_data.py

    • 2.1 实现 fetch_member_consumption_data(site_id, member_id, months=3)

      • 使用 get_etl_readonly_connection(site_id) + SET LOCAL app.current_site_id 获取 FDW 连接
      • v_dwd_settlement_head + v_dwd_table_fee_log 获取台桌结账(settle_type IN (1,3)
      • v_dwd_store_goods_sale 获取商城订单
      • v_dim_member_card_account 获取会员卡明细
      • v_dws_member_consumption_summary + v_dws_member_visit_detail 获取汇总和到店数据
      • v_dim_memberscd2_is_current=1)获取会员昵称
      • 消费记录限制 100 条,按 settle_date DESC 排序,超出标注 truncated
      • 金额使用 items_sum 口径,拆分 assistant_pd_money / assistant_cx_money
      • 5 秒查询超时,超时抛出 TimeoutError
      • 需求: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 11.1, 11.2, 11.3, 11.4, 11.5, 11.7
    • 2.2 实现 fetch_member_notes(site_id, member_id, limit=50)

      • 使用 get_connection() 查询 biz.notes
      • created_at DESC 排序,最多 limit
      • 单条备注内容截断 500 字符,超出附加"…(已截断)"
      • 需求: 4.3, 4.4, 6.3, 6.4, 14.4
    • 2.3 编写属性测试数据获取返回结构完整性P1

      • Property 1: 数据获取函数返回结构完整性
      • Mock 数据库返回随机行,验证 fetch_member_consumption_data() 返回字典包含所有必需键
      • 验证每条消费记录包含 settle_datesettle_typeitems_sum 等 10 个字段
      • 测试文件: tests/test_data_fetchers/test_member_data_props.py
      • 验证: 需求 1.1, 1.3, 1.5, 2.1, 2.2, 2.4
    • 2.4 编写属性测试正向交易过滤P2+ 金额口径P3+ 记录限制与排序P4

      • Property 2: 消费记录仅包含正向交易 — 生成混合 settle_type 记录,验证输出仅含 1/3
      • Property 3: 金额口径使用 items_sum — 验证输出包含 items_sum 且不含 consume_money
      • Property 4: 消费记录数量限制与排序 — 生成 0-200 条记录,验证输出 ≤100 且 settle_date 降序
      • 测试文件: tests/test_data_fetchers/test_member_data_props.py
      • 验证: 需求 1.2, 1.4, 1.9, 3.5, 11.3, 11.4, 14.3
    • 2.5 编写属性测试备注截断P6+ 备注数量限制P17

      • Property 6: 备注截断不变量 — 生成 0-2000 字符字符串,验证截断后 ≤500超长以"…(已截断)"结尾
      • Property 17: 备注数量限制 — 生成 0-100 条备注,验证输出 ≤50 且 created_at 降序
      • 测试文件: tests/test_data_fetchers/test_member_data_props.py
      • 验证: 需求 4.4, 6.4, 14.4
    • 2.6 编写单元测试member_data 边界情况

      • 客户无消费记录时返回空数组和默认值
      • 客户无备注时返回空数组
      • FDW 查询超时时抛出 TimeoutError
      • 会员不存在时 member_nickname 为空字符串
      • 测试文件: tests/test_data_fetchers/test_data_fetchers_unit.py
      • 需求: 1.10, 3.4, 6.6, 12.1, 12.2
  • 3. 实现助教数据获取assistant_data.py

    • 3.1 实现 fetch_assistant_info(site_id, assistant_id)

      • v_dim_assistant 获取花名、级别、入职日期
      • v_dws_assistant_salary_calc 获取本月客户数、绩效档位
      • 计算 tenure_months(入职日期到当前日期)
      • 助教不存在时抛出 ValueError("assistant not found")
      • 需求: 2.1, 2.5, 2.6, 11.1, 11.2
    • 3.2 实现 fetch_service_history(site_id, assistant_id, member_id, months=3)

      • v_dwd_assistant_service_log 获取服务记录,WHERE is_trash = false
      • v_dws_member_assistant_relation_index 获取关系指数
      • v_dws_member_assistant_intimacy 获取亲密度
      • service_date DESC 排序
      • 需求: 2.2, 2.3, 2.4, 11.1, 11.2
    • 3.3 编写属性测试废单排除P5

      • Property 5: 废单记录排除
      • 生成含 is_trash 标记的服务记录,验证输出不含 is_trash=true 的记录
      • 测试文件: tests/test_data_fetchers/test_assistant_data_props.py
      • 验证: 需求 2.3
    • 3.4 编写单元测试assistant_data 边界情况

      • 助教不存在时抛出 ValueError
      • 无服务历史时返回空列表
      • FDW 查询超时时抛出 TimeoutError
      • 测试文件: tests/test_data_fetchers/test_data_fetchers_unit.py
      • 需求: 2.6, 4.5, 12.1
  • 4. 检查点 — 数据获取层完成

    • 确保所有测试通过ask the user if questions arise.
  • 5. 实现应用 3 Prompt 拼接app3_clue.py

    • 5.1 改造 app3_clue.pybuild_prompt()async def

      • 新增 site_id 参数,调用 fetch_member_consumption_data() 获取真实消费数据
      • 组装 Prompt JSONcurrent_timemember_nicknamemain_datareference
      • referenceai_cache 获取 app6_clues + 最近 2 套 app8_history
      • 空数据时标注"该客户暂无消费记录"
      • run() 中调用 build_prompt()await
      • 需求: 3.1, 3.2, 3.3, 3.4, 3.5, 12.1, 12.2, 12.3
    • 5.2 编写属性测试App3 Prompt 结构完整性P7 局部)

      • Property 7App3 部分): build_prompt 返回结构完整性
      • Mock 数据获取返回随机数据,验证 Prompt JSON 包含 current_timemember_nicknamemain_datareference 顶层键
      • 测试文件: tests/test_ai_apps/test_build_prompt_props.py
      • 验证: 需求 3.1, 3.2
  • 6. 实现应用 4 Prompt 拼接app4_analysis.py

    • 6.1 改造 app4_analysis.pybuild_prompt()async def

      • 使用 asyncio.gather 并发调用 fetch_assistant_info() + fetch_service_history() + fetch_member_consumption_data()
      • 调用 fetch_member_notes() 获取客户备注
      • 组装 Prompt JSONcurrent_timeassistant_infoservice_historytask_assignment_basiscustomer_data(含 system_data + notes)、reference
      • referenceai_cache 获取 app8_current + 最近 2 套 app8_history
      • 部分数据获取失败时使用 return_exceptions=True 降级处理
      • 需求: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 11.6, 12.1, 12.4
    • 6.2 编写属性测试App4 Prompt 结构完整性P7 局部)

      • Property 7App4 部分): build_prompt 返回结构完整性
      • Mock 数据获取返回随机数据,验证 Prompt JSON 包含 current_timeassistant_infoservice_historycustomer_datareference 顶层键
      • 测试文件: tests/test_ai_apps/test_build_prompt_props.py
      • 验证: 需求 4.1, 4.2
  • 7. 实现应用 5 Prompt 拼接app5_tactics.py

    • 7.1 改造 app5_tactics.pybuild_prompt()async def

      • 复用应用 4 的数据获取逻辑(fetch_assistant_info + fetch_service_history + fetch_member_consumption_data
      • context["app4_result"] 获取 task_suggestion,缺失时设为空对象
      • 组装 Prompt JSON同 App4 结构 + task_suggestion
      • 需求: 5.1, 5.2, 5.3, 5.4
    • 7.2 编写属性测试App5 task_suggestion 传递P8

      • Property 8: App5 task_suggestion 传递
      • 生成随机 app4_result(含空/缺失),验证 task_suggestion 字段正确传递或设为空对象
      • 测试文件: tests/test_ai_apps/test_build_prompt_props.py
      • 验证: 需求 5.3, 5.4
  • 8. 实现应用 6 Prompt 拼接app6_note.py

    • 8.1 改造 app6_note.pybuild_prompt()async def
      • 调用 fetch_member_consumption_data() 获取消费数据
      • 调用 fetch_member_notes() 获取全部备注作为 all_notes
      • 组装 Prompt JSONcurrent_timecurrent_notereference(含 member_nicknameconsumption_dataall_notesapp3_cluesapp8_history
      • 空备注时 all_notes 设为空数组
      • 需求: 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 12.1, 12.2
  • 9. 实现应用 7 Prompt 拼接app7_customer.py

    • 9.1 改造 app7_customer.pybuild_prompt()async def

      • 调用 fetch_member_consumption_data() 获取客观数据
      • 调用 fetch_member_notes() 获取备注作为 subjective_data.notes
      • 每条备注标注"【来源:{recorded_by},请甄别信息真实性】"
      • 组装 Prompt JSONcurrent_timemember_idmember_nicknameobjective_datasubjective_datareference
      • 空备注时标注"该客户暂无主观备注信息"
      • 需求: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 12.1, 12.2
    • 9.2 编写属性测试App7 主观信息标注P9

      • Property 9: App7 主观信息来源标注
      • 生成随机备注(含 recorded_by),验证 Prompt 中每条备注附带"【来源:{recorded_by},请甄别信息真实性】"
      • 测试文件: tests/test_ai_apps/test_build_prompt_props.py
      • 验证: 需求 7.4
  • 10. 检查点 — 应用 3-7 Prompt 拼接完成

    • 确保所有测试通过ask the user if questions arise.
  • 11. 实现错误降级与 Token 预算控制

    • 11.1 在各应用 build_prompt() 中实现统一错误降级模式

      • 使用 asyncio.gather(return_exceptions=True) 捕获部分失败
      • 失败部分使用默认空值(空数组/空对象),附带提示文本
      • 确保 Prompt JSON 不含 NonePython/ nullJSON使用 default=str 处理 datetime/Decimal
      • 需求: 12.1, 12.2, 12.3, 12.4
    • 11.2 实现 Prompt 字符数限制

      • 应用 3/4/5/6/7 的 system message content ≤ 8000 字符
      • 消费记录超 100 条时截断并标注"仅展示最近 100 条,共 {total} 条"
      • 备注超 50 条时截断并标注"仅展示最近 50 条备注"
      • 单个文本字段不超过 1000 字符
      • 需求: 14.1, 14.3, 14.4, 14.5
    • 11.3 编写属性测试错误降级P14+ Token 预算P15

      • Property 14: 错误降级产生合法 Prompt — 随机让 0-N 个数据获取函数失败,验证 build_prompt 返回合法 JSON不含 null
      • Property 15: 应用 3-7 Prompt Token 预算 — 生成大量数据,验证 system message ≤ 8000 字符
      • 测试文件: tests/test_ai_apps/test_build_prompt_props.py
      • 验证: 需求 12.1, 12.2, 12.4, 14.1
  • 12. 实现页面上下文文本化page_context.py

    • 12.1 实现 build_page_text(source_page, context_id, site_id, filters) 框架

      • 根据 source_page 路由到对应内部函数(_text_task_detail()_text_customer_detail() 等)
      • 输出结构化中文描述文本(分段标题 + 缩进),非 JSON
      • 输出限制 2000 字符,超出截断并标注
      • 未识别的 source_page 返回空字符串
      • 数据获取失败返回"页面上下文获取失败,请直接描述您的问题"
      • 需求: 8.1, 8.2, 8.8, 8.9, 8.11
    • 12.2 实现详情类页面文本化函数

      • _text_task_detail(task_id, site_id) — 从 biz.coach_tasks + 会员信息 + 备注 + ai_cache 获取数据
      • _text_customer_detail(member_id, site_id) — 复用 fetch_member_consumption_data() + 维客线索
      • _text_coach_detail(assistant_id, site_id) — 复用 fetch_assistant_info() + 任务统计 + 备注
      • _text_customer_service_records(member_id, site_id) — 服务记录列表
      • _text_task_list(task_id, site_id) — 任务摘要 + 客户-助教关系
      • 不传入 member_phone 等敏感字段
      • 需求: 8.3, 8.4, 8.5, 8.12
    • 12.3 实现看板类与其他页面文本化函数

      • _text_board_finance(site_id, filters) — 财务 DWS 汇总,默认"本月"
      • _text_board_customer(site_id, filters) — 客户排名 top 列表
      • _text_board_coach(site_id, filters) — 助教排名
      • _text_performance(site_id, filters)v_dws_assistant_salary_calc 绩效数据
      • _text_my_profile(site_id) — 用户信息 + 助教绑定
      • 看板未传筛选参数时使用默认值
      • 需求: 8.6, 8.7, 8.10
    • 12.4 编写属性测试页面上下文长度P10+ 类型覆盖P11+ 敏感字段排除P12

      • Property 10: 页面上下文输出长度约束 — 生成大量数据,验证 build_page_text() 输出 ≤ 2000 字符
      • Property 11: 页面上下文覆盖所有页面类型 — 枚举 10 种类型,验证不抛异常且返回非空字符串
      • Property 12: 页面上下文不泄露敏感字段 — 生成含手机号的数据,验证输出不含 member_phone
      • 测试文件: tests/test_data_fetchers/test_page_context_props.py
      • 验证: 需求 8.8, 8.1, 8.2, 8.12
    • 12.5 编写单元测试page_context 边界情况

      • 未识别 contextType 时返回空字符串
      • 看板无筛选参数时使用默认值
      • 数据获取失败时返回降级文本
      • task-detail 页面完整流程验证
      • 测试文件: tests/test_data_fetchers/test_data_fetchers_unit.py
      • 需求: 8.10, 8.11, 9.5
  • 13. 实现应用 1 页面上下文集成app1_chat.py

    • 13.1 改造 app1_chat.py_build_page_context()async def

      • 调用 page_context.build_page_text(source_page, context_id, site_id, filters) 获取页面上下文文本
      • source_page 映射到 contextTypecontextId 传入 context_id
      • 看板类页面从请求参数提取筛选参数传入 filters
      • contextType 为空或未识别时跳过页面上下文注入
      • 将返回文本作为 system prompt 中的 page_context 字段注入
      • 确保 biz_params.user_prompt_paramsUser_IDRoleNickname)注入后仍正确存在
      • system prompt 总字符数控制在 4000 以内
      • 需求: 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 14.2
    • 13.2 编写属性测试biz_params 不变量P13+ App1 Token 预算P16

      • Property 13: biz_params 注入后不变量 — 生成随机用户信息,验证 user_prompt_params 包含 User_IDRoleNickname 且值一致
      • Property 16: 应用 1 System Prompt Token 预算 — 生成大量页面上下文,验证 system prompt ≤ 4000 字符
      • 测试文件: tests/test_ai_apps/test_app1_props.py
      • 验证: 需求 9.6, 13.2, 14.2
    • 13.3 编写单元测试App1 页面上下文集成

      • contextType 为空时跳过页面上下文
      • task-detail 页面上下文注入后 system prompt 结构正确
      • 看板筛选参数正确传递到 build_page_text()
      • 页面上下文获取失败时使用降级文本
      • 测试文件: tests/test_ai_apps/test_ai_apps_unit.py
      • 需求: 9.1, 9.4, 9.5, 12.5
  • 14. 检查点 — 页面上下文与应用 1 集成完成

    • 确保所有测试通过ask the user if questions arise.
  • 15. 前端看板筛选参数传递(小程序端)

    • 15.1 修改看板页面跳转 chat 的参数传递

      • board-finance 页面跳转时传入 timeDimension + areaFilter
      • board-customer 页面跳转时传入 dimension + typeFilter
      • board-coach 页面跳转时传入 dimension + projectFilter + timeDimension
      • 将筛选参数编码为 chat 页面 URL 查询参数
      • 需求: 10.1, 10.2, 10.3, 10.4
    • 15.2 后端从请求中提取看板筛选参数

      • 在 chat 消息接口中解析 URL 查询参数中的筛选参数
      • 将筛选参数传入 build_page_text()filters 参数
      • 需求: 10.4, 9.4
  • 16. 集成连线与最终验证

    • 16.1 确保 dispatcher 调用链中 build_prompt()await 正确

      • 消费事件链App3 → App8 → App7 + App4 → App5所有 build_prompt 调用加 await
      • 备注事件链App6 → App8build_prompt 调用加 await
      • 验证 run() 方法中 build_prompt() 调用已改为 await
      • 需求: 3.1, 4.1, 5.1, 6.1, 7.1, 11.6
    • 16.2 编写单元测试:各应用完整流程

      • App3 完整流程Mock 数据 → build_prompt → 验证 JSON 结构和内容
      • App4 并发数据获取:验证 asyncio.gather 调用
      • App5 task_suggestion 传递:验证 context["app4_result"] 正确传入
      • App7 主观信息标注:验证备注标注格式
      • RLS 隔离:验证 get_etl_readonly_connection 被调用且传入正确 site_id
      • 测试文件: tests/test_ai_apps/test_ai_apps_unit.py
      • 需求: 3.1, 4.1, 5.3, 7.4, 11.2, 13.1
  • 17. 最终检查点 — 全部完成

    • 确保所有测试通过ask the user if questions arise.

备注

  • 标记 * 的任务为可选,可跳过以加速 MVP
  • 每个任务引用具体需求编号,确保可追溯
  • 属性测试验证设计文档中的 17 个正确性属性P1-P17
  • 检查点确保增量验证
  • 测试文件组织:tests/test_data_fetchers/(数据获取层)、tests/test_ai_apps/(应用层)