你大概已经装好了 ollama,也拉下来一个能聊天的模型,可真要接上自己的资料做问答,问题就冒出来了:切片多长、向量用哪个模型、检索回来的段落怎么塞进提示词、跑起来慢得离谱又该从哪查。这篇不重复协议和原理,只给一条能落地的顺序:先让检索单独跑通,再把生成接上,最后补超时、并发、日志和一套小评测。
你大概已经装好了 ollama,也拉下来一个能聊天的模型,可真要接上自己的资料做问答,问题就冒出来了:切片多长、向量用哪个模型、检索回来的段落怎么塞进提示词、跑起来慢得离谱又该从哪查。这篇不重复协议和原理,只给一条能落地的顺序:先让检索单独跑通,再把生成接上,最后补超时、并发、日志和一套小评测。
整条链路的验收标准可以压成一句话:给你一个明确知道答案在哪个文件里的问题,系统能先把那句话找出来,再照着它把答案说对。做不到就按下面的顺序逐段排查,别一上来就全链路调参。
先把链路拆成两段:检索一段、生成一段
检索段只做三件事:读文档、切片、算向量并存进本地向量库,对外只暴露一个接口——给一个问题返回若干候选段落。生成段只吃「问题 + 候选段落」吐答案。两段之间用文件或函数边界隔开,别一开始就串成一条流水线。分开的最大好处是排错有落点:答得烂时能立刻判断是没检索到,还是检索到了但模型没用好。前者调切片和向量模型,后者调提示词,方向完全不同。
- 检索段:只负责读文档、切片、算向量入本地向量库,产出「问题进、候选段落出」一个接口
- 生成段:只吃「问题加候选段落」,吐答案,别的什么都不管
- 边界形式:两段之间用文件或独立函数隔开,方便单独调用、单独看输出
- 验收方式:拿三个你明确知道答案在哪份文件里的问题去查,看候选段落里有没有那一句
切片从一个固定长度起步就够了,按段落或标题切比按字数硬切好,中文场景下的切片长度和重叠比例随文档类型变,先用一批真实文档各跑一遍看召回效果再定。判断召回好坏不看分数,只看一件事:你期望的那段文字有没有出现在候选里。
把检索结果接进生成,提示词按「只能用给定材料」写
提示词骨架固定成三段:角色和约束、检索到的材料(每段带来源编号)、用户问题。约束里明确写「材料里没有就说不知道,不要编」,并要求模型在答案里标出引用的是第几段材料。材料不要全塞,按相似度取前若干条,超出就截断;上下文塞得越满,首字越慢,也越容易被无关内容带偏。能塞多少受模型上下文长度限制,跑之前先估一遍单次请求的输入规模。
- 来源编号
- 给每段材料编个号,让模型在答案里标出引用的是哪几段,方便人工核对
- 取前若干条
- 按相似度排序后只取头部,条数太多会拖慢首字并引入噪声
- 温度
- 调低一些答案更贴材料,留高容易出现同一批材料两次答案对不上
- 输入规模
- 材料加问题的总长度,先估算再决定每次取几条材料
ollama 的调用走本地 HTTP 接口,把请求体里的温度调低能让答案更贴材料。答案里加来源编号是后面做评测的基础:人工核对时能一眼看出这句话是从哪段材料推出来的,出错了也能快速定位是检索还是生成的问题。
跑得慢、并发一高就卡:先把运行时护栏补上
| 环节 | 常见状况 | 建议处理 |
|---|---|---|
| 检索 | 向量库查询超时 | 单独设检索超时,超时就走降级分支 |
| 生成 | 长答案被全局超时误杀 | 按「多久没吐新内容」设流式超时,不用总时长 |
| 并发 | 请求一多每个都变慢 | 给推理侧设最大并发上限,超出就排队或返回忙 |
| 服务重启 | 模型重新加载,首次请求特别慢 | 当成正常冷启动,别记成故障告警 |
- 拆超时检索和生成各设一个超时,别用一个全局超时盖住整条链路;生成是流式返回的话,按「多久没吐新内容」判断,而不是按整次请求总时长,不然长答案会被误杀
- 限并发本地模型吃显存,并发数不是越大越快。超过显存或算力上限后队列会让每个请求都变慢,所以给推理侧设一个最大并发上限,多的请求排队或直接返回忙
- 加降级向量库查不到、模型超时或推理进程挂了时,返回「暂时取不到资料」的明确提示,而不是把堆栈抛给前端;本地服务重启后模型要重新加载,第一次请求慢是正常的
- 打日志每次请求记录:检索到几段、检索耗时、生成耗时、命中了哪些材料编号。没有这几个字段,慢和烂都无从复盘
别靠感觉:攒一套一次性小评测再改参数
凑二十到五十条「问题 + 唯一正确答案 + 答案出自哪个文件」的对照表,覆盖三类:答案明写在文档里的、要跨两段拼起来的、文档里根本没有的。第三类专门用来验模型会不会硬编。每次改切片长度、换向量模型、改提示词之后重跑这一套,只看三个数:正确率、乱编率、平均响应时间。三项一起看,避免为了提正确率把响应时间拖到不可用。
- 明写题:答案在单个文档段落里,用来验基础召回
- 拼接题:答案要跨两段拼,用来验检索是否覆盖完整信息
- 无答案题:文档里根本没有,用来验模型会不会硬编
- 改参数后重跑:切片、向量模型、提示词每变一次就重跑一次
评测集要小而稳,别每次换题;题目一换,前后两次数值就不可比了,参数到底是改好了还是改坏了说不清。这套东西的定位是回归测试,不是发论文,它只能告诉你这次改动没把原来对的弄坏,不保证线上就一定好,真实用户的问题分布永远比你的题集脏。
下一步想知道本地模型和常见向量模型的搭配效果、以及不同中转方案的接入方式,可以到站内工具目录和价格追踪页对照当时的数字,再决定要不要把部分推理换成云端。→常见问题
ollama 里选哪个模型做 RAG 生成,选哪个算向量?
生成模型和向量模型是两件事,别用一个模型全干。生成侧优先挑指令跟随稳、上下文够长的;向量侧单独挑一个专门做嵌入的模型。两者在 ollama 里是分开拉取和调用的。具体哪些模型适合,去站内嵌入模型页和模型库看当期清单,别照抄别人的组合。
检索明明找到了正确段落,模型还是答错,怎么办?
先看材料是怎么塞的:段落之间有没有加分隔和编号,问题有没有放在材料后面。再确认约束写没写「只能依据材料回答」。最后把温度调低重跑。如果材料对、约束齐、温度低还是错,多半是模型本身对这段内容不熟,换生成模型或缩短输入材料再试。
本地跑起来特别慢,第一反应该查哪里?
按顺序查:模型是否完整加载进显存(没吃满显存会走 CPU,慢一个量级)、切片数量是不是过多导致向量检索本身耗时、单次塞进生成的材料是不是太长、有没有并发请求在抢资源。到站内接口测速页量一下本地接口的延迟基线,有基线才知道慢是模型问题还是链路问题。