想象一下,你是一家小公司的负责人,终于招到了一位精力充沛但有点笨拙的AI实习助理。它上知天文下知地理,可你让它查“一杯冰美式多少钱”,它回你一篇三百字的小作文,从咖啡豆产地讲到烘焙工艺,就是没有一个干净的数字。你让它写一份工作总结,它交上来的格式十个人十个样。直到有一天,你发现这位助理其实“认表格不认人话”——只要你在任务说明里把格式写清楚,它就能规规矩矩地填表、排版,一改散漫作风。这份“任务说明”,就是Prompt工程师日常打磨的东西。而今天要学的,是其中最基础也最救命的两类格式控制:JSON和Markdown。前者让AI输出程序能直接读的结构化数据,后者让AI输出排版美观的文档。掌握了它们,AI就从“话痨”变成了“靠谱文书”。
学会格式控制,你就能让大模型输出可靠的结构化数据与规范文档,无论是搭Agent、做数据流水线还是写自动化报告,这一步都是把AI从“能聊天”推向“能干活”的关键门槛。
目录
可视化演示
展示Prompt控制AI输出JSON结构、Markdown格式渲染及Schema校验流程,理解结构化输出核心方法。
本节配有交互动效(进入视口后自动加载,约 3KB)。
JSON结构化输出 Prompt指定JSON格式,模型输出键值对结构化数据 支持嵌套对象、数组和多种数据类型 Prompt → LLM → JSON{key: value} 通过Prompt控制AI输出标准JSON结构,便于程序解析
JSON结构化输出:给助理一张“数据交接表”
你让AI实习助理去查“一杯冰美式多少钱”,它回你一篇热情洋溢的小作文,从咖啡因含量扯到门店排队时长。你哭笑不得,于是拿出一张空表格,在上面写好栏目名:name、price、currency,然后对它说:“把答案填进这张表。”助理立刻安静下来,规规矩矩地填好了一行数据。这张“表”,就是JSON。
JSON的全称是JavaScript Object Notation,它用键值对来组织数据,就像一张只有两列的表格:左栏是“栏目名”(称为键,key),右栏是“填的内容”(称为值,value)。程序之间传递数据时,JSON是最通用的“交接表”——无论是Python、Java还是Go,都能读懂这张表。而大模型恰好也认识它,只要你把表头写在Prompt里。
当你在Prompt中声明“只输出JSON”,并列出需要的字段名和字段类型,AI就会按表格填写。字段名要写在双引号里,字符串值也要加双引号;数字直接裸写;布尔值写true或false;多行数组用方括号括起来。为了让AI填得更准确,可以在Prompt末尾附上一个完整的JSON示例,它模仿示例的能力远超你的想象。
养成“用表格接数据”的习惯后,AI实习助理的散文病就治好了大半。但要注意,表格只有交接数据时才用;如果需要一份给老板看的文档,还有另一套规范等着它——那是下一节的故事。
- 花括号定边界JSON对象由一对花括号包裹,表示“这张交接表从这里开始、到那里结束”。
- 键名用双引号"key"就是表格栏目名,JSON标准规定键名必须用双引号包裹,单引号或裸写都不合法。
- 冒号连接键值冒号把栏目名和内容连接起来,读作“这一栏的值是……”。
- 值类型多样值可以是字符串(加双引号)、数字(裸写)、布尔值、数组、嵌套对象或null空值。
- 逗号分隔条目相邻条目之间用逗号分隔,但最后一条后面绝不能加逗号,否则就是经典的“尾逗号”错误。
Markdown排版控制:助理的“汇报排版规范”
数据交接用表,但你要给老板交一份阅读体验良好的文档,不能又是一张冷冰冰的表。于是你给助理立下规矩:写文档必须用统一的排版规范——一级标题用井号,要点用短横线,代码放进代码块。助理照做后,交上来的文档终于从“手写便签”升级成了“正式公文”。
这套“排版规范”就是Markdown。它是一种轻量级标记语言,用几个简单符号表达文档结构:井号#表示标题,短横线-表示无序列表,数字加点表示有序列表,三个反引号包裹代码块,竖线和短横线组成表格。Markdown本身是给人读的纯文本,经过渲染器处理后会变成漂亮的HTML页面。
在Prompt中控制Markdown,核心是限定元素种类和层级。要明确告诉AI:一级标题用什么、二级标题用什么、列表嵌套时缩进几个空格。尤其要注意代码块的语言标记——如果文档里要展示JSON,应该写```json,渲染器会识别并高亮。AI有时会漏写语言标记或把代码块和引用块混用,这些都需要在Prompt里提前声明。
有了排版规范,助理交上来的报告从“手写便签”升级成“正式公文”。现在你手上有两张神器:JSON负责“数据交接”,Markdown负责“文档排版”。但神器能不能起作用,关键看你写的“任务说明书”——也就是Prompt——是否把这些要求讲清楚了。
- 井号定标题层级#数量表示标题级别,#是一级标题,##是二级标题,最多六级,对应文档的章节结构。
- 列表符号短横线加空格生成无序列表,数字加点生成有序列表,换行后缩进可表示嵌套层级。
- 三反引号围代码连续三个反引号成对出现,中间内容按代码块显示,加上语言名如json可获得语法高亮。
\text{\0\`} + \text{lang} - 表格用竖线与横线竖线分隔单元格,短横线行分隔表头,AI生成的表格常在这里漏掉分隔线。
Prompt指令设计:任务说明书的四要素
你手里有了两张神器,但助理并不知道今天该用哪张。你需要在“任务说明书”——Prompt——里把格式要求写清楚。指令含糊,助理就自由发挥;指令精确,助理就规规矩矩。一个格式控制型Prompt,就像一份给实习助理的流程图:每一步走到哪、用什么格式,全部画好。
一份合格的格式控制Prompt通常由四个部分拼成:格式声明、字段/结构说明、示例、约束。格式声明是第一句话,直接告诉AI“只输出JSON”或“输出Markdown文档”;字段说明列出需要的键名和类型,相当于告诉助理表格有哪些栏目;示例给一个完整样例,AI的模仿能力极强,一个例子胜过十句解释;约束则是禁令清单,比如“不要解释、不要问候、不要用代码块包裹”。
这四个要素中,“声明”最容易被忽略的其实是位置——它要放在Prompt最前面,因为大模型对开头的指令权重更高。“示例”则最容易被偷懒跳过,但它恰恰最能稳定输出格式。另外,“一次只问一事”也很重要:既要求JSON又要求写一段散文,AI往往会顾此失彼。
四要素齐了,AI实习助理就像拿到了流程图,照着走即可。但Prompt写得再好,也不能保证助理100%听话——毕竟它是语言模型,不是编译器。所以拿到输出后,还要有一道“质检验收”的工序。
- 格式声明第一句话就亮明格式,例如“只输出JSON,不要任何解释文字”。
- 字段/结构说明把需要的键名和类型列出来,例如“必须包含name(字符串)、price(数字)”。
- 示例引导给一个完整的JSON或Markdown样例,AI会照着样例会话的格式模仿。
- 约束补充追加“不要用代码块、不要输出多余内容”等禁令,压缩自由发挥的空间。
格式校验方法:质检员的验收流程
助理交表,你不能直接入库——万一是错的呢?质检员要先检查表格:栏目齐不齐、类型对不对、有没有乱涂乱画,通过才放行。这道质检工序在工程上叫“格式校验”,是AI应用落地时绝不能省的一环。
AI输出的原始文本,需要经过一到四道关卡才能变成可靠的数据。第一关是“提取”:从一段混合文本中抠出JSON片段,通常优先寻找```json代码块,找不到就找第一个花括号和最后一个花括号之间的内容。第二关是“语法解析”:用json.loads把JSON字符串变成Python字典,任何语法错误都会当场抛出异常。第三关是“字段检查”:核对必填字段是否存在、类型是否匹配。如果是Markdown文档,还会用正则或渲染器检查标题层级是否合理。
这套流程在工程上叫“抽取-解析-校验”流水线。它的核心思想是:永远不要把AI输出当作可信数据,先把它当作待加工的原料,通过质检后才转正。这也是Prompt工程师与普通API调用者最大的区别——前者有完整的校验意识。
质检这道闸门,挡住了一大批助理的“鬼画符”。但质检员手里的“错题本”也很重要——知道助理常犯哪些错,才能在Prompt里提前打预防针。下一节我们就翻开这本错题本。
- 提取extract从原始文本中抠出JSON片段,优先匹配```json代码块,退而求其次找首尾花括号。
- 语法解析json.loads把JSON字符串解析成Python字典,这一步是质检的核心闸门,语法错误在此暴露。
- 必填字段检查逐个核对required列表中的字段是否存在于字典中,相当于清点表格栏目有没有漏填。
- 输出OK或Error通过则交给业务逻辑使用,失败则触发重试或告警,绝不静默吞掉。
常见错误排查:质检打回的“错题本”
质检员手里有本“错题本”,记录着助理最常犯的几类格式错误。认识这些错误,你就能在Prompt里提前写约束,避免踩坑;即使出错,也能一眼定位、快速修复。大模型输出JSON时的错误,翻来覆去就是那么几类。
第一类是“转义引号”:AI可能输出 {\"name\": \"x\"} 这样的文本,这是因为它在内部对引号做了转义,但你拿到的字符串里残留了反斜杠,json.loads会解析成奇怪的字段名或直接报错。处理办法是先解码或替换多余的反斜杠。第二类是“尾逗号”:对象或数组的最后一项后面多了一个逗号,Python的dict允许这样写,但JSON标准不允许,json.loads会报"Expecting property name enclosed in double quotes"。
第三类是“截断”:模型输出有长度上限,JSON被拦腰斩断,缺少右花括号,导致解析失败。这类错误的处理办法是检测到未闭合时触发重试,或者让模型“继续补全”。第四类是“Markdown污染”:AI不听劝,非要把JSON包在```代码块里,或者在JSON前后加了“好的,这是你要的信息”这类解释文字。对付它,就靠前面说的提取步骤。
有了错题本,助理再犯同类错,你一眼就能认出。但质检和诊断终究是事后补救,有没有办法“事前”就把规矩定死?有——给交接表配一本“填写说明书”,也就是JSON Schema。
- 转义引号字符串值里出现反斜杠转义,需要先解码或修正再解析,否则字段名会带反斜杠。
- 尾逗号最后一项后残留逗号,JSON语法禁止,常用正则删除或要求AI重写。
- 截断右花括号缺失,JSON不完整,检测到未闭合时重试或让模型续写。
\text{\{"name": "冰美式"} \to \text{缺少右括号}} - Markdown污染JSON被代码块或解释文字包裹,提取代码块内容即可解决。
\text{\0\1\2} \to \text{提取}
JSON Schema约束:给交接表配“填写说明书”
光有表格还不够,新来的助理不知道“价格”该填数字还是带¥的字符串、“名称”能不能为空。你干脆写一本“填写说明书”:每一栏的类型、是否必填、取值范围,全部写死。这本说明书,就是JSON Schema。
JSON Schema用JSON自身的语法,去描述另一份JSON的合法结构。它解决三个核心问题:字段类型对不对(price必须是number而不是string)、字段齐不齐(required数组声明哪些键必须有)、取值范围合不合法(enum限定可接受的枚举值)。把它和AI输出结合,就是这个场景下最完整的一道保险。
一个最简单的Schema长这样:type声明根节点必须是对象,properties定义每个键的类型,required列出必填键。用Python的jsonschema库,一条validate调用就能完成全部校验。相比手写字段检查,Schema把规则集中管理,改起来也方便——AI输出的结构越来越复杂时,它尤其好用。
有了Schema这本“填写说明书”,你对助理输出的质量基本可以“高枕无忧”——说明书在手,质量我有。至此,从Prompt设计到输出校验再到异常兜底,一套完整的JSON/Markdown格式控制闭环就成型了。
- type声明根类型整个数据必须是object对象,这是Schema的根节点约束。
- properties定义字段逐键声明每个字段的类型,如name必须是string、price必须是number。
- required必填清单数组中的每个键,输出JSON里都必须存在,否则校验失败。
- 附加约束enum限定取值范围,minItems限定数组长度,additionalProperties可禁止多余字段。
AI 应用场景
商品信息批量抽取入库
阶段:数据预处理 / 结构化抽取
解决的问题:运营每天要手动把商品页面描述录入数据库,费时且容易出错。通过Prompt让AI从商品文本中抽取名称、价格、库存,并以JSON输出,程序自动校验后入库,将人工作业变为全自动流水线。
具体案例:某电商后台接入大模型,输入“新款陶瓷马克杯,容量350ml,售价29.9元,还剩120件”,Prompt要求只输出JSON且必须包含name、price、stock字段,再用Schema校验类型,校验通过后写入数据库。商品入库从5分钟一件降到5秒一件。
自动生成结构化周报
阶段:文档生成
解决的问题:每周写周报要手动排格式,重复劳动严重。用Prompt让AI按Markdown模板生成周报:一级标题、二级标题、要点列表、数据表格,团队直接渲染成网页或复制进文档工具,统一了团队文档风格。
具体案例:某研发团队让AI根据git提交记录生成周报,Prompt指定“使用Markdown,一级标题为'本周进展',二级标题按项目分,每个项目下列3至5条要点”,输出后自动渲染成HTML并发送到企微群,从写报到发布只需五秒。
客服聊天记录结构化存档
阶段:数据清洗 / 归档
解决的问题:客服聊天记录是自由文本,难以统计和分析。通过Prompt抽取对话中的用户意图、商品ID、处理状态,输出JSON并校验,把海量对话沉淀为可查询的结构化数据,为后续BI报表和智能质检打基础。
具体案例:某SaaS客服平台每天处理百万条会话,智能体抽取intent、product_id、resolution三个字段,用Schema校验必填项,失败记录自动进入重试队列。历史聊天数据从“废纸堆”变成了“可检索档案”。
Python 演示
import jsonimport refrom typing import Any, Dict, List, Optional def build_json_prompt(question: str, fields: List[str]) -> str: """构造要求 JSON 输出的 Prompt, 字段名由开发者指定.""" field_str = ", ".join('"%s"' % f for f in fields) return ( "请只输出 JSON 对象, 不要输出任何解释文字, 不要用 Markdown 代码块包裹.\n" "JSON 必须包含以下字段: " + field_str + "\n" "例如: {" + ", ".join('"%s": "示例值"' % f for f in fields) + "}\n" "问题: " + question ) def extract_json(raw: str) -> Optional[str]: """从 AI 回复中提取 JSON 文本: 优先找代码块, 其次找最外层花括号.""" block = re.search(r"
block = re.search(r"```(?:json)?\s*(.+?)```", raw, re.S)这是提取JSON的核心,用正则匹配```json代码块,re.S让点号能匹配换行。json_text = raw[start:end + 1]找不到代码块时退而求其次,取第一个花括号到最后一个花括号之间的文本。data = json.loads(json_text)语法校验的闸门,任何JSON语法问题都会在这里抛出异常。for field in required: if field not in data: raise KeyError(...)逐个核对必填字段,相当于清点表格栏目。prompt = build_json_prompt(...)用“声明+字段+示例”三段式构造Prompt,是格式化输出的第一道防线。counts["h2"] = len(re.findall(r"^## ", md_text, re.M))用正则统计Markdown二级标题数量,检查文档层级是否合理。
常见误区
误区“AI这么聪明,输出JSON一定是合法JSON,直接 json.loads 肯定能成功,如果失败就是AI不行。”
正解AI是语言模型而不是编译器,它输出的JSON完全可能带尾逗号、转义引号、Markdown代码块甚至解释文字。正确的工程习惯是:把AI输出当作“待加工的原料”,先提取、再解析、最后校验。解析失败时优先考虑重试或修复,而不是责怪模型。
为何常见:演示环境里AI经常输出完美JSON,让人误以为这是确定性行为,忽略了LLM本质是概率生成,同样的Prompt每次输出都可能有微小差异。
误区“Python字典就是单引号写的,所以JSON的键也可以写单引号,双引号太麻烦。”
正解JSON是独立于任何编程语言的文本标准,键名和字符串值必须使用双引号。单引号在Python字典里合法,但json.loads解析时会直接报错。写Prompt时也要明确告诉AI“键名用双引号”,否则它可能照抄你在示例里写的Python风格。
为何常见:很多教程从Python入手教JSON,Python的dict字面量和JSON语法长得像,初学者极易混淆两者的规则。
误区“Markdown渲染后看起来都差不多,缩进多一个空格少一个空格没影响。”
正解在列表嵌套、引用块、代码块中,缩进直接决定层级关系。AI输出的列表经常把子项顶到一级,渲染后原有层级全部丢失。Prompt里要明确要求“子项缩进两空格”,校验时也要用正则检查缩进是否符合预期。
为何常见:日常手写Markdown时随意缩进,浏览器渲染不报错,导致大家低估了缩进在结构和可读性上的作用。
误区“Prompt里写了'只输出JSON',AI就不会输出任何别的东西,这是铁律。”
正解Prompt是“期望”而不是“命令”,大模型可能违背指令,尤其在指令与其他要求冲突时。所以工程上必须在输出侧做兜底:提取代码块、json.loads、Schema校验、失败重试。好的Prompt加可靠的校验,双保险才算稳。
为何常见:刚接触Prompt的人把LLM当成普通API,默认指令100%被执行,忽略了概率模型的不确定性本质。
面试题
Q1. JSON中表示字符串值必须使用什么引号?
- A.双引号字符串← 正确答案
- B.单引号字符串
- C.反引号字符串
- D.不加引号裸写
答案:A。JSON标准规定键名和字符串值必须用双引号。单引号是Python字典的写法,反引号是模板字符串的写法,裸写则会被当作数字或变量名,都不是合法的JSON字符串。
Q2. AI把JSON包在```json代码块里还加了问候语,最稳妥的处理方式是?
- A.提示用户手动删除
- B.正则提取代码块内容← 正确答案
- C.放弃JSON改用文本
- D.用eval执行解析
答案:B。AI用代码块包裹JSON是常见行为,正确做法是用正则匹配``json与``之间的内容再解析。手动删除不现实,eval有代码执行风险,放弃JSON则因噎废食。
Q3. 以下哪些是JSON标准中的合法值?
- A."abc"字符串字面量← 正确答案
- B.123数字字面量← 正确答案
- C.undefined未定义值
- D.null空值字面量← 正确答案
答案:ABD。JSON合法值包括字符串、数字、布尔值、数组、对象和null。undefined是JavaScript的专有类型,不属于JSON标准。A是字符串、B是数字、D是null空值,均合法。
Q4. 一个JSON对象的最后一项后面多了一个逗号,会发生什么?
- A.完全合法的写法
- B.解析时直接报错← 正确答案
- C.系统自动将其忽略
- D.变成普通字符串内容
答案:B。这是“尾逗号”错误。Python的dict允许尾逗号,但JSON标准严格禁止,json.loads会抛出"Expecting property name enclosed in double quotes"之类的异常。应通过正则删除或让AI重写。
Q5. 在Markdown文档中展示一段JSON示例,正确的方式是?
- A.使用加粗强调显示
- B.放进json代码块中← 正确答案
- C.用表格单元格存放
- D.放在引用块中展示
答案:B。三反引号加json语言标记的代码块是最佳选择,它能获得语法高亮,且避免JSON的花括号被Markdown解析器误处理。加粗、表格、引用都不适合展示多行代码。
Q6. JSON Schema中required字段数组的作用是什么?
- A.声明哪些字段必修← 正确答案
- B.限定整数还是小数
- C.校验缺字段时报错← 正确答案
- D.改变字段输出顺序
答案:AC。required数组声明必填字段,校验时只要缺一个就报错,这是它的两个核心作用。限定类型要靠properties里的type,required本身不限定类型,更不会改变输出顺序。
Q7. 解析AI输出时遇到{\"name\": \"x\"}这样的内容,最可能的原因是什么?
- A.AI额外添加了解释
- B.文本被Markdown污染
- C.引号转义处理出错← 正确答案
- D.文件使用了错误编码
答案:C。反斜杠出现在引号前,说明AI在生成时对双引号做了转义,或者经过了双层序列化导致反斜杠残留。这不是解释文字、Markdown污染或编码问题,应先解码或替换多余反斜杠再解析。
Q8. 以下哪些方法能提升AI输出JSON的稳定性?
- A.明确声明字段与类型← 正确答案
- B.给出一段完整示例← 正确答案
- C.输出后做解析校验← 正确答案
- D.让模型自由发挥创作
答案:ABC。字段声明让AI知道表格栏目,示例让AI模仿格式,解析校验作为兜底,三者共同提升稳定性。让模型自由发挥是反效果,它会回到散文输出的老路。
Q9. AI输出因长度限制被截断,JSON缺少右花括号,最合适的处理方式是?
- A.直接忽略这个坏样本
- B.检测未闭合后重试← 正确答案
- C.用eval调用执行代码
- D.把JSON改存为纯文本
答案:B。截断是长度限制导致的常见问题,检测到花括号未闭合后触发重试或让模型续写是最稳方案。忽略会丢数据,eval有安全风险,改成纯文本就失去了结构化意义。
Q10. 从AI回复中提取出``json和``之间的内容后,还需要做什么才能得到字典?
- A.直接当成字典对象
- B.调用一次json.loads← 正确答案
- C.替换掉所有换行符
- D.转成YAML格式使用
答案:B。提取出的内容只是JSON字符串,不是Python对象。必须调用json.loads才能把它解析成字典。直接当字典用会类型报错,替换换行符不是必须,转YAML则多此一举。