OpenAI 响应 API
ADK-Rust 为 OpenAI 的 响应 API(/v1/responses 端点)提供了专用客户端,这是 Chat Completions API 的后继方案。响应 API 是使用当前 GPT-5.6 模型的推荐方式,包括其完整的推理强度范围。
概览
┌─────────────────────────────────────────────────────────────────────┐
│ OpenAI Responses API Client │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Endpoint: POST /v1/responses │
│ Client: OpenAIResponsesClient │
│ Config: OpenAIResponsesConfig │
│ Feature: openai │
│ │
│ Capabilities: │
│ • Streaming and non-streaming │
│ • Reasoning summaries │
│ • Tool / function calling │
│ • Multi-turn via previous_response_id │
│ • Built-in tools (web search, file search, code interpreter) │
│ • System instructions │
│ • Model-aware sampling controls and max_output_tokens │
│ • Automatic retry with exponential backoff │
│ │
│ vs Chat Completions (OpenAIClient): │
│ • Stateful conversations (server-side context) │
│ • Native reasoning summaries │
│ • Built-in tool hosting │
│ • Simpler multi-turn (no manual message history) │
│ │
└─────────────────────────────────────────────────────────────────────┘
何时使用哪个客户端
| 功能 | OpenAIClient(聊天补全) | OpenAIResponsesClient(响应) |
|---|---|---|
| 端点 | /v1/chat/completions | /v1/responses |
| 模型 | 兼容聊天的模型 | 当前的 GPT 和推理模型 |
| 推理摘要 | 不可用 | 原生支持 |
| 内置工具 | 不可用 | 网络搜索、文件搜索、代码解释器 |
| 服务端状态 | 手动消息历史记录 | previous_response_id |
| 结构化输出 | response_format | text.format(计划中) |
| 成熟度 | 稳定、广泛采用 | OpenAI 推荐的较新方案 |
在需要带有摘要、内置工具的推理模型,或希望使用 OpenAI 的最新 API 时,请使用 OpenAIResponsesClient。如需与现有 Chat Completions 工作流保持向后兼容,请使用 OpenAIClient。
安装
[dependencies]
adk-rust = { version = "2.1.0", features = ["openai"] }
adk-tool = "2.1.0"
或者直接使用 adk-model:
[dependencies]
adk-model = { version = "2.1.0", features = ["openai"] }
设置您的 API 密钥:
export OPENAI_API_KEY="sk-..."
快速入门
use adk_rust::prelude::*;
use adk_rust::session::{CreateRequest, SessionService};
use adk_rust::futures::StreamExt;
use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};
use std::collections::HashMap;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("OPENAI_API_KEY")?;
// 1. Create the Responses API client
let config = OpenAIResponsesConfig::new(&api_key, "gpt-5.6-terra");
let model = Arc::new(OpenAIResponsesClient::new(config)?);
// 2. Build an agent
let agent = Arc::new(
LlmAgentBuilder::new("assistant")
.instruction("You are a helpful assistant. Be concise.")
.model(model)
.build()?,
);
// 3. Create a session
let sessions: Arc<dyn SessionService> = Arc::new(InMemorySessionService::new());
sessions.create(CreateRequest {
app_name: "my_app".into(),
user_id: "user".into(),
session_id: Some("s1".into()),
state: HashMap::new(),
}).await?;
// 4. Run through the Runner
let runner = Runner::builder()
.app_name("my_app")
.agent(agent)
.session_service(sessions)
.build()?;
let message = Content::new("user").with_text("What is the capital of France?");
let mut stream = runner.run(
adk_rust::UserId::new("user")?,
adk_rust::SessionId::new("s1")?,
message,
).await?;
while let Some(event) = stream.next().await {
let event = event?;
if let Some(content) = &event.llm_response.content {
for part in &content.parts {
if let Some(text) = part.text() {
print!("{text}");
}
}
}
}
println!();
Ok(())
}
配置
基本配置
use adk_model::openai::OpenAIResponsesConfig;
// Minimal — just API key and model
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-luna");
// With organization and project
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
.with_organization("org-...")
.with_project("proj-...");
// Custom base URL (for proxies or compatible APIs)
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
.with_base_url("https://my-proxy.example.com/v1");
推理模型
对于 GPT-5.6 推理模型,请配置推理强度和摘要:
use adk_model::openai::{
OpenAIReasoningEffort, OpenAIResponsesClient,
OpenAIResponsesConfig, ReasoningSummary,
};
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
.with_reasoning_summary(ReasoningSummary::Detailed);
let model = OpenAIResponsesClient::new_with_reasoning_effort(
config,
OpenAIReasoningEffort::Max,
)?;
| 推理力度 | 描述 |
|---|---|
None | 禁用推理以实现最低延迟 |
Minimal | 在支持的模型上使用旧版最小推理 |
Low | 较低推理力度 |
Medium | 平衡推理 |
High | 较高推理力度 |
XHigh | 极高推理力度 |
Max | 支持模型的最大推理能力 |
GPT-5.6 通过 Responses API支持 None、Low、Medium、High、XHigh和 Max。Chat Completions 最多支持 XHigh。
| 推理摘要 | 描述 |
|---|---|
Auto | 模型决定是否包含摘要 |
Concise | 推理的简要摘要 |
Detailed | 详细的推理总结 |
推理摘要会在响应流中显示为 Part::Thinking,这样您就可以向用户展示模型的思考过程。
重试配置
use adk_model::retry::RetryConfig;
let client = OpenAIResponsesClient::new(config)?
.with_retry_config(RetryConfig {
max_retries: 3,
..Default::default()
});
对于速率限制(429)、服务器错误(500/502/503/504)和网络故障,系统会自动重试。
可用模型
| 模型 | 类型 | 描述 |
|---|---|---|
gpt-5.6-terra | 推理 | 面向生产代理的均衡默认选项 |
gpt-5.6-sol | 推理 | 旗舰级推理与编码 |
gpt-5.6-luna | 推理 | 高性价比、高吞吐量工作负载 |
gpt-5.6 | 推理 | 旗舰别名 |
gpt-5 | 推理 | 上一代兼容性 |
gpt-4.1 系列 | 聊天 | 兼容性和显式采样控制 |
o3 / o4-mini | 推理 | 上一代推理兼容性 |
功能
工具调用
函数工具的工作方式与 OpenAIClient 相同——在 agent 上定义工具,runner 负责处理工具调用循环:
use adk_rust::prelude::*;
use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};
use adk_tool::FunctionTool;
use std::sync::Arc;
async fn get_weather(
_ctx: Arc<dyn ToolContext>,
args: serde_json::Value,
) -> Result<serde_json::Value> {
let city = args["city"].as_str().unwrap_or("unknown");
Ok(serde_json::json!({
"city": city,
"temperature_f": 72,
"conditions": "Sunny"
}))
}
let weather_tool = FunctionTool::new(
"get_weather",
"Get current weather for a city. Requires a 'city' string parameter.",
get_weather,
);
let config = OpenAIResponsesConfig::new(&api_key, "gpt-5.6-terra");
let model = Arc::new(OpenAIResponsesClient::new(config)?);
let agent = LlmAgentBuilder::new("weather_agent")
.instruction("Use the get_weather tool to answer weather questions.")
.model(model)
.tool(Arc::new(weather_tool))
.build()?;
多轮对话
Runner 会通过会话自动管理对话历史。每一轮的上下文都会被保留:
// Turn 1
let msg1 = Content::new("user").with_text("My name is Alice.");
let mut stream = runner.run(uid.clone(), sid.clone(), msg1).await?;
// ... consume stream ...
// Turn 2 — the model remembers the previous turn
let msg2 = Content::new("user").with_text("What is my name?");
let mut stream = runner.run(uid.clone(), sid.clone(), msg2).await?;
// Response: "Your name is Alice."
按请求覆盖推理设置
使用 LlmRequest 扩展按请求覆盖推理设置:
use adk_rust::prelude::*;
let agent = LlmAgentBuilder::new("flexible_reasoner")
.model(model)
.generate_content_config(GenerateContentConfig {
extensions: {
let mut ext = std::collections::HashMap::new();
ext.insert("openai".to_string(), serde_json::json!({
"reasoning": {
"effort": "high",
"summary": "detailed"
}
}));
ext
},
..Default::default()
})
.build()?;
内置工具
Responses API 支持由 OpenAI 托管的工具。优先使用 adk-tool 提供的类型化封装:
use adk_tool::OpenAIWebSearchTool;
use std::sync::Arc;
let agent = LlmAgentBuilder::new("researcher")
.model(model)
.tool(Arc::new(OpenAIWebSearchTool::new().preview()))
.build()?;
可用的封装包括 OpenAIWebSearchTool、OpenAIFileSearchTool、OpenAICodeInterpreterTool、OpenAIImageGenerationTool、OpenAIComputerUseTool、OpenAIMcpTool、OpenAILocalShellTool、OpenAIShellTool 和 OpenAIApplyPatchTool。
之前的响应 ID
对于服务器端对话状态(绕过本地会话历史),传入 previous_response_id:
let agent = LlmAgentBuilder::new("stateful")
.model(model)
.generate_content_config(GenerateContentConfig {
extensions: {
let mut ext = std::collections::HashMap::new();
ext.insert("openai".to_string(), serde_json::json!({
"previous_response_id": "resp_abc123"
}));
ext
},
..Default::default()
})
.build()?;
流式传输行为
Responses API 客户端会实时流式传输文本和推理增量:
- 文本增量以带有
partial: true的Part::Text到达 - 推理摘要增量以带有
partial: true的Part::Thinking到达 - 函数调用会从最终的
ResponseCompleted事件中发出,并包含正确的名称和参数 - 最终事件包含带有使用情况元数据和完成原因的
turn_complete: true
这意味着在模型生成内容时,你会看到文本逐个 token 出现,而函数调用则会以可直接执行的完整对象到达。
提供商元数据
每个响应都包含通过 response_id 提供商元数据:
if let Some(meta) = &response.provider_metadata {
let response_id = meta["openai"]["response_id"].as_str();
// Use for previous_response_id, logging, debugging
}
其他元数据可能包括:
encrypted_content— 来自推理模型(用于保留上下文)built_in_tool_outputs— Web 搜索、文件搜索、代码解释器的结果
错误处理
错误会映射到结构化的 AdkError,并使用适当的类别:
| HTTP 状态 | 错误类别 | 可重试 |
|---|---|---|
| 401 | Unauthorized | 否 |
| 429 | RateLimited | 是 |
| 500、502、503、504 | Unavailable | 是 |
| 其他 | Internal | 否 |
match runner.run(uid, sid, message).await {
Ok(stream) => { /* process stream */ }
Err(e) if e.is_retryable() => { /* retry logic */ }
Err(e) if e.is_unauthorized() => { /* check API key */ }
Err(e) => { /* handle other errors */ }
}
后台模式与取消
对于长时间运行的请求,使用 background: true 提交并轮询完成状态:
use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};
let client = OpenAIResponsesClient::new(config)?;
// Submit with background: true via extensions
let mut gen_config = GenerateContentConfig::default();
gen_config.extensions.insert("openai".into(), serde_json::json!({ "background": true }));
// ... send request, extract response_id from provider_metadata ...
// Poll until terminal status
let response = client.poll_response("resp_abc123").await?;
// Check provider_metadata["openai"]["status"]: "completed", "in_progress", "failed", "cancelled"
// Cancel a running background response
let cancelled = client.cancel_response("resp_abc123").await?;
深度研究模型(o3-deep-research、o4-mini-deep-research)会自动启用后台模式,无需显式指定 background: true。
示例
完整的 7 个场景示例位于 examples/openai_responses/:
export OPENAI_API_KEY=sk-...
cargo run --manifest-path examples/openai_responses/Cargo.toml
涵盖的场景:
- 基本的非流式聊天
- 基本的流式聊天
- 带摘要的推理模型(
o4-mini兼容路径) - 使用函数工具进行工具调用
- 多轮对话
- 系统指令
- 温度和生成配置(
gpt-4.1-nano兼容路径)
其他示例
六个独立的示例 crate 演示了 Responses API 的特定功能:
| 示例 | 运行命令 | 功能 |
|---|---|---|
| WebSocket 传输 | cargo run --manifest-path examples/openai_ws_minimal/Cargo.toml | 低延迟持久连接 |
| 后台模式 | cargo run --manifest-path examples/openai_background/Cargo.toml | 提交并轮询工作流 |
| 对话 API | cargo run --manifest-path examples/openai_conversations/Cargo.toml | 服务端管理的多轮对话 |
| 内置工具 | cargo run --manifest-path examples/openai_builtin_tools/Cargo.toml | 图像生成、网页搜索 |
| 深度研究 | cargo run --manifest-path examples/openai_deep_research/Cargo.toml | 自动后台研究 |
| 开放式响应 | cargo run --manifest-path examples/openai_open_responses/Cargo.toml | 与提供商无关的端点 |
相关
- 云端模型提供商 — 所有受支持的 LLM 提供商
- Ollama(本地) — 在本地运行模型
- LlmAgent — 将模型与代理结合使用
- 函数工具 — 向代理添加工具
上一页:← 云端提供商 | 下一页:Ollama(本地) →