fix(worker): 知识写入 Milvus 必须探测字段名并补齐必填字段

背景:走 `POST /api/v1/knowledge/upload` 灌了 22 块场内基金知识,MySQL 全部写入成功、
向量事件也全部投递,却全部同步失败(重试 3 次进死信),客服检索不到新知识。
逐层定位出三个真问题,都在写入侧:

1) **字段名硬编码**。检索侧早已按 AGENTS.md 改用运行时探测
   (`app/core/knowledge_schema.py`:`doc_id`↔`knowledge_id`、`content`↔`snippet`),
   写侧却一直硬编码 `knowledge_id` / `snippet`。本机集合实际是
   `doc_id`/`content`/`chapter`/`visibility`/…(架构师那套 schema),于是
   `Attempt to insert an unexpected field knowledge_id` 整条失败。
   现在两侧共用 `resolve_schema` 的同一份映射表,调用方只用**逻辑**字段名;
   集合没有的字段(如另一套环境无 `intent`)跳过而不是报错。

2) **非 nullable 必填字段没给**。改完名字后报
   `Insert missed an field chapter to collection without set nullable==true`:
   集合里存在、调用方没提供的 VARCHAR 字段必须补值。VARCHAR 的判据用
   `params.max_length`,不必 import pymilvus 的枚举。

3) **补值不能一律空串**:`visibility` 留空会被检索侧
   `visibility == "public"` 的过滤整行排除。这条最隐蔽 —— `query` 查得到、`search`
   查不到,表现为「入库成功但客服永远答不出新知识」,比写入直接失败更难定位。
   现在按 `FIELD_DEFAULTS` 给有语义的字段默认值。

Worker 侧把 `fields` 的键改成逻辑名(`snippet` → `content`),上限表随之改名。

**测试**:原来的桩没有 `describe_collection`,所以这条路径从未覆盖到真机 schema
(这正是缺陷长期存在的原因)。现在桩提供两套真实 schema 并参数化,另加
「跳过集合没有的字段」「探测不出必要字段必须失败关闭」两个用例。

**验证**:22 块重新同步后 `fin_product_collection` 236 行、`visibility` 全为 `public`;
问「南方沪深300ETF 的起投金额是多少」命中新块 `score=0.7932`(≥ `HIGH_SCORE` 0.75),
客服从「转人工」变为直接作答,端到端 3.34 秒。

**另**:新增 `docs/43-场内基金产品手册(知识库入库版).md` —— 从 `docs/42` 抽出
**客户可见**的纯净内容(去掉全部内部决策备注)供入库;`docs/42` 保留为草稿与决策记录。
This commit is contained in:
2026-09-13 20:08:31 +08:00
parent 6f397ab513
commit fef4c826ff
5 changed files with 436 additions and 43 deletions
@@ -0,0 +1,168 @@
# 场内基金产品手册
> 本手册面向客户,说明本平台场内基金(ETF / LOF)的公开交易规则与产品资料。
> 手册内容均为公开信息,不含任何个人账户数据。
## 一、交易规则
### 1.1 场内基金怎么买、最小买多少
问:场内基金怎么买?最小买多少?一次能买多少份?
答:本平台的场内基金按"手"撮合,**1 手 = 100 份**,委托数量必须是 100 份的整数倍。
最小交易金额以产品详情页披露的字段为准(平台产品库中登记为 100.00 元);
实际所需金额按成交价 × 份数计算,随市价变动。
实际可买数量与所需金额请以交易页面的实时报价为准。
### 1.2 场内基金的费用有哪些
问:买场内基金要交哪些费用?费率是多少?管理费多少?托管费多少?
答:场内基金涉及两类费用。
**(1)基金自身的费用**,从基金资产中按日计提、体现在净值里,不向您单独收取:
本平台 20 只场内基金的管理费率为 **0.15%~1.20%/年**、托管费率为 **0.05%~0.20%/年**。
其中 ETF 通常较低(如沪深300ETF 管理费 0.15%/年、托管费 0.05%/年),
LOF 与主动管理型较高(如南方积极配置混合 1.20%/年、托管费 0.20%/年)。
货币 ETF 另收销售服务费(如货币ETF南方 0.25%/年)。各产品的具体费率见下方费率一览。
**(2)交易费用**,即您买卖时产生的**券商佣金**,费率由您开户的券商决定,
本平台不代收、也不设定该费率。
### 1.3 报价的最小变动单位
问:场内基金报价最小变动多少?
答:本平台场内基金的最小价格变动单位为 **0.001 元**。
### 1.4 风险等级与适当性
问:我能买什么风险等级的产品?风险等级不匹配能买吗?
答:产品风险等级从 **R1 到 R5**,由低到高。平台按您的**有效风险测评结果**做匹配校验:
测评等级与产品等级不匹配时,下单会被拦截。
请先完成风险承受能力测评,并以交易页面的校验结果为准。
客服不能修改您的测评结果,也不能代为开通跨级权限。
### 1.5 场内基金与场外基金的区别
问:场内基金和场外基金有什么不一样?
答:场内基金(ETF / LOF)在交易所挂牌,按市价、以"手"为单位实时撮合成交;
场外基金按当日净值申赎,通常 T+1 确认。
本平台的模拟交易针对**场内**基金,下单即按市价全额成交。
## 二、产品清单
问:平台上有哪些场内基金?产品代码是什么?有哪些 ETF?
答:本平台场内基金共 **20 只**,包含 13 只 ETF 与 7 只 LOF。
下表净值为最新披露值,会随行情变动:
| 代码 | 名称 | 交易所 | 类型 | 风险等级 | 净值 | 净值日期 |
|---|---|---|---|---|---|---|
| 159329 | 沙特ETF南方 | 深交所 | ETF | R5 | 0.9167 | 2026-09-10 |
| 159382 | 创业板人工智能ETF南方 | 深交所 | ETF | R4 | 2.5841 | 2026-09-11 |
| 159511 | 通信ETF南方 | 深交所 | ETF | R4 | 2.3755 | 2026-09-11 |
| 159615 | 恒生生物科技ETF南方 | 深交所 | ETF | R5 | 1.1027 | 2026-09-11 |
| 159687 | 亚太精选ETF南方 | 深交所 | ETF | R5 | 1.8891 | 2026-09-10 |
| 159700 | 科创债ETF南方 | 深交所 | ETF | R2 | 101.8009 | 2026-09-11 |
| 159948 | 创业板ETF南方 | 深交所 | ETF | R4 | 3.6895 | 2026-09-11 |
| 510300 | 沪深300ETF | 上交所 | ETF | R3 | 4.5794 | 2026-09-11 |
| 510500 | 中证500ETF南方 | 上交所 | ETF | R4 | 7.6027 | 2026-09-11 |
| 511070 | 公司债ETF南方 | 上交所 | ETF | R2 | 103.0145 | 2026-09-11 |
| 511810 | 货币ETF南方 | 上交所 | ETF | R1 | 0.2661 | 2026-09-11 |
| 588890 | 科创芯片ETF南方 | 上交所 | ETF | R4 | 1.2327 | 2026-09-11 |
| 160105 | 南方积极配置混合(LOF) | 深交所 | LOF | R3 | 1.2514 | 2026-09-11 |
| 160127 | 南方新兴消费增长股票(LOF)A | 深交所 | LOF | R4 | 0.8364 | 2026-09-11 |
| 160128 | 南方金利定开债券A | 深交所 | LOF | R2 | 1.0260 | 2026-09-11 |
| 160129 | 南方金利定开债券C | 深交所 | LOF | R2 | 1.0240 | 2026-09-11 |
| 160142 | 南方优势产业(LOF) | 深交所 | LOF | R3 | 1.0623 | 2026-09-11 |
| 160143 | 南方创业板2年定期开放混合 | 深交所 | LOF | R3 | 1.6105 | 2026-09-11 |
| 501018 | 南方原油A | 上交所 | LOF | R5 | 2.0750 | 2026-09-10 |
| 501062 | 南方瑞合定开混合(LOF) | 上交所 | LOF | R3 | 2.1048 | 2026-09-11 |
宽基与债券类 ETF 的风险等级多为 R2~R3,行业主题与跨境类 ETF 多为 R4~R5。
完整清单与实时净值请以产品列表页为准。
## 三、重点产品
### 3.1 沪深300ETF(510300)
问:沪深300ETF 的起投金额是多少?南方沪深300ETF 怎么买?510300 的费率是多少?
答:沪深300ETF 的产品代码为 **510300**,在**上交所**挂牌,属于 ETF,风险等级 **R3**。
它按"手"交易,**1 手 = 100 份**;最小交易金额以产品详情页披露的字段为准(登记为 100.00 元)。
该产品最新净值为 **4.5794 元**(2026-09-11),
管理费率 **0.15%/年**、托管费率 **0.05%/年**,从基金资产中计提、不单独向您收取。
实际成交金额、可买数量与费用请以交易页面的实时报价为准。
**产品披露**:本产品为同指数参考产品,非本公司发行的基金,在本平台仅用于功能演示。
### 3.2 其他产品的查询
问:某只产品的风险等级和费率是多少?怎么查?
答:每只产品的代码、名称、交易所、类型、风险等级、最新净值见上方产品清单,
管理费与托管费见下方费率一览;也可以在产品列表页搜索代码或名称后进入详情页查看。
## 四、费率一览
问:各家基金的管理费和托管费分别是多少?
答:本平台 20 只场内基金的费率如下(单位:%/年,均为从基金资产中计提、不单独向客户收取):
| 代码 | 名称 | 管理费率 | 托管费率 | 销售服务费率 |
|---|---|---|---|---|
| 159329 | 沙特ETF南方 | 0.50 | 0.10 | — |
| 159382 | 创业板人工智能ETF南方 | 0.50 | 0.10 | — |
| 159511 | 通信ETF南方 | 0.50 | 0.10 | — |
| 159615 | 恒生生物科技ETF南方 | 0.50 | 0.15 | — |
| 159687 | 亚太精选ETF南方 | 0.20 | 0.05 | — |
| 159700 | 科创债ETF南方 | 0.15 | 0.05 | — |
| 159948 | 创业板ETF南方 | 0.15 | 0.05 | — |
| 510300 | 沪深300ETF | 0.15 | 0.05 | — |
| 510500 | 中证500ETF南方 | 0.15 | 0.05 | — |
| 511070 | 公司债ETF南方 | 0.15 | 0.05 | — |
| 511810 | 货币ETF南方 | 0.30 | 0.05 | 0.25 |
| 588890 | 科创芯片ETF南方 | 0.50 | 0.10 | — |
| 160105 | 南方积极配置混合(LOF) | 1.20 | 0.20 | — |
| 160127 | 南方新兴消费增长股票(LOF)A | 1.20 | 0.20 | — |
| 160128 | 南方金利定开债券A | 0.50 | 0.15 | — |
| 160129 | 南方金利定开债券C | 0.50 | 0.15 | — |
| 160142 | 南方优势产业(LOF) | 1.20 | 0.20 | — |
| 160143 | 南方创业板2年定期开放混合 | 1.20 | 0.20 | — |
| 501018 | 南方原油A | 1.00 | 0.20 | — |
| 501062 | 南方瑞合定开混合(LOF) | 1.20 | 0.20 | — |
"销售服务费率"为"—"表示该产品不收取销售服务费。
除上表费用外,买卖时产生的券商佣金由您开户的券商决定,本平台不代收。
## 五、常见问答
### 5.1 ETF 能定投吗?
问:ETF 能定投吗?可以自动扣款吗?
答:本平台的场内基金按市价实时撮合成交,**不提供自动定投计划**。
如需分批买入,可以自行分次下单,每次委托数量为 100 份的整数倍。
### 5.2 场内基金多久成交、多久到账?
问:买入后多久成交?
答:本平台为模拟交易,委托按市价**即时全额成交**,成交后持仓与资金变动实时更新。
### 5.3 产品的涨跌幅在哪里看?
问:在哪里看基金今天的涨跌?
答:产品列表页与详情页展示最新净值与当日涨跌;产品详情页另有历史净值走势图。
### 5.4 起投金额是固定的吗?
问:起投金额是多少?会变吗?
答:场内基金按"手"交易(1 手 = 100 份),
最小交易金额以产品详情页披露的字段为准(登记为 100.00 元);
实际所需金额随市价变动,请以交易页面的实时报价为准。