docs(W24): 交付前复核补正 + 场内基金演示线 + 一键启动端到端实跑

按甲方「按你建议的来 一次性搞定上边的建议」执行七项。

文档事实纠错(4 处,逐条实测核对后改)
- D2.4 §AC-04/AC-05:「当前 617 块全部为 public」与本文档自己的 v1.6/v1.8
  版本行(public 730 / registered 25)自相矛盾 ⇒ 标「设计当时」+ 补 v1.8 现状
  (755 块),写明 AC-04/AC-05 现已可证伪、不再需要「造一条测试块」
- D2.5 演示脚本:「family_id 628 块全覆盖」⇒ 755 块(W24 复测)
- D4.8 §9.2:把「集合条数 basic 105 / product 398 / faq 300 / policy 576」
  当成真实条数引用 —— 那是 upsert 墓碑行被计入 get_collection_stats().row_count
  的结果(同 D2.1 v6.9)。已补口径更正段,定规:引用块数一律用 _chunks.jsonl
- D2.6 答辩报告:补 W24 状态 —— docs/43 已入库(702 → 755 块);出口经
  E2c-my 细分后共六个,转人工只在 E5c

演示脚本增强
- D2.5 新增 §4.7 场内基金演示线:5 条台词逐条真 HTTP 实测
  · 场内基金有哪些?             → 20 只清单(13 ETF + 7 LOF)
  · 科创债ETF南方怎么样?        → 单只产品行(R2 / 净值 101.8009)
  · 南方金利定开债券A的管理费率? → 0.50%/年 + 0.15%/年
  · 场内基金报价的最小变动单位?  → 0.001 元
  · 沪深300ETF怎么样?           → E4 生成式作答,且明示「非本公司发行」
  并附修复前/后对比表(修复前:命中另一只产品 / 返回 20 只整张表)
- demo.ps1 自检 2:补 fin_basic_collection ⇒ 四个集合计数(154/251/288/62=755)

_build 处置(不删,改为「把废弃做成一眼可见」)
- 与 D1.6 §4.22 四 已记录的裁定冲突(理由:删掉等于删留痕,也删掉
  「为什么不能重跑」的证据)⇒ 不删
- 三个正文源 _body_kb/_body_plan/_body_requirements.html 顶部加红框
  「已过期」横幅,逐文件列出已核实的滞后项(617 块全 public / 旧品牌
  XX科技·400-XXX·nanfangwm ×5 / 48 条·51 项·7 个批次 / US-CS-08·FR-CS-023)
- _build\README 追加「五、2026-09-21 补记」

端到端实跑(冷启动,非 -SkipStart)
- 停掉全部服务 → 启动演示.bat(demo.ps1 -NoBrowser)⇒ 五项自检全过、rc=0
- 8 个入口 URL 全部 200(portal 首页 / 访客页 / 客户登录 / 员工登录 /
  投顾工作台 / docs / openapi.json / health)
- 访客 token 真对话「科创债ETF南方怎么样?」⇒ succeeded、transfer=False、答单只产品

落档
- D2.1 v6.39 追加「交付前文档复核补正」表(7 项)+ 端到端实跑结论
- D1.6 §11.2 补 W24-8 / W24-9;§11.5 补第 5、6 条
This commit is contained in:
张胜宇
2026-09-21 14:51:32 +08:00
parent 2762b05203
commit 29da85d010
8 changed files with 86 additions and 4 deletions
+3 -3
View File
@@ -105,21 +105,21 @@ if (Get-Command docker -ErrorAction SilentlyContinue) {
Warn "没找到 docker 命令,本项跳过"
}
Section "自检 2/5 · 向量库可查(三个集合计数)"
Section "自检 2/5 · 向量库可查(四个集合计数)"
$probe = @'
import sys
sys.path.insert(0, '.')
from app.core.config import get_settings as g
from pymilvus import MilvusClient
client = MilvusClient(uri=g().resolved_milvus_uri)
for name in ("fin_faq_collection", "fin_product_collection", "fin_policy_collection"):
for name in ("fin_faq_collection", "fin_product_collection", "fin_policy_collection", "fin_basic_collection"):
print(name, client.query(collection_name=name, filter='', output_fields=['count(*)']))
'@
# 经 stdin 送给 python,不走命令行参数:PowerShell 5.1 传原生命令参数时会吞掉内嵌双引号,
# 而这段探测代码必须保留字符串字面量(集合名与 output_fields)。
$probeOut = $probe | & $Python - 2>&1
if ($LASTEXITCODE -eq 0 -and (($probeOut | Out-String) -like "*count*")) {
Ok "三个集合可查:"
Ok "四个集合可查(含 fin_basic_collection 补充语料):"
$probeOut | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
} else {
Warn "向量库探测失败:知识题会走 E5b 兜底(答不出但不会编)"
@@ -66,6 +66,20 @@
**验收(可复算)**:金标 `M-1 46/46`、`M-4 46/46`、`M-6 5/46`、`M-7/M-8/M-9/M-10 = 0`、`M-2 28/31`、`M-2b 15/18`、`M-3 4/4` —— **与 `w23` 基线逐项一致**,且 `w24d` / `w24e` **两次独立复跑结果相同**(本仓库有"只跑一次就宣布修好是假绿"的历史教训);全量 **`1996 passed / 3 skipped`**(上一轮 `1994`,**+2 条新守卫**);`ruff` **零新增**;真 HTTP 11 条全绿(「科创债ETF南方怎么样」→ 单只产品;「…风险等级」→ R2;「…管理费率」→ 0.15+0.05;「场内基金有哪些」→ 20 只清单;访客侧同答、无档位越权)。
**🔎 交付前文档复核补正(同日 · 按甲方「**按你建议的来 一次性搞定**」执行)**
| # | 项 | 处置 |
|---|---|---|
| 1 | `客服agent\D2.4` §AC-04/AC-05 段写「`_chunks.jsonl` **当前 617 块全部为 `public`**」,与本文档自己的 v1.6/v1.8 版本行**自相矛盾** | 标「设计当时」+ 补 v1.8 现状(755 块 / `public 730` + `registered 25`),并写明 **AC-04/AC-05 现已可证伪**、不再需要「造一条测试块」 |
| 2 | `客服agent\D2.5` 演示脚本写「族判定(`family_id` **628** 块全覆盖)」 | 改 **755 块**(`W24` 复测);这是答辩当天要照着念的稿子 |
| 3 | `开发文档\D4.8` §9.2 把「集合条数 `basic 105 / product 398 / faq 300 / policy 576`」**当成真实条数**引用 | 那是 `upsert` **墓碑行**被计入 `get_collection_stats().row_count` 的结果(同本文档 `v6.9`);已补口径更正段,定规:**引用块数一律用 `_chunks.jsonl`,不用 `row_count`** |
| 4 | `客服agent\D2.6` 答辩报告缺 `W24` 状态 | 补一条:① `docs/43` 已入库(702 → 755 块);② 出口经 `E2c-my` 细分后**共六个**,转人工只在 `E5c` |
| 5 | `demo.ps1` 自检 2 只探**三个**集合 | 补 `fin_basic_collection` ⇒ **四个集合计数**(实测 154 / 251 / 288 / 62 = 755) |
| 6 | `客服agent\_build\` 三个正文源(`_body_kb/plan/requirements.html`)会被评委翻到,口径与交付件不一致 | **不删**(`D1.6` §4.22 四 已裁定「保留」,理由是删掉等于删留痕);改为在三个文件顶部加**红框「已过期」横幅**,逐文件列出**已核实的滞后项**,并引导到 README 与现行交付件 |
| 7 | `客服agent\D2.5` 新增 §4.7 **场内基金演示线**(5 条台词,逐条真 HTTP 实测) | 本轮最直观的「变智能了」证据:修复前「科创债ETF南方怎么样」命中**另一只产品**的产品卡、「任意场内基金」返回 **20 只整张表**;现在给单只产品行与 20 只清单 |
**端到端实跑(冷启动)**:停掉全部服务后执行 `启动演示.bat`(`demo.ps1 -NoBrowser`)⇒ **五项自检全过**、退出码 0;8 个入口 URL 全部 `200`(`/portal/` `/portal/guest/home/` `/portal/customer/login/` `/portal/employee-console/login/` `/portal/employee-advisor/dashboard/` `/docs` `/openapi.json` `/internal/health/ready`);再用访客 token 打一条真对话(「科创债ETF南方怎么样?」)⇒ `succeeded`、`transfer=False`、答单只产品。
**改动文件**:`tools/build_knowledge_chunks.py`(新增源 + 三开关 + 行标签修复)、`tools/load_knowledge_milvus.py`(`embed()` 分批 + 自检期望)、`app/service/agent/implementations/customer_service.py`(产品名识别三处 + `display_hits`)、`tests/unit/service/test_customer_service_agent.py`(+2 守卫)、`knowledge/_chunks.jsonl`(702 → 755)、`knowledge/product/场内基金产品手册(知识库入库版).md`(新镜像)、`docs/43-…md`(表头单位)、`_eval_harness/cases_46.json`(两条期望修订)、`开发文档/D4.8`(§10)、`开发文档/D1.6`(§11)、`开发文档/D1.1`、`客服agent/D2.4`、`客服agent/D2.8`、`客服agent/D2.9`、本文件。
## v6.38 本轮修订要点(2026-09-21 · `W21` 第二轮:**四项待决按建议全部落地** —— `D1` 生成侧禁令 + `D2` 指代依据 + `D3` 答非所问闸门 + `D4` 作答语气)
@@ -87,7 +87,7 @@ cd D:\桌面\金融\group_fqcd_jr
---
## 4. 客服线(登录 `cust_t` · 6 组台词)
## 4. 客服线(登录 `cust_t` · 7 组台词)
### 4.1 本人画像 / 分层(`E2e`,确定性取数,不调模型)
@@ -149,6 +149,35 @@ cd D:\桌面\金融\group_fqcd_jr
**一句话口径**:转人工只有 **4 类白名单**(用户显式要求 / `P0` 反诈 / `P1` 账户数据 / `P2` 写操作与争议),**白名单外发生转人工 = 验收不合格**(`H-04` 有 AST 结构性守卫)。
### 4.7 场内基金(`W24` 新增语料 · 20 只产品已入库)
> **为什么单列一组**:这是「不智能」最容易被现场戳穿的一类 —— **问在库的产品、却答另一只**。
> 根因是 `docs/43-场内基金产品手册`(20 只:13 只 ETF + 7 只 LOF)**从未进过切片 `SOURCES`**,
> 语料里根本没有这批产品(`W21` 实测:702 块里「科创债」**0 处**);`W24` 已入库,切片件 **702 → 755 块**。
> 完整实施与验收见 `开发文档\D4.8` §10。
| # | 台词 | 实测出口 | 实测答复(节选) |
|---|---|---|---|
| 1 | 场内基金有哪些? | `E3` 知识直返 | 「本平台场内基金共 **20 只**,包含 13 只 ETF 与 7 只 LOF。ETF 例如:沙特ETF南方(159329)…科创债ETF南方(159700)…沪深300ETF(510300)…(共 13 只);LOF 例如:南方积极配置混合(LOF)(160105)…南方金利定开债券A(160128)…(共 7 只)。完整清单与实时净值请以产品列表页为准。」 |
| 2 | 科创债ETF南方怎么样? | `E3` 知识直返 | 「二、产品清单:代码 159700 / 名称 科创债ETF南方 / 交易所 深交所 / 类型 ETF / **风险等级 R2** / 净值 101.8009 / 净值日期 2026-09-11」 |
| 3 | 南方金利定开债券A的管理费率是多少? | `E3` 知识直返 | 「四、费率一览:代码 160128 / 名称 南方金利定开债券A / **管理费率(%/年) 0.50** / 托管费率(%/年) 0.15 / 销售服务费率(%/年) 无」 |
| 4 | 场内基金报价的最小变动单位是多少? | `E3` 知识直返 | 「本平台场内基金的最小价格变动单位为 **0.001 元**。」 |
| 5 | 沪深300ETF怎么样? | **`E4` 证据约束生成** | 「沪深300ETF(代码510300)在上交所挂牌,属于ETF,**风险等级为R3**…管理费率为0.15%/年,托管费率为0.05%/年…需要说明的是,**该产品为同指数参考产品,非本公司发行的基金**,在本平台仅用于功能演示。」 |
> **可念的一句话**:「第 5 条是全库**唯一一个名字里没有『南方』字样的产品**(`510300 沪深300ETF`),
> 而且手册自己写明它**不是本公司发行的** —— 系统既**认得出它**,也**没有把它认领成自家产品**。」
**修复前 vs 修复后(现场对比用)**
| 台词 | 修复前(`W21` 实测) | 修复后(`W24` 实测) |
|---|---|---|
| 科创债ETF南方怎么样? | top1 命中 **`南方稳健增利债券A` 的产品卡**(0.6696)—— **问 A 拿到 B 的资料** | 该产品**自己的**产品行(代码 / 交易所 / 类型 / 风险等级 / 净值) |
| 任意一只场内基金 | 返回 **20 只产品的整张表**(切片器把整节块换上来) | 单只产品的自解释行 |
> ⚠️ **演示注意**:这几条走的是 `E3` 知识直返(原文直返,不调模型),**响应最快**,
> 适合开场第 1—2 条用来"稳住";第 5 条走 `E4` 会调模型,约 3—5 秒。
---
## 5. 排障表
@@ -33,3 +33,20 @@
该风险已登记在:开发文档\D1.1-文档索引与权威声明.md §13 第九轮 · 构建脚本已过期(勿重跑)
登记日期:2026-09-17
五、2026-09-21 补记:三个正文源已加「已过期」横幅
交付前的文档复核发现:评委若直接打开 _body_kb.html / _body_requirements.html /
_body_plan.html,会看到与现行交付件不一致的口径,误以为项目口径混乱。
处置:**不删除本目录**(理由见下),改为在三个正文源顶部加一段**红框「已过期」横幅**,
并逐文件列出**已核实的滞后项**,把读者引导到 README 与现行交付件。
为什么不删:本目录是「被显式宣告废弃并留痕」的构建脚手架 —— 删掉等于删留痕,
也删掉了「为什么不能重跑」的证据(该裁定见 开发文档\D1.6 §4.22 四)。
已核实的滞后项(2026-09-21 实测):
- _body_kb.html 「_chunks.jsonl 当前 617 块全部为 public」
(现行 755 块、public 730 / registered 25)
- _body_requirements.html XX科技 / 400-XXX-XXXX / nanfangwm.com ×2/×2/×1
「48 条」×4、「51 项」、「7 个批次」
仍含删除前文本 US-CS-08 与 FR-CS-023
- _body_plan.html 「48 条」、「51 项」×2、「7 个批次」×2
+6
View File
@@ -1,3 +1,9 @@
<div style="border:3px solid #c00;background:#fff4f4;color:#8b0000;padding:14px 18px;margin:0 0 20px 0;line-height:1.8;font-size:14px;">
<p style="margin:0 0 6px 0;"><strong>⚠️ 本文件已过期(2026-09-17 起)—— 构建中间产物,仅作历史留痕。</strong></p>
<p style="margin:0 0 6px 0;"><strong>它不是交付件,也不代表现行口径;请勿重跑构建、勿据它下结论。</strong></p>
<p style="margin:0;font-weight:normal;">现行交付件与口径以 <code>客服agent\D2.2-客服Agent需求文档.html</code> / <code>D2.3-客服Agent开发计划.html</code> / <code>D2.4-客服Agent知识库设计方案.html</code> 三份为准。本目录的废弃状态已登记在 <code>_build\README-已过期-请勿重新生成.txt</code> 与 <code>开发文档\D1.1</code>「§13 第九轮 · 构建脚本已过期(勿重跑)」。</p>
<p style="margin:6px 0 0 0;font-weight:normal;">本文件<b>已知滞后项</b>:语料写「<code>_chunks.jsonl</code> <b>当前 617 块全部为 <code>public</code></b>」(现行:<b>755 块</b>、<code>public 730 / registered 25</code>);出口未含 <code>E4</code> 证据约束生成与「六个出口」口径。</p>
</div>
<!-- ==================== 0 ==================== -->
<h1 id="0.-文档定位与阅读指引">0. 文档定位与阅读指引</h1>
+6
View File
@@ -1,3 +1,9 @@
<div style="border:3px solid #c00;background:#fff4f4;color:#8b0000;padding:14px 18px;margin:0 0 20px 0;line-height:1.8;font-size:14px;">
<p style="margin:0 0 6px 0;"><strong>⚠️ 本文件已过期(2026-09-17 起)—— 构建中间产物,仅作历史留痕。</strong></p>
<p style="margin:0 0 6px 0;"><strong>它不是交付件,也不代表现行口径;请勿重跑构建、勿据它下结论。</strong></p>
<p style="margin:0;font-weight:normal;">现行交付件与口径以 <code>客服agent\D2.2-客服Agent需求文档.html</code> / <code>D2.3-客服Agent开发计划.html</code> / <code>D2.4-客服Agent知识库设计方案.html</code> 三份为准。本目录的废弃状态已登记在 <code>_build\README-已过期-请勿重新生成.txt</code> 与 <code>开发文档\D1.1</code>「§13 第九轮 · 构建脚本已过期(勿重跑)」。</p>
<p style="margin:6px 0 0 0;font-weight:normal;">本文件<b>已知滞后项</b>:需求计数写 <b>「48 条」、「51 项」×2、「7 个批次」×2</b>(现行:<b>52 条 / 57 项 / 8 个批次</b>);未含批次 H(智能增强)。</p>
</div>
<!-- ==================== 0 ==================== -->
<h1 id="0.-文档定位与前提">0. 文档定位与前提</h1>
@@ -1,3 +1,9 @@
<div style="border:3px solid #c00;background:#fff4f4;color:#8b0000;padding:14px 18px;margin:0 0 20px 0;line-height:1.8;font-size:14px;">
<p style="margin:0 0 6px 0;"><strong>⚠️ 本文件已过期(2026-09-17 起)—— 构建中间产物,仅作历史留痕。</strong></p>
<p style="margin:0 0 6px 0;"><strong>它不是交付件,也不代表现行口径;请勿重跑构建、勿据它下结论。</strong></p>
<p style="margin:0;font-weight:normal;">现行交付件与口径以 <code>客服agent\D2.2-客服Agent需求文档.html</code> / <code>D2.3-客服Agent开发计划.html</code> / <code>D2.4-客服Agent知识库设计方案.html</code> 三份为准。本目录的废弃状态已登记在 <code>_build\README-已过期-请勿重新生成.txt</code> 与 <code>开发文档\D1.1</code>「§13 第九轮 · 构建脚本已过期(勿重跑)」。</p>
<p style="margin:6px 0 0 0;font-weight:normal;">本文件<b>已知滞后项</b>:品牌仍是旧口径 <b>XX科技 / 400-XXX-XXXX / nanfangwm.com</b>(现行:<b>南方基金 / 400-889-8899 / nffund.com</b>);需求计数写 <b>「48 条」×4、「51 项」、「7 个批次」</b>(现行:<b>52 条 / 57 项 / 8 个批次</b>);仍含删除前文本 <code>US-CS-08</code> 与 <code>FR-CS-023</code>。</p>
</div>
<!-- ==================== 0 ==================== -->
<h1 id="0.-文档定位与阅读指引">0. 文档定位与阅读指引</h1>
@@ -3417,6 +3417,8 @@ pytest **2 failed / 1577 passed / 2 skipped**(= `T0` 基线同两项)、ruff
| `W24-5` | 「3.2 其他产品的查询」(导航型小节) | **不入库**(`exclude_sections`)—— 它抢走了 `B-06` 的 top1 | 本步实测 |
| `W24-6` | 旧数据集 | **不用旧数据,全部用新数据**(甲方原话) | 未做任何增量 upsert;全部 drop 重建 |
| `W24-7` | 是否允许删旧 Milvus 库 | **允许**(「必要时可以跑单元测试与回归测试」「全部一起做一起测试」) | 本轮重建 1 次(补切片后再重建 1 次,共 2 次) |
| `W24-8` | 演示脚本是否加入**场内基金演示线** | **加**(`D2.5` 新增 §4.7,5 条台词逐条真 HTTP 实测) | 「科创债ETF南方怎么样」→ 单只产品行;「场内基金有哪些」→ 20 只清单;「沪深300ETF怎么样」→ `E4` 生成式作答且**不认领非本公司产品** |
| `W24-9` | `客服agent\_build\` 是否**删除** | **不删** —— 与 `D1.6` §4.22 四 已记录的裁定冲突(理由是「删掉等于删留痕,也删掉『为什么不能重跑』的证据」)⇒ 改为在三个正文源顶部加**红框「已过期」横幅** + 逐文件列出已核实的滞后项 | `_build\README` 追加「五、2026-09-21 补记」 |
### 11.3 本轮**判据变更**(必须知情,不要当成"零回归")
@@ -3441,3 +3443,5 @@ pytest **2 failed / 1577 passed / 2 skipped**(= `T0` 基线同两项)、ruff
2. **`E5b` 展示层净化仍不覆盖「收益 + 数字%」形态**(§10.5 第 5 条)—— 本轮未动,继续挂账。
3. 语料里仍有 **2 个零容忍地雷块**(`POL-SPM-016` / `POL-SPM-022-01`),是**禁令条款**,**故意保留**,不是缺陷。
4. `ruff` 既有告警未顺手改(`customer_service.py:34` I001、`:1220` E501,行号因新增代码下移);本轮**引入过** 2 条 `tools/build_knowledge_chunks.py` `B905`,已在轮内改 `zip(..., strict=True)` 清零。
5. **交付前文档复核又发现 4 处事实错误**(`D2.4` 自相矛盾 / `D2.5` 过期块数 / `D4.8` 墓碑行误标 / `D2.6` 缺 `W24` 状态),已在同日补正,见 `D2.1` `v6.39` 的「交付前文档复核补正」表。
6. **`_build\` 未删**(`W24-9`):它与已记录的裁定冲突,且本仓库有过「清理判据过宽导致误删留痕文件」的教训(§4.22 后的自我失误留痕)⇒ 处置改为「把废弃做成一眼可见」。