import json
import math
import os
from openai import OpenAI, APIStatusError, APIConnectionError
tools = [{"type": "function", "function": {
"name": "celsius_to_fahrenheit",
"description": "Convert Celsius to Fahrenheit.",
"parameters": {"type": "object", "properties": {
"celsius": {"type": "number", "minimum": -273.15, "maximum": 10000}
}, "required": ["celsius"], "additionalProperties": False}
}}]
def execute(name, arguments):
if name != "celsius_to_fahrenheit":
return {"error": "Unknown tool"}
try:
args = json.loads(arguments)
if not isinstance(args, dict) or set(args) != {"celsius"}:
raise ValueError("Expected celsius only")
value = args["celsius"]
if isinstance(value, bool) or not isinstance(value, (int, float)):
raise ValueError("Expected a number")
if not math.isfinite(value) or not -273.15 <= value <= 10000:
raise ValueError("Temperature out of range")
return {"celsius": value, "fahrenheit": round(value * 9 / 5 + 32, 6)}
except (ValueError, TypeError):
return {"error": "Invalid tool arguments"}
messages = [{"role": "user", "content": "Use the tool to convert 25 Celsius to Fahrenheit."}]
try:
with OpenAI(base_url="https://api.apione.ai/v1",
api_key=os.environ["APIONE_API_KEY"],
timeout=60, max_retries=0) as client:
for round_number in range(4):
raw = client.chat.completions.with_raw_response.create(
model=os.environ["APIONE_MODEL"], messages=messages,
tools=tools, tool_choice="auto")
ids = {name: raw.headers[name] for name in
("X-Request-ID", "X-Maxx-Trace-Id", "X-Maxx-Request-ID")
if name in raw.headers}
print("request identifiers:", ids)
result = raw.parse()
if not result.choices:
raise RuntimeError("No choices returned")
message = result.choices[0].message
calls = message.tool_calls or []
if not calls:
print(message.content)
break
if len(calls) > 8:
raise RuntimeError("Too many tool calls")
messages.append(message.model_dump(exclude_none=True))
for call in calls:
output = execute(call.function.name, call.function.arguments)
messages.append({"role": "tool", "tool_call_id": call.id,
"content": json.dumps(output)})
else:
raise RuntimeError("Tool-call round limit reached")
except APIStatusError as error:
print("HTTP status:", error.status_code)
headers = error.response.headers
print("request identifiers:", {name: headers[name] for name in
("X-Request-ID", "X-Maxx-Trace-Id", "X-Maxx-Request-ID") if name in headers})
raise SystemExit(1) from None
except APIConnectionError:
print("Connection failed: no HTTP response or server request ID received.")
raise SystemExit(1) from None