当前位置: 首页 > news >正文

面向 LLM 的程序设计 3:LLM-Friendly 的响应结构:扁平键、稳定字段与类型标注

在满足能力端点与确定性契约之后,响应长什么样仍会直接影响模型能不能「读对结果、少误解、少编造字段」。本系列继续围绕「让 AI 更好理解、更好调用」,讨论如何把 JSON 响应设计成对模型和后续工具链都更友好:键名稳定、层次尽量扁平、数组与对象的语义一眼能读懂,并用明确的标量类型(整数金额的分、布尔库存等)减少歧义。

本篇为系列第三篇:前两篇分别谈了能力端点JSON Schema 硬契约;本篇聚焦响应体形态——在契约已成立的前提下,仍要避免「能校验却难理解」的嵌套与命名,让解析与链式调用更省心。

摘要:深层嵌套、缩写键名、同一语义多种字段名、金额与布尔用字符串承载,都会增加模型解析负担与幻觉风险。采用扁平或浅层结构、稳定且可预期的 snake_case 全名与业务语义一致的类型(如price_cents: integerin_stock: boolean),并在顶层保留response_type判别字段,可显著提升 LLM 与程序化下游的消费体验。本文说明原则与正反对照,并给出可运行对比示例。

关键词:LLM-Friendly API;JSON 响应设计;扁平结构;稳定字段;类型标注

源代码链接:面向 LLM 的程序设计 3:LLM-Friendly 的响应结构源代码


1 为什么「有 Schema」还不够?

即便请求与响应都通过了 JSON Schema 校验,仍可能出现:

  1. 层次过深:结果藏在data.payload.result.items之下,模型在多步推理中容易数错层级或把兄弟字段张冠李戴。
  2. 键名不稳定或过于简略rdlist这类缩写对人可读性差,对模型也缺少语义锚点;不同接口分别用id/productId/pid表示同一概念时,跨工具拼接容易混用。
  3. 标量类型语义模糊:金额用"19.99"字符串、in_stock"yes",模型可能输出与下游不一致的格式;整数分 + 货币码、「真假的布尔」更利于确定性处理。
  4. 数组项形状不一致:有的元素是对象、有的嵌套多一层 wrapper,会给「取第 i 个元素的某字段」这类操作埋下错误种子。

可以把响应想象成给另一位工程师的交接单:Schema 保证「字段合法」,而LLM-Friendly 结构保证「一眼知道每格写什么、少翻层、少猜缩写」。


2 设计原则小结

原则含义💡 理解要点
扁平优先重要结论放在顶层或浅层;避免无信息增量的深套娃像目录页:先见到「有几条、是什么类型」,再展开列表
键名稳定、可读全词、snake_case、同一概念全局同名(如始终product_id避免同一文档多种命名风格混用
类型即语义钱用整数最小单位 +currency;是否库存用boolean减少「字符串里的数字」带来的二次解析
列表元素同质数组内对象字段集合一致;少用「有时对象有时字符串」便于模型写循环与下游代码复用
顶层判别可用response_type(或等价枚举)区分不同成功形态便于分支逻辑与少误读字段

🔍实际例子:搜索商品接口的成功体可设计为response_type: "product_search"product_count: 3products: [{ product_id, title, price_cents, currency, in_stock }],而不是d: { r: { l: [...] } }且金额为"12.50"字符串。


3 反例与正例(概念对照)

反例(仍可能过校验,但难理解)

  • 深层路径:body.data.results.items[].product.meta.title
  • 缩写键:pamtflg
  • 金额:"19.99"(string),库存:"1"(string)

正例(契约 + 友好)

  • 顶层:response_typeproduct_countproducts
  • 单项:product_idtitleprice_cents(int)、currency(如CNY)、in_stock(bool)
  • 可选:统一分页next_cursor(string | null)与 Schema 对齐,避免魔法嵌套

完整字段定义见配套 demo 中的 Pydantic 模型与 OpenAPI。


4 本示例在做什么?

配套demo同一套内存里的 mock 商品(例如sku_1001无线鼠标、sku_1002机械键盘,含原价整数分、币种、是否有货),经同一个过滤条件生成两种响应;两端都走 FastAPI + Pydantic,OpenAPI/docs里能看到两套不同的响应 Schema,但都满足校验。

共同请求POST,请求体 JSON 为ProductSearchRequest,字段只有query(字符串,可空)。服务端对MOCK_PRODUCTS标题子串匹配(不区分大小写):query为空则返回全部商品;query非空则只保留title中含该子串的项。main.py里固定发送{"query": "键盘"},因此只会命中「机械键盘」一条,便于两份响应在「条数相同」的前提下纯粹对比形状

1)POST /examples/nested-legacy(反例)

  • 响应根上是缩写键d,其下为rl(表示 data / result / list),列表元素为i(商品 id)与m(meta)。
  • 标题与价格在m里缩写为tamt;其中amt是字符串,由内部price_cents格式化成类似"99.00"的小数字符串,故意丢掉「整数分 + 币种」的确定性表达。
  • 若要用自然语言描述取一条商品的标题:需要走路径大致如d.r.l[0].m.t,id 为d.r.l[0].i不建议在生产照搬这一形状。

2)POST /examples/flat-llm-friendly(正例)

  • 顶层依次给出response_type(本 demo 固定为"product_search",用于多态判别)、product_count(整数条数)、products(数组)。
  • 数组元素是同质对象:product_idtitleprice_cents整数最小货币单位)、currency(三字母,如CNY)、in_stock布尔)。与同一条 mock 数据源对齐,但不再把价格压成无币种的字符串。

如何对照:先uvicorn server_api:app --reload --port 8312,再在项目目录运行python main.py;终端会先后打印两次美化后的 JSON。读者可以数一下:反例从根到「第一条商品标题」经过几层键名、正例是否一眼能读到products[0].title;并打开http://127.0.0.1:8312/docs展开两个 POST,对照自动生成的响应 Schema 与字段说明。

启动服务后,再在另外一个terminal中运行python main.py,terminal中返回:

=== 1. 反模式:POST /examples/nested-legacy === 请求: {'query': '键盘'} 响应 JSON(美化): { "d": { "r": { "l": [ { "i": "sku_1002", "m": { "t": "机械键盘", "amt": "459.00" } } ] } } } === 2. LLM-Friendly:POST /examples/flat-llm-friendly === 请求: {'query': '键盘'} 响应 JSON(美化): { "response_type": "product_search", "product_count": 1, "products": [ { "product_id": "sku_1002", "title": "机械键盘", "price_cents": 45900, "currency": "CNY", "in_stock": false } ] }

5 完整代码与文档

  • 运行与架构README_运行与架构.md
  • 完整方案README_完整方案.md

在项目目录下执行pip install -r requirements.txt,启动uvicorn server_api:app --reload --port 8312后,另开终端运行python main.py


http://www.jsqmd.com/news/585176/

相关文章:

  • SAP物料管理避坑指南:删除标记函数这些细节要注意
  • 2026年4月华为云10分钟超简单安装OpenClaw及大模型百炼APIKey流程
  • Linux文件名修改方法大全
  • Qwen3.5-9B新手入门:图文识别+代码生成,一个镜像搞定AI应用
  • 用FreeCAD模拟机械运动:以旋转把手为例,快速检查零件干涉与间隙
  • 从OpenPose到HRNet:2D姿态估计实战选型指南(附COCO数据集性能对比)
  • SpringBoot3项目里,MyBatis-Flex的APT怎么做到零配置自动生成Mapper?
  • 告别单位换算!Allegro中同时显示mil和mm的3种方法横向评测
  • tao-8k效果实测:8192长度文本嵌入向量生成惊艳效果展示
  • Pixel Dream Workshop 面试宝典:常见Java面试题在AI项目中的实践
  • 千问3.5-2B快速部署:7860端口默认开放,无需额外nginx反代即可对外提供服务
  • STM32F4 FSMC驱动TFT LCD详解:从正点原子例程到CubeMX配置的迁移心法
  • 2025年大中华区21个主要城市甲级写字楼市场数据
  • 2026年4月云端1分钟零基础部署OpenClaw及大模型百炼APIKey步骤
  • 电吉他手必备:2.4G无线音频模块实战指南(含低延时配置技巧)
  • ChromaDB实战:从零构建嵌入式向量数据库应用
  • Ostrakon-VL 代码辅助新体验:像使用 Codex 一样生成图像处理代码
  • 零代码OCR解决方案:cv_resnet18_ocr-detection快速部署与场景应用
  • Pixel Aurora Engine快速上手:Streamlit像素UI一键部署教程
  • 1940-2025年各省市区县乡镇各月100m高空平均风速及风向角计算结果
  • PlantUML Editor:代码驱动的UML可视化全流程解决方案
  • ZYNQ 7020开发板调试:解决‘Could not find ARM device‘错误的3个关键步骤
  • 数字花园养成:OpenClaw+Gemma-3-12b-it自动化维护个人知识库
  • Wan2.2-I2V-A14B开源镜像部署教程:GPU算力深度优化+FlashAttention-2加速
  • 2026年热门的EPS挤出发泡注入计量泵/青岛液压隔膜计量泵/计量泵/青岛计量泵深度厂家推荐 - 行业平台推荐
  • VirtualBox复制文本到Windows老是多空行?试试这个Ubuntu登录选项切换法
  • YOLO X Layout效果实测:11种文档元素识别,表格图片一网打尽
  • 告别卡顿!用Gnirehtet反向供网,让Spacedesk有线拓展摆脱WiFi依赖
  • Ostrakon-VL-8B构建智能学习系统:自动化作业批改与反馈生成
  • 国内母牛料工厂哪家强?2026年实力分析来袭,东北饲料/犊牛羔羊料/三七乳猪料/开口料/融邦饲料,母牛料产品推荐 - 品牌推荐师