post cover

技术热点落地:RL 后训练把 4B 开源模型练成检索专家——Castform + Neon 成本砍 100 倍的实战路径(2026-08-06)


技术热点落地:RL 后训练把 4B 开源模型练成检索专家——Castform + Neon 成本砍 100 倍的实战路径

热点来源:8/5 Neon 发布博客 “How Castform + Neon Beats Frontier Models on Price and Efficiency”HN 324 分 / 80+ 评论原文):用 Castform 平台对 4B 开源模型(示例配置为 Qwen3.5-4B)做强化学习(RL)后训练,在检索任务上准确率追平 GPT-5.6 Sol,成本低约 100 倍。文中给的对照数字:一个典型多轮检索请求用 gpt-5.6-sol 要 >10 秒、端到端约 $0.03;而小开源模型单价便宜两个数量级,只是开箱能力不足——RL 后训练就是用来补这个差的。配套的 castform-ai/benchmax 仓库(Apache-2.0) 里有完整的 neon_rag 可运行示例。对团队的实操含义:“把自家语料变成检索模型”第一次有了不用懂 ML/GPU 细节的落地路径,后训练被做成了像写 prompt 一样的事

前情提要


适用场景与目标

这个热点解决了什么问题?

Agentic retrieval(代理式检索)的现状是:模型在循环里反复调用搜索工具,每一轮循环都是一次前沿模型调用,贵且慢。Neon 给的成本账:一次多轮检索用 gpt-5.6-sol 约 $0.03、延迟 >10s,在客服、RAG、内部知识库这类高频场景下直接不可承受。换小开源模型便宜 100 倍,但开箱检索能力跟不上。Castform 的思路是:用 RL 后训练让 4B 模型学会”怎么用检索工具”,而不是让前沿模型每次现学——训练一次,推理期每次都是小模型的成本。

适用场景

场景价值推荐路线
企业内部知识库问答(文档/Wiki/手册)检索准确率追平前沿模型,单次成本降 1-2 个数量级Castform + Neon Lakebase Search
客服 / 支持助手的高频检索成本敏感、需要低延迟后训练 4B 模型 + 同款混合检索工具
RAG 管线的检索环节替换不换基座大模型,只换”检索决策器”训练专用检索模型,路由给生成模型
已有大量语料但没有标注数据自动合成 QA 训练集(文档→问题→答案)benchmax qa_generation pipeline
团队无 ML/GPU 工程能力后训练做成了平台化操作Castform 托管训练 + 观测面板

不适合的场景

  • 数据完全不能出域:Castform 是托管平台,语料要传到云端。HN 评论区(nullbio)直接问了这个问题;想要本地闭环得自建 RL 训练栈(torchtune/OpenRLHF 等),失去”零门槛”价值
  • 对准确率数字有合规级要求:Neon 文章里没有给出可复现的公共基准(BrowseComp 等)数字,只有自家图表——上生产前必须用你自己的评估集重新测(见坑 1)
  • 任务不是”检索+引用”型:奖励函数围绕 retrieval/citation/correctness 设计,泛化到代码生成、多步推理等任务需要完全重写环境
  • 语料本身质量差:训练数据直接来自你的文档,文档过期/矛盾,练出来的模型就继承这些错误(见坑 4)

最小可行方案(MVP)步骤

先跑通(约 1-2 小时,主要是下载和建库)

以官方 neon_rag 示例为骨架,把 GitLab Handbook 换成你自己的 Markdown 文档:

  1. 准备语料:把 Markdown 文档放进 examples/neon_rag/documents/;没有就用官方 dummy 语料:
    git clone --depth 1 https://gitlab.com/gitlab-com/content-sites/handbook.git documents/gitlab-handbook
  2. 建 Neon 项目:在 Neon Console 新建项目,记下 project ID(形如 flat-frost-16947914),按文档创建 API key。
  3. 克隆 benchmax 并做一次性设置(需要 uv):
    git clone https://github.com/castform-ai/benchmax.git && cd benchmax/examples/neon_rag
    export NEON_API_KEY="..." NEON_PROJECT_ID="..."
    uv run python setup_neon.py    # 启用 pgvector + 全文检索扩展,生成 .env.neon
  4. 确认生成了两个数据库连接(安全设计,后面细讲):
    NEON_DATA_PREPARATION_DATABASE_URL="postgresql://..."  # 可写:建库/灌语料用
    NEON_SEARCH_DATABASE_URL="postgresql://..."            # 只读:训练/推理检索用
  5. 生成训练数据 + 启动训练(默认 20 条 QA,16 训练 / 4 评估):
    source ./.env.neon
    uv run python main.py launch \
      --question-count 20 \
      --neon-data-preparation-database-url "$NEON_DATA_PREPARATION_DATABASE_URL" \
      --neon-search-database-url "$NEON_SEARCH_DATABASE_URL"
    # --force 重灌语料重建 QA;--yes 跳过确认
    命令会依次执行:切块嵌入入库 → 合成 QA → 打包环境 → 本地+云端沙箱验证 → 确认后启动 RL 训练(会花 credits,默认有 Y/N 确认)。
  6. 盯观测面板:在 https://app.castform.com/train/<run_id> 看平均奖励曲线和单任务 trace,确认模型在”学检索”而不是”奖励黑客”。

再优化(按需)

  • 数据量--question-count 从 20 提到 100-1000;语料大时先跑 uv run python main.py data 只重生成 QA,ingest 只更新索引,不用每次全量重来
  • 基座与超参:示例默认 Qwen/Qwen3.5-4Bmax_context_tokens=10_000num_epochs=3(main.py 的 TRAINING_ARGS);换更强基座或加 epoch 前先在验证集上对比
  • 检索工具:示例用 lakebase_text(BM25 全文)+ lakebase_vector(向量)+ RRF 合并;生产建议把检索封装成独立 search API,不要像示例那样把 Postgres URL 直接塞给训练环境(示例 README 自己也标注了 not production-ready)
  • 数据来源扩展:Castform 首页还演示了从 Braintrust/Langfuse/Langsmith 导入 agent traces 生成训练集——有现成生产 trace 的团队可以直接吃这口

关键实现细节

为什么”RL 后训练”能补检索能力的差?

“缺定义不是缺内核”:4B 模型不是不会检索,而是不知道在你的语料里该怎么搜、搜到什么程度该停。RL 后训练 = 让模型在一个真实工具环境里试错:模型调 search 工具 → 拿到结果 → 继续搜或作答 → 奖励函数打分 → 反馈回传。Neon 文章给的奖励拆成三块(平台演示里还有第 4 块):

def reward(trace, ground_truth):
    """把一次 rollout 的 trace 和标准答案对比打分。"""
    answer     = parse_trace(trace)   # 有没有给出最终答案
    retrieval  = ...                  # 有没有检索到正确来源
    citation   = ...                  # 有没有引用正确的 chunk
    correctness= ...                  # 答案对不对
    return retrieval + citation + correctness

平台演示的完整版是 correctness + conciseness + citation + tool_call_efficiency——加 conciseness 和 tool_call_efficiency 是为了防”奖励黑客”:不加的话模型可能学会疯狂搜索直到撞上答案,或输出冗长废话刷分。

混合检索工具是训练环境和推理环境共用的

这是这套方案最巧的一点:训练时的工具调用 = 推理时的工具调用,不存在”训练用模拟器、上线用真环境”的落差。核心是一个混合检索:

def run_tool(tool, tool_args):
    """Single tool: hybrid search over Lakebase."""
    if tool == "search":
        query  = tool_args["query"]
        bm25   = neon.lakebase_text(query, k)    # 全文检索 (BM25)
        vector = neon.lakebase_vector(query, k)  # 向量检索 (pgvector)
        return rrf_merge(bm25, vector, k)        # 倒数排名融合

示例环境的固定参数(neon_rag_env.py):JUDGE_MODEL = "gpt-5.4-mini"(用便宜模型当裁判打分)、EMBEDDING_MODEL = "text-embedding-3-large"(3072 维,换嵌入模型必须匹配建库时的维度)、MAX_SEARCH_CALLS = 8(限制单任务最多 8 次搜索,也是防奖励黑客)。

训练数据是”从语料里长出来的”,不是人工标的

Castform 的合成管线:文档 → 抽取 ground truth → 生成问题(默认 41% 单跳 lookup / 59% 多跳 multi-hop 混合)。示例里的真实效果:

文档:Trains booked through Navan will be paid by GitLab travel card. Train rides must be standard cabin class with 14 day booking lead time. 问题:When booking a rail trip in Navan, what are the rules for how early I need to reserve it and which seating level I’m expected to choose? 答案:标准舱 + 提前 14 天预订。

为什么用 Neon:训练负载是”突发型”的

数千个并行 rollout、每个可能调几十次搜索,是典型的 bursty 工作负载。Neon 的动态扩缩容(autoscale/scale-to-zero)在峰值给低延迟搜索、空闲时缩到零;Neon branching 可以给每个 rollout 一个隔离数据库状态(训练有状态 agent 时防止相互污染),time-travel 查询能回放 agent 当时看到的状态。


常见坑与规避清单

#规避
1拿自家图表当基准,没有公共基准可复现上生产前用你的评估集重测,别直接引用”追平 Sol”
2只盯着 100x 便宜,忘了对比 Luna/DS Flash 这些中间档先跑”直接 prompt 便宜模型”的基线,再决定要不要花训练钱
3语料过期/互相矛盾,模型继承了错误优先最近更新的文档合成 QA;刻意加入矛盾文档做训练样本
4训练环境直连数据库,安全边界不清数据准备用写库、检索用只读库;生产用独立 search API
5奖励函数没防”黑客”,模型刷分不干活conciseness + tool_call_efficiency + MAX_SEARCH_CALLS 三件套
6新数据入库就要重训先只 ingest 更新索引;分布漂移大再重训(见坑 6 展开)
7语料/日志上传托管平台,数据合规风险敏感数据走零保留服务商或自建 RL 栈

⚠️ 坑 1:HN 第一质疑——“没有公共基准,指标口径是什么?”

HN 用户 breadislove 原话:“你们在什么上测的?竟然没有一个常见检索基准(如 BrowseComp+)?报的什么指标?“krm01 补刀:“AI 进展的追踪越来越难,因为基准口径总是被往有利方向偏。” 规避:把”追平 GPT-5.6 Sol”当作方向性证据而非验收标准。复现路径:用你自己的语料建评估集(50-200 条 QA 足够),分别跑基座模型、直接 prompt 的便宜模型、后训练模型,比 top-k 命中率 / 引用正确率 / 端到端延迟。官方训练 run 的 trace 对比在 app.castform.com/train/<run_id> 可见,可以作为参考但别当结论。

⚠️ 坑 2:100x 便宜不是全部——中间档模型可能已经够用

HN 用户 andai 指出文章”没有提 Luna(便宜 25 倍)和 DS Flash(便宜 50 倍)在同任务上的表现,也没提自己的模型快多少”。创始人 seahyinghang8 回应:Luna 的对比其实在文章第一张图里,“Luna 表现确实不错,Sol 只是略好一点点,但 Luna 便宜得多”。 规避:训练前先花 30 分钟做基线——把 gpt-5.6-sol / gpt-5.6-luna / deepseek-v4-flash 直接接到同一个检索工具上跑你的评估集。如果 Luna 已经达标,你省下的不止是推理费,还有整条训练管线的维护成本。

⚠️ 坑 3:语料质量 = 训练质量,GIGO 在这里是真的

HN 用户 richwater:“FAANG 里大量语料是过期/误导/错的,奖励函数从语料本身推导,怎么处理?“创始人给的三条思路:优先用最近更新的文档合成问题(假设新文档更正确);刻意把讲同一主题但互相矛盾的文档都放进去当训练样本(让模型学会”文档 A 说 X,文档 B 说 Y”并解释冲突);从内部 Slack/工单里挖真问题(这些是被验证过的 ground truth)。 规避:语料入库前跑一遍过期检测(按最后修改时间排序,>N 个月的标记),至少把明显的 dead doc 清出去。

⚠️ 坑 4:两个数据库 URL 是安全设计,别图省事合并

setup 生成两条连接:DATA_PREPARATION(可写,建表/灌语料/生成 QA 用,不提供给训练环境)和 SEARCH(只读,训练和验证的检索全走它)。示例 README 特别标注 not production-ready:“生产建议让检索工具对接独立 search API,而不是拿 Postgres URL 直连玩具库。“训练环境里能写库 = 你的训练任务能改你的生产数据,这条边界一定要留。

⚠️ 坑 5:奖励黑客是 RL 训练的头号翻车点

奖励函数只给”答案对”加分时,模型会学出各种钻空子行为:无限搜索直到撞见答案、把答案抄进引用、输出超长内容刷分。示例的三道保险:conciseness 奖励(答得简洁加分)、tool_call_efficiency(搜索次数少加分)、MAX_SEARCH_CALLS = 8 硬上限。Castform 观测面板的核心价值就是单任务 trace 检查——发现 reward 曲线在涨但 trace 行为怪异,立刻停。

⚠️ 坑 6:新数据要不要重训?——先 ingest,别急着 launch

HN 用户 linux_devil:“语料更新了是不是每次都要重训?“创始人 kumama:“后训练模型学的是跨文档可迁移的通用搜索策略,新文档进语料一般不用重训,除非分布严重漂移。” 规避:日常更新走 uv run python main.py ingest(只重建索引);当检索质量明显下滑或语料换了主题域时,再重新合成 QA + 重训。基座模型升级同理——创始人说 pipeline 跑通后,换新基座重跑一遍是”trivial”的。


成本 / 性能 / 维护权衡

方案单次检索成本延迟准确率前期投入维护
全量 gpt-5.6-sol~$0.03(多轮)>10s基线(最高)
直接 prompt 便宜模型低 25-100 倍开箱偏低
后训练 4B(本文)低 ~100 倍≈ Sol训练费 + 数据管线语料更新 + 定期重训

权衡要点:

  • 训练成本一次性,推理成本是持续性的:高频检索场景(客服、RAG、合规查询)几个月就能回本;低频场景不如直接 prompt 便宜模型
  • 维护的真成本在数据管线:RL 训练本身是平台托管,但”语料清洗 → 合成 QA → 评估集”这条链子是你的,跑通后每次重训只是重按按钮
  • 平台锁定要提前想:Castform 是托管 SaaS(语料和训练环境在它那里),benchmax SDK 是 Apache-2.0 开源的可自托管研究;Neon 是数据库,数据可以导出。上生产前确认你的合规边界
  • 模型路由可以叠加:7/31 那篇的分层路由思路照样适用——把后训练检索模型当作”小模型层”的一员,只有它搞不定的请求才升级到前沿模型

一周内可执行行动清单

  • Day 1:通读 neon_rag 示例 README,在本地 clone 仓库,确认 uv 可用
  • Day 2:建 Neon 项目 + API key,跑 setup_neon.py,用 GitLab Handbook 或你自己的小语料把 launch 全流程跑通(可以先 --question-count 10 省钱)
  • Day 3:在观测面板看奖励曲线和单任务 trace,理解”学检索”长什么样;对比训练前后模型的检索行为
  • Day 4:搭基线——把 Luna / DS Flash 直接接到同一检索工具上,跑你自己的 50-100 条评估 QA,记录准确率和成本
  • Day 5:用真实业务语料(注意先做过期/矛盾清洗)重合成 QA 集,跑一轮正式训练;同步建”评估集 + 打分脚本”的自动化
  • Day 6:把检索工具从直连 Postgres 改成独立 search API(生产化),用只读连接跑推理冒烟测试
  • Day 7:算账——对比后训练模型 vs 基线方案的月度推理成本、延迟 P95、检索命中率,写一页决策文档给团队

参考资源


写在最后:这次热点的真正信号不是”某个 4B 模型追平了 Sol”,而是**“后训练”第一次被产品化到了 prompt 工程级别的门槛**——语料进、模型出,中间没有 GPU 运维。理性姿势:先跑便宜模型基线,再用小成本试一轮训练,拿你自己的数据说话;引用”100x”之前,先确认你的场景真的吃满了这 100 倍。