Wink Pings

一个 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

Obsessive-1.7B 示例输出

固定结果集上的成绩

测试集是 131 道留出的 SimpleQA 问题,其中 29 道被故意从搜索结果里删掉了答案。

基座Obsessive
答案在结果里时能找到50%94%
答案不在时说“没找到”0%100%
编造答案10%0%
中位耗时(4060 笔记本)5.1 秒2.0 秒

“答案不在时不说假话”这项从 0 到 100,是这个小模型真正的卖点。小参数量的模型一旦找不到东西,通常会用预训练权重里的记忆硬凑一个答案出来,这在流水线里比报错更难查。

换成真实维基搜索,胜负变了

作者又用维基百科的搜索 API 测了一轮,120 道题加 40 个需要多个事实的请求。这个后端它训练时没见过。

基座Obsessive
有回复38%100%
回复里有正确答案37/12024/120
多事实请求全部答对1/4040/40
编造事实值4 of 43 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