Skip to content

Commit 3c6959d

Browse files
committed
feat, fix: communicating to host + timeout handle
1 parent 0e40eab commit 3c6959d

7 files changed

Lines changed: 84 additions & 1 deletion

File tree

genstack/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .genstack import Genstack
2+
3+
__all__ = ["Genstack"]

genstack/genstack.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import httpx
2+
from typing import Dict, Any, Optional, Union
3+
import asyncio
4+
5+
class Genstack:
6+
def __init__(self, api_key: str, base_url : Optional[str] = None):
7+
if not api_key.startswith("gen-") or any(c.isspace() for c in api_key):
8+
raise ValueError("API key must start with 'gen-' and contain no spaces or line breaks.")
9+
self.api_key : str = api_key
10+
self.base_url : str = base_url or "http://localhost:8000"
11+
async def __call(self, payload: Dict[str, Any]) -> Dict[str, Any]:
12+
async with httpx.AsyncClient(timeout=httpx.Timeout(30.0)) as client:
13+
try:
14+
response = await client.post(
15+
url=f"{self.base_url}/api/v1/sdk/generate",
16+
headers={
17+
"x-api-key" : f"{self.api_key}"
18+
},
19+
json=payload
20+
)
21+
response.raise_for_status()
22+
return response.json()
23+
except httpx.HTTPStatusError as e:
24+
return e.response.json()
25+
except Exception as e:
26+
return {"error" : str(e)}
27+
async def __generate_async(self, payload : Dict[str, Any]) -> Dict[str, Any]:
28+
return await self.__call(payload=payload)
29+
def generate(self, input : Union[str, Dict[str, Any]], model : Optional[str] = "auto", track : Optional[str] = None) -> Dict[str, Any]:
30+
if not track :
31+
raise ValueError("Track is required.")
32+
if not isinstance(input, (str, dict)):
33+
raise TypeError("Payload must be a string or a dictionary.")
34+
if isinstance(input, str):
35+
inner_payload = {"input": input}
36+
else:
37+
inner_payload = input
38+
39+
payload = {
40+
"payload": inner_payload,
41+
"model": model,
42+
"track": track
43+
}
44+
return asyncio.run(self.__generate_async(payload=payload))

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "genstack"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
description = "Universal AI SDK from Genstack"
55
authors = [{name="Shrey Kumar", email="shreyk.dev@gmail.com"}]
66
readme = "README.md"
@@ -12,3 +12,5 @@ dependencies = ["httpx"]
1212
requires = ["hatchling"]
1313
build-backend = "hatchling.build"
1414

15+
[tool.pytest.ini_options]
16+
pythonpath = ["."]

requirements.txt

874 Bytes
Binary file not shown.

tests/call_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from genstack import Genstack
2+
from dotenv import load_dotenv
3+
import os
4+
5+
load_dotenv()
6+
7+
8+
9+
client = Genstack(api_key=os.getenv("GENSTACK_API_KEY"))
10+
11+
12+
res = client.generate(input="3 fun facts about Ferrari", track="dragon", model="gpt-4-1-nano-oai")
13+
14+
if "output" in res:
15+
print(res["output"][0]["output"]["text"])
16+
else:
17+
print("Error:", res.get("message", "Unknown error"))

tests/test_generate.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from genstack import Genstack
2+
import pytest
3+
4+
def test_generate_with_invalid_type():
5+
client = Genstack(api_key="gen-")
6+
with pytest.raises(TypeError):
7+
client.generate(input=123, track="test-track")

tests/x_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Sample:
2+
def __init__(self) -> None:
3+
timeout = 30
4+
@staticmethod
5+
def say(self) -> None:
6+
print(self.timeout)
7+
8+
sam = Sample()
9+
10+
sam.say()

0 commit comments

Comments
 (0)