embed-client 0.0.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.
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,180 @@
1
+ """
2
+ Async client for Embedding Service API (OpenAPI 3.0.2)
3
+
4
+ - 100% type-annotated
5
+ - English docstrings and examples
6
+ - Ready for PyPi
7
+ """
8
+
9
+ from typing import Any, Dict, List, Optional, Union
10
+ import aiohttp
11
+
12
+ class EmbeddingServiceError(Exception):
13
+ """Base exception for EmbeddingServiceAsyncClient."""
14
+
15
+ class EmbeddingServiceConnectionError(EmbeddingServiceError):
16
+ """Raised when the service is unavailable or connection fails."""
17
+
18
+ class EmbeddingServiceHTTPError(EmbeddingServiceError):
19
+ """Raised for HTTP errors (4xx, 5xx)."""
20
+ def __init__(self, status: int, message: str):
21
+ super().__init__(f"HTTP {status}: {message}")
22
+ self.status = status
23
+ self.message = message
24
+
25
+ class EmbeddingServiceAPIError(EmbeddingServiceError):
26
+ """Raised for errors returned by the API in the response body."""
27
+ def __init__(self, error: Any):
28
+ super().__init__(f"API error: {error}")
29
+ self.error = error
30
+
31
+ class EmbeddingServiceAsyncClient:
32
+ """
33
+ Asynchronous client for the Embedding Service API.
34
+ Args:
35
+ base_url (str): Base URL of the embedding service (e.g., "http://localhost").
36
+ port (int): Port of the embedding service (e.g., 8001).
37
+ Raises:
38
+ ValueError: If base_url or port is not provided.
39
+ """
40
+ def __init__(self, base_url: str, port: int):
41
+ if not base_url:
42
+ raise ValueError("base_url must be provided.")
43
+ if port is None:
44
+ raise ValueError("port must be provided.")
45
+ self.base_url = base_url.rstrip("/")
46
+ self.port = port
47
+ self._session: Optional[aiohttp.ClientSession] = None
48
+
49
+ def _make_url(self, path: str, base_url: Optional[str] = None, port: Optional[int] = None) -> str:
50
+ url = (base_url or self.base_url).rstrip("/")
51
+ port_val = port if port is not None else self.port
52
+ return f"{url}:{port_val}{path}"
53
+
54
+ async def __aenter__(self):
55
+ self._session = aiohttp.ClientSession()
56
+ return self
57
+
58
+ async def __aexit__(self, exc_type, exc, tb):
59
+ if self._session:
60
+ await self._session.close()
61
+ self._session = None
62
+
63
+ async def health(self, base_url: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]:
64
+ """
65
+ Check the health of the service.
66
+ Args:
67
+ base_url (str, optional): Override base URL.
68
+ port (int, optional): Override port.
69
+ Returns:
70
+ dict: Health status and model info.
71
+ """
72
+ url = self._make_url("/health", base_url, port)
73
+ try:
74
+ async with self._session.get(url) as resp:
75
+ await self._raise_for_status(resp)
76
+ return await resp.json()
77
+ except EmbeddingServiceHTTPError:
78
+ raise
79
+ except EmbeddingServiceConnectionError:
80
+ raise
81
+ except aiohttp.ClientConnectionError as e:
82
+ raise EmbeddingServiceConnectionError(f"Connection error: {e}") from e
83
+ except aiohttp.ClientResponseError as e:
84
+ raise EmbeddingServiceHTTPError(e.status, e.message) from e
85
+ except Exception as e:
86
+ raise EmbeddingServiceError(f"Unexpected error: {e}") from e
87
+
88
+ async def get_openapi_schema(self, base_url: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]:
89
+ """
90
+ Get the OpenAPI schema of the service.
91
+ Args:
92
+ base_url (str, optional): Override base URL.
93
+ port (int, optional): Override port.
94
+ Returns:
95
+ dict: OpenAPI schema.
96
+ """
97
+ url = self._make_url("/openapi.json", base_url, port)
98
+ try:
99
+ async with self._session.get(url) as resp:
100
+ await self._raise_for_status(resp)
101
+ return await resp.json()
102
+ except EmbeddingServiceHTTPError:
103
+ raise
104
+ except EmbeddingServiceConnectionError:
105
+ raise
106
+ except aiohttp.ClientConnectionError as e:
107
+ raise EmbeddingServiceConnectionError(f"Connection error: {e}") from e
108
+ except aiohttp.ClientResponseError as e:
109
+ raise EmbeddingServiceHTTPError(e.status, e.message) from e
110
+ except Exception as e:
111
+ raise EmbeddingServiceError(f"Unexpected error: {e}") from e
112
+
113
+ async def get_commands(self, base_url: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]:
114
+ """
115
+ Get the list of available commands.
116
+ Args:
117
+ base_url (str, optional): Override base URL.
118
+ port (int, optional): Override port.
119
+ Returns:
120
+ dict: List of commands and their descriptions.
121
+ """
122
+ url = self._make_url("/api/commands", base_url, port)
123
+ try:
124
+ async with self._session.get(url) as resp:
125
+ await self._raise_for_status(resp)
126
+ return await resp.json()
127
+ except EmbeddingServiceHTTPError:
128
+ raise
129
+ except EmbeddingServiceConnectionError:
130
+ raise
131
+ except aiohttp.ClientConnectionError as e:
132
+ raise EmbeddingServiceConnectionError(f"Connection error: {e}") from e
133
+ except aiohttp.ClientResponseError as e:
134
+ raise EmbeddingServiceHTTPError(e.status, e.message) from e
135
+ except Exception as e:
136
+ raise EmbeddingServiceError(f"Unexpected error: {e}") from e
137
+
138
+ async def cmd(self, command: str, params: Optional[Dict[str, Any]] = None, base_url: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]:
139
+ """
140
+ Execute a command via JSON-RPC protocol.
141
+ Args:
142
+ command (str): Command to execute (embed, models, health, help, config).
143
+ params (dict, optional): Parameters for the command.
144
+ base_url (str, optional): Override base URL.
145
+ port (int, optional): Override port.
146
+ Returns:
147
+ dict: Command execution result.
148
+ """
149
+ url = self._make_url("/cmd", base_url, port)
150
+ payload = {"command": command}
151
+ if params is not None:
152
+ payload["params"] = params
153
+ try:
154
+ async with self._session.post(url, json=payload) as resp:
155
+ await self._raise_for_status(resp)
156
+ data = await resp.json()
157
+ # Обработка ошибок, возвращаемых сервером в теле ответа
158
+ if "error" in data:
159
+ raise EmbeddingServiceAPIError(data["error"])
160
+ return data
161
+ except EmbeddingServiceAPIError:
162
+ raise
163
+ except EmbeddingServiceHTTPError:
164
+ raise
165
+ except EmbeddingServiceConnectionError:
166
+ raise
167
+ except aiohttp.ClientConnectionError as e:
168
+ raise EmbeddingServiceConnectionError(f"Connection error: {e}") from e
169
+ except aiohttp.ClientResponseError as e:
170
+ raise EmbeddingServiceHTTPError(e.status, e.message) from e
171
+ except Exception as e:
172
+ raise EmbeddingServiceError(f"Unexpected error: {e}") from e
173
+
174
+ async def _raise_for_status(self, resp: aiohttp.ClientResponse):
175
+ try:
176
+ resp.raise_for_status()
177
+ except aiohttp.ClientResponseError as e:
178
+ raise EmbeddingServiceHTTPError(e.status, e.message) from e
179
+
180
+ # TODO: Add methods for /cmd, /api/commands, etc.
@@ -0,0 +1,94 @@
1
+ """
2
+ Example usage of EmbeddingServiceAsyncClient.
3
+
4
+ This example demonstrates how to use the async client to check the health of the embedding service,
5
+ request embeddings, and handle all possible exceptions.
6
+
7
+ Run this script with:
8
+ python -m asyncio embed_client/example_async_usage.py --base-url http://localhost --port 8001
9
+
10
+ You can also set EMBED_CLIENT_BASE_URL and EMBED_CLIENT_PORT environment variables.
11
+ """
12
+
13
+ import asyncio
14
+ import sys
15
+ import os
16
+ from embed_client.async_client import (
17
+ EmbeddingServiceAsyncClient,
18
+ EmbeddingServiceConnectionError,
19
+ EmbeddingServiceHTTPError,
20
+ EmbeddingServiceAPIError,
21
+ EmbeddingServiceError,
22
+ )
23
+
24
+ def get_params():
25
+ base_url = None
26
+ port = None
27
+ for i, arg in enumerate(sys.argv):
28
+ if arg in ("--base-url", "-b") and i + 1 < len(sys.argv):
29
+ base_url = sys.argv[i + 1]
30
+ if arg in ("--port", "-p") and i + 1 < len(sys.argv):
31
+ port = sys.argv[i + 1]
32
+ if not base_url:
33
+ base_url = os.environ.get("EMBED_CLIENT_BASE_URL")
34
+ if not port:
35
+ port = os.environ.get("EMBED_CLIENT_PORT")
36
+ if not base_url or not port:
37
+ print("Error: base_url and port must be provided via --base-url/--port arguments or EMBED_CLIENT_BASE_URL/EMBED_CLIENT_PORT environment variables.")
38
+ sys.exit(1)
39
+ return None, None
40
+ return base_url, int(port)
41
+
42
+ async def main():
43
+ base_url, port = get_params()
44
+ # Always use try/except to handle all possible errors
45
+ try:
46
+ async with EmbeddingServiceAsyncClient(base_url=base_url, port=port) as client:
47
+ # Check health
48
+ try:
49
+ health = await client.health()
50
+ print("Service health:", health)
51
+ except EmbeddingServiceConnectionError as e:
52
+ print("[Connection error]", e)
53
+ return
54
+ except EmbeddingServiceHTTPError as e:
55
+ print(f"[HTTP error] {e.status}: {e.message}")
56
+ return
57
+ except EmbeddingServiceError as e:
58
+ print("[Other error]", e)
59
+ return
60
+
61
+ # Request embeddings for a list of texts
62
+ texts = ["hello world", "test embedding"]
63
+ try:
64
+ result = await client.cmd("embed", params={"texts": texts})
65
+ vectors = result["result"]
66
+ print(f"Embeddings for {len(texts)} texts:")
67
+ for i, vec in enumerate(vectors):
68
+ print(f" Text: {texts[i]!r}\n Vector: {vec[:5]}... (total {len(vec)} dims)")
69
+ except EmbeddingServiceAPIError as e:
70
+ print("[API error]", e.error)
71
+ except EmbeddingServiceHTTPError as e:
72
+ print(f"[HTTP error] {e.status}: {e.message}")
73
+ except EmbeddingServiceConnectionError as e:
74
+ print("[Connection error]", e)
75
+ except EmbeddingServiceError as e:
76
+ print("[Other error]", e)
77
+
78
+ # Example: error handling for invalid command
79
+ try:
80
+ await client.cmd("not_a_command")
81
+ except EmbeddingServiceAPIError as e:
82
+ print("[API error for invalid command]", e.error)
83
+
84
+ # Example: error handling for empty texts
85
+ try:
86
+ await client.cmd("embed", params={"texts": []})
87
+ except EmbeddingServiceAPIError as e:
88
+ print("[API error for empty texts]", e.error)
89
+
90
+ except Exception as e:
91
+ print("[Unexpected error]", e)
92
+
93
+ if __name__ == "__main__":
94
+ asyncio.run(main())
@@ -0,0 +1,94 @@
1
+ """
2
+ Example usage of EmbeddingServiceAsyncClient.
3
+
4
+ This example demonstrates how to use the async client to check the health of the embedding service,
5
+ request embeddings, and handle all possible exceptions.
6
+
7
+ Run this script with:
8
+ python -m asyncio embed_client/example_async_usage_ru.py --base-url http://localhost --port 8001
9
+
10
+ You can also set EMBED_CLIENT_BASE_URL and EMBED_CLIENT_PORT environment variables.
11
+ """
12
+
13
+ import asyncio
14
+ import sys
15
+ import os
16
+ from embed_client.async_client import (
17
+ EmbeddingServiceAsyncClient,
18
+ EmbeddingServiceConnectionError,
19
+ EmbeddingServiceHTTPError,
20
+ EmbeddingServiceAPIError,
21
+ EmbeddingServiceError,
22
+ )
23
+
24
+ def get_params():
25
+ base_url = None
26
+ port = None
27
+ for i, arg in enumerate(sys.argv):
28
+ if arg in ("--base-url", "-b") and i + 1 < len(sys.argv):
29
+ base_url = sys.argv[i + 1]
30
+ if arg in ("--port", "-p") and i + 1 < len(sys.argv):
31
+ port = sys.argv[i + 1]
32
+ if not base_url:
33
+ base_url = os.environ.get("EMBED_CLIENT_BASE_URL")
34
+ if not port:
35
+ port = os.environ.get("EMBED_CLIENT_PORT")
36
+ if not base_url or not port:
37
+ print("Error: base_url and port must be provided via --base-url/--port arguments or EMBED_CLIENT_BASE_URL/EMBED_CLIENT_PORT environment variables.")
38
+ sys.exit(1)
39
+ return None, None
40
+ return base_url, int(port)
41
+
42
+ async def main():
43
+ base_url, port = get_params()
44
+ # Always use try/except to handle all possible errors
45
+ try:
46
+ async with EmbeddingServiceAsyncClient(base_url=base_url, port=port) as client:
47
+ # Check health
48
+ try:
49
+ health = await client.health()
50
+ print("Service health:", health)
51
+ except EmbeddingServiceConnectionError as e:
52
+ print("[Connection error]", e)
53
+ return
54
+ except EmbeddingServiceHTTPError as e:
55
+ print(f"[HTTP error] {e.status}: {e.message}")
56
+ return
57
+ except EmbeddingServiceError as e:
58
+ print("[Other error]", e)
59
+ return
60
+
61
+ # Request embeddings for a list of texts
62
+ texts = ["hello world", "test embedding"]
63
+ try:
64
+ result = await client.cmd("embed", params={"texts": texts})
65
+ vectors = result["result"]
66
+ print(f"Embeddings for {len(texts)} texts:")
67
+ for i, vec in enumerate(vectors):
68
+ print(f" Text: {texts[i]!r}\n Vector: {vec[:5]}... (total {len(vec)} dims)")
69
+ except EmbeddingServiceAPIError as e:
70
+ print("[API error]", e.error)
71
+ except EmbeddingServiceHTTPError as e:
72
+ print(f"[HTTP error] {e.status}: {e.message}")
73
+ except EmbeddingServiceConnectionError as e:
74
+ print("[Connection error]", e)
75
+ except EmbeddingServiceError as e:
76
+ print("[Other error]", e)
77
+
78
+ # Example: error handling for invalid command
79
+ try:
80
+ await client.cmd("not_a_command")
81
+ except EmbeddingServiceAPIError as e:
82
+ print("[API error for invalid command]", e.error)
83
+
84
+ # Example: error handling for empty texts
85
+ try:
86
+ await client.cmd("embed", params={"texts": []})
87
+ except EmbeddingServiceAPIError as e:
88
+ print("[API error for empty texts]", e.error)
89
+
90
+ except Exception as e:
91
+ print("[Unexpected error]", e)
92
+
93
+ if __name__ == "__main__":
94
+ asyncio.run(main())
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: embed-client
3
+ Version: 0.0.1
4
+ Summary: Async client for Embedding Service API
5
+ Author: Your Name
6
+ Requires-Dist: aiohttp
7
+ Provides-Extra: test
8
+ Requires-Dist: pytest; extra == "test"
9
+ Requires-Dist: pytest-asyncio; extra == "test"
@@ -0,0 +1,8 @@
1
+ embed_client/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
2
+ embed_client/async_client.py,sha256=HzvJ85Qh8fT-YHuam4YFW5Kbxx2hrbsOV8EzjbQ34Eg,7329
3
+ embed_client/example_async_usage.py,sha256=7j9Hro7-TjsKVC2vHUX2J1_-Rh3V9FxsOmsCdCV8KYM,3555
4
+ embed_client/example_async_usage_ru.py,sha256=kZXQcbEFkx9tWXoCq-AoyvvUY4aCuW1XqPVb1ADWeAM,3558
5
+ embed_client-0.0.1.dist-info/METADATA,sha256=GUuiN2owdcnNa7XqqZeEJo_G9oV8Z7ZoqcNUtn-Cuyo,252
6
+ embed_client-0.0.1.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
7
+ embed_client-0.0.1.dist-info/top_level.txt,sha256=uG00A4d9o9DFrhiN7goObpeig72Pniby0E7UpDRgyXY,13
8
+ embed_client-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.7.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ embed_client