AI模型新范式!OpenAI Harmony格式革新,推理提速、编码精简近30%!

OpenAI近期推出了其全新的Harmony格式,并将其应用于gpt-oss系列模型。这一新格式在推理结构和工具调用方面,与我们此前在Qwen3等模型中常用的ChatML格式展现出截然不同的范式。对于从事推理模型开发或构建推理基础设施的专业人士而言,深入理解这两种格式的差异至关重要。新媒网跨境了解到,本文将对ChatML与Harmony格式进行深度对比分析,旨在阐明其中的变革与深远影响。
ChatML:开放模型领域的“经典”对话结构
ChatML(Chat Markup Language,聊天标记语言)是许多开源模型,尤其是Qwen系列模型,长期以来所采用的主流格式。它本质上是一种受XML启发的会话结构化方式,其发展源于清晰区分会话不同组成部分的需求。
ChatML格式的关键特点包括:
- 标记边界清晰:它采用
<|im_start|>和<|im_end|>等特殊令牌来明确标记消息的起始与结束,确保了信息分隔的明确性。 - 角色分明:结构基于明确的角色设定,如
system(系统)、user(用户)和assistant(助手),这有助于模型理解消息的发送者和预期接收者。 - 思考逻辑内嵌:模型在进行内部思考或推理时,通常会将其内容封装在
<think>...</think>块中,使得推理过程与最终输出能够在一个消息中呈现。 - 工具定义与调用:工具定义和其调用方式采用XML风格的标签进行封装,提供了一种结构化的方式来描述和执行外部功能。
- 成熟且经过验证:作为一种经过广泛实践的格式,ChatML在多个模型和应用场景中得到了验证,其稳定性与可用性已获认可。
可以将ChatML视为一种“经典”方法,其特点是直观、类似XML的结构,并侧重于信息的清晰表达。
Harmony:OpenAI的创新响应格式
Harmony是OpenAI专为gpt-oss系列模型设计的全新响应格式。它不仅仅是一种简单的提示格式,更是对模型如何构造输出的全面革新,尤其体现在处理复杂推理和工具使用场景上。
Harmony格式的核心创新包括:
- 多通道架构:消息可以被标记为
analysis(分析/推理)、commentary(评论/工具前言)或final(最终/面向用户),这使得不同类型的信息流能够独立管理。 - 严格的角色层级:引入了
system > developer > user > assistant > tool的角色优先级体系,用于更精细地处理指令冲突和消息路由。 - 消息路由机制:通过
to=语法,明确指定消息在不同组件之间的传递方向,增强了交互的可追溯性与控制力。 - TypeScript风格的工具定义:相较于传统的JSON Schema,这种定义方式更具表达力和简洁性,也更符合现代开发者的习惯。
- 通道级安全标准:不同通道可以应用不同的安全过滤标准,例如,
analysis通道的推理内容可能不受像final通道那样的严格安全审查,这为模型的内部工作流程提供了更大的灵活性。
Harmony将模型的输出视为一个多线程的对话过程,其中不同类型的内容通过不同的通道流动,极大地提升了复杂任务处理的精细度。
TypeScript风格语法:为何意义重大?
Harmony最引人注目的设计选择之一,便是采用TypeScript风格的工具定义,而非传统的JSON Schema。这并非简单的语法调整,其背后蕴含着扎实的逻辑考量。
代码化定义的优势
近期关于代码代理的研究表明,以代码形式表达操作具有多项优势:
- 极致简洁:代码动作通常比JSON格式精简约30%,有效减少了冗余信息。
- 并行处理能力:当需要并行处理多组操作时,例如4个并行流,每个流包含5个动作,若使用JSON可能需要处理20个独立的JSON块;而采用代码,则可以是一个统一的表达式,大大简化了管理。
- 变量管理便捷:能够轻松地存储和引用操作结果,例如
rock_image = generate_image("rock"),提高了推理过程的连贯性。 - 日志可读性增强:代理的运行日志变得更加清晰易懂,便于开发人员进行调试和追踪。
- LLM原生友好:大型语言模型在训练数据中包含了大量代码,因此它们对代码风格的理解和生成更为流畅。
工具定义对比:ChatML vs. Harmony
ChatML(基于JSON Schema):
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}
Harmony(TypeScript风格):
namespace functions {
// Get weather for a city
type get_weather = (_: {
city: string,
unit?: "celsius" | "fahrenheit", // default: celsius
}) => any;
}
显而易见,TypeScript版本的定义不仅更为简洁,也更符合开发者的编程习惯,并且由于其与大型语言模型训练数据的契合度更高,模型在处理此类定义时能够表现出更好的流畅性。
实际案例深度解析
接下来,通过一系列实际应用场景,新媒网跨境将对比这两种格式在处理从简单对话到复杂多步骤推理与工具调用时的具体表现。
1. 基础对话(无思考过程)
最简单的情况,仅是提出一个问题,不涉及任何推理步骤。
ChatML (Qwen3)
<|im_start|>user
What's the capital of France?<|im_end|>
<|im_start|>assistant
<think>
</think>
The capital of France is Paris.<|im_end|>

OpenAI Harmony
<|start|>user<|message|>What's the capital of France?<|end|>
<|start|>assistant<|channel|>final<|message|>The capital of France is Paris.<|return|>

异同分析: 即使在无需思考的场景中,Qwen3的ChatML格式仍会包含空的<think></think>标签,作为一种结构性提示。而Harmony则更为直接,它会立即跳转到final通道,用于输出面向用户的最终内容。这体现了Harmony在信息流管理上的精简与直接。
2. 带有思考过程的对话
在这一场景中,两种格式在处理内部推理上的哲学差异变得尤为清晰。
ChatML (Qwen3)
<|im_start|>user
If I have 3 apples and buy 5 more, then give away 2, how many do I have?<|im_end|>
<|im_start|>assistant
<think>
Starting with 3 apples
Adding 5 more: 3 + 5 = 8
Giving away 2: 8 - 2 = 6
So the final answer is 6 apples.
</think>
You would have 6 apples. Here's the breakdown: You start with 3 apples, buy 5 more (3 + 5 = 8), then give away 2 (8 - 2 = 6).<|im_end|>

OpenAI Harmony
<|start|>user<|message|>If I have 3 apples and buy 5 more, then give away 2, how many do I have?<|end|>
<|start|>assistant<|channel|>analysis<|message|>User starts with 3 apples. Buys 5 more: 3 + 5 = 8. Gives away 2: 8 - 2 = 6. Final count is 6 apples.<|end|>
<|start|>assistant<|channel|>final<|message|>You would have 6 apples. Here's the breakdown: You start with 3 apples, buy 5 more (3 + 5 = 8), then give away 2 (8 - 2 = 6).<|return|>

异同分析: ChatML将所有内容,包括内部思考,都整合在一个消息中。而Harmony则将推理过程(通过analysis通道)与最终答案(通过final通道)明确地分离为独立的消息。Harmony的这种分离式处理,使得从面向用户的内容中程序化地过滤出内部推理过程变得更为简便,有助于实现更精细化的内容管理。
3. 带有思考过程的多轮对话
多轮对话场景能够清晰地揭示每种格式如何管理会话历史。
ChatML (Qwen3)
<|im_start|>user
What's 15% of 80?<|im_end|>
<|im_start|>assistant
15% of 80 is 12. To calculate: 80 × 0.15 = 12<|im_end|>
<|im_start|>user
Now add 25 to that result<|im_end|>
<|im_start|>assistant
<think>
The previous result was 12.
Adding 25: 12 + 25 = 37
</think>
Adding 25 to 12 gives us 37.<|im_end|>

值得注意的是,Qwen3会移除先前轮次中的思考内容,以节省令牌消耗。
OpenAI Harmony
<|start|>user<|message|>What's 15% of 80?<|end|>
<|start|>assistant<|channel|>analysis<|message|>Calculate 15% of 80: 80 × 0.15 = 12<|end|>
<|start|>assistant<|channel|>final<|message|>15% of 80 is 12.<|return|>
<|start|>user<|message|>Now add 25 to that result<|end|>
<|start|>assistant<|channel|>analysis<|message|>Previous result was 12. Adding 25: 12 + 25 = 37<|end|>
<|start|>assistant<|channel|>final<|message|>Adding 25 to 12 gives us 37.<|return|>

历史管理对比: 两种格式都会对历史推理进行剪枝,以优化性能或节省资源。然而,Harmony的通道系统使得这种剪枝和内容管理变得更加显式和可控。通过通道,开发者可以更精确地决定哪些历史信息需要保留,哪些可以去除。
4. 函数调用
在处理工具(函数)调用方面,两种格式的表现差异显著。
ChatML (Qwen3)
<|im_start|>system
# Tools
You may call one or more functions to assist with the user query.
<tools>
{"type": "function", "function": {"name": "get_weather", "description": "Get weather for a city", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}
</tools>
For each function call, return a json object within <tool_call></tool_call> XML tags.<|im_end|>
<|im_start|>user
What's the weather in Tokyo?<|im_end|>
<|im_start|>assistant
<think>
User wants Tokyo weather. Need to call get_weather function.
</think>
I'll check the current weather in Tokyo for you.
<tool_call>
{"name": "get_weather", "arguments": {"city": "Tokyo", "unit": "celsius"}}
</tool_call><|im_end|>
<|im_start|>user
<tool_response>
{"temperature": 22, "condition": "partly cloudy", "humidity": 65}
</tool_response><|im_end|>
<|im_start|>assistant
The current weather in Tokyo is 22°C with partly cloudy skies and 65% humidity.<|im_end|>

OpenAI Harmony
<|start|>developer<|message|># Tools
## functions
namespace functions {
// Get weather for a city
type get_weather = (_: {
city: string,
unit?: "celsius" | "fahrenheit", // default: celsius
}) => any;
} // namespace functions<|end|>
<|start|>user<|message|>What's the weather in Tokyo?<|end|>
<|start|>assistant<|channel|>commentary<|message|>I'll check the current weather in Tokyo for you.<|end|>
<|start|>assistant<|channel|>commentary to=functions.get_weather<|constrain|>json<|message|>{"city": "Tokyo", "unit": "celsius"}<|call|>
<|start|>functions.get_weather to=assistant<|channel|>commentary<|message|>{"temperature": 22, "condition": "partly cloudy", "humidity": 65}<|end|>
<|start|>assistant<|channel|>final<|message|>The current weather in Tokyo is 22°C with partly cloudy skies and 65% humidity.<|return|>

关键差异点:
- 工具定义方式:ChatML采用传统的JSON Schema来定义工具,而Harmony则使用了更具现代感的TypeScript风格类型定义。
- 工具响应处理:ChatML将工具响应封装为用户消息的一部分进行处理;Harmony则引入了一个专门的工具角色(
functions.get_weather to=assistant),使得工具交互更加明确。 - 消息路由清晰度:Harmony的
to=语法明确指示了消息在不同组件之间的流向,清晰地展示了从助手到工具再到助手的完整交互流程。 - 通道分离:Harmony将工具交互过程(通过
commentary通道)与最终答案(通过final通道)区分开来,这有助于更细致地管理用户可见的信息和模型的内部操作。
5. 链式思考的函数调用
在处理需要多步骤思考和连续工具调用的复杂场景时,这两种架构的差异得到了充分展现。
ChatML (Qwen3)
<|im_start|>system
# Tools
<tools>
{"type": "function", "function": {"name": "get_weather", "description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}
{"type": "function", "function": {"name": "get_flight_status", "description": "Check flight status", "parameters": {"type": "object", "properties": {"flight_number": {"type": "string"}}}}}
</tools><|im_end|>
<|im_start|>user
Should I pack an umbrella for my UA902 flight to Tokyo?<|im_end|>
<|im_start|>assistant
<think>
User is asking about packing an umbrella for flight UA902 to Tokyo.
I need to:
1. Check the flight status to confirm it's going to Tokyo
2. Check Tokyo's weather to see if rain is expected
Let me start with the flight status.
</think>
I'll help you decide if you need an umbrella. Let me check your flight details and the weather in Tokyo.
<tool_call>
{"name": "get_flight_status", "arguments": {"flight_number": "UA902"}}
</tool_call><|im_end|>
<|im_start|>user
<tool_response>
{"flight": "UA902", "destination": "Tokyo (NRT)", "status": "On time", "departure": "14:30"}
</tool_response><|im_end|>
<|im_start|>assistant
<think>
Flight confirmed to Tokyo, departing at 14:30. Now checking weather.
</think>
<tool_call>
{"name": "get_weather", "arguments": {"city": "Tokyo"}}
</tool_call><|im_end|>
<|im_start|>user
<tool_response>
{"temperature": 18, "condition": "rainy", "precipitation": "80%"}
</tool_response><|im_end|>
<|im_start|>assistant
<think>
Tokyo weather shows rainy conditions with 80% precipitation. Definitely need an umbrella.
</think>
Yes, you should definitely pack an umbrella! Your UA902 flight to Tokyo is on time (departing at 14:30), and Tokyo is currently experiencing rainy weather with an 80% chance of precipitation. Better to be prepared! ☔<|im_end|>

OpenAI Harmony
<|start|>developer<|message|># Tools
## functions
namespace functions {
type get_weather = (_: {city: string}) => any;
type get_flight_status = (_: {flight_number: string}) => any;
} // namespace functions<|end|>
<|start|>user<|message|>Should I pack an umbrella for my UA902 flight to Tokyo?<|end|>
<|start|>assistant<|channel|>analysis<|message|>User asking about packing umbrella for UA902 to Tokyo. Need to: 1) Verify flight destination 2) Check Tokyo weather. Starting with flight status.<|end|>
<|start|>assistant<|channel|>commentary<|message|>I'll help you decide if you need an umbrella. Let me check your flight details and the weather in Tokyo.<|end|>
<|start|>assistant<|channel|>commentary to=functions.get_flight_status<|constrain|>json<|message|>{"flight_number": "UA902"}<|call|>
<|start|>functions.get_flight_status to=assistant<|channel|>commentary<|message|>{"flight": "UA902", "destination": "Tokyo (NRT)", "status": "On time", "departure": "14:30"}<|end|>
<|start|>assistant<|channel|>analysis<|message|>Flight confirmed to Tokyo, on time at 14:30. Now checking weather conditions.<|end|>
<|start|>assistant<|channel|>commentary to=functions.get_weather<|constrain|>json<|message|>{"city": "Tokyo"}<|call|>
<|start|>functions.get_weather to=assistant<|channel|>commentary<|message|>{"temperature": 18, "condition": "rainy", "precipitation": "80%"}<|end|>
<|start|>assistant<|channel|>analysis<|message|>Tokyo has rainy conditions with 80% precipitation. Clear recommendation to pack umbrella.<|end|>
<|start|>assistant<|channel|>final<|message|>Yes, you should definitely pack an umbrella! Your UA902 flight to Tokyo is on time (departing at 14:30), and Tokyo is currently experiencing rainy weather with an 80% chance of precipitation. Better to be prepared! ☔<|return|>

复杂场景下的表现:
- ChatML:在一个对话轮次中,ChatML能够在多次工具调用之间保留并展现模型的思考过程,将内部推理与工具调用紧密结合。
- Harmony:Harmony则通过独立的
analysis消息,明确追踪每一个推理步骤,使得模型的内部决策路径更加清晰、可追溯。其commentary通道还可以在执行工具之前,包含面向用户的“前言”或解释。 - 执行轨迹:Harmony的消息路由机制(
to=)在多步交互中创建了清晰的执行轨迹,极大地提升了复杂代理行为的可调试性和可理解性。
对生态系统的深远影响
Harmony格式的引入,标志着我们对模型输出结构化方式的认知迈向了新的阶段,其影响体现在以下几个方面:
- 通道级安全标准:为不同信息通道设置差异化的安全标准,对于需要进行复杂推理但同时需要确保用户输出内容合规性的模型而言,无疑是一项颠覆性的变革。
- 可观测性显著提升:明确的消息路由和多通道设计,使得开发人员能够更便捷地调试和理解复杂代理的行为,从而优化模型表现。
- 代码优先的工具定义:TypeScript风格的工具定义有望成为新的行业标准,这不仅因为其简洁性,更在于它与现代软件开发工作流的高度契合。
- 结构化推理能力:在格式层面将模型的思考过程与最终输出分离,而非仅仅依赖于约定俗成的做法,这为构建更健壮、更可控的智能体提供了坚实的基础。
核心要点回顾
总而言之,ChatML作为一种成熟且被广泛支持的格式,以其简洁直观的特点在开放模型生态中占据一席之地。而Harmony则引入了通道、消息路由等一系列强大且创新的概念。两种格式虽然都能处理推理和工具调用,但其背后的设计理念和实现路径截然不同。Harmony的TypeScript风格工具定义更加简洁,对开发者也更为友好,其通道系统则能实现对用户可见内容的细粒度控制。
新媒网跨境获悉,理解这两种格式的运作机制对于当前快速发展的AI生态系统至关重要。尽管我们无法直接选择模型所采用的格式(除非参与基础模型的训练),但深入掌握其工作原理,有助于我们构建更高效的推理基础设施,并最大限度地发挥这些强大推理模型的能力。
新媒网(公号: 新媒网跨境发布),是一个专业的跨境电商、游戏、支付、贸易和广告社区平台,为百万跨境人传递最新的海外淘金精准资讯情报。
本文来源:新媒网 https://nmedialink.com/posts/openai-harmony-format-30-simpler-code.html


粤公网安备 44011302004783号 











