面向 LLM 的程序设计 1:API 契约设计:从 REST 到「能力端点」

当能力或 API 被 LLM / Agent 调用时,是否容易被模型理解、是否便于稳定调用 ,往往直接决定这套能力会不会被选对、用对。本系列围绕「让 AI 更好理解、更好调用 」这一主线,聚焦面向 LLM / Agent 的接口与数据设计 ------从 API 契约、工具与 Schema、提示与错误模型,到安全幂等、可观测性与生产实践,系统讨论如何把接口与描述设计得更好,以减少误选、误用与幻觉,并更顺地落到工程环境。本篇为系列开篇,从「通用一问一答式接口」与「能力端点」的对比切入,建立后续各篇的共同语境。

摘要 :直接暴露「问一句答一句」的通用接口(如 /ask)会让 LLM 难以稳定选对能力、输入输出语义模糊。用能力化端点 (如 /summarize-document/list-orders-by-user)替代通用对话接口,可以约束输入输出与语义,便于模型选对能力、减少幻觉与误用。本文说明动机、设计原则,并给出可运行的示例项目。

关键词:LLM API 设计;能力端点;REST;Agent 调用;接口契约

代码链接:面向 LLM 的程序设计 1:API 契约设计示例代码


1 为什么通用「问一句答一句」接口不适合被 LLM 调用?

很多系统会对外提供一个「万能」接口:用户或调用方发一段自然语言,系统用大模型生成回复并返回。例如:

  • POST /chatPOST /ask:请求体 { "message": "用户问题" },响应为 { "reply": "模型生成的回答" }

对人来说,这种接口简单直观;但对被 LLM/Agent 调用的下游 API 而言,存在明显问题:

  1. 能力不可区分:调用方(另一个 LLM)只能看到「一个会说话的黑盒」,无法从接口语义上区分「这是做摘要的」「这是查订单的」还是「这是写邮件的」。模型需要从文档或示例中猜测,容易选错或重复造轮子。
  2. 输入输出无契约:请求和响应都是自由文本或简单键,没有结构化约束。模型可能传入无关参数或漏传必要信息,响应也可能难以被程序化解析(例如混入解释性文字)。
  3. 难以编排与重试:多步工作流中,上一步的输出要作为下一步的输入。若每一步都是「自然语言进、自然语言出」,中间结果难以稳定解析,重试与错误处理也缺乏明确边界。

因此,面向「被 AI 调用」的 API,更稳妥的做法是:把能力拆成独立、语义明确的能力端点,每个端点对应一类确定性的输入/输出契约。


2 什么是「能力端点」?

能力端点 指的是:每个 HTTP 端点对应一类明确的能力 ,且请求与响应都有清晰、可校验的结构(通常为 JSON Schema)。

对比项 通用接口(如 /ask 能力端点(如 /summarize-document
语义 模糊:「问什么答什么」 明确:「对文档做摘要」
输入 自由文本或少量键 结构化:如 document_idmax_length
输出 自由文本 结构化:如 summaryword_count
模型选路 需从文档推断 可从路径/名称直接对应到能力

示例(概念层面):

  • POST /summarize-document:输入 { "document_id": "xxx", "max_length": 200 },输出 { "summary": "...", "word_count": 42 }
  • POST /list-orders-by-user:输入 { "user_id": "xxx", "status": "pending", "limit": 10 },输出 { "orders": [...], "total": 5 }

这样,当 LLM 需要「查用户订单」时,可以直接选择 list-orders-by-user 并按照约定传参,而不是向一个通用的「聊天」接口发一句自然语言再解析回复。


3 设计原则小结

  • 一端点一能力 :每个 URL 对应一种明确能力,路径名即语义(如 summarize-documentlist-orders-by-user)。
  • 输入输出结构化:请求体、响应体使用 JSON,并尽量用固定字段名与类型(后续可配合 JSON Schema/OpenAPI 做严格约束,见本系列第二篇)。
  • 命名稳定、可发现:路径与字段名一旦对外暴露,尽量保持兼容;新增能力用新端点而非在旧端点上堆参数。

4 本示例在做什么?

本主题配套的 demo 实现了一个对比示例:

  • 通用接口POST /ask,请求 { "message": "..." },响应 { "reply": "..." },语义与结构均模糊。
  • 能力端点
    • POST /summarize-document:传入 document_id、可选 max_length,返回 summaryword_count
    • POST /list-orders-by-user:传入 user_id、可选 statuslimit,返回 orders 列表与 total

通过同一套服务同时提供两种风格,便于在文档或博客中对比「通用接口」与「能力端点」在可发现性、参数清晰度、响应可解析性上的差异。Demo 使用 FastAPI 实现,提供 OpenAPI 文档,并配有运行说明与完整方案文档。

当我们通过 uvicorn server_api:app --reload --host 127.0.0.1 --port 8310 启动服务后,再在另外一个terminal中运行 python main.py,terminal中返回:

复制代码
=== 1. 通用接口 POST /ask ===

请求: {"message": "帮我查一下 user_001 的订单"}
响应: {'reply': '您可以提供用户 ID 和状态筛选条件,我会帮您查询订单列表。'}

请求: {"message": "给 doc_001 做个摘要"}
响应: {'reply': '请提供文档 ID,我可以为您生成摘要。'}

=== 2. 能力端点 POST /list-orders-by-user ===

请求: {"user_id": "user_001", "status": "pending", "limit": 5}
响应: {'orders': [{'order_id': 'ord_1', 'amount': 99.0, 'status': 'pending'}], 'total': 1}

=== 3. 能力端点 POST /summarize-document ===

请求: {"document_id": "doc_001", "max_length": 100}
响应: {'summary': '人工智能在自然语言处理领域取得显著进展。大语言模型能够完成摘要、问答、翻译等任务。企业可将 LLM 与内部 API 结合,构建智能客服与数据分析应用。', 'word_count': 75}

5 完整代码与文档

在项目目录 demo/ 下执行 pip install -r requirements.txt 并配置 .env 后,运行 uvicorn server_api:app --reload 即可在本地体验上述接口。


相关推荐
思绪无限3 分钟前
YOLOv5至YOLOv12升级:常见车型识别系统的设计与实现(完整代码+界面+数据集项目)
人工智能·深度学习·yolo·目标检测·目标跟踪·yolov12·yolo全家桶
lkforce4 分钟前
MiniMind学习笔记(零)--基础概念
人工智能·算法·机器学习·token·分词器·minimind·词汇表
Ndmzi7 分钟前
每次启动claude 后powershell字体颜色就自动修改了,退出后也不会恢复原状,这是什么原因?
人工智能
Baihai_IDP7 分钟前
以 Nano-vLLM 为例,深入理解 LLM 推理引擎(Part 2)
人工智能·面试·llm
刘~浪地球8 分钟前
当AI开始“制造“:智能工厂是提升效率还是取代工人?
人工智能·制造
BFT白芙堂9 分钟前
基于 AR 阻抗可视化的 Franka Research3 机械臂遥操作设计与应用
人工智能·深度学习·机器学习·机器人·ar·franka
踩着两条虫13 分钟前
VTJ.PRO 新手入门:从环境搭建到 AI 生成首个 Vue3 应用
前端·javascript·数据库·vue.js·人工智能·低代码
2013编程爱好者15 分钟前
【AI】豆包+千问下载以及使用指南
人工智能·千问·豆包
山科智能信息处理实验室16 分钟前
(ITES 2025)教育推荐系统综述:主流技术、应用场景与未来趋势
人工智能
OneThingAI19 分钟前
网心技术 | Claude Managed Agents 让 Harness 变成服务
人工智能·claude·onethingai·网心科技