ailoy-py 0.0.1__cp312-cp312-macosx_14_0_arm64.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.
- ailoy/.dylibs/libomp.dylib +0 -0
- ailoy/.dylibs/libtvm_runtime.dylib +0 -0
- ailoy/__init__.py +3 -0
- ailoy/agent.py +729 -0
- ailoy/ailoy_py.cpython-312-darwin.so +0 -0
- ailoy/ailoy_py.pyi +29 -0
- ailoy/cli/__main__.py +11 -0
- ailoy/cli/model.py +112 -0
- ailoy/presets/tools/calculator.json +24 -0
- ailoy/presets/tools/frankfurter.json +33 -0
- ailoy/presets/tools/nytimes.json +26 -0
- ailoy/presets/tools/tmdb.json +185 -0
- ailoy/runtime.py +273 -0
- ailoy/vector_store.py +207 -0
- ailoy_py-0.0.1.dist-info/METADATA +88 -0
- ailoy_py-0.0.1.dist-info/RECORD +18 -0
- ailoy_py-0.0.1.dist-info/WHEEL +6 -0
- ailoy_py-0.0.1.dist-info/entry_points.txt +3 -0
ailoy/runtime.py
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
from asyncio import Event, to_thread
|
2
|
+
from collections import defaultdict
|
3
|
+
from typing import Any, AsyncGenerator, Generator, Literal, Optional, TypedDict
|
4
|
+
|
5
|
+
from .ailoy_py import BrokerClient, generate_uuid, start_threads, stop_threads
|
6
|
+
|
7
|
+
__all__ = ["Runtime", "AsyncRuntime"]
|
8
|
+
|
9
|
+
|
10
|
+
class Packet(TypedDict):
|
11
|
+
packet_type: Literal["respond", "respond_execute"]
|
12
|
+
instruction_type: Optional[Literal["call_function", "define_component", "delete_component", "call_method"]]
|
13
|
+
headers: list[bool | int | str]
|
14
|
+
body: dict[str, Any]
|
15
|
+
|
16
|
+
|
17
|
+
class RuntimeBase:
|
18
|
+
def __init__(self, address: str = "inproc://"):
|
19
|
+
self.address: str = address
|
20
|
+
self._responses: dict[str, Packet] = {}
|
21
|
+
self._exec_responses: defaultdict[str, dict[int, Packet]] = defaultdict(dict)
|
22
|
+
self._listen_lock: Optional[Event] = None
|
23
|
+
|
24
|
+
start_threads(self.address)
|
25
|
+
self._client: BrokerClient = BrokerClient(address)
|
26
|
+
txid = self._send_type1("connect")
|
27
|
+
if not txid:
|
28
|
+
raise RuntimeError("Connection failed")
|
29
|
+
self._sync_listen()
|
30
|
+
if not self._responses[txid]["body"]["status"]:
|
31
|
+
raise RuntimeError("Connection failed")
|
32
|
+
del self._responses[txid]
|
33
|
+
|
34
|
+
def __del__(self):
|
35
|
+
self.stop()
|
36
|
+
|
37
|
+
def __enter__(self):
|
38
|
+
return self
|
39
|
+
|
40
|
+
def __exit__(self, type, value, traceback):
|
41
|
+
self.stop()
|
42
|
+
|
43
|
+
def stop(self):
|
44
|
+
if self._client:
|
45
|
+
txid = self._send_type1("disconnect")
|
46
|
+
if not txid:
|
47
|
+
raise RuntimeError("Disconnection failed")
|
48
|
+
while txid not in self._responses:
|
49
|
+
self._sync_listen()
|
50
|
+
if not self._responses[txid]["body"]["status"]:
|
51
|
+
raise RuntimeError("Disconnection failed")
|
52
|
+
self._client = None
|
53
|
+
stop_threads(self.address)
|
54
|
+
|
55
|
+
def _send_type1(self, ptype: Literal["connect", "disconnect"]) -> Optional[str]:
|
56
|
+
txid = generate_uuid()
|
57
|
+
if self._client.send_type1(txid, ptype):
|
58
|
+
return txid
|
59
|
+
raise RuntimeError("Failed to send packet")
|
60
|
+
|
61
|
+
def _send_type2(
|
62
|
+
self,
|
63
|
+
ptype: Literal["subscribe", "unsubscribe", "execute"],
|
64
|
+
itype: Literal["call_function", "define_component", "delete_component", "call_method"],
|
65
|
+
*args,
|
66
|
+
):
|
67
|
+
txid = generate_uuid()
|
68
|
+
if self._client.send_type2(txid, ptype, itype, *args):
|
69
|
+
return txid
|
70
|
+
raise RuntimeError("Failed to send packet")
|
71
|
+
|
72
|
+
def _send_type3(
|
73
|
+
self,
|
74
|
+
ptype: Literal["respond", "respond_execute"],
|
75
|
+
status: bool,
|
76
|
+
*args,
|
77
|
+
):
|
78
|
+
txid = generate_uuid()
|
79
|
+
if self._client.send_type2(txid, ptype, status, *args):
|
80
|
+
return txid
|
81
|
+
raise RuntimeError("Failed to send packet")
|
82
|
+
|
83
|
+
def _sync_listen(self) -> None:
|
84
|
+
packet = self._client.listen()
|
85
|
+
if packet is not None:
|
86
|
+
txid = packet["headers"][0]
|
87
|
+
if packet["packet_type"] == "respond_execute":
|
88
|
+
idx = packet["headers"][1]
|
89
|
+
self._exec_responses[txid][idx] = packet
|
90
|
+
else:
|
91
|
+
self._responses[txid] = packet
|
92
|
+
|
93
|
+
async def _listen(self) -> None:
|
94
|
+
# If listen lock exists -> wait
|
95
|
+
if self._listen_lock:
|
96
|
+
await self._listen_lock.wait()
|
97
|
+
else:
|
98
|
+
# Create a new event
|
99
|
+
self._listen_lock = Event()
|
100
|
+
# Listen packet
|
101
|
+
packet = await to_thread(self._client.listen)
|
102
|
+
if packet is not None:
|
103
|
+
txid = packet["headers"][0]
|
104
|
+
if packet["packet_type"] == "respond_execute":
|
105
|
+
idx = packet["headers"][1]
|
106
|
+
self._exec_responses[txid][idx] = packet
|
107
|
+
else:
|
108
|
+
self._responses[txid] = packet
|
109
|
+
# Emit event
|
110
|
+
self._listen_lock.set()
|
111
|
+
self._listen_lock = None
|
112
|
+
|
113
|
+
|
114
|
+
class Runtime(RuntimeBase):
|
115
|
+
def __init__(self, address: str = "inproc://"):
|
116
|
+
super().__init__(address)
|
117
|
+
|
118
|
+
def call(self, func_name: str, input: Any) -> Any:
|
119
|
+
rv = [v for v in self.call_iter(func_name, input)]
|
120
|
+
if len(rv) == 0:
|
121
|
+
return None
|
122
|
+
elif len(rv) == 1:
|
123
|
+
return rv[0]
|
124
|
+
else:
|
125
|
+
return rv
|
126
|
+
|
127
|
+
def call_iter(self, func_name: str, input: Any) -> Generator[Any, None, None]:
|
128
|
+
txid = self._send_type2("execute", "call_function", func_name, input)
|
129
|
+
|
130
|
+
def generator():
|
131
|
+
idx = 0
|
132
|
+
finished = False
|
133
|
+
while not finished:
|
134
|
+
while idx not in self._exec_responses[txid]:
|
135
|
+
self._sync_listen()
|
136
|
+
packet = self._exec_responses[txid].pop(idx)
|
137
|
+
if not packet["body"]["status"]:
|
138
|
+
raise RuntimeError(packet["body"]["reason"])
|
139
|
+
if packet["headers"][2]:
|
140
|
+
finished = True
|
141
|
+
yield packet["body"]["out"]
|
142
|
+
idx += 1
|
143
|
+
del self._exec_responses[txid]
|
144
|
+
|
145
|
+
return generator()
|
146
|
+
|
147
|
+
def define(self, comp_type: str, comp_name: str, input: Any) -> None:
|
148
|
+
txid = self._send_type2("execute", "define_component", comp_type, comp_name, input)
|
149
|
+
while 0 not in self._exec_responses[txid]:
|
150
|
+
self._sync_listen()
|
151
|
+
packet = self._exec_responses[txid][0]
|
152
|
+
if not packet["body"]["status"]:
|
153
|
+
raise RuntimeError(packet["body"]["reason"])
|
154
|
+
del self._exec_responses[txid]
|
155
|
+
|
156
|
+
def delete(self, comp_name: str) -> None:
|
157
|
+
txid = self._send_type2("execute", "delete_component", comp_name)
|
158
|
+
while 0 not in self._exec_responses[txid]:
|
159
|
+
self._sync_listen()
|
160
|
+
packet = self._exec_responses[txid][0]
|
161
|
+
if not packet["body"]["status"]:
|
162
|
+
raise RuntimeError(packet["body"]["reason"])
|
163
|
+
del self._exec_responses[txid]
|
164
|
+
|
165
|
+
def call_method(self, comp_name: str, func_name: str, input: Any) -> Any:
|
166
|
+
rv = [v for v in self.call_iter_method(comp_name, func_name, input)]
|
167
|
+
if len(rv) == 0:
|
168
|
+
return None
|
169
|
+
elif len(rv) == 1:
|
170
|
+
return rv[0]
|
171
|
+
else:
|
172
|
+
return rv
|
173
|
+
|
174
|
+
def call_iter_method(self, comp_name: str, func_name: str, input: Any) -> Generator[Any, None, None]:
|
175
|
+
txid = self._send_type2("execute", "call_method", comp_name, func_name, input)
|
176
|
+
|
177
|
+
def generator():
|
178
|
+
idx = 0
|
179
|
+
finished = False
|
180
|
+
while not finished:
|
181
|
+
while idx not in self._exec_responses[txid]:
|
182
|
+
self._sync_listen()
|
183
|
+
packet = self._exec_responses[txid].pop(idx)
|
184
|
+
if not packet["body"]["status"]:
|
185
|
+
raise RuntimeError(packet["body"]["reason"])
|
186
|
+
if packet["headers"][2]:
|
187
|
+
finished = True
|
188
|
+
yield packet["body"]["out"]
|
189
|
+
idx += 1
|
190
|
+
del self._exec_responses[txid]
|
191
|
+
|
192
|
+
return generator()
|
193
|
+
|
194
|
+
|
195
|
+
class AsyncRuntime(RuntimeBase):
|
196
|
+
def __init__(self, address: str = "inproc://"):
|
197
|
+
super().__init__(address)
|
198
|
+
|
199
|
+
async def call(self, func_name: str, input: Any) -> Any:
|
200
|
+
rv = [v async for v in self.call_iter(func_name, input)]
|
201
|
+
if len(rv) == 0:
|
202
|
+
return None
|
203
|
+
elif len(rv) == 1:
|
204
|
+
return rv[0]
|
205
|
+
else:
|
206
|
+
return rv
|
207
|
+
|
208
|
+
def call_iter(self, func_name: str, input: Any) -> AsyncGenerator[Any, None]:
|
209
|
+
txid = self._send_type2("execute", "call_function", func_name, input)
|
210
|
+
|
211
|
+
async def generator():
|
212
|
+
idx = 0
|
213
|
+
finished = False
|
214
|
+
while not finished:
|
215
|
+
while idx not in self._exec_responses[txid]:
|
216
|
+
await self._listen()
|
217
|
+
packet = self._exec_responses[txid].pop(idx)
|
218
|
+
if not packet["body"]["status"]:
|
219
|
+
raise RuntimeError(packet["body"]["reason"])
|
220
|
+
if packet["headers"][2]:
|
221
|
+
finished = True
|
222
|
+
yield packet["body"]["out"]
|
223
|
+
idx += 1
|
224
|
+
del self._exec_responses[txid]
|
225
|
+
|
226
|
+
return generator()
|
227
|
+
|
228
|
+
async def define(self, comp_type: str, comp_name: str, input: Any) -> None:
|
229
|
+
txid = self._send_type2("execute", "define_component", comp_type, comp_name, input)
|
230
|
+
while 0 not in self._exec_responses[txid]:
|
231
|
+
await self._listen()
|
232
|
+
packet = self._exec_responses[txid][0]
|
233
|
+
if not packet["body"]["status"]:
|
234
|
+
raise RuntimeError(packet["body"]["reason"])
|
235
|
+
del self._exec_responses[txid]
|
236
|
+
|
237
|
+
async def delete(self, comp_name: str) -> None:
|
238
|
+
txid = self._send_type2("execute", "delete_component", comp_name)
|
239
|
+
while 0 not in self._exec_responses[txid]:
|
240
|
+
await self._listen()
|
241
|
+
packet = self._exec_responses[txid][0]
|
242
|
+
if not packet["body"]["status"]:
|
243
|
+
raise RuntimeError(packet["body"]["reason"])
|
244
|
+
del self._exec_responses[txid]
|
245
|
+
|
246
|
+
async def call_method(self, comp_name: str, func_name: str, input: Any) -> Any:
|
247
|
+
rv = [v async for v in self.call_iter_method(comp_name, func_name, input)]
|
248
|
+
if len(rv) == 0:
|
249
|
+
return None
|
250
|
+
elif len(rv) == 1:
|
251
|
+
return rv[0]
|
252
|
+
else:
|
253
|
+
return rv
|
254
|
+
|
255
|
+
def call_iter_method(self, comp_name: str, func_name: str, input: Any) -> AsyncGenerator[Any, None]:
|
256
|
+
txid = self._send_type2("execute", "call_method", comp_name, func_name, input)
|
257
|
+
|
258
|
+
async def generator():
|
259
|
+
idx = 0
|
260
|
+
finished = False
|
261
|
+
while not finished:
|
262
|
+
while idx not in self._exec_responses[txid]:
|
263
|
+
await self._listen()
|
264
|
+
packet = self._exec_responses[txid].pop(idx)
|
265
|
+
if not packet["body"]["status"]:
|
266
|
+
raise RuntimeError(packet["body"]["reason"])
|
267
|
+
if packet["headers"][2]:
|
268
|
+
finished = True
|
269
|
+
yield packet["body"]["out"]
|
270
|
+
idx += 1
|
271
|
+
del self._exec_responses[txid]
|
272
|
+
|
273
|
+
return generator()
|
ailoy/vector_store.py
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
from typing import Any, Dict, List, Literal, Optional
|
2
|
+
|
3
|
+
from pydantic import BaseModel, TypeAdapter
|
4
|
+
|
5
|
+
from ailoy.runtime import Runtime, generate_uuid
|
6
|
+
|
7
|
+
__all__ = ["VectorStore"]
|
8
|
+
|
9
|
+
|
10
|
+
class VectorStoreInsertItem(BaseModel):
|
11
|
+
document: str
|
12
|
+
metadata: Optional[Dict[str, Any]] = None
|
13
|
+
|
14
|
+
|
15
|
+
class VectorStoreRetrieveItem(VectorStoreInsertItem):
|
16
|
+
id: str
|
17
|
+
similarity: float
|
18
|
+
|
19
|
+
|
20
|
+
class ComponentState(BaseModel):
|
21
|
+
embedding_model_name: str
|
22
|
+
vector_store_name: str
|
23
|
+
valid: bool
|
24
|
+
|
25
|
+
|
26
|
+
class VectorStore:
|
27
|
+
"""
|
28
|
+
The `VectorStore` class provides a high-level abstraction for storing and retrieving documents.
|
29
|
+
It mainly consists of two modules - embedding model and vector store.
|
30
|
+
|
31
|
+
It supports embedding text using AI and interfacing with pluggable vector store backends such as FAISS or ChromaDB.
|
32
|
+
This class handles initialization, insertion, similarity-based retrieval, and cleanup.
|
33
|
+
|
34
|
+
Typical usage involves:
|
35
|
+
1. Initializing the store via `initialize()`
|
36
|
+
2. Inserting documents via `insert()`
|
37
|
+
3. Querying similar documents via `retrieve()`
|
38
|
+
|
39
|
+
The embedding model and vector store are defined dynamically within the provided runtime.
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(
|
43
|
+
self,
|
44
|
+
runtime: Runtime,
|
45
|
+
embedding_model_name: Literal["BAAI/bge-m3"],
|
46
|
+
vector_store_name: Literal["faiss", "chromadb"],
|
47
|
+
url: Optional[str] = None,
|
48
|
+
collection: Optional[str] = None,
|
49
|
+
embedding_model_attrs: dict[str, Any] = dict(),
|
50
|
+
vector_store_attrs: dict[str, Any] = dict(),
|
51
|
+
):
|
52
|
+
"""
|
53
|
+
Creates an instance.
|
54
|
+
|
55
|
+
:param runtime: The runtime environment used to manage components.
|
56
|
+
:param embedding_model_name: The name of the embedding model to use. Currently it only supports `BAAI/bge-m3`.
|
57
|
+
:param url: (ChromaDB only) URL of the database.
|
58
|
+
:param collection: (ChromaDB only) The collection name of the database.
|
59
|
+
:param vector_store_name: The name of the vector store provider (One of faiss or chromaDB).
|
60
|
+
:param embedding_model_attrs: Additional initialization parameters (for `define_component` runtime call).
|
61
|
+
:param vector_store_attrs: Additional initialization parameters (for `define_component` runtime call).
|
62
|
+
"""
|
63
|
+
self._runtime = runtime
|
64
|
+
self._component_state = ComponentState(
|
65
|
+
embedding_model_name=generate_uuid(),
|
66
|
+
vector_store_name=generate_uuid(),
|
67
|
+
valid=False,
|
68
|
+
)
|
69
|
+
self.define(
|
70
|
+
embedding_model_name,
|
71
|
+
vector_store_name,
|
72
|
+
url,
|
73
|
+
collection,
|
74
|
+
embedding_model_attrs,
|
75
|
+
vector_store_attrs,
|
76
|
+
)
|
77
|
+
|
78
|
+
def __del__(self):
|
79
|
+
self.delete()
|
80
|
+
|
81
|
+
def __enter__(self):
|
82
|
+
return self
|
83
|
+
|
84
|
+
def __exit__(self, type, value, traceback):
|
85
|
+
self.delete()
|
86
|
+
|
87
|
+
def define(
|
88
|
+
self,
|
89
|
+
embedding_model_name: Literal["BAAI/bge-m3"],
|
90
|
+
vector_store_name: Literal["faiss", "chromadb"],
|
91
|
+
url: Optional[str] = None,
|
92
|
+
collection: Optional[str] = None,
|
93
|
+
embedding_model_attrs: dict[str, Any] = dict(),
|
94
|
+
vector_store_attrs: dict[str, Any] = dict(),
|
95
|
+
):
|
96
|
+
"""
|
97
|
+
Defines the embedding model and vector store components to the runtime.
|
98
|
+
This must be called before using any other method in the class. If already defined, this is a no-op.
|
99
|
+
"""
|
100
|
+
if self._component_state.valid:
|
101
|
+
return
|
102
|
+
|
103
|
+
# Dimension size may be different based on embedding model
|
104
|
+
dimension = 1024
|
105
|
+
|
106
|
+
# Initialize embedding model
|
107
|
+
if embedding_model_name == "BAAI/bge-m3":
|
108
|
+
dimension = 1024
|
109
|
+
self._runtime.define(
|
110
|
+
"tvm_embedding_model",
|
111
|
+
self._component_state.embedding_model_name,
|
112
|
+
{
|
113
|
+
"model": "BAAI/bge-m3",
|
114
|
+
**embedding_model_attrs,
|
115
|
+
},
|
116
|
+
)
|
117
|
+
else:
|
118
|
+
raise NotImplementedError(f"Unsupprted embedding model: {embedding_model_name}")
|
119
|
+
|
120
|
+
# Initialize vector store
|
121
|
+
if vector_store_name == "faiss":
|
122
|
+
if "dimension" not in vector_store_attrs:
|
123
|
+
vector_store_attrs["dimension"] = dimension
|
124
|
+
self._runtime.define("faiss_vector_store", self._component_state.vector_store_name, vector_store_attrs)
|
125
|
+
elif vector_store_name == "chromadb":
|
126
|
+
if "url" not in vector_store_attrs:
|
127
|
+
vector_store_attrs["url"] = url
|
128
|
+
if "collection" not in vector_store_attrs:
|
129
|
+
vector_store_attrs["collection"] = collection
|
130
|
+
self._runtime.define("chromadb_vector_store", self._component_state.vector_store_name, vector_store_attrs)
|
131
|
+
else:
|
132
|
+
raise NotImplementedError(f"Unsupprted vector store: {vector_store_name}")
|
133
|
+
|
134
|
+
self._component_state.valid = True
|
135
|
+
|
136
|
+
def delete(self):
|
137
|
+
"""
|
138
|
+
Delete resources from the runtime.
|
139
|
+
This should be called when the VectorStore is no longer needed. If already deleted, this is a no-op.
|
140
|
+
"""
|
141
|
+
if not self._component_state.valid:
|
142
|
+
return
|
143
|
+
|
144
|
+
self._runtime.delete(self._component_state.embedding_model_name)
|
145
|
+
self._runtime.delete(self._component_state.vector_store_name)
|
146
|
+
self._component_state.valid = False
|
147
|
+
|
148
|
+
# TODO: add NDArray typing
|
149
|
+
def embedding(self, text: str) -> Any:
|
150
|
+
"""
|
151
|
+
Generates an embedding vector for the given input text using the embedding model.
|
152
|
+
|
153
|
+
:param text: Input text to embed.
|
154
|
+
:returns: The resulting embedding vector.
|
155
|
+
"""
|
156
|
+
resp = self._runtime.call_method(
|
157
|
+
self._component_state.embedding_model_name,
|
158
|
+
"infer",
|
159
|
+
{
|
160
|
+
"prompt": text,
|
161
|
+
},
|
162
|
+
)
|
163
|
+
return resp["embedding"]
|
164
|
+
|
165
|
+
def insert(self, document: str, metadata: Optional[Dict[str, Any]] = None):
|
166
|
+
"""
|
167
|
+
Inserts a new document into the vector store.
|
168
|
+
|
169
|
+
:param document: The raw text document to insert.
|
170
|
+
:param metadata: Metadata records additional information about the document.
|
171
|
+
"""
|
172
|
+
embedding = self.embedding(document)
|
173
|
+
self._runtime.call_method(
|
174
|
+
self._component_state.vector_store_name,
|
175
|
+
"insert",
|
176
|
+
{
|
177
|
+
"embedding": embedding,
|
178
|
+
"document": document,
|
179
|
+
"metadata": metadata,
|
180
|
+
},
|
181
|
+
)
|
182
|
+
|
183
|
+
def retrieve(self, query: str, top_k: int = 5) -> List[VectorStoreRetrieveItem]:
|
184
|
+
"""
|
185
|
+
Retrieves the top-K most similar documents to the given query.
|
186
|
+
|
187
|
+
:param query: The input query string to search for similar content.
|
188
|
+
:param top_k: Number of top similar documents to retrieve.
|
189
|
+
:returns: A list of retrieved items.
|
190
|
+
"""
|
191
|
+
embedding = self.embedding(query)
|
192
|
+
resp = self._runtime.call_method(
|
193
|
+
self._component_state.vector_store_name,
|
194
|
+
"retrieve",
|
195
|
+
{
|
196
|
+
"query_embedding": embedding,
|
197
|
+
"top_k": top_k,
|
198
|
+
},
|
199
|
+
)
|
200
|
+
results = TypeAdapter(List[VectorStoreRetrieveItem]).validate_python(resp["results"])
|
201
|
+
return results
|
202
|
+
|
203
|
+
def clean(self):
|
204
|
+
"""
|
205
|
+
Removes all entries from the vector store.
|
206
|
+
"""
|
207
|
+
self._runtime.call_method(self._component_state.vector_store_name, "clean", {})
|
@@ -0,0 +1,88 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: ailoy-py
|
3
|
+
Version: 0.0.1
|
4
|
+
Summary: Python binding for Ailoy runtime APIs
|
5
|
+
Author-Email: "Brekkylab Inc." <contact@brekkylab.com>
|
6
|
+
License-Expression: Apache-2.0
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
8
|
+
Classifier: Intended Audience :: Developers
|
9
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Requires-Python: >=3.10
|
17
|
+
Requires-Dist: anyio>=4.9.0
|
18
|
+
Requires-Dist: jmespath>=1.0.1
|
19
|
+
Requires-Dist: mcp>=1.8.0
|
20
|
+
Requires-Dist: numpy>=2.0.2
|
21
|
+
Requires-Dist: pydantic>=2.11.4
|
22
|
+
Requires-Dist: rich>=14.0.0
|
23
|
+
Requires-Dist: typer>=0.15.4
|
24
|
+
Description-Content-Type: text/markdown
|
25
|
+
|
26
|
+
# ailoy-py
|
27
|
+
|
28
|
+
Python binding for Ailoy runtime APIs.
|
29
|
+
|
30
|
+
See our [documentation](https://brekkylab.github.io/ailoy) for more details.
|
31
|
+
|
32
|
+
## Install
|
33
|
+
|
34
|
+
```bash
|
35
|
+
pip install ailoy-py
|
36
|
+
```
|
37
|
+
|
38
|
+
## Quickstart
|
39
|
+
|
40
|
+
```python
|
41
|
+
from ailoy import Runtime, Agent
|
42
|
+
|
43
|
+
# The runtime must be started to use Ailoy
|
44
|
+
rt = Runtime()
|
45
|
+
|
46
|
+
# Defines an agent
|
47
|
+
# During this step, the model parameters are downloaded and the LLM is set up for execution
|
48
|
+
with Agent(rt, model_name="Qwen/Qwen3-0.6B") as agent:
|
49
|
+
# This is where the actual LLM call happens
|
50
|
+
for resp in agent.query("Please give me a short poem about AI"):
|
51
|
+
agent.print(resp)
|
52
|
+
|
53
|
+
# Stop the runtime
|
54
|
+
rt.stop()
|
55
|
+
```
|
56
|
+
|
57
|
+
## Building from source
|
58
|
+
|
59
|
+
### Prerequisites
|
60
|
+
|
61
|
+
- Python 3.10 or higher
|
62
|
+
- C/C++ compiler
|
63
|
+
(recommended versions are below)
|
64
|
+
- GCC >= 13
|
65
|
+
- LLVM Clang >= 17
|
66
|
+
- Apple Clang >= 15
|
67
|
+
- MSVC >= 19.29
|
68
|
+
- CMake >= 3.24.0
|
69
|
+
- Git
|
70
|
+
- OpenSSL
|
71
|
+
- Rust & Cargo >= 1.82.0
|
72
|
+
- OpenMP
|
73
|
+
- BLAS
|
74
|
+
- LAPACK
|
75
|
+
- Vulkan SDK (if you are using vulkan)
|
76
|
+
|
77
|
+
|
78
|
+
### Setup development environment
|
79
|
+
|
80
|
+
```bash
|
81
|
+
pip install -e .
|
82
|
+
```
|
83
|
+
|
84
|
+
### Generate wheel
|
85
|
+
|
86
|
+
```bash
|
87
|
+
python -m build -w
|
88
|
+
```
|
@@ -0,0 +1,18 @@
|
|
1
|
+
ailoy/ailoy_py.cpython-312-darwin.so,sha256=O174nGPlqj7xn4WdBaPa87C7TWtZN9NA_PrTXz13omo,17025088
|
2
|
+
ailoy/ailoy_py.pyi,sha256=Yf90FEXkslpCpr1r2eqQ3-_1jLo65zmG94bBXDRqinU,991
|
3
|
+
ailoy/vector_store.py,sha256=Ojhr4bcSfKKuMaldfsjz_G41AGgz4vyvpkWn5WMFE2c,7365
|
4
|
+
ailoy/__init__.py,sha256=ArHu4OLbxU_re9cX-7zhshRqkn46gBcl-0SxDa5Wk00,148
|
5
|
+
ailoy/runtime.py,sha256=tVdUaqqx9NB-h4grRkW_R2XYW5ihFn95aUhnTZkl_Zg,9997
|
6
|
+
ailoy/agent.py,sha256=orrfgeH6Xo9nPkHqJJ1YqS_8-5-0_tkpKlF8YcdRIqU,24998
|
7
|
+
ailoy/cli/model.py,sha256=cerCHE-VY9TOwqRcLBtmqnV-5vphpvyhtrfPFZiTKCM,2979
|
8
|
+
ailoy/cli/__main__.py,sha256=HnBVb2em1F2NLPeNX5r3xRndRrnGaXVCduo8WBULAI0,179
|
9
|
+
ailoy/.dylibs/libomp.dylib,sha256=GX9Rol1LBJAoha7wZJMQxuCUi_o41Yo5QLBTMN85rRI,735616
|
10
|
+
ailoy/.dylibs/libtvm_runtime.dylib,sha256=XRFCL65dNaE9JNMvuLvfBoriquAs90OfMl_AmNd_BG8,3324976
|
11
|
+
ailoy/presets/tools/tmdb.json,sha256=UGLN5uAJ2b-Hu3nLcW95WXDLB3mfC3rBYfQANp_e8Ps,7046
|
12
|
+
ailoy/presets/tools/calculator.json,sha256=ePnZsjZChnvS08s9eVdIp4Bys_PlJBXPHCCjv6oMvzA,1040
|
13
|
+
ailoy/presets/tools/nytimes.json,sha256=wrfe9bnAlSPzHladoGEX2oCAeE0wed3BvgXQ_Z2PdXg,918
|
14
|
+
ailoy/presets/tools/frankfurter.json,sha256=bZ5vhszf_aR-B_QN4L2xrI5nR-f4AMZk41UUDq1dTXg,1152
|
15
|
+
ailoy_py-0.0.1.dist-info/RECORD,,
|
16
|
+
ailoy_py-0.0.1.dist-info/WHEEL,sha256=NdzsWaD5A_LKBhqfKDFIgjB3iRnxft5CRtv8RBeg8bg,141
|
17
|
+
ailoy_py-0.0.1.dist-info/entry_points.txt,sha256=gVG45uDE6kef0wm6SEMYSgZgRNNRhSAeP2n2lPR00dI,50
|
18
|
+
ailoy_py-0.0.1.dist-info/METADATA,sha256=FAyzKTteIMgZse5H99IVQ5q2ScjU9hlTuOggBNrgTF0,2010
|