结论先行:投研场景是 RAG 数据工程的典型考场——文档杂、格式旧、更新快。ashare-web 把 A 股财报、券商研报、投资者关系记录建成 RAG 问答系统,靠差异化解析、幂等导入、Unstructured-to-SQL 和降级策略扛住真实语料。
一、语料规模与挑战
真实投研语料的体量超出大多数团队的想象:841 家公司、252,386 份文档、147GB,时间跨度从 2000 年至今。更麻烦的是格式:其中 23.3% 是非常规格式——HTML 公告、OLE2 老 .doc、巨潮 .bin 老式文本。没有差异化解析兜底,近四分之一的语料在入口处就丢了,后面的检索再好也无济于事。
这类语料的更新节奏也苛刻。财报季集中批量入库,公告随披露即到,研报和投资者关系记录持续累积。导入管道必须能承接批量洪峰,也能随到随处理,还不能因为一次失败就整批返工——规模一大,任何一次全量重跑都是工程事故。
二、幂等键与增量
系统以文件内容 SHA-256 前 16 位 hex 作为幂等键。导入时先比对:内容没变的文件直接跳过,只有变更文件才重处理。财报年年发布、历史文件反复回灌,这个设计保证同一条数据入库多少次都只占一个位置,不会重复也不会冲突。
大规模语料还要考虑中断:批量导入跑到一半挂掉,断点续跑让已完成的批次不返工。增量导入后需重启 serve 才能检索到新数据,这是当前版本的明确边界。另一层保护是降级策略:嵌入缓存不完整时,系统静默降级为纯 BM25——检索质量暂降,服务可用性不丢,等缓存补齐再恢复混合检索。
三、表格指标进结构化库
财报里最有价值的部分是表格:营收、净利、毛利率这类指标。纯向量检索对“某公司近三年营收是多少”这类问题并不擅长,系统用 Unstructured-to-SQL 把表格指标抽进 SQLite 指标库,同一个问题可以同时走语义检索和 SQL 查询两条路,互相校验。
结构化指标的另一个好处是可组合。时间过滤在这种场景里几乎必需:某次测试里,17,590 条候选经时间过滤后剩 829 条,18,805 条剩 827 条,约过滤 95.5%——没有结构化元数据,这种过滤根本无从做起,全量候选也会把生成端的上下文窗口挤爆。
| 能力 | 实现 |
|---|---|
| 幂等导入 | SHA-256 前 16 位 hex 为键 |
| 结构化指标 | Unstructured-to-SQL → SQLite |
| 服务接口 | /api/search、/api/ask |
| 降级策略 | 缓存不全时回退纯 BM25 |
四、可复用的工程经验
这套系统的价值不在单点技术,而在把几个朴素原则跑通:入口处不丢数据(差异化解析)、重复导入不返工(幂等键)、指标不只靠向量(结构化库)、缓存不全也不停服(降级策略)。效果可以量化:检索冒烟测试里 000001、000002 均 10/10 命中,000002 的十个问题端到端 4.6 秒。在一份已匿名的同类客户交付里,859 份文档导入 0 失败,产出 36,395 个 chunk、约 3519 万字符。
想在自己的语料上复用这些经验,可以按环节深入:老格式差异化解析见 老格式文档解析;切片与增强见 切片策略 与 Chunk 四级增强;大规模语料的生命周期管理见 知识库生命周期;真实案例的完整指标可参考 已匿名客户案例。
案例深读:从 147GB 语料到 4.6 秒问答的链路账
把整条链路的数字摆在一起,才能看清每个环节的贡献。语料层:841 家公司、252,386 份文档、147 GB,其中 23.3% 非常规格式靠差异化解析兜底。项目层:两家上市发行人 859 份文档 0 失败,36,395 个 chunk、约 3519 万字符,研报 227 份来自 25 家机构、投资者关系记录 112 份、457 项指标入 SQLite 指标库。嵌入层:Qwen3-Embedding-4B + 磁盘嵌入缓存,评测迭代零重复嵌入。检索层:BM25 与 Dense 按 1.6 : 1.0 加权 RRF 融合,时间过滤把候选集从 17,590 压到 829(约 95.5%),检索冒烟 000001、000002 均 10/10 命中。端到端:000002 十问 4.6 秒。
这条链路里没有单点魔法:0 失败来自解析与审计(added + unchanged == total),命中率来自混合检索与查询改写,秒级响应来自过滤、精排与分层生成的配合。其他行业的迁移思路见私有化部署与数据主权;评测方法论的完整拆解见RAG 评测三层指标。
常见问题 FAQ
Q1:投研语料最大的难点是什么?
文档杂、格式旧、更新快。841 家公司、252,386 份文档、147GB 中,23.3% 是 HTML、OLE2 .doc、巨潮 .bin 等非常规格式,必须靠差异化解析兜底,否则入口就丢四分之一。
Q2:幂等键用什么实现?
文件内容 SHA-256 的前 16 位 hex。导入先比对,未变文件跳过,仅变更文件重处理;增量导入后需重启 serve,新数据才可检索。
Q3:表格里的指标怎么被查到?
经 Unstructured-to-SQL 抽进 SQLite 指标库,既能向量检索也能 SQL 查询。“近三年营收”这类问题可同时走语义与结构化两条路,互相校验。
Q4:嵌入缓存不完整时怎么办?
系统静默降级为纯 BM25,检索服务不中断,等缓存补齐后恢复混合检索;配合幂等键与断点续跑,批量导入也不返工。
需要搭建企业级 RAG 知识库?了解丑梨AI
私有化部署的 RAG 数据工程基座:解析、清洗、脱敏、压缩、切片、治理、评测一站式流水线,全本地推理,数据不出域,单机可部署。