Files
Neo-ZQYY/apps/backend/app/ai/schemas.py
Neo 2dfc926f96 feat(ai): W1-AI-CLOSURE 超级 Sprint — 9 APP 全链路收口 + chat 上下文真激活
Phase 2.3 chat 上下文捕获链路从未真正激活到完整工作:
- 14 处 ai-float-button 补 sourcePage,chat.ts 三分支同步设 pageFilters.contextId
- 后端 page_context 4 层 BUG 修(列名错位 + RLS site_id 未重设)
- xcx_chat filters.pop 破坏 body.page_context 引用 — dict() 浅拷贝隔离
- chat 流式 markdown 实时解析(表格/标题/列表/加粗 + KPI 富卡)
- reference_card KPI 富卡接入 SSE 路径,db 真写入
- 维客线索 source 显示规则:AI 来源用机器人 icon 替代长文字

数据库:
- public.member_retention_clue 加 emoji + runtime_mode + sandbox_instance_id
- biz.ai_run_logs 加 assistant_id + 复合索引
- chk_ai_cache_type CHECK 约束 8 类应用名
- cache_type / app_type 命名统一(app6_note / app7_customer / app8_consolidation)
- 历史 emoji 抽取脚本 44/44 成功

后端 silent failure 修:
- cleanup_service WHERE app_type → cache_type(90 天清理 + 20K 上限重新生效)
- _build_ai_insight 字段错位修复(app4 → app7 + 字段对齐 prompt schema)
- task_manager talkingPoints 改 app5_tactics + tactics 字段
- task_manager aiSuggestion 改取 one_line_summary
- cache_service.CACHE_EXPIRY_DAYS 加 app2a_finance_area
- WS /ws/ai-cache 加 token + JWT + site_id 校验(P0 信息泄露漏洞)
- internal_ai token 改 hmac.compare_digest

工具/文档:
- main.py 加 RotatingFileHandler logs/backend.log + uvicorn /health 过滤
- 新建 utils/clue_category.py(VI 6 类配色 + emoji fallback + source 显示规则)
- 新建 utils/markdown.ts(轻量 md 转 rich-text 解析 + streaming 容错)
- audit + 数据库变更说明 + backlog §七 #14 收口 + #15-#38 残余子任务
- backlog 追加 §十一 App1 参数/MCP/沙箱审计 + §十二 百炼/SQL MCP 主任务线

实地 MCP 走查:14 入口数据层 + 5 代表入口 sourcePage 注入 + customer-detail 全模块 + chat md 渲染 + reference_card 富卡 都已验证。9 项预先 BUG/UX 登记 §七 #29-#38 后续修复。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:39:07 +08:00

166 lines
3.4 KiB
Python
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.
"""AI 集成层 Pydantic 模型定义。
覆盖请求/响应体、缓存类型枚举、线索模型、各应用结果模型。
"""
from __future__ import annotations
import enum
from pydantic import BaseModel, Field
# ── 请求/响应 ──
class ChatStreamRequest(BaseModel):
"""SSE 流式对话请求体"""
message: str
source_page: str | None = None
page_context: dict | None = None
screen_content: str | None = None
class SSEEvent(BaseModel):
"""SSE 事件"""
type: str # chunk / done / error
content: str | None = None
conversation_id: int | None = None
tokens_used: int | None = None
message: str | None = None
# ── 缓存类型枚举 ──
class CacheTypeEnum(str, enum.Enum):
"""ai_cache.cache_type 允许的取值(8 类,与 prompt 文件名 + 数据库 chk_ai_cache_type
约束完全对齐;app1_chat 走 ai_messages 不进缓存)。
W1-AI-CLOSURE 组 1 命名统一:旧名字 app6_note_analysis / app7_customer_analysis /
app8_clue_consolidated / app8_consolidate 已在数据库迁移中清理,代码不再使用。
"""
APP2_FINANCE = "app2_finance"
APP2A_FINANCE_AREA = "app2a_finance_area"
APP3_CLUE = "app3_clue"
APP4_ANALYSIS = "app4_analysis"
APP5_TACTICS = "app5_tactics"
APP6_NOTE = "app6_note"
APP7_CUSTOMER = "app7_customer"
APP8_CONSOLIDATION = "app8_consolidation"
# ── 线索相关 ──
class App3CategoryEnum(str, enum.Enum):
"""App3 线索分类3 个枚举值)"""
CUSTOMER_BASIC = "客户基础"
CONSUMPTION_HABIT = "消费习惯"
PLAY_PREFERENCE = "玩法偏好"
class App6CategoryEnum(str, enum.Enum):
"""App6/8 线索分类6 个枚举值)"""
CUSTOMER_BASIC = "客户基础"
CONSUMPTION_HABIT = "消费习惯"
PLAY_PREFERENCE = "玩法偏好"
PROMO_PREFERENCE = "促销偏好"
SOCIAL_RELATION = "社交关系"
IMPORTANT_FEEDBACK = "重要反馈"
class ClueItem(BaseModel):
"""单条线索App3/App6 共用)"""
category: str
summary: str
detail: str
emoji: str
class ConsolidatedClueItem(BaseModel):
"""整合后线索App8含 providers"""
category: str
summary: str
detail: str
emoji: str
providers: str
# ── 各应用结果模型 ──
class App2InsightItem(BaseModel):
"""App2 财务洞察单条"""
seq: int
title: str
body: str
class App2Result(BaseModel):
"""App2 财务洞察结果"""
insights: list[App2InsightItem]
class App3Result(BaseModel):
"""App3 客户数据维客线索结果"""
clues: list[ClueItem]
class App4Result(BaseModel):
"""App4 关系分析结果"""
task_description: str
action_suggestions: list[str]
one_line_summary: str
class App5TacticsItem(BaseModel):
"""App5 话术单条"""
scenario: str
script: str
class App5Result(BaseModel):
"""App5 话术参考结果"""
tactics: list[App5TacticsItem]
class App6Result(BaseModel):
"""App6 备注分析结果"""
score: int = Field(ge=1, le=10)
clues: list[ClueItem]
class App7StrategyItem(BaseModel):
"""App7 客户分析策略单条"""
title: str
content: str
class App7Result(BaseModel):
"""App7 客户分析结果"""
strategies: list[App7StrategyItem]
summary: str
class App8Result(BaseModel):
"""App8 维客线索整理结果"""
clues: list[ConsolidatedClueItem]