☰
QMD 仓库 API 设计原则解析:从 REST 七条准则到检索评测的实战验证
2026/10/1 10:37:08 网站建设 项目流程

QMD 仓库 API 设计原则解析:从 REST 七条准则到检索评测的实战验证

【免费下载链接】qmdmini cli search engine for your docs, knowledge bases, meeting notes, whatever. Tracking current sota approaches while being all local项目地址: https://gitcode.com/GitHub_Trending/qmd1/qmd

本指南以 test/eval-docs/api-design-principles.md 中沉淀的 REST API 设计原则为核心骨架,系统梳理名词化 URL、复数资源、层级关系、过滤分页、版本化、错误处理与限流等七条准则,并对照本仓库(qmd,一个全本地的迷你 CLI 搜索引擎)的源码与评测体系,说明这些文档在检索评测中的实际用途、如何把它们接入本地知识库,以及如何借助 BM25 与语义检索验证 Agent 能否基于它们回答真实的 API 设计问题。读完本文,你将既掌握一套可直接落地的 REST API 设计规范,也理解"规范文档如何成为可评测的语料"这一完整闭环。

一、文档定位:这份 API 设计原则在仓库中的角色

在 qmd 仓库中,test/eval-docs/api-design-principles.md 并非普通的代码注释,而是一份被专门用于检索评测的"黄金语料"。它位于test/eval-docs/目录,与 distributed-systems-overview.md(分布式系统)、machine-learning-primer.md(机器学习)、remote-work-policy.md(远程办公政策)、startup-fundraising-memo.md(融资备忘录)等文档共同构成评测用文档集。

从仓库结构看,test/eval-docs目录在多个评测链路中被引用:

  • test/eval.test.ts 中通过evalDocsDir定位该目录,将其中每份文档插入评测集合(对应代码位置 test/eval.test.ts);
  • test/eval-bm25.test.ts 同样以eval-docs为插入目标(test/eval-bm25.test.ts);
  • test/bench-guard.test.ts 使用eval-docs作为基准集合就绪性断言的对象(如 test/bench-guard.test.ts);
  • test/eval-deep-research.ts 中的查询集直接引用api-design文档作为期望命中结果(见下节)。

也就是说,这份 API 设计原则文档在本仓库中扮演"知识基准"角色:搜索引擎的检索质量、重排效果,都以"能否命中这份文档"为衡量标准。这也是为什么理解它本身的内容,与理解仓库评测机制同等重要。

二、核心原则逐条拆解:七条可落地的 REST 设计准则

原文档正文完整地给出了七条设计原则,以下是每条原则的完整展开与工程化注释。

原则一:用名词,不用动词(Use Nouns, Not Verbs)

URL 应当表示资源而非动作,动作交给 HTTP 方法来表达。这是 REST 风格与 RPC 风格最直观的分界线。

推荐写法:

GET /users/123 → 读取 123 号用户资源 POST /orders → 在 orders 集合中创建新订单 DELETE /products/456 → 删除 456 号产品资源

应避免的写法:

GET /getUser?id=123 POST /createOrder GET /deleteProduct/456

工程化要点:当 URL 中出现get、create、delete等动词时,通常意味着动作语义被塞进了路径,而 HTTP 方法(GET/POST/PUT/DELETE/PATCH)本就承担了动作表达。保持名词化还有助于路由配置、权限控制(基于资源粒度)与缓存层设计保持一致。

原则二:始终使用复数名词(Use Plural Nouns)

为了一致性,资源集合应统一用复数形式:

/users (而不是 /user) /orders (而不是 /order) /products (而不是 /product)

工程化要点:复数约定消除了"单数到底指集合还是指单个资源"的歧义,配合原则三的层级嵌套,GET /users/123/orders与GET /users/123/orders/456能天然读作"用户 123 的订单集合"与"用户 123 的某笔订单"。复数集合 + 数字 ID 的路径模式也是 OpenAPI/Swagger 生态最常见的约定。

原则三:用 URL 层级表达资源关系(Hierarchical Relationships)

通过 URL 层级表达"从属/嵌套"关系:

GET /users/123/orders → 获取用户 123 的全部订单 GET /users/123/orders/456 → 获取用户 123 的订单 456

工程化要点:层级结构适用于"一对多"强从属关系;当关系变成"多对多"或资源间无强父子约束时,文档(原则四)给出更合适的做法——用查询参数过滤而非无限加深路径。从源码结构看,qmd 自身的 MCP 服务器同样使用层级化资源寻址:文档通过qmd://URI 暴露(见 src/mcp/server.ts),与"资源化寻址"的思路一脉相承。

原则四:过滤与分页(Filtering and Pagination)

过滤、排序、分页统一交给查询参数:

GET /products?category=electronics&sort=price&page=2&limit=20

参数语义参考:

参数作用常见取值
category按字段过滤业务枚举值
sort指定排序字段price、-price(降序)
page页码(从 1 起)1、2…
limit每页条数常用10/20/50,需设上限

工程化要点:分页参数务必设置上限并文档化;排序字段应白名单化,防止任意字段注入导致性能问题或信息泄露。page+limit之外,游标分页(cursor-based)在大数据集下更稳定,但本原则文档以page+limit为基线,两种方案可依业务取舍。

原则五:版本化(Versioning)

API 应当始终携带版本号,本原则文档明确偏好 URL 版本化:

/v1/users /v2/users

工程化要点:URL 版本化(/v1、/v2)与 Header 版本化(Accept: application/vnd.example.v1+json)各有取舍,本规范选择前者,理由是它直观、可缓存、便于在网关层按版本分流。实践中建议:破坏性变更升大版本、向后兼容变更留在当前版本内,并配合迁移窗口。

原则六:错误处理(Error Handling)

返回一致的错误响应结构,并配以恰当的 HTTP 状态码:

{ "error": { "code": "VALIDATION_ERROR", "message": "Email format is invalid", "field": "email" } }

错误对象字段语义:

字段含义示例
code机器可读的错误码,便于客户端分支处理VALIDATION_ERROR、NOT_FOUND、RATE_LIMITED
message面向开发者的可读描述Email format is invalid
field出错字段(校验类错误的定位信息)email

工程化要点:code与 HTTP 状态码配合使用——状态码表达大类(4xx 客户端错误/5xx 服务端错误),code表达精确子类;field字段让前端能直接把错误定位到表单控件。错误响应体结构一旦发布即成为对外契约,务必与版本化策略绑定。

原则七:限流(Rate Limiting)

实现限流,并通过响应头告知客户端额度与重置时间:

X-RateLimit-Limit: 1000 # 窗口内允许的总请求数 X-RateLimit-Remaining: 999 # 窗口内剩余请求数 X-RateLimit-Reset: 1640000000 # 额度重置的 Unix 时间戳(秒)

工程化要点:这三个响应头(Limit/Remaining/Reset)已成为事实上的行业惯例,客户端可以据此做本地退避,而不是盲目重试;配合429 Too Many Requests状态码与Retry-After头,可构成完整的限流反馈闭环。文档末尾的结论强调:最好的 API 是开发者无需阅读文档就能上手的 API——一致性、直觉化正是七条原则的共同目标。

三、这些原则在本仓库中的实际价值:作为检索评测的"语义靶场"

上文反复强调这份文档在test/eval-docs/中的语料身份,这里给出完整的实证链路。

3.1 先决条件:把 eval-docs 接入本地知识库

要让评测运行,需先把test/eval-docs注册为 qmd 集合(文档只读,此处仅说明操作方式):

qmd collection add test/eval-docs --name eval-docs qmd embed

这两步的提示直接出现在 test/eval-deep-research.ts 与 test/eval-harness.ts 中:评测脚本会先检查eval-docs集合是否存在,不存在则输出上述命令并退出。

3.2 评测查询集:针对 api-design 的"难题"

test/eval-deep-research.jsonl 中与本文档直接相关的查询有(含行号):

行号查询期望命中难度说明
L7how to structure URLs for our serviceapi-designhardREST 端点,无精确关键词命中
L18why URLs should be things not actionsapi-designhard名词而非动词的概念反转
L24how to get user 123's purchasesapi-designhard层级 URL 的示例式提问

注意这些查询的刻意设计:与目标文档没有任何精确关键词重合(notes字段明确标注 "no exact match")。例如why URLs should be things not actions与文档中的 "Use Nouns, Not Verbs" 需要语义等价理解才能建立关联——这正是 qmd 查询扩展与重排能力要解决的问题。

3.3 评测机制:BM25 基线 vs 深度研究链路

test/eval-deep-research.ts 实现了双方法对比评测:

  • BM25 基线:通过bun src/qmd.ts search "${query}" -c eval-docs --json -n 5调用纯关键词检索(test/eval-deep-research.ts);
  • 深度研究链路:通过bun src/qmd.ts query "${query}" -c eval-docs --json -n 5触发"查询扩展 → 重排"的完整语义链路(test/eval-deep-research.ts)。

评测统计 Hit@1 / Hit@3 / Hit@5 三项指标,即期望文档出现在前 1/3/5 条结果中的比例(test/eval-deep-research.ts),并以findRank定位期望文档的命中排名(test/eval-deep-research.ts)。运行方式:

bun test/eval-deep-research.ts

而 test/eval-bm25.test.ts 则从另一角度验证:即使没有语义扩展,BM25 对eval-docs集合也能完成索引与检索(其插入逻辑位于 test/eval-bm25.test.ts),为对比提供基线参照。

3.4 通用检索入口:在命令行里"问"这份文档

不依赖评测脚本,也可以直接用 qmd CLI 检索这份原则文档:

# 建立集合(首次) qmd collection add test/eval-docs --name eval-docs qmd embed # 关键词检索(BM25) bun src/qmd.ts search "how to get user 123's purchases" -c eval-docs --json -n 5 # 语义检索(查询扩展 + 重排) bun src/qmd.ts query "why URLs should be things not actions" -c eval-docs --json -n 5

-c eval-docs指定集合,--json输出结构化结果(含file、score、title),-n 5限制返回条数。这套 CLI 参数在评测脚本中与上述两条命令完全一致。

四、延伸:REST 原则与 qmd 架构的对应观察

从源码结构看,qmd 自身的对外接口设计也体现了资源化、一致性的思路,可作为七条原则的仓库内印证:

  • 资源寻址:MCP 服务器将文档以qmd://URI 资源形式暴露,并实现qmd://资源的模板化访问(见 src/mcp/server.ts),对应"资源而非动作"的资源化设计;
  • 结构化响应:搜索结果以统一结构返回docid、file、title、score、context、line、snippet等字段(src/mcp/server.ts),类似错误处理原则中"一致响应结构"的实践;
  • 限制与防御:仓库包含 src/mcp/origin-guard.ts(来源校验),是服务端防御性设计的一环,与"限流/错误处理"所强调的服务端自我保护精神一致。

需要说明的是,以上是基于仓库现有结构的对应性观察,并非文档声称 qmd 实现了某条 REST 原则——文档本身只是作为评测语料存在。

五、结语:规范文档如何成为可评测资产

回到这份 api-design-principles.md:它同时具备双重身份——对开发者是一份可直接落地的 REST 设计清单(名词化 URL、复数资源、层级关系、查询参数过滤分页、URL 版本化、结构化错误、限流头),对 qmd 仓库则是一份"语义难度拉满"的评测语料(三条例证查询均无关键词重合,强制依赖语义理解)。

七条原则最终指向同一目标——让 API 直觉化、一致化,"最好的 API 是开发者无需读文档就能上手的 API"。而在本仓库中,检验"Agent 是否真的理解这份文档"的方式同样朴素而严格:构造无关键词重合的问题,看检索链路能否把它找回来。这份文档因此成为"规范 → 语料 → 评测 → 反哺"闭环中的一环,也是理解 qmd 检索与重排能力的绝佳起点。

如需深入:评测脚本见 test/eval-deep-research.ts 与 test/eval-bm25.test.ts,查询集见 test/eval-deep-research.jsonl,集合注册与状态检查见 test/eval-harness.ts 与 test/bench-guard.test.ts。

【免费下载链接】qmdmini cli search engine for your docs, knowledge bases, meeting notes, whatever. Tracking current sota approaches while being all local项目地址: https://gitcode.com/GitHub_Trending/qmd1/qmd

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

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

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

立即咨询