Files
ai-kefu-jc/docs/superpowers/plans/2026-09-29-building-materials-ai-kefu.md
T
2026-09-29 18:29:07 +08:00

26 KiB
Raw Blame History

HESUPIPE 建材 AI 客服 实施计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 复制 D:\refactor\ai-kefu 汽车AI客服到本项目并完成建材(HESUPIPE 管道外贸)行业定制。

Architecture: 方案A"完整拷贝+定制"——保留参考项目全部架构(FastAPI+SQLite+智谱GLM、WebSocket/REST 双通道、三重输出墙、联系方式管道、邮件+UniService推送、管理后台、170+测试),只定制约15%行业相关内容(4个提示词、多语言正则墙、前端文案、品牌更名)。

Tech Stack: Python 3.13 / FastAPI / SQLAlchemy(async)+aiosqlite / 智谱GLM(glm-4-flash) / 原生HTML-JS-CSS前端 / pytest+pytest-asyncio / Docker+OpenResty

设计文档: docs/superpowers/specs/2026-09-29-building-materials-ai-kefu-design.md(本计划的所有决策依据)

参考项目: D:\refactor\ai-kefu(只读,绝不修改)

重要约束:

  • ⚠️ 绝不拷贝参考项目的 .env(含真实密钥)和 data/cc_ai_kefu.db(含生产数据)
  • 开发期 PUSH_ENABLED=false、NOTIFY_EMAIL 用测试邮箱(Task 11 验收通过后才切生产)
  • 每个任务结束必须 pytest -q 全绿后才能 commit

Task 1: 项目拷贝、清理与测试基线

Files:

  • Create: 整个项目骨架(从参考项目拷贝)

  • Delete: static/blog.html、redis 相关配置

  • Step 1: 拷贝项目(排除密钥/数据/缓存)

cd /d/refactor
MSYS_NO_PATHCONV=1 robocopy "D:\\refactor\\ai-kefu" "D:\\refactor\\ai-kefu-jc" /E \
  /XD .git data __pycache__ .pytest_cache .ruff_cache .playwright-mcp .superpowers .vscode \
  /XF .env

⚠️ Git Bash 下 MSYS 会把 /E /XD 等开关当路径转换导致 robocopy 报"无效参数", 必须加 MSYS_NO_PATHCONV=1 前缀(实测验证;替代写法是 //E //XD //XF 双斜杠)。 robocopy 返回码 0-7 都算成功(1=有文件拷贝),≥8 才是失败。 docs/superpowers/ 下会合入参考项目的汽车 specs/plans 归档,与本项目的建材设计文档共存,无冲突(文件名不同)。

git 仓库说明:本项目在设计阶段已 git init 并有 3 个 docs commit 在案; robocopy 的 /XD .git 只排除源目录的 .git,不影响目标已有仓库。Step 6 前用 git rev-parse --is-inside-work-tree 确认输出 true 即可(若在全新环境重跑本计划则先 git init)。

  • Step 2: 验证拷贝结果
cd /d/refactor/ai-kefu-jc && ls app/ static/ tests/ scripts/
# 预期:四个目录都在;确认不存在 .env 和 data/cc_ai_kefu.db
test ! -f .env && echo OK-no-env
mkdir -p data
  • Step 3: 清理无用件
rm static/blog.html

移除 redis 三处:

  1. requirements.txt 删除 redis>=5.0.0 行
  2. docker-compose.yml 删除整个 redis service 块(cc-ai-kefu-redis)
  3. .env.example 删除 REDIS_URL/REDIS_PASSWORD 行及注释
  • Step 4: 安装依赖并建 .env 占位
pip install -r requirements.txt -r requirements-dev.txt
cp .env.example .env

.env 中 ZHIPU_API_KEY 先留占位(跑测试不需真实 Key,LLM 全 mock)。

  • Step 5: 基线测试——未改任何代码前必须全绿
python -m pytest -q

预期:170+ passed(参考项目全绿,拷贝后应同样全绿)。若有 Windows 环境性失败,先修复环境再继续(参考项目 conftest.py 头部有 Windows aiosqlite 清理说明)。

  • Step 6: Commit
git add -A && git commit -m "chore: 从汽车AI客服项目拷贝骨架并清理(blog页/redis)"

Task 2: 公司事实卡 company_facts.md

Files:

  • Modify: app/prompts/company_facts.md(整体重写)

  • Test: tests/test_company_facts.py(更新断言)

  • Step 1: 抓取官网资料

用 WebFetch 依次抓取(提取硬事实,忽略模板化文案):

  • https://hesupipe.com/(已抓取过:公司概况/十大产品线/联系方式)

  • https://hesupipe.com/about-us/(或等价关于页)

  • 产品分类页(HDPE/PVC/PPR 等主要品类页,取规格范围)

  • https://hesupipe.com/certificates/(认证清单)

  • https://hesupipe.com/sales-network/(销售网络/出口国家)

  • 新闻页 1-2 篇真实项目案例(如智利农业供水管项目)

  • Step 2: 重写事实卡

保留参考项目事实卡的结构框架和使用规则段(防编造的"统一兜底/不扩展"原则原样保留),替换内容段。结构:

# HESUPIPE 公司事实卡
## 公司概况
(1998年成立/2007年起出口/河南郑州/高新技术企业——只写官网可验证的)
## 产品线总表
(HDPE管道及管件/HDPE波纹管/PVC管道及管件/PVC电工套管/PPR管道/球墨铸铁管/法兰阀门/HDPE渔网箱/门窗类——每类一行主要规格范围,如 DN20-DN1200)
## 应用领域
(市政给水/燃气油气/排水排污/农业灌溉/电气保护/疏浚/海水养殖)
## 认证
(证书页实际列出的,逐条;没有就整节省略,不编)
## 销售网络与出口市场
(官网实际提及的国家/地区)
## 使用规则(原样保留参考项目的兜底原则)
(未列出的一律说"转客户经理确认";禁止推测/扩展/编造)

红线自查:不含价格、交期、MOQ、产能数字;不收录"world-class"类模板化空话。

  • Step 3: 更新 test_company_facts.py 断言

改为断言建材关键词(如 HESUPIPE、HDPE 或实际产品词)存在、汽车词(BYD/Hesu Auto/vehicle)不存在。

  • Step 4: 跑测试
python -m pytest tests/test_company_facts.py -q

预期:PASS

  • Step 5: Commit
git add -A && git commit -m "feat: HESUPIPE 公司事实卡(官网硬事实+防编造规则)"

⚠️ 审核关卡(设计文档§4.2):事实卡完成后请需求方业务侧过目确认后方可上线(可异步,不阻塞后续任务)。


Task 3: 系统提示词 system.md 重写

Files:

  • Modify: app/prompts/system.md(整篇重写,框架保留)

  • Step 1: 重写 system.md

保留参考项目的六段结构,逐段建材化:

  1. 语言规则(最高优先级):保留"客户用什么语言就用什么语言回复,默认英语";新增:拒绝价格/交期/MOQ/样品费等实质问题时,回复中必须包含固定英文短句 Please leave your contact and our manager will send the full quotation.(保证输出墙正则可靠命中)
  2. 职能边界:AI 只做需求了解+留资;价格/交期/MOQ/装柜方案/样品费/认证清单/库存→转客户经理;问实质问题时若已知意向品类:"确认品类+引导留资"一气呵成
  3. 红线:不出现价格数字(含复述客户预算);不输出电话/邮箱;不再三索要已留资客户的联系方式
  4. 说话风格:外贸销售式简短口语;时效承诺用 "reply within 12 hours"(不提中国作息)
  5. 对话推进:预算路径改为 "Which application? Water supply, gas, drainage or irrigation?";规格追问(口径/压力/标准);围绕已说品类推进
  6. 好差示例:6-8 组管道场景(例:客户说 "PE100 water pipe DN110",差:泛问 what do you need;好:确认 SDR11/SDR17? + 询问工程量;中文话术示例同步改管道语境)
  • Step 2: 自查清单

  • 所有汽车词(car/vehicle/BYD/Toyota/test drive/提车/试驾/续航)已清零:grep -in "car\b\|vehicle\|byd\|toyota\|test drive\|试驾\|提车\|续航" app/prompts/system.md 预期无输出

  • 红线覆盖:MOQ、lead time、container loading、sample fee、certificate、price range

  • 固定英文拒绝短句原样出现(与 boundary_filter 的 DEFLECTIONS 措辞协调但不冲突——prompt 是"含义",墙是"兜底")

  • Step 3: 跑全量测试(system.md 变更影响的测试)

python -m pytest -q

预期:PASS(若有断言 system.md 内容的测试,同步更新)

  • Step 4: Commit
git add -A && git commit -m "feat: 系统提示词建材化(管道外贸人设+多语言拒绝短句)"

Task 4: 提取与评估提示词(extractor.md / evaluator.md)

Files:

  • Modify: app/prompts/extractor.md、app/prompts/evaluator.md

  • Step 1: 重写 extractor.md 字段定义

中文键画像字段改建材语义(设计文档§4.3):

  • 意向品类(HDPE给水管/PVC排水管/PPR…)

  • 规格要求:自由文本保留客户原话(如 "DN110 PE100 SDR11"),明确指示不拆分不过度结构化

  • 标准要求:单独一列(ISO4427/ASTM/EN/SCH 系列,客户提到才记)

  • 采购数量、用途(给水/燃气/排污/灌溉/…)、项目类型、目标国家、预算提及、联系方式字段原样保留参考项目机制

  • Step 2: 重写 evaluator.md 评估语义

三级保留;示例改管道采购:明确品类+规格+数量=interested;仅泛泛浏览=pending;明确无采购计划=not_interested。

  • Step 3: 新增 extractor 字段静态断言测试(spec §9.1 第4条落地;严格 TDD 可提前到 Step 1 之前先写先跑红)

tests/test_company_facts.py 风格,新建断言:extractor 提示词加载后包含 意向品类、规格要求、标准要求 字段定义,且不含 车型/意向品牌 汽车字段。

  • Step 4: 跑全量测试并 Commit
python -m pytest -q && git add -A && git commit -m "feat: 提取/评估提示词建材化(规格自由文本+标准单列)"

Task 5: 多语言输出墙 boundary_filter.py(TDD 核心)

Files:

  • Modify: app/services/boundary_filter.py

  • Test: tests/test_boundary_filter.py

  • Step 1: 先写失败的多语言墙测试

在 tests/test_boundary_filter.py 追加(沿用该文件现有参数化风格):

# ---- 多语言价格墙(建材市场扩充): 必须拦截 ----
MULTILINGUAL_PRICE_HITS = [
    "El precio es 500 dólares",           # 西语 词前置
    "Costo por tonelada 320",             # 西语
    "O preço é 1200 reais",               # 葡语(巴西)
    "Цена 500 за тонну",                  # 俄语
    "Стоимость 800 долларов",             # 俄语
    "السعر 500 دولار",                    # 阿语
    "€500 per ton",                       # 欧元符号
    "£420 per container",                 # 英镑符号
    "500 dólares",                        # 数字+货币词后缀
    "Delivery in 15 días",                # 西语时间承诺
    "Срок 2 недели",                      # 俄语时间承诺
]
# ---- 建材规格形态: 不得误杀 ----
SPEC_NON_HITS = [
    "DN800 double wall corrugated pipe",
    "PN16 pressure rating",
    "SDR11 and SDR17 both available",
    "PE100 material",
    "600mm diameter",
    "SCH40 and SCH80",
    "3/4 inch and 2 inch sizes",
    "ISO4427 certified",
    "20ft container load", "40ft HQ",
    "5.8m and 11.8m lengths",
    "PE80 PE100 grades",
    # Task 3 质量审查发现: customs 是 custo 超集,高频外贸词,不得误杀
    "customs paperwork for 20ft containers",
    "HS code 3917 for customs clearance",
]

断言:前者每个 violates_boundary(s) 为 True;后者每个为 False。

  • Step 2: 跑测试确认失败
python -m pytest tests/test_boundary_filter.py -q

预期:多语言 HITS 用例 FAIL(现有正则拦不住)

  • Step 3: 扩充 PRICE_PATTERNS

在 PRICE_PATTERNS 列表追加(保持参考项目"注释说明设计意图"的风格):

# ---- 多语言墙(建材市场: 欧/英/南美/俄语区/中东) ----
# 货币符号: €/£ 参考项目只有 $
re.compile(r"[€£]\s?\d"),
# 价格名词前置(西/葡/俄/阿): 词后 0-20 非数字字符内出现数字
# ⚠️ 拉丁词必须加 \b 词边界——custo 是英文 customs 的子串,外贸高频
#    "customs paperwork for 20ft" 会被误杀(Task 3 质量审查发现)
re.compile(r"\b(?:precio|costo|custo|preço|цена|стоимость|سعر|ثمن)\b[^\d\n]{0,20}\d", re.I),
# 货币名词后置(数字+货币词)
re.compile(r"\d[\d,.]*\s*(?:d[óo]lares?|euros?\b|рублей|руб\.?)", re.I),
# 多语言时间承诺(与英文 days/weeks 组同构)
# ⚠️ 不收 horas/hours/小时——system.md 的 "reply within 12 hours" 依赖此豁免
re.compile(r"\d+\s*[- ]?(?:d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|أيام)\b"),

同时审查现有汽车特定排除项:

  • \d[\d,.]*\s*(usd|美元|块钱|万块?(?!\s*(公里|km))) 的 公里|km 排除 → 建材语境已无里程语义,但保留无害;确认不误杀建材形态

  • (两|三|四|五|六|七|八|九|十)\s*万(?!\s*(公里|km)) 保留(中文预算)

  • 时间承诺 \d+\s*[- ]?(day|week|month)s?\b 保留(英文交期承诺)

  • Step 4: 跑测试至全绿

python -m pytest tests/test_boundary_filter.py -q

预期:PASS(含原有全部用例不回归)

  • Step 5: 迂回话术建材化 + ES 话术池(spec §6 第3层)
  1. 行业残留清零(用户可见输出,实测在参考项目 L54/L57):
    • DEFLECTIONS_EN_CONTACT 的 "Anything else about the cars?" → "...about pipes?"
    • DEFLECTIONS_ZH_CONTACT 的 "还想了解什么车?" → "还想了解什么管道产品?"
    • 全文件扫一遍 DEFLECTIONS/PIVOTS/NO_CONTACT 各池,确认无其他汽车措辞
  2. 新增 ES 话术池(南美第一大流量,spec §6.3):
    • 新增 DEFLECTIONS_ES、DEFLECTIONS_ES_CONTACT、PIVOTS_ES、PIVOTS_ES_CONTACT (西语版话术,如 "El precio exacto te lo envía nuestro gerente por WhatsApp, ¿me lo dejas?")
    • deflection_for() / pivot_for() 现为"汉字→ZH,否则 EN"二分支,扩展为三分支: 汉字 → ZH;西语特征(re.search(r"[áéíóúñ¿¡]", msg) 粗匹配,与参考项目 汉字检测同构)→ ES;否则 → EN
  3. 测试:tests/test_boundary_filter.py 追加——西语消息选 ES 池、英文选 EN、 中文选 ZH;"cars"/"什么车" 不再出现在任何话术池
  • Step 6: 同步 scripts/breach_rate.py

把上述新词表同步进 breach_rate.py 的统计模式(保持与墙一致,供上线观察期用)。

Step 6b: 打包前序任务遗留的提示词微修(Task 3/4 质量审查移交,随本任务 commit):

  1. extractor.md 字段说明末尾补一行(Task 4 Important):「字段值统一用中文概括(如 Kenya→肯尼亚、irrigation→灌溉);唯一例外是规格要求——必须原样保留客户原文,绝不翻译」
  2. evaluator.md:「询问价格/索要联系方式」两条移出 interested 必要条件列表,单独设「积极信号(加分项,非必要条件)」小节(Task 4 Minor 1)
  3. evaluator.md interested 示例补「聊了几轮后」(Task 4 Minor 2)
  4. extractor.md 标准要求示例改 "ASTM D3035" 并补「编号原样保留」(Task 4 Minor 4)
  5. system.md line 181「固定英文短句」统一为「引导留资模板句」(Task 4 Minor 5)
  6. system.md line 18 与语言规则段确认无残留字面张力(Task 3 复审 nano-nit 已修 line 19,复核即可) 修完跑 test_extractor_evaluator_prompts.py 相关断言(必要时同步微调断言)。
  • Step 7: 全量测试 + Commit
python -m pytest -q && git add -A && git commit -m "feat: 多语言输出墙(€/£/西葡俄阿价格词+时间承诺+ES话术池)+话术建材化+防误杀"

Task 6: 会话编排与联系方式管道建材化

Files:

  • Modify: app/services/conversation.py、app/services/contact_pipeline.py

  • Test: tests/test_contact_pipeline.py、tests/test_context_seeding.py

  • Step 1: 先写失败的阿语数字测试

tests/test_contact_pipeline.py 追加:

def test_arabic_digits_normalized():
    # 阿语数字(中东买家)提取后应转 ASCII,CRM 可直接拨
    confirmed, _ = split_validate({"whatsapp": "+٩٦٦٥٠١٢٣٤٥٦٧"})
    assert confirmed["whatsapp"] == "+966501234567"

(具体 API 名以参考项目实际函数签名为准——split_validate/canon 归一化入口。)

  • Step 2: 跑测试确认失败
python -m pytest tests/test_contact_pipeline.py -q -k arabic

预期:FAIL(号码原样保留阿语数字)

  • Step 3: 实现数字归一化

contact_pipeline.py 顶部加:

# Unicode 十进制数字 → ASCII(阿语٠-٩/波斯语۰-۹), 中东买家号码 CRM 可直接拨
_DIGIT_TRANSLATE = str.maketrans("٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹", "01234567890123456789")

在归一化入口(normalize_contacts/digits_only 调用链的最前端)对值做 v.translate(_DIGIT_TRANSLATE)。注意:正则 \d Unicode 模式本就匹配阿语数字,位数校验能过——本步只解决"存进去的形式"。

  • Step 4: conversation.py 建材化
  1. BOUNDARY_TRIGGER_RE:确认已含 MOQ/lead time/delivery time/sample/certificate 类词;补 container loading|装柜|起订(以实际正则现状为准增补)
  2. context 种子白名单:vehicle_name/vehicle_id → product_name/product_id
  3. _build_context_reminder/_enrich_short_message 中的车型话术 → 产品方案话术
  4. 同步更新 tests/test_context_seeding.py 的键名
  5. 话术跨层同步(Task 3 质量审查 Minor 4):conversation.py 约 592 行的注入提醒与 boundary_filter.py 的 NO_CONTACT_WEB 仍是 "our manager replies fast!",与 system.md 的 "reply within 12 hours" 口径不一致——统一为 12 小时句(或两版并存亦可,但须明确决定)
  • Step 5: 全量测试 + Commit
python -m pytest -q && git add -A && git commit -m "feat: 会话编排建材化+阿语号码转ASCII"

Task 7: 服务端杂项更名

Files:

  • Modify: app/main.py、app/services/email_service.py、app/api/routes/chat_rest.py、app/services/rate_limit.py、app/config.py(如有 DB 默认名)

  • Step 1: 逐文件更名

文件 改动
app/main.py FastAPI(title="AI汽车客服") → title="HESUPIPE AI 客服"
app/services/email_service.py 发件人 【XYH】 → 【HESUPIPE】;确认无汽车字段引用
app/api/routes/chat_rest.py docstring "HESU app" → HESUPIPE;种子键名若此处再有引用同步
app/services/rate_limit.py docstring "Mirrors hesu's" 更新
app/config.py + .env.example DATABASE_URL 默认 data/hesupipe_ai_kefu.db
  • Step 2: 全局残留扫描
grep -rin "汽车\|vehicle\|byd\|toyota\|hesu auto\|borderlesscar\|VOLT\|XYH\|cc-ai-kefu\|cc_ai_kefu\|car\b\|cars\|什么车\|车型\|车价" app/ tests/ scripts/ --include="*.py" | grep -v "docs/"

预期:无输出(docstring/注释里的行业残留一并清零;car\b|cars|什么车|车型 抓 boundary_filter 话术池等用户可见输出)。

  • Step 3: 全量测试 + Commit
python -m pytest -q && git add -A && git commit -m "chore: 服务端品牌与行业残留更名清零"

Task 8: 部署配置更名

Files:

  • Modify: docker-compose.yml、deploy.sh、openresty.conf、.env.example

  • Step 1: 更名

文件 改动
docker-compose.yml 容器名 cc-ai-kefu→hs-ai-kefu;端口 8016:8000→8017:8000(redis 服务已在 Task1 删)
deploy.sh 健康检查 URL 8016→8017
openresty.conf upstream cc_ai_kefu→hesupipe_ai_kefu;127.0.0.1:8016→8017;alias /www/cc_ai_kefu/→/www/hesupipe_ai_kefu/;日志名同步(含注释掉的 HTTPS 段)
.env.example APP_PORT=8017;PUSH_EXTERNAL_KEY_PREFIX=ai-kefu-jc;PUSH_ENABLED=false(开发期)
  • Step 2: 残留扫描
grep -rn "cc_ai_kefu\|cc-ai-kefu\|8016" docker-compose.yml deploy.sh openresty.conf .env.example

预期:无输出。

  • Step 3: 测试 + Commit
python -m pytest -q && git add -A && git commit -m "chore: 部署配置更名(hs-ai-kefu/8017/hesupipe_ai_kefu)"

Task 9: 前端建材化(文案/主题/GDPR + 静态断言同步)

Files:

  • Modify: static/chat.html、static/widget.js、static/js/chat.js、static/js/theme.js、static/admin.html、static/widget-test.html

  • Test: tests/test_invite_static.py、tests/test_theme_static.py

  • Step 1: 了解静态测试的真实性质(避免走错路)

tests/test_invite_static.py/test_theme_static.py 是结构回归网,不是文案断言—— 它们断言的是邀请卡面板出厂 hide、pointer-events、回流顺序、theme.js 与 widget.js 调色板逐字同步、无残留旧色 hex 等结构性质。所以本任务的测试策略是: 直接改前端文件,然后跑结构回归测试防破坏(它们会在你漏改某处色值/结构时指路)。

  • Step 2: 前端文案与配置
文件 改动
chat.html 标题 HESUPIPE Support;描述管道场景;欢迎语 "What kind of piping project are you working on?";热门话题 Get Quotation / Pipe Specifications / Delivery & Shipping;WhatsApp +8615937108317;邮箱 hesu@hesuu.com
widget.js 默认 title/whatsapp/email 同上;邀请卡文案管道化(pipe specs, MOQ, delivery timing);话题按钮同步
js/chat.js WhatsApp/email fallback 默认值同步
admin.html VOLT → HESUPIPE(title/header/头像字母)
js/theme.js 默认品牌色橙 #f08a31 → HESUPIPE 品牌蓝(从 hesupipe.com CSS 取实际主色值)。⚠️ 色值有三处要同步:theme.js 的 DEFAULT_COLOR、widget.js 的 DEFAULT_PALETTE(内联副本,测试强制两份一致)、css/style.css 的 :root 槽位值——漏任何一处 test_theme_static 会红
widget.js GDPR 行:首次对话邀请卡/首条消息附加 "By chatting, you agree to our privacy policy."(链接指向 hesupipe.com 隐私政策页,URL 实施时与需求方确认,可先 https://hesupipe.com/privacy-policy/ 占位)
头像 kefu.png/kefu-small.png 替换(需求方提供 logo 或用品牌蓝底 "H" 字母临时生成)
  • Step 3: 跑静态断言与全量测试至绿
python -m pytest tests/test_invite_static.py tests/test_theme_static.py -q
python -m pytest -q
  • Step 4: 残留扫描 + Commit
grep -rin "HESU Support\|hesu auto\|vehicle\|VOLT\|borderlesscar\|1903717\|f08a31" static/ | grep -v blog
git add -A && git commit -m "feat: 前端HESUPIPE品牌化+管道文案+GDPR提示"

Task 10: 全量回归与收尾扫描

Files: 无新增(验证任务)

  • Step 1: 全仓行业残留终扫
grep -rin "汽车\|vehicle\|byd\|toyota\|test drive\|试驾\|提车\|hesu auto\|borderlesscar\|VOLT\|XYH\|cc_ai_kefu\|cc-ai-kefu\|car\b\|cars\|什么车\|车型\|车价" app/ static/ tests/ scripts/ *.yml *.sh *.conf 2>/dev/null

预期:仅 docs/ 归档 changelog 里有(允许——历史档案)。

  • Step 2: 全量测试
python -m pytest -q

预期:全绿(170+,含新增多语言/阿语数字用例)

  • Step 3: 本地起服务冒烟
python -m uvicorn app.main:app --port 8017 &
curl -s http://127.0.0.1:8017/health
# 预期 {"status":"ok"} 类响应; 浏览器开 http://127.0.0.1:8017/ 与 /admin 目检
  • Step 4: Commit(如有收尾改动)

Task 11: 真人验收(真实 LLM + mock 推送联调)

Files:

  • Create: docs/test-checklist.md(基于参考项目同名文件改写)

  • 临时: .env 填真实智谱 Key

  • Step 1: 编写真人验收清单

按设计文档 §9.2 全项写入 docs/test-checklist.md(问价×2语言/MOQ/样品/交期/认证→转留资;留资→画像+邮件[测试邮箱]+mock推送;换号→更正邮件;已留资不再索要;规格聊天不误杀;后台三视图核对)。

  • Step 2: 起 mock UniService 并配置联调
python scripts/mock_uniservice.py &   # 本地假CRM, 默认端口 9099

.env:PUSH_ENABLED=true、PUSH_API_URL=http://127.0.0.1:9099/open/v1/inquiry/push、 PUSH_API_KEY=test-key-123(mock 脚本期待的固定 Key,不设会 401)、 NOTIFY_EMAIL=测试邮箱、真实智谱 Key。

  • Step 3: 逐项真人验收

按清单实聊(英文+西语+中文三种语言各至少一轮完整留资流程)。核对:邮件收到、mock 推送 accepted、admin 后台画像/意向/日志正确。

  • Step 4: 修复发现的问题直至清单全过 + Commit
git add -A && git commit -m "test: 真人验收清单+联调修复"

Task 12: 交付物(嵌入代码/说明/CLAUDE.md)

Files:

  • Create: docs/embed-guide.md、CLAUDE.md、README.md

  • Step 1: 官网嵌入说明 docs/embed-guide.md

内容:一段可粘贴的挂件代码(script 标签+data-* 配置示例:位置/主题色/WhatsApp/自动邀请),贴到 WordPress 哪里(页脚模板或主题设置)、隐私政策页要求。给官网管理员一页读完即可操作。

  • Step 2: CLAUDE.md 血缘记录

记录:上游参考项目 D:\refactor\ai-kefu、85%同源、上游修bug需对照其 docs/ changelog 手动同步、本项目 external_key 前缀 ai-kefu-jc、开发期 PUSH 关闭约定、上线观察期跑 breach_rate.py。

  • Step 3: README.md

项目简介/本地启动(pip install、.env、uvicorn)/测试(pytest)/部署(deploy.sh+openresty)/管理后台入口。

  • Step 4: Commit
git add -A && git commit -m "docs: 官网嵌入指南+CLAUDE.md血缘+README"

上线切换(验收全过后,需求方操作确认)

  1. .env 切生产:PUSH_API_URL 指真实 UniService、真实 API Key、NOTIFY_EMAIL=客户经理邮箱
  2. 服务器部署:deploy.sh(端口 8017)+ openresty 域名配置(需求方提供,如 ai.hesupipe.com)
  3. 官网按 docs/embed-guide.md 嵌入挂件
  4. 第一周观察期:跑 scripts/breach_rate.py 看漏放/误杀,发现即补正则(设计文档 §9.3)