OpenAI - Response API

OpenAI - Response API

OpenAI의 Response API를 LiteLLM에서 사용하는 방법을 알아봐요. 스트리밍, 웹 검색, 이미지 생성, 컴퓨터 사용, MCP 도구, 함수 호출까지 지원해요.

출처: 문서

본문

사용법

LiteLLM Python SDK

비스트리밍

import litellm

# Non-streaming response
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn.",
    max_output_tokens=100
)

print(response)

스트리밍

import litellm

# Streaming response
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn.",
    stream=True
)

for event in response:
    print(event)

웹 검색

import litellm

response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="What is the capital of France?",
    tools=[{
        "type": "web_search_preview",
        "search_context_size": "medium"  # Options: "low", "medium", "high"
    }]
)

print(response)

자세한 내용은 웹 검색 가이드를 참고해요.

스트리밍 이미지 생성

import litellm
import base64

# Streaming image generation with partial images
stream = litellm.responses(
    model="gpt-5.6-terra",  # Use an actual image generation model
    input="Generate a gorgeous image of a river made of white owl feathers",
    stream=True,
    tools=[{"type": "image_generation", "partial_images": 2}],

)

for event in stream:
    if event.type == "response.image_generation_call.partial_image":
        idx = event.partial_image_index
        image_base64 = event.partial_image_b64
        image_bytes = base64.b64decode(image_base64)
        with open(f"river{idx}.png", "wb") as f:
            f.write(image_bytes)

GET a Response

import litellm

# First, create a response
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn.",
    max_output_tokens=100
)

# Get the response ID
response_id = response.id

# Retrieve the response by ID
retrieved_response = litellm.get_responses(
    response_id=response_id
)

print(retrieved_response)

# For async usage
# retrieved_response = await litellm.aget_responses(response_id=response_id)

DELETE a Response

import litellm

# First, create a response
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn.",
    max_output_tokens=100
)

# Get the response ID
response_id = response.id

# Delete the response by ID
delete_response = litellm.delete_responses(
    response_id=response_id
)

print(delete_response)

# For async usage
# delete_response = await litellm.adelete_responses(response_id=response_id)

OpenAI SDK가 있는 LiteLLM Proxy

config.yaml:

model_list:
  - model_name: openai/gpt-5.6-terra
    litellm_params:
      model: openai/gpt-5.6-terra
      api_key: os.environ/OPENAI_API_KEY

Proxy 서버 시작:

litellm --config /path/to/config.yaml

# RUNNING on http://0.0.0.0:4000

비스트리밍

from openai import OpenAI

# Initialize client with your proxy URL
client = OpenAI(
    base_url="http://localhost:4000",  # Your proxy URL
    api_key="your-api-key"             # Your proxy API key
)

# Non-streaming response
response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn."
)

print(response)

스트리밍

from openai import OpenAI

# Initialize client with your proxy URL
client = OpenAI(
    base_url="http://localhost:4000",  # Your proxy URL
    api_key="your-api-key"             # Your proxy API key
)

# Streaming response
response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn.",
    stream=True
)

for event in response:
    print(event)

스트리밍 이미지 생성

from openai import OpenAI
import base64

# Initialize client with your proxy URL
client = OpenAI(api_key="sk-", base_url="http://localhost:4000")

stream = client.responses.create(
    model="gpt-5.6-terra",
    input="Draw a gorgeous image of a river made of white owl feathers, snaking its way through a serene winter landscape",
    stream=True,
    tools=[{"type": "image_generation", "partial_images": 2}],
)

for event in stream:
    print(f"event: {event}")
    if event.type == "response.image_generation_call.partial_image":
        idx = event.partial_image_index
        image_base64 = event.partial_image_b64
        image_bytes = base64.b64decode(image_base64)
        with open(f"river{idx}.png", "wb") as f:
            f.write(image_bytes)

GET/DELETE a Response

from openai import OpenAI

# Initialize client with your proxy URL
client = OpenAI(
    base_url="http://localhost:4000",  # Your proxy URL
    api_key="your-api-key"             # Your proxy API key
)

# First, create a response
response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Tell me a three sentence bedtime story about a unicorn."
)

# Get the response ID
response_id = response.id

# Retrieve the response by ID
retrieved_response = client.responses.retrieve(response_id)
print(retrieved_response)

# Delete the response by ID
delete_response = client.responses.delete(response_id)
print(delete_response)

지원되는 Responses API 파라미터

제공사 지원 파라미터
openai 모든 Responses API 파라미터 지원

재사용 가능한 프롬프트

prompt 파라미터로 저장된 프롬프트 템플릿을 참조하고 선택적으로 변수를 제공해요.

import litellm

response = litellm.responses(
    model="openai/gpt-5.6-terra",
    prompt={
        "id": "pmpt_abc123",
        "version": "2",
        "variables": {
            "customer_name": "Jane Doe",
            "product": "40oz juice box",
        },
    },
)

print(response)

Proxy에서도 같은 파라미터가 지원돼요:

from openai import OpenAI

client = OpenAI(base_url="http://localhost:4000", api_key="your-api-key")

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    prompt={
        "id": "pmpt_abc123",
        "version": "2",
        "variables": {
            "customer_name": "Jane Doe",
            "product": "40oz juice box",
        },
    },
)

print(response)

Computer Use

import litellm

# Non-streaming response
response = litellm.responses(
    model="computer-use-preview",
    tools=[{
        "type": "computer_use_preview",
        "display_width": 1024,
        "display_height": 768,
        "environment": "browser" # other possible values: "mac", "windows", "ubuntu"
    }],
    input=[
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": "Check the latest OpenAI news on bing.com."
            }
            # Optional: include a screenshot of the initial state of the environment
            # {
            #     type: "input_image",
            #     image_url: f"data:image/png;base64,{screenshot_base64}"
            # }
          ]
        }
    ],
    reasoning={
        "summary": "concise",
    },
    truncation="auto"
)

print(response.output)

MCP Tools

import litellm
from typing import Optional

# Configure MCP Tools
MCP_TOOLS = [
    {
        "type": "mcp",
        "server_label": "deepwiki",
        "server_url": "https://mcp.deepwiki.com/mcp",
        "allowed_tools": ["ask_question"]
    }
]

# Step 1: Make initial request - OpenAI will use MCP LIST and return MCP calls for approval
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    tools=MCP_TOOLS,
    input="What transport protocols does the 2025-03-26 version of the MCP spec support?"
)

# Get the MCP approval ID
mcp_approval_id = None
for output in response.output:
    if output.type == "mcp_approval_request":
        mcp_approval_id = output.id
        break

# Step 2: Send followup with approval for the MCP call
response_with_mcp_call = litellm.responses(
    model="openai/gpt-5.6-terra",
    tools=MCP_TOOLS,
    input=[
        {
            "type": "mcp_approval_response",
            "approve": True,
            "approval_request_id": mcp_approval_id
        }
    ],
    previous_response_id=response.id,
)

print(response_with_mcp_call)

Proxy에서도 동일하게 동작해요. config.yaml을 설정하고 OpenAI SDK로 client.responses.create(...)를 호출하면 됩니다.

Verbosity 파라미터

respones API에 verbosity 파라미터가 지원돼요.

from litellm import responses

question = "Write a poem about a boy and his first pet dog."

for verbosity in ["low", "medium", "high"]:
    response = responses(
        model="gpt-5.6-luna",
        input=question,
        text={"verbosity": verbosity}
    )

    print(response)

Proxy:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:4000",  # Your proxy URL
    api_key="your-api-key"             # Your proxy API key
)

question = "Write a poem about a boy and his first pet dog."

for verbosity in ["low", "medium", "high"]:
    response = client.responses.create(
        model="gpt-5.6-luna",
        input=question,
        text={"verbosity": verbosity}
    )

    # Extract text
    output_text = ""
    for item in response.output:
        if hasattr(item, "content"):
            for content in item.content:
                if hasattr(content, "text"):
                    output_text += content.text

    usage = response.usage
    print(verbosity, output_text, usage.output_tokens)

함수 호출

import litellm
import json

tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get current weather for a location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string"}
            },
            "required": ["location"]
        }
    }
]

# Step 1: Request with tools (parallel_tool_calls=True allows multiple calls)
response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input=[{"role": "user", "content": "What's the weather in Paris and Tokyo?"}],
    tools=tools,
    parallel_tool_calls=True, # Defaults = True
)

# Step 2: Execute tool calls and collect results
tool_results = []
for output in response.output:
    if output.type == "function_call":
        result = {"temperature": 15, "condition": "sunny"}  # Your function logic here
        tool_results.append({
            "type": "function_call_output",
            "call_id": output.call_id,
            "output": json.dumps(result)
        })

# Step 3: Send results back
final_response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input=tool_results,
    tools=tools,
)

print(final_response.output)

parallel_tool_calls=False로 설정하면 턴당 0개 또는 1개 도구만 호출되도록 보장할 수 있어요.

도구 검색 및 네임스페이스

도구 검색은 모델이 프롬프트에 모든 도구 정의를 보내는 대신 런타임에 도구를 동적으로 로드하게 해줘요. 함수를 네임스페이스로 그룹화하고 defer_loading: true로 표시하면 모델이 실제로 필요한 스키마만 로드해서 토큰을 절약할 수 있어요.

gpt-5.4 이상이 필요해요. 자세한 내용은 OpenAI Tool Search 문서를 참고해요.

import litellm

# Define namespaces with deferred tools
tools = [
    {"type": "tool_search"},  # Enable tool search
    {
        "type": "namespace",
        "name": "crm",
        "description": "CRM tools for customer management",
        "tools": [
            {
                "type": "function",
                "name": "get_customer",
                "description": "Get customer details by ID",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "customer_id": {"type": "string"}
                    },
                    "required": ["customer_id"],
                },
                "defer_loading": True,
            },
            {
                "type": "function",
                "name": "list_customers",
                "description": "List customers with optional filters",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "status": {"type": "string", "enum": ["active", "inactive"]},
                    },
                },
                "defer_loading": True,
            },
        ],
    },
    {
        "type": "namespace",
        "name": "billing",
        "description": "Billing and invoicing tools",
        "tools": [
            {
                "type": "function",
                "name": "get_invoice",
                "description": "Get an invoice by ID",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "invoice_id": {"type": "string"}
                    },
                    "required": ["invoice_id"],
                },
                "defer_loading": True,
            },
        ],
    },
]

response = litellm.responses(
    model="openai/gpt-5.6-terra",
    input="Look up invoice INV-2024-001 from the billing system",
    tools=tools,
)

# The response contains tool_search_call, tool_search_output, and function_call items
for item in response.output:
    if isinstance(item, dict):
        if item["type"] == "tool_search_call":
            print(f"Searched namespaces: {item['arguments']['paths']}")
        elif item["type"] == "tool_search_output":
            print(f"Loaded {len(item['tools'])} tool(s)")
        elif item["type"] == "function_call":
            print(f"Called: {item.get('namespace', '')}.{item['name']}({item['arguments']})")
    else:
        if item.type == "function_call":
            print(f"Called: {item.namespace}.{item.name}({item.arguments})")

채팅 완성 브리지를 통한 도구 검색

모델에 openai/responses/를 접두사로 붙여 /v1/chat/completions 엔드포인트를 통해서도 도구 검색을 사용할 수 있어요. 요청은 Responses API로 라우팅되지만 표준 채팅 완성 응답을 반환해요.

import litellm

response = litellm.completion(
    model="openai/responses/gpt-5.6-terra",
    messages=[{"role": "user", "content": "Look up invoice INV-2024-001"}],
    tools=[
        {"type": "tool_search"},
        {
            "type": "namespace",
            "name": "billing",
            "description": "Billing and invoicing tools",
            "tools": [
                {
                    "type": "function",
                    "name": "get_invoice",
                    "description": "Get an invoice by ID",
                    "parameters": {
                        "type": "object",
                        "properties": {"invoice_id": {"type": "string"}},
                        "required": ["invoice_id"],
                    },
                    "defer_loading": True,
                },
            ],
        },
    ],
)

# Standard chat completions response
for tool_call in response.choices[0].message.tool_calls:
    print(f"Called: {tool_call.function.name}({tool_call.function.arguments})")
curl http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/responses/gpt-5.6-terra",
    "messages": [{"role": "user", "content": "Look up invoice INV-2024-001"}],
    "tools": [
      {"type": "tool_search"},
      {
        "type": "namespace",
        "name": "billing",
        "description": "Billing and invoicing tools",
        "tools": [
          {
            "type": "function",
            "name": "get_invoice",
            "description": "Get an invoice by ID",
            "parameters": {
              "type": "object",
              "properties": {"invoice_id": {"type": "string"}},
              "required": ["invoice_id"]
            },
            "defer_loading": true
          }
        ]
      }
    ]
  }'

자유 형식 함수 호출

import litellm

response = litellm.responses(
    model="gpt-5.6-luna",
    input="Please use the code_exec tool to calculate the area of a circle with radius equal to the number of 'r's in strawberry",
    text={"format": {"type": "text"}},
    tools=[
        {
            "type": "custom",
            "name": "code_exec",
            "description": "Executes arbitrary python code",
        }
    ]
)
print(response.output)

Context-Free 문법

import litellm
import textwrap

# ----------------- grammars for MS SQL dialect -----------------
mssql_grammar = textwrap.dedent(r"""
            // ---------- Punctuation & operators ----------
            SP: " "
            COMMA: ","
            GT: ">"
            EQ: "="
            SEMI: ";"

            // ---------- Start ----------
            start: "SELECT" SP "TOP" SP NUMBER SP select_list SP "FROM" SP table SP "WHERE" SP amount_filter SP "AND" SP date_filter SP "ORDER" SP "BY" SP sort_cols SEMI

            // ---------- Projections ----------
            select_list: column (COMMA SP column)*
            column: IDENTIFIER

            // ---------- Tables ----------
            table: IDENTIFIER

            // ---------- Filters ----------
            amount_filter: "total_amount" SP GT SP NUMBER
            date_filter: "order_date" SP GT SP DATE

            // ---------- Sorting ----------
            sort_cols: "order_date" SP "DESC"

            // ---------- Terminals ----------
            IDENTIFIER: /[A-Za-z_][A-Za-z0-9_]*/
            NUMBER: /[0-9]+/
            DATE: /'[0-9]{4}-[0-9]{2}-[0-9]{2}'/
    """)

sql_prompt_mssql = (
    "Call the mssql_grammar to generate a query for Microsoft SQL Server that retrieve the "
    "five most recent orders per customer, showing customer_id, order_id, order_date, and total_amount, "
    "where total_amount > 500 and order_date is after '2025-01-01'. "
)

response = litellm.responses(
    model="gpt-5.6-terra",
    input=sql_prompt_mssql,
    text={"format": {"type": "text"}},
    tools=[
        {
            "type": "custom",
            "name": "mssql_grammar",
            "description": "Executes read-only Microsoft SQL Server queries limited to SELECT statements with TOP and basic WHERE/ORDER BY. YOU MUST REASON HEAVILY ABOUT THE QUERY AND MAKE SURE IT OBEYS THE GRAMMAR.",
            "format": {
                "type": "grammar",
                "syntax": "lark",
                "definition": mssql_grammar
            }
        },
    ],
    parallel_tool_calls=False
)

print("--- MS SQL Query ---")
print(response_mssql.output[1].input)

최소 추론 (Minimal Reasoning)

import litellm

response = litellm.responses(
    model="gpt-5.6-terra",
    input= [{ 'role': 'developer', 'content': prompt },
            { 'role': 'user', 'content': 'The food that the restaurant was great! I recommend it to everyone.' }],
    reasoning = {
        "effort": "minimal"
    },
)

print(response)

Proxy에서도 동일:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:4000",  # Your proxy URL
    api_key="your-api-key"             # Your proxy API key
)

prompt = "Classify sentiment of the review as positive|neutral|negative. Return one word only."

response = client.responses.create(
    model="gpt-5.6-terra",
    input= [{ 'role': 'developer', 'content': prompt },
            { 'role': 'user', 'content': 'The food that the restaurant was great! I recommend it to everyone.' }],
    reasoning = {
        "effort": "minimal"
    },
)

# Extract model's text output
output_text = ""
for item in response.output:
    if hasattr(item, "content"):
        for content in item.content:
            if hasattr(content, "text"):
                output_text += content.text

# Token usage details
usage = response.usage

print("--------------------------------")
print("Output:")
print(output_text)

더 알아보기 (Learn more)

  • OpenAI Responses API 문서
  • 웹 검색 가이드