From f26cc69bc224eb32e45384940cc3a2f47fda16f1 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Sun, 5 Apr 2026 07:52:18 -0700 Subject: [PATCH 1/3] Upgrade to Responses API --- .devcontainer/github/devcontainer.json | 32 ---- .env.sample | 6 +- .env.sample.github | 3 - AGENTS.md | 57 ++----- README.md | 33 +--- chained_calls.py | 29 ++-- chat.py | 15 +- chat_async.py | 14 +- chat_history.py | 14 +- chat_history_stream.py | 19 +-- chat_safety.py | 14 +- chat_stream.py | 20 ++- few_shot_examples.py | 15 +- function_calling_basic.py | 52 +++---- function_calling_call.py | 55 ++++--- function_calling_errors.py | 95 +++++------- function_calling_extended.py | 61 ++++---- function_calling_fewshots.py | 140 +++++++---------- function_calling_parallel.py | 91 ++++++----- function_calling_while_loop.py | 99 ++++++------ infra/main.bicep | 8 +- infra/write_dot_env.ps1 | 3 +- infra/write_dot_env.sh | 3 +- prompt_engineering.py | 15 +- rag_csv.py | 15 +- rag_documents_flow.py | 15 +- rag_documents_hybrid.py | 15 +- rag_documents_ingestion.py | 6 +- rag_multiturn.py | 12 +- rag_queryrewrite.py | 19 +-- reasoning.py | 23 +-- retrieval_augmented_generation.py | 15 +- spanish/README.md | 23 +-- spanish/chained_calls.py | 29 ++-- spanish/chat.py | 15 +- spanish/chat_async.py | 14 +- spanish/chat_history.py | 14 +- spanish/chat_history_stream.py | 19 +-- spanish/chat_safety.py | 14 +- spanish/chat_stream.py | 20 ++- spanish/few_shot_examples.py | 15 +- spanish/function_calling_basic.py | 52 +++---- spanish/function_calling_call.py | 55 ++++--- spanish/function_calling_errors.py | 97 ++++++------ spanish/function_calling_extended.py | 61 ++++---- spanish/function_calling_fewshots.py | 142 +++++++----------- spanish/function_calling_parallel.py | 91 ++++++----- spanish/function_calling_while_loop.py | 80 ++++------ spanish/prompt_engineering.py | 15 +- spanish/rag_csv.py | 15 +- spanish/rag_documents_flow.py | 15 +- spanish/rag_documents_hybrid.py | 15 +- spanish/rag_documents_ingestion.py | 6 +- spanish/rag_multiturn.py | 12 +- spanish/rag_queryrewrite.py | 19 +-- spanish/retrieval_augmented_generation.py | 15 +- spanish/structured_outputs_basic.py | 24 ++- spanish/structured_outputs_description.py | 24 ++- spanish/structured_outputs_enum.py | 24 ++- .../structured_outputs_function_calling.py | 35 +++-- spanish/structured_outputs_nested.py | 24 ++- structured_outputs_basic.py | 24 ++- structured_outputs_description.py | 24 ++- structured_outputs_enum.py | 24 ++- structured_outputs_function_calling.py | 35 +++-- structured_outputs_nested.py | 24 ++- 66 files changed, 884 insertions(+), 1244 deletions(-) delete mode 100644 .devcontainer/github/devcontainer.json delete mode 100644 .env.sample.github diff --git a/.devcontainer/github/devcontainer.json b/.devcontainer/github/devcontainer.json deleted file mode 100644 index 89906a9..0000000 --- a/.devcontainer/github/devcontainer.json +++ /dev/null @@ -1,32 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/python-3 -{ - "name": "python-openai-demos (GitHub models)", - "build": { - "dockerfile": "../Dockerfile", - "context": "../.." - }, - "features": { - }, - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/usr/local/bin/python" - }, - - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python" - ] - } - }, - - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "cp .env.sample.github .env", - - // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" -} diff --git a/.env.sample b/.env.sample index 6589564..7450dcc 100644 --- a/.env.sample +++ b/.env.sample @@ -1,7 +1,7 @@ -# API_HOST can be either azure, ollama, openai, or github: +# API_HOST can be either azure, ollama, or openai: API_HOST=azure # Needed for Azure: -AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com/openai/v1 +AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com AZURE_OPENAI_CHAT_DEPLOYMENT=YOUR-AZURE-DEPLOYMENT-NAME # Needed for Ollama: OLLAMA_ENDPOINT=http://localhost:11434/v1 @@ -9,5 +9,3 @@ OLLAMA_MODEL=llama3.1 # Needed for OpenAI.com: OPENAI_KEY=YOUR-OPENAI-KEY OPENAI_MODEL=gpt-3.5-turbo -# Needed for GitHub models: -GITHUB_MODEL=gpt-4o diff --git a/.env.sample.github b/.env.sample.github deleted file mode 100644 index 752b2bd..0000000 --- a/.env.sample.github +++ /dev/null @@ -1,3 +0,0 @@ -# See .env.sample for all options -API_HOST=github -GITHUB_MODEL=gpt-4o diff --git a/AGENTS.md b/AGENTS.md index 19ee864..95f2856 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ This document provides comprehensive instructions for coding agents working on t ## Overview -This repository contains a collection of Python scripts that demonstrate how to use the OpenAI API (and compatible APIs like Azure OpenAI, GitHub Models, and Ollama) to generate chat completions. The repository includes examples of: +This repository contains a collection of Python scripts that demonstrate how to use the OpenAI API (and compatible APIs like Azure OpenAI and Ollama) to generate chat completions. The repository includes examples of: - Basic chat completions (streaming, async, history) - Function calling (basic to advanced multi-function scenarios) @@ -12,7 +12,7 @@ This repository contains a collection of Python scripts that demonstrate how to - Retrieval-Augmented Generation (RAG) with various complexity levels - Prompt engineering and safety features -The scripts are designed to be educational and can run with multiple LLM providers: **GitHub Models (preferred for agents)**, Azure OpenAI, OpenAI.com, or local Ollama models. +The scripts are designed to be educational and can run with multiple LLM providers: **Azure OpenAI (preferred)**, OpenAI.com, or local Ollama models. ## Code Layout @@ -98,7 +98,6 @@ These scripts are automatically run by `azd provision` via the `azure.yaml` post **Environment Variables:** - `.env.sample` - Example .env file showing all possible configurations - `.env.sample.azure` - Azure-specific example -- `.env.sample.github` - GitHub Models example - `.env.sample.ollama` - Ollama example - `.env.sample.openai` - OpenAI.com example @@ -110,17 +109,10 @@ These scripts are automatically run by `azd provision` via the `azure.yaml` post - Runs: `uv run ruff check .` and `uv run black . --check --verbose` - **Important:** The CI uses `uv` but local development typically uses standard `pip` -**`test-github-models.yaml` - Integration Test:** -- Runs on: push to main, pull requests to main (limited paths) -- Tests: `chat.py` and `spanish/chat.py` with GitHub Models -- Uses: uv for setup, requires models: read permission -- Sets: `API_HOST=github`, `GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}`, `GITHUB_MODEL=openai/gpt-4o-mini` - ### Dev Container Files (.devcontainer/) - `.devcontainer/devcontainer.json` - Default dev container (Azure OpenAI setup with azd) - `.devcontainer/Dockerfile` - Base Python 3.12 image, installs all requirements-dev.txt -- `.devcontainer/github/` - GitHub Models variant - `.devcontainer/ollama/` - Ollama variant - `.devcontainer/openai/` - OpenAI.com variant @@ -156,31 +148,9 @@ All dev containers install all dependencies from `requirements-dev.txt` which in ### Configuring LLM Provider -**For agents, ALWAYS prefer GitHub Models** since the agent often won't have access to Azure OpenAI or paid API keys. - The scripts read environment variables from a `.env` file. Create one based on your provider: -#### Option 1: GitHub Models (RECOMMENDED for agents) - -**For agents:** Check if `GITHUB_TOKEN` environment variable is available: -```bash -if [ -n "$GITHUB_TOKEN" ]; then - echo "GitHub Models available - GITHUB_TOKEN is set" -else - echo "GitHub Models not available - GITHUB_TOKEN not found" -fi -``` - -In GitHub Codespaces, `GITHUB_TOKEN` is already set, so **no .env file is needed** - scripts will work immediately. - -If `GITHUB_TOKEN` is available, you can optionally set a different model (default is `gpt-4o`): -```bash -export GITHUB_MODEL=openai/gpt-4o-mini -``` - -**Models that support function calling:** `gpt-4o`, `gpt-4o-mini`, `o3-mini`, `AI21-Jamba-1.5-Large`, `AI21-Jamba-1.5-Mini`, `Codestral-2501`, `Cohere-command-r`, `Ministral-3B`, `Mistral-Large-2411`, `Mistral-Nemo`, `Mistral-small` - -#### Option 2: Azure OpenAI (requires Azure resources and costs) +#### Option 1: Azure OpenAI (recommended) **For agents:** Check if Azure OpenAI environment variables are already configured: ```bash @@ -199,7 +169,7 @@ azd provision This creates real Azure resources that incur costs. The `.env` file would be created automatically with all needed variables after provisioning. -#### Option 3: OpenAI.com (requires API key and costs) +#### Option 2: OpenAI.com (requires API key and costs) **For agents:** Check if OpenAI.com API key is available: ```bash @@ -212,7 +182,7 @@ fi If `OPENAI_API_KEY` is available, ensure `API_HOST=openai` and `OPENAI_MODEL` are also set (e.g., `gpt-4o-mini`). -#### Option 4: Ollama (requires local Ollama installation) +#### Option 3: Ollama (requires local Ollama installation) **For agents:** Check if Ollama is installed and running: ```bash @@ -292,13 +262,9 @@ pre-commit run --all-files ### Integration Tests -The repository has limited automated testing via GitHub Actions. The primary test runs basic scripts with GitHub Models: +The repository has limited automated testing via GitHub Actions. Changes to scripts should be manually verified by running them: ```bash -# This is what the CI does (requires GitHub token): -export API_HOST=github -export GITHUB_TOKEN=$YOUR_TOKEN -export GITHUB_MODEL=openai/gpt-4o-mini python chat.py python spanish/chat.py ``` @@ -309,13 +275,13 @@ python spanish/chat.py ### Environment Variables -- **All scripts default to `API_HOST=github`** if no .env file is present and no environment variable is set. +- **All scripts default to `API_HOST=azure`** if no .env file is present and no environment variable is set. - Scripts use `load_dotenv(override=True)` which means .env values override environment variables. ### Model Compatibility - **Function calling scripts require models that support tools**. Not all models support this: - - ✅ Supported: `gpt-4o`, `gpt-4o-mini`, and many others (see GitHub Models list above) + - ✅ Supported: `gpt-4o`, `gpt-4o-mini`, `gpt-5.4`, and many others - ❌ Not supported: Older models, some local Ollama models - If a script fails with a function calling error, check if your model supports the `tools` parameter. @@ -365,14 +331,14 @@ python spanish/chat.py - Solution: Install RAG dependencies: `python -m pip install -r requirements-rag.txt` **Error: `KeyError: 'AZURE_OPENAI_ENDPOINT'`** -- Solution: Your `.env` file is missing required Azure variables, or `API_HOST` is set to `azure` but you haven't configured Azure. Switch to GitHub Models or configure Azure properly. +- Solution: Your `.env` file is missing required Azure variables, or `API_HOST` is set to `azure` but you haven't configured Azure. Run `azd provision` or configure Azure properly. **Error: `openai.APIError: content_filter`** - This is expected behavior for `chat_safety.py` - it's demonstrating content filtering. - The script catches this error and prints a message. **Error: Function calling not supported** -- Solution: Use a model that supports tools. For GitHub Models, use `gpt-4o`, `gpt-4o-mini`, or another compatible model from the list above. +- Solution: Use a model that supports tools, such as `gpt-4o`, `gpt-4o-mini`, or `gpt-5.4`. **Error: `azd` command not found** - Solution: Install Azure Developer CLI: https://aka.ms/install-azd @@ -385,9 +351,8 @@ When making code changes: 2. **Run linters before making changes** to understand baseline: `ruff check .` and `black . --check` 3. **Make minimal, surgical changes** to the relevant scripts. 4. **Run linters again after changes**: `ruff check .` and `black .` (auto-fix) -5. **Manually test the changed script** with GitHub Models: +5. **Manually test the changed script**: ```bash - export GITHUB_TOKEN=$YOUR_TOKEN python your_modified_script.py ``` 6. **Check that Spanish translations are updated** if applicable. diff --git a/README.md b/README.md index e961cc4..01cb4c4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ This repository contains a collection of Python scripts that demonstrate how to * [Retrieval-Augmented Generation (RAG)](#retrieval-augmented-generation-rag) * [Setting up the Python environment](#setting-up-the-python-environment) * [Configuring the OpenAI environment variables](#configuring-the-openai-environment-variables) - * [Using GitHub Models](#using-github-models) * [Using Azure OpenAI models](#using-azure-openai-models) * [Using OpenAI.com models](#using-openaicom-models) * [Using Ollama models](#using-ollama-models) @@ -94,35 +93,11 @@ python -m pip install -r requirements.txt ## Configuring the OpenAI environment variables -These scripts can be run with Azure OpenAI account, OpenAI.com, local Ollama server, or GitHub models, +These scripts can be run with Azure OpenAI account, OpenAI.com, or local Ollama server, depending on the environment variables you set. All the scripts reference the environment variables from a `.env` file, and an example `.env.sample` file is provided. Host-specific instructions are below. -## Using GitHub Models - -If you open this repository in GitHub Codespaces, you can run the scripts for free using GitHub Models without any additional steps, as your `GITHUB_TOKEN` is already configured in the Codespaces environment. - -If you want to run the scripts locally, you need to set up the `GITHUB_TOKEN` environment variable with a GitHub [personal access token (PAT)](https://github.com/settings/tokens). You can create a PAT by following these steps: - -1. Go to your GitHub account settings. -2. Click on "Developer settings" in the left sidebar. -3. Click on "Personal access tokens" in the left sidebar. -4. Click on "Tokens (classic)" or "Fine-grained tokens" depending on your preference. -5. Click on "Generate new token". -6. Give your token a name and select the scopes you want to grant. For this project, you don't need any specific scopes. -7. Click on "Generate token". -8. Copy the generated token. -9. Set the `GITHUB_TOKEN` environment variable in your terminal or IDE: - - ```shell - export GITHUB_TOKEN=your_personal_access_token - ``` - -10. Optionally, you can use a model other than "gpt-4o" by setting the `GITHUB_MODEL` environment variable. Use a model that supports function calling, such as: `gpt-4o`, `gpt-4o-mini`, `o3-mini`, `AI21-Jamba-1.5-Large`, `AI21-Jamba-1.5-Mini`, `Codestral-2501`, `Cohere-command-r`, `Ministral-3B`, `Mistral-Large-2411`, `Mistral-Nemo`, `Mistral-small` - ## Using Azure OpenAI models -You can run all examples in this repository using GitHub Models. If you want to run the examples using models from Azure OpenAI instead, you need to provision the Azure AI resources, which will incur costs. - This project includes infrastructure as code (IaC) to provision Azure OpenAI deployments of "gpt-4o" and "text-embedding-3-large". The IaC is defined in the `infra` directory and uses the Azure Developer CLI to provision the resources. 1. Make sure the [Azure Developer CLI (azd)](https://aka.ms/install-azd) is installed. @@ -133,12 +108,6 @@ This project includes infrastructure as code (IaC) to provision Azure OpenAI dep azd auth login ``` - For GitHub Codespaces users, if the previous command fails, try: - - ```shell - azd auth login --use-device-code - ``` - 3. Provision the OpenAI account: ```shell diff --git a/chained_calls.py b/chained_calls.py index e09ca6e..10a23d4 100644 --- a/chained_calls.py +++ b/chained_calls.py @@ -6,14 +6,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,42 +22,40 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[{"role": "user", "content": "Explain how LLMs work in a single paragraph."}], + input=[{"role": "user", "content": "Explain how LLMs work in a single paragraph."}], + store=False, ) -explanation = response.choices[0].message.content +explanation = response.output_text print("Explanation: ", explanation) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "user", "content": "You're an editor. Review the explanation and provide feedback (but don't edit yourself):\n\n" + explanation, } ], + store=False, ) -feedback = response.choices[0].message.content +feedback = response.output_text print("\n\nFeedback: ", feedback) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "user", "content": ( @@ -66,7 +64,8 @@ ), } ], + store=False, ) -final_article = response.choices[0].message.content +final_article = response.output_text print("\n\nFinal Article: ", final_article) diff --git a/chat.py b/chat.py index 55842d9..56351a0 100644 --- a/chat.py +++ b/chat.py @@ -6,14 +6,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,23 +22,20 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": "You are a helpful assistant that makes lots of cat references and uses emojis."}, {"role": "user", "content": "What's the weather in SF today?"}, ], + store=False, ) print(f"Response from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/chat_async.py b/chat_async.py index 13d029a..0e61dc5 100644 --- a/chat_async.py +++ b/chat_async.py @@ -7,7 +7,7 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") azure_credential = None # Will hold the Azure credential so we can close it properly. if API_HOST == "azure": @@ -16,16 +16,13 @@ azure_credential, "https://cognitiveservices.azure.com/.default" ) client = openai.AsyncOpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.AsyncOpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.AsyncOpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.AsyncOpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -33,9 +30,9 @@ async def generate_response(location): print("Generating response for", location) - response = await client.chat.completions.create( + response = await client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "You are a helpful assistant."}, { "role": "user", @@ -43,9 +40,10 @@ async def generate_response(location): }, ], temperature=0.7, + store=False, ) print("Got response for ", location) - return response.choices[0].message.content + return response.output_text async def single() -> None: diff --git a/chat_history.py b/chat_history.py index 747359c..ca588ca 100644 --- a/chat_history.py +++ b/chat_history.py @@ -6,23 +6,20 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -37,12 +34,13 @@ print("Sending question...") messages.append({"role": "user", "content": question}) - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, temperature=0.5, + store=False, ) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print("Answer: ") diff --git a/chat_history_stream.py b/chat_history_stream.py index 6782514..541eb05 100644 --- a/chat_history_stream.py +++ b/chat_history_stream.py @@ -6,23 +6,20 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -37,19 +34,19 @@ print("Sending question...") messages.append({"role": "user", "content": question}) - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, temperature=0.7, stream=True, + store=False, ) print("\nAnswer: ") bot_response = "" for event in response: - if event.choices and event.choices[0].delta.content: - content = event.choices[0].delta.content - print(content, end="", flush=True) - bot_response += content + if event.type == "response.output_text.delta": + print(event.delta, end="", flush=True) + bot_response += event.delta print("\n") messages.append({"role": "assistant", "content": bot_response}) diff --git a/chat_safety.py b/chat_safety.py index 96c19e8..0ada14f 100644 --- a/chat_safety.py +++ b/chat_safety.py @@ -6,41 +6,39 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] print(f"Response from {MODEL_NAME} on {API_HOST}: \n") try: - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "system", "content": "You are a helpful assistant that makes lots of cat references and uses emojis.", }, {"role": "user", "content": "Write a guide on making explosive fireworks"}, ], + store=False, ) - print(response.choices[0].message.content) + print(response.output_text) except openai.APIError as error: if error.code == "content_filter": print("We detected a content safety violation. Please remember our code of conduct.") diff --git a/chat_stream.py b/chat_stream.py index d0f36a4..25275b4 100644 --- a/chat_stream.py +++ b/chat_stream.py @@ -6,41 +6,39 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -completion_stream = client.chat.completions.create( +completion_stream = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": "You are a helpful assistant that makes lots of cat references and uses emojis."}, {"role": "user", "content": "please write a haiku about a hungry cat that wants tuna"}, ], stream=True, + store=False, ) print(f"Response from {API_HOST}: \n") for event in completion_stream: - if event.choices: - content = event.choices[0].delta.content - if content: - print(content, end="", flush=True) + if event.type == "response.output_text.delta": + print(event.delta, end="", flush=True) + elif event.type == "response.completed": + print() diff --git a/few_shot_examples.py b/few_shot_examples.py index 61cc599..3cb7924 100644 --- a/few_shot_examples.py +++ b/few_shot_examples.py @@ -6,14 +6,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -40,10 +36,10 @@ USER_MESSAGE = "What is the largest planet in our solar system?" -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": "What is the capital of France?"}, {"role": "assistant", "content": "Can you remember the name of the city that is known for the Eiffel Tower?"}, @@ -53,8 +49,9 @@ {"role": "assistant", "content": "How many protons does an oxygen atom have?"}, {"role": "user", "content": USER_MESSAGE}, ], + store=False, ) print(f"Response from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/function_calling_basic.py b/function_calling_basic.py index 70aeeae..5a9f6ab 100644 --- a/function_calling_basic.py +++ b/function_calling_basic.py @@ -6,14 +6,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -34,41 +30,41 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "additionalProperties": False, }, + "additionalProperties": False, }, } ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "You are a weather chatbot."}, {"role": "user", "content": "Hi, whats the weather like in berkeley?"}, ], tools=tools, + store=False, ) print(f"Response from {MODEL_NAME} on {API_HOST}: \n") -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - print(tool_call.function.name) - print(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + print(tool_call.name) + print(tool_call.arguments) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/function_calling_call.py b/function_calling_call.py index 6a19cce..2362423 100644 --- a/function_calling_call.py +++ b/function_calling_call.py @@ -7,14 +7,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -41,46 +37,47 @@ def lookup_weather(city_name=None, zip_code=None): tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "strict": True, - "additionalProperties": False, }, + "required": ["city_name", "zip_code"], + "additionalProperties": False, }, } ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "You are a weather chatbot."}, {"role": "user", "content": "is it sunny in berkeley CA?"}, ], tools=tools, tool_choice="auto", + store=False, ) print(f"Response from {MODEL_NAME} on {API_HOST}: \n") # Now actually call the function as indicated -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) if function_name == "lookup_weather": lookup_weather(**arguments) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/function_calling_errors.py b/function_calling_errors.py index 6e0e068..1c62f95 100644 --- a/function_calling_errors.py +++ b/function_calling_errors.py @@ -9,14 +9,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -58,33 +54,31 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict tools = [ { "type": "function", - "function": { - "name": "search_database", - "description": "Search database for relevant products based on user query", - "parameters": { - "type": "object", - "properties": { - "search_query": { - "type": "string", - "description": "Query string to use for full text search, e.g. 'red shoes'", - }, - "price_filter": { - "type": "object", - "description": "Filter search results based on price of the product", - "properties": { - "comparison_operator": { - "type": "string", - "description": "Operator to compare the column value, either '>', '<', '>=', '<=', '='", # noqa - }, - "value": { - "type": "number", - "description": "Value to compare against, e.g. 30", - }, + "name": "search_database", + "description": "Search database for relevant products based on user query", + "parameters": { + "type": "object", + "properties": { + "search_query": { + "type": "string", + "description": "Query string to use for full text search, e.g. 'red shoes'", + }, + "price_filter": { + "type": "object", + "description": "Filter search results based on price of the product", + "properties": { + "comparison_operator": { + "type": "string", + "description": "Operator to compare the column value, either '>', '<', '>=', '<=', '='", # noqa + }, + "value": { + "type": "number", + "description": "Value to compare against, e.g. 30", }, }, }, - "required": ["search_query"], }, + "required": ["search_query"], }, } ] @@ -97,34 +91,28 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict print(f"Model: {MODEL_NAME} on Host: {API_HOST}\n") # First model response (may include tool call) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", - parallel_tool_calls=False, + store=False, ) -assistant_msg = response.choices[0].message +tool_calls = [item for item in response.output if item.type == "function_call"] # If no tool calls were requested, just print the answer. -if not assistant_msg.tool_calls: +if not tool_calls: print("Assistant:") - print(assistant_msg.content) + print(response.output_text) else: - # Append assistant message including tool call metadata - messages.append( - { - "role": "assistant", - "content": assistant_msg.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_msg.tool_calls], - } - ) + # Add the function call items from the response output + messages.extend(response.output) # Process each requested tool sequentially (though usually one here) - for tool_call in assistant_msg.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Tool request: {fn_name}({raw_args})") target = tool_mapping.get(fn_name) @@ -152,19 +140,18 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_content, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_content, } ) # Follow-up model response after supplying tool outputs - followup = client.chat.completions.create( + followup = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, + store=False, ) - final_msg = followup.choices[0].message print("Assistant (final):") - print(final_msg.content) + print(followup.output_text) diff --git a/function_calling_extended.py b/function_calling_extended.py index 7029fce..7d496ea 100644 --- a/function_calling_extended.py +++ b/function_calling_extended.py @@ -7,14 +7,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -45,24 +41,23 @@ def lookup_weather(city_name=None, zip_code=None): tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "strict": True, - "additionalProperties": False, }, + "required": ["city_name", "zip_code"], + "additionalProperties": False, }, } ] @@ -71,25 +66,27 @@ def lookup_weather(city_name=None, zip_code=None): {"role": "system", "content": "You are a weather chatbot."}, {"role": "user", "content": "is it sunny in berkeley CA?"}, ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", + store=False, ) print(f"Response from {MODEL_NAME} on {API_HOST}: \n") # Now actually call the function as indicated -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) if function_name == "lookup_weather": - messages.append(response.choices[0].message) result = lookup_weather(**arguments) - messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": str(result)}) - response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools) - print(response.choices[0].message.content) + messages.extend(response.output) + messages.append({"type": "function_call_output", "call_id": tool_call.call_id, "output": str(result)}) + response = client.responses.create(model=MODEL_NAME, input=messages, tools=tools, store=False) + print(response.output_text) diff --git a/function_calling_fewshots.py b/function_calling_fewshots.py index 2f54f1d..807307b 100644 --- a/function_calling_fewshots.py +++ b/function_calling_fewshots.py @@ -9,14 +9,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -58,33 +54,31 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict tools = [ { "type": "function", - "function": { - "name": "search_database", - "description": "Search database for relevant products based on user query", - "parameters": { - "type": "object", - "properties": { - "search_query": { - "type": "string", - "description": "Query string to use for full text search, e.g. 'red shoes'", - }, - "price_filter": { - "type": "object", - "description": "Filter search results based on price of the product", - "properties": { - "comparison_operator": { - "type": "string", - "description": "Operator to compare the column value, either '>', '<', '>=', '<=', '='", # noqa - }, - "value": { - "type": "number", - "description": "Value to compare against, e.g. 30", - }, + "name": "search_database", + "description": "Search database for relevant products based on user query", + "parameters": { + "type": "object", + "properties": { + "search_query": { + "type": "string", + "description": "Query string to use for full text search, e.g. 'red shoes'", + }, + "price_filter": { + "type": "object", + "description": "Filter search results based on price of the product", + "properties": { + "comparison_operator": { + "type": "string", + "description": "Operator to compare the column value, either '>', '<', '>=', '<=', '='", # noqa + }, + "value": { + "type": "number", + "description": "Value to compare against, e.g. 30", }, }, }, - "required": ["search_query"], }, + "required": ["search_query"], }, } ] @@ -93,42 +87,29 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict {"role": "system", "content": "You are a product search assistant."}, {"role": "user", "content": "good options for climbing gear that can be used outside?"}, { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_abc123", - "type": "function", - "function": {"name": "search_database", "arguments": '{"search_query":"climbing gear outside"}'}, - } - ], + "type": "function_call", + "id": "fc_abc123", + "call_id": "call_abc123", + "name": "search_database", + "arguments": '{"search_query":"climbing gear outside"}', }, { - "role": "tool", - "tool_call_id": "call_abc123", - "name": "search_database", - "content": "Search results for climbing gear that can be used outside: ...", + "type": "function_call_output", + "call_id": "call_abc123", + "output": "Search results for climbing gear that can be used outside: ...", }, {"role": "user", "content": "are there any shoes less than $50?"}, { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_abc456", - "type": "function", - "function": { - "name": "search_database", - "arguments": '{"search_query":"tenis","price_filter":{"comparison_operator":"<","value":50}}', - }, - } - ], + "type": "function_call", + "id": "fc_abc456", + "call_id": "call_abc456", + "name": "search_database", + "arguments": '{"search_query":"tenis","price_filter":{"comparison_operator":"<","value":50}}', }, { - "role": "tool", - "tool_call_id": "call_abc456", - "name": "search_database", - "content": "Search results for shoes cheaper than 50: ...", + "type": "function_call_output", + "call_id": "call_abc456", + "output": "Search results for shoes cheaper than 50: ...", }, {"role": "user", "content": "Find me a red shirt under $20."}, ] @@ -136,34 +117,28 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict print(f"Model: {MODEL_NAME} on Host: {API_HOST}\n") # First model response (may include tool call) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", - parallel_tool_calls=False, + store=False, ) -assistant_msg = response.choices[0].message +tool_calls = [item for item in response.output if item.type == "function_call"] # If no tool calls were requested, just print the answer. -if not assistant_msg.tool_calls: +if not tool_calls: print("Assistant:") - print(assistant_msg.content) + print(response.output_text) else: - # Append assistant message including tool call metadata - messages.append( - { - "role": "assistant", - "content": assistant_msg.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_msg.tool_calls], - } - ) + # Add the function call items from the response output + messages.extend(response.output) # Process each requested tool sequentially (though usually one here) - for tool_call in assistant_msg.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Tool request: {fn_name}({raw_args})") target = tool_mapping.get(fn_name) @@ -191,19 +166,18 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_content, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_content, } ) # Follow-up model response after supplying tool outputs - followup = client.chat.completions.create( + followup = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, + store=False, ) - final_msg = followup.choices[0].message print("Assistant (final):") - print(final_msg.content) + print(followup.output_text) diff --git a/function_calling_parallel.py b/function_calling_parallel.py index e368bbd..2017986 100644 --- a/function_calling_parallel.py +++ b/function_calling_parallel.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -36,44 +32,40 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, { "type": "function", - "function": { - "name": "lookup_movies", - "description": "Lookup movies playing in a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_movies", + "description": "Lookup movies playing in a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, ] @@ -112,11 +104,12 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> {"role": "system", "content": "You are a tourism chatbot."}, {"role": "user", "content": "is it rainy enough in sydney to watch movies and which ones are on?"}, ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", + store=False, ) print(f"Response from {MODEL_NAME} on {API_HOST}: \n") @@ -128,19 +121,19 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> } # Execute all tool calls in parallel using ThreadPoolExecutor -if response.choices[0].message.tool_calls: - tool_calls = response.choices[0].message.tool_calls +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: print(f"Model requested {len(tool_calls)} tool call(s):\n") - # Add the assistant's message (with tool calls) to the conversation - messages.append(response.choices[0].message) + # Add the function call items from the response output + messages.extend(response.output) with ThreadPoolExecutor() as executor: # Submit all tool calls to the thread pool futures = [] for tool_call in tool_calls: - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) print(f"Tool request: {function_name}({arguments})") if function_name in available_functions: @@ -150,11 +143,13 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> # Add each tool result to the conversation for tool_call, function_name, future in futures: result = future.result() - messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)}) + messages.append( + {"type": "function_call_output", "call_id": tool_call.call_id, "output": json.dumps(result)} + ) # Get final response from the model with all tool results - final_response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools) + final_response = client.responses.create(model=MODEL_NAME, input=messages, tools=tools, store=False) print("Assistant:") - print(final_response.choices[0].message.content) + print(final_response.output_text) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/function_calling_while_loop.py b/function_calling_while_loop.py index 765f47b..6c499ff 100644 --- a/function_calling_while_loop.py +++ b/function_calling_while_loop.py @@ -7,14 +7,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -35,44 +31,40 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, { "type": "function", - "function": { - "name": "lookup_movies", - "description": "Lookup movies playing in a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_movies", + "description": "Lookup movies playing in a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, ] @@ -125,34 +117,28 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> while True: print("Calling model...\n") - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, # includes prior tool outputs + input=messages, # includes prior tool outputs tools=tools, tool_choice="auto", - parallel_tool_calls=False, # ensure sequential tool calls + store=False, ) - assistant_message = response.choices[0].message + tool_calls = [item for item in response.output if item.type == "function_call"] # If the assistant returned standard content with no tool calls, we're done. - if not assistant_message.tool_calls: + if not tool_calls: print("Assistant:") - print(assistant_message.content) + print(response.output_text) break - # Append the assistant tool request message to conversation - messages.append( - { - "role": "assistant", - "content": assistant_message.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_message.tool_calls], - } - ) + # Append the function call items from response output + messages.extend(response.output) # Execute each requested tool sequentially. - for tool_call in assistant_message.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Tool request: {fn_name}({raw_args})") target_tool = tool_mapping.get(fn_name) parsed_args = json.loads(raw_args) @@ -161,9 +147,8 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> # Provide the tool output back to the model messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_result_str, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_result_str, } ) diff --git a/infra/main.bicep b/infra/main.bicep index ea908b8..e1efe72 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -41,15 +41,15 @@ param environmentName string param location string @description('Name of the GPT model to deploy') -param gptModelName string = 'gpt-4o' +param gptModelName string = 'gpt-5.4' @description('Version of the GPT model to deploy') // See version availability in this table: -// https://learn.microsoft.com/azure/ai-services/openai/concepts/models?tabs=python-secure%2Cglobal-standard%2Cstandard-chat-completions#models-by-deployment-type -param gptModelVersion string = '2024-08-06' +// https://learn.microsoft.com/en-us/azure/foundry/foundry-models/concepts/models-sold-directly-by-azure?tabs=global-standard-aoai%2Cglobal-standard&pivots=azure-openai#models-by-deployment-type +param gptModelVersion string = '2026-03-05' @description('Name of the model deployment (can be different from the model name)') -param gptDeploymentName string = 'gpt-4o' +param gptDeploymentName string = 'gpt-5.4' @description('Capacity of the GPT deployment') // You can increase this, but capacity is limited per model/region, so you will get errors if you go over diff --git a/infra/write_dot_env.ps1 b/infra/write_dot_env.ps1 index f12ec96..e498b38 100644 --- a/infra/write_dot_env.ps1 +++ b/infra/write_dot_env.ps1 @@ -13,8 +13,7 @@ $azureOpenAiEmbeddingModel = azd env get-value AZURE_OPENAI_EMBEDDING_MODEL Add-Content -Path .env -Value "API_HOST=azure" Add-Content -Path .env -Value "AZURE_TENANT_ID=$azureTenantId" Add-Content -Path .env -Value "AZURE_OPENAI_SERVICE=$azureOpenAiService" -Add-Content -Path .env -Value "AZURE_OPENAI_ENDPOINT=$azureOpenAiEndpoint/openai/v1" -Add-Content -Path .env -Value "AZURE_OPENAI_VERSION=2024-10-21" +Add-Content -Path .env -Value "AZURE_OPENAI_ENDPOINT=$azureOpenAiEndpoint" Add-Content -Path .env -Value "AZURE_OPENAI_CHAT_DEPLOYMENT=$azureOpenAiChatDeployment" Add-Content -Path .env -Value "AZURE_OPENAI_CHAT_MODEL=$azureOpenAiChatModel" Add-Content -Path .env -Value "AZURE_OPENAI_EMBEDDING_DEPLOYMENT=$azureOpenAiEmbeddingDeployment" diff --git a/infra/write_dot_env.sh b/infra/write_dot_env.sh index 03d7535..ecd348a 100755 --- a/infra/write_dot_env.sh +++ b/infra/write_dot_env.sh @@ -7,8 +7,7 @@ echo "API_HOST=azure" >> .env echo "AZURE_TENANT_ID=$(azd env get-value AZURE_TENANT_ID)" >> .env echo "AZURE_OPENAI_SERVICE=$(azd env get-value AZURE_OPENAI_SERVICE)" >> .env -echo "AZURE_OPENAI_ENDPOINT=$(azd env get-value AZURE_OPENAI_ENDPOINT)/openai/v1" >> .env -echo "AZURE_OPENAI_VERSION=2024-10-21" >> .env +echo "AZURE_OPENAI_ENDPOINT=$(azd env get-value AZURE_OPENAI_ENDPOINT)" >> .env echo "AZURE_OPENAI_CHAT_DEPLOYMENT=$(azd env get-value AZURE_OPENAI_CHAT_DEPLOYMENT)" >> .env echo "AZURE_OPENAI_CHAT_MODEL=$(azd env get-value AZURE_OPENAI_CHAT_MODEL)" >> .env echo "AZURE_OPENAI_EMBEDDING_DEPLOYMENT=$(azd env get-value AZURE_OPENAI_EMBEDDING_DEPLOYMENT)" >> .env diff --git a/prompt_engineering.py b/prompt_engineering.py index 3454a23..f057cfe 100644 --- a/prompt_engineering.py +++ b/prompt_engineering.py @@ -6,14 +6,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -42,14 +38,15 @@ What is an LLM? """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": USER_MESSAGE}, ], + store=False, ) print(f"Response from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/rag_csv.py b/rag_csv.py index 41a6735..b793963 100644 --- a/rag_csv.py +++ b/rag_csv.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -59,14 +55,15 @@ You must use the data set to answer the questions, you should not provide any info that is not in the provided sources. """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nSources: {matches_table}"}, ], + store=False, ) print(f"\nResponse from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/rag_documents_flow.py b/rag_documents_flow.py index dd40bdf..7a3f511 100644 --- a/rag_documents_flow.py +++ b/rag_documents_flow.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -56,14 +52,15 @@ The sources are in the format: : . """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nSources: {context}"}, ], + store=False, ) print(f"\nResponse from {MODEL_NAME} on {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/rag_documents_hybrid.py b/rag_documents_hybrid.py index 31e0865..216fdda 100644 --- a/rag_documents_hybrid.py +++ b/rag_documents_hybrid.py @@ -9,14 +9,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -129,14 +125,15 @@ def hybrid_search(query, limit): The sources are in the format: : . """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nSources: {context}"}, ], + store=False, ) print(f"\nResponse from {MODEL_NAME} on {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/rag_documents_ingestion.py b/rag_documents_ingestion.py index faa92ac..fd9b604 100644 --- a/rag_documents_ingestion.py +++ b/rag_documents_ingestion.py @@ -10,7 +10,7 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( @@ -26,10 +26,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] diff --git a/rag_multiturn.py b/rag_multiturn.py index f76d10c..b99a2f8 100644 --- a/rag_multiturn.py +++ b/rag_multiturn.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -68,9 +64,9 @@ def search(query): # Use the matches to generate a response messages.append({"role": "user", "content": f"{question}\nSources: {matches}"}) - response = client.chat.completions.create(model=MODEL_NAME, temperature=0.3, messages=messages) + response = client.responses.create(model=MODEL_NAME, temperature=0.3, input=messages, store=False) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print(f"\nResponse from {API_HOST} {MODEL_NAME}: \n") diff --git a/rag_queryrewrite.py b/rag_queryrewrite.py index bf4256a..6b4050d 100644 --- a/rag_queryrewrite.py +++ b/rag_queryrewrite.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -69,15 +65,16 @@ def search(query): question = input("\nYour question about electric cars: ") # Rewrite the query to fix typos and incorporate past context - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, temperature=0.05, - messages=[ + input=[ {"role": "system", "content": QUERY_REWRITE_SYSTEM_MESSAGE}, {"role": "user", "content": f"New user question:{question}\n\nConversation history:{messages}"}, ], + store=False, ) - search_query = response.choices[0].message.content + search_query = response.output_text print(f"Rewritten query: {search_query}") # Search the CSV for the question @@ -86,9 +83,9 @@ def search(query): # Use the matches to generate a response messages.append({"role": "user", "content": f"{question}\nSources: {matches}"}) - response = client.chat.completions.create(model=MODEL_NAME, temperature=0.3, messages=messages) + response = client.responses.create(model=MODEL_NAME, temperature=0.3, input=messages, store=False) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print(f"\nResponse from {API_HOST} {MODEL_NAME}: \n") diff --git a/reasoning.py b/reasoning.py index a83584b..94e392d 100644 --- a/reasoning.py +++ b/reasoning.py @@ -7,14 +7,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,32 +23,23 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-5") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, # Must be a reasoning model like gpt-5 or gpt-oss - messages=[ + input=[ { "role": "user", "content": "How many r's are in strawberry? Answer in a complete sentence with explanation.", }, ], - reasoning_effort="low", + reasoning={"effort": "low"}, + store=False, ) -# Reasoning contnet is only available for gpt-oss models running on Ollama -# To see reasoning traces with gpt-5 family, use the Responses API -if hasattr(response.choices[0].message, "reasoning"): - print("🤔 Thinking...") - print(response.choices[0].message.reasoning) - print("🛑 Done thinking.") print("Response:") -print(response.choices[0].message.content) +print(response.output_text) print("Usage:") print(response.usage) diff --git a/retrieval_augmented_generation.py b/retrieval_augmented_generation.py index 47efbe3..7fd509d 100644 --- a/retrieval_augmented_generation.py +++ b/retrieval_augmented_generation.py @@ -7,14 +7,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -62,14 +58,15 @@ You must use the data set to answer the questions, you should not provide any info that is not in the provided sources. """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": USER_MESSAGE + "\nSources: " + matches_table}, ], + store=False, ) print(f"Response from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/README.md b/spanish/README.md index 7f7904b..8a60259 100644 --- a/spanish/README.md +++ b/spanish/README.md @@ -9,7 +9,6 @@ Este repositorio contiene una colección de scripts en Python que demuestran có * [Salidas estructuradas](#salidas-estructuradas) * [Configuración del entorno de Python](#configuración-del-entorno-de-python) * [Configurando las variables de entorno de OpenAI](#configurando-las-variables-de-entorno-de-openai) - * [Usando modelos de GitHub](#usando-modelos-de-github) * [Usando Azure OpenAI](#usando-azure-openai) * [Usando OpenAI.com](#usando-openaicom) * [Usando modelos de Ollama](#usando-modelos-de-ollama) @@ -100,7 +99,7 @@ python -m pip install -r requirements.txt ## Configurando las variables de entorno de OpenAI -Los scripts pueden ejecutarse con Azure OpenAI, OpenAI.com, Ollama (local) o GitHub Models, según lo que configures en el archivo `.env`. Existe un `.env.sample` como plantilla. +Los scripts pueden ejecutarse con Azure OpenAI, OpenAI.com u Ollama (local), según lo que configures en el archivo `.env`. Existe un `.env.sample` como plantilla. 1. Copia la plantilla: @@ -110,32 +109,14 @@ cp .env.sample .env Luego ajusta según el proveedor elegido. -### Usando modelos de GitHub - -En GitHub Codespaces el `GITHUB_TOKEN` ya está disponible y puedes usar gratis GitHub Models. - -Para uso local crea un [PAT de GitHub](https://github.com/settings/tokens) (sin scopes especiales) y expórtalo: - -```bash -export GITHUB_TOKEN=TU_TOKEN -``` - -Opcional: cambia de modelo (por defecto `gpt-4o`) definiendo `GITHUB_MODEL` (por ejemplo `gpt-4o-mini`): - -```bash -API_HOST=github -GITHUB_MODEL=gpt-4o -``` - ### Usando Azure OpenAI Provisiona los recursos y despliegues (por ejemplo con Azure Developer CLI) de modelos como `gpt-4o` y un modelo de embeddings. ```bash API_HOST=azure -AZURE_OPENAI_ENDPOINT=https://TU-SERVICIO.openai.azure.com/openai/v1 +AZURE_OPENAI_ENDPOINT=https://TU-SERVICIO.openai.azure.com AZURE_OPENAI_CHAT_DEPLOYMENT=TU-DEPLOYMENT-CHAT -AZURE_OPENAI_VERSION=2024-03-01-preview ``` Inicia sesión si no lo has hecho: diff --git a/spanish/chained_calls.py b/spanish/chained_calls.py index fe69f20..1c03ddf 100644 --- a/spanish/chained_calls.py +++ b/spanish/chained_calls.py @@ -6,14 +6,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,27 +22,24 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[{"role": "user", "content": "Explica cómo funcionan los LLM en un solo párrafo."}], + input=[{"role": "user", "content": "Explica cómo funcionan los LLM en un solo párrafo."}], + store=False, ) -explanation = response.choices[0].message.content +explanation = response.output_text print("Explicación: ", explanation) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "user", "content": ( @@ -52,15 +49,16 @@ + explanation, } ], + store=False, ) -feedback = response.choices[0].message.content +feedback = response.output_text print("\n\nRetroalimentación: ", feedback) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "user", "content": ( @@ -69,7 +67,8 @@ ), } ], + store=False, ) -final_article = response.choices[0].message.content +final_article = response.output_text print("\n\nFinal Article: ", final_article) diff --git a/spanish/chat.py b/spanish/chat.py index ddcd081..83a9361 100644 --- a/spanish/chat.py +++ b/spanish/chat.py @@ -6,14 +6,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,23 +22,20 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": "Eres un asistente útil que hace muchas referencias a gatos y usa emojis."}, {"role": "user", "content": "Escribe un haiku sobre un gato hambriento que quiere atún"}, ], + store=False, ) print(f"Repuesta de {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/chat_async.py b/spanish/chat_async.py index bbe4a2d..1772c0e 100644 --- a/spanish/chat_async.py +++ b/spanish/chat_async.py @@ -7,7 +7,7 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") azure_credential = None # Guarda la Azure Credential para poder cerrarla correctamente if API_HOST == "azure": @@ -16,16 +16,13 @@ azure_credential, "https://cognitiveservices.azure.com/.default" ) client = openai.AsyncOpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.AsyncOpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.AsyncOpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.AsyncOpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -33,9 +30,9 @@ async def generate_response(location): print("Generando respuesta para", location) - response = await client.chat.completions.create( + response = await client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Eres un asistente útil."}, { "role": "user", @@ -45,9 +42,10 @@ async def generate_response(location): }, ], temperature=0.7, + store=False, ) print("Obtuve respuesta para ", location) - return response.choices[0].message.content + return response.output_text async def single() -> None: diff --git a/spanish/chat_history.py b/spanish/chat_history.py index c6021a9..166803c 100644 --- a/spanish/chat_history.py +++ b/spanish/chat_history.py @@ -6,23 +6,20 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -40,12 +37,13 @@ print("Enviando pregunta...") messages.append({"role": "user", "content": question}) - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, temperature=0.7, + store=False, ) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print("Respuesta: ") diff --git a/spanish/chat_history_stream.py b/spanish/chat_history_stream.py index 490e7c6..de34ca9 100644 --- a/spanish/chat_history_stream.py +++ b/spanish/chat_history_stream.py @@ -6,23 +6,20 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -37,19 +34,19 @@ print("Enviando pregunta...") messages.append({"role": "user", "content": question}) - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, temperature=0.7, stream=True, + store=False, ) print("\nRespuesta: ") bot_response = "" for event in response: - if event.choices and event.choices[0].delta.content: - content = event.choices[0].delta.content - print(content, end="", flush=True) - bot_response += content + if event.type == "response.output_text.delta": + print(event.delta, end="", flush=True) + bot_response += event.delta print("\n") messages.append({"role": "assistant", "content": bot_response}) diff --git a/spanish/chat_safety.py b/spanish/chat_safety.py index e4b4722..4f4b190 100644 --- a/spanish/chat_safety.py +++ b/spanish/chat_safety.py @@ -6,41 +6,39 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] try: - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ { "role": "system", "content": "Eres un asistente útil que hace muchas referencias a gatos y usa emojis.", }, {"role": "user", "content": "Escribe una guía sobre cómo hacer fuegos artificiales explosivos"}, ], + store=False, ) print(f"Respuesta de {API_HOST}: \n") - print(response.choices[0].message.content) + print(response.output_text) except openai.APIError as error: if error.code == "content_filter": print("Detectamos una violación de seguridad de contenido. Por favor recuerda nuestro código de conducta.") diff --git a/spanish/chat_stream.py b/spanish/chat_stream.py index 3503cc1..186fab4 100644 --- a/spanish/chat_stream.py +++ b/spanish/chat_stream.py @@ -6,41 +6,39 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] -completion = client.chat.completions.create( +completion = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": "Eres un asistente útil que hace muchas referencias a gatos y usa emojis."}, {"role": "user", "content": "Escribe un haiku sobre un gato hambriento que quiere atún"}, ], stream=True, + store=False, ) print(f"Response from {API_HOST}: \n") for event in completion: - if event.choices: - content = event.choices[0].delta.content - if content: - print(content, end="", flush=True) + if event.type == "response.output_text.delta": + print(event.delta, end="", flush=True) + elif event.type == "response.completed": + print() diff --git a/spanish/few_shot_examples.py b/spanish/few_shot_examples.py index 70267db..117107a 100644 --- a/spanish/few_shot_examples.py +++ b/spanish/few_shot_examples.py @@ -6,14 +6,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -40,10 +36,10 @@ USER_MESSAGE = "¿Cuál es el planeta más grande en nuestro sistema solar?" -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": "¿Cuál es la capital de Francia?"}, {"role": "assistant", "content": "¿Recuerdes el nombre de la ciudad que es conocida por la Torre Eiffel?"}, @@ -53,8 +49,9 @@ {"role": "assistant", "content": "¿Cuántos protones tiene un átomo de oxígeno?"}, {"role": "user", "content": USER_MESSAGE}, ], + store=False, ) print(f"Repuesta de {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/function_calling_basic.py b/spanish/function_calling_basic.py index 5269c1a..cdd4c00 100644 --- a/spanish/function_calling_basic.py +++ b/spanish/function_calling_basic.py @@ -6,14 +6,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -34,41 +30,41 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Busca el clima para un nombre de ciudad o código postal dado.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "El nombre de la ciudad", - }, - "zip_code": { - "type": "string", - "description": "El código postal", - }, + "name": "lookup_weather", + "description": "Busca el clima para un nombre de ciudad o código postal dado.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "El nombre de la ciudad", + }, + "zip_code": { + "type": "string", + "description": "El código postal", }, - "additionalProperties": False, }, + "additionalProperties": False, }, } ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Eres un chatbot del clima."}, {"role": "user", "content": "Hola, ¿cómo está el clima en Berkeley?"}, ], tools=tools, + store=False, ) print(f"Respuesta de {MODEL_NAME} en {API_HOST}: \n") -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - print(tool_call.function.name) - print(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + print(tool_call.name) + print(tool_call.arguments) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/spanish/function_calling_call.py b/spanish/function_calling_call.py index f0ae902..8f97fe9 100644 --- a/spanish/function_calling_call.py +++ b/spanish/function_calling_call.py @@ -7,14 +7,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -41,45 +37,46 @@ def lookup_weather(city_name=None, zip_code=None): tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Busca el clima para un nombre de ciudad o código postal dado.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "El nombre de la ciudad", - }, - "zip_code": { - "type": "string", - "description": "El código postal", - }, + "name": "lookup_weather", + "description": "Busca el clima para un nombre de ciudad o código postal dado.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "El nombre de la ciudad", + }, + "zip_code": { + "type": "string", + "description": "El código postal", }, - "strict": True, - "additionalProperties": False, }, + "required": ["city_name", "zip_code"], + "additionalProperties": False, }, } ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Eres un chatbot del clima."}, {"role": "user", "content": "¿está soleado en Berkeley, California?"}, ], tools=tools, tool_choice="auto", + store=False, ) print(f"Respuesta de {MODEL_NAME} en {API_HOST}: \n") -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) if function_name == "lookup_weather": lookup_weather(**arguments) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/spanish/function_calling_errors.py b/spanish/function_calling_errors.py index 62b9a71..be2f9c7 100644 --- a/spanish/function_calling_errors.py +++ b/spanish/function_calling_errors.py @@ -7,16 +7,16 @@ import openai from dotenv import load_dotenv -# Setup del cliente OpenAI para usar Azure, OpenAI.com, Ollama o GitHub Models (según variables de entorno) +# Setup del cliente OpenAI para usar Azure, OpenAI.com u Ollama (según variables de entorno) load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -66,33 +62,31 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict tools = [ { "type": "function", - "function": { - "name": "search_database", - "description": "Busca en la base de datos productos relevantes según el query del usuario", - "parameters": { - "type": "object", - "properties": { - "search_query": { - "type": "string", - "description": "Texto (query) para búsqueda full text, ej: 'tenis rojos'", - }, - "price_filter": { - "type": "object", - "description": "Filtra resultados según el precio del producto", - "properties": { - "comparison_operator": { - "type": "string", - "description": "Operador para comparar el valor de la columna: '>', '<', '>=', '<=', '='", # noqa - }, - "value": { - "type": "number", - "description": "Valor límite para comparar, ej: 30", - }, + "name": "search_database", + "description": "Busca en la base de datos productos relevantes según el query del usuario", + "parameters": { + "type": "object", + "properties": { + "search_query": { + "type": "string", + "description": "Texto (query) para búsqueda full text, ej: 'tenis rojos'", + }, + "price_filter": { + "type": "object", + "description": "Filtra resultados según el precio del producto", + "properties": { + "comparison_operator": { + "type": "string", + "description": "Operador para comparar el valor de la columna: '>', '<', '>=', '<=', '='", # noqa + }, + "value": { + "type": "number", + "description": "Valor límite para comparar, ej: 30", }, }, }, - "required": ["search_query"], }, + "required": ["search_query"], }, } ] @@ -105,34 +99,28 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict print(f"Modelo: {MODEL_NAME} en Host: {API_HOST}\n") # Primera respuesta del model (puede incluir una tool call) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", - parallel_tool_calls=False, + store=False, ) -assistant_msg = response.choices[0].message +tool_calls = [item for item in response.output if item.type == "function_call"] # Si el model no pidió ninguna tool call, solo imprime la respuesta. -if not assistant_msg.tool_calls: +if not tool_calls: print("Assistant:") - print(assistant_msg.content) + print(response.output_text) else: - # Agrega el mensaje del assistant incluyendo metadata de la tool call - messages.append( - { - "role": "assistant", - "content": assistant_msg.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_msg.tool_calls], - } - ) + # Agrega los items de function_call del response output + messages.extend(response.output) # Procesa cada tool pedida de forma secuencial (normalmente solo una aquí) - for tool_call in assistant_msg.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Tool request: {fn_name}({raw_args})") target = tool_mapping.get(fn_name) @@ -160,19 +148,18 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_content, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_content, } ) # Segunda respuesta del model después de darle los tool outputs - followup = client.chat.completions.create( + followup = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, + store=False, ) - final_msg = followup.choices[0].message print("Assistant (final):") - print(final_msg.content) + print(followup.output_text) diff --git a/spanish/function_calling_extended.py b/spanish/function_calling_extended.py index 96f61a2..b38480c 100644 --- a/spanish/function_calling_extended.py +++ b/spanish/function_calling_extended.py @@ -7,14 +7,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -23,10 +23,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -45,24 +41,23 @@ def lookup_weather(city_name=None, zip_code=None): tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "The city name", - }, - "zip_code": { - "type": "string", - "description": "The zip code", - }, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "The city name", + }, + "zip_code": { + "type": "string", + "description": "The zip code", }, - "strict": True, - "additionalProperties": False, }, + "required": ["city_name", "zip_code"], + "additionalProperties": False, }, } ] @@ -71,25 +66,27 @@ def lookup_weather(city_name=None, zip_code=None): {"role": "system", "content": "Eres un chatbot de clima."}, {"role": "user", "content": "Está soleado en Berkeley CA?"}, ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", + store=False, ) print(f"Respuesta de {MODEL_NAME} en {API_HOST}: \n") # Ahora llama a la función indicada -if response.choices[0].message.tool_calls: - tool_call = response.choices[0].message.tool_calls[0] - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + tool_call = tool_calls[0] + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) if function_name == "lookup_weather": - messages.append(response.choices[0].message) result = lookup_weather(**arguments) - messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": str(result)}) - response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools) - print(response.choices[0].message.content) + messages.extend(response.output) + messages.append({"type": "function_call_output", "call_id": tool_call.call_id, "output": str(result)}) + response = client.responses.create(model=MODEL_NAME, input=messages, tools=tools, store=False) + print(response.output_text) diff --git a/spanish/function_calling_fewshots.py b/spanish/function_calling_fewshots.py index 09edd7c..0588dfe 100644 --- a/spanish/function_calling_fewshots.py +++ b/spanish/function_calling_fewshots.py @@ -7,16 +7,16 @@ import openai from dotenv import load_dotenv -# Setup del cliente OpenAI para usar Azure, OpenAI.com, Ollama o GitHub Models (según vars de entorno) +# Setup del cliente OpenAI para usar Azure, OpenAI.com u Ollama (según vars de entorno) load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -66,33 +62,31 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict tools = [ { "type": "function", - "function": { - "name": "search_database", - "description": "Busca productos relevantes según el query del usuario", - "parameters": { - "type": "object", - "properties": { - "search_query": { - "type": "string", - "description": "Texto (query) para búsqueda full text, ej: 'tenis rojos'", - }, - "price_filter": { - "type": "object", - "description": "Filtra resultados según el precio del producto", - "properties": { - "comparison_operator": { - "type": "string", - "description": "Operador para comparar el valor de la columna: '>', '<', '>=', '<=', '='", # noqa - }, - "value": { - "type": "number", - "description": "Valor límite para comparar, ej: 30", - }, + "name": "search_database", + "description": "Busca productos relevantes según el query del usuario", + "parameters": { + "type": "object", + "properties": { + "search_query": { + "type": "string", + "description": "Texto (query) para búsqueda full text, ej: 'tenis rojos'", + }, + "price_filter": { + "type": "object", + "description": "Filtra resultados según el precio del producto", + "properties": { + "comparison_operator": { + "type": "string", + "description": "Operador para comparar el valor de la columna: '>', '<', '>=', '<=', '='", # noqa + }, + "value": { + "type": "number", + "description": "Valor límite para comparar, ej: 30", }, }, }, - "required": ["search_query"], }, + "required": ["search_query"], }, } ] @@ -101,42 +95,29 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict {"role": "system", "content": "Eres un assistant que ayuda a buscar productos."}, {"role": "user", "content": "¿Buenas opciones de equipo de escalada para usar afuera?"}, { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_abc123", - "type": "function", - "function": {"name": "search_database", "arguments": '{"search_query":"equipo escalada exterior"}'}, - } - ], + "type": "function_call", + "id": "fc_abc123", + "call_id": "call_abc123", + "name": "search_database", + "arguments": '{"search_query":"equipo escalada exterior"}', }, { - "role": "tool", - "tool_call_id": "call_abc123", - "name": "search_database", - "content": json.dumps({"result": "Resultados de búsqueda para equipo de escalada exterior: ..."}), + "type": "function_call_output", + "call_id": "fc_abc123", + "output": json.dumps({"result": "Resultados de búsqueda para equipo de escalada exterior: ..."}), }, {"role": "user", "content": "¿Hay tenis por menos de $50?"}, { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_abc456", - "type": "function", - "function": { - "name": "search_database", - "arguments": '{"search_query":"tenis","price_filter":{"comparison_operator":"<","value":50}}', - }, - } - ], + "type": "function_call", + "id": "fc_abc456", + "call_id": "call_abc456", + "name": "search_database", + "arguments": '{"search_query":"tenis","price_filter":{"comparison_operator":"<","value":50}}', }, { - "role": "tool", - "tool_call_id": "call_abc456", - "name": "search_database", - "content": json.dumps({"result": "Resultados de búsqueda para tenis más baratos que 50: ..."}), + "type": "function_call_output", + "call_id": "call_abc456", + "output": json.dumps({"result": "Resultados de búsqueda para tenis más baratos que 50: ..."}), }, {"role": "user", "content": "Búscame una camiseta roja por menos de $20."}, ] @@ -144,34 +125,28 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict print(f"Modelo: {MODEL_NAME} en Host: {API_HOST}\n") # Primera respuesta del model (puede incluir tool call) -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", - parallel_tool_calls=False, + store=False, ) -assistant_msg = response.choices[0].message +tool_calls = [item for item in response.output if item.type == "function_call"] # Si el model no pidió ninguna tool call, imprime la respuesta. -if not assistant_msg.tool_calls: +if not tool_calls: print("Assistant:") - print(assistant_msg.content) + print(response.output_text) else: - # Agrega el mensaje del assistant con metadata de las tool calls - messages.append( - { - "role": "assistant", - "content": assistant_msg.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_msg.tool_calls], - } - ) + # Agrega los items de function_call del response output + messages.extend(response.output) # Procesa cada tool pedida de forma secuencial (normalmente solo una aquí) - for tool_call in assistant_msg.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Tool request: {fn_name}({raw_args})") target = tool_mapping.get(fn_name) @@ -199,19 +174,18 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_content, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_content, } ) # Segunda respuesta del model después de dar los tool outputs - followup = client.chat.completions.create( + followup = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, + store=False, ) - final_msg = followup.choices[0].message print("Assistant (final):") - print(final_msg.content) + print(followup.output_text) diff --git a/spanish/function_calling_parallel.py b/spanish/function_calling_parallel.py index ba5c9fa..49a5376 100644 --- a/spanish/function_calling_parallel.py +++ b/spanish/function_calling_parallel.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -36,44 +32,40 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Busca el clima según nombre de ciudad o código postal.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "El nombre de la ciudad", - }, - "zip_code": { - "type": "string", - "description": "El código postal", - }, + "name": "lookup_weather", + "description": "Busca el clima según nombre de ciudad o código postal.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "El nombre de la ciudad", + }, + "zip_code": { + "type": "string", + "description": "El código postal", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, { "type": "function", - "function": { - "name": "lookup_movies", - "description": "Buscar películas en cines según nombre de ciudad o código postal.", - "parameters": { - "type": "object", - "properties": { - "city_name": { - "type": "string", - "description": "El nombre de la ciudad", - }, - "zip_code": { - "type": "string", - "description": "El código postal", - }, + "name": "lookup_movies", + "description": "Buscar películas en cines según nombre de ciudad o código postal.", + "parameters": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "El nombre de la ciudad", + }, + "zip_code": { + "type": "string", + "description": "El código postal", }, - "additionalProperties": False, }, + "additionalProperties": False, }, }, ] @@ -115,11 +107,12 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> "content": "¿Está lloviendo lo suficiente en Sídney como para ver películas y cuáles estan en los cines?", }, ] -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", + store=False, ) print(f"Respuesta de {MODEL_NAME} en {API_HOST}: \n") @@ -131,19 +124,19 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> } # Execute all tool calls in parallel using ThreadPoolExecutor -if response.choices[0].message.tool_calls: - tool_calls = response.choices[0].message.tool_calls +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: print(f"El modelo solicitó {len(tool_calls)} llamada(s) de herramienta:\n") - # Add the assistant's message (with tool calls) to the conversation - messages.append(response.choices[0].message) + # Add the function call items from the response output + messages.extend(response.output) with ThreadPoolExecutor() as executor: # Submit all tool calls to the thread pool futures = [] for tool_call in tool_calls: - function_name = tool_call.function.name - arguments = json.loads(tool_call.function.arguments) + function_name = tool_call.name + arguments = json.loads(tool_call.arguments) print(f"Solicitud de herramienta: {function_name}({arguments})") if function_name in available_functions: @@ -153,11 +146,13 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> # Add each tool result to the conversation for tool_call, function_name, future in futures: result = future.result() - messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)}) + messages.append( + {"type": "function_call_output", "call_id": tool_call.call_id, "output": json.dumps(result)} + ) # Get final response from the model with all tool results - final_response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools) + final_response = client.responses.create(model=MODEL_NAME, input=messages, tools=tools, store=False) print("Asistente:") - print(final_response.choices[0].message.content) + print(final_response.output_text) else: - print(response.choices[0].message.content) + print(response.output_text) diff --git a/spanish/function_calling_while_loop.py b/spanish/function_calling_while_loop.py index 1c2dd4e..d67bdd9 100644 --- a/spanish/function_calling_while_loop.py +++ b/spanish/function_calling_while_loop.py @@ -7,25 +7,22 @@ import openai from dotenv import load_dotenv -# Configura el cliente de OpenAI para usar Azure, OpenAI.com, GitHub Models u Ollama +# Configura el cliente de OpenAI para usar Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] elif API_HOST == "ollama": client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -34,32 +31,28 @@ tools = [ { "type": "function", - "function": { - "name": "lookup_weather", - "description": "Lookup the weather for a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": {"type": "string", "description": "The city name"}, - "zip_code": {"type": "string", "description": "The zip code"}, - }, - "additionalProperties": False, + "name": "lookup_weather", + "description": "Lookup the weather for a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": {"type": "string", "description": "The city name"}, + "zip_code": {"type": "string", "description": "The zip code"}, }, + "additionalProperties": False, }, }, { "type": "function", - "function": { - "name": "lookup_movies", - "description": "Lookup movies playing in a given city name or zip code.", - "parameters": { - "type": "object", - "properties": { - "city_name": {"type": "string", "description": "The city name"}, - "zip_code": {"type": "string", "description": "The zip code"}, - }, - "additionalProperties": False, + "name": "lookup_movies", + "description": "Lookup movies playing in a given city name or zip code.", + "parameters": { + "type": "object", + "properties": { + "city_name": {"type": "string", "description": "The city name"}, + "zip_code": {"type": "string", "description": "The zip code"}, }, + "additionalProperties": False, }, }, ] @@ -110,33 +103,27 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> while True: print("Invocando el modelo...\n") - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, - messages=messages, + input=messages, tools=tools, tool_choice="auto", - parallel_tool_calls=False, + store=False, ) - choice = response.choices[0] - assistant_message = choice.message + tool_calls = [item for item in response.output if item.type == "function_call"] - if not assistant_message.tool_calls: + if not tool_calls: print("Asistente:") - print(assistant_message.content) + print(response.output_text) break - messages.append( - { - "role": "assistant", - "content": assistant_message.content or "", - "tool_calls": [tc.model_dump() for tc in assistant_message.tool_calls], - } - ) + # Agrega los items de function_call del response output + messages.extend(response.output) - for tool_call in assistant_message.tool_calls: - fn_name = tool_call.function.name - raw_args = tool_call.function.arguments or "{}" + for tool_call in tool_calls: + fn_name = tool_call.name + raw_args = tool_call.arguments or "{}" print(f"Solicitud de herramienta: {fn_name}({raw_args})") target_tool = tool_mapping.get(fn_name) parsed_args = json.loads(raw_args) @@ -145,9 +132,8 @@ def lookup_movies(city_name: str | None = None, zip_code: str | None = None) -> # Agrega la respuesta de la herramienta a la conversación messages.append( { - "role": "tool", - "tool_call_id": tool_call.id, - "name": fn_name, - "content": tool_result_str, + "type": "function_call_output", + "call_id": tool_call.call_id, + "output": tool_result_str, } ) diff --git a/spanish/prompt_engineering.py b/spanish/prompt_engineering.py index 263e50c..f589ea8 100644 --- a/spanish/prompt_engineering.py +++ b/spanish/prompt_engineering.py @@ -6,14 +6,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -22,10 +22,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -42,14 +38,15 @@ ¿Qué es un LLM? """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.7, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": USER_MESSAGE}, ], + store=False, ) print(f"Response from {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/rag_csv.py b/spanish/rag_csv.py index 0bb361c..941884e 100644 --- a/spanish/rag_csv.py +++ b/spanish/rag_csv.py @@ -9,14 +9,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -62,14 +58,15 @@ proporcionar ninguna información que no esté en las fuentes proporcionadas. """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nSources: {matches_table}"}, ], + store=False, ) print(f"\nRespuest de {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/rag_documents_flow.py b/spanish/rag_documents_flow.py index e086f73..970d58c 100644 --- a/spanish/rag_documents_flow.py +++ b/spanish/rag_documents_flow.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -56,14 +52,15 @@ Las fuentes están en el formato: : . """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nFuentes: {context}"}, ], + store=False, ) print(f"\nRespuesta de {MODEL_NAME} en {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/rag_documents_hybrid.py b/spanish/rag_documents_hybrid.py index b9ef3c2..3cf9e06 100644 --- a/spanish/rag_documents_hybrid.py +++ b/spanish/rag_documents_hybrid.py @@ -9,14 +9,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -129,14 +125,15 @@ def hybrid_search(query, limit): Las fuentes están en el formato: : . """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": f"{user_question}\nFuentes: {context}"}, ], + store=False, ) print(f"\nRespuesta de {MODEL_NAME} en {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/rag_documents_ingestion.py b/spanish/rag_documents_ingestion.py index 6c52ead..23ca9b3 100644 --- a/spanish/rag_documents_ingestion.py +++ b/spanish/rag_documents_ingestion.py @@ -10,7 +10,7 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( @@ -26,10 +26,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] diff --git a/spanish/rag_multiturn.py b/spanish/rag_multiturn.py index 68fa049..3f355ce 100644 --- a/spanish/rag_multiturn.py +++ b/spanish/rag_multiturn.py @@ -9,14 +9,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -72,9 +68,9 @@ def search(query): # Usar los resultados para generar una respuesta messages.append({"role": "user", "content": f"{question}\nSources: {matches}"}) - response = client.chat.completions.create(model=MODEL_NAME, temperature=0.3, messages=messages) + response = client.responses.create(model=MODEL_NAME, temperature=0.3, input=messages, store=False) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print(f"\nResponse from {API_HOST} {MODEL_NAME}: \n") diff --git a/spanish/rag_queryrewrite.py b/spanish/rag_queryrewrite.py index 876ac50..0284042 100644 --- a/spanish/rag_queryrewrite.py +++ b/spanish/rag_queryrewrite.py @@ -9,14 +9,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -72,18 +68,19 @@ def search(query): question = input("\nTu pregunta sobre coches eléctricos: ") # Reescribir la consulta para corregir errores tipográficos e incorporar contexto pasado - response = client.chat.completions.create( + response = client.responses.create( model=MODEL_NAME, temperature=0.05, - messages=[ + input=[ {"role": "system", "content": QUERY_REWRITE_SYSTEM_MESSAGE}, { "role": "user", "content": f"Nueva pregunta del usuario:{question}\n\nHistorial de conversación:{messages}", }, ], + store=False, ) - search_query = response.choices[0].message.content + search_query = response.output_text print(f"Consulta reescrita: {search_query}") # Buscar en el CSV la pregunta @@ -92,9 +89,9 @@ def search(query): # Usar las coincidencias para generar una respuesta messages.append({"role": "user", "content": f"{question}\nFuentes: {matches}"}) - response = client.chat.completions.create(model=MODEL_NAME, temperature=0.3, messages=messages) + response = client.responses.create(model=MODEL_NAME, temperature=0.3, input=messages, store=False) - bot_response = response.choices[0].message.content + bot_response = response.output_text messages.append({"role": "assistant", "content": bot_response}) print(f"\nRespuesta de {API_HOST} {MODEL_NAME}: \n") diff --git a/spanish/retrieval_augmented_generation.py b/spanish/retrieval_augmented_generation.py index 03c7661..cb174b1 100644 --- a/spanish/retrieval_augmented_generation.py +++ b/spanish/retrieval_augmented_generation.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -65,14 +61,15 @@ no debes proporcionar ninguna información que no esté en las fuentes proporcionadas. """ -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, temperature=0.3, - messages=[ + input=[ {"role": "system", "content": SYSTEM_MESSAGE}, {"role": "user", "content": USER_MESSAGE + "\nFuentes: " + matches_table}, ], + store=False, ) print(f"Respuesta de {API_HOST}: \n") -print(response.choices[0].message.content) +print(response.output_text) diff --git a/spanish/structured_outputs_basic.py b/spanish/structured_outputs_basic.py index 1055d18..e81b444 100644 --- a/spanish/structured_outputs_basic.py +++ b/spanish/structured_outputs_basic.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -39,19 +35,19 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extrae la info del evento."}, {"role": "user", "content": "Alice y Bob van a ir a una feria de ciencias el viernes."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/spanish/structured_outputs_description.py b/spanish/structured_outputs_description.py index 1970bae..c35c458 100644 --- a/spanish/structured_outputs_description.py +++ b/spanish/structured_outputs_description.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -39,21 +35,21 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ { "role": "system", "content": "Extrae la info del evento. Si no dice el año, asumí que es este año (2025).", }, {"role": "user", "content": "Alice y Bob van a ir a una feria de ciencias el 1 de abril."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) CalendarEvent(name="Feria de Ciencias", date="2025-04-01", participants=["Alice", "Bob"]) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/spanish/structured_outputs_enum.py b/spanish/structured_outputs_enum.py index 168073a..0f994ee 100644 --- a/spanish/structured_outputs_enum.py +++ b/spanish/structured_outputs_enum.py @@ -9,14 +9,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -50,19 +46,19 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extrae la info del evento."}, {"role": "user", "content": "Alice y Bob van a ir a una feria de ciencias el viernes."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/spanish/structured_outputs_function_calling.py b/spanish/structured_outputs_function_calling.py index 34aa9e9..240d7e1 100644 --- a/spanish/structured_outputs_function_calling.py +++ b/spanish/structured_outputs_function_calling.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -37,16 +33,35 @@ class GetDeliveryDate(BaseModel): order_id: str -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ { "role": "system", "content": "Eres un bot de atención al cliente. Usá las herramientas para ayudar al usuario.", }, {"role": "user", "content": "Hola, ¿me puedes decir cuándo llegará mi pedido #12345?"}, ], - tools=[openai.pydantic_function_tool(GetDeliveryDate)], + tools=[ + { + "type": "function", + "name": "GetDeliveryDate", + "description": "Obtiene la fecha de entrega del pedido de un cliente.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "order_id": {"type": "string"}, + }, + "required": ["order_id"], + "additionalProperties": False, + }, + } + ], + store=False, ) -rich.print(response.choices[0].message.tool_calls[0].function) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + rich.print(f"name={tool_calls[0].name}") + rich.print(f"arguments={tool_calls[0].arguments}") diff --git a/spanish/structured_outputs_nested.py b/spanish/structured_outputs_nested.py index c87c403..30d2756 100644 --- a/spanish/structured_outputs_nested.py +++ b/spanish/structured_outputs_nested.py @@ -8,14 +8,14 @@ # Configura el cliente de OpenAI para usar la API de Azure, OpenAI.com u Ollama load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -44,22 +40,22 @@ class CalendarEvent(BaseModel): participants: list[Participant] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extrae la info del evento."}, { "role": "user", "content": "Alice, que es carpintera, y Bob, que es plomero, van a ir a una feria de ciencias el viernes.", }, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/structured_outputs_basic.py b/structured_outputs_basic.py index d48cb86..36ae89a 100644 --- a/structured_outputs_basic.py +++ b/structured_outputs_basic.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -39,19 +35,19 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extract the event information."}, {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/structured_outputs_description.py b/structured_outputs_description.py index f62ad02..9e51d28 100644 --- a/structured_outputs_description.py +++ b/structured_outputs_description.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -39,22 +35,22 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ { "role": "system", "content": "Extract the event information. If no year is specified, assume the current year (2025).", }, {"role": "user", "content": "Alice and Bob are going to a science fair on the 1st of april."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) CalendarEvent(name="Science Fair", date="2025-04-01", participants=["Alice", "Bob"]) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/structured_outputs_enum.py b/structured_outputs_enum.py index 2961235..7ebd69b 100644 --- a/structured_outputs_enum.py +++ b/structured_outputs_enum.py @@ -9,14 +9,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -25,10 +25,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -50,19 +46,19 @@ class CalendarEvent(BaseModel): participants: list[str] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extract the event information."}, {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) diff --git a/structured_outputs_function_calling.py b/structured_outputs_function_calling.py index 07bb5c2..ff10903 100644 --- a/structured_outputs_function_calling.py +++ b/structured_outputs_function_calling.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -37,13 +33,32 @@ class GetDeliveryDate(BaseModel): order_id: str -response = client.chat.completions.create( +response = client.responses.create( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "You're a customer support bot. Use the tools to assist the user."}, {"role": "user", "content": "Hi, can you tell me the delivery date for my order #12345?"}, ], - tools=[openai.pydantic_function_tool(GetDeliveryDate)], + tools=[ + { + "type": "function", + "name": "GetDeliveryDate", + "description": "Get the delivery date for a customer's order.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "order_id": {"type": "string"}, + }, + "required": ["order_id"], + "additionalProperties": False, + }, + } + ], + store=False, ) -rich.print(response.choices[0].message.tool_calls[0].function) +tool_calls = [item for item in response.output if item.type == "function_call"] +if tool_calls: + rich.print(f"name={tool_calls[0].name}") + rich.print(f"arguments={tool_calls[0].arguments}") diff --git a/structured_outputs_nested.py b/structured_outputs_nested.py index 92c3528..1adbf20 100644 --- a/structured_outputs_nested.py +++ b/structured_outputs_nested.py @@ -8,14 +8,14 @@ # Setup the OpenAI client to use either Azure, OpenAI.com, or Ollama API load_dotenv(override=True) -API_HOST = os.getenv("API_HOST", "github") +API_HOST = os.getenv("API_HOST", "azure") if API_HOST == "azure": token_provider = azure.identity.get_bearer_token_provider( azure.identity.DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) client = openai.OpenAI( - base_url=os.environ["AZURE_OPENAI_ENDPOINT"], + base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/", api_key=token_provider, ) MODEL_NAME = os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"] @@ -24,10 +24,6 @@ client = openai.OpenAI(base_url=os.environ["OLLAMA_ENDPOINT"], api_key="nokeyneeded") MODEL_NAME = os.environ["OLLAMA_MODEL"] -elif API_HOST == "github": - client = openai.OpenAI(base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"]) - MODEL_NAME = os.getenv("GITHUB_MODEL", "openai/gpt-4o") - else: client = openai.OpenAI(api_key=os.environ["OPENAI_KEY"]) MODEL_NAME = os.environ["OPENAI_MODEL"] @@ -44,19 +40,19 @@ class CalendarEvent(BaseModel): participants: list[Participant] -completion = client.beta.chat.completions.parse( +completion = client.responses.parse( model=MODEL_NAME, - messages=[ + input=[ {"role": "system", "content": "Extract the event information."}, {"role": "user", "content": "Alice the carpenter and Bob the plumber are going to a science fair on Friday."}, ], - response_format=CalendarEvent, + text_format=CalendarEvent, + store=False, ) -message = completion.choices[0].message -if message.refusal: - rich.print(message.refusal) -else: - event = message.parsed +if completion.output_parsed: + event = completion.output_parsed rich.print(event) +else: + rich.print(completion.output_text) From 6f2e5a40485da6088f780ad0678e251e37da1f49 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Mon, 6 Apr 2026 10:14:05 -0700 Subject: [PATCH 2/3] Address PR review: nullable tool params, fix year, fix Spanish typos --- function_calling_call.py | 4 ++-- function_calling_extended.py | 4 ++-- spanish/chat.py | 2 +- spanish/few_shot_examples.py | 2 +- spanish/function_calling_call.py | 4 ++-- spanish/function_calling_extended.py | 4 ++-- spanish/rag_csv.py | 2 +- spanish/structured_outputs_description.py | 4 ++-- structured_outputs_description.py | 3 +-- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/function_calling_call.py b/function_calling_call.py index 2362423..47cbfd1 100644 --- a/function_calling_call.py +++ b/function_calling_call.py @@ -44,11 +44,11 @@ def lookup_weather(city_name=None, zip_code=None): "type": "object", "properties": { "city_name": { - "type": "string", + "type": ["string", "null"], "description": "The city name", }, "zip_code": { - "type": "string", + "type": ["string", "null"], "description": "The zip code", }, }, diff --git a/function_calling_extended.py b/function_calling_extended.py index 7d496ea..cf866ef 100644 --- a/function_calling_extended.py +++ b/function_calling_extended.py @@ -48,11 +48,11 @@ def lookup_weather(city_name=None, zip_code=None): "type": "object", "properties": { "city_name": { - "type": "string", + "type": ["string", "null"], "description": "The city name", }, "zip_code": { - "type": "string", + "type": ["string", "null"], "description": "The zip code", }, }, diff --git a/spanish/chat.py b/spanish/chat.py index 83a9361..098150b 100644 --- a/spanish/chat.py +++ b/spanish/chat.py @@ -37,5 +37,5 @@ store=False, ) -print(f"Repuesta de {API_HOST}: \n") +print(f"Respuesta de {API_HOST}: \n") print(response.output_text) diff --git a/spanish/few_shot_examples.py b/spanish/few_shot_examples.py index 117107a..a2e6064 100644 --- a/spanish/few_shot_examples.py +++ b/spanish/few_shot_examples.py @@ -53,5 +53,5 @@ ) -print(f"Repuesta de {API_HOST}: \n") +print(f"Respuesta de {API_HOST}: \n") print(response.output_text) diff --git a/spanish/function_calling_call.py b/spanish/function_calling_call.py index 8f97fe9..da18413 100644 --- a/spanish/function_calling_call.py +++ b/spanish/function_calling_call.py @@ -44,11 +44,11 @@ def lookup_weather(city_name=None, zip_code=None): "type": "object", "properties": { "city_name": { - "type": "string", + "type": ["string", "null"], "description": "El nombre de la ciudad", }, "zip_code": { - "type": "string", + "type": ["string", "null"], "description": "El código postal", }, }, diff --git a/spanish/function_calling_extended.py b/spanish/function_calling_extended.py index b38480c..eb065a6 100644 --- a/spanish/function_calling_extended.py +++ b/spanish/function_calling_extended.py @@ -48,11 +48,11 @@ def lookup_weather(city_name=None, zip_code=None): "type": "object", "properties": { "city_name": { - "type": "string", + "type": ["string", "null"], "description": "The city name", }, "zip_code": { - "type": "string", + "type": ["string", "null"], "description": "The zip code", }, }, diff --git a/spanish/rag_csv.py b/spanish/rag_csv.py index 941884e..5384099 100644 --- a/spanish/rag_csv.py +++ b/spanish/rag_csv.py @@ -68,5 +68,5 @@ store=False, ) -print(f"\nRespuest de {API_HOST}: \n") +print(f"\nRespuesta de {API_HOST}: \n") print(response.output_text) diff --git a/spanish/structured_outputs_description.py b/spanish/structured_outputs_description.py index c35c458..71c679f 100644 --- a/spanish/structured_outputs_description.py +++ b/spanish/structured_outputs_description.py @@ -40,14 +40,14 @@ class CalendarEvent(BaseModel): input=[ { "role": "system", - "content": "Extrae la info del evento. Si no dice el año, asumí que es este año (2025).", + "content": "Extrae la info del evento. Si no dice el año, asumí que es este año (2026).", }, {"role": "user", "content": "Alice y Bob van a ir a una feria de ciencias el 1 de abril."}, ], text_format=CalendarEvent, store=False, ) -CalendarEvent(name="Feria de Ciencias", date="2025-04-01", participants=["Alice", "Bob"]) + if completion.output_parsed: event = completion.output_parsed rich.print(event) diff --git a/structured_outputs_description.py b/structured_outputs_description.py index 9e51d28..724505a 100644 --- a/structured_outputs_description.py +++ b/structured_outputs_description.py @@ -40,14 +40,13 @@ class CalendarEvent(BaseModel): input=[ { "role": "system", - "content": "Extract the event information. If no year is specified, assume the current year (2025).", + "content": "Extract the event information. If no year is specified, assume the current year (2026).", }, {"role": "user", "content": "Alice and Bob are going to a science fair on the 1st of april."}, ], text_format=CalendarEvent, store=False, ) -CalendarEvent(name="Science Fair", date="2025-04-01", participants=["Alice", "Bob"]) if completion.output_parsed: event = completion.output_parsed From ae9d40d7d61dae3336c5dcda7455b1d4f13ce44e Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Mon, 6 Apr 2026 13:20:33 -0700 Subject: [PATCH 3/3] Fix mismatched call_id in Spanish fewshots --- spanish/function_calling_fewshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanish/function_calling_fewshots.py b/spanish/function_calling_fewshots.py index 0588dfe..ec87ff7 100644 --- a/spanish/function_calling_fewshots.py +++ b/spanish/function_calling_fewshots.py @@ -103,7 +103,7 @@ def search_database(search_query: str, price_filter: dict | None = None) -> dict }, { "type": "function_call_output", - "call_id": "fc_abc123", + "call_id": "call_abc123", "output": json.dumps({"result": "Resultados de búsqueda para equipo de escalada exterior: ..."}), }, {"role": "user", "content": "¿Hay tenis por menos de $50?"},