diff --git a/openai_agents/model_providers/README.md b/openai_agents/model_providers/README.md index 097dc525..df8f286e 100644 --- a/openai_agents/model_providers/README.md +++ b/openai_agents/model_providers/README.md @@ -18,7 +18,7 @@ Start the LiteLLM provider worker: # Set the required environment variable for your chosen provider export ANTHROPIC_API_KEY="your_anthropic_api_key" # For Anthropic -uv run openai_agents/model_providers/run_worker_litellm_provider.py +uv run openai_agents/model_providers/run_litellm_provider_worker.py ``` Then run the example in a separate terminal: @@ -30,7 +30,36 @@ The example uses Anthropic Claude by default but can be modified to use other Li Find more LiteLLM providers at: https://docs.litellm.ai/docs/providers -## Not Yet Implemented +### Extra + +#### GPT-OSS with Ollama + +This example demonstrates tool calling using the gpt-oss reasoning model with a local Ollama server. +Running this example requires sufficiently powerful hardware (and involves a 14 GB model download. +It is adapted from the [OpenAI Cookbook example](https://cookbook.openai.com/articles/gpt-oss/run-locally-ollama#agents-sdk-integration). + + +Make sure you have [Ollama](https://ollama.com/) installed: +```bash +ollama serve +``` + +Download the `gpt-oss` model: +```bash +ollama pull gpt-oss:20b +``` + +Start the gpt-oss worker: +```bash +uv run openai_agents/model_providers/run_gpt_oss_worker.py +``` + +Then run the example in a separate terminal: +```bash +uv run openai_agents/model_providers/run_gpt_oss_workflow.py +``` + +### Not Yet Implemented - **Custom Example Agent** - Custom OpenAI client integration - **Custom Example Global** - Global default client configuration diff --git a/openai_agents/model_providers/run_gpt_oss_worker.py b/openai_agents/model_providers/run_gpt_oss_worker.py new file mode 100644 index 00000000..88c85fca --- /dev/null +++ b/openai_agents/model_providers/run_gpt_oss_worker.py @@ -0,0 +1,58 @@ +import asyncio +import logging +from datetime import timedelta +from typing import Optional + +from agents import Model, ModelProvider, OpenAIChatCompletionsModel +from openai import AsyncOpenAI +from temporalio.client import Client +from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin +from temporalio.worker import Worker + +from openai_agents.model_providers.workflows.gpt_oss_workflow import GptOssWorkflow + +ollama_client = AsyncOpenAI( + base_url="http://localhost:11434/v1", # Local Ollama API endpoint + api_key="ollama", # Ignored by Ollama +) + + +class CustomModelProvider(ModelProvider): + def get_model(self, model_name: Optional[str]) -> Model: + model = OpenAIChatCompletionsModel( + model=model_name if model_name else "gpt-oss:20b", + openai_client=ollama_client, + ) + return model + + +async def main(): + # Configure logging to show workflow debug messages + logging.basicConfig(level=logging.WARNING) + logging.getLogger("temporalio.workflow").setLevel(logging.DEBUG) + + # Create client connected to server at the given address + client = await Client.connect( + "localhost:7233", + plugins=[ + OpenAIAgentsPlugin( + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30) + ), + model_provider=CustomModelProvider(), + ), + ], + ) + + worker = Worker( + client, + task_queue="openai-agents-model-providers-task-queue", + workflows=[ + GptOssWorkflow, + ], + ) + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/openai_agents/model_providers/run_gpt_oss_workflow.py b/openai_agents/model_providers/run_gpt_oss_workflow.py new file mode 100644 index 00000000..35df5979 --- /dev/null +++ b/openai_agents/model_providers/run_gpt_oss_workflow.py @@ -0,0 +1,27 @@ +import asyncio + +from temporalio.client import Client +from temporalio.contrib.openai_agents import OpenAIAgentsPlugin + +from openai_agents.model_providers.workflows.gpt_oss_workflow import GptOssWorkflow + + +async def main(): + client = await Client.connect( + "localhost:7233", + plugins=[ + OpenAIAgentsPlugin(), + ], + ) + + result = await client.execute_workflow( + GptOssWorkflow.run, + "What's the weather in Tokyo?", + id="litellm-gpt-oss-workflow-id", + task_queue="openai-agents-model-providers-task-queue", + ) + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/openai_agents/model_providers/run_worker_litellm_provider.py b/openai_agents/model_providers/run_litellm_provider_worker.py similarity index 100% rename from openai_agents/model_providers/run_worker_litellm_provider.py rename to openai_agents/model_providers/run_litellm_provider_worker.py diff --git a/openai_agents/model_providers/workflows/gpt_oss_workflow.py b/openai_agents/model_providers/workflows/gpt_oss_workflow.py new file mode 100644 index 00000000..d7ed8021 --- /dev/null +++ b/openai_agents/model_providers/workflows/gpt_oss_workflow.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +from agents import Agent, Runner, function_tool, set_tracing_disabled +from temporalio import workflow + + +@workflow.defn +class GptOssWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + set_tracing_disabled(disabled=True) + + @function_tool + def get_weather(city: str): + workflow.logger.debug(f"Getting weather for {city}") + return f"The weather in {city} is sunny." + + agent = Agent( + name="Assistant", + instructions="You only respond in haikus. When asked about the weather always use the tool to get the current weather..", + model="gpt-oss:20b", + tools=[get_weather], + ) + + result = await Runner.run(agent, prompt) + return result.final_output