THINGJS RAG 知识库 · 项目复盘
关键取舍
为什么先按 API 成员切片,再限制片段长度?
- 文档结构:ThingJS API 文档以类和成员组织,一个成员通常包含方法签名、说明与示例。先按
###切分能保留这一组内容。 - 长度限制:只有同一成员超过 800 字才继续分段,相邻段目标重叠 200 字;代码块尽量保留完整。800 和 200 进入切块指纹,调整后需要重新生成向量索引。
为什么用向量与 BM25 双路检索?
- 不同问法:BM25 对类名、方法名等明确标识符有用;向量检索能补充中文口语问法。
- 融合方式:RRF 按排名合并两路结果,单路贡献为
1 / (60 + 名次 + 1);同一片段在两路出现时累加分数。类名不再额外给融合排名加分。
为什么不用大模型改写问句?
- 可控性:别名扩写和近邻类名纠错基于已有类目录,避免改写出文档中不存在的类。
- 调用成本:规则在检索前执行,不增加一次生成模型调用。
遇到的问题与处理
“摄像机看向某点”没有 API 名称,怎样找到方法?
- 问题:口语问句里没有
Camera或lookAt;仅靠字面匹配容易漏掉目标成员。 - 处理:检索前用别名表补充类名和方法关键词;索引的检索文本加入类名、成员名等信息,生成时仍使用原文片段。
多个类同时提问时,为什么后面的类会遗漏?
- 问题:
Box、Sphere、Cylinder一起提问时,融合结果里可能有三个类,但直接取前 5 条会让前两个类占满采用列表。 - 处理:单类仍取 5 条;问句涉及多个类时,每类最多 3 条并轮流采用。同一类里点名成员优先,其余再优先概述和构造函数。
怎么判断是检索没找到,还是模型没答好?
- 先看采用列表:目标类或成员未进入列表,检查切片、别名、问句规划与融合。
- 再看回答:目标片段已经进入列表,但回答遗漏或引用不符,检查生成提示、格式与引用校验。
- 评测时分开检查:检索黄金集按规则看类命中、成员命中和误空。生成黄金集先检查引用是否落在本次证据上,再由裁判模型判断这次回答是否正确。在线单次提问使用采用列表和引用校验。
目前的边界
用户说不要用某个方法时,检索到的片段还能直接生成吗?
- 问题:被问句明确禁用的成员仍可能进入采用列表。若整段交给生成模型,回答容易再次提到它。
- 处理:生成前从采用结果里排除这些片段。排除后没有可用证据就不调用生成模型;引用只能指向留下来的证据。
API Key 能防止不同客户文档互相检索吗?
- 当前能力:正式 MCP 接入用 API Key 控制谁可以调用,用量记在该 Key 上;网页使用独立日 token 池。语料带来源标记。当前没有文档级 ACL,也不是按租户拆库。
- 边界:来源标记不能阻止跨客户文档被检索。按产品线拆索引并强制来源过滤属于后续方案。
文档量大幅增长时,哪一层需要先调整?
- 关键词索引:当前 BM25 索引整体驻内存,文档与进程数增长会增加内存占用。
- 检索范围:全库检索在大规模语料下可能引入更多噪声。按产品线或类缩小范围、外置关键词索引和共享查询缓存是后续扩容思路,尚未作为当前成果。
经验总结
- 保留文档结构:按成员切片,再对超长成员分段,便于检索和引用定位。
- 把召回与采用分开看:融合结果出现目标片段,不代表片段一定进入生成上下文;多类问题还需检查采用配额。
- 把门禁与实测分开写:评测指标和阈值说明发版要求;没有实际测量记录时,不据此声称命中率或幻觉率已达标。