Files
Neo-ZQYY/docs/prd/Neo_Specs/NS2-ai-prompt-refinement.md
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

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

559 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NS2AI Prompt 细化 — ai-prompt-refinement
> 优先级NS1 完成后立即执行Prompt 细化是 AI 功能闭环的关键)
> 预估工作量:中等
> 前置条件P5-A 已完成AI 骨架就绪、NS1 已完成(后端 API 数据结构确定)
> 参考基准:`docs/prd/specs/P5-miniapp-ai-integration.md`P5-B 阶段定义)
> SPEC 状态:✅ 三件套已完成requirements.md → design.md → tasks.md
> SPEC 路径:`.kiro/specs/ai-prompt-refinement/`
> 实施状态:⏳ 未开始(代码实施待启动)
---
## 一、背景与目标
P5-A 阶段已交付 AI 集成管道:百炼封装、缓存 API、SSE 框架、应用 2/8 完整实现、应用 1/3/4/5/6/7 的触发机制和调用骨架。但应用 1/3/4/5/6/7 的 `build_prompt()` 函数仍为占位骨架,核心数据字段(`consumption_records``service_history``objective_data` 等)标记为 TODO。
本 SPEC 目标:将 6 个应用的 Prompt 拼接函数从骨架升级为完整实现,使 AI 应用能基于真实数据生成有价值的分析结果。
### 当前骨架状态
| 应用 | 文件 | 骨架状态 | 待细化字段 |
|------|------|---------|-----------|
| 应用 1 | `app1_chat.py` | 页面上下文文本化工具留接口 | `page_context` + `screen_content` 合并为 `build_page_text()` 输出(详见 3.7 设计决策) |
| 应用 3 | `app3_clue.py` | `build_prompt()` 占位 | `consumption_records`DWD+DWS 订单明细全维度) |
| 应用 4 | `app4_analysis.py` | `build_prompt()` 占位 | `service_history``assistant_info` |
| 应用 5 | `app5_tactics.py` | `build_prompt()` 占位 | `service_history``assistant_info`(同应用 4 |
| 应用 6 | `app6_note.py` | `build_prompt()` 占位 | `consumption_data`(同应用 3 的 main_data |
| 应用 7 | `app7_customer.py` | `build_prompt()` 占位 | `objective_data`(同应用 3 的 main_data |
---
## 二、技术架构
### 2.1 数据获取层(新建共享模块)
Prompt 细化的核心是从数据库获取真实数据并格式化为 AI 可读的 JSON。多个应用共享相同的数据获取逻辑应抽取为共享模块
```
apps/backend/app/ai/
├── data_fetchers/ 🆕 新建
│ ├── __init__.py
│ ├── member_data.py # 客户数据获取(消费记录、会员卡、余额等)
│ ├── assistant_data.py # 助教数据获取(基本信息、服务历史)
│ ├── service_history.py # 服务记录获取(助教-客户维度)
│ └── page_context.py # 页面上下文文本化(应用 1 专用)
├── apps/
│ ├── app1_chat.py 🔧 补充页面文本化调用
│ ├── app3_clue.py 🔧 补充 consumption_records 拼接
│ ├── app4_analysis.py 🔧 补充 service_history + assistant_info
│ ├── app5_tactics.py 🔧 补充 service_history + assistant_info
│ ├── app6_note.py 🔧 补充 consumption_data
│ └── app7_customer.py 🔧 补充 objective_data
```
### 2.2 数据获取函数设计
#### `member_data.py` — 客户数据获取(应用 3/6/7 共用)
```python
async def fetch_member_consumption_data(
site_id: int, member_id: int, months: int = 3
) -> dict:
"""获取客户近 N 个月消费数据DWD+DWS 全维度)。
返回结构对应 P5 spec 中 main_data
- consumption_records: 台桌结账 + 商城订单明细列表
- member_cards: 会员卡明细
- card_balance_total: 储值卡余额合计
- stored_value_balance_total: 储值余额合计
- expected_visit_date: 预计到店日期
- days_since_last_visit: 距上次到店天数
"""
```
数据源(全部通过 FDW
- `fdw_etl.v_dwd_settlement_head` + `fdw_etl.v_dwd_table_fee_log`(台桌结账)
- `fdw_etl.v_dwd_store_goods_sale`(商城订单)
- `fdw_etl.v_dwd_recharge_order`(充值记录)
- `fdw_etl.v_dim_member_card_account`(会员卡明细)
- `fdw_etl.v_dws_member_consumption_summary`(消费汇总 + 余额)
- `fdw_etl.v_dws_member_visit_detail`(到店明细 → 计算预计到店日期)
> ⚠️ 金额口径:使用 `items_sum`= table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money禁止 `consume_money`
> ⚠️ 会员字段断档DQ-6/DQ-7member_phone/member_name 通过 member_id JOIN dim_member
#### `assistant_data.py` — 助教数据获取(应用 4/5 共用)
```python
async def fetch_assistant_info(
site_id: int, assistant_id: int
) -> dict:
"""获取助教基本信息(花名、级别、工龄等)。"""
async def fetch_service_history(
site_id: int, assistant_id: int, member_id: int, months: int = 3
) -> list[dict]:
"""获取助教服务该客户的历史记录。"""
```
数据源:
- `fdw_etl.v_dim_assistant`(基本信息)
- `fdw_etl.v_dwd_assistant_service_log`(服务记录,按助教+客户筛选)
- `fdw_etl.v_dws_member_assistant_relation_index`(关系指数)
- `fdw_etl.v_dws_member_assistant_intimacy`(亲密度)
#### `page_context.py` — 页面上下文文本化(应用 1 专用)
```python
async def build_page_text(
source_page: str, context_data: dict, site_id: int
) -> str:
"""将页面数据转换为 AI 可读的结构化文本。
根据 source_page 类型,从数据库获取对应数据并格式化。
"""
```
支持的页面类型及数据获取:
| source_page | 数据获取 | 文本化内容 |
|-------------|---------|-----------|
| `task-detail` | coach_tasks + member + notes + ai_cache | 任务信息 + 客户信息 + 备注 + AI 分析 |
| `customer-detail` | member + consumption + clues | 客户全信息 + 消费记录 + 维客线索 |
| `coach-detail` | assistant + tasks + notes | 助教信息 + 任务统计 + 备注 |
| `board-finance` | finance DWS 汇总 | 财务数据摘要 |
| `board-customer` | 当前筛选维度 top 列表 | 客户排名摘要 |
| `board-coach` | 当前筛选维度排名 | 助教排名摘要 |
| `performance` | salary_calc + daily_detail | 绩效数据摘要 |
| `my-profile` | user info + assistant binding | 个人信息摘要 |
### 2.3 数据库连接模式
- 所有 FDW 查询通过 `get_etl_readonly_connection(site_id)``fdw_etl.*` 视图
- 业务库查询通过 `get_connection()`
- 查询前必须 `SET LOCAL app.current_site_id`RLS 隔离)
---
## 三、各应用 Prompt 细化详细设计
### 3.1 应用 3客户数据维客线索分析
`build_prompt()` 需要拼接的完整 JSON 结构(参考 P5 spec
```json
{
"current_time": "2026-03-08 14:30:25",
"member_nickname": "客户昵称",
"main_data": {
"consumption_records": [
{
"settle_date": "2026-03-05",
"settle_type": 1,
"items_sum": 280.00,
"table_charge_money": 180.00,
"assistant_pd_money": 80.00,
"assistant_cx_money": 0,
"goods_money": 20.00,
"room_name": "VIP-3",
"duration_minutes": 120,
"assistant_names": ["张助教"]
}
],
"member_cards": [
{"card_type": "金卡", "balance": 1500.00, "gift_balance": 200.00}
],
"card_balance_total": 1700.00,
"stored_value_balance_total": 1700.00,
"expected_visit_date": "2026-03-10",
"days_since_last_visit": 15
},
"reference": {
"app6_clues": [...],
"app8_history": [
{"generated_at": "2026-03-01", "clues": [...]},
{"generated_at": "2026-02-15", "clues": [...]}
]
}
}
```
实现要点:
- `consumption_records``v_dwd_settlement_head` + `v_dwd_table_fee_log` 获取settle_type IN (1,3)
- 金额字段逐项拆分table_charge_money / assistant_pd_money / assistant_cx_money / goods_money不使用 consume_money
- `expected_visit_date``v_dws_member_visit_detail` 的到店间隔推算
- reference 从 `ai_cache` 获取 app6 + app8 最近 2 套历史
### 3.2 应用 4关系分析/任务建议
`build_prompt()` 需要拼接的完整 JSON 结构:
```json
{
"current_time": "2026-03-08 14:30:25",
"assistant_info": {
"nickname": "张助教",
"level": "高级",
"hire_date": "2024-06-01",
"tenure_months": 21,
"monthly_customers": 45,
"performance_tier": "A档"
},
"service_history": [
{
"service_date": "2026-03-01",
"duration_minutes": 90,
"items_sum": 250.00,
"room_name": "VIP-3",
"is_pd": true
}
],
"task_assignment_basis": "优先召回",
"customer_data": {
"system_data": { /* 3 main_data */ },
"notes": [
{"recorded_by": "张助教", "content": "客户喜欢打斯诺克", "created_at": "2026-02-28"}
]
},
"reference": {
"app8_current": {...},
"app8_history": [...]
}
}
```
实现要点:
- `assistant_info``v_dim_assistant` + `v_dws_assistant_salary_calc` 获取
- `service_history``v_dwd_assistant_service_log` 按助教+客户筛选
- `customer_data.system_data` 复用 `member_data.fetch_member_consumption_data()`
- `customer_data.notes``biz.notes` 获取该客户的全部备注
- reference 从 `ai_cache` 获取 app8 最新 + 最近 2 套历史
### 3.3 应用 5话术参考
结构与应用 4 基本一致,额外增加 `task_suggestion` 字段(应用 4 的返回结果)。
实现要点:
- 复用应用 4 的 `assistant_info` + `service_history` + `customer_data` 获取逻辑
- `task_suggestion` 从应用 4 的 `run()` 返回值传入(调用链:应用 4 → 应用 5
### 3.4 应用 6备注分析
```json
{
"current_time": "2026-03-08 14:30:25",
"current_note": {
"content": "客户说下周要带朋友来打球",
"recorded_by": "张助教",
"created_at": "2026-03-08 14:25:00"
},
"reference": {
"member_nickname": "王先生",
"consumption_data": { /* 3 main_data */ },
"all_notes": [...],
"app3_clues": [...],
"app8_history": [...]
}
}
```
实现要点:
- `current_note` 从触发上下文获取(备注提交事件传入)
- `consumption_data` 复用 `member_data.fetch_member_consumption_data()`
- `all_notes``biz.notes` 获取所有助教对该客户的全部备注
- reference 从 `ai_cache` 获取 app3 + app8 历史
### 3.5 应用 7客户分析
```json
{
"current_time": "2026-03-08 14:30:25",
"member_id": 12345,
"member_nickname": "王先生",
"objective_data": { /* 3 main_data */ },
"subjective_data": {
"notes": [
{"recorded_by": "张助教", "content": "...", "created_at": "..."}
]
},
"reference": {
"app8_current": {...},
"app8_history": [...]
}
}
```
实现要点:
- `objective_data` 复用 `member_data.fetch_member_consumption_data()`
- `subjective_data.notes``biz.notes` 获取全部备注,标注创建者
- 主观信息需在 Prompt 中标注【来源XXX请甄别信息真实性】
- reference 从 `ai_cache` 获取 app8 最新 + 最近 2 套历史
### 3.6 应用 1biz_params 权限隔离(已实现,需确认)
> ✅ RNS1.4 已在 `app1_chat.py` 的 `_build_system_prompt()` 中实现 biz_params 拼接。
应用 1 通过 `biz_params.user_prompt_params` 向百炼 AI 传入用户身份信息,实现数据查询隔离:
```python
system_content = {
"task": "你是台球门店的 AI 助手...",
"biz_params": {
"user_prompt_params": {
"User_ID": str(user_id),
"Role": role, # "助教" | "管理者"
"Nickname": nickname,
},
},
}
```
权限控制规则(百炼平台侧执行):
- 助教身份:仅允许查询与该助教相关的数据,禁止查询其他助教业绩/工资/客户关系等敏感数据,禁止查询门店级财务数据
- 管理者身份:可查询该门店下所有数据
- 所有查询必须包含 `site_id` 过滤
NS2 需确认事项:
- 前端调用 `POST /api/chat/conversations/:id/messages` 时,是否正确传入 `user_id`/`role`/`nickname`
- 后端从 JWT token 中提取用户信息并传入 `_build_system_prompt()`,确保不可伪造
### 3.7 应用 1页面上下文传递与文本化
#### P5 原始设计 vs NS2 实际方案
P5 PRD 定义应用 1 首条 Prompt 包含三个字段:
| 字段 | P5 定义 | 含义 |
|------|---------|------|
| `source_page` | 来源页面标识 | 如 `task-detail``board-finance` |
| `page_context` | 页面上下文摘要 | 结构化数据,后端可从 DB 获取 |
| `screen_content` | 用户当前屏幕可见内容的文本化描述 | 需前端传入当前视口内容 |
AI需求2.md 原文对应:
- `page_context` → "用户正在查看页面内容:页面上下文(来源页面+内容摘要)"
- `screen_content` → "用户页面视野内容:当前屏幕内容"
#### `screen_content` 的设计决策
> ⚠️ **设计决策NS2 与 P5 的差异点)**NS2 不要求前端传入 `screen_content`,改由后端根据 `contextType` + `contextId` + 筛选参数自动查询数据库,生成等效的页面上下文文本。
**决策理由:**
1. 微信小程序前端难以将当前屏幕 DOM 序列化为结构化文本(无 `innerText` 等 Web API
2. RNS1.4 已实现 `contextType`/`contextId` 参数机制,后端可据此精确获取页面数据
3. 后端自动查询可获取比前端视口更完整的上下文(如关联的 AI 分析、历史备注等)
4. 看板类页面通过额外传入筛选参数(`timeDimension``dimension` 等),后端可还原用户当前视图的数据范围
**等效覆盖说明:**
- P5 的 `page_context`(结构化数据摘要)→ NS2 通过 `build_page_text()` 从 DB 获取,完全覆盖
- P5 的 `screen_content`(屏幕可见内容)→ NS2 通过 `contextType` + 筛选参数推断用户当前视图,近似覆盖
- 对于详情类页面task-detail、customer-detail 等),后端获取的数据与用户屏幕内容高度一致
- 对于看板类页面,通过筛选参数还原当前视图的数据维度和范围
**局限性:**
- 无法获取用户滚动位置(如长列表中用户正在看第几条)
- 无法获取用户输入中但未提交的内容
- 看板页面若前端未传筛选参数,使用默认值可能与用户实际视图不一致
#### 实际方案:后端根据 contextType 自动获取页面上下文
与 RNS1.4 已有的 `contextType`/`contextId` 参数兼容:
```
前端传入 contextType="task-detail" + contextId="12345"+ 看板类页面的筛选参数)
→ 后端 build_page_text("task-detail", 12345, site_id, filters?)
→ 后端从数据库获取任务详情、客户信息、备注、AI 分析等
→ 格式化为结构化中文文本(同时覆盖 page_context 和 screen_content 的信息需求)
→ 拼接为首条 user message 的 page_context 字段
```
#### contextType 映射表
| 前端 contextType | 后端数据获取 | 文本化内容 |
|-----------------|-------------|-----------|
| `task-detail` | coach_tasks + member + notes + ai_cache | 任务信息 + 客户信息 + 备注 + AI 分析 |
| `customer-detail` | member + consumption + clues | 客户全信息 + 消费记录 + 维客线索 |
| `coach-detail` | assistant + tasks + notes | 助教信息 + 任务统计 + 备注 |
| `board-finance` | finance DWS 汇总(按当前筛选条件) | 财务数据摘要 |
| `board-customer` | 当前筛选维度 top 列表 | 客户排名摘要 |
| `board-coach` | 当前筛选维度排名 | 助教排名摘要 |
| `performance` | salary_calc + daily_detail | 绩效数据摘要 |
| `my-profile` | user info + assistant binding | 个人信息摘要 |
| `task-list` | 长按的任务摘要 + 客户-助教关系 | 任务概要 |
| `customer-service-records` | 服务记录列表 | 服务记录摘要 |
#### 前端需要补充的参数
当前前端仅传 `contextType` + `contextId`,对于看板类页面需要额外传入筛选条件:
| contextType | 必传参数 | 可选参数 |
|-------------|---------|---------|
| `task-detail` | contextIdtaskId | — |
| `customer-detail` | contextIdmemberId | — |
| `coach-detail` | contextIdassistantId | — |
| `board-finance` | — | `timeDimension`(时间维度)、`areaFilter`(区域筛选) |
| `board-customer` | — | `dimension`(排序维度)、`typeFilter`(类型筛选) |
| `board-coach` | — | `dimension``projectFilter``timeDimension` |
| `performance` | — | `timeDimension` |
| `task-list` | contextIdtaskId | — |
| `my-profile` | — | — |
#### 实现要点
- 每个页面类型对应一个文本化函数,在 `data_fetchers/page_context.py` 中实现
- 文本化输出为结构化中文描述(非 JSON便于 AI 理解上下文
- 数据量控制:每个页面上下文不超过 2000 字符,避免 token 浪费
- 敏感信息脱敏:不传入 member_phone 等断档字段
- 看板类页面:若前端未传筛选条件,使用默认值(如 board-finance 默认"本月"
- 错误降级数据获取失败时page_context 传入"页面上下文获取失败",不阻断对话
---
## 四、数据库审查
### 4.1 数据获取涉及的表
| 数据获取函数 | 涉及表 | 连接方式 |
|-------------|--------|---------|
| `fetch_member_consumption_data` | v_dwd_settlement_head, v_dwd_table_fee_log, v_dwd_store_goods_sale, v_dwd_recharge_order, v_dim_member_card_account, v_dws_member_consumption_summary, v_dws_member_visit_detail | FDW |
| `fetch_assistant_info` | v_dim_assistant, v_dws_assistant_salary_calc | FDW |
| `fetch_service_history` | v_dwd_assistant_service_log, v_dws_member_assistant_relation_index, v_dws_member_assistant_intimacy | FDW |
| `build_page_text` | 以上全部 + biz.coach_tasks, biz.notes, biz.ai_cache, public.member_retention_clue | FDW + 业务库 |
### 4.2 无需新建表
本 SPEC 不需要新建数据库表。所有数据获取基于 NS1 已建立的 FDW 映射和 P4/P5-A 已建立的业务表。
### 4.3 性能考虑
- `fetch_member_consumption_data` 涉及 7 张 FDW 表查询,建议:
- 消费记录限制最近 3 个月WHERE settle_date >= NOW() - INTERVAL '3 months'
- 单次查询最多返回 100 条记录
- 考虑使用 NS1 中建议的 `biz.task_detail_cache` 缓存聚合结果
- 页面文本化(应用 1需要实时获取数据建议设置 5 秒查询超时
---
## 五、调用链与数据流
### 5.1 消费事件链
```
新结算单到达
→ 应用 3.build_prompt(member_data) → 百炼 API → ai_cache
→ 应用 8.run() → member_retention_clue
→ 应用 7.build_prompt(member_data + notes) → 百炼 API → ai_cache
→ 应用 4.build_prompt(assistant_data + member_data) → 百炼 API → ai_cache
→ 应用 5.build_prompt(app4_result) → 百炼 API → ai_cache
```
### 5.2 备注提交事件链
```
备注提交
→ 应用 6.build_prompt(note + member_data) → 百炼 API → ai_cache
→ 应用 8.run() → member_retention_clue
```
### 5.3 应用 1 对话流
```
用户点击 AI 入口
→ 前端传入 contextType + contextId+ 看板类页面的筛选参数)
→ 后端 build_page_text(contextType, contextId, site_id, filters?)
→ 从数据库获取对应页面数据,格式化为结构化中文文本
→ 文本同时覆盖 P5 定义的 page_context数据摘要和 screen_content屏幕内容
→ 拼接为首条 user message 的 page_context 字段
→ 注入 biz_paramsUser_ID/Role/Nickname到 system prompt
→ SSE 流式调用百炼 API
```
> ⚠️ 与 P5 PRD 原始设计的差异(详见 3.7 设计决策):
> P5 设计为前端传入 `source_page` + `page_context` + `screen_content` 三个独立字段,
> NS2 采用后端自动查询方案,前端仅传入 `contextType` + `contextId` + 筛选参数,
> 后端通过 `build_page_text()` 生成合并的页面上下文文本,等效覆盖 `page_context` 和 `screen_content` 的信息需求。
---
## 六、参考文档
| 文档 | 路径 | 用途 |
|------|------|------|
| P5 AI 集成 spec | `docs/prd/specs/P5-miniapp-ai-integration.md` | Prompt JSON 结构定义、调用链时序 |
| AI 应用 Prompt | `docs/prd/ai-app-prompts.md` | 8 个应用的 System Prompt、biz_params 定义 |
| AI 需求文档 | `docs/prd/AI需求2.md` | 8 个应用的详细需求表、传参格式 |
| AI 应用→页面映射 | `docs/reports/2026-03-20__ai_app_page_mapping.md` | 各应用输出内容在哪个页面的什么位置展示 |
| API 契约 | `docs/miniprogram-dev/API-contract.md` | 接口响应格式(决定数据结构) |
| DWD-DOC 标杆 | `docs/reports/DWD-DOC/` | 金额口径、字段语义权威参考 |
| AI 应用骨架代码 | `apps/backend/app/ai/apps/app*.py` | 当前骨架实现(含 biz_params 已实现) |
| 百炼客户端 | `apps/backend/app/ai/bailian_client.py` | API 调用封装 |
| 缓存服务 | `apps/backend/app/ai/cache_service.py` | ai_cache 读写 |
| NS1 接口设计 | `docs/prd/Neo_Specs/NS1-xcx-backend-api.md` | 后端数据结构参考 |
| RNS1.4 任务计划 | `.kiro/specs/rns1-chat-integration/tasks.md` | 当前 chat 模块实施进度 |
---
## 七、预审查清单(已确认)
> 以下问题已在 SPEC 细化阶段requirements.md / design.md中逐一确认。
### 7.1 数据结构
1. **消费记录字段范围**:每条记录包含 `settle_date``settle_type``items_sum``table_charge_money``assistant_pd_money``assistant_cx_money``goods_money``room_name``duration_minutes``assistant_names` 共 10 个字段。不包含折扣明细和支付方式明细token 预算有限,这些字段对 AI 分析价值低)。
2. **服务记录字段范围**:每条记录包含 `service_date``duration_minutes``items_sum``room_name``is_pd`(是否陪打)。不包含台桌类型和客户评价。
3. **备注内容截断**:单条备注最大 500 字符,超出截断并附加"…(已截断)"标记。备注总数最多 50 条(按 `created_at DESC`)。
4. **会员卡明细粒度**:仅包含 `card_type`(卡类型)、`balance`(余额)、`gift_balance`(赠送余额),不含卡号、开卡日期、有效期。
### 7.2 Prompt 优化
5. **Token 预算**:应用 3/4/5/6/7 的 system message content ≤ 8000 字符(约 4000 token应用 1 的 system prompt含页面上下文≤ 4000 字符(约 2000 token
6. **数据时间窗口**:默认近 3 个月,通过 `months` 参数可配置。各应用统一使用 3 个月窗口。
7. **空数据处理**:使用明确的空状态提示词(如"该客户暂无消费记录,请基于已有信息分析"),不传入空数据不做说明。`reference` 无历史数据时设为空对象并标注"暂无历史线索"。
### 7.3 页面文本化(应用 1
8. **文本化格式**:输出为结构化中文描述文本(分段标题 + 缩进),非 JSON。中文描述更便于 AI 理解上下文语义。
9. **数据量控制**:每个页面上下文统一 ≤ 2000 字符,不按页面类型动态调整。超出截断并标注。
10. **实时性要求**:实时获取最新数据(不使用缓存),设置 5 秒 FDW 查询超时。数据获取失败时返回降级文本,不阻断对话。
### 7.4 性能与安全
11. **FDW 查询并发**:支持。使用 `asyncio.gather(return_exceptions=True)` 并发执行多个数据获取函数,部分失败不阻断。同一连接上的多个 FDW 查询串行执行(共享 RLS 设置)。
12. **数据脱敏**`member_phone` 已断档不传。会员信息通过 `member_id JOIN v_dim_member (scd2_is_current=1)` 获取昵称,不传入手机号等敏感字段。`build_page_text()` 输出中不包含 `member_phone`
13. **错误降级**:部分失败继续。失败部分使用默认空值(空数组/空对象),在 Prompt 中标注"该部分数据获取失败",继续生成 Prompt 并调用百炼 API。确保 Prompt JSON 不含 `null`
---
## 八、任务清单(已细化,详见 SPEC tasks.md
> SPEC 三件套已完成:`requirements.md`14 条需求)→ `design.md`17 个正确性属性)→ `tasks.md`17 个顶层任务)。
> 以下为 PRD 级任务概览,详细实施步骤见 `.kiro/specs/ai-prompt-refinement/tasks.md`。
### Batch A共享数据获取层tasks 1-4
- [ ] T1创建 `data_fetchers/` 模块骨架(`__init__.py` + 3 个子模块)
- [ ] T2实现 `member_data.py``fetch_member_consumption_data` + `fetch_member_notes`
- [ ] T3实现 `assistant_data.py``fetch_assistant_info` + `fetch_service_history`
- [ ] T4检查点 — 数据获取层完成
### Batch BPrompt 拼接实现tasks 5-11
- [ ] T5完善 `app3_clue.py``build_prompt()`async + 真实数据)
- [ ] T6完善 `app4_analysis.py``build_prompt()`asyncio.gather 并发获取)
- [ ] T7完善 `app5_tactics.py``build_prompt()`(复用 App4 + task_suggestion
- [ ] T8完善 `app6_note.py``build_prompt()`(消费数据 + 全部备注)
- [ ] T9完善 `app7_customer.py``build_prompt()`(客观+主观数据,标注来源)
- [ ] T10检查点 — 应用 3-7 完成
- [ ] T11实现错误降级与 Token 预算控制
### Batch C应用 1 页面文本化 + 前端配合tasks 12-15
- [ ] T12实现 `page_context.py`10 种页面类型文本化)
- [ ] T13集成 `app1_chat.py``_build_page_context()` 调用 `build_page_text()`
- [ ] T14检查点 — 页面上下文完成
- [ ] T15前端看板筛选参数传递小程序 ai-float-button + chat 页面参数解析)
### Batch D集成联调tasks 16-17
- [ ] T16集成连线dispatcher await 正确性 + 端到端验证)
- [ ] T17最终检查点
### 属性测试(可选,标记 * 的子任务)
- 17 个正确性属性P1-P17对应 Hypothesis 属性测试
- 测试文件:`tests/test_data_fetchers/``tests/test_ai_apps/`