استجابات OpenAI API

يوفّر ADK-Rust عميلاً مخصصًا لـ OpenAI استجابات API (نقطة النهاية /v1/responses) — وهي البديل عن 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_formattext.format (مخطط لها)
مستوى النضجمستقر ومعتمد على نطاق واسعأحدث، ويوصى به من قِبل OpenAI

استخدم OpenAIResponsesClient عندما تحتاج إلى نماذج استدلال مع ملخصات أو أدوات مضمّنة، أو عندما تريد استخدام أحدث API من OpenAI. استخدم OpenAIClient للتوافق مع الإصدارات السابقة لسير عمل Chat Completions الحالي.


التثبيت

[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 ‏None وLow وMedium وHigh وXHigh وMax عبر واجهة API للاستجابات. تدعم إكمالات الدردشة ما يصل إلى 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 — عرّف الأدوات على الوكيل، ويتولى المشغّل حلقة استدعاء الأداة:

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()?;

المحادثات متعددة الأدوار

يدير المشغّل سجل المحادثة تلقائيًا من خلال الجلسات. ويتم الحفاظ على سياق كل دور:

// 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.

معرّف الاستجابة السابقة

للحصول على حالة المحادثة من جانب الخادم (مع تجاوز سجل الجلسة المحلي)، مرّر 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 النص وتغيّرات الاستدلال في الوقت الفعلي:

  • تصل تغيّرات النص باعتبارها Part::Text مع partial: true
  • تصل تغيّرات ملخص الاستدلال باعتبارها Part::Thinking مع partial: true
  • تُصدر استدعاءات الدوال من حدث ResponseCompleted النهائي، مع الأسماء والوسائط الصحيحة
  • يتضمن الحدث النهائي turn_complete: true مع بيانات استخدام وصف سبب الإنهاء

يعني هذا أنك ترى النص يظهر رمزًا تلو الآخر أثناء التوليد، بينما تصل استدعاءات الدوال ككائنات مكتملة جاهزة للتنفيذ.


بيانات تعريف المزوّد

تتضمن كل استجابة بيانات تعريف المزوّد مع 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 — نتائج البحث على الويب، والبحث في الملفات، ومفسّر التعليمات البرمجية

معالجة الأخطاء

تُحوَّل الأخطاء إلى AdkError منظَّمة مع الفئات المناسبة:

HTTP الحالةفئة الخطأقابل لإعادة المحاولة
401Unauthorizedلا
429RateLimitedنعم
500, 502, 503, 504Unavailableنعم
أخرى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

السيناريوهات المشمولة:

  1. محادثة أساسية من دون بث
  2. محادثة أساسية مع البث
  3. نموذج استدلال مع ملخص (مسار التوافق مع o4-mini)
  4. استدعاء الأدوات باستخدام أدوات الدوال
  5. محادثة متعددة الأدوار
  6. تعليمات النظام
  7. إعداد درجة الحرارة وإعدادات التوليد (مسار التوافق مع gpt-4.1-nano)

أمثلة إضافية

توضّح ستة صناديق أمثلة مستقلة ميزات Responses API محددة:

المثالأمر التشغيلالميزة
نقل WebSocketcargo run --manifest-path examples/openai_ws_minimal/Cargo.tomlاتصال دائم منخفض زمن الاستجابة
الوضع في الخلفيةcargo run --manifest-path examples/openai_background/Cargo.tomlسير عمل الإرسال والاستطلاع
المحادثات APIcargo 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نقاط نهاية مستقلة عن المزوّد


السابق: ← موفرو السحابة | التالي: Ollama (محلي) →