latentkit 0.1.1__py3-none-any.whl

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.
latentkit/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ from latentkit._exceptions import LatentKitAPIError, LatentKitError
2
+ from latentkit.client import AsyncLatentKit, LatentKit
3
+ from latentkit.types import StreamEvent
4
+
5
+ __all__ = ["AsyncLatentKit", "LatentKit", "LatentKitAPIError", "LatentKitError", "StreamEvent"]
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class LatentKitError(Exception):
7
+ """Base exception for the Python SDK."""
8
+
9
+
10
+ class LatentKitAPIError(LatentKitError):
11
+ """Raised when the LatentKit API returns a non-2xx response."""
12
+
13
+ def __init__(self, status_code: int, body: Any) -> None:
14
+ self.status_code = status_code
15
+ self.body = body
16
+ self.code = _extract_code(body)
17
+ message = _extract_message(body)
18
+ if message:
19
+ super().__init__(f"LatentKit API error {status_code}: {message}")
20
+ else:
21
+ super().__init__(f"LatentKit API error {status_code}: {body!r}")
22
+
23
+
24
+ def _extract_message(body: Any) -> str | None:
25
+ if isinstance(body, str):
26
+ return body or None
27
+ if not isinstance(body, dict):
28
+ return None
29
+ for key in ("message", "detail", "error"):
30
+ value = body.get(key)
31
+ if isinstance(value, str) and value:
32
+ return value
33
+ nested = body.get("error")
34
+ if isinstance(nested, dict):
35
+ value = nested.get("message")
36
+ if isinstance(value, str) and value:
37
+ return value
38
+ return None
39
+
40
+
41
+ def _extract_code(body: Any) -> str | None:
42
+ if not isinstance(body, dict):
43
+ return None
44
+ value = body.get("code")
45
+ if isinstance(value, str) and value:
46
+ return value
47
+ nested = body.get("error")
48
+ if isinstance(nested, dict):
49
+ value = nested.get("code")
50
+ if isinstance(value, str) and value:
51
+ return value
52
+ return None
latentkit/_stream.py ADDED
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from collections.abc import AsyncIterator, Iterator
5
+
6
+ import httpx
7
+
8
+ from latentkit.types import StreamEvent
9
+
10
+
11
+ def iter_sse_events(response: httpx.Response) -> Iterator[StreamEvent]:
12
+ buffer: list[str] = []
13
+ for line in response.iter_lines():
14
+ if line == "":
15
+ if buffer:
16
+ yield _parse_sse_event(buffer)
17
+ buffer = []
18
+ continue
19
+ buffer.append(line)
20
+ if buffer:
21
+ yield _parse_sse_event(buffer)
22
+
23
+
24
+ async def aiter_sse_events(response: httpx.Response) -> AsyncIterator[StreamEvent]:
25
+ buffer: list[str] = []
26
+ async for line in response.aiter_lines():
27
+ if line == "":
28
+ if buffer:
29
+ yield _parse_sse_event(buffer)
30
+ buffer = []
31
+ continue
32
+ buffer.append(line)
33
+ if buffer:
34
+ yield _parse_sse_event(buffer)
35
+
36
+
37
+ def _parse_sse_event(lines: list[str]) -> StreamEvent:
38
+ event_name: str | None = None
39
+ data_lines: list[str] = []
40
+ for raw_line in lines:
41
+ if raw_line.startswith("event:"):
42
+ event_name = raw_line.partition(":")[2].strip() or None
43
+ continue
44
+ if raw_line.startswith("data:"):
45
+ data_lines.append(raw_line.partition(":")[2].lstrip())
46
+ payload = "\n".join(data_lines)
47
+ if payload == "[DONE]":
48
+ return StreamEvent(data=payload, event=event_name or "done", is_done=True)
49
+ try:
50
+ parsed = json.loads(payload)
51
+ except json.JSONDecodeError:
52
+ parsed = payload
53
+ return StreamEvent(data=parsed, event=event_name)
@@ -0,0 +1,113 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterator, Iterator
4
+ from typing import Any
5
+
6
+ import httpx
7
+
8
+ from latentkit._exceptions import LatentKitAPIError
9
+ from latentkit._stream import aiter_sse_events, iter_sse_events
10
+ from latentkit.types import JSONDict, StreamEvent
11
+
12
+
13
+ def normalize_base_url(base_url: str) -> str:
14
+ raw = base_url.rstrip("/")
15
+ return raw if raw.endswith("/v1") else f"{raw}/v1"
16
+
17
+
18
+ def build_headers(api_key: str, extra_headers: dict[str, str] | None = None) -> dict[str, str]:
19
+ headers = {
20
+ "Authorization": f"Bearer {api_key}",
21
+ "Content-Type": "application/json",
22
+ }
23
+ if extra_headers:
24
+ headers.update(extra_headers)
25
+ return headers
26
+
27
+
28
+ def request_json(
29
+ client: httpx.Client,
30
+ *,
31
+ method: str,
32
+ url: str,
33
+ headers: dict[str, str],
34
+ body: JSONDict | None = None,
35
+ ) -> JSONDict:
36
+ request_kwargs: dict[str, Any] = {"headers": headers}
37
+ if body is not None:
38
+ request_kwargs["json"] = body
39
+ response = client.request(method, url, **request_kwargs)
40
+ return _decode_json_response(response)
41
+
42
+
43
+ async def arequest_json(
44
+ client: httpx.AsyncClient,
45
+ *,
46
+ method: str,
47
+ url: str,
48
+ headers: dict[str, str],
49
+ body: JSONDict | None = None,
50
+ ) -> JSONDict:
51
+ request_kwargs: dict[str, Any] = {"headers": headers}
52
+ if body is not None:
53
+ request_kwargs["json"] = body
54
+ response = await client.request(method, url, **request_kwargs)
55
+ return _decode_json_response(response)
56
+
57
+
58
+ def stream_events(
59
+ client: httpx.Client,
60
+ *,
61
+ method: str,
62
+ url: str,
63
+ headers: dict[str, str],
64
+ body: JSONDict | None = None,
65
+ ) -> Iterator[StreamEvent]:
66
+ def generator() -> Iterator[StreamEvent]:
67
+ request_kwargs: dict[str, Any] = {"headers": {**headers, "Accept": "text/event-stream"}}
68
+ if body is not None:
69
+ request_kwargs["json"] = body
70
+ with client.stream(method, url, **request_kwargs) as response:
71
+ _ensure_success(response)
72
+ yield from iter_sse_events(response)
73
+
74
+ return generator()
75
+
76
+
77
+ def astream_events(
78
+ client: httpx.AsyncClient,
79
+ *,
80
+ method: str,
81
+ url: str,
82
+ headers: dict[str, str],
83
+ body: JSONDict | None = None,
84
+ ) -> AsyncIterator[StreamEvent]:
85
+ async def generator() -> AsyncIterator[StreamEvent]:
86
+ request_kwargs: dict[str, Any] = {"headers": {**headers, "Accept": "text/event-stream"}}
87
+ if body is not None:
88
+ request_kwargs["json"] = body
89
+ async with client.stream(method, url, **request_kwargs) as response:
90
+ _ensure_success(response)
91
+ async for event in aiter_sse_events(response):
92
+ yield event
93
+
94
+ return generator()
95
+
96
+
97
+ def _decode_json_response(response: httpx.Response) -> JSONDict:
98
+ _ensure_success(response)
99
+ payload = response.json()
100
+ if not isinstance(payload, dict):
101
+ raise LatentKitAPIError(response.status_code, payload)
102
+ return payload
103
+
104
+
105
+ def _ensure_success(response: httpx.Response) -> None:
106
+ if response.is_success:
107
+ return
108
+ body: Any
109
+ try:
110
+ body = response.json()
111
+ except Exception:
112
+ body = response.text
113
+ raise LatentKitAPIError(response.status_code, body)
latentkit/client.py ADDED
@@ -0,0 +1,107 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import httpx
6
+
7
+ from latentkit._transport import arequest_json, astream_events, build_headers, normalize_base_url, request_json, stream_events
8
+ from latentkit.resources.agents import AgentsResource, AsyncAgentsResource
9
+ from latentkit.resources.audio import AsyncTranscriptionResource, AsyncTranslationResource, TranscriptionResource, TranslationResource
10
+ from latentkit.resources.chat import AsyncChatResource, ChatResource
11
+ from latentkit.resources.completions import AsyncCompletionsResource, CompletionsResource
12
+ from latentkit.resources.embeddings import AsyncEmbeddingsResource, EmbeddingsResource
13
+ from latentkit.resources.image import AsyncImageResource, ImageResource
14
+ from latentkit.resources.queue import AsyncQueueResource, QueueResource
15
+ from latentkit.resources.speech import AsyncSpeechResource, SpeechResource
16
+ from latentkit.resources.video import AsyncVideoResource, VideoResource
17
+ from latentkit.resources.vision import AsyncVisionResource, VisionResource
18
+
19
+
20
+ class LatentKit:
21
+ """Synchronous Python client for LatentKit's canonical `/v1` API."""
22
+
23
+ def __init__(
24
+ self,
25
+ *,
26
+ api_key: str,
27
+ base_url: str = "https://ai.latentkit.com",
28
+ timeout: float = 120.0,
29
+ headers: dict[str, str] | None = None,
30
+ http_client: httpx.Client | None = None,
31
+ ) -> None:
32
+ self._base_v1 = normalize_base_url(base_url)
33
+ self._headers = build_headers(api_key, headers)
34
+ self._owns_client = http_client is None
35
+ self._http = http_client or httpx.Client(timeout=timeout)
36
+ self.chat = ChatResource(self._request_json, self._stream_events, self._base_v1)
37
+ self.completions = CompletionsResource(self._request_json, self._stream_events, self._base_v1)
38
+ self.embeddings = EmbeddingsResource(self._request_json, self._base_v1)
39
+ self.image = ImageResource(self._request_json, self._base_v1)
40
+ self.speech = SpeechResource(self._request_json, self._base_v1)
41
+ self.transcription = TranscriptionResource(self._request_json, self._base_v1)
42
+ self.translation = TranslationResource(self._request_json, self._base_v1)
43
+ self.video = VideoResource(self._request_json, self._base_v1)
44
+ self.vision = VisionResource(self._request_json, self._stream_events, self._base_v1)
45
+ self.queue = QueueResource(self._request_json, self._base_v1)
46
+ self.agents = AgentsResource(self._request_json, self._stream_events, self._base_v1)
47
+
48
+ def _request_json(self, method: str, url: str, body: dict[str, Any] | None) -> dict[str, Any]:
49
+ return request_json(self._http, method=method, url=url, headers=self._headers, body=body)
50
+
51
+ def _stream_events(self, method: str, url: str, body: dict[str, Any] | None):
52
+ return stream_events(self._http, method=method, url=url, headers=self._headers, body=body)
53
+
54
+ def close(self) -> None:
55
+ if self._owns_client:
56
+ self._http.close()
57
+
58
+ def __enter__(self) -> LatentKit:
59
+ return self
60
+
61
+ def __exit__(self, *_exc: object) -> None:
62
+ self.close()
63
+
64
+
65
+ class AsyncLatentKit:
66
+ """Async Python client for LatentKit's canonical `/v1` API."""
67
+
68
+ def __init__(
69
+ self,
70
+ *,
71
+ api_key: str,
72
+ base_url: str = "https://ai.latentkit.com",
73
+ timeout: float = 120.0,
74
+ headers: dict[str, str] | None = None,
75
+ http_client: httpx.AsyncClient | None = None,
76
+ ) -> None:
77
+ self._base_v1 = normalize_base_url(base_url)
78
+ self._headers = build_headers(api_key, headers)
79
+ self._owns_client = http_client is None
80
+ self._http = http_client or httpx.AsyncClient(timeout=timeout)
81
+ self.chat = AsyncChatResource(self._request_json, self._stream_events, self._base_v1)
82
+ self.completions = AsyncCompletionsResource(self._request_json, self._stream_events, self._base_v1)
83
+ self.embeddings = AsyncEmbeddingsResource(self._request_json, self._base_v1)
84
+ self.image = AsyncImageResource(self._request_json, self._base_v1)
85
+ self.speech = AsyncSpeechResource(self._request_json, self._base_v1)
86
+ self.transcription = AsyncTranscriptionResource(self._request_json, self._base_v1)
87
+ self.translation = AsyncTranslationResource(self._request_json, self._base_v1)
88
+ self.video = AsyncVideoResource(self._request_json, self._base_v1)
89
+ self.vision = AsyncVisionResource(self._request_json, self._stream_events, self._base_v1)
90
+ self.queue = AsyncQueueResource(self._request_json, self._base_v1)
91
+ self.agents = AsyncAgentsResource(self._request_json, self._stream_events, self._base_v1)
92
+
93
+ async def _request_json(self, method: str, url: str, body: dict[str, Any] | None) -> dict[str, Any]:
94
+ return await arequest_json(self._http, method=method, url=url, headers=self._headers, body=body)
95
+
96
+ def _stream_events(self, method: str, url: str, body: dict[str, Any] | None):
97
+ return astream_events(self._http, method=method, url=url, headers=self._headers, body=body)
98
+
99
+ async def close(self) -> None:
100
+ if self._owns_client:
101
+ await self._http.aclose()
102
+
103
+ async def __aenter__(self) -> AsyncLatentKit:
104
+ return self
105
+
106
+ async def __aexit__(self, *_exc: object) -> None:
107
+ await self.close()
@@ -0,0 +1,35 @@
1
+ from latentkit.resources.agents import AgentsResource, AsyncAgentsResource
2
+ from latentkit.resources.audio import AsyncTranscriptionResource, AsyncTranslationResource, TranscriptionResource, TranslationResource
3
+ from latentkit.resources.chat import AsyncChatResource, ChatResource
4
+ from latentkit.resources.completions import AsyncCompletionsResource, CompletionsResource
5
+ from latentkit.resources.embeddings import AsyncEmbeddingsResource, EmbeddingsResource
6
+ from latentkit.resources.image import AsyncImageResource, ImageResource
7
+ from latentkit.resources.queue import AsyncQueueResource, QueueResource
8
+ from latentkit.resources.speech import AsyncSpeechResource, SpeechResource
9
+ from latentkit.resources.video import AsyncVideoResource, VideoResource
10
+ from latentkit.resources.vision import AsyncVisionResource, VisionResource
11
+
12
+ __all__ = [
13
+ "AgentsResource",
14
+ "AsyncAgentsResource",
15
+ "AsyncChatResource",
16
+ "AsyncCompletionsResource",
17
+ "AsyncEmbeddingsResource",
18
+ "AsyncImageResource",
19
+ "AsyncQueueResource",
20
+ "AsyncSpeechResource",
21
+ "AsyncTranscriptionResource",
22
+ "AsyncTranslationResource",
23
+ "AsyncVideoResource",
24
+ "AsyncVisionResource",
25
+ "ChatResource",
26
+ "CompletionsResource",
27
+ "EmbeddingsResource",
28
+ "ImageResource",
29
+ "QueueResource",
30
+ "SpeechResource",
31
+ "TranscriptionResource",
32
+ "TranslationResource",
33
+ "VideoResource",
34
+ "VisionResource",
35
+ ]
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterator, Iterator
4
+ from typing import Any
5
+
6
+ from latentkit.types import JSONDict, StreamEvent
7
+
8
+
9
+ class AgentSessionsResource:
10
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
11
+ self._request_json = request_json
12
+ self._stream_events = stream_events
13
+ self._base = f"{base_v1}/agent/sessions"
14
+
15
+ def create(self, **payload: Any) -> JSONDict:
16
+ return self._request_json("POST", self._base, payload)
17
+
18
+ def run(self, session_id: str, *, stream: bool = False) -> JSONDict:
19
+ return self._request_json("POST", f"{self._base}/{session_id}/run", {"stream": stream})
20
+
21
+ def run_stream(self, session_id: str) -> Iterator[StreamEvent]:
22
+ return self._stream_events("POST", f"{self._base}/{session_id}/run", {"stream": True})
23
+
24
+ def input(self, session_id: str, *, message: str, policy_id: str | None = None) -> JSONDict:
25
+ return self._request_json(
26
+ "POST",
27
+ f"{self._base}/{session_id}/input",
28
+ {"message": message, "policy_id": policy_id},
29
+ )
30
+
31
+ def cancel(self, session_id: str) -> JSONDict:
32
+ return self._request_json("POST", f"{self._base}/{session_id}/cancel", None)
33
+
34
+ def retrieve(self, session_id: str) -> JSONDict:
35
+ return self._request_json("GET", f"{self._base}/{session_id}", None)
36
+
37
+ def steps(self, session_id: str) -> JSONDict:
38
+ return self._request_json("GET", f"{self._base}/{session_id}/steps", None)
39
+
40
+ def stream(self, session_id: str) -> Iterator[StreamEvent]:
41
+ return self._stream_events("GET", f"{self._base}/{session_id}/stream", None)
42
+
43
+
44
+ class AsyncAgentSessionsResource:
45
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
46
+ self._request_json = request_json
47
+ self._stream_events = stream_events
48
+ self._base = f"{base_v1}/agent/sessions"
49
+
50
+ async def create(self, **payload: Any) -> JSONDict:
51
+ return await self._request_json("POST", self._base, payload)
52
+
53
+ async def run(self, session_id: str, *, stream: bool = False) -> JSONDict:
54
+ return await self._request_json("POST", f"{self._base}/{session_id}/run", {"stream": stream})
55
+
56
+ def run_stream(self, session_id: str) -> AsyncIterator[StreamEvent]:
57
+ return self._stream_events("POST", f"{self._base}/{session_id}/run", {"stream": True})
58
+
59
+ async def input(self, session_id: str, *, message: str, policy_id: str | None = None) -> JSONDict:
60
+ return await self._request_json(
61
+ "POST",
62
+ f"{self._base}/{session_id}/input",
63
+ {"message": message, "policy_id": policy_id},
64
+ )
65
+
66
+ async def cancel(self, session_id: str) -> JSONDict:
67
+ return await self._request_json("POST", f"{self._base}/{session_id}/cancel", None)
68
+
69
+ async def retrieve(self, session_id: str) -> JSONDict:
70
+ return await self._request_json("GET", f"{self._base}/{session_id}", None)
71
+
72
+ async def steps(self, session_id: str) -> JSONDict:
73
+ return await self._request_json("GET", f"{self._base}/{session_id}/steps", None)
74
+
75
+ def stream(self, session_id: str) -> AsyncIterator[StreamEvent]:
76
+ return self._stream_events("GET", f"{self._base}/{session_id}/stream", None)
77
+
78
+
79
+ class AgentsResource:
80
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
81
+ self.sessions = AgentSessionsResource(request_json, stream_events, base_v1)
82
+
83
+
84
+ class AsyncAgentsResource:
85
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
86
+ self.sessions = AsyncAgentSessionsResource(request_json, stream_events, base_v1)
@@ -0,0 +1,133 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from latentkit.types import JSONDict
6
+
7
+
8
+ class TranscriptionResource:
9
+ def __init__(self, request_json: Any, base_v1: str) -> None:
10
+ self._request_json = request_json
11
+ self._url = f"{base_v1}/transcription"
12
+
13
+ def create(
14
+ self,
15
+ *,
16
+ audio: JSONDict | None = None,
17
+ input: Any = None,
18
+ language: str | None = None,
19
+ prompt: str | None = None,
20
+ response_format: str | None = None,
21
+ temperature: float | None = None,
22
+ response_profile: str | None = None,
23
+ extra_body: JSONDict | None = None,
24
+ ) -> JSONDict:
25
+ body: JSONDict = {
26
+ "audio": audio,
27
+ "input": input,
28
+ "language": language,
29
+ "prompt": prompt,
30
+ "response_format": response_format,
31
+ "temperature": temperature,
32
+ }
33
+ if response_profile:
34
+ body["response_profile"] = response_profile
35
+ if extra_body:
36
+ body.update(extra_body)
37
+ return self._request_json("POST", self._url, body)
38
+
39
+
40
+ class AsyncTranscriptionResource:
41
+ def __init__(self, request_json: Any, base_v1: str) -> None:
42
+ self._request_json = request_json
43
+ self._url = f"{base_v1}/transcription"
44
+
45
+ async def create(
46
+ self,
47
+ *,
48
+ audio: JSONDict | None = None,
49
+ input: Any = None,
50
+ language: str | None = None,
51
+ prompt: str | None = None,
52
+ response_format: str | None = None,
53
+ temperature: float | None = None,
54
+ response_profile: str | None = None,
55
+ extra_body: JSONDict | None = None,
56
+ ) -> JSONDict:
57
+ body: JSONDict = {
58
+ "audio": audio,
59
+ "input": input,
60
+ "language": language,
61
+ "prompt": prompt,
62
+ "response_format": response_format,
63
+ "temperature": temperature,
64
+ }
65
+ if response_profile:
66
+ body["response_profile"] = response_profile
67
+ if extra_body:
68
+ body.update(extra_body)
69
+ return await self._request_json("POST", self._url, body)
70
+
71
+
72
+ class TranslationResource:
73
+ def __init__(self, request_json: Any, base_v1: str) -> None:
74
+ self._request_json = request_json
75
+ self._url = f"{base_v1}/translation"
76
+
77
+ def create(
78
+ self,
79
+ *,
80
+ audio: JSONDict | None = None,
81
+ input: Any = None,
82
+ target_language: str | None = None,
83
+ prompt: str | None = None,
84
+ response_format: str | None = None,
85
+ temperature: float | None = None,
86
+ response_profile: str | None = None,
87
+ extra_body: JSONDict | None = None,
88
+ ) -> JSONDict:
89
+ body: JSONDict = {
90
+ "audio": audio,
91
+ "input": input,
92
+ "target_language": target_language,
93
+ "prompt": prompt,
94
+ "response_format": response_format,
95
+ "temperature": temperature,
96
+ }
97
+ if response_profile:
98
+ body["response_profile"] = response_profile
99
+ if extra_body:
100
+ body.update(extra_body)
101
+ return self._request_json("POST", self._url, body)
102
+
103
+
104
+ class AsyncTranslationResource:
105
+ def __init__(self, request_json: Any, base_v1: str) -> None:
106
+ self._request_json = request_json
107
+ self._url = f"{base_v1}/translation"
108
+
109
+ async def create(
110
+ self,
111
+ *,
112
+ audio: JSONDict | None = None,
113
+ input: Any = None,
114
+ target_language: str | None = None,
115
+ prompt: str | None = None,
116
+ response_format: str | None = None,
117
+ temperature: float | None = None,
118
+ response_profile: str | None = None,
119
+ extra_body: JSONDict | None = None,
120
+ ) -> JSONDict:
121
+ body: JSONDict = {
122
+ "audio": audio,
123
+ "input": input,
124
+ "target_language": target_language,
125
+ "prompt": prompt,
126
+ "response_format": response_format,
127
+ "temperature": temperature,
128
+ }
129
+ if response_profile:
130
+ body["response_profile"] = response_profile
131
+ if extra_body:
132
+ body.update(extra_body)
133
+ return await self._request_json("POST", self._url, body)
@@ -0,0 +1,102 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterator, Iterator
4
+ from typing import Any
5
+
6
+ from latentkit.types import JSONDict, StreamEvent
7
+
8
+
9
+ class ChatResource:
10
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
11
+ self._request_json = request_json
12
+ self._stream_events = stream_events
13
+ self._url = f"{base_v1}/chat"
14
+
15
+ def create(
16
+ self,
17
+ *,
18
+ messages: list[dict[str, Any]],
19
+ max_tokens: int = 1000,
20
+ temperature: float = 0.7,
21
+ response_profile: str | None = None,
22
+ extra_body: JSONDict | None = None,
23
+ ) -> JSONDict:
24
+ body: JSONDict = {
25
+ "messages": messages,
26
+ "max_tokens": max_tokens,
27
+ "temperature": temperature,
28
+ }
29
+ if response_profile:
30
+ body["response_profile"] = response_profile
31
+ if extra_body:
32
+ body.update(extra_body)
33
+ return self._request_json("POST", self._url, body)
34
+
35
+ def stream(
36
+ self,
37
+ *,
38
+ messages: list[dict[str, Any]],
39
+ max_tokens: int = 1000,
40
+ temperature: float = 0.7,
41
+ response_profile: str | None = None,
42
+ extra_body: JSONDict | None = None,
43
+ ) -> Iterator[StreamEvent]:
44
+ body: JSONDict = {
45
+ "messages": messages,
46
+ "max_tokens": max_tokens,
47
+ "temperature": temperature,
48
+ "stream": True,
49
+ }
50
+ if response_profile:
51
+ body["response_profile"] = response_profile
52
+ if extra_body:
53
+ body.update(extra_body)
54
+ return self._stream_events("POST", self._url, body)
55
+
56
+
57
+ class AsyncChatResource:
58
+ def __init__(self, request_json: Any, stream_events: Any, base_v1: str) -> None:
59
+ self._request_json = request_json
60
+ self._stream_events = stream_events
61
+ self._url = f"{base_v1}/chat"
62
+
63
+ async def create(
64
+ self,
65
+ *,
66
+ messages: list[dict[str, Any]],
67
+ max_tokens: int = 1000,
68
+ temperature: float = 0.7,
69
+ response_profile: str | None = None,
70
+ extra_body: JSONDict | None = None,
71
+ ) -> JSONDict:
72
+ body: JSONDict = {
73
+ "messages": messages,
74
+ "max_tokens": max_tokens,
75
+ "temperature": temperature,
76
+ }
77
+ if response_profile:
78
+ body["response_profile"] = response_profile
79
+ if extra_body:
80
+ body.update(extra_body)
81
+ return await self._request_json("POST", self._url, body)
82
+
83
+ def stream(
84
+ self,
85
+ *,
86
+ messages: list[dict[str, Any]],
87
+ max_tokens: int = 1000,
88
+ temperature: float = 0.7,
89
+ response_profile: str | None = None,
90
+ extra_body: JSONDict | None = None,
91
+ ) -> AsyncIterator[StreamEvent]:
92
+ body: JSONDict = {
93
+ "messages": messages,
94
+ "max_tokens": max_tokens,
95
+ "temperature": temperature,
96
+ "stream": True,
97
+ }
98
+ if response_profile:
99
+ body["response_profile"] = response_profile
100
+ if extra_body:
101
+ body.update(extra_body)
102
+ return self._stream_events("POST", self._url, body)