Karakeep 模型对比工具(compare-models):基于真实书签数据的 AI 标签质量盲测实战指南
2026/9/12 13:13:15 网站建设 项目流程

Karakeep 模型对比工具(compare-models):基于真实书签数据的 AI 标签质量盲测实战指南

【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder

本文围绕 Karakeep 仓库中 tools/compare-models/README.md 所描述的独立 CLI 工具展开。该工具用你实例中真实存在的书签数据,以「盲测 + 随机乱序」的方式对比不同 AI 模型的自动打标签质量,是你在更换/升级打标签模型、做 AI 标签质量验收时的实用评估方案。读完本文,你将掌握两种对比模式(模型 vs 模型、模型 vs 现有 AI 标签)的完整配置、运行与投票交互流程,并理解其背后复用的 Karakeep 共享推理与提示词基础设施。

工具定位:为什么需要对比模型打标签效果

Karakeep 的核心能力之一是「AI 自动打标签」:系统会把书签内容交给配置好的大模型,生成一组规范化标签。当你想从gpt-4o-mini换到claude-3-5-sonnet,或想验证某个新模型是否比现有模型更优秀时,单纯跑一两次推理很难得出可靠结论——标签质量带有较强主观性,且不同模型对同一内容的标签风格差异很大。

compare-models工具正是为此设计:它从你的 Karakeep 实例拉取真实书签,对每个书签分别让两个候选方(两个模型,或一个模型 vs 现有 AI 标签)生成标签,然后由你人工投票选出更优的一方。整个过程是盲测的——投票界面只显示 "Model A" / "Model B",模型真实名称直到最终结果才揭晓;同时每个书签的左右位置会随机打乱,消除位置偏见。正如 README 所强调的,这是一个「human-in-the-loop」(人在回路)的手动评估工具,结果只输出到控制台、不做持久化,适合作为模型选型与质量验收的决策依据。

前置条件与整体架构

你需要准备什么

  • 一个可访问的 Karakeep 实例(本机或远程),并拥有 API Key;
  • 实例中已有若干链接型(link)书签;在「模型 vs 现有」模式下还需这些书签已带 AI 生成的标签;
  • 一个兼容 OpenAI 接口的推理服务:可以是 OpenAI 官方,也可以是 OpenRouter 等聚合服务(工具通过OPENAI_BASE_URL切换,见下文);
  • 支持pnpm的 Node.js 环境(推荐使用 pnpm workspace 运行)。

从源码看工具的模块划分

工具位于 tools/compare-models/src,源码结构清晰地对应了 README 描述的功能:

  • index.ts:主流程入口,负责模式判断、取数、逐条推理、投票统计与最终结果展示;
  • config.ts:用 zod 对全部环境变量做校验与默认值处理;
  • apiClient.ts:基于@karakeep/sdk封装 Karakeep API 客户端,负责分页拉取书签;
  • bookmarkProcessor.ts:把书签内容拼装成提示词输入;
  • inferenceClient.ts:创建 OpenAI 兼容推理客户端并解析结构化标签输出;
  • interactive.ts:终端交互(投票提问、盲测展示、进度与最终结果渲染);
  • types.ts:BookmarkComparisonResultFinalResults等核心类型定义。

该工具本身不重复造轮子,而是直接复用 Karakeep 主应用的共享基础设施:API 走@karakeep/sdk(类型安全、自带鉴权),推理走@karakeep/shared/inference的 OpenAI 客户端(支持结构化输出),提示词走@karakeep/shared/prompts的统一标签提示词构建器(含 token 管理)。这一点在 package.json 的依赖声明中可以得到印证:@karakeep/sdk@karakeep/shared均为 workspace 依赖,另有chalk(终端着色)与zod(校验/解析)。

环境变量与配置详解

工具的全部配置都通过环境变量注入,并在 config.ts 中由 zod schema 统一校验。README 给出的必填项如下:

# Karakeep API 配置 KARAKEEP_API_KEY=your_api_key_here KARAKEEP_SERVER_ADDR=https://your-karakeep-instance.com # 对比模式(默认: model-vs-model) # - "model-vs-model": 两个模型互相比较 # - "model-vs-existing": 新模型 vs 现有 AI 标签 COMPARISON_MODE=model-vs-model # 待比较的模型 # MODEL1_NAME: 要测试的新模型(始终必填) # MODEL2_NAME: 第二个参与对比的模型(仅 model-vs-model 模式必填) MODEL1_NAME=gpt-4o-mini MODEL2_NAME=claude-3-5-sonnet # OpenAI/OpenRouter API 配置(用于推理) OPENAI_API_KEY=your_openai_or_openrouter_key OPENAI_BASE_URL=https://openrouter.ai/api/v1 # 可选,默认直连 OpenAI # 可选:测试书签数量(默认: 10) COMPARE_LIMIT=10

源码中隐藏的可选进阶参数

对照 config.ts,除 README 列出的变量外,源码还支持以下几组进阶推理参数(README 未展开,但实战中很有用):

环境变量类型/取值范围默认值作用
COMPARISON_MODEmodel-vs-model/model-vs-existingmodel-vs-model对比模式
COMPARE_LIMIT整数10参与测试的书签数量
INFERENCE_CONTEXT_LENGTH整数8000推理上下文长度,控制送入模型的 token 上限
INFERENCE_MAX_OUTPUT_TOKENS整数2048模型最大输出 token 数
INFERENCE_USE_MAX_COMPLETION_TOKENStrue/falsefalse是否使用最大补全 token 上限
INFERENCE_REASONING_EFFORTlow/medium/high/none/xhigh未设置推理强度,适配支持 reasoning effort 的模型
OPENAI_SERVICE_TIERauto/default/flex未设置OpenAI 服务等级

需要说明的是:config.tsz.string().min(1)校验KARAKEEP_API_KEYMODEL1_NAMEOPENAI_API_KEY,用z.string().url()校验KARAKEEP_SERVER_ADDROPENAI_BASE_URL,因此缺失或格式错误的环境变量会让工具启动即报错退出——这也是 README「错误处理」一节中「缺失必填环境变量会以明确错误信息退出」的源码依据。若配置非法,zod 抛出的校验错误会被 index.ts 末尾的main().catch()捕获并以红色✗ Fatal error打印。

直连 OpenAI 与使用 OpenRouter

工具通过OPENAI_BASE_URL决定推理端点,README 给出了两种典型配置:

使用 OpenRouter(可在一个 Key 下访问多个模型):

OPENAI_BASE_URL=https://openrouter.ai/api/v1 OPENAI_API_KEY=your_openrouter_key

直连 OpenAI:

OPENAI_API_KEY=your_openai_key # OPENAI_BASE_URL 省略即可直连 OpenAI

从 inferenceClient.ts 的源码可以看到,createInferenceClient会把上述变量连同textModelimageModel(此处均设为待比较的模型名)、contextLengthmaxOutputTokensoutputSchema: "structured"等一起传给共享的OpenAIInferenceClient。这也意味着:只要是 OpenAI 兼容协议的服务(OpenRouter、各类自建网关等),都可以通过OPENAI_BASE_URL接入。

安装与三种运行方式

方式一:pnpm 运行(推荐)

README 推荐的开发运行方式,利用tsx直接执行 TypeScript 源码,并自动加载.env文件:

cd tools/compare-models pnpm install pnpm run

pnpm run实际执行的是 package.json 中的脚本tsx --env-file=./.env src/index.ts——注意它要求当前目录下存在.env文件。

方式二:使用 .env 文件

先创建.env

KARAKEEP_API_KEY=your_api_key KARAKEEP_SERVER_ADDR=https://your-karakeep-instance.com MODEL1_NAME=gpt-4o-mini MODEL2_NAME=claude-3-5-sonnet OPENAI_API_KEY=your_openai_key COMPARE_LIMIT=10

然后同样执行:

pnpm run

方式三:编译后直接用 node 运行

先构建出dist/index.js,再用环境变量注入方式运行:

pnpm build export KARAKEEP_API_KEY=your_api_key export KARAKEEP_SERVER_ADDR=https://your-karakeep-instance.com export MODEL1_NAME=gpt-4o-mini export MODEL2_NAME=claude-3-5-sonnet export OPENAI_API_KEY=your_openai_key node dist/index.js

pnpm build对应脚本为tsc && chmod +x dist/index.js,构建产物位于dist/index.js;同时 package.json 声明了bin: { "compare-models": "dist/index.js" },即构建后可获得compare-models命令行入口。README 特别提示:推荐pnpm run(走 tsx 开发模式)以获得最佳体验。

两种对比模式与使用流程

Model vs Model:两个模型互相对比

COMPARISON_MODE=model-vs-model MODEL1_NAME=gpt-4o-mini MODEL2_NAME=claude-3-5-sonnet

该模式下,每个书签会让两个模型各自独立推理生成标签,然后由你投票选择哪一组的标签更好。源码 index.ts 在启动时会校验MODEL2_NAME是否提供,缺失则直接红色报错并以退出码 1 终止。

Model vs Existing:新模型 vs 现有 AI 标签

COMPARISON_MODE=model-vs-existing MODEL1_NAME=gpt-4o-mini # 该模式不需要 MODEL2_NAME

此模式不再让第二个模型跑推理,而是把书签上已经存在的 AI 标签作为对手。它适合三种典型场景:

  • 测试新模型是否比当前模型产出更好的标签;
  • 评估是否值得从当前模型切换到另一个模型;
  • 对现有 AI 标签做质量抽检(QA)。

关键过滤规则:该模式只对比已带 AI 标签的书签。README 明确说明只保留attachedBy: "ai"的标签;源码 index.ts 中对应实现为bookmarks.filter((b) => b.tags.some((t) => t.attachedBy === "ai"))attachedBy字段的取值在数据库层被约束为"ai" | "human",见 packages/db/schema.ts。若过滤后没有符合条件的书签,工具会打印黄色提示并直接结束。

完整使用流程(结合源码)

  1. 拉取书签KarakeepAPIClient.fetchBookmarks调用 SDK 的GET /bookmarks,以 50 条一批分页拉取,携带includeContent: truearchived: false参数,并在客户端侧过滤出content.type === "link"的书签,最终截取前COMPARE_LIMIT条。这一点对应 README「Bookmark Filtering」中「只测链接型书签、非归档、最新 N 条」的说明(apiClient.ts)。

  2. 逐条推理:对每个书签,先由extractBookmarkContent把 URL、标题、描述、HTML 内容拼接为文本,再调用共享的buildTextPrompt构建打标签提示词(空自定义提示词、标签风格为as-generated,即保留模型原始生成结果),见 bookmarkProcessor.ts。随后用 zod 定义的{ tags: string[] }结构约束模型输出,并解析为标签数组,见 inferenceClient.ts。推理按顺序逐条执行,保证状态管理简单(README 已注明)。

  3. 随机乱序 + 盲测展示:源码用Math.random() < 0.5决定模型 1 还是模型 2 显示在 "Model A" 位置,投票界面只显示 "Model A" / "Model B"(displayComparisonblind参数为true),模型真名在投票阶段完全隐藏。

  4. 人工投票:界面形如 README 给出的示例:

    === Bookmark 1/10 === How to Build Better AI Systems https://example.com/article This article explores modern approaches to... ───────────────────────────────────── Model A (blind): • ai • machine-learning • engineering Model B (blind): • artificial-intelligence • ML • software-development ───────────────────────────────────── Which tags do you prefer? [1=Model A, 2=Model B, s=skip, q=quit] >

    合法输入与对应行为(interactive.ts 的askQuestion+ index.ts 的计票逻辑):

    • 1:投给 Model A(计票时按乱序结果映射回真实模型);
    • 2:投给 Model B;
    • s/skip:跳过本次对比(计入 Skipped);
    • q/quit:提前退出并展示当前累计结果。
  5. 展示最终结果:全部完成或提前退出后,控制台输出投票汇总与胜者:

    ─────────────────────────────────────── === FINAL RESULTS === ─────────────────────────────────────── gpt-4o-mini: 6 votes claude-3-5-sonnet: 3 votes Skipped: 1 Errors: 0 ─────────────────────────────────────── Total bookmarks tested: 10 🏆 WINNER: gpt-4o-mini ───────────────────────────────────────

    从 interactive.ts 的displayFinalResults源码可见,票数相同会显示🏁 RESULT: TIE,否则显示🏆 WINNER: <模型名>。只有在这个最终结果里,真实模型名才会揭晓。

错误处理

  • 任一模型在某书签上推理失败时,会打印红色错误信息(✗ Error: ...),该次对比计入Errors,流程继续(index.ts 中的try/catch+counters.errors++);
  • 错误数在最终结果中单独一行展示(Errors: N);
  • 必填环境变量缺失/非法时,工具以清晰的错误信息退出(见上文配置校验部分)。

书签过滤规则的实现细节

README 明确当前工具只测试以下书签,这些规则都可以在源码中找到对应实现:

  • 仅链接型书签fetchBookmarks中用b.content?.type === "link"过滤,不含文本笔记(text notes)与资产(assets)类书签;
  • 非归档:请求参数固定携带archived: false
  • 最新 N 条:分页拉取后slice(0, limit)limitCOMPARE_LIMIT
  • model-vs-existing 模式附加条件:仅保留含attachedBy: "ai"标签的书签,且该模式下模型 2 的「标签」直接取自书签上现有的 AI 标签(bookmark.tags.filter((t) => t.attachedBy === "ai").map((t) => t.name)),不再触发推理。

从源码看架构复用与设计取舍

README「Architecture」一节总结了工具对 Karakeep 共享基础设施的复用,结合源码可以看得更具体:

  • API 客户端apiClient.ts使用createKarakeepClient(来自@karakeep/sdk),以Bearer ${KARAKEEP_API_KEY}鉴权,baseUrl 为${KARAKEEP_SERVER_ADDR}/api/v1/,请求GET /bookmarks并支持 cursor 分页——与 Karakeep 主应用使用同一套类型安全 SDK。
  • 推理inferenceClient.ts复用@karakeep/shared/inferenceOpenAIInferenceClient,配置outputSchema: "structured",配合 zod schema 获得结构化、可解析的标签输出。
  • 提示词bookmarkProcessor.ts复用@karakeep/shared/prompts.serverbuildTextPrompt(带contextLengthtoken 管理),并以as-generated保留模型原始标签风格,保证对比的是模型真实能力而非被提示词改写后的结果。

这种「零代码重复、全量复用主应用核心逻辑」的设计,保证了对比结论与 Karakeep 实际打标签路径的一致性——你在工具里测出的模型差异,就是将来接入主应用后的真实差异。

注意事项与使用建议

  • 评估方式:工具面向人工、人在回路的评估,结果只打印在控制台,不持久化、不写回 Karakeep(README「Notes」已明确);
  • 内容拉取:书签以includeContent=true拉取,因此评估依据的是真实抓取内容;
  • 推理顺序:推理串行执行,模型数量与书签数量较多时耗时较长,建议先用较小的COMPARE_LIMIT(如默认 10)试跑;
  • 样本选择:测试结果受所选书签样本影响较大,若要评估模型切换,建议覆盖不同类型、不同领域的书签,并可多次运行观察一致性;
  • 现有 AI 标签的前提:使用model-vs-existing前,请确认实例中确有 AI 生成的标签(无则工具会提示 No bookmarks found with AI tags 并退出)。

构建与产物

如需生成独立可执行产物:

pnpm build

构建产物为dist/index.js(可执行位已在构建脚本中设置),配合 package.json 中的bin声明,可通过compare-models命令直接调用。产物同样依赖上述环境变量,运行方式与「方式三」一致。

小结

compare-models是 Karakeep 生态中一个轻量而严谨的模型评估工具:以真实书签为样本、以共享推理管线为引擎、以盲测与随机乱序消除主观偏差、以人工投票作为最终裁决。无论你是想换一个更便宜的模型、评估开源模型能否替代商业模型,还是例行抽检已有 AI 标签质量,都可以用 tools/compare-models/README.md 与本文提供的源码级细节,在几分钟内搭建起一次可复现的对比实验。

【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询