GitHub Actions
Clean sync from GitHub - no large files in history
1390f29
Raw History Blame Contribute Delete
5.85 kB
#!/usr/bin/env python3
"""
Validate that the configured Azure OpenAI resource supports the Responses
API before enabling USE_RESPONSES_API=true (see .env.example and
agents/analyzer.py / agents/synthesis.py).
Responses API requires a specific minimum preview api-version and has
historically had narrower deployment/region availability than Chat
Completions -- this is a required go/no-go check, not an assumption
(this codebase has been burned before by unverified API-version
assumptions; see AZURE_API_VERSION_FIX.md and CLAUDE.md's version history).
Run: python scripts/validate_responses_api.py
"""
import os
import sys
from dotenv import load_dotenv
from openai import AzureOpenAI
load_dotenv()
# Ordered oldest -> newest. Azure OpenAI's own error message names the exact
# minimum version it requires, so this list only needs to bracket that value
# closely enough to report it -- it is not meant to be exhaustive.
CANDIDATE_VERSIONS = [
"2024-05-01-preview",
"2024-08-01-preview",
"2024-10-01-preview",
"2024-12-01-preview",
"2025-01-01-preview",
"2025-02-01-preview",
"2025-03-01-preview",
"2025-04-01-preview",
]
def _try_responses_call(client: AzureOpenAI, deployment: str) -> tuple[bool, str]:
try:
response = client.responses.create(
model=deployment,
instructions="You are a helpful assistant.",
input="Say hello in one word.",
max_output_tokens=20,
)
return True, response.output_text
except Exception as e:
return False, str(e)
def main() -> bool:
print("=" * 80)
print("Validating Azure OpenAI Responses API availability")
print("=" * 80)
print()
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
api_key = os.getenv("AZURE_OPENAI_API_KEY")
deployment = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME")
configured_version = os.getenv("AZURE_OPENAI_API_VERSION", "2024-02-01")
print(f"Endpoint: {endpoint}")
print(f"Deployment: {deployment}")
print(f"Currently configured AZURE_OPENAI_API_VERSION: {configured_version}")
print()
# Step 1: does the *currently configured* version work?
client = AzureOpenAI(api_key=api_key, api_version=configured_version, azure_endpoint=endpoint)
ok, detail = _try_responses_call(client, deployment)
if ok:
print(f"βœ… Responses API works with your CURRENT AZURE_OPENAI_API_VERSION ({configured_version}).")
print(f" Sample output: {detail!r}")
print()
print("Safe to set USE_RESPONSES_API=true without changing AZURE_OPENAI_API_VERSION.")
return True
print(f"❌ Responses API failed at your current API version ({configured_version}):")
print(f" {detail[:200]}")
print()
print("Probing newer API versions to find the minimum that works...")
print()
working_version = None
for v in CANDIDATE_VERSIONS:
client = AzureOpenAI(api_key=api_key, api_version=v, azure_endpoint=endpoint)
ok, detail = _try_responses_call(client, deployment)
status = "βœ… SUCCESS" if ok else "❌ failed"
print(f" {v}: {status}" + ("" if ok else f" ({detail[:120]})"))
if ok:
working_version = v
break
print()
if not working_version:
print("=" * 80)
print("❌ Responses API is NOT available on this resource/deployment/region")
print(" at any of the probed API versions.")
print(" USE_RESPONSES_API=true would fall back to Chat Completions on every")
print(" call (the code degrades gracefully), but that means no benefit from")
print(" enabling the flag -- leave it false until this is resolved with Azure.")
print("=" * 80)
return False
print("=" * 80)
print(f"βœ… Responses API works starting at api-version {working_version}")
print()
print("Before enabling USE_RESPONSES_API=true, also confirm the embeddings call")
print("(rag/embeddings.py) and Chat Completions fallback path still work if you")
print("bump AZURE_OPENAI_API_VERSION -- both currently read the same env var.")
print("=" * 80)
# Step 2: confirm embeddings and Chat Completions still work at the
# newer version, since rag/embeddings.py reads the SAME
# AZURE_OPENAI_API_VERSION env var (falls back to "2024-02-01" only if
# unset) -- bumping it for Responses API is a global change, not scoped
# to the analyzer/synthesis agents.
embedding_deployment = os.getenv("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME")
client = AzureOpenAI(api_key=api_key, api_version=working_version, azure_endpoint=endpoint)
if embedding_deployment:
try:
resp = client.embeddings.create(input="test", model=embedding_deployment)
print(f"βœ… Embeddings still work at {working_version} (dim={len(resp.data[0].embedding)})")
except Exception as e:
print(f"⚠️ Embeddings FAILED at {working_version}: {str(e)[:150]}")
print(" Do not bump AZURE_OPENAI_API_VERSION globally without resolving this --")
print(" consider a separate api_version for rag/embeddings.py instead.")
try:
resp = client.chat.completions.create(
model=deployment,
messages=[{"role": "user", "content": "Say hi in one word."}],
temperature=0,
max_tokens=10,
)
print(f"βœ… Chat Completions fallback path still works at {working_version}")
except Exception as e:
print(f"⚠️ Chat Completions FAILED at {working_version}: {str(e)[:150]}")
print()
print(f"Next step: set AZURE_OPENAI_API_VERSION={working_version} in .env, then")
print("USE_RESPONSES_API=true.")
return True
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)