专题 · Deep Dive

全部专题

从 0 到 1 做一个无人机智能问答助手

把散在说明书、操作手册、故障处理和业务规范里的知识,变成一个能直接问、答案还能查到是哪份文档第几章的知识入口——先解决「知识从哪里来」,后面的业务查询和 Copilot 用的都是这一层。

给要在企业文档堆上做 RAG 问答的工程同学:不止讲三层怎么分,每一层都落到具体组件与参数——解析用什么、切到多长、向量多少维、召回几条、阈值怎么定。这套口径是通用的,换掉「无人机」三个字,任何企业知识库都能照着落地。

先记住这三样

一句话

问一句能答,答了能翻回原文哪一章。

一条链
  1. 1系统齐了,答疑没人接
  2. 2一线问的是场景,搜不出来
  3. 3所以先做知识入口

一张导图

系统齐了,答疑没人接一线问的是场景,搜不出来所以先做知识入口背景文档怎么变成能搜的块怎么搜对,又不多引中间件凭什么信这个答案问题说现场的话也能问出答案每条答案说得出在哪份文档第几章每次改版能分数比出来目标01 为什么做方案架构实现02 怎么做文档规模提问量与延迟成本与改版结果难点在切分,同库优于多库出处比答案更重要,阈值只能自己标先建评测,再谈调优沉淀文档谁维护、多久改版一次,一个问题要不要跨两份文档才答得全答错了谁负责,检索不到时你希望它闭嘴还是猜有没有 200 道真实题能量一遍反思03 做成什么从 0 到 1 做一个无人机智能问答助手
01为什么做

背景

平台先解决的是「能不能飞」。等真跑起来,卡点变成另一件事:一线不知道该怎么办。这一期的起点不是选什么技术,是答疑一天被打断几十次。

  1. 1

    系统齐了,答疑没人接

    设备、航线、工单、巡检记录都在系统里。能做的事都有,出问题的是「这种情况该怎么办」这句话没人答得上——机型手册、操作规范、故障处理、业务规范分别躺在网盘、群文件和纸质扫描件里,同一个故障有两份版本不一致的处置说明。

  2. 2

    一线问的是场景,搜不出来

    「失联以后应该怎么处理」这句话在文档里没有原文对应,靠人翻目录、靠熟手指路。答疑集中在少数几个熟手身上,一天被打断几十次;更麻烦的是回答没有出处,同一个人今天一个说法明天一个说法,出了事没人能回查当时到底答了什么。

  3. 3

    所以先做知识入口

    让 AI 替人操作平台之前,先解决「问一句能答、答了能翻回原文哪一章」。这一层不稳,后面每一步都不稳。

问题

「文档多、检索难」不叫问题。拆开是三件事,每件事都有自己的出错方式;04 架构里那几层,就是照着这三件事摆的。

  1. 1

    文档怎么变成能搜的块

    同一份内容有三种载体(Word / PDF / 扫描件)。PDF 还带目录页与页眉页脚,直接按页抽文本会把「保密声明」当成正文喂给模型。按字数一刀切又会把「前置条件」和「操作步骤」切成两块——答案少了前面那句限定,读起来照样通顺,照着做会炸机。

  2. 2

    怎么搜对,又不多引中间件

    纯关键词搜不到同义说法(「失联」对「链路中断」);纯向量搜不到型号、编号、代码这类必须精确命中的串。而向量、原文、元数据分开存,就得额外维护它们一致:每多引一个中间件,就多一套权限、备份、升级和对账。

  3. 3

    凭什么信这个答案

    答案没有出处,没人敢照着它去动设备——所以出处不是加分项,是这条链路能不能上生产的门槛。手里没有一批真实问题,也说不清这次改动是变好了还是碰巧对上了,调优最后就变成改改看。

目标

三条,按顺序来:先让一线问得出答案,再让他们信这个答案,最后让我们自己改得动。

  1. 1

    说现场的话也能问出答案

    一线说的是机器在什么情况下报什么错,不是文档标题。要把这句大白话搜成对的内容,不能要求提问的人先搞懂文档是怎么分类的。

  2. 2

    每条答案说得出在哪份文档第几章

    找不着依据就直接说找不着,别让模型编一段看着像的话。能指出哪份文档第几章,一线才敢照着做。

  3. 3

    每次改版能分数比出来

    先攒一批真实问题当考卷。每次改完再考一遍,才知道是变好了还是变坏了。没有这张考卷,全靠感觉。

02怎么做

方案

一条链:一个问题怎么变成带出处的答案一次真实提问:「无人机失联以后应该怎么处理?」

走一遍最能代表系统价值的路径。这条顺序同时也是排查效果问题的检查顺序——答案不对,就沿它往回找。

第 1 / 6 步
知识层上线前,说明书、操作手册、故障处理、业务规范先解析、按章节与语义切分、生成向量,并挂上型号、版本、章节。

架构

知识层

解析 · 切分 · Embedding构建
一句话

把分散文档变成可检索的知识:解析、切分、向量化,切的时候就把元数据带上。

30 秒 · 为什么这么设计

切分不按字数砍,按标题、章节、段落和语义切,才保得住「这段属于哪台设备的哪一步」。设备型号、文档版本、章节这些元数据必须在入库时就挂上,否则检索层想按机型过滤时无从下手。

常见追问

为什么不把整本手册直接塞进上下文?

上下文有限,越长越贵、越容易注意力稀释;一份手册里跟本次问题真正相关的往往只有几段。先检索再生成,才扛得住文档量。

手册改版了怎么办?

版本作为元数据跟着片段入库,检索时按版本过滤;改版按文档粒度增量重索引,老版本标失效不物理删除。这也是知识治理要加强的第一项:型号、版本、业务分类管不住,召回就会拿到过期说法。

为什么不在提问时对扫描件做 OCR?

OCR 是文档属性,不是问题属性——同一页每次问都重转一遍,白付延迟和成本。离线转写成 Markdown 还能人工校对,图片不会自己变清晰,但文本可以一直复用。

它拒绝什么、什么时候会出错

不改写业务口径原始说明书、手册、业务规范保持原样,知识层只做解析、切分和索引,不在系统里产生第二套口径。
不做无依据的回答召回内容达不到相关性要求就明确拒答,不靠模型的通用知识补全。在设备运维场景里,看起来对但没有出处的答案比不答更危险。
不一步到位做执行这一期只解决知识问题。业务查询、Copilot、业务执行按 RAG → Agent → Tool 的顺序往后长,不在这一层抢跑。
不只靠向量向量、关键词、元数据三路一起用,任何单独一路都会在真实业务问题上翻车;合池按名次融合,截断之前还要过一次 Rerank。
不只看最终答案评测按链路逐段看,只改被定位到的那一段;跳过定位直接改 Prompt,等于把问题换个地方藏起来。
不为检索单独引中间件一个 Postgres 接得住向量、全文、元数据三件事。Elasticsearch / Milvus 不是不好,是要等到千万级 Chunk 或多租户隔离才划算——没到那条线就引入,只是把一致性问题从库内搬到库间。

实现

技术选型

每一格都给实名组件与具体参数。口径是通用的:换掉「无人机」三个字,任何一套企业文档知识库都能照着抄。

解析与入库

Word / PPT / 混合TikaDocumentReader(Apache Tika):一种 reader 覆盖几十种格式,不为每种格式引库
PDF(有目录)ParagraphPdfDocumentReader 按 PDF 目录抽章节段落——按页抽会把一步操作切成两半
PDF(无目录)PagePdfDocumentReader(PDFBox)页级兜底
Markdown / HTMLMarkdownDocumentReader 保留标题层级;JsoupDocumentReader 走 CSS 选择器
扫描件与图片多模态模型离线转写为 Markdown;复杂版式(跨页大表、公式)成规模再挂 MinerU 服务,Java 侧只调 HTTP
表格转 Markdown 表并保留表题与所在章节,整表作为一个 Chunk,不拉平成一段话

切分参数

第一刀按标题层级切成语义块(章节是天然语义单位)
第二刀超过 800 token 的块用 TokenTextSplitter 二次切:chunkSize 800 tokens、minChunkSizeChars 350、按标点边界、不重叠(Spring AI 默认档)
不拆的东西表格、步骤 + 前置条件、参数对照清单
上下文补偿SummaryMetadataEnricher 生成上一节 / 下一节摘要进元数据
每条 Chunk 元数据文档 ID · 标题路径 · 章节号 · 页码 · 设备型号 · 文档版本 · 业务类型

向量化与存储

Embedding阿里云百炼 text-embedding-v4,1024 维(默认档),单条上限 8192 token——装得下一个完整章节
为什么不用长上下文那档qwen3.7-text-embedding 支持 131k 上下文,但块只有 800 token 时用不上,多付的成本没有收益
向量库Postgres + pgvector,vector(1024) + HNSW;Java 侧用 Spring AI 的 PgVectorStore
全文检索同库 tsvector + GIN + ts_rank,中文分词装 pg_jieba 或 zhparser——不额外引入 Elasticsearch
体量边界HNSW 千万级以内稳定(约 1000 万行是可靠线,5000 万以上才需要换架构);索引维度实际上限约 2000,我们用 1024
运维档位建索引前 maintenance_work_mem 临时 8–16GB、建完改回;内存紧张上 halfvec 量化,索引与 RAM 减半、精度约留 99%
为什么不选 Milvus向量和业务元数据同库同表,一条 SQL 就能做「机型/版本过滤 + 向量近邻 + 全文匹配 + RRF」;选 Milvus 就要双写、对账、两套权限和备份,而它的分布式、GPU 索引、十亿级召回我们一条都用不上。触发迁移的信号:Chunk 破千万、写入并发拖垮 HNSW 重建、需要按租户做向量隔离——检索已封在 VectorStore 接口后,到时只换适配器

检索与重排

三路召回向量 top 20 + 全文 top 20 + 元数据硬过滤(机型 / 版本 / 业务类型)
合池RRF 按名次融合,避开多路分数不可比,取前 15
重排qwen3-rerank(单次 ≤ 500 篇、每篇 4000 token);备选 gte-rerank-v2
进上下文top 3–5 段,宁少勿滥
拒答阈值用 rerank 分档 + 测试集标定,不用绝对相似度——换模型或改版手册分数会整体漂移,换模型必须重标

生成与服务

编排框架Spring AI Alibaba:解析 → 切分 → 向量化 → 入库 → 检索 → 重排 → 生成全链路都在 Spring 生态内,不为 RAG 单开 Python 服务
对话模型qwen-plus 做日常问答、qwen-max 做复杂处置归纳,DeepSeek 可切换;只依赖「稳定输出、上下文变长后不退化」两条契约
提示词结构三段固定:角色 · 带出处的检索片段 · 硬约束(无依据即声明并指出该查哪份文档)
服务形态问答服务是平台内的一个 Spring Boot 模块,文档治理走管理端上传,不建独立中台——知识库的 owner 是业务方不是算法岗
出处展示答案下方列文档名 + 章节 + 页码,点开回原文,这是拒答之外的第二道信任机制

会踩的坑

这些坑跟业务无关,换任何一套企业文档问答都会原样遇到。顺序照着链路走:文档解析 → 切成块 → 入库 → 定阈值 → 文档改版 → 调优。

  1. 1

    PDF 按页抽,页眉页脚混进正文

    最常见的第一坑。按页抽取会把一步操作从中间截断,而每页重复的页眉(机型名)和页脚(保密声明)会被当成正文向量化——于是「保密」两个字出现在几百个 Chunk 里,谁都能命中,谁都不该命中。

    怎么改的有目录的 PDF 一律按目录抽段落;入库前按「跨页重复出现的短行」识别并剥离页眉页脚;表格单独抽块并打表标签。

  2. 2

    扫描件被当成空文档,却看不出来

    图片型 PDF 用文本抽取器跑完,一页只出几个字符,但流程不报错——向量库里看起来「这份文档已入库」,实际是空的。用户问不到答案时,你以为是没召回,其实是根本没内容。

    怎么改的入库时按页统计可提取字符数,低于阈值判定为图片页并生成待转写清单;把「空内容率」做成入库报告的第一行。

  3. 3

    切分只看长度,不看结构

    固定 500 字一刀切,最稳定的翻车方式是「前置条件被切到上一块」:答案里少了那句「仅限带 RTK 模块的机型」,读起来完全可信,实际会炸机。

    怎么改的结构优先、长度兜底;表格与步骤整块不拆;用相邻节摘要补上下文;把「限定条件」类字段进元数据,让过滤而不是模型去守。

  4. 4

    元数据没填就入库

    脏元数据比缺内容更难查:向量能命中,过滤却把它筛掉了,或者反过来把别的机型带进来。用户只看到「答非所问」,看不到是标注问题。

    怎么改的入库即校验必填元数据,缺项的 Chunk 进治理队列不入库;上线前抽查 50 条 Chunk 的型号与版本对不对得上原文。

  5. 5

    把向量相似度当置信度写死

    阈值定在 0.82 那天很准,换了 embedding 模型、或者手册改版重新切分之后,分数区间整体平移——要么全线拒答,要么全线放行,而且没人知道是哪天变的。

    怎么改的阈值挂在 rerank 之后的分档上,用测试集标定;换模型或改切分策略时把「重标阈值」写进变更清单,不做就视为未回归。

  6. 6

    改版文档不重索引

    手册出了 V3,向量库里 V2 还在,而且 V2 的措辞往往更「干净」,召回排名更高。用户拿到的是过期处置步骤,出处链接点进去还是老 PDF——看起来完全自洽。

    怎么改的版本进元数据、检索默认当前版本;文档改版按文档粒度增量重建并标记旧版本失效;出处带版本号,让过期在答案里可见。

  7. 7

    跳过定位直接调 Prompt

    答不准就去改提示词,改完那三个问题确实对了——这是最省事的错觉,代价是另外三百个问题在你没看的地方退化了,而且没有回归集就发现不了。

    怎么改的先建测试集再动手;沿 问题→召回→排序→上下文→答案 逐段定位,只改被指到的那一段;每轮改动跑全量回归。

  8. 8

    没有拒答分支就上线

    第一次遇到编造答案的用户,之后每次结果都不会再核对出处——信任是一次性资产。而拒答率过高本身也是信号:说明知识库缺料,不是模型保守。

    怎么改的拒答话术和出处展示先于功能上线;把拒答率当健康指标盯,超线就回到知识治理而不是调模型。

03做成什么

结果

按一家 500 人规模公司的产品线文档估出来的参考基线——用来做容量规划、预期管理和「该配多大机器」的判断。

这些是推算值,不是实测值。上线前用 200–500 条真实问题量一遍,把这张表换成实测;换模型、换分块参数都要重量一遍。人力与周期:一个后端 + 一个业务方兼职文档治理,第一期(解析入库 + 混合检索 + 出处展示)3–4 周到内部可用。

文档规模约 600 份 / 3–5 万页:20 款机型 × 4 类手册 ≈ 80、平台操作手册 30、故障与工单 FAQ 300、业务规范与法规 100、培训材料 100。切成 20–40 万条 chunk(每份平均 300–800 块),1024 维原始向量约 1.6GB,halfvec 后约 0.8GB——离 pgvector 的千万级可靠线还差一个数量级
提问量与延迟100–200 人(运维、售后、巡检),日均 300–800 问,峰值 QPS 远小于 1;检索(向量 + 全文 + RRF)< 100ms,rerank 100–300ms,生成 1–3s,端到端 2–4s
成本与改版开销几乎全在生成端。按日均 800 问 × 约 3k token 估,检索与重排的单次成本低一个量级——所以省钱先想「少塞上下文」,不是换向量库。每周 10–30 份改版,按文档粒度增量重建,不做全量重跑

及格线

Top-5 召回命中 ≥ 90%测试集里正确片段进过前 5 的比例。不达标先查切分与元数据过滤,别去调提示词——片段没进候选,模型再强也编不出来。
答案可用率 ≥ 80%答案带得出处、业务方判定「能照着做」,而且点开的章节必须真的含答案(出处点击有效率 100%)——有一条失效就先修文档 ID 与章节锚点,出处错一次前面全白做。不达标多半是 chunk 丢了前置条件,回到 02 的切分问题。
拒答率 < 15%过高说明阈值定死或召回太窄;过低说明该拒的没拒。用 rerank 分档重标,不要靠放开阈值凑数。

沉淀

这一期真正带得走的不是「RAG」这个词,是下面这三条判断。下次做任何知识库,它们都会再用到一次。

  1. 1

    难点在切分,同库优于多库

    同一台大模型,切分质量决定上限:调提示词之前,先把块的结构、边界和元数据修对,收益大得多也稳得多。向量、全文、元数据放在同一个 Postgres 里,一条 SQL 就能组合召回;每多引一个中间件,都是要还的运维债。

  2. 2

    出处比答案更重要,阈值只能自己标

    能追溯才有人敢照着操作——出处机制是拒答之外的第二道信任防线,不是锦上添花的展示。别人给的相似度门槛,换个模型、换批语料就失效,必须用自己的题集标定,换模型即重标。

  3. 3

    先建评测,再谈调优

    没有 200 道题,所有「感觉变好了」都是噪声,也挡不住改版回退。评测集是这套系统真正的护城河。

反思

以后再设计知识库,我先问这三个问题。

  1. 1

    文档谁维护、多久改版一次,一个问题要不要跨两份文档才答得全

    决定要不要重索引机制,也决定切分粒度。

  2. 2

    答错了谁负责,检索不到时你希望它闭嘴还是猜

    决定出处、拒答和阈值是不是硬要求。

  3. 3

    有没有 200 道真实题能量一遍

    决定能不能上线。

你大概率会问

RAG、Agent、Tool 分别解决什么问题?

RAG 找知识,Agent 做决策,Tool 调业务。前者回答「失联以后怎么处理」,中者判断「先查这台设备的状态」,后者真正调用设备查询接口拿到电量、在线状态和任务状态。

这个助手和无人机平台是什么关系?

不是独立的聊天机器人,而是建立在平台之上的智能入口。前期解决知识问题,之后把设备状态、任务信息、机场信息接进来,再靠 Agent 和 Tool Calling 让 AI 从回答走向调用平台能力——演进路线是 知识问答 → 业务查询 → Copilot → 业务执行。

如果重新设计,先优化什么?

不继续堆模型,按三个方向走:知识治理(版本、型号、业务分类这些元数据管住)、检索质量(混合检索、Rerank、问题拆解、上下文管理)、业务融合(把知识能力和 Agent、Tool 接起来,从回答问题走向帮用户完成任务)。

这个项目最大的价值是什么?

把分散在说明书、操作手册、业务文档和人员经验里的知识,变成自然语言可以直接访问的入口:以前是人找资料,现在是人问问题、系统找知识。同时它给后面的 Copilot 打了底——知识这一层站住了,业务查询和执行才有人接。

这套做法换个业务还能用吗?

能,换的只是文档主题和元数据字段。链路与参数(结构优先切分、800 token 兜底、三路召回 + RRF + Rerank、阈值靠测试集标定、按文档粒度增量重索引)是通用的;把「设备型号」换成「产品线」「部门」,其余照抄。

最小可跑通版本要多小?

一个 Postgres(pgvector + 中文分词)、一个 Embedding 模型、一个 rerank、一个对话模型,加上 200 条测试集就能跑通并量化。先跑通再谈架构:没有测试集之前,任何架构讨论都是空转。