Implementation:Arize ai Phoenix OpenAI Adapter
Overview
The OpenAIAdapter is a concrete implementation of the BaseLLMAdapter abstract class that integrates the OpenAI Chat Completions API (including Azure OpenAI) into the Phoenix evaluator framework. It resides in the phoenix-evals sub-package and provides both synchronous and asynchronous methods for text generation and structured object extraction. The adapter supports structured output (via json_schema response format), tool calling, and an automatic fallback strategy. It is also aware of model-specific constraints such as varying system role semantics across GPT, o1, and o3 model families.
Description
The module defines the OpenAIAdapter class and two supporting functions: identify_openai_client() and get_openai_rate_limit_errors(). Key design characteristics:
- Client identification: Detects OpenAI clients by checking for the
OpenAIClientWrappertype, the"openai"module namespace, or the presence ofchat.completionsinterface. - Dual provider registration: The adapter is registered under both
openaiandazureproviders via separate@register_providerdecorators with distinct client factories but the same rate limit error type. - Sync/async client detection: Inspects class names for
"Async"or usesinspect.iscoroutinefunctiononchat.completions.createto determine the client mode. Enforces correct method usage (sync methods on sync clients, async on async). - Model-aware system role mapping: The
_system_role()method maps system messages to the correct role string based on the model:"system"for GPT models"user"for o1-mini and o1-preview (which do not support system or developer roles)"developer"for o1 and o3 models
- Capability detection:
_supports_structured_output()checks if the model supports JSON schema response format (gpt-4o variants), and_supports_tool_calls()returnsFalsefor o1/o3 reasoning models. - Schema normalization:
_ensure_additional_properties_false()recursively adds"additionalProperties": falseto all object types, as required by OpenAI's structured output API. - Multimodal support: Handles text, image (base64 and URL), and audio content from legacy
MultimodalPromptobjects.
Usage
from openai import OpenAI
from phoenix.evals.llm.adapters.openai.adapter import OpenAIAdapter
# Synchronous usage
client = OpenAI(api_key="sk-...")
adapter = OpenAIAdapter(client=client, model="gpt-4o")
# Text generation
response = adapter.generate_text("What is the capital of France?")
# Structured output (prefers json_schema response format for gpt-4o)
schema = {
"type": "object",
"properties": {
"label": {"type": "string", "enum": ["relevant", "irrelevant"]},
"explanation": {"type": "string"}
},
"required": ["label", "explanation"]
}
result = adapter.generate_object("Classify this text.", schema=schema)
from openai import AsyncOpenAI
# Asynchronous usage
async_client = AsyncOpenAI(api_key="sk-...")
adapter = OpenAIAdapter(client=async_client, model="gpt-4o")
response = await adapter.async_generate_text("Summarize this document.")
result = await adapter.async_generate_object(prompt, schema=schema)
# Azure OpenAI usage (registered under "azure" provider)
from openai import AzureOpenAI
azure_client = AzureOpenAI(
api_key="...",
api_version="2024-02-01",
azure_endpoint="https://my-resource.openai.azure.com/"
)
adapter = OpenAIAdapter(client=azure_client, model="gpt-4o")
Code Reference
I/O Contract
generate_text / async_generate_text
| Direction | Type | Description |
|---|---|---|
| Input | Union[PromptLike, MultimodalPrompt] |
A string prompt, list of message dicts, list of Message TypedDicts, or legacy MultimodalPrompt (with text, image, and audio parts)
|
| Input | **kwargs |
Additional keyword arguments forwarded to client.chat.completions.create()
|
| Output | str |
The choices[0].message.content from the OpenAI response
|
| Raises | ValueError |
If sync method is called on async client (or vice versa), or if content is None
|
| Raises | PhoenixUnsupportedAudioFormat |
If an audio part uses an unsupported format |
generate_object / async_generate_object
| Direction | Type | Description |
|---|---|---|
| Input | Union[PromptLike, MultimodalPrompt] |
A prompt in any supported format |
| Input | Dict[str, Any] |
A JSON schema defining the expected output structure |
| Input | ObjectGenerationMethod |
AUTO (default: prefers structured output for gpt-4o), STRUCTURED_OUTPUT, or TOOL_CALLING
|
| Output | Dict[str, Any] |
Parsed JSON from structured output, or parsed function arguments from tool calls |
| Raises | ValueError |
If the model does not support the requested method, or no tool calls in response |
Usage Examples
Model-Specific System Role Handling
from phoenix.evals.llm.prompts import Message, MessageRole
messages = [
Message(role=MessageRole.SYSTEM, content="You are a classifier."),
Message(role=MessageRole.USER, content="Classify this text."),
]
# For GPT models: system message uses role="system"
adapter_gpt = OpenAIAdapter(client=client, model="gpt-4o")
# Internally: [{"role": "system", ...}, {"role": "user", ...}]
# For o1: system message uses role="developer"
adapter_o1 = OpenAIAdapter(client=client, model="o1")
# Internally: [{"role": "developer", ...}, {"role": "user", ...}]
# For o1-mini: system message uses role="user"
adapter_o1mini = OpenAIAdapter(client=client, model="o1-mini")
# Internally: [{"role": "user", ...}, {"role": "user", ...}]
Capability-Aware Object Generation
# gpt-4o supports both structured output and tool calling
# AUTO mode will prefer structured output
adapter = OpenAIAdapter(client=client, model="gpt-4o")
result = adapter.generate_object(prompt, schema=schema) # Uses json_schema response format
# o1 models do not support tool calling
# AUTO mode will use structured output if available
adapter = OpenAIAdapter(client=client, model="o1")
result = adapter.generate_object(prompt, schema=schema)
Related Pages
- Arize_ai_Phoenix_LLM_Base_Types - Abstract base class
BaseLLMAdapterand core type definitions - Arize_ai_Phoenix_Anthropic_Adapter - Anthropic adapter following the same interface
- Arize_ai_Phoenix_Google_Adapter - Google GenAI adapter following the same interface
- Arize_ai_Phoenix_LiteLLM_Adapter - LiteLLM adapter that also supports OpenAI via model routing
- Arize_ai_Phoenix_LangChain_Adapter - LangChain adapter supporting OpenAI LangChain models
- Arize_ai_Phoenix_LLM_Prompts - Prompt template and message abstraction layer
- Arize_ai_Phoenix_Evals_Rate_Limiters - Rate limiting subsystem integrated via
openai.RateLimitError - Arize_ai_Phoenix_Evals_Executors - Task execution framework that orchestrates adapter calls