Files
Neo-ZQYY/docs/specs/ai-prompt-refinement/requirements.md
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

222 lines
23 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 细化
## 简介
NS2 将 P5-A 阶段交付的 6 个 AI 应用(应用 1/3/4/5/6/7`build_prompt()` 占位骨架升级为完整实现。核心工作包括:创建共享数据获取层(`data_fetchers/`)从 FDW 视图获取真实业务数据、完善 6 个应用的 Prompt 拼接函数使 AI 能基于真实数据生成分析、以及实现应用 1 的页面上下文文本化(根据 `contextType` 自动获取并格式化页面数据)。
### 依赖
- P5-AAI 集成管道)— 百炼封装、缓存 API、SSE 框架、应用 2/8 完整实现、应用 1/3/4/5/6/7 触发机制和调用骨架
- NS1小程序后端 API— 后端数据结构确定、FDW 映射建立
- RNS1.4CHAT 对齐与联调收尾)— chat 模块路径迁移、`contextType`/`contextId` 参数机制
### 来源文档
- `docs/prd/Neo_Specs/NS2-ai-prompt-refinement.md` — NS2 完整 PRD
- `docs/prd/specs/P5-miniapp-ai-integration.md` — P5 AI 集成 specPrompt JSON 结构定义)
- `docs/miniprogram-dev/API-contract.md` — 接口契约(数据结构参考)
- `docs/prd/Neo_Specs/NS1-xcx-backend-api.md` — NS1 后端 API spec
## 术语表
- **Data_Fetcher**:共享数据获取模块,位于 `apps/backend/app/ai/data_fetchers/`,负责从数据库查询并格式化 AI 所需数据
- **Build_Prompt**:各 AI 应用中的 Prompt 拼接函数,将数据获取层返回的数据组装为百炼 API 所需的消息列表
- **FDW_View**PostgreSQL Foreign Data Wrapper 视图,前缀 `fdw_etl.v_*`,用于从业务库只读访问 ETL 库数据
- **Page_Context_Builder**:页面上下文文本化模块,根据 `contextType` 从数据库获取页面数据并格式化为 AI 可读的结构化中文文本
- **Bailian_Client**:百炼 API 统一封装层,位于 `apps/backend/app/ai/bailian_client.py`
- **AI_Cache**AI 缓存表 `biz.ai_cache`,存储各应用的 AI 分析结果供前端读取和跨应用引用
- **items_sum**DWD-DOC 强制使用的消费金额口径,= `table_charge_money` + `goods_money` + `assistant_pd_money` + `assistant_cx_money` + `electricity_money`
- **RLS**Row Level Security通过 `SET LOCAL app.current_site_id` 实现多门店数据隔离
- **contextType**:前端跳转 chat 页面时传入的页面类型标识(如 `task-detail``board-finance`),后端据此路由到对应的文本化函数
- **contextId**:前端跳转 chat 页面时传入的页面实体 ID如 taskId、memberId
- **biz_params**:应用 1 system prompt 中注入的用户身份参数,百炼平台侧据此执行数据查询隔离
## 需求
### 需求 1客户消费数据获取模块
**用户故事:** 作为 AI 应用(应用 3/6/7我需要获取客户近期消费数据的完整结构化信息以便基于真实数据生成维客线索分析、备注分析和运营策略。
#### 验收标准
1. THE Data_Fetcher SHALL 提供 `fetch_member_consumption_data(site_id, member_id, months)` 异步函数,从 FDW_View 获取客户近 N 个月(默认 3 个月)的消费数据,返回包含以下字段的字典:`consumption_records`(消费记录列表)、`member_cards`(会员卡明细列表)、`card_balance_total`(储值卡余额合计)、`stored_value_balance_total`(储值余额合计)、`expected_visit_date`(预计到店日期)、`days_since_last_visit`(距上次到店天数)
2. THE Data_Fetcher SHALL 从 `fdw_etl.v_dwd_settlement_head``fdw_etl.v_dwd_table_fee_log` 获取台桌结账记录,从 `fdw_etl.v_dwd_store_goods_sale` 获取商城订单记录,仅包含正向交易(`settle_type IN (1, 3)`
3. THE Data_Fetcher SHALL 为每条消费记录返回以下金额拆分字段:`settle_date``settle_type``items_sum``table_charge_money``assistant_pd_money``assistant_cx_money``goods_money``room_name``duration_minutes``assistant_names`(服务助教列表)
4. THE Data_Fetcher SHALL 使用 `items_sum` 作为消费金额口径,禁止使用 `consume_money`
5. THE Data_Fetcher SHALL 从 `fdw_etl.v_dim_member_card_account` 获取会员卡明细,每张卡包含 `card_type`(卡类型)、`balance`(余额)、`gift_balance`(赠送余额)
6. THE Data_Fetcher SHALL 从 `fdw_etl.v_dws_member_visit_detail` 的到店间隔数据推算 `expected_visit_date`,并计算 `days_since_last_visit`
7. THE Data_Fetcher SHALL 通过 `member_id` JOIN `fdw_etl.v_dim_member``scd2_is_current=1`)获取会员昵称和手机号,禁止使用结算单冗余的 `member_phone`/`member_name` 字段
8. THE Data_Fetcher SHALL 在执行 FDW 查询前通过 `get_etl_readonly_connection(site_id)` 获取连接,并执行 `SET LOCAL app.current_site_id` 设置 RLS 隔离
9. THE Data_Fetcher SHALL 将单次查询返回的消费记录数限制为最多 100 条,按 `settle_date` 倒序排列
10. IF FDW 查询超时(超过 5 秒或连接失败THEN THE Data_Fetcher SHALL 抛出明确的异常,包含失败的视图名称和错误类型,由调用方决定降级策略
### 需求 2助教数据获取模块
**用户故事:** 作为 AI 应用(应用 4/5我需要获取助教基本信息和助教-客户服务历史,以便基于真实数据生成关系分析和话术参考。
#### 验收标准
1. THE Data_Fetcher SHALL 提供 `fetch_assistant_info(site_id, assistant_id)` 异步函数,从 `fdw_etl.v_dim_assistant``fdw_etl.v_dws_assistant_salary_calc` 获取助教基本信息,返回包含以下字段的字典:`nickname`(花名)、`level`(级别)、`hire_date`(入职日期)、`tenure_months`(工龄月数)、`monthly_customers`(本月服务客户数)、`performance_tier`(绩效档位)
2. THE Data_Fetcher SHALL 提供 `fetch_service_history(site_id, assistant_id, member_id, months)` 异步函数,从 `fdw_etl.v_dwd_assistant_service_log` 获取助教服务该客户的历史记录(默认近 3 个月),每条记录包含:`service_date``duration_minutes``items_sum``room_name``is_pd`(是否陪打)
3. THE Data_Fetcher SHALL 使用 `dwd_assistant_service_log_ex.is_trash` 排除废单记录,禁止使用已废弃的 `dwd_assistant_trash_event`
4. THE Data_Fetcher SHALL 从 `fdw_etl.v_dws_member_assistant_relation_index` 获取助教-客户关系指数,从 `fdw_etl.v_dws_member_assistant_intimacy` 获取亲密度数据
5. THE Data_Fetcher SHALL 在执行 FDW 查询前通过 `get_etl_readonly_connection(site_id)` 获取连接,并执行 `SET LOCAL app.current_site_id` 设置 RLS 隔离
6. IF FDW 查询超时或连接失败THEN THE Data_Fetcher SHALL 抛出明确的异常,包含失败的视图名称和错误类型
### 需求 3应用 3 Prompt 拼接完善(客户数据维客线索分析)
**用户故事:** 作为系统,我需要在客户新增消费时,将真实的消费数据、会员卡信息和历史线索拼接为完整的 Prompt JSON以便 AI 能基于真实数据提取维客线索。
#### 验收标准
1. WHEN 应用 3 的 `build_prompt()` 被调用时THE Build_Prompt SHALL 调用 `fetch_member_consumption_data()` 获取客户近 3 个月消费数据,替换当前的 TODO 占位符
2. THE Build_Prompt SHALL 将获取到的数据组装为 P5 spec 定义的 Prompt JSON 结构,包含 `current_time`(精确到秒)、`member_nickname``main_data`(含 `consumption_records``member_cards``card_balance_total``stored_value_balance_total``expected_visit_date``days_since_last_visit`)、`reference`(含 `app6_clues``app8_history`
3. THE Build_Prompt SHALL 在 `reference.app8_history` 中包含最近 2 套应用 8 历史结果,每套附带 `generated_at` 时间戳
4. IF 客户无消费记录THEN THE Build_Prompt SHALL 将 `consumption_records` 设为空数组,其余字段使用默认值(余额为 0、`days_since_last_visit` 为 nullPrompt 中标注"该客户暂无消费记录"
5. THE Build_Prompt SHALL 将每条消费记录中的金额字段逐项拆分(`table_charge_money``assistant_pd_money``assistant_cx_money``goods_money`),禁止使用 `consume_money`
### 需求 4应用 4 Prompt 拼接完善(关系分析/任务建议)
**用户故事:** 作为系统,我需要在助教参与新结算或被分配召回任务时,将助教信息、服务历史和客户数据拼接为完整的 Prompt JSON以便 AI 能生成关系分析和任务建议。
#### 验收标准
1. WHEN 应用 4 的 `build_prompt()` 被调用时THE Build_Prompt SHALL 调用 `fetch_assistant_info()` 获取助教基本信息,调用 `fetch_service_history()` 获取助教-客户服务历史,调用 `fetch_member_consumption_data()` 获取客户消费数据,替换当前的 TODO 占位符
2. THE Build_Prompt SHALL 将获取到的数据组装为 P5 spec 定义的 Prompt JSON 结构,包含 `current_time``assistant_info``service_history``task_assignment_basis``customer_data`(含 `system_data``notes`)、`reference`(含 `app8_current``app8_history`
3. THE Build_Prompt SHALL 从 `biz.notes` 获取所有助教对该客户的全部备注,每条备注包含 `recorded_by`(创建者)、`content`(内容)、`created_at`(创建时间)
4. THE Build_Prompt SHALL 对备注内容进行截断处理,单条备注最大 500 字符,超出部分截断并附加"…(已截断)"标记
5. IF 助教无服务该客户的历史记录THEN THE Build_Prompt SHALL 将 `service_history` 设为空数组Prompt 中标注"该助教暂无服务该客户的记录"
6. THE Build_Prompt SHALL 在 `reference` 中包含应用 8 最新结果(`app8_current`)和最近 2 套历史(`app8_history`),每套附带 `generated_at` 时间戳
### 需求 5应用 5 Prompt 拼接完善(话术参考)
**用户故事:** 作为系统,我需要在应用 4 完成后,将应用 4 的分析结果连同助教信息和服务历史拼接为完整的 Prompt JSON以便 AI 能生成针对性的沟通话术。
#### 验收标准
1. WHEN 应用 5 的 `build_prompt()` 被调用时THE Build_Prompt SHALL 复用应用 4 的数据获取逻辑(`fetch_assistant_info()``fetch_service_history()``fetch_member_consumption_data()`),替换当前的 TODO 占位符
2. THE Build_Prompt SHALL 将获取到的数据组装为 P5 spec 定义的 Prompt JSON 结构,包含 `current_time``assistant_info``service_history``task_assignment_basis``customer_data`(含 `system_data``notes`)、`task_suggestion`(应用 4 的完整返回结果)、`reference`(含 `app8_history`
3. THE Build_Prompt SHALL 从 `context["app4_result"]` 获取应用 4 的返回结果,作为 `task_suggestion` 字段传入 Prompt
4. IF `context["app4_result"]` 为空或缺失THEN THE Build_Prompt SHALL 将 `task_suggestion` 设为空对象Prompt 中标注"暂无任务建议"
### 需求 6应用 6 Prompt 拼接完善(备注分析)
**用户故事:** 作为系统,我需要在助教提交备注后,将备注内容、客户消费数据和历史备注拼接为完整的 Prompt JSON以便 AI 能分析备注价值并提取维客线索。
#### 验收标准
1. WHEN 应用 6 的 `build_prompt()` 被调用时THE Build_Prompt SHALL 调用 `fetch_member_consumption_data()` 获取客户消费数据,替换当前的 TODO 占位符
2. THE Build_Prompt SHALL 将获取到的数据组装为 P5 spec 定义的 Prompt JSON 结构,包含 `current_time``current_note`(含 `content``recorded_by``created_at`)、`reference`(含 `member_nickname``consumption_data``all_notes``app3_clues``app8_history`
3. THE Build_Prompt SHALL 从 `biz.notes` 获取所有助教对该客户的全部备注作为 `all_notes`,每条备注包含 `recorded_by``content``created_at`
4. THE Build_Prompt SHALL 对 `all_notes` 中每条备注内容进行截断处理,单条备注最大 500 字符
5. THE Build_Prompt SHALL 在 `reference` 中包含应用 3 最新线索(`app3_clues`)和最近 2 套应用 8 历史(`app8_history`),每套附带 `generated_at` 时间戳
6. IF 客户无历史备注THEN THE Build_Prompt SHALL 将 `all_notes` 设为空数组
### 需求 7应用 7 Prompt 拼接完善(客户分析)
**用户故事:** 作为系统,我需要在消费事件链中应用 8 完成后,将客户全量客观数据和主观备注拼接为完整的 Prompt JSON以便 AI 能生成全局运营策略。
#### 验收标准
1. WHEN 应用 7 的 `build_prompt()` 被调用时THE Build_Prompt SHALL 调用 `fetch_member_consumption_data()` 获取客户消费数据,替换当前的 TODO 占位符
2. THE Build_Prompt SHALL 将获取到的数据组装为 P5 spec 定义的 Prompt JSON 结构,包含 `current_time``member_id``member_nickname``objective_data`(同应用 3 的 `main_data` 结构)、`subjective_data`(含 `notes`)、`reference`(含 `app8_current``app8_history`
3. THE Build_Prompt SHALL 从 `biz.notes` 获取该客户的全部备注作为 `subjective_data.notes`,每条备注包含 `recorded_by`(创建者)、`content``created_at`
4. THE Build_Prompt SHALL 对来自备注的主观信息在 Prompt 中标注"【来源:{recorded_by},请甄别信息真实性】"
5. THE Build_Prompt SHALL 在 `reference` 中包含应用 8 最新结果(`app8_current`)和最近 2 套历史(`app8_history`),每套附带 `generated_at` 时间戳
6. IF 客户无备注记录THEN THE Build_Prompt SHALL 将 `subjective_data.notes` 设为空数组Prompt 中标注"该客户暂无主观备注信息"
### 需求 8页面上下文文本化框架
**用户故事:** 作为助教,我希望从任意页面进入 AI 对话时AI 能自动了解当前页面的上下文信息(客户数据、任务信息、看板数据等),以便提供与当前场景相关的回答。
> **P5 对齐说明**P5 spec 定义应用 1 首条 Prompt 包含 `page_context`(页面上下文摘要)和 `screen_content`用户当前屏幕可见内容两个独立字段。NS2 采用后端自动查询方案,通过 `build_page_text()` 生成合并的页面上下文文本,等效覆盖两个字段的信息需求。详见 NS2 PRD 3.7 设计决策。
#### 验收标准
1. THE Page_Context_Builder SHALL 提供 `build_page_text(source_page, context_id, site_id, filters)` 异步函数,根据 `source_page`(即 `contextType`)从数据库获取对应页面数据并格式化为结构化中文文本
2. THE Page_Context_Builder SHALL 支持以下 10 种页面类型的文本化:`task-detail``customer-detail``coach-detail``board-finance``board-customer``board-coach``performance``my-profile``task-list``customer-service-records`
3. WHEN `source_page``task-detail`THE Page_Context_Builder SHALL 从 `biz.coach_tasks`、会员信息、备注和 `ai_cache` 获取数据,输出包含任务信息、客户信息、备注摘要和 AI 分析的结构化文本
4. WHEN `source_page``customer-detail`THE Page_Context_Builder SHALL 从会员信息、消费记录和维客线索获取数据,输出包含客户全信息、消费记录摘要和维客线索的结构化文本
5. WHEN `source_page``coach-detail`THE Page_Context_Builder SHALL 从助教信息、任务统计和备注获取数据,输出包含助教信息、任务统计和备注摘要的结构化文本
6. WHEN `source_page` 为看板类页面(`board-finance``board-customer``board-coach`THE Page_Context_Builder SHALL 接受可选的筛选参数(`timeDimension``dimension``areaFilter` 等),从对应 DWS 汇总视图获取数据,输出数据摘要文本
7. WHEN `source_page``performance`THE Page_Context_Builder SHALL 从 `fdw_etl.v_dws_assistant_salary_calc` 获取绩效数据,输出绩效数据摘要文本
8. THE Page_Context_Builder SHALL 将每个页面上下文的输出文本控制在 2000 字符以内,避免 token 浪费
9. THE Page_Context_Builder SHALL 输出结构化中文描述文本(非 JSON使用分段标题和缩进格式便于 AI 理解
10. IF 看板类页面未传入筛选参数THEN THE Page_Context_Builder SHALL 使用默认值(如 `board-finance` 默认"本月"、`board-customer` 默认按消费金额排序)
11. IF 数据获取失败FDW 超时、连接失败等THEN THE Page_Context_Builder SHALL 返回"页面上下文获取失败,请直接描述您的问题"文本,不阻断对话流程
12. THE Page_Context_Builder SHALL 不传入 `member_phone` 等已断档的敏感字段,会员信息通过 `member_id` JOIN `v_dim_member` 获取
### 需求 9应用 1 页面上下文集成
**用户故事:** 作为助教,我希望从不同页面入口进入 AI 对话时AI 的首条回复能体现对当前页面上下文的理解,而不是一个通用的空白对话。
#### 验收标准
1. WHEN 用户从任意页面进入 chat 页面时THE Build_Prompt SHALL 在 `app1_chat.py``_build_page_context()` 中调用 `Page_Context_Builder.build_page_text()`,根据 `contextType``contextId` 获取页面上下文文本
2. THE Build_Prompt SHALL 将 `build_page_text()` 返回的文本作为 system prompt 中的 `page_context` 字段注入,替换当前的空透传实现
3. WHEN `contextType` 为详情类页面(`task-detail``customer-detail``coach-detail`THE Build_Prompt SHALL 使用 `contextId` 作为实体 ID 传入 `build_page_text()`
4. WHEN `contextType` 为看板类页面(`board-finance``board-customer``board-coach`THE Build_Prompt SHALL 将前端传入的筛选参数(`timeDimension``dimension` 等)作为 `filters` 传入 `build_page_text()`
5. IF `contextType` 为空或未识别的类型THEN THE Build_Prompt SHALL 跳过页面上下文注入AI 以通用对话模式响应
6. THE Build_Prompt SHALL 确保 `biz_params.user_prompt_params``User_ID``Role``Nickname`)在页面上下文注入后仍正确存在于 system prompt 中
### 需求 10前端看板筛选参数传递
**用户故事:** 作为助教或管理者,我希望从看板页面进入 AI 对话时AI 能了解当前看板的筛选条件(时间维度、排序维度等),以便基于当前视图提供分析。
#### 验收标准
1. WHEN 用户从 `board-finance` 页面跳转到 chat 页面时THE Miniprogram SHALL 将当前的 `timeDimension`(时间维度)和 `areaFilter`(区域筛选)作为额外参数传入 chat 页面
2. WHEN 用户从 `board-customer` 页面跳转到 chat 页面时THE Miniprogram SHALL 将当前的 `dimension`(排序维度)和 `typeFilter`(类型筛选)作为额外参数传入 chat 页面
3. WHEN 用户从 `board-coach` 页面跳转到 chat 页面时THE Miniprogram SHALL 将当前的 `dimension``projectFilter`(技能筛选)和 `timeDimension` 作为额外参数传入 chat 页面
4. THE Miniprogram SHALL 将看板筛选参数编码为 chat 页面 URL 的查询参数,后端从请求中提取并传入 `build_page_text()``filters` 参数
### 需求 11数据获取层全局约束
**用户故事:** 作为后端开发者,我需要确保所有数据获取函数遵循统一的数据库连接、金额口径和安全规范,以保证数据一致性和多门店隔离。
#### 验收标准
1. THE Data_Fetcher SHALL 对所有 FDW 查询使用 `get_etl_readonly_connection(site_id)` 获取只读连接,对业务库查询使用 `get_connection()` 获取连接
2. THE Data_Fetcher SHALL 在每次 FDW 查询前执行 `SET LOCAL app.current_site_id = {site_id}`,确保 RLS 多门店数据隔离生效
3. THE Data_Fetcher SHALL 在所有涉及金额的查询和计算中使用 `items_sum` 口径,禁止使用 `consume_money`
4. THE Data_Fetcher SHALL 在所有涉及助教费用的查询中将费用拆分为 `assistant_pd_money`(陪打)和 `assistant_cx_money`(超休),禁止使用合并的 `service_fee`
5. THE Data_Fetcher SHALL 在所有涉及会员信息的查询中通过 `member_id` JOIN `v_dim_member``scd2_is_current=1`)获取昵称和手机号,禁止使用结算单冗余字段
6. THE Data_Fetcher SHALL 支持多个数据获取函数并发执行(通过 `asyncio.gather`),以减少 Prompt 构建的总耗时
7. THE Data_Fetcher SHALL 为所有 FDW 查询设置 5 秒超时,超时后抛出 `TimeoutError` 并记录慢查询日志
### 需求 12空数据与错误降级处理
**用户故事:** 作为系统,我需要在数据获取部分失败或数据为空时,仍能生成有效的 Prompt 并调用 AI以保证 AI 功能的可用性。
#### 验收标准
1. IF 某个数据获取函数失败FDW 超时、连接失败等THEN THE Build_Prompt SHALL 将该部分数据设为默认空值(空数组或空对象),在 Prompt 中标注"该部分数据获取失败",继续生成 Prompt 并调用百炼 API
2. IF 客户无消费记录、无备注、无服务历史THEN THE Build_Prompt SHALL 在 Prompt 中使用明确的空状态提示词(如"该客户暂无消费记录,请基于已有信息分析"),而非传入空数据不做说明
3. IF AI_Cache 中无 reference 历史数据如新客户首次结算THEN THE Build_Prompt SHALL 将 `reference` 设为空对象,在 Prompt 中标注"暂无历史线索"
4. THE Build_Prompt SHALL 确保在任何数据获取失败的情况下Prompt 的整体 JSON 结构仍然合法,不出现 null 值导致百炼 API 解析失败
5. IF 应用 1 的页面上下文获取失败THEN THE Build_Prompt SHALL 使用"页面上下文获取失败,请直接描述您的问题"作为 `page_context`,不阻断对话
### 需求 13biz_params 端到端正确性
**用户故事:** 作为系统管理员,我需要确保应用 1 的用户身份信息从前端到百炼平台的完整传递链路正确无误,以保证数据查询隔离生效。
#### 验收标准
1. THE Backend SHALL 从 JWT token 中提取 `user_id``role``nickname`,传入 `app1_chat.py``_build_system_prompt()`,确保用户身份信息不可由前端伪造
2. THE Build_Prompt SHALL 在 system prompt 的 `biz_params.user_prompt_params` 中注入 `User_ID`(字符串)、`Role`"助教"或"管理者")、`Nickname`(昵称),供百炼平台侧执行数据查询隔离
3. WHILE 用户身份为助教时THE Bailian_Client SHALL 确保百炼平台仅允许查询与该助教相关的数据,禁止查询其他助教业绩、工资、客户关系等敏感数据,禁止查询门店级财务数据
4. WHILE 用户身份为管理者时THE Bailian_Client SHALL 确保百炼平台允许查询该门店下所有数据
5. THE Backend SHALL 确保所有传入百炼平台的查询均包含 `site_id` 过滤,防止跨门店数据泄露
### 需求 14Prompt Token 预算控制
**用户故事:** 作为系统,我需要控制每个应用首条 Prompt 的数据量,避免超出百炼 API 的 token 限制或产生不必要的 token 消耗。
#### 验收标准
1. THE Build_Prompt SHALL 将应用 3/4/5/6/7 的首条 Prompt JSON 总字符数控制在 8000 字符以内(约 4000 token
2. THE Build_Prompt SHALL 将应用 1 的 system prompt含页面上下文总字符数控制在 4000 字符以内(约 2000 token
3. WHEN 消费记录数量超过 100 条时THE Data_Fetcher SHALL 仅返回最近 100 条记录,并在 Prompt 中标注"仅展示最近 100 条,共 {total} 条"
4. WHEN 备注总数超过 50 条时THE Build_Prompt SHALL 仅传入最近 50 条备注(按 `created_at` 倒序),并在 Prompt 中标注"仅展示最近 50 条备注"
5. THE Build_Prompt SHALL 对所有传入 Prompt 的文本字段进行长度检查,单个文本字段不超过 1000 字符