AQIT 0.1.0
Loading...
Searching...
No Matches
openai_client.py
Go to the documentation of this file.
1# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2# This file is part of the Aquin Engine. Unauthorized copying, modification,
3# distribution, or use of this file, via any medium, is strictly prohibited.
4# Proprietary and confidential. See LICENSE for terms.
5
6"""OpenAI client for GPU tools — local key or Aquin web proxy (same as aquin chat)."""
7from __future__ import annotations
8
9import json
10import os
11from pathlib import Path
12from types import SimpleNamespace
13from typing import Any
14
15import httpx
16
17_CONFIG_PATH = Path.home() / ".aquin" / "config.json"
18_ENGINE_STATE = Path.home() / ".aquin" / "engine.json"
19
20
21def _read_json(path: Path) -> dict[str, str]:
22 if not path.exists():
23 return {}
24 try:
25 data = json.loads(path.read_text(encoding="utf-8"))
26 return data if isinstance(data, dict) else {}
27 except Exception:
28 return {}
29
30
31def _saved_api_key() -> str:
32 from aquin.auth_config import resolve_api_key
33 return resolve_api_key(allow_missing=True)
34
37 def __init__(self, proxy: "AquinOpenAIProxy") -> None:
38 self._proxy = proxy
39
40 def create(self, **kwargs: Any) -> Any:
41 payload = {k: v for k, v in kwargs.items() if v is not None}
42 data = self._proxy._chat(payload)
43 choice = (data.get("choices") or [{}])[0]
44 message = choice.get("message") or {}
45 return SimpleNamespace(
46 choices=[SimpleNamespace(message=SimpleNamespace(content=message.get("content", "")))]
47 )
48
49
51 def __init__(self, proxy: "AquinOpenAIProxy") -> None:
52 self._proxy = proxy
53
54 def create(self, **kwargs: Any) -> Any:
55 payload = {k: v for k, v in kwargs.items() if v is not None}
56 data = self._proxy._embeddings(payload)
57 rows = data.get("data") or []
58 return SimpleNamespace(
59 data=[SimpleNamespace(embedding=row.get("embedding", [])) for row in rows]
60 )
61
62
64 """Uses OPENAI_API_KEY from the Next.js app (Bearer AQUIN_API_KEY), like aquin chat."""
65
66 def __init__(self, api_key: str, base_url: str, session_id: str = "") -> None:
67 self._api_key = api_key
68 self._base_url = base_url.rstrip("/")
69 self._session_id = session_id.strip()
70 self.chat = SimpleNamespace(completions=_ProxyChatCompletions(self))
73 def _headers(self) -> dict[str, str]:
74 return {"Authorization": f"Bearer {self._api_key}"}
76 def _post(self, path: str, payload: dict[str, Any]) -> dict[str, Any]:
77 url = f"{self._base_url}{path}"
78 resp = httpx.post(
79 url,
80 json=payload,
81 headers=self._headers(),
82 timeout=120.0,
83 )
84 if resp.status_code >= 400:
85 raise RuntimeError(
86 f"OpenAI proxy {path} failed ({resp.status_code}) at {url}: {resp.text[:300]}"
87 )
88 return resp.json()
89
90 def _chat(self, payload: dict[str, Any]) -> dict[str, Any]:
91 body = {**payload, "stream": False}
92 if self._session_id:
93 return self._post(f"/api/sync/sessions/{self._session_id}/agent", body)
94 return self._post("/api/sync/openai/chat", body)
95
96 def _embeddings(self, payload: dict[str, Any]) -> dict[str, Any]:
97 if self._session_id:
98 return self._post(f"/api/sync/sessions/{self._session_id}/embeddings", payload)
99 return self._post("/api/sync/openai/embeddings", payload)
101
102def get_openai_client(ctx: dict[str, Any] | None = None) -> Any | None:
103 """
104 Prefer local OPENAI_API_KEY; otherwise proxy via Aquin web (AQUIN_API_KEY + base URL).
105 Chat uses /api/sync/sessions/{id}/agent — same path as aquin chat.
106 """
107 local_key = os.environ.get("OPENAI_API_KEY", "").strip()
108 if local_key:
109 try:
110 from openai import OpenAI
111 return OpenAI(api_key=local_key)
112 except Exception:
113 return None
114
115 cfg = _read_json(_ENGINE_STATE)
116 c = ctx or {}
117 api_key = (
118 c.get("api_key")
119 or _saved_api_key()
120 or os.environ.get("AQUIN_API_KEY", "").strip()
121 or cfg.get("api_key", "").strip()
122 )
123 base_url = (
124 c.get("base_url")
125 or os.environ.get("AQUIN_BASE_URL", "").strip()
126 or cfg.get("base_url", "").strip()
127 or "https://api.aquin.app"
128 )
129 session_id = c.get("session_id") or ""
130 if api_key:
131 return AquinOpenAIProxy(api_key, base_url, session_id=session_id)
132 return None
dict[str, Any] _embeddings(self, dict[str, Any] payload)
dict[str, Any] _post(self, str path, dict[str, Any] payload)
None __init__(self, str api_key, str base_url, str session_id="")
dict[str, Any] _chat(self, dict[str, Any] payload)
None __init__(self, "AquinOpenAIProxy" proxy)
None __init__(self, "AquinOpenAIProxy" proxy)
dict[str, str] _read_json(Path path)
Any|None get_openai_client(dict[str, Any]|None ctx=None)