aquin 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aquin-0.1.0/PKG-INFO +11 -0
- aquin-0.1.0/README.md +1 -0
- aquin-0.1.0/aquin/__init__.py +20 -0
- aquin-0.1.0/aquin/client.py +106 -0
- aquin-0.1.0/aquin/exceptions.py +30 -0
- aquin-0.1.0/pyproject.toml +17 -0
- aquin-0.1.0/test.py +9 -0
aquin-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aquin
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the Aquin model API
|
|
5
|
+
Project-URL: Homepage, https://aquin.app
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: httpx>=0.27.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
Aquin SDK
|
aquin-0.1.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Aquin SDK
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from aquin.client import AquinClient, CompletionResponse
|
|
2
|
+
from aquin.exceptions import (
|
|
3
|
+
AquinError,
|
|
4
|
+
InvalidKeyError,
|
|
5
|
+
InsufficientCreditsError,
|
|
6
|
+
RateLimitError,
|
|
7
|
+
ModelNotFoundError,
|
|
8
|
+
InferenceError,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"AquinClient",
|
|
13
|
+
"CompletionResponse",
|
|
14
|
+
"AquinError",
|
|
15
|
+
"InvalidKeyError",
|
|
16
|
+
"InsufficientCreditsError",
|
|
17
|
+
"RateLimitError",
|
|
18
|
+
"ModelNotFoundError",
|
|
19
|
+
"InferenceError",
|
|
20
|
+
]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from aquin.exceptions import (
|
|
4
|
+
AquinError,
|
|
5
|
+
InvalidKeyError,
|
|
6
|
+
InsufficientCreditsError,
|
|
7
|
+
RateLimitError,
|
|
8
|
+
ModelNotFoundError,
|
|
9
|
+
InferenceError,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
DEFAULT_BASE_URL = "https://www.aquin.app"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class CompletionResponse:
|
|
17
|
+
text: str
|
|
18
|
+
tokens_in: int
|
|
19
|
+
tokens_out: int
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AquinClient:
|
|
23
|
+
def __init__(self, api_key: str, base_url: str = DEFAULT_BASE_URL):
|
|
24
|
+
if not api_key:
|
|
25
|
+
raise ValueError("api_key is required")
|
|
26
|
+
self._api_key = api_key
|
|
27
|
+
self._base_url = base_url.rstrip("/")
|
|
28
|
+
|
|
29
|
+
def complete(
|
|
30
|
+
self,
|
|
31
|
+
prompt: str,
|
|
32
|
+
max_tokens: int = 512,
|
|
33
|
+
temperature: float = 0.7,
|
|
34
|
+
) -> CompletionResponse:
|
|
35
|
+
try:
|
|
36
|
+
res = httpx.post(
|
|
37
|
+
f"{self._base_url}/api/v1/model",
|
|
38
|
+
headers={
|
|
39
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
},
|
|
42
|
+
json={
|
|
43
|
+
"prompt": prompt,
|
|
44
|
+
"max_tokens": max_tokens,
|
|
45
|
+
"temperature": temperature,
|
|
46
|
+
},
|
|
47
|
+
timeout=120,
|
|
48
|
+
follow_redirects=True,
|
|
49
|
+
)
|
|
50
|
+
except httpx.ConnectError:
|
|
51
|
+
raise InferenceError("Could not connect to Aquin API.")
|
|
52
|
+
except httpx.TimeoutException:
|
|
53
|
+
raise InferenceError("Request timed out.")
|
|
54
|
+
|
|
55
|
+
return self._handle_response(res)
|
|
56
|
+
|
|
57
|
+
async def acomplete(
|
|
58
|
+
self,
|
|
59
|
+
prompt: str,
|
|
60
|
+
max_tokens: int = 512,
|
|
61
|
+
temperature: float = 0.7,
|
|
62
|
+
) -> CompletionResponse:
|
|
63
|
+
async with httpx.AsyncClient() as client:
|
|
64
|
+
try:
|
|
65
|
+
res = await client.post(
|
|
66
|
+
f"{self._base_url}/api/v1/model",
|
|
67
|
+
headers={
|
|
68
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
},
|
|
71
|
+
json={
|
|
72
|
+
"prompt": prompt,
|
|
73
|
+
"max_tokens": max_tokens,
|
|
74
|
+
"temperature": temperature,
|
|
75
|
+
},
|
|
76
|
+
timeout=120,
|
|
77
|
+
follow_redirects=True,
|
|
78
|
+
)
|
|
79
|
+
except httpx.ConnectError:
|
|
80
|
+
raise InferenceError("Could not connect to Aquin API.")
|
|
81
|
+
except httpx.TimeoutException:
|
|
82
|
+
raise InferenceError("Request timed out.")
|
|
83
|
+
|
|
84
|
+
return self._handle_response(res)
|
|
85
|
+
|
|
86
|
+
def _handle_response(self, res: httpx.Response) -> CompletionResponse:
|
|
87
|
+
if res.status_code == 200:
|
|
88
|
+
data = res.json()
|
|
89
|
+
return CompletionResponse(
|
|
90
|
+
text=data["text"],
|
|
91
|
+
tokens_in=data["tokens_in"],
|
|
92
|
+
tokens_out=data["tokens_out"],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
error_msg = res.json().get("error", "Unknown error")
|
|
97
|
+
except Exception:
|
|
98
|
+
error_msg = f"HTTP {res.status_code}: {res.text or 'empty response'}"
|
|
99
|
+
|
|
100
|
+
match res.status_code:
|
|
101
|
+
case 401: raise InvalidKeyError(error_msg, 401)
|
|
102
|
+
case 402: raise InsufficientCreditsError(error_msg, 402)
|
|
103
|
+
case 404: raise ModelNotFoundError(error_msg, 404)
|
|
104
|
+
case 429: raise RateLimitError(error_msg, 429)
|
|
105
|
+
case 502 | 503: raise InferenceError(error_msg, res.status_code)
|
|
106
|
+
case _: raise AquinError(error_msg, res.status_code)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class AquinError(Exception):
|
|
2
|
+
"""Base exception for all Aquin SDK errors."""
|
|
3
|
+
def __init__(self, message: str, status_code: int = None):
|
|
4
|
+
super().__init__(message)
|
|
5
|
+
self.status_code = status_code
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class InvalidKeyError(AquinError):
|
|
9
|
+
"""API key is invalid or disabled."""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InsufficientCreditsError(AquinError):
|
|
14
|
+
"""Account does not have enough credits."""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RateLimitError(AquinError):
|
|
19
|
+
"""Too many requests."""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ModelNotFoundError(AquinError):
|
|
24
|
+
"""The model for this API key has not been trained yet."""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class InferenceError(AquinError):
|
|
29
|
+
"""The inference server failed."""
|
|
30
|
+
pass
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aquin"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the Aquin model API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
dependencies = [
|
|
13
|
+
"httpx>=0.27.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://aquin.app"
|
aquin-0.1.0/test.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from aquin import AquinClient
|
|
2
|
+
|
|
3
|
+
client = AquinClient(
|
|
4
|
+
api_key="aq-m_R3tlzj46F8FhnJK6XtSMC2x4VYmjCDTNKDY1DkxNLVU",
|
|
5
|
+
base_url="https://www.aquin.app"
|
|
6
|
+
)
|
|
7
|
+
res = client.complete("What is LoRA?")
|
|
8
|
+
print(res.text)
|
|
9
|
+
print(f"tokens_in={res.tokens_in} tokens_out={res.tokens_out}")
|