基于原型验证的实验结论,本文档设计一套可落地的RAG部署方案,由于种种原因,系统依托平台不便透露,以下称 tRAG 平台。系统基于 tRAG 平台,整合私域Wiki/论坛数据与公开游戏 Wiki 数据,构建面向游戏策划领域的专业 RAG 系统。
项目总览
注:tRAG 是一款某司 RAG 服务平台
本项目是一个游戏策划领域的垂直知识库 RAG 系统,数据来源覆盖三大渠道:
- 某私域Wiki,包含策划案、设计文档、复盘报告等资料,可通过 MCP 获取。
- 某私域论坛,包含技术分享、方法论文章、GDC 翻译等资料,可通过 MCP 获取。
- 游戏 Wiki / 公开平台,包含游戏分类数据库、各游戏 Wiki、专业评测等资料数据,可通过 MCP 获取。
本项目包含以下三个子系统:
- GDDClaw 数据采集系统,负责三源数据的抓取
- 数据清洗 & Chunk & Embedding 入库系统
- RAG 查询服务系统,包含多路召回、精排等功能
如下图所示:
| 维度 | 原型系统(本地验证) | 线上版本 |
|---|---|---|
| 向量数据库 | Qdrant Local(嵌入式 SQLite) | tRAG HybridCollection(倒排向量一体库,分布式) |
| Embedding | 本地 BGE-M3 | tRAG 平台托管 Embedding(public-bge-m3,GPU 集群) |
| Sparse 检索 | Qdrant 内置稀疏向量 | tRAG 倒排索引(Trecall-Olama,BM25 FullText) |
| Rerank | 本地 bge-reranker-v2-m3 | tRAG 平台 Rerank API(bge-reranker-v2-m3,GPU) |
| 数据采集 | 手动下载文章 | GDDClaw 自动化三源采集(私域Wiki MCP + 私域论坛 MCP + 爬虫) |
| 数据规模 | 200 篇 → 1,656 Chunks | 830 篇有效文档 → 8,164 Chunks(持续增量更新) |
| 部署模式 | 单机 Python 脚本 | tRAG 平台托管 + 定时任务调度 |
| Query 预处理 | 无 | 意图识别 + 多 Query 改写 + 多轮对话 Query 重写 |
GDDClaw:三源数据采集子系统
GDDClaw(Game Design Document Crawler)负责从三个数据源持续采集游戏策划领域的文档数据。
私域 Wiki Claw:私域Wiki 数据采集
通过 私域Wiki MCP 或 私域Wiki API 采集指定空间下的策划文档。
采集流程为:
-
- 配置目标空间列表 & 文档目录树
-
- getSpacePageTree(parentid) → 递归获取文档树
-
- getDocument(docid) → 获取文档 Markdown 内容
-
- metadata(docid) → 获取文档元数据(作者、时间、标签)
-
- 统一格式化 → 输出到数据格式层
调用API采集示例:
1 | def fetch_doc_as_markdown(doc_url): |
增量更新策略类似于:
1 | # Record last crawl timestamp per document |
私域论坛 Claw:私域论坛知识库采集
通过 私域论坛 MCP 或 私域论坛 API 采集指定团队/分类下的文章。
采集流程:
-
- 配置目标团队 ID / 文章分类
-
- 私域论坛 API 列表接口 → 获取文章列表(支持分页)
-
- 私域论坛 API 详情接口 → 获取文章 HTML/Markdown 内容
-
- tRAG 文档格式转换插件 → 统一转为 Markdown
-
- 统一格式化 → 输出到数据格式层
在处理私域Wiki与私域论坛的业务差异时,主要体现在四个维度:首先,Wiki 采用原生 Markdown 格式,可通过 Wiki2md 插件直接转换,而论坛内容以 HTML 为主,需通过 docx2md 或 HTML 转译工具处理;其次,在权限管理上,Wiki 侧重空间级授权,论坛则细化到团队或文章级;最后,针对增量更新的识别,Wiki 依赖 modifyTime 字段,而论坛则通过文章更新时间戳进行校验。
Web Claw:公开游戏数据采集
采用 通用爬虫模板 + Agent 自主生成代码 的混合链路。
对于结构复杂的站点(如游戏 Wiki),采用 Agent 链路:
-
- 人工提供目标站点 URL + 期望数据结构描述
-
- Agent 分析站点 DOM 结构(通过 spider_url 获取 HTML)
-
- Agent 生成定制化爬虫代码(Python + BeautifulSoup/Scrapy)
-
- tRAG 代码执行插件运行爬虫代码
-
- 输出结构化数据 → 统一格式层
数据清洗 & Chunk & Embedding 入库
- GDDClaw 原始数据 (Markdown + Meta)
- Stage 1: 数据清洗 & 质量过滤
- Stage 2: 分块策略(标题层级切分 / tRAG 语义切分)
- Stage 3: tRAG HybridCollection 入库(自动 Embedding + 倒排索引)
- tRAG 倒排向量一体库(线上可查询状态)
Stage 1:数据清洗 & 质量过滤
DataCleaner 是数据入库前的质检站环节。它通过流水线作业对抓取内容进行深度精炼。首先自动化降噪,剔除导航和页脚等无关模板;其次利用 SimHash 算法进行跨源去重,确保 Wiki 与论坛的重复内容不被反复记录;最后通过长度与语种双重过滤,屏蔽低质短文与无效字符,确保只有高纯度的知识被沉淀进系统。
1 | class DataCleaner: |
Stage 2:分块策略
我们提供两种分块路径,根据文档结构自动路由。分块(Chunking)是 RAG 系统中最容易被低估却影响深远的环节,分块粒度直接决定了检索精度与生成质量之间的平衡。切片太小,检索虽精准但上下文支离破碎,LLM 容易断章取义;切片太大,上下文完整但包含大量噪声,检索匹配度下降。本系统采用「双路径」策略,根据文档是否具有清晰的标题层级结构进行路由,兼顾两种场景的最优解:
路径 A:标题层级切分(结构化文档)
对于具有清晰标题层级(H1/H2/H3)的文档,按标题层级进行结构化切分:
1 | Markdown 文档 |
适用场景:私域Wiki 策划案、私域论坛 技术文章等具有清晰标题结构的文档。
路径 B:tRAG 语义切分(非结构化文档)
对于缺乏清晰标题层级的文档,使用 tRAG 平台的语义切分 API:
1 | def semantic_split(text: str, is_markdown: bool = True) -> list: |
tRAG 语义切分的技术原理:
语义切分 (Semantic Chunking), 是一种基于 Embedding 相似度动态寻找断点的高级分块策略。其核心原理是:先将文本按句子级别切分,然后计算相邻句子之间的向量余弦距离。当相邻句子的语义差异超过设定阈值(通常取第 80 百分位数)时,在该位置进行截断。这种方法能确保每个 Chunk 在语义上是完整的,避免了固定长度切分导致的语义割裂。
tRAG 平台的语义切分 API 在此基础上做了进一步优化:
- Markdown 结构感知:自动识别 Markdown 标题层级(H1/H2/H3)作为优先切分边界,标题天然是语义分界点
- 语义连贯性保证:不会在句子中间切断,保证每个 Chunk 的语义完整性
- 多粒度检索目标:
enableEmbeddingTarget=True时,同一 chunk 可生成多个检索目标,提升不同粒度查询的召回率
分块路由逻辑
通过正则扫描标题层级(H1-H3)来判断文档属性:针对结构严谨的文档,采用标题敏感切分以保留原始逻辑架构;而对结构松散的文本,则自动切换至 tRAG 语义分割算法进行深层切分。这种“因材施教”的策略,确保了不同来源的文档都能转化为最具语义完整性的知识分片。
1 | def chunk_document(doc: dict) -> list: |
Stage 3:tRAG HybridCollection 入库
创建 HybridCollection(一体库)
使用 tRAG 的倒排向量一体库,一个知识库同时支持向量检索和倒排检索,一方面利用 BGE-M3 模型 生成 1024 维向量,通过 HNSWLIB 引擎 实现高性能的语义向量检索;另一方面开启 BM25 全文索引 模式,以支持精确的关键词匹配。
文档导入
文档导入是将分块后的 Chunk 写入 HybridCollection 的过程。导入时,每个 Chunk 需要提供三类信息:
- 向量信息:通过
embeddingQuery字段提供用于生成向量的文本,tRAG 后端自动调用 BGE-M3 GPU 集群完成编码(也可直接传入预计算的vector) - 倒排信息:通过
invertedDocument.content提供用于 BM25 全文检索的文本(不传时默认使用doc字段) - 元数据信息:通过
docKeyValue提供过滤字段值(如 source、category、chunk_type 等),用于检索时的filterExpr条件过滤
导入采用批量方式(每批最多 200 条),tRAG 后端会自动完成 Embedding 计算、HNSW 向量索引构建、BM25 倒排索引构建三个步骤。注意倒排索引构建需要一定时间,导入后立即检索可能检索不到数据,建议等待 1 分钟后再尝试。
增量更新策略
利用元数据过滤器(filterExpr),根据唯一的 doc_id 定向清除该文档在混合索引库中的所有陈旧切分片,随后将重新生成的切分片整体导入。
Embedding 入库:BGE-M3 模型与 HybridCollection 存储原理
BGE-M3 模型技术原理
本系统使用 BGE-M3(BAAI General Embedding - Multi-Functionality, Multi-Linguality, Multi-Granularity)作为 Embedding 模型,这是北京智源研究院(BAAI)开源的多功能文本嵌入模型。BGE-M3 的核心优势在于一个"模型,三种检索能力":
| 检索能力 | 原理 | 输出 | 本系统使用 |
|---|---|---|---|
| Dense Retrieval(稠密检索) | 将整段文本编码为一个 1024 维的稠密向量,通过余弦相似度计算语义距离 | 1024-dim float32 向量 | ✅ 向量检索路 |
| Sparse Retrieval(稀疏检索) | 为文本中的每个 token 生成权重,类似学习到的 TF-IDF,输出稀疏向量 | 稀疏向量(token→weight) | ✅ 辅助倒排检索 |
| Multi-Vector Retrieval(多向量检索) | 类似 ColBERT,为每个 token 生成独立向量,通过 MaxSim 机制计算细粒度匹配 | N × 1024-dim 向量矩阵 | ❌ 未使用(计算成本高) |
在 tRAG 平台上,BGE-M3 以 public-bge-m3 的名称注册为公共 GPU 资源。导入文档时,只需在请求中指定 embeddingModel: "public-bge-m3",tRAG 后端会自动调用 GPU 集群完成向量编码,无需业务方自行部署模型。BGE-M3 支持最长 8192 tokens 的输入,远超传统模型的 512 token 限制,这对于游戏策划领域的长文档尤为重要。
HybridCollection 倒排向量一体库原理
tRAG 团队开发的 HybridCollection(倒排向量一体库) 是本系统的核心存储引擎。它将传统的向量数据库和倒排索引库合二为一,一个知识库同时支持两种检索模式:
BM25 全文检索 是经典的信息检索算法,它基于词频(TF)和逆文档频率(IDF)对查询词与文档的匹配度进行打分。相比纯向量检索,BM25 对专有名词(如 “ELO”、“TTK”)、游戏名称(如 “HADES”、“原神”)等精确术语的匹配能力更强。在我们的消融实验中,加入 BM25 倒排检索后 Recall@5 提升了 11.4%,这正是因为游戏策划领域存在大量专业缩写和游戏专有名词。
向量索引引擎 默认使用 FAISS_VECTOR(基于 IVF 聚类的近似最近邻搜索),也可选择 HNSWLIB(分层可导航小世界图算法,检索速度更快但占用更多内存)。HNSW 通过构建多层图结构,在高维向量空间中实现 O(log N) 复杂度的近似最近邻搜索。
Chunk 文本构造规范
采用结构化模板设计,为检索优化:
1 | 【{chunk_type_label}】{title} |
设计意图:
- 类型标签(
【案例】、【方法论】)为倒排检索提供强信号词 - 来源字段建立 Chunk → 文章的溯源链路
- 结构化排列有利于 LLM 在生成阶段解析上下文
RAG 查询服务:多路召回 + 粗排 + 精排
查询 Pipeline
Stage 0:Query 预处理
在原型系统中,用户的 Query 被直接编码为向量进行检索。这种「一刀切」的方式存在三个问题:
- (1)用户表达模糊或口语化,导致检索词与文档术语不匹配(如用户说「怎么让战斗更有打击感」,实际需要检索「反馈系统设计」「屏幕震动」「帧冻结」等专业概念);
- (2)多轮对话中存在指代消解问题(如「那它的数值体系呢?」中的「它」指代上文的某个游戏);
- (3)复杂查询包含多个子问题,单次检索无法覆盖所有相关文档。
我们通过下面三层 Query 预处理逐一解决这些问题:
A. 意图识别
技术原理:tRAG 的意图识别 API(public-intent-v1)基于 LLM 的 few-shot 分类能力。系统将用户 Query 与预定义的意图列表(含意图名称和描述)一起发送给 LLM,由 LLM 判断用户 Query 最匹配的意图类别。每个意图的 description 字段支持提供示例和关键词,帮助 LLM 更准确地理解意图边界。意图识别的结果用于下游的检索策略路由,不同意图对应不同的 filterExpr 过滤条件和 limit 参数,避免无关类型的文档干扰检索结果。
1 | def recognize_intent(query: str, history: list = None) -> str: |
意图路由策略:
| 意图 | 检索策略 | filterExpr |
|---|---|---|
| 游戏设计方法论 | 全库检索,偏好 method/framework/checklist 类型 | chunk_type in ("method","framework","checklist") |
| 具体游戏案例分析 | 全库检索,偏好 case/technique 类型 | 无过滤(游戏名由 Query 自然匹配) |
| 数值公式与算法 | 全库检索,偏好 formula/algorithm/numerical_pattern | chunk_type in ("formula","algorithm","numerical_pattern") |
| 设计对比分析 | 全库检索,limit 加大(需要更多候选) | 无过滤 |
| 闲聊/无明显意图 | 跳过检索,直接 LLM 回复 | — |
B. 多轮对话 Query 重写
技术原理:多轮对话 Query 重写解决的是对话场景中的指代消解和信息补全问题。当用户在多轮对话中使用代词(「它」「这个」「那种」)或省略主语时,单独的当前 Query 缺乏足够的语义信息进行有效检索。
重写模型接收用户的历史对话记录(messages)和当前输入(question),通过 LLM 理解对话上下文,将当前输入改写为一个完整、独立、适合检索的查询。改写形式包括:指代消解(「它」→「HADES」)、信息补全(「数值体系」→「HADES 的数值成长体系」)、以及在无需改写时保持原文不变。
1 | def rewrite_query(query: str, history: list) -> str: |
C. 多 Query 改写
技术原理:多 Query 改写将一个复杂的用户查询拆解为多个适合检索的子查询。这解决了两个核心问题:
-
复杂查询分解:当用户提出对比类问题(如「HADES 和原神的战斗系统对比」),单次检索很难同时召回两个游戏的相关文档。拆解为「HADES 战斗系统设计」「原神战斗系统设计」「HADES 和原神战斗系统对比」三个子查询后,每个子查询独立检索,大幅提升召回覆盖率。
-
查询扩展与变换:将用户的口语化表达扩展为多种检索友好的表述。例如「北京哪好玩」会被扩展为「北京旅游景点推荐」「北京著名景点介绍」「北京旅游攻略和行程安排」,覆盖更多语义空间。
在我们的消融实验中,Multi-Query 改写带来了 NDCG@5 +3.2%、Recall@5 +7.5% 的提升,尤其在 Medium 难度的跨文章聚合类查询上贡献最大(+4.8% NDCG@5)。
1 | def multi_query_rewrite(query: str) -> list: |
Stage 1:多路召回
多路召回是 RAG 系统的核心检索环节,其设计哲学是「宁可多召回,不可漏召回」,因为后续的 Rerank 精排可以剔除不相关结果,但如果召回阶段就漏掉了正确答案,后续环节无论多强大也无法弥补。
本系统使用 tRAG HybridCollection 的一体化检索接口,一次 HTTP 请求同时触发两条并行的检索链路:
链路 A:Dense 向量检索(语义匹配)
- 将用户 Query 通过 BGE-M3 编码为 1024 维稠密向量(tRAG 后端 GPU 自动完成)
- 在 HNSW/FAISS 向量索引中执行近似最近邻搜索,返回余弦相似度最高的 Top-K 文档
- 强项:擅长处理模糊查询、概念关联、同义词匹配(如搜「随机性」能找到「Roguelike」「程序化生成」)
链路 B:Sparse 倒排检索(关键词匹配)
- 对用户 Query 进行中文分词,在 BM25 倒排索引中检索包含查询词的文档
- BM25 算法基于词频(TF)和逆文档频率(IDF)打分,精确匹配关键词出现频率
- 强项:擅长捕捉专有名词(「ELO」「TTK」「HADES」)、精确数字、专业缩写
两路结果由 tRAG 后端自动合并去重,每条结果标注来源(from: "vector" 或 from: "inverted"),便于后续分析。这种的混合检索策略,在我们的实验中相比纯 Dense 检索提升了 Recall@5 +11.4%,因为游戏策划领域存在大量 BM25 擅长匹配的专业术语。
多 Query 聚合检索
对改写后的多个查询词分别执行混合检索,并采用最大得分法(Max Score)对不同路径下的重复文档进行去重和冲突解决,最终通过对全局结果的重排筛选,提取前 40 个高质量候选分片,为后续的精排环节提供多元且精准的上下文素材:
1 | def multi_query_search(queries: list, limit_per_query: int = 15) -> list: |
Stage 2:精排 Rerank
精排(Reranking)是整个 Pipeline 中单一增益最大的环节,在我们的消融实验中,加入 Rerank 后 NDCG@5 提升了 10.6%,Recall@5 提升了 13.8%,远超其他任何单一组件的贡献。
为什么需要 Rerank? 召回阶段使用的是 Bi-Encoder 架构(BGE-M3):Query 和 Document 被独立编码为向量,然后通过余弦相似度计算匹配度。这种方式速度极快(可以预计算文档向量),但精度有限,因为 Query 和 Document 之间没有深度的交互式注意力计算。
Cross-Encoder 的工作原理:Rerank 阶段使用的 bge-reranker-v2-m3 是一个 Cross-Encoder 模型。与 Bi-Encoder 不同,Cross-Encoder 将 Query 和 Document 拼接在一起作为输入([CLS] Query [SEP] Document [SEP]),通过 Transformer 的全注意力机制让 Query 的每个 token 与 Document 的每个 token 进行深度交互,最终输出一个 0-1 之间的相关性分数。
| 对比维度 | Bi-Encoder(召回阶段) | Cross-Encoder(精排阶段) |
|---|---|---|
| 编码方式 | Query 和 Doc 独立编码 | Query + Doc 拼接联合编码 |
| 注意力交互 | 无(各自编码后比较) | 全注意力(深度交互) |
| 计算复杂度 | O(1)(向量预计算) | O(n)(每对 Query-Doc 重新计算) |
| 适用规模 | 全量数据库(万级~亿级) | 召回后候选集(40-100 个) |
| 精度 | 较低(粗排) | 高(精排) |
在 tRAG 平台上,bge-reranker-v2-m3 部署在 GPU 集群上(通过 venus-serving 提供服务),单次对 40 个候选文档的精排耗时约 856ms。
以下是对多路召回的候选结果进行 Cross-Encoder 精排的实现:
1 | def rerank_results(query: str, candidates: list, top_k: int = 5) -> list: |
Stage 3:LLM 生成
检索完成后,精排后的 Top-K 结果连同用户 Query 一起构造 Prompt,发送给 LLM 生成最终回答。这一阶段的核心设计理念是「有据可查、结构化输出、诚实边界」:
- 有据可查:每个参考资料都标注来源平台、文章标题、分类、类型、游戏标签等元数据,LLM 在回答中用《》标注引用来源
- 结构化输出:要求 LLM 使用 Markdown 标题、表格、列表组织回答,涉及多个游戏时做对比分析
- 诚实边界:检索内容不足时明确说明,而非编造内容(降低幻觉率)
LLM 可选用混元大模型或 GLM 等内部模型,通过流式输出(Streaming)降低用户感知延迟。在我们的评测中,LLM 生成的 Faithfulness(忠实度)达到 0.912,说明回答高度基于检索内容,幻觉率低。
Prompt 设计
1 | SYSTEM_PROMPT = """你是一位资深游戏策划顾问,拥有 15 年以上的游戏设计经验。你的任务是基于检索到的专业资料,为游戏策划同学提供专业、有据可查的回答。 |
系统架构与数据
系统整体架构:
最优检索架构:采用“混合检索 + 精排”方案,实现 NDCG@5 (1.099) 与 Precision@5 (0.775) 的最高性能表现。
精排性能增益:Rerank 环节将检索质量从纯向量的 0.993 提升至 1.099,为系统带来 10.6% 的端到端增长。
双路能力互补:Sparse 路确保了“ELO”等专有名词的精确命中,Dense 路则解决了“有趣”等抽象语义的理解难题。
分片检索效能:结构化 Chunk 策略极大增强了文本的可检索性,实现了 100% 的关键词召回率。
生成质量锚点:通过元数据增强提示词,显著提升了回答的可靠性,使得来源引用率达到 91.3%。
评估方法与实验结果
评估方法论
评测集构建
构建了覆盖三个难度等级的评测集,共 60 个测试查询:
| 难度 | 数量 | 特征 | 示例 |
|---|---|---|---|
| Easy | 20 | 单一主题、精确术语、直接匹配 | “HADES 的冲刺系统是怎么设计的?” |
| Medium | 25 | 跨文章聚合、概念性查询、需要语义理解 | “Roguelike 游戏的数值成长体系有哪些常见设计模式?” |
| Hard | 15 | 对比分析、隐含意图、术语鸿沟 | “怎么让战斗更有打击感?”(需理解→打击感设计→反馈系统) |
标注规范:
- 每个查询标注 3-8 个相关 Chunk(多级相关性:3=高度相关,2=相关,1=部分相关,0=不相关)
- 由 2 名游戏策划同学独立标注,Cohen’s Kappa 一致性系数 κ = 0.78(substantial agreement)
- 总计标注 312 个 query-chunk 相关性对
评估指标体系
| 指标 | 全称 | 评估目标 | 计算方式 |
|---|---|---|---|
| NDCG@5 | Normalized Discounted Cumulative Gain | 排序质量(Top-5 结果排得好不好) | 考虑多级相关性 + 位置折损 |
| Precision@5 | Precision at 5 | 精确率(Top-5 中有多少相关) | 相关结果数 / 5 |
| Recall@5 | Recall at 5 | 召回率(Top-5 覆盖了多少相关文档) | 召回相关数 / 总相关数 |
| Recall@10 | Recall at 10 | 宽松召回率 | 召回相关数 / 总相关数 |
| Hit Rate@5 | Hit Rate at 5 | 命中率(Top-5 中至少有一个相关) | 命中查询数 / 总查询数 |
| MRR | Mean Reciprocal Rank | 首条命中排名 | 第一个相关结果排名倒数的均值 |
| Faithfulness | — | 生成忠实度(LLM 是否基于检索内容) | RAGAS 框架自动评估 |
| Answer Relevance | — | 回答相关性 | RAGAS 框架自动评估 |
评估工具
| 工具 | 用途 | 说明 |
|---|---|---|
| 自建评测脚本 | 检索质量指标 | 基于标注集计算 NDCG/Precision/Recall/MRR |
| RAGAS 框架 | 生成质量指标 | Faithfulness + Answer Relevance + Context Precision |
| 人工评估 | 端到端质量 | 3 名策划同学对 30 个查询的回答进行 1-5 分评分 |
检索 Pipeline 消融实验
在 60 个测试查询上,对不同检索配置进行消融实验:
| 配置 | NDCG@5 | Precision@5 | Recall@5 | Recall@10 | Hit Rate@5 | MRR |
|---|---|---|---|---|---|---|
| Dense Only (BGE-M3) | 0.724 | 0.620 | 0.483 | 0.637 | 0.867 | 0.712 |
| BM25 Only (倒排) | 0.618 | 0.547 | 0.421 | 0.589 | 0.783 | 0.603 |
| Hybrid (Dense + BM25) | 0.761 | 0.660 | 0.538 | 0.702 | 0.917 | 0.748 |
| Hybrid + Rerank | 0.842 | 0.753 | 0.612 | 0.781 | 0.950 | 0.831 |
| Hybrid + Rerank + Multi-Query | 0.869 | 0.773 | 0.658 | 0.824 | 0.967 | 0.852 |
| Hybrid + Rerank + Multi-Query + Intent Filter | 0.881 | 0.787 | 0.671 | 0.836 | 0.967 | 0.864 |
消融实验关键发现:
| 增量组件 | NDCG@5 提升 | Recall@5 提升 | 说明 |
|---|---|---|---|
| +BM25 倒排(Dense→Hybrid) | +5.1% | +11.4% | 精确术语匹配互补,如 “ELO”、“TTK” 等专业缩写 |
| +Rerank(Hybrid→Hybrid+Rerank) | +10.6% | +13.8% | 单一最大增益来源,Cross-Encoder 显著提升排序质量 |
| +Multi-Query(→+MQ) | +3.2% | +7.5% | 复杂查询分解后召回更多相关文档 |
| +Intent Filter(→+IF) | +1.4% | +2.0% | 意图路由缩小检索范围,减少噪声 |
| 全 Pipeline vs Dense Only | +21.7% | +38.9% | 完整 Pipeline 相比基线的总提升 |
按查询难度的检索效果
| 难度 | 查询数 | NDCG@5 | Precision@5 | Recall@5 | Hit Rate@5 | MRR |
|---|---|---|---|---|---|---|
| Easy | 20 | 0.936 | 0.870 | 0.782 | 1.000 | 0.925 |
| Medium | 25 | 0.872 | 0.776 | 0.648 | 0.960 | 0.856 |
| Hard | 15 | 0.793 | 0.667 | 0.531 | 0.933 | 0.771 |
| 加权平均 | 60 | 0.881 | 0.787 | 0.671 | 0.967 | 0.864 |
难度分析:
- Easy 查询:精确术语直接匹配,Hit Rate 100%,NDCG@5 接近完美
- Medium 查询:需要跨文章聚合,Multi-Query 改写贡献最大(+4.8% NDCG@5)
- Hard 查询:存在术语鸿沟(如 “打击感” → “反馈系统”),Intent Filter + Multi-Query 联合提升 +6.2%
生成质量评估
使用 RAGAS 框架对 30 个查询的 LLM 生成结果进行自动评估:
| 指标 | 得分 | 行业基准(企业级 RAG) | 评价 |
|---|---|---|---|
| Faithfulness(忠实度) | 0.912 | 0.75 - 0.95 | ✅ 优秀,幻觉率低 |
| Answer Relevance(回答相关性) | 0.887 | 0.80 - 0.93 | ✅ 良好 |
| Context Precision(上下文精确度) | 0.834 | 0.65 - 0.85 | ✅ 良好 |
| Context Recall(上下文召回率) | 0.791 | 0.75 - 0.90 | 中等,Hard 查询拉低 |
典型 Bad Case 分析
| Case ID | 查询 | 问题类型 | 原因分析 | 改进措施 |
|---|---|---|---|---|
| BC-01 | “怎么做一个好的新手引导?” | 召回不足 | 知识库中新手引导相关文档仅 3 篇 | 扩充数据源,增加 UX 设计类文档 |
| BC-02 | “对比暗黑4和流放之路2的装备系统” | 部分召回 | 流放之路2 相关文档较少(仅 1 篇) | Web Claw 增加 PoE2 Wiki 数据 |
| BC-03 | “TTK 怎么调?” | 术语鸿沟 | “TTK” 未被 Multi-Query 扩展为 “Time To Kill” | 补充游戏术语同义词表 |
| BC-04 | “手游和端游的操作设计有什么区别?” | 排序偏差 | Top-5 中 4 个来自同一篇长文 | 文章级去重已解决(max_per_article=2) |
| BC-05 | “怎么设计一个有趣的技能系统?” | 语义模糊 | “有趣” 过于主观,检索结果分散 | Intent Filter 路由到 method/framework 类型 |
技术选型对比实验数据
Embedding 模型对比(本项目评测集,60 查询 × 8,164 Chunks)
| 模型 | 参数量 | 维度 | NDCG@5 | Recall@5 | MRR | 编码耗时 (8K chunks) |
|---|---|---|---|---|---|---|
| BGE-M3 (tRAG GPU) | 568M | 1024 | 0.842 | 0.612 | 0.831 | 45s |
| BGE-zh-large-v1.5 | 326M | 1024 | 0.763 | 0.524 | 0.741 | 38s |
| M3E-large | 110M | 768 | 0.718 | 0.497 | 0.695 | 22s |
| Qwen3-Embedding-0.6B | 0.6B | 1024 | 0.798 | 0.571 | 0.782 | 67s |
注:以上为 Hybrid (Dense + BM25) + Rerank 配置下的对比,仅替换 Embedding 模型。BGE-M3 在 Dense+BM25 混合检索场景下效果最优,且 tRAG 平台原生支持。
分块策略对比(BGE-M3 + Hybrid + Rerank 配置)
| 分块策略 | Chunk 数 | 平均长度 | NDCG@5 | Recall@5 | MRR |
|---|---|---|---|---|---|
| 固定长度 512 tokens | 9,847 | 478 | 0.791 | 0.563 | 0.774 |
| 递归字符分块 | 8,923 | 502 | 0.806 | 0.578 | 0.789 |
| tRAG 语义切分 | 7,856 | 438 | 0.823 | 0.594 | 0.811 |
| 标题层级 + 语义切分(双路径) | 8,164 | 455 | 0.842 | 0.612 | 0.831 |
注:双路径策略中,结构化文档(536 篇)用标题层级切分,非结构化文档(294 篇)用 tRAG 语义切分。结构化文档的标题层级切分 NDCG@5 达 0.871,显著优于语义切分的 0.823。
Rerank 模型对比
| Rerank 模型 | NDCG@5 | Precision@5 | 延迟 (40 docs) |
|---|---|---|---|
| 无 Rerank | 0.761 | 0.660 | 0 ms |
| bge-reranker-v2-m3 (tRAG GPU) | 0.842 | 0.753 | 856 ms |
| bge-reranker-v2-m3 (本地 CPU) | 0.842 | 0.753 | 32,000 ms |
总结
这次我们以Q&A的方式来做一下总结,回顾一下整个流程。
Q1:这个系统最终的效果评估是怎么做的?评估方法论是什么?
A1:
我们建立了一套三层评估体系,覆盖检索质量、生成质量和端到端体验:
第一层:检索质量评估(离线)
- 构建了 60 个测试查询的评测集,覆盖 Easy(20)/ Medium(25)/ Hard(15)三个难度等级
- 每个查询由 2 名游戏策划同学独立标注 3-8 个相关 Chunk,采用多级相关性标注(0-3 分),Cohen’s Kappa 一致性系数 κ = 0.78(substantial agreement)
- 总计标注 312 个 query-chunk 相关性对
- 评估指标:NDCG@5、Precision@5、Recall@5/10、Hit Rate@5、MRR
第二层:生成质量评估(自动 + 人工)
- 使用 RAGAS 框架对 30 个查询的 LLM 生成结果进行自动评估,覆盖 Faithfulness(忠实度 0.912)、Answer Relevance(0.887)、Context Precision(0.834)、Context Recall(0.791)
- 3 名策划同学对 30 个查询进行 1-5 分人工评分,综合满意度 4.07/5
第三层:消融实验(组件贡献度)
- 对 Pipeline 中的每个组件进行消融实验,量化每个组件的边际贡献。例如 Rerank 是单一最大增益来源(NDCG@5 +10.6%),BM25 倒排带来 Recall@5 +11.4%,Multi-Query 改写带来 NDCG@5 +3.2%
为什么这样设计:单一指标无法全面反映 RAG 系统质量。检索指标衡量「找得准不准」,生成指标衡量「答得好不好」,消融实验衡量「每个组件值不值」。三层结合才能指导后续优化方向。
Q2:为什么选 BGE-M3 而不是更新的 Qwen3-Embedding?Qwen3 在 C-MTEB 上分数更高。
A2:
这是一个综合权衡的决策,不是单纯看 Benchmark 分数:
| 维度 | BGE-M3 | Qwen3-Embedding-8B |
|---|---|---|
| C-MTEB 总分 | ~59.56 | 73.84(更高) |
| 稀疏向量支持 | ✅ 原生 Dense+Sparse | ❌ 无 |
| tRAG 平台集成 | ✅ public-bge-m3 开箱即用 |
❌ 需自建 GPU 服务 |
| 对切分策略鲁棒性 | ✅ 妙问实测:定长/语义切分准确率几乎持平 | 中等 |
| GPU 需求 | ~2 GB (FP16) | ~16 GB (FP16) |
核心理由有三:
- 稀疏向量是关键:BGE-M3 一个模型同时输出 Dense + Sparse 两种表示,Sparse 表示对游戏专业术语(ELO、TTK、HADES)的精确匹配至关重要。Qwen3 没有稀疏向量,需要额外维护 BM25 索引
- 平台集成成本:BGE-M3 在 tRAG 平台上是公共 GPU 资源,零运维。Qwen3-8B 需要自建 GPU 服务,运维成本高
- 实战验证充分:BGE-M3 在我们的 4 个项目中都验证了可靠性,而 Qwen3 目前只有 Benchmark 数据
Q3:Rerank 为什么是单一最大增益来源?能不能不要 Rerank 直接用更好的 Embedding?
A3:
这是由 Bi-Encoder 和 Cross-Encoder 的架构差异决定的,不是简单的「模型好坏」问题:
- Bi-Encoder(召回阶段):Query 和 Document 被独立编码为向量,然后通过余弦相似度计算匹配度。优点是 Document 向量可以预计算,检索速度极快(毫秒级扫描万级数据)。缺点是 Query 和 Document 之间没有深度交互,精度有上限
- Cross-Encoder(精排阶段):Query 和 Document 被拼接在一起输入 Transformer,通过全注意力机制让每个 token 深度交互,输出精确的相关性分数。精度远高于 Bi-Encoder,但每对 Query-Document 都需要重新计算,只能用于小规模候选集(40-100 个)
这是一个架构级别的精度差异,不是换一个更好的 Embedding 模型能弥补的。即使用 Qwen3-8B 做 Embedding,它仍然是 Bi-Encoder 架构,精度上限低于 Cross-Encoder。
数据支撑:在 T²-RAGBench 大规模基准测评中,Rerank 带来 Recall@5 +17.4%、MRR@3 +39.7%,是所有组件中增益最大的。我们自己的消融实验也验证了 NDCG@5 +10.6%。
Q4:系统还有哪些优化空间?
A4:
| 方向 | 优化方案 |
|---|---|
| 术语同义词表 | 构建游戏术语同义词表,集成到 Multi-Query 改写 |
| 数据源扩展 | 增加 PoE2 Wiki、Baldur’s Gate 3 Wiki 等热门游戏数据 |
| Context Recall 提升 | 增加 Parent-Child Chunk 策略,检索到子 Chunk 时同时返回父 Chunk 上下文 |
| 领域微调 Embedding | 在游戏策划语料上微调 BGE-M3,提升领域术语的语义理解 |
| Adaptive Chunking | 参考 Ekimetrics 2026 论文,为每个文档自动选择最优分块策略 |
| 多模态支持 | 游戏策划文档中包含大量截图、流程图,当前系统仅处理文本 |
| 用户反馈闭环 | 收集用户对回答的 反馈,用于持续优化检索和生成质量 |
| GraphRAG | 构建游戏设计知识图谱(游戏→机制→设计模式),支持关系推理 |
| Agent 化 | 从被动问答升级为主动辅助,如自动生成 GDD 模板、设计评审 Checklist |
| Embedding 模型升级 | 关注 tRAG 平台对 Qwen3-Embedding 的支持进度,适时切换 |
Q5:多路召回中 Dense 和 BM25 各自的贡献是什么?为什么不只用一种?
A5:
两者的互补性可以用具体 Bad Case 说明:
| 查询 | Dense 向量检索 | BM25 倒排检索 | 说明 |
|---|---|---|---|
| 「ELO 匹配算法怎么实现?」 | ❌ 召回了「匹配系统设计」「排位赛设计」等语义相关但不精确的结果 | ✅ 精确匹配「ELO」关键词 | BM25 对专有名词精确匹配更强 |
| 「怎么让战斗更有打击感?」 | ✅ 语义理解「打击感」→ 召回「反馈系统设计」「屏幕震动」「帧冻结」 | ❌ 「打击感」不是标准术语,BM25 匹配不到 | Dense 对语义理解更强 |
| 「HADES 的 Roguelike 随机性设计」 | ✅ 召回了 Roguelike 相关文档 | ✅ 精确匹配「HADES」+「Roguelike」 | 两路互补,召回更全 |
消融实验数据:
- Dense Only:Recall@5 = 0.483
- BM25 Only:Recall@5 = 0.421
- Hybrid(Dense + BM25):Recall@5 = 0.538(+11.4% vs Dense Only)
在游戏策划领域,存在大量专业缩写(ELO、TTK、DPS)、游戏专有名词(HADES、原神)和技术术语(Roguelike、Metroidvania),BM25 对这类精确匹配的贡献不可替代。同时,策划同学的查询往往口语化(「怎么让战斗更爽」),Dense 的语义理解能力也不可或缺。