OpenAI harmony 响应格式

gpt-oss 模型 在训练时采用了 harmony 响应格式来定义对话结构、生成推理输出和组织函数调用。如果您不是直接使用 gpt-oss,而是通过 API 或像 Ollama 这样的提供商使用,您无需担心此格式,因为您的推理解决方案将处理格式化。如果您正在构建自己的推理解决方案,本指南将引导您完成提示格式。该格式旨在模仿 OpenAI Responses API,因此如果您以前使用过该 API,此格式应该会让您感到熟悉。gpt-oss 不应在不使用 harmony 格式的情况下使用,否则将无法正常工作。

概念

角色

模型处理的每条消息都有一个关联的角色。模型了解三种类型的角色:

| 角色 | 目的 |

角色 目的
system 系统消息用于指定推理过程、知识截止日期和内置工具等元信息
developer 开发人员消息用于提供有关模型指令(通常被认为是“系统提示”)和可用函数工具的信息
user 通常代表模型的输入
assistant 模型的输出,可以是工具调用或消息输出。输出也可能与特定的“通道”相关联,用于标识消息的意图。
tool 代表工具调用输出的消息。特定的工具名称将用作消息内的角色。

当存在指令冲突时,这些角色也代表模型应用的优先级:system > developer > user > assistant > tool

通道

Assistant 消息可以在三个不同的“通道”中输出。这些通道用于区分面向用户的响应和面向内部的消息。

| 通道 | 目的 |

通道 目的
final 标记为 final 通道的消息是 intended to be shown to the end-user 的消息,代表模型响应。
analysis 这些是模型用于其思维链 (CoT) 的消息。重要提示: analysis 通道中的消息不遵循与 final 消息相同的安全标准。避免向最终用户显示这些消息。
commentary 任何函数工具调用通常会在 commentary 通道上触发,而内置工具通常会在 analysis 通道上触发。但是,有时内置工具仍会输出到 commentary。有时模型也会使用此通道来生成调用多个函数的 前导语

Harmony 渲染器库

我们建议尽可能通过 PyPIcrates.io 使用我们的 harmony 渲染器,因为它将自动处理以正确的格式渲染您的消息并将它们转换为模型处理的 token。

下面是一个使用渲染器构建系统提示和简短对话的示例。

from openai_harmony import (
    Author,
    Conversation,
    DeveloperContent,
    HarmonyEncodingName,
    Message,
    Role,
    SystemContent,
    ToolDescription,
    load_harmony_encoding,
    ReasoningEffort
)

encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

system_message = (
    SystemContent.new()
        .with_model_identity(
            "You are ChatGPT, a large language model trained by OpenAI."
        )
        .with_reasoning_effort(ReasoningEffort.HIGH)
        .with_conversation_start_date("2025-06-28")
        .with_knowledge_cutoff("2024-06")
        .with_required_channels(["analysis", "commentary", "final"])
)

developer_message = (
    DeveloperContent.new()
        .with_instructions("Always respond in riddles")
        .with_function_tools(
            [
                ToolDescription.new(
                    "get_location",
                    "Gets the location of the user.",
                ),
                ToolDescription.new(
                    "get_current_weather",
                    "Gets the current weather in the provided location.",
                    parameters={
                        "type": "object",
                        "properties": {
                            "location": {
                                "type": "string",
                                "description": "The city and state, e.g. San Francisco, CA",
                            },
                            "format": {
                                "type": "string",
                                "enum": ["celsius", "fahrenheit"],
                                "default": "celsius",
                            },
                        },
                        "required": ["location"],
                    },
                ),
            ]
        )
)

convo = Conversation.from_messages(
    [
        Message.from_role_and_content(Role.SYSTEM, system_message),
        Message.from_role_and_content(Role.DEVELOPER, developer_message),
        Message.from_role_and_content(Role.USER, "What is the weather in Tokyo?"),
        Message.from_role_and_content(
            Role.ASSISTANT,
            'User asks: "What is the weather in Tokyo?" We need to use get_weather tool.',
        ).with_channel("analysis"),
        Message.from_role_and_content(Role.ASSISTANT, '{"location": "Tokyo"}')
        .with_channel("commentary")
        .with_recipient("functions.get_weather")
        .with_content_type("json"),
        Message.from_author_and_content(
            Author.new(Role.TOOL, "functions.lookup_weather"),
            '{ "temperature": 20, "sunny": true }',
        ).with_recipient("assistant").with_channel("commentary"),
    ]
)

tokens = encoding.render_conversation_for_completion(convo, Role.ASSISTANT)

# After receiving a token response
# Do not pass in the stop token
parsed_response = encoding.parse_messages_from_completion_tokens(new_tokens, Role.ASSISTANT)

此外,openai_harmony 库还包括一个 StreamableParser,用于在模型生成新 token 时进行解析和解码。这可能很有用,例如用于流式输出和在解码过程中处理 Unicode 字符。

from openai_harmony import (
    load_harmony_encoding,
    Role,
    StreamableParser,
    HarmonyEncodingName
)

encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)
stream = StreamableParser(encoding, role=Role.ASSISTANT)

tokens = [
    200005,35644,200008,1844,31064,25,392,4827,382,220,17,659,220,17,16842,12295,81645,
    13,51441,6052,13,200007,200006,173781,200005,17196,200008,17,659,220,17,314,220,19,
    13,200002
]

for token in tokens:
    stream.process(token)
    print("--------------------------------")
    print("current_role", stream.current_role)
    print("current_channel", stream.current_channel)
    print("last_content_delta", stream.last_content_delta)
    print("current_content_type", stream.current_content_type)
    print("current_recipient", stream.current_recipient)
    print("current_content", stream.current_content)

提示格式

如果您选择构建自己的渲染器,您需要遵循以下格式。

特殊 Token

模型使用一组特殊 token 来识别输入的结构。如果您正在使用 tiktoken,这些 token 在 o200k_harmony 编码中进行编码。所有特殊 token 都遵循 <|type|> 格式。

| 特殊 token | 目的 | Token ID |

特殊 token 目的 Token ID
<|start|> 指示 消息 的开始。后面是消息的“header”信息,以 角色 开头