class OpenAIChatCompletionClient(BaseOpenAIChatCompletionClient, Component[OpenAIClientConfigurationConfigModel]): """Chat completion client for OpenAI hosted models. To use this client, you must install the `openai` extra: .. code-block:: bash pip install "autogen-ext[openai]" You can also use this client for OpenAI-compatible ChatCompletion endpoints. **Using this client for non-OpenAI models is not tested or guaranteed.** For non-OpenAI models, please first take a look at our `community extensions `_ for additional model clients. Args: model (str): Which OpenAI model to use. api_key (optional, str): The API key to use. **Required if 'OPENAI_API_KEY' is not found in the environment variables.** organization (optional, str): The organization ID to use. base_url (optional, str): The base URL to use. **Required if the model is not hosted on OpenAI.** timeout: (optional, float): The timeout for the request in seconds. max_retries (optional, int): The maximum number of retries to attempt. model_info (optional, ModelInfo): The capabilities of the model. **Required if the model name is not a valid OpenAI model.** frequency_penalty (optional, float): logit_bias: (optional, dict[str, int]): max_tokens (optional, int): n (optional, int): presence_penalty (optional, float): response_format (optional, Dict[str, Any]): the format of the response. Possible options are: .. code-block:: text # Text response, this is the default. {"type": "text"} .. code-block:: text # JSON response, make sure to instruct the model to return JSON. {"type": "json_object"} .. code-block:: text # Structured output response, with a pre-defined JSON schema. { "type": "json_schema", "json_schema": { "name": "name of the schema, must be an identifier.", "description": "description for the model.", # You can convert a Pydantic (v2) model to JSON schema # using the `model_json_schema()` method. "schema": "", # Whether to enable strict schema adherence when # generating the output. If set to true, the model will # always follow the exact schema defined in the # `schema` field. Only a subset of JSON Schema is # supported when `strict` is `true`. # To learn more, read # https://platform.openai.com/docs/guides/structured-outputs. "strict": False, # or True }, } It is recommended to use the `json_output` parameter in :meth:`~autogen_ext.models.openai.BaseOpenAIChatCompletionClient.create` or :meth:`~autogen_ext.models.openai.BaseOpenAIChatCompletionClient.create_stream` methods instead of `response_format` for structured output. The `json_output` parameter is more flexible and allows you to specify a Pydantic model class directly. seed (optional, int): stop (optional, str | List[str]): temperature (optional, float): top_p (optional, float): parallel_tool_calls (optional, bool): Whether to allow parallel tool calls. When not set, defaults to server behavior. user (optional, str): default_headers (optional, dict[str, str]): Custom headers; useful for authentication or other custom requirements. add_name_prefixes (optional, bool): Whether to prepend the `source` value to each :class:`~autogen_core.models.UserMessage` content. E.g., "this is content" becomes "Reviewer said: this is content." This can be useful for models that do not support the `name` field in message. Defaults to False. include_name_in_message (optional, bool): Whether to include the `name` field in user message parameters sent to the OpenAI API. Defaults to True. Set to False for model providers that don't support the `name` field (e.g., Groq). stream_options (optional, dict): Additional options for streaming. Currently only `include_usage` is supported. Examples: The following code snippet shows how to use the client with an OpenAI model: .. code-block:: python from autogen_ext.models.openai import OpenAIChatCompletionClient from autogen_core.models import UserMessage openai_client = OpenAIChatCompletionClient( model="gpt-4o-2024-08-06", # api_key="sk-...", # Optional if you have an OPENAI_API_KEY environment variable set. ) result = await openai_client.create([UserMessage(content="What is the capital of France?", source="user")]) # type: ignore print(result) # Close the client when done. # await openai_client.close() To use the client with a non-OpenAI model, you need to provide the base URL of the model and the model info. For example, to use Ollama, you can use the following code snippet: .. code-block:: python from autogen_ext.models.openai import OpenAIChatCompletionClient from autogen_core.models import ModelFamily custom_model_client = OpenAIChatCompletionClient( model="deepseek-r1:1.5b", base_url="http://localhost:11434/v1", api_key="placeholder", model_info={ "vision": False, "function_calling": False, "json_output": False, "family": ModelFamily.R1, "structured_output": True, }, ) # Close the client when done. # await custom_model_client.close() To use streaming mode, you can use the following code snippet: .. code-block:: python import asyncio from autogen_core.models import UserMessage from autogen_ext.models.openai import OpenAIChatCompletionClient async def main() -> None: # Similar for AzureOpenAIChatCompletionClient. model_client = OpenAIChatCompletionClient(model="gpt-4o") # assuming OPENAI_API_KEY is set in the environment. messages = [UserMessage(content="Write a very short story about a dragon.", source="user")] # Create a stream. stream = model_client.create_stream(messages=messages) # Iterate over the stream and print the responses. print("Streamed responses:") async for response in stream: if isinstance(response, str): # A partial response is a string. print(response, flush=True, end="") else: # The last response is a CreateResult object with the complete message. print("\\n\\n------------\\n") print("The complete response:", flush=True) print(response.content, flush=True) # Close the client when done. await model_client.close() asyncio.run(main()) To use structured output as well as function calling, you can use the following code snippet: .. code-block:: python import asyncio from typing import Literal from autogen_core.models import ( AssistantMessage, FunctionExecutionResult, FunctionExecutionResultMessage, SystemMessage, UserMessage, ) from autogen_core.tools import FunctionTool from autogen_ext.models.openai import OpenAIChatCompletionClient from pydantic import BaseModel # Define the structured output format. class AgentResponse(BaseModel): thoughts: str response: Literal["happy", "sad", "neutral"] # Define the function to be called as a tool. def sentiment_analysis(text: str) -> str: \"\"\"Given a text, return the sentiment.\"\"\" return "happy" if "happy" in text else "sad" if "sad" in text else "neutral" # Create a FunctionTool instance with `strict=True`, # which is required for structured output mode. tool = FunctionTool(sentiment_analysis, description="Sentiment Analysis", strict=True) async def main() -> None: # Create an OpenAIChatCompletionClient instance. model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") # Generate a response using the tool. response1 = await model_client.create( messages=[ SystemMessage(content="Analyze input text sentiment using the tool provided."), UserMessage(content="I am happy.", source="user"), ], tools=[tool], ) print(response1.content) # Should be a list of tool calls. # [FunctionCall(name="sentiment_analysis", arguments={"text": "I am happy."}, ...)] assert isinstance(response1.content, list) response2 = await model_client.create( messages=[ SystemMessage(content="Analyze input text sentiment using the tool provided."), UserMessage(content="I am happy.", source="user"), AssistantMessage(content=response1.content, source="assistant"), FunctionExecutionResultMessage( content=[FunctionExecutionResult(content="happy", call_id=response1.content[0].id, is_error=False, name="sentiment_analysis")] ), ], # Use the structured output format. json_output=AgentResponse, ) print(response2.content) # Should be a structured output. # {"thoughts": "The user is happy.", "response": "happy"} # Close the client when done. await model_client.close() asyncio.run(main()) To load the client from a configuration, you can use the `load_component` method: .. code-block:: python from autogen_core.models import ChatCompletionClient config = { "provider": "OpenAIChatCompletionClient", "config": {"model": "gpt-4o", "api_key": "REPLACE_WITH_YOUR_API_KEY"}, } client = ChatCompletionClient.load_component(config) To view the full list of available configuration options, see the :py:class:`OpenAIClientConfigurationConfigModel` class. """ component_type = "model" component_config_schema = OpenAIClientConfigurationConfigModel component_provider_override = "autogen_ext.models.openai.OpenAIChatCompletionClient" def __init__(self, **kwargs: Unpack[OpenAIClientConfiguration]): if "model" not in kwargs: raise ValueError("model is required for OpenAIChatCompletionClient") model_capabilities: Optional[ModelCapabilities] = None # type: ignore self._raw_config: Dict[str, Any] = dict(kwargs).copy() copied_args = dict(kwargs).copy() if "model_capabilities" in kwargs: model_capabilities = kwargs["model_capabilities"] del copied_args["model_capabilities"] model_info: Optional[ModelInfo] = None if "model_info" in kwargs: model_info = kwargs["model_info"] del copied_args["model_info"] add_name_prefixes: bool = False if "add_name_prefixes" in kwargs: add_name_prefixes = kwargs["add_name_prefixes"] include_name_in_message: bool = True if "include_name_in_message" in kwargs: include_name_in_message = kwargs["include_name_in_message"] # Special handling for Gemini model. assert "model" in copied_args and isinstance(copied_args["model"], str) if copied_args["model"].startswith("gemini-"): if "base_url" not in copied_args: copied_args["base_url"] = _model_info.GEMINI_OPENAI_BASE_URL if "api_key" not in copied_args and "GEMINI_API_KEY" in os.environ: copied_args["api_key"] = os.environ["GEMINI_API_KEY"] if copied_args["model"].startswith("claude-"): if "base_url" not in copied_args: copied_args["base_url"] = _model_info.ANTHROPIC_OPENAI_BASE_URL if "api_key" not in copied_args and "ANTHROPIC_API_KEY" in os.environ: copied_args["api_key"] = os.environ["ANTHROPIC_API_KEY"] if copied_args["model"].startswith("Llama-"): if "base_url" not in copied_args: copied_args["base_url"] = _model_info.LLAMA_API_BASE_URL if "api_key" not in copied_args and "LLAMA_API_KEY" in os.environ: copied_args["api_key"] = os.environ["LLAMA_API_KEY"] client = _openai_client_from_config(copied_args) create_args = _create_args_from_config(copied_args) super().__init__( client=client, create_args=create_args, model_capabilities=model_capabilities, model_info=model_info, add_name_prefixes=add_name_prefixes, include_name_in_message=include_name_in_message, ) def __getstate__(self) -> Dict[str, Any]: state = self.__dict__.copy() state["_client"] = None return state def __setstate__(self, state: Dict[str, Any]) -> None: self.__dict__.update(state) self._client = _openai_client_from_config(state["_raw_config"]) def _to_config(self) -> OpenAIClientConfigurationConfigModel: copied_config = self._raw_config.copy() return OpenAIClientConfigurationConfigModel(**copied_config) @classmethod def _from_config(cls, config: OpenAIClientConfigurationConfigModel) -> Self: copied_config = config.model_copy().model_dump(exclude_none=True) # Handle api_key as SecretStr if "api_key" in copied_config and isinstance(config.api_key, SecretStr): copied_config["api_key"] = config.api_key.get_secret_value() return cls(**copied_config)