一个 1.1 GB 的搜索小模型:只查一次,只引用原文,找不到就说找不到
有人把 LFM3-1.7B 微调成了一个专职搜索子模型:拿到问题只调一次 web_search,答案必须能从结果里逐字摘出来,否则直接回一句“搜索结果里没有”。在 131 道题上,它把编造答案的比例压到了 0。
有人在 r/LocalLLaMA 上放了个微调模型,名字叫 Obsessive-1.7B,GGUF 版本 1.1 GB。基座是 LFM3-1.7B,只训练一件事:拿到一个事实性问题,调用一次 web_search,然后返回三行东西,答案、逐字引用、来源 URL。结果里没有,就回一句 “Not found in the search results.”
它被设计成跑在更大模型下面的子 agent,不做聊天。作者自己说,基座 LFM 在工具调用和信息抽取上的表现让他有点意外。
输出长这样:
Answer: Barbara Liskov
Evidence: "Liskov ... the second woman to receive the Turing Award."
Source: https://en.wikipedia.org/wiki/Barbara_Liskov

固定结果集上的成绩
测试集是 131 道留出的 SimpleQA 问题,其中 29 道被故意从搜索结果里删掉了答案。
| 基座 | Obsessive | |
|---|---|---|
| 答案在结果里时能找到 | 50% | 94% |
| 答案不在时说“没找到” | 0% | 100% |
| 编造答案 | 10% | 0% |
| 中位耗时(4060 笔记本) | 5.1 秒 | 2.0 秒 |
“答案不在时不说假话”这项从 0 到 100,是这个小模型真正的卖点。小参数量的模型一旦找不到东西,通常会用预训练权重里的记忆硬凑一个答案出来,这在流水线里比报错更难查。
换成真实维基搜索,胜负变了
作者又用维基百科的搜索 API 测了一轮,120 道题加 40 个需要多个事实的请求。这个后端它训练时没见过。
| 基座 | Obsessive | |
|---|---|---|
| 有回复 | 38% | 100% |
| 回复里有正确答案 | 37/120 | 24/120 |
| 多事实请求全部答对 | 1/40 | 40/40 |
| 编造事实值 | 4 of 4 | 3 of 52 |
单看原始正确率,基座反而更高。原因是它不死心,会一直搜、写很长的回复,答案出现的机会自然更多。但 62% 的情况下它把轮次耗光,什么都没返回。Obsessive 只搜一次,只说自己能逐字引用的内容。
这个取舍划不划算,取决于你的流程能不能容忍“空手而归”。对需要把结果塞进下游模型的场景,一次干净的空返回往往比一段似是而非的长文本好用。
已知问题
作者列得挺坦诚:
- 一次对话只能问一个问题,多轮会把它搞晕。训练时只有单轮,笔记本显存也有限。
- 会把“某人声称自己解决了 Y”报成“是”。
- 大约十分之一的题,答案明明在结果里,它却说没找到。
- 有时会引到隔壁的事实,比如引成了另一年的获奖者。只支持英文。
训练细节:LoRA rank 16,约 9k 条工具调用对话,全程在一块 RTX 4060 笔记本上跑。搜索语料来自维基百科和 FineWeb 页面,每条答案和引用都校验过是否逐字出现,大约四分之一的数据专门教它说“没找到”。作者提到数据准备阶段还用了本地的 qwen 3.8 flash 帮忙出题。
怎么跑
llama-server -hf banyohavlusu23/Obsessive-1.7B-GGUF --jinja -c 16384
温度设 0。仓库里有 Pi、OpenCode、Hermes 的配置和一份不需要 API key 的 Python 脚本。模型页:https://huggingface.co/banyohavlusu23/Obsessive-1.7B-GGUF (原帖链接一开始是坏的,作者后来在回复里更正了)。许可证沿用基座的 LFM Open License。
搜索这块,作者自己搭了个本地引擎做训练数据,SQLite 全文检索加 BM25 排序,返回结果做成常见搜索 API 的样子,标题、URL、摘要。这样数据免费且可复现。实际使用时它调用你框架里现成的 web_search:仓库里的 research.py 支持维基百科(免 key)、SearXNG 和 Brave,在 Pi 里他用的是 pi-web-access 加 Brave。他补了一句,摘要给得越长,回答质量越好。
跟帖里两个值得记的点
有人问它测没测过提示注入,也就是模型把搜索结果当成指令执行,而不是当成数据。作者说没有,这一版没做。他解释,训练只奖励能从结果里逐字引用出来的答案,而且这个模型除了搜索没有别的工具,最坏情况大概是“配着真实引用的错误答案”,而不是真的去执行动作。提问的人不太认同,认为最坏情况是它把一条指令当成结果返回给上层 agent。
另一个建议更实用:别让这个 1.7B 模型自己纠结查询词。让上层的 router 并行发两三条改写过的查询,小模型只负责在合并后的片段里做落地抽取。作者说这是他的第一次微调实验,基本靠感觉训的,会试试这个思路。
还有人用 MiniCPM5-2B 做同样的事,全程跑在内存和 CPU 上,显存留给大模型,能开 3 个 32K 上下文的并行实例。作者在下面回了一句,关掉 reasoning、温度设 0,差别大得很。
有条评论说得挺准:一个 1.7B 的模型能在缺答案时做到 100% 弃答,这事不常见,因为小模型几乎总会从预训练权重里捞个兜底答案出来。
发布时间: 2026-11-07 20:13