Hacker News 中文摘要

RSS订阅

类 Jev 单函数 LLM 封装,含视觉模型 -- A single function Jev-like wrapper for LLMs, including vision models

我对Jev以及围绕它出现的可自托管项目产生兴趣,例如OpenJev和SemIf。读这些项目让我学到一个巧妙技巧:读取大语言模型的token概率。对某些人来说这算是老办法,比如OpenAI的logprobs cookbook中就有,但对我来说是新的。基本思路是写出这样的提示:状态是我的订单到货时已损坏、我想退款,问题是该由哪个团队处理,选项为账单、物流、退货,只回答最佳选项的字母。

正文

我被 Jev 吸引了,也看了围绕它出现的可自托管项目,比如 OpenJev 和 SemIf。读这些东西让我学到一个很妙的技巧:读取 LLM 的 token 概率。对一些人来说这似乎早就是老把戏了,比如 OpenAI 的 logprobs cookbook,但对我来说是新的。

基本思路是写这样的提示词:State 写「我的订单到货时是坏的,我要退款」,Question 写「该由哪个团队处理?」,选项是 [A] 账单、[B] 配送、[C] 退货,最后要求只回答最优选项的字母。再往兼容的 Chat Completions 请求里加几个 JSON 参数:maxcompletiontokens 设成 1、logprobs 设成 true、top_logprobs 设成 20。API 会返回那个字母,以及模型对其他候选 token 的 log 概率。

每个问题都重复一遍。强制只生成一个 token,可以避免冗长回答,速度极快,不过处理输入仍然要花时间。如果后端支持,每个问题共享的 state 前缀还能用 KV 缓存。

有趣的是,这套做法对视觉模型同样有效。Jev 文档里的请求格式目前只描述文本/JSON 的 state。我在本地实验里加了一个用于图片的 attachments 字段。

我的例子抓取网络摄像头画面,发送 base64 JPEG,然后打印一张表格:是否有人出现、在室内还是室外、场景有多亮。在 RTX 3090 上跑 Gemma 4 12B,大约能达到 1 帧/秒,每帧问三个问题。我也拿它跑过 OpenAI 的 gpt-6-luna,大约 0.2 FPS。大概是因为我没做任何优化,每帧每个问题都要单独穿过他们的系统建一次连接。

专用的计算机视觉模型当然高效得多,但我喜欢这里的灵活性:想改一个判断条件,用自然语言描述一下就行。

下面是独立的 Python 示例。OpenCV 只用来方便地访问摄像头,不做任何实际的计算机视觉。脚本用 uv 运行,只依赖 opencv-python。开头定义一个 data 结构,包含 state、attachments 和 questions(person、plant、setting、light)。score() 函数负责:把 attachments 里的文件路径或 base64 data URL 加载成图片;只在目标主机是 api.openai.com 时带上 API key;把 choice、noul、score 三种题型统一转成带字母的选项,要求模型只回答一个字母;OpenAI 走 /responses 端点,llama.cpp 走 /chat/completions,参数里 topp 设为 1,避免剪掉候选;拿到第一个输出 token 的 toplogprobs 后,用 exp(logprob - peak) 把分数归一化成概率,并对缺失选项做校验;最后按题型返回选项结果、true 的概率或序数的期望值。主程序解析 URL 和模型名,打开 V4L2 摄像头并把缓冲区设成 1,用一个后台线程逐帧打分,同时持续预览画面,每完成一帧就打印时间、各问题的取值和 FPS。

脚本处理了 API 差异:llama.cpp 用 Chat Completions,OpenAI 用 Responses,才能让它返回候选。

我用 llama.cpp 跑了 Gemma 4 12B QAT。在 Linux、装好 NVIDIA 驱动、curl、zstd 和 uv 的前提下:

  1. 下载模型(约 7 GB)和多模态投影器(约 175 MB):先 mkdir -p ~/models/gemma-4-12b/ 并进入该目录,然后用 curl -fL -C - -o 分别下载 gemma-4-12b-it-qat-q40.gguf 和 mmproj-gemma-4-12b-it-qat-q40.gguf,两个文件都在 Hugging Face 的 google/gemma-4-12B-it-qat-q4_0-gguf 仓库下。
  2. 下载适配 RTX 3090(CUDA 架构 86)的独立 llama.cpp 二进制:curl 取回 llama.zst,用 zstd -d 解压到 ~/bin/llama,再 chmod +x。
  3. 运行 ~/bin/llama serve --models-dir ~/models/ --port 8060。
  4. 把 Python 示例保存为 webcam.py,在另一个终端里从该目录运行 uv run webcam.py http://localhost:8060/v1 gemma-4-12b;或者在环境里设好 OPENAIAPIKEY,运行 uv run webcam.py https://api.openai.com/v1 gpt-6-luna。

评论

社区主要对比用通用大模型硬套选择题提示与 Jev 的性价比,多数人认为 Jev 更便宜果断,少数人指出其只是语法解码加缓存的 API 包装,同时夹杂“热狗分类”式调侃。

认为 Jev 比用通用 LLM 做选择题提示更便宜且更果断

  • 用普通大模型加提示回答选项,比 Jev 慢且贵,且在实时场景更犹豫,成本相近(较多人)
  • > 在实时判断句子是否说完时,通用大模型比 Jev 更慢更犹豫,尽管花费差不多(@CROON_tv)

认为 Jev 只是已有技术(语法解码/缓存)的包装或 API 突破

  • 基于语法的解码配合 JSON 响应早已可实现,Jev 可能仅是加了缓存的同类方案;或认为 Jev 本身只是 API 层面突破(较多人)
  • > 用语法解码配合 JSON 响应岂不是一样?Jev 不过就是加了不错缓存的这东西吧(@prathje)

质疑直接让通用模型输出选项字母的鲁棒性与校准

  • 强行限制只答 A/B/C 可能得到 D 或额外说明,且缺乏概率校准;常规大模型因 RLHF 偏向代理行为,可能不如专用方法准(较多人)
  • > 要是它答了“D”或说“需要更多信息”呢?而且这没有校准(@roger_)

希望扩展到图像或多模态并搭配更好语法支持

  • 有人期待同样机制用于图像分类;另指出 Fireworks AI 因具备正规语法支持可能效果更佳(少数人)
  • > 配合具备完善语法支持的 Fireworks AI 可能效果更佳(@Havoc)

有价值的补充

  • 有开发者发布了可接入任意 OpenAI 兼容端点的 Jev 包装器,并指出实现代码量极少(@czl_my, @lostmsu)
  • 星际迷航自动门类比:真正有价值的是环境感知与意图推断,多模态模型从上下文猜意图并适时行动才是方向,而非简单触发器(@TeMPOraL)
  • 纯玩笑代表:有人用“热狗/不是热狗”调侃这类分类任务之简单(@Mashimo)