24 KiB
P5:AI 集成层 — miniapp-ai-integration
优先级:P5(依赖 P3 + P4) 预估工作量:大 详细应用需求:#file:docs/prd/AI需求2.md
⚠️ 两阶段交付策略(2026-03-07 评审决定)
P5 的 8 个 AI 应用中,应用 3/4/5/6/7 的首条 Prompt JSON 结构包含占位符字段(consumption_records、service_history、objective_data 等),这些字段的具体结构取决于对应页面 API 的数据格式。在页面 API 未开发前,Prompt 结构无法确定,强行实现会导致"先猜后改"的浪费。
因此 P5 拆分为两个阶段:
P5-A(当前阶段,P4 之后立即执行)
交付"管道":建表、百炼封装、缓存 API、SSE 框架,以及 Prompt 已完全确定的应用(应用 2、应用 8)。 应用 3/4/5/6/7 只实现触发机制和调用骨架(Prompt 拼接函数留接口,用 TODO 标记)。
P5-B(Prompt 细化,随页面 API 同步完成)
各应用的 Prompt JSON 细化和拼接实现,分散到对应页面的开发任务中:
- P6(task-detail)→ 细化应用 4/5 的 Prompt(服务记录结构确定后)
- P9(customer-detail)→ 细化应用 3/6/7 的 Prompt(消费记录结构确定后)
详见各 spec 的对应任务。
需求(Requirements)
用户故事
- 作为助教,我可以在任意页面点击 AI 按钮,跳转到对话页面与 AI 交流,AI 了解当前页面上下文。
- 作为助教,我在任务详情页能看到 AI 生成的维客线索分析、关系分析、话术参考、客户分析。
- 作为助教,我提交备注后,系统自动通过 AI 分析备注内容,提取维客线索并评分。
- 作为管理者,我在财务看板能看到 AI 生成的财务洞察分析。
- 作为系统,所有 AI 对话(含系统调用)都要持久化记录。
- 作为系统,客户结账单出现后自动生成客户全量分析与运营建议。
- 作为系统,应用 3/应用 6 产出新线索后,自动整合去重生成统一维客线索。
验收标准
- AC1:应用 1 通用对话支持流式返回(SSE),前端逐字展示
- AC2:应用 2 财务洞察每日自动更新,覆盖 8 个时间维度,返回结构化 JSON(序号+标题+正文)
- AC3:应用 3 维客线索在客户新增消费时自动更新,返回 JSON 维客线索(分类标签限 3 个枚举:客户基础/消费习惯/玩法偏好),提供者统一为"系统"
- AC4:应用 4 在助教参与新结算/优先召回任务分配/高优先召回任务分配时触发,读取应用 8 最新缓存
- AC5:应用 5 联动应用 4,提供沟通话术
- AC6:应用 6 在每个备注提交后自动分析,返回 JSON(评分 1-10 + 维客线索 0-N 条,分类标签 6 个枚举:客户基础/消费习惯/玩法偏好/促销偏好/社交关系/重要反馈),提供者为当前备注提供人
- AC7:应用 7 在消费事件链中应用 8 完成后触发(串行),基于客户全量信息生成运营策略
- AC8:应用 8 在应用 3 或应用 6 有新内容产生后立即触发,整合去重维客线索
- AC9:所有 AI 调用记录持久化(conversation_id, message_id, app_id, user_id/系统, role, content, tokens_used, nickname, created_at, site_id)
设计要点
8 个 AI 应用
| 应用 | 用途 | 调用方式 | 触发条件 | 返回格式 |
|---|---|---|---|---|
| 应用 1 | 通用对话 | 用户主动(流式) | 点击 AI 入口 | SSE 流式文本 |
| 应用 2 | 财务洞察 | 后台轮询 | 每日 | JSON(序号+标题+正文数组) |
| 应用 3 | 客户数据维客线索分析 | 后台事件 | 客户新增消费 | JSON(线索数组:详情+标签+摘要+Emoji) |
| 应用 4 | 关系分析/任务建议 | 后台事件 | 助教参与新结算 / 优先召回任务分配 / 高优先召回任务分配 | JSON(任务描述+行动建议数组+一句话总结) |
| 应用 5 | 话术参考 | 后台联动 | 应用 4 调用时 | JSON(话术内容数组) |
| 应用 6 | 备注分析 | 后台事件 | 每个备注提交时 | JSON(线索数组+评分) |
| 应用 7 | 客户分析 | 后台事件 | 消费事件链:应用 8 完成后 | JSON(策略数组:标题+正文 + 总结) |
| 应用 8 | 维客线索整理 | 后台联动 | 应用 3 或应用 6 有新内容时 | JSON(整合后线索数组:详情+标签+摘要+Emoji+提供者) |
调用链与时序
消费事件(结账单):
└→ 应用 3(维客线索分析)→ 应用 8(线索整理)→ 应用 7(客户分析)
(串行执行:应用 7 等待应用 8 完成后再启动,确保读到本次消费触发的最新线索)
如果该结算单有助教参与:
└→ 应用 4(关系分析,等待应用 8 完成后执行)→ 应用 5(话术参考)
备注提交事件:
└→ 应用 6(备注分析)→ 应用 8(线索整理)
任务分配事件(优先召回/高优先召回):
└→ 应用 4(关系分析,读取应用 8 最新缓存)→ 应用 5(话术参考)
- 消费事件链为严格串行:应用 3 → 应用 8 → 应用 7,保证应用 7 的 reference 中包含本次消费产生的最新线索
- 应用 4 触发条件分两种场景:
- 消费事件(有助教参与的新结算单):等待应用 3 → 应用 8 完成后再执行,确保读到本次消费的最新线索
- 任务分配事件(优先召回/高优先召回):直接执行,读取应用 8 已有缓存
- 应用 8 在应用 3 或应用 6 每次产出后立即触发
- 应用 4 读取应用 8 缓存时,若缓存不存在(如新客户首次结算),reference 传空对象,Prompt 中标注"暂无历史线索"
应用分工说明
- 应用 3 vs 应用 6:应用 3 侧重客观数据分析(消费、到店频率等),应用 6 侧重主观备注分析(备注内容价值挖掘)
- 应用 3 vs 应用 7:应用 3 侧重单次消费触发的线索提取,应用 7 侧重客户全量信息的全局运营策略
- 应用 8:整合应用 3 + 应用 6 的线索,合并相似内容,保持最小改动原则
信息隔离
应用 1 通过 biz_params.user_prompt_params 传入:
User_ID:当前用户 IDRole:身份(助教/管理者)Nickname:昵称
百炼平台侧根据参数做数据查询隔离。
AI 入口汇总
所有入口统一使用应用 1,跳转 chat.html,第一条消息为页面上下文:
| 来源页面 | 触发方式 | 上下文内容 |
|---|---|---|
| task-list | 长按任务 → AI | 任务详情 + 客户-助教关系 |
| task-detail / coach-detail / customer-detail | "问问助手" | 页面完整内容 |
| board-* / performance-* / customer-service-records / my-profile | 右下角 AI 按钮 | 页面内容摘要 |
表结构
biz.ai_conversations
- id, user_id, nickname, app_id, site_id
- source_page, source_context (JSON)
- created_at
biz.ai_messages
- id, conversation_id, role (user/assistant/system)
- content, tokens_used
- created_at
biz.ai_cache
- id, cache_type (app2_finance / app3_clue / app4_analysis / app5_tactics / app6_note_analysis / app7_customer_analysis / app8_clue_consolidated)
- site_id, target_id (member_id 或 assistant_id 或 pair)
- result_json, score (应用6专用)
- triggered_by (trigger_job_id)
- created_at, expires_at
应用 3 返回格式
应用 3 侧重客观数据,分类标签限 3 个枚举,提供者统一为"系统":
{
"clues": [
{
"category": "消费习惯",
"summary": "偏好周末下午时段消费",
"detail": "近3个月周末消费占比72%,分析过程...",
"emoji": "📅"
}
]
}
- 分类标签枚举:客户基础 / 消费习惯 / 玩法偏好
- 输入:客户近 3 个月消费数据(DWD+DWS 订单明细全维度)、会员卡明细、余额合计、应到店日期、到店间隔
- 消费金额口径(已校准):使用
items_sum(= table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money),不得使用consume_money(三种历史口径混合,详见 DWD-DOC consume/consume-money-caliber.md) - 参考信息:应用 6 的线索结果 + 最近 2 套应用 8 的历史信息(附生成时间)
应用 6 返回格式
应用 6 侧重主观备注分析,分类标签 6 个枚举,提供者为当前备注提供人:
{
"score": 7,
"clues": [
{
"category": "社交关系",
"summary": "常带朋友来消费",
"detail": "备注提到经常约朋友周末来打球...",
"emoji": "👥"
}
]
}
- 分类标签枚举:客户基础 / 消费习惯 / 玩法偏好 / 促销偏好 / 社交关系 / 重要反馈
- 评分规则:6 分为标准分,重复信息/低价值/时效性低酌情扣分,高价值信息酌情加分
- 输入:当前备注内容 + 客户消费数据 + 所有助教对该客户的全部备注
- 参考信息:应用 3 的线索结果 + 最近 2 套应用 8 的历史信息(附生成时间)
应用 7 返回格式
{
"strategies": [
{
"title": "高频消费但余额不足",
"content": "客户近3个月消费12次但储值卡余额仅剩200元..."
}
],
"summary": "该客户为高频活跃用户,建议重点维护储值续费..."
}
- 输入:客户全量客观数据 + 所有备注(标注创建者)
- 消费金额口径(已校准):同应用 3,使用
items_sum而非consume_money - 参考信息:最新 + 最近 2 套应用 8 的历史信息(附生成时间)
- 主观信息需标注【来源:XXX,请甄别信息真实性】
应用 8 返回格式
{
"clues": [
{
"category": "消费习惯",
"summary": "偏好周末下午时段消费",
"detail": "近3个月周末消费占比72%...",
"emoji": "📅",
"providers": "系统,张助教"
}
]
}
- 分类标签枚举:客户基础 / 消费习惯 / 玩法偏好 / 促销偏好 / 社交关系 / 重要反馈
- 输入:当前最新应用 3 + 应用 6 的全部线索内容
- 原则:合并相似线索(多提供者逗号分隔),其余原文返回,最小改动
首条 Prompt 数据结构(后端调用时拼接)
以下定义每个应用调用百炼 API 时,后端需要拼接的首条用户消息(user message)JSON 结构。 System Prompt 见
docs/prd/ai-app-prompts.md。 ⚠️ 占位标记(两阶段策略):各应用的consumption_records、assistant_info、service_history等字段当前为字符串占位符。 P5-A 阶段只实现调用骨架,Prompt 拼接函数留接口。具体 JSON 子结构在以下阶段细化:
- 应用 4/5 的
service_history、assistant_info→ P6-T4(task-detail 页面 API 开发时)- 应用 3/6/7 的
consumption_records、objective_data→ P9-T1(customer-detail 页面 API 开发时)
通用规则(所有应用生效):
- 所有首条 Prompt JSON 中统一加入
"current_time": "2026-03-08 14:30:25"字段(精确到秒),让 AI 知道当前时间上下文 - 所有 reference 中的参考资料必须标注生成时间(
generated_at字段),让 AI 判断信息时效性
应用 1:通用对话
由前端发起,首条消息为页面上下文:
{
"current_time": "2026-03-08 14:30:25",
"source_page": "来源页面标识(如 task-detail、board-finance)",
"page_context": "页面上下文摘要(客户信息、任务信息等结构化文本)",
"screen_content": "用户当前屏幕可见内容的文本化描述"
}
应用 2:财务洞察
{
"current_time": "2026-03-08 08:05:00",
"site_id": 12345,
"time_dimension": "本月",
"date_range": {"start": "2026-03-01 08:00:00", "end": "2026-04-01 08:00:00"},
"current_period": {
"income_structure": {"table_fee": 0, "assistant_pd": 0, "assistant_cx": 0, "goods": 0, "recharge": 0},
"prepaid_assets": {"total_balance": 0, "recharge_amount": 0, "consumption_deduction": 0},
"expense_summary": {"rent": 0, "utilities": 0, "supplies": 0, "salary": 0, "other": 0},
"platform_settlement": {"groupbuy_income": 0, "platform_fee": 0, "net_income": 0}
},
"previous_period": {
"time_dimension": "上月",
"date_range": {"start": "2026-02-01 08:00:00", "end": "2026-03-01 08:00:00"},
"income_structure": {},
"prepaid_assets": {},
"expense_summary": {},
"platform_settlement": {}
}
}
- 8 个时间维度:本月/上月/本周/上周/前3月不含本月/本季/上季/近6月不含本月
- 营业日分界点 08:00
- 收入结构字段映射(已校准,数据源:DWD-DOC 03-财务全景):
table_fee=table_charge_money(56.6%)、assistant_pd=assistant_pd_money(30.6%)、assistant_cx=assistant_cx_money(0.9%)、goods=goods_money(10.1%)、recharge= 充值 pay_amount(settle_type=5) electricity_money全为 0(门店未启用灯控),不纳入收入结构
应用 3:客户数据维客线索分析
{
"current_time": "2026-03-08 14:30:25",
"member_nickname": "客户昵称",
"main_data": {
"consumption_records": "近3个月消费数据(DWD+DWS 订单明细:台费、充值、助教消费等全维度)",
"member_cards": "名下会员卡明细",
"card_balance_total": 0,
"stored_value_balance_total": 0,
"expected_visit_date": "2026-03-10",
"days_since_last_visit": 15
},
"reference": {
"app6_clues": "应用6的线索结果(如有)",
"app8_history": [
{"generated_at": "2026-03-01", "clues": "最近第1套应用8结果"},
{"generated_at": "2026-02-15", "clues": "最近第2套应用8结果"}
]
}
}
应用 4:关系分析 / 任务建议
{
"current_time": "2026-03-08 14:30:25",
"assistant_info": "助教基本信息(花名、级别、工龄等)",
"service_history": "助教服务该客户的历史记录",
"task_assignment_basis": "任务分配的依据(新结算/优先召回/高优先召回)",
"customer_data": {
"system_data": "客户近3个月消费数据(同应用3的 main_data 结构)",
"notes": [
{"recorded_by": "备注创建者", "content": "备注全文", "created_at": "时间"}
]
},
"reference": {
"app8_current": "当前最新维客线索(应用8结果)",
"app8_history": [
{"generated_at": "2026-03-01", "clues": "最近第1套应用8结果"},
{"generated_at": "2026-02-15", "clues": "最近第2套应用8结果"}
]
}
}
应用 5:话术参考
{
"current_time": "2026-03-08 14:30:25",
"assistant_info": "助教基本信息",
"service_history": "助教服务该客户的历史记录",
"task_assignment_basis": "任务分配的依据",
"customer_data": {
"system_data": "客户近3个月消费数据(同应用3的 main_data 结构)",
"notes": [
{"recorded_by": "备注创建者", "content": "备注全文", "created_at": "时间"}
]
},
"task_suggestion": "本次任务建议(应用4返回的完整结果)",
"reference": {
"app8_history": [
{"generated_at": "2026-03-01", "clues": "最近第1套应用8结果"},
{"generated_at": "2026-02-15", "clues": "最近第2套应用8结果"}
]
}
}
应用 6:备注分析
{
"current_time": "2026-03-08 14:30:25",
"current_note": {
"content": "本次提交的备注内容",
"recorded_by": "备注创建者",
"created_at": "提交时间"
},
"reference": {
"member_nickname": "客户昵称",
"consumption_data": "客户近3个月消费数据(同应用3的 main_data 结构)",
"all_notes": [
{"recorded_by": "创建者", "content": "备注全文", "created_at": "时间"}
],
"app3_clues": "应用3的线索结果(如有)",
"app8_history": [
{"generated_at": "2026-03-01", "clues": "最近第1套应用8结果"},
{"generated_at": "2026-02-15", "clues": "最近第2套应用8结果"}
]
}
}
应用 7:客户分析
{
"current_time": "2026-03-08 14:30:25",
"member_id": 12345,
"member_nickname": "客户昵称",
"objective_data": "客户近3个月消费数据(同应用3的 main_data 结构)",
"subjective_data": {
"notes": [
{"recorded_by": "创建者", "content": "备注全文", "created_at": "时间"}
]
},
"reference": {
"app8_current": "最新维客线索(应用8结果)",
"app8_history": [
{"generated_at": "2026-03-01", "clues": "最近第1套应用8结果"},
{"generated_at": "2026-02-15", "clues": "最近第2套应用8结果"}
]
}
}
应用 8:维客线索整理
{
"current_time": "2026-03-08 14:30:25",
"app3_clues": {
"generated_at": "2026-03-05 14:30:00",
"clues": [
{"detail": "...", "category": "消费习惯", "summary": "...", "emoji": "📅"}
]
},
"app6_clues": {
"generated_at": "2026-03-05 14:25:00",
"clues": [
{"category": "社交关系", "emoji": "👥", "detail": "...", "summary": "..."}
]
}
}
数据写入规则
- 应用 1:流式返回完成后,将完整的 assistant 回复写入
ai_messages(role=assistant),用户消息在发送时即写入(role=user) - 应用 3/6 的线索产出后,先写入
ai_cache,再触发应用 8 - 应用 8 整合后的线索全量替换该客户在
member_retention_clue中的所有 AI 来源线索(source IN ('ai_consumption', 'ai_note')),人工线索(source='manual')不受影响。全量替换合理性:应用 8 输入包含应用 3 + 应用 6 的全部线索,AI 整合时会保留重要内容,输出即为该客户的完整 AI 线索集 - 应用 2/4/5/7 的结果写入
ai_cache,供前端读取 - 所有 AI 调用记录写入
ai_conversations+ai_messages(含 tokens_used 统计)
应用 8 → member_retention_clue 字段映射
应用 8 返回的每条线索写入 member_retention_clue 时,字段映射如下:
| 应用 8 返回字段 | member_retention_clue 列 | 说明 |
|---|---|---|
category |
category |
直接映射,枚举值必须与 DDL CHECK 约束一致(6 个值) |
emoji + summary |
summary |
emoji 拼接在 summary 前面存储,如 📅 偏好周末下午时段消费,前端直接读取展示 |
detail |
detail |
直接映射 |
providers |
recorded_by_name |
多提供者逗号分隔,如 系统,张助教 |
| — | recorded_by_assistant_id |
系统触发时填 NULL |
| — | source |
根据线索来源判断:纯应用 3 产出 → ai_consumption,纯应用 6 产出 → ai_note,混合来源 → ai_consumption(以客观数据为主) |
| — | member_id |
从触发上下文获取 |
| — | site_id |
从触发上下文获取 |
| — | recorded_at |
写入时间 NOW() |
ai_cache 数据保留策略
- 应用 1(通用对话):对话记录保留在
ai_conversations+ai_messages中,无条数限制(按需清理) - 应用 2-8:每个
(cache_type, site_id, target_id)组合保留最近 500 条记录,超过时删除最旧的 - 清理时机:每次写入新记录后,异步检查并清理超限记录
ai_cache target_id 约定
| 应用 | cache_type | target_id 含义 | 示例 |
|---|---|---|---|
| 应用 2 | app2_finance | 时间维度编码 | this_month、last_week、last_3_months 等 |
| 应用 3 | app3_clue | member_id | 12345 |
| 应用 4 | app4_analysis | {assistant_id}_{member_id} |
100_12345 |
| 应用 5 | app5_tactics | {assistant_id}_{member_id} |
100_12345 |
| 应用 6 | app6_note_analysis | member_id | 12345 |
| 应用 7 | app7_customer_analysis | member_id | 12345 |
| 应用 8 | app8_clue_consolidated | member_id | 12345 |
应用 2 的 8 个时间维度编码:this_month / last_month / this_week / last_week / last_3_months / this_quarter / last_quarter / last_6_months
应用 2 调度机制
- 调度方式:ETL 调度器中的调度任务,在每日 08:00(营业日切点)后的首次任务执行时触发
- 执行逻辑:DWS 日更数据更新完成后,依次对 8 个时间维度发起独立调用(共 8 次百炼 API 调用)
- 每次调用生成一条
ai_cache记录,target_id为时间维度编码 - 如果 ETL 调度器中尚无此调度逻辑,需在 P5-A 阶段补充
应用 1 对话历史管理
- 每次从任意页面进入 chat 页面时,始终新建对话(
ai_conversations新增一行),不复用已有对话 - 历史对话列表按时间倒序展示,20 条/页懒加载
- 暂不支持删除对话
前端消费方式
| 应用 | 前端展示位置 | 数据来源 | 展示说明 |
|---|---|---|---|
| 应用 1 | chat 页面 | SSE 流式 + ai_messages |
实时对话,历史记录从 ai_messages 读取 |
| 应用 2 | board-finance 财务看板 | ai_cache(cache_type=app2_finance) |
JSON 数组渲染为洞察卡片(序号+标题+正文) |
| 应用 3 | 不直接展示 | ai_cache(cache_type=app3_clue) |
作为基础资料供应用 8 整合,不在页面显示 |
| 应用 4 | task-detail 任务详情页 | ai_cache(cache_type=app4_analysis) |
展示任务描述+行动建议+一句话总结;summary 摘要同时在 task-list 任务卡片中显示 |
| 应用 5 | task-detail 任务详情页 | ai_cache(cache_type=app5_tactics) |
展示话术参考列表 |
| 应用 6 | task-detail 备注卡片 | ai_cache(cache_type=app6_note_analysis) |
score 以打星方式呈现在备注卡片上;线索部分不直接展示,作为基础资料供应用 8 整合 |
| 应用 7 | customer-detail 客户详情页 | ai_cache(cache_type=app7_customer_analysis) |
展示运营策略数组+总结 |
| 应用 8 | customer-detail + task-detail | member_retention_clue 表 |
展示整合后的维客线索(Emoji+标签+摘要+详情);task-detail 中提供者显示为"By:系统"或"By:备注"(不显示具体人名) |
任务清单
P5-A 阶段(当前执行,Prompt 已确定 + 调用骨架)
- T1:创建
biz.ai_conversations+biz.ai_messages+biz.ai_cache表(cache_type 扩展 app7/app8) - T2:实现百炼 API 统一封装层(流式/非流式、重试、日志、JSON 输出模式)
- T3:实现应用 1 通用对话 API(SSE 流式返回,上下文注入框架先搭建,页面文本化工具留接口)
- T5:实现应用 2 财务洞察轮询任务(Prompt 已完全确定,JSON 输出:序号+标题+正文)
- T6-骨架:实现应用 3 触发机制 + 调用框架(Prompt 拼接函数留接口,
consumption_records等字段待 P9-T1 细化) - T7-骨架:实现应用 4 触发机制 + 调用框架(Prompt 拼接函数留接口,
service_history等字段待 P6-T4 细化) - T8-骨架:实现应用 5 联动框架(Prompt 拼接函数留接口,随应用 4 同步细化)
- T9-骨架:实现应用 6 触发机制 + 调用框架(Prompt 拼接函数留接口,
consumption_data等字段待 P9-T1 细化) - T10-骨架:实现应用 7 触发机制 + 调用框架(Prompt 拼接函数留接口,
objective_data等字段待 P9-T1 细化) - T11:实现应用 8 维客线索整理(Prompt 已完全确定,应用 3/6 产出后触发,合并去重→写入 member_retention_clue)
- T12:实现 AI 缓存读写 API(前端读取缓存结果)
- T13:查阅百炼文档确认流式返回技术方案(SSE vs WebSocket)及 JSON 输出最佳实践
P5-B 阶段(Prompt 细化,分散到对应页面 spec)
以下任务不在 P5 中独立执行,而是嵌入对应页面的开发任务:
- T4:实现页面内容文本化工具(各页面数据 → AI 可读文本)→ 随 P6-P9 各页面逐步实现
- T6-完整:应用 3 Prompt JSON 细化 + 拼接实现 → 在 P9-T1(customer-detail API)中完成
- T7-完整:应用 4 Prompt JSON 细化 + 拼接实现 → 在 P6-T4(task-detail API)中完成
- T8-完整:应用 5 Prompt JSON 细化 + 拼接实现 → 在 P6-T4(task-detail API)中完成
- T9-完整:应用 6 Prompt JSON 细化 + 拼接实现 → 在 P9-T1(customer-detail API)中完成
- T10-完整:应用 7 Prompt JSON 细化 + 拼接实现 → 在 P9-T1(customer-detail API)中完成