☰
自然语言 vs JSON:为什么模型更爱“说话”,而不是“填表”?
2026/10/30 2:46:14 网站建设 项目流程

有人问过这样一个问题:

“为啥非要自创协议而不是沿用 MCP 呢?自然语言是各个模型最通用的语言,语言理解力达标,就能用对格式,从而规避 MCP 时期让模型直接输出 JSON 的不稳定。况且现在模型训练 Function Calling 的方法也证实了自然语言对 JSON 是更优越的。比如 DS,内部的工具表示是 DSML 而不是 JSON。”

这段话里其实藏着四个关键问题,值得逐一拆开:

  1. 自然语言和严格 JSON,哪个更适合模型来表达工具调用?
  2. MCP到底是干什么的?它和 Function Calling 是什么关系?
  3. DeepSeek 为什么用DSML而不是 JSON?
  4. 我们到底该不该"自创协议"?

本文会把这些问题讲清楚,并配上具体示例。


一、先分清两层:模型侧 vs 协议侧

很多人把MCP和Function Calling混为一谈,这是理解偏差的起点。

层级名称解决什么问题典型形式
模型侧Function Calling / Tool Use模型如何表达"我要调用哪个工具、参数是什么"JSON Schema + 模型输出结构化参数
协议侧MCP(Model Context Protocol)工具如何被发现、如何被不同客户端复用、鉴权怎么做JSON-RPC 2.0

一个简单的类比:

  • Function Calling 是"模型说我想点一杯咖啡(大杯、少糖)"。
  • MCP 是"咖啡店的标准菜单系统,任何 App 都能连上去点单,而不用每家 App 都单独对接一次"。

MCP并没有取代模型的 Function Calling,它是在 Function Calling 之上加了一层标准化协议。模型仍然需要决定调用什么,只是工具的定义和执行被抽到了独立的 Server 里。


二、为什么模型直接吐 JSON 会不稳定?

模型是在海量自然语言上预训练的,对自然语言的理解和生成能力远强于严格的结构化格式。

常见失败模式

当要求模型输出严格 JSON 时,经常出现:

  • 多写或少写大括号、引号
  • 字段名幻觉(location写成city)
  • 类型错误(数字写成字符串)
  • 在 JSON 前后夹杂自然语言
  • 长参数时格式崩溃

这些错误在早期 Function Calling 中非常常见,尤其是较小模型或复杂参数场景。

研究证据:Natural Language Tools(NLT)

2025 年有一篇重要论文Natural Language Tools: A Natural Language Approach to Tool Calling In Large Language Agents(arXiv:2510.14453),提出用自然语言替代严格 JSON 做工具选择。

核心做法是把工具选择解耦:

  • 让模型对每个工具回答YES / NO,而不是生成完整 JSON。
  • 工具描述用自然语言。

实验结果(跨 10 个模型、6400 次试验):

  • 准确率从69.1% → 87.5%(+18.4 个百分点)
  • 方差下降约70%
  • Token 消耗降低约31%

后续复现研究(2026)在 14 个模型、8560 次试验中也得到了类似结论:NLT 平均提升 14.9 个百分点,关键错误减少 93%。

结论:对很多模型来说,自然语言描述 + 简单决策比强制生成复杂 JSON 更稳定、更准确。


三、DeepSeek 的选择:DSML

DeepSeek 没有选择让模型直接生成标准 JSON,而是设计了DSML(DeepSeek Markup Language)。

DSML 示例

模型内部生成的工具调用大致长这样:

<|DSML|tool_calls><|DSML|invokename="read_file"><|DSML|parametername="path"string="true">src/app.ts</|DSML|parameter></|DSML|invoke></|DSML|tool_calls>

或者一个更完整的搜索示例:

<|DSML|calls><|DSML|invokename="search"><|DSML|parametername="queries"string="true">小柴胡冲剂 布洛芬 相互作用 一起吃</|DSML|parameter></|DSML|invoke></|DSML|calls>

服务端再转换成标准格式

推理框架 / API Server 会把 DSML 解析成 OpenAI 兼容的tool_calls:

{"tool_calls":[{"type":"function","function":{"name":"read_file","arguments":"{\"path\":\"src/app.ts\"}"}}]}

为什么这样设计?

  • XML 风格的标记对模型来说更容易稳定生成(标签有明确起止)。
  • 参数值直接写在标签之间,避免复杂的 JSON 转义。
  • 服务端负责解析和校验,模型只需"说清楚意图"。

这正是"自然语言(或模型友好格式)优先"的实践体现。


四、标准 Function Calling 示例(对比)

OpenAI / 兼容接口风格

工具定义:

{"type":"function","function":{"name":"get_weather","description":"Get weather of a location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"}},"required":["location"]}}}

模型输出(理想情况):

{"tool_calls":[{"id":"call_abc123","type":"function","function":{"name":"get_weather","arguments":"{\"location\": \"Hangzhou, Zhejiang\"}"}}]}

Claude(Anthropic)风格

工具定义使用input_schema:

{"name":"get_weather","description":"Get the current weather for a given city.","input_schema":{"type":"object","properties":{"city":{"type":"string"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["city"]}}

模型返回的是tool_usecontent block,而不是tool_calls数组。


五、MCP 协议示例(协议层)

MCP 使用JSON-RPC 2.0。下面是典型的工具发现与调用流程。

1. 列出工具(tools/list)

请求:

{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}

响应:

{"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"get_weather","description":"Get current weather information for a location","inputSchema":{"type":"object","properties":{"location":{"type":"string"}},"required":["location"]}}]}}

2. 调用工具(tools/call)

请求:

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_weather","arguments":{"location":"Hangzhou"}}}

响应:

{"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"Current weather in Hangzhou: 24°C, Cloudy"}],"isError":false}}

注意:MCP 客户端拿到工具定义后,仍然是通过模型的 Function Calling 能力把这些工具交给模型,再把模型的决策转成tools/call请求发给 Server。


六、四种思路对比

方案优点缺点适合场景
严格 JSON Function Calling结构清晰、易解析、生态成熟模型容易格式错误,Token 开销大工具少、参数简单、模型强(有严格模式)
DSML / 模型友好标记生成更稳定,模型友好需要专用解析器DeepSeek 等自研模型
Natural Language Tools准确率高、方差小、Token 少参数复杂时表达能力受限工具选择为主、参数简单的场景
MCP工具一次编写、多客户端复用有协议开销,Token 可能更多需要跨应用、跨团队复用工具时

七、实践建议

  1. 模型侧优先考虑"模型友好"

    如果是自研模型或开源模型,可以像 DeepSeek 一样设计更易生成的格式(DSML、XML、甚至自然语言 + 解析),而不是强行让模型当 JSON 生成器。

  2. 协议侧按需选择 MCP

    • 只给自己的产品用 → 直接 Function Calling 就够了。
    • 要给多个客户端(Claude Desktop、Cursor、自己的 Agent)共用工具 → MCP 很有价值。
    • 工具数量非常多时,注意 Token 成本,有人开始转向 CLI-first 方案。
  3. 两者可以共存

    MCP Server 对外暴露标准协议,内部执行时仍然可以用任何模型友好的方式让模型决策。

  4. 生产中建议加一层校验与修复

    即使模型很强,也建议对工具调用结果做 schema 校验、重试或 fallback。


八、总结

自然语言(或模型友好格式)是模型最擅长的表达方式,强制严格 JSON 会带来不必要的不稳定。

DeepSeek 用 DSML、NLT 论文的实验,都在验证这一点。

但 MCP 解决的是另一层问题——工具的标准化发现与复用,它和"模型怎么表达工具调用"并不矛盾。

正确的理解是:

  • 模型怎么说话→ 尽量贴合模型优势(自然语言 / DSML 等)。
  • 工具怎么被连接→ 需要协议层(MCP 或其他方案)来做标准化。

不要把"模型侧的格式选择"和"协议侧的生态标准"混为一谈。两者解决的是不同问题,也都可以根据实际场景灵活选择。

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

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

立即咨询