code2video/gpt_request.py
2025-09-29 08:30:07 +00:00

1062 lines
37 KiB
Python

import openai
import time
import random
import os
import base64
from openai import OpenAI
import time
import json
import pathlib
# Read and cache once
_CFG_PATH = pathlib.Path(__file__).with_name("api_config.json")
with _CFG_PATH.open("r", encoding="utf-8") as _f:
_CFG = json.load(_f)
def cfg(svc: str, key: str, default=None):
return os.getenv(f"{svc}_{key}".upper(), _CFG.get(svc, {}).get(key, default))
def generate_log_id():
"""Generate a log ID with 'tkb' prefix and current timestamp."""
return f"tkb{int(time.time() * 1000)}"
def request_claude(prompt, log_id=None, max_tokens=16384, max_retries=3):
base_url = cfg("claude", "base_url")
api_key = cfg("claude", "api_key")
client = OpenAI(base_url=base_url, api_key=api_key)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
retry_count = 0
while retry_count < max_retries:
try:
response = client.chat.completions.create(
model="claude-4-opus",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt,
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return response.choices[0].message.content.strip()
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_claude_token(prompt, log_id=None, max_tokens=10000, max_retries=3):
base_url = cfg("claude", "base_url")
api_key = cfg("claude", "api_key")
client = OpenAI(base_url=base_url, api_key=api_key)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model="claude-4-opus",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt,
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
# --- MODIFIED: token usage ---
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_gemini_with_video(prompt: str, video_path: str, log_id=None, max_tokens: int = 10000, max_retries: int = 3):
"""
Makes a multimodal request to the Gemini-2.5 model using video + text.
Args:
prompt (str): The user instruction, e.g., "Please evaluate and suggest improvements for this educational animation."
video_path (str): Local path to the video file (MP4 preferred, <20MB recommended).
log_id (str, optional): Tracking ID
max_tokens (int): Max response token length
max_retries (int): Max retry attempts
Returns:
dict: The Gemini model response
"""
base_url = cfg("gemini", "base_url")
api_version = cfg("gemini", "api_version")
api_key = cfg("gemini", "api_key")
model_name = cfg("gemini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
# Load and base64-encode video
if not os.path.exists(video_path):
raise FileNotFoundError(f"Video not found: {video_path}")
with open(video_path, "rb") as f:
video_bytes = f.read()
video_base64 = base64.b64encode(video_bytes).decode("utf-8")
data_url = f"data:video/mp4;base64,{video_base64}"
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": data_url, "detail": "high"}, "media_type": "video/mp4"},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
delay = (2**retry_count) * 0.2 + random.random() * 0.2
print(f"Retry {retry_count}/{max_retries} after error: {e}, waiting {delay:.2f}s...")
time.sleep(delay)
def request_gemini_video_img(
prompt: str, video_path: str, image_path: str, log_id=None, max_tokens: int = 10000, max_retries: int = 3
):
"""
Makes a multimodal request to the Gemini-2.5 model using video & ref img + text.
Args:
prompt (str): The user instruction, e.g., "Please evaluate and suggest improvements for this educational animation."
video_path (str): Local path to the video file (MP4 preferred, <20MB recommended).
log_id (str, optional): Tracking ID
max_tokens (int): Max response token length
max_retries (int): Max retry attempts
Returns:
dict: The Gemini model response
"""
base_url = cfg("gemini", "base_url")
api_version = cfg("gemini", "api_version")
api_key = cfg("gemini", "api_key")
model_name = cfg("gemini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
# Load and base64-encode video
if not os.path.exists(video_path):
raise FileNotFoundError(f"Video not found: {video_path}")
with open(video_path, "rb") as f:
video_bytes = f.read()
video_base64 = base64.b64encode(video_bytes).decode("utf-8")
video_data_url = f"data:video/mp4;base64,{video_base64}"
if not os.path.isfile(image_path):
raise FileNotFoundError(f"Image file not found: {image_path}")
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
image_data_url = f"data:image/png;base64,{base64_image}"
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {"url": video_data_url, "detail": "high"},
"media_type": "video/mp4",
},
{
"type": "image_url",
"image_url": {"url": image_data_url, "detail": "high"},
"media_type": "image/png",
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
delay = (2**retry_count) * 0.2 + random.random() * 0.2
print(f"Retry {retry_count}/{max_retries} after error: {e}, waiting {delay:.2f}s...")
time.sleep(delay)
return None
def request_gemini_video_img_token(
prompt: str, video_path: str, image_path: str, log_id=None, max_tokens: int = 10000, max_retries: int = 3
):
"""
Makes a multimodal request to the Gemini-2.5 model using video & ref img + text.
Args:
prompt (str): The user instruction, e.g., "Please evaluate and suggest improvements for this educational animation."
video_path (str): Local path to the video file (MP4 preferred, <20MB recommended).
log_id (str, optional): Tracking ID
max_tokens (int): Max response token length
max_retries (int): Max retry attempts
Returns:
dict: The Gemini model response
"""
base_url = cfg("gemini", "base_url")
api_version = cfg("gemini", "api_version")
api_key = cfg("gemini", "api_key")
model_name = cfg("gemini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
# Load and base64-encode video
if not os.path.exists(video_path):
raise FileNotFoundError(f"Video not found: {video_path}")
with open(video_path, "rb") as f:
video_bytes = f.read()
video_base64 = base64.b64encode(video_bytes).decode("utf-8")
video_data_url = f"data:video/mp4;base64,{video_base64}"
if not os.path.isfile(image_path):
raise FileNotFoundError(f"Image file not found: {image_path}")
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
image_data_url = f"data:image/png;base64,{base64_image}"
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {"url": video_data_url, "detail": "high"},
"media_type": "video/mp4",
},
{
"type": "image_url",
"image_url": {"url": image_data_url, "detail": "high"},
"media_type": "image/png",
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
# return completion
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
delay = (2**retry_count) * 0.2 + random.random() * 0.2
print(f"Retry {retry_count}/{max_retries} after error: {e}, waiting {delay:.2f}s...")
time.sleep(delay)
return None, usage_info
def request_gemini(prompt, log_id=None, max_tokens=8000, max_retries=3):
"""
Makes a request to the gemini-2.5-pro-preview-03-25 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gemini", "base_url")
api_version = cfg("gemini", "api_version")
api_key = cfg("gemini", "api_key")
model_name = cfg("gemini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_gemini_token(prompt, log_id=None, max_tokens=8000, max_retries=3):
"""
Makes a request to the gemini-2.5-pro-preview-03-25 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gemini", "base_url")
api_version = cfg("gemini", "api_version")
api_key = cfg("gemini", "api_key")
model_name = cfg("gemini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_gpt4o(prompt, log_id=None, max_tokens=8000, max_retries=3):
"""
Makes a request to the gpt-4o-2024-11-20 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt4o", "base_url")
api_version = cfg("gpt4o", "api_version")
ak = cfg("gpt4o", "api_key")
model_name = cfg("gpt4o", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt,
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion.choices[0].message.content
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_gpt4o_token(prompt, log_id=None, max_tokens=8000, max_retries=3):
"""
Makes a request to the gpt-4o-2024-11-20 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt4o", "base_url")
api_version = cfg("gpt4o", "api_version")
ak = cfg("gpt4o", "api_key")
model_name = cfg("gpt4o", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt,
},
],
}
],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_o4mini(prompt, log_id=None, max_tokens=8000, max_retries=3, thinking=False):
"""
Makes a request to the o4-mini-2025-04-16 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
thinking (bool, optional): Whether to enable thinking mode, default False
Returns:
dict: The model's response
"""
base_url = cfg("gpt4omini", "base_url")
api_version = cfg("gpt4omini", "api_version")
ak = cfg("gpt4omini", "api_key")
model_name = cfg("gpt4omini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
# Configure extra_body for thinking if enabled
extra_body = None
if thinking:
extra_body = {"thinking": {"type": "enabled", "budget_tokens": 2000}}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
extra_body=extra_body,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_o4mini_token(prompt, log_id=None, max_tokens=8000, max_retries=3, thinking=False):
"""
Makes a request to the o4-mini-2025-04-16 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 8000
max_retries (int, optional): Maximum number of retry attempts, default 3
thinking (bool, optional): Whether to enable thinking mode, default False
Returns:
dict: The model's response
"""
base_url = cfg("gpt4omini", "base_url")
api_version = cfg("gpt4omini", "api_version")
ak = cfg("gpt4omini", "api_key")
model_name = cfg("gpt4omini", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
# Configure extra_body for thinking if enabled
extra_body = None
if thinking:
extra_body = {"thinking": {"type": "enabled", "budget_tokens": 2000}}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
extra_body=extra_body,
)
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_gpt5(prompt, log_id=None, max_tokens=1000, max_retries=3):
"""
Makes a request to the gpt-5-chat-2025-08-07 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 1000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt5", "base_url")
api_version = cfg("gpt5", "api_version")
ak = cfg("gpt5", "api_key")
model_name = cfg("gpt5", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_gpt5_token(prompt, log_id=None, max_tokens=1000, max_retries=3):
"""
Makes a request to the gpt-5-chat-2025-08-07 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 1000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt5", "base_url")
api_version = cfg("gpt5", "api_version")
ak = cfg("gpt5", "api_key")
model_name = cfg("gpt5", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_gpt41(prompt, log_id=None, max_tokens=1000, max_retries=3):
"""
Makes a request to the gpt-4.1-2025-04-14 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 1000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt41", "base_url")
api_version = cfg("gpt41", "api_version")
api_key = cfg("gpt41", "api_key")
model_name = cfg("gpt41", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=api_key,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
# Exponential backoff with jitter
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
def request_gpt41_token(prompt, log_id=None, max_tokens=1000, max_retries=3):
"""
Makes a request to the gpt-4.1-2025-04-14 model with retry functionality.
Args:
prompt (str): The text prompt to send to the model
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 1000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt41", "base_url")
api_version = cfg("gpt41", "api_version")
ak = cfg("gpt41", "api_key")
model_name = cfg("gpt41", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
usage_info = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
extra_headers=extra_headers,
)
if completion.usage:
usage_info["prompt_tokens"] = completion.usage.prompt_tokens
usage_info["completion_tokens"] = completion.usage.completion_tokens
usage_info["total_tokens"] = completion.usage.total_tokens
return completion, usage_info
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
# 即使失败也返回,以便主程序可以继续
print(f"Failed after {max_retries} attempts. Last error: {str(e)}")
return None, usage_info
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
return None, usage_info
def request_gpt41_img(prompt, image_path=None, log_id=None, max_tokens=1000, max_retries=3):
"""
Makes a request to the gpt-4.1-2025-04-14 model with optional image input and retry functionality.
Args:
prompt (str): The text prompt to send to the model
image_path (str, optional): Absolute path to an image file to include
log_id (str, optional): The log ID for tracking requests, defaults to tkb+timestamp
max_tokens (int, optional): Maximum tokens for response, default 1000
max_retries (int, optional): Maximum number of retry attempts, default 3
Returns:
dict: The model's response
"""
base_url = cfg("gpt41", "base_url")
api_version = cfg("gpt41", "api_version")
ak = cfg("gpt41", "api_key")
model_name = cfg("gpt41", "model")
client = openai.AzureOpenAI(
azure_endpoint=base_url,
api_version=api_version,
api_key=ak,
)
if log_id is None:
log_id = generate_log_id()
extra_headers = {"X-TT-LOGID": log_id}
if image_path:
# 检查图片路径是否存在
if not os.path.isfile(image_path):
raise FileNotFoundError(f"Image file not found: {image_path}")
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}},
],
}
]
else:
messages = [{"role": "user", "content": prompt}]
retry_count = 0
while retry_count < max_retries:
try:
completion = client.chat.completions.create(
model=model_name,
messages=messages,
max_tokens=max_tokens,
extra_headers=extra_headers,
)
return completion
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise Exception(f"Failed after {max_retries} attempts. Last error: {str(e)}")
delay = (2**retry_count) * 0.1 + (random.random() * 0.1)
print(
f"Request failed with error: {str(e)}. Retrying in {delay:.2f} seconds... (Attempt {retry_count}/{max_retries})"
)
time.sleep(delay)
if __name__ == "__main__":
# Gemini
# response_gemini = request_gemini("上海天气怎么样?")
# print(response_gemini.model_dump_json())
# # GPT-4o
# response_gpt4o = request_gpt4o("上海天气怎么样?")
# print(response_gpt4o)
# # o4-mini
# response_o4mini = request_o4mini("上海天气怎么样?")
# print(response_o4mini.model_dump_json())
# # GPT-4.1
response_gpt41 = request_gpt41("上海天气怎么样?")
print(response_gpt41.model_dump_json())
# GPT-5
# response_gpt5 = request_gpt5("新加坡天气怎么样?")
# print(response_gpt5.model_dump_json())
# # Claude
# response_claude = request_claude_token("新加坡天气怎么样?")
# print(response_claude)