MetaRec / MetaRec-backend /client.py
Hanny658's picture
clean: Removed legacy no-caller functions/modules
95b1416
Raw
History Blame Contribute Delete
3.89 kB
import os
import httpx
from openai import AsyncAzureOpenAI, AzureOpenAI, AsyncOpenAI, OpenAI
from dotenv import load_dotenv, find_dotenv
# tries to find .env in current path, or traverses parent directories until found
dotenv_path = find_dotenv()
load_dotenv(dotenv_path)
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
AZURE_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT", "https://agenthiack.openai.azure.com/")
AZURE_API_VERSION = os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
DEFAULT_OPENAI_COMPATIBLE_BASE_URL = "https://api.groq.com/openai/v1"
def _first_env_value(*names: str, default: str = "") -> str:
for name in names:
value = os.getenv(name)
if value:
return value.strip()
return default
def _env_bool(name: str, default: bool) -> bool:
value = os.getenv(name)
if value is None:
return default
return value.strip().lower() not in {"0", "false", "no", "off"}
def _env_int(name: str, default: int, *, min_value: int = 0) -> int:
try:
return max(min_value, int(os.getenv(name, str(default))))
except (TypeError, ValueError):
return default
def _env_float(name: str, default: float, *, min_value: float = 0.1) -> float:
try:
return max(min_value, float(os.getenv(name, str(default))))
except (TypeError, ValueError):
return default
def get_openai_compatible_config() -> tuple[str, str]:
"""Return API key and base URL for OpenAI-compatible providers.
LLM_* variables are canonical for MetaRec. OPENAI_COMPAT* aliases make it
clear that this client targets the OpenAI-compatible API surface, not the
Azure OpenAI client used by the legacy agent modules.
"""
api_key = _first_env_value(
"LLM_API_KEY",
"OPENAI_COMPAT_API_KEY",
"OPENAI_COMPATIBLE_API_KEY",
"GROQ_API_KEY",
)
base_url = _first_env_value(
"LLM_BASE_URL",
"OPENAI_COMPAT_BASE_URL",
"OPENAI_COMPATIBLE_BASE_URL",
"GROQ_BASE_URL",
default=DEFAULT_OPENAI_COMPATIBLE_BASE_URL,
).rstrip("/")
return api_key, base_url
def get_openai_compatible_transport_config() -> dict[str, object]:
return {
"timeout": _env_float("LLM_TIMEOUT_SECONDS", 30.0),
"max_retries": _env_int("LLM_SDK_MAX_RETRIES", 2),
"trust_env": _env_bool("LLM_TRUST_ENV", True),
}
def describe_openai_compatible_config(model: str | None = None) -> str:
transport = get_openai_compatible_transport_config()
return (
f"base_url={LLM_BASE_URL} "
f"model={model or os.getenv('LLM_MODEL') or '(unset)'} "
f"api_key_configured={bool(LLM_API_KEY)} "
f"timeout={transport['timeout']} "
f"max_retries={transport['max_retries']} "
f"trust_env={transport['trust_env']}"
)
def _client_kwargs(async_client: bool = False) -> dict[str, object]:
transport = get_openai_compatible_transport_config()
kwargs: dict[str, object] = {
"base_url": LLM_BASE_URL,
"api_key": LLM_API_KEY,
"max_retries": transport["max_retries"],
}
timeout = transport["timeout"]
if transport["trust_env"]:
kwargs["timeout"] = timeout
elif async_client:
kwargs["http_client"] = httpx.AsyncClient(timeout=timeout, trust_env=False)
else:
kwargs["http_client"] = httpx.Client(timeout=timeout, trust_env=False)
return kwargs
LLM_API_KEY, LLM_BASE_URL = get_openai_compatible_config()
def create_sync_client():
client = OpenAI(**_client_kwargs(async_client=False))
return client
def create_sync_azure_client():
client = AzureOpenAI(
azure_endpoint=AZURE_ENDPOINT,
api_key=OPENAI_API_KEY,
api_version=AZURE_API_VERSION,
)
return client
def create_async_client():
client = AsyncOpenAI(**_client_kwargs(async_client=True))
return client