agno 2.3.22__py3-none-any.whl → 2.3.24__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.
- agno/agent/agent.py +28 -1
- agno/agent/remote.py +1 -1
- agno/db/mongo/mongo.py +9 -1
- agno/db/mysql/async_mysql.py +5 -7
- agno/db/mysql/mysql.py +5 -7
- agno/db/mysql/schemas.py +39 -21
- agno/db/postgres/async_postgres.py +10 -2
- agno/db/postgres/postgres.py +5 -7
- agno/db/postgres/schemas.py +39 -21
- agno/db/singlestore/schemas.py +41 -21
- agno/db/singlestore/singlestore.py +14 -3
- agno/db/sqlite/async_sqlite.py +7 -2
- agno/db/sqlite/schemas.py +36 -21
- agno/db/sqlite/sqlite.py +3 -7
- agno/knowledge/chunking/markdown.py +94 -8
- agno/knowledge/chunking/semantic.py +2 -2
- agno/knowledge/knowledge.py +215 -207
- agno/models/base.py +32 -8
- agno/models/google/gemini.py +27 -4
- agno/os/routers/agents/router.py +1 -1
- agno/os/routers/evals/evals.py +2 -2
- agno/os/routers/knowledge/knowledge.py +21 -5
- agno/os/routers/knowledge/schemas.py +1 -1
- agno/os/routers/memory/memory.py +4 -4
- agno/os/routers/session/session.py +2 -2
- agno/os/routers/teams/router.py +2 -2
- agno/os/routers/traces/traces.py +3 -3
- agno/os/routers/workflows/router.py +1 -1
- agno/os/schema.py +1 -1
- agno/os/utils.py +1 -1
- agno/remote/base.py +1 -1
- agno/team/remote.py +1 -1
- agno/team/team.py +24 -4
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +150 -13
- agno/tools/crawl4ai.py +3 -0
- agno/tools/file.py +14 -13
- agno/tools/function.py +15 -2
- agno/tools/mcp/mcp.py +1 -0
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/python.py +14 -6
- agno/tools/toolkit.py +122 -23
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/chromadb.py +1 -1
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +1 -1
- agno/vectordb/milvus/milvus.py +1 -1
- agno/vectordb/mongodb/mongodb.py +13 -3
- agno/vectordb/pgvector/pgvector.py +1 -1
- agno/vectordb/pineconedb/pineconedb.py +2 -2
- agno/vectordb/qdrant/qdrant.py +1 -1
- agno/vectordb/redis/redisdb.py +2 -2
- agno/vectordb/singlestore/singlestore.py +1 -1
- agno/vectordb/surrealdb/surrealdb.py +2 -2
- agno/vectordb/weaviate/weaviate.py +1 -1
- agno/workflow/remote.py +1 -1
- agno/workflow/workflow.py +14 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/METADATA +1 -1
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/RECORD +62 -62
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/WHEEL +0 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/top_level.txt +0 -0
agno/tools/toolkit.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from collections import OrderedDict
|
|
2
|
-
from
|
|
2
|
+
from inspect import iscoroutinefunction
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
|
|
3
5
|
|
|
4
6
|
from agno.tools.function import Function
|
|
5
|
-
from agno.utils.log import log_debug, log_warning, logger
|
|
7
|
+
from agno.utils.log import log_debug, log_error, log_warning, logger
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class Toolkit:
|
|
@@ -14,6 +16,7 @@ class Toolkit:
|
|
|
14
16
|
self,
|
|
15
17
|
name: str = "toolkit",
|
|
16
18
|
tools: Sequence[Union[Callable[..., Any], Function]] = [],
|
|
19
|
+
async_tools: Optional[Sequence[tuple[Callable[..., Any], str]]] = None,
|
|
17
20
|
instructions: Optional[str] = None,
|
|
18
21
|
add_instructions: bool = False,
|
|
19
22
|
include_tools: Optional[list[str]] = None,
|
|
@@ -32,6 +35,9 @@ class Toolkit:
|
|
|
32
35
|
Args:
|
|
33
36
|
name: A descriptive name for the toolkit
|
|
34
37
|
tools: List of tools to include in the toolkit (can be callables or Function objects from @tool decorator)
|
|
38
|
+
async_tools: List of (async_callable, tool_name) tuples for async variants.
|
|
39
|
+
Used when async methods have different names than sync methods.
|
|
40
|
+
Example: [(self.anavigate_to, "navigate_to"), (self.ascreenshot, "screenshot")]
|
|
35
41
|
instructions: Instructions for the toolkit
|
|
36
42
|
add_instructions: Whether to add instructions to the toolkit
|
|
37
43
|
include_tools: List of tool names to include in the toolkit
|
|
@@ -47,7 +53,11 @@ class Toolkit:
|
|
|
47
53
|
"""
|
|
48
54
|
self.name: str = name
|
|
49
55
|
self.tools: Sequence[Union[Callable[..., Any], Function]] = tools
|
|
56
|
+
self._async_tools: Sequence[tuple[Callable[..., Any], str]] = async_tools or []
|
|
57
|
+
# Functions dict - used by agent.run() and agent.print_response()
|
|
50
58
|
self.functions: Dict[str, Function] = OrderedDict()
|
|
59
|
+
# Async functions dict - used by agent.arun() and agent.aprint_response()
|
|
60
|
+
self.async_functions: Dict[str, Function] = OrderedDict()
|
|
51
61
|
self.instructions: Optional[str] = instructions
|
|
52
62
|
self.add_instructions: bool = add_instructions
|
|
53
63
|
|
|
@@ -71,8 +81,11 @@ class Toolkit:
|
|
|
71
81
|
self.cache_dir: Optional[str] = cache_dir
|
|
72
82
|
|
|
73
83
|
# Automatically register all methods if auto_register is True
|
|
74
|
-
if auto_register
|
|
75
|
-
self.
|
|
84
|
+
if auto_register:
|
|
85
|
+
if self.tools:
|
|
86
|
+
self._register_tools()
|
|
87
|
+
if self._async_tools:
|
|
88
|
+
self._register_async_tools()
|
|
76
89
|
|
|
77
90
|
def _get_tool_name(self, tool: Union[Callable[..., Any], Function]) -> str:
|
|
78
91
|
"""Get the name of a tool, whether it's a Function or callable."""
|
|
@@ -125,14 +138,25 @@ class Toolkit:
|
|
|
125
138
|
log_warning(f"Show result tool(s) not present in the toolkit: {', '.join(missing_show_result)}")
|
|
126
139
|
|
|
127
140
|
def _register_tools(self) -> None:
|
|
128
|
-
"""Register all tools."""
|
|
141
|
+
"""Register all sync tools."""
|
|
129
142
|
for tool in self.tools:
|
|
130
143
|
self.register(tool)
|
|
131
144
|
|
|
145
|
+
def _register_async_tools(self) -> None:
|
|
146
|
+
"""Register all async tools with their mapped names.
|
|
147
|
+
|
|
148
|
+
Async detection is automatic via iscoroutinefunction.
|
|
149
|
+
"""
|
|
150
|
+
for async_func, tool_name in self._async_tools:
|
|
151
|
+
self.register(async_func, name=tool_name)
|
|
152
|
+
|
|
132
153
|
def register(self, function: Union[Callable[..., Any], Function], name: Optional[str] = None) -> None:
|
|
133
154
|
"""Register a function with the toolkit.
|
|
134
155
|
|
|
135
156
|
This method supports both regular callables and Function objects (from @tool decorator).
|
|
157
|
+
Automatically detects if the function is async (using iscoroutinefunction) and registers
|
|
158
|
+
it to the appropriate dict (functions for sync, async_functions for async).
|
|
159
|
+
|
|
136
160
|
When a Function object is passed (e.g., from a @tool decorated method), it will:
|
|
137
161
|
1. Extract the configuration from the Function object
|
|
138
162
|
2. Look for a bound method with the same name on `self`
|
|
@@ -140,17 +164,18 @@ class Toolkit:
|
|
|
140
164
|
|
|
141
165
|
Args:
|
|
142
166
|
function: The callable or Function object to register
|
|
143
|
-
name: Optional custom name for the function
|
|
144
|
-
|
|
145
|
-
Returns:
|
|
146
|
-
The registered function
|
|
167
|
+
name: Optional custom name for the function (useful for aliasing)
|
|
147
168
|
"""
|
|
148
169
|
try:
|
|
149
170
|
# Handle Function objects (from @tool decorator)
|
|
150
171
|
if isinstance(function, Function):
|
|
151
|
-
|
|
172
|
+
# Auto-detect if this is an async function
|
|
173
|
+
is_async = function.entrypoint is not None and iscoroutinefunction(function.entrypoint)
|
|
174
|
+
return self._register_decorated_tool(function, name, is_async=is_async)
|
|
175
|
+
|
|
176
|
+
# Handle regular callables - auto-detect async
|
|
177
|
+
is_async = iscoroutinefunction(function)
|
|
152
178
|
|
|
153
|
-
# Handle regular callables
|
|
154
179
|
tool_name = name or function.__name__
|
|
155
180
|
if self.include_tools is not None and tool_name not in self.include_tools:
|
|
156
181
|
return
|
|
@@ -168,14 +193,19 @@ class Toolkit:
|
|
|
168
193
|
stop_after_tool_call=tool_name in self.stop_after_tool_call_tools,
|
|
169
194
|
show_result=tool_name in self.show_result_tools or tool_name in self.stop_after_tool_call_tools,
|
|
170
195
|
)
|
|
171
|
-
|
|
172
|
-
|
|
196
|
+
|
|
197
|
+
if is_async:
|
|
198
|
+
self.async_functions[f.name] = f
|
|
199
|
+
log_debug(f"Async function: {f.name} registered with {self.name}")
|
|
200
|
+
else:
|
|
201
|
+
self.functions[f.name] = f
|
|
202
|
+
log_debug(f"Function: {f.name} registered with {self.name}")
|
|
173
203
|
except Exception as e:
|
|
174
204
|
func_name = self._get_tool_name(function)
|
|
175
205
|
logger.warning(f"Failed to create Function for: {func_name}")
|
|
176
206
|
raise e
|
|
177
207
|
|
|
178
|
-
def _register_decorated_tool(self, function: Function, name: Optional[str] = None) -> None:
|
|
208
|
+
def _register_decorated_tool(self, function: Function, name: Optional[str] = None, is_async: bool = False) -> None:
|
|
179
209
|
"""Register a Function object from @tool decorator, binding it to self.
|
|
180
210
|
|
|
181
211
|
When @tool decorator is used on a class method, it creates a Function with an unbound
|
|
@@ -185,6 +215,7 @@ class Toolkit:
|
|
|
185
215
|
Args:
|
|
186
216
|
function: The Function object from @tool decorator
|
|
187
217
|
name: Optional custom name override
|
|
218
|
+
is_async: If True, register to async_functions dict instead of functions
|
|
188
219
|
"""
|
|
189
220
|
import inspect
|
|
190
221
|
|
|
@@ -207,14 +238,24 @@ class Toolkit:
|
|
|
207
238
|
|
|
208
239
|
if params and params[0] == "self":
|
|
209
240
|
# Create a bound method by wrapping the function to include self
|
|
210
|
-
|
|
211
|
-
def bound(*args, **kwargs):
|
|
212
|
-
return func(instance, *args, **kwargs)
|
|
241
|
+
if is_async:
|
|
213
242
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
243
|
+
def make_bound_method(func, instance):
|
|
244
|
+
async def bound(*args, **kwargs):
|
|
245
|
+
return await func(instance, *args, **kwargs)
|
|
246
|
+
|
|
247
|
+
bound.__name__ = getattr(func, "__name__", tool_name)
|
|
248
|
+
bound.__doc__ = getattr(func, "__doc__", None)
|
|
249
|
+
return bound
|
|
250
|
+
else:
|
|
251
|
+
|
|
252
|
+
def make_bound_method(func, instance):
|
|
253
|
+
def bound(*args, **kwargs):
|
|
254
|
+
return func(instance, *args, **kwargs)
|
|
255
|
+
|
|
256
|
+
bound.__name__ = getattr(func, "__name__", tool_name)
|
|
257
|
+
bound.__doc__ = getattr(func, "__doc__", None)
|
|
258
|
+
return bound
|
|
218
259
|
|
|
219
260
|
bound_method = make_bound_method(original_func, self)
|
|
220
261
|
else:
|
|
@@ -251,8 +292,36 @@ class Toolkit:
|
|
|
251
292
|
cache_dir=function.cache_dir if function.cache_dir else self.cache_dir,
|
|
252
293
|
cache_ttl=function.cache_ttl if function.cache_ttl != 3600 else self.cache_ttl,
|
|
253
294
|
)
|
|
254
|
-
|
|
255
|
-
|
|
295
|
+
|
|
296
|
+
if is_async:
|
|
297
|
+
self.async_functions[f.name] = f
|
|
298
|
+
log_debug(f"Async function: {f.name} registered with {self.name} (from @tool decorator)")
|
|
299
|
+
else:
|
|
300
|
+
self.functions[f.name] = f
|
|
301
|
+
log_debug(f"Function: {f.name} registered with {self.name} (from @tool decorator)")
|
|
302
|
+
|
|
303
|
+
def get_functions(self) -> Dict[str, Function]:
|
|
304
|
+
"""Get sync functions dict.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Dict of function name to Function for sync execution
|
|
308
|
+
"""
|
|
309
|
+
return self.functions
|
|
310
|
+
|
|
311
|
+
def get_async_functions(self) -> Dict[str, Function]:
|
|
312
|
+
"""Get functions dict optimized for async execution.
|
|
313
|
+
|
|
314
|
+
Returns a merged dict where async_functions take precedence over functions.
|
|
315
|
+
This allows async-optimized implementations to be automatically used in async contexts,
|
|
316
|
+
while falling back to sync implementations for tools without async variants.
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Dict of function name to Function, with async variants preferred
|
|
320
|
+
"""
|
|
321
|
+
# Merge: start with sync functions, override with async variants
|
|
322
|
+
merged = OrderedDict(self.functions)
|
|
323
|
+
merged.update(self.async_functions)
|
|
324
|
+
return merged
|
|
256
325
|
|
|
257
326
|
@property
|
|
258
327
|
def requires_connect(self) -> bool:
|
|
@@ -275,6 +344,36 @@ class Toolkit:
|
|
|
275
344
|
"""
|
|
276
345
|
pass
|
|
277
346
|
|
|
347
|
+
def _check_path(self, file_name: str, base_dir: Path, restrict_to_base_dir: bool = True) -> Tuple[bool, Path]:
|
|
348
|
+
"""Check if the file path is within the base directory.
|
|
349
|
+
|
|
350
|
+
This method validates that a given file path resolves to a location
|
|
351
|
+
within the specified base_dir, preventing directory traversal attacks.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
file_name: The file name or relative path to check.
|
|
355
|
+
base_dir: The base directory to validate against.
|
|
356
|
+
restrict_to_base_dir: If True, reject paths outside base_dir.
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
Tuple of (is_safe, resolved_path). If not safe, returns base_dir as the path.
|
|
360
|
+
"""
|
|
361
|
+
file_path = base_dir.joinpath(file_name).resolve()
|
|
362
|
+
|
|
363
|
+
if not restrict_to_base_dir:
|
|
364
|
+
return True, file_path
|
|
365
|
+
|
|
366
|
+
if base_dir == file_path:
|
|
367
|
+
return True, file_path
|
|
368
|
+
|
|
369
|
+
try:
|
|
370
|
+
file_path.relative_to(base_dir)
|
|
371
|
+
except ValueError:
|
|
372
|
+
log_error(f"Path escapes base directory: {file_name}")
|
|
373
|
+
return False, base_dir
|
|
374
|
+
|
|
375
|
+
return True, file_path
|
|
376
|
+
|
|
278
377
|
def __repr__(self):
|
|
279
378
|
return f"<{self.__class__.__name__} name={self.name} functions={list(self.functions.keys())}>"
|
|
280
379
|
|
|
@@ -32,7 +32,7 @@ class Cassandra(VectorDb):
|
|
|
32
32
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
33
33
|
|
|
34
34
|
embedder = OpenAIEmbedder()
|
|
35
|
-
|
|
35
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
36
36
|
# Initialize base class with name and description
|
|
37
37
|
super().__init__(name=name, description=description)
|
|
38
38
|
|
agno/vectordb/chroma/chromadb.py
CHANGED
|
@@ -117,7 +117,7 @@ class ChromaDb(VectorDb):
|
|
|
117
117
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
118
118
|
|
|
119
119
|
embedder = OpenAIEmbedder()
|
|
120
|
-
|
|
120
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
121
121
|
self.embedder: Embedder = embedder
|
|
122
122
|
# Distance metric
|
|
123
123
|
self.distance: Distance = distance
|
|
@@ -71,7 +71,7 @@ class Clickhouse(VectorDb):
|
|
|
71
71
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
72
72
|
|
|
73
73
|
_embedder = OpenAIEmbedder()
|
|
74
|
-
|
|
74
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
75
75
|
self.embedder: Embedder = _embedder
|
|
76
76
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
77
77
|
|
|
@@ -100,7 +100,7 @@ class CouchbaseSearch(VectorDb):
|
|
|
100
100
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
101
101
|
|
|
102
102
|
embedder = OpenAIEmbedder()
|
|
103
|
-
|
|
103
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
104
104
|
self.embedder = embedder
|
|
105
105
|
self.overwrite = overwrite
|
|
106
106
|
self.is_global_level_index = is_global_level_index
|
agno/vectordb/milvus/milvus.py
CHANGED
|
@@ -89,7 +89,7 @@ class Milvus(VectorDb):
|
|
|
89
89
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
90
90
|
|
|
91
91
|
embedder = OpenAIEmbedder()
|
|
92
|
-
|
|
92
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
93
93
|
self.embedder: Embedder = embedder
|
|
94
94
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
95
95
|
|
agno/vectordb/mongodb/mongodb.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import time
|
|
3
|
+
from importlib import metadata
|
|
3
4
|
from typing import Any, Dict, List, Optional, Union
|
|
4
5
|
|
|
5
6
|
from bson import ObjectId
|
|
@@ -20,11 +21,14 @@ except ImportError:
|
|
|
20
21
|
try:
|
|
21
22
|
from pymongo import AsyncMongoClient, MongoClient, errors
|
|
22
23
|
from pymongo.collection import Collection
|
|
24
|
+
from pymongo.driver_info import DriverInfo
|
|
23
25
|
from pymongo.operations import SearchIndexModel
|
|
24
26
|
|
|
25
27
|
except ImportError:
|
|
26
28
|
raise ImportError("`pymongo` not installed. Please install using `pip install pymongo`")
|
|
27
29
|
|
|
30
|
+
DRIVER_METADATA = DriverInfo(name="Agno", version=metadata.version("agno"))
|
|
31
|
+
|
|
28
32
|
|
|
29
33
|
class MongoDb(VectorDb):
|
|
30
34
|
"""
|
|
@@ -110,7 +114,7 @@ class MongoDb(VectorDb):
|
|
|
110
114
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
111
115
|
|
|
112
116
|
embedder = OpenAIEmbedder()
|
|
113
|
-
|
|
117
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
114
118
|
self.embedder = embedder
|
|
115
119
|
|
|
116
120
|
self.distance_metric = distance_metric
|
|
@@ -135,6 +139,11 @@ class MongoDb(VectorDb):
|
|
|
135
139
|
self._async_db = None
|
|
136
140
|
self._async_collection: Optional[Collection] = None
|
|
137
141
|
|
|
142
|
+
if self._client is not None:
|
|
143
|
+
# append_metadata was added in PyMongo 4.14.0, but is a valid database name on earlier versions
|
|
144
|
+
if callable(self._client.append_metadata):
|
|
145
|
+
self._client.append_metadata(DRIVER_METADATA)
|
|
146
|
+
|
|
138
147
|
def _get_client(self) -> MongoClient:
|
|
139
148
|
"""Create or retrieve the MongoDB client."""
|
|
140
149
|
if self._client is None:
|
|
@@ -157,7 +166,7 @@ class MongoDb(VectorDb):
|
|
|
157
166
|
warnings.filterwarnings(
|
|
158
167
|
"ignore", category=UserWarning, message=".*connected to a CosmosDB cluster.*"
|
|
159
168
|
)
|
|
160
|
-
self._client = MongoClient(self.connection_string, **cosmos_kwargs) # type: ignore
|
|
169
|
+
self._client = MongoClient(self.connection_string, **cosmos_kwargs, driver=DRIVER_METADATA) # type: ignore
|
|
161
170
|
|
|
162
171
|
self._client.admin.command("ping")
|
|
163
172
|
|
|
@@ -173,7 +182,7 @@ class MongoDb(VectorDb):
|
|
|
173
182
|
else:
|
|
174
183
|
try:
|
|
175
184
|
log_debug("Creating MongoDB Client")
|
|
176
|
-
self._client = MongoClient(self.connection_string, **self.kwargs)
|
|
185
|
+
self._client = MongoClient(self.connection_string, **self.kwargs, driver=DRIVER_METADATA) # type: ignore
|
|
177
186
|
# Trigger a connection to verify the client
|
|
178
187
|
self._client.admin.command("ping")
|
|
179
188
|
log_info("Connected to MongoDB successfully.")
|
|
@@ -195,6 +204,7 @@ class MongoDb(VectorDb):
|
|
|
195
204
|
maxPoolSize=self.kwargs.get("maxPoolSize", 100),
|
|
196
205
|
retryWrites=self.kwargs.get("retryWrites", True),
|
|
197
206
|
serverSelectionTimeoutMS=5000,
|
|
207
|
+
driver=DRIVER_METADATA,
|
|
198
208
|
)
|
|
199
209
|
# Verify connection
|
|
200
210
|
try:
|
|
@@ -122,7 +122,7 @@ class PgVector(VectorDb):
|
|
|
122
122
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
123
123
|
|
|
124
124
|
embedder = OpenAIEmbedder()
|
|
125
|
-
|
|
125
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
126
126
|
self.embedder: Embedder = embedder
|
|
127
127
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
128
128
|
|
|
@@ -26,7 +26,7 @@ from agno.filters import FilterExpr
|
|
|
26
26
|
from agno.knowledge.document import Document
|
|
27
27
|
from agno.knowledge.embedder import Embedder
|
|
28
28
|
from agno.knowledge.reranker.base import Reranker
|
|
29
|
-
from agno.utils.log import log_debug,
|
|
29
|
+
from agno.utils.log import log_debug, log_warning, logger
|
|
30
30
|
from agno.vectordb.base import VectorDb
|
|
31
31
|
|
|
32
32
|
|
|
@@ -136,7 +136,7 @@ class PineconeDb(VectorDb):
|
|
|
136
136
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
137
137
|
|
|
138
138
|
_embedder = OpenAIEmbedder()
|
|
139
|
-
|
|
139
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
140
140
|
self.embedder: Embedder = _embedder
|
|
141
141
|
self.reranker: Optional[Reranker] = reranker
|
|
142
142
|
|
agno/vectordb/qdrant/qdrant.py
CHANGED
|
@@ -102,7 +102,7 @@ class Qdrant(VectorDb):
|
|
|
102
102
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
103
103
|
|
|
104
104
|
embedder = OpenAIEmbedder()
|
|
105
|
-
|
|
105
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
106
106
|
|
|
107
107
|
self.embedder: Embedder = embedder
|
|
108
108
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
agno/vectordb/redis/redisdb.py
CHANGED
|
@@ -16,7 +16,7 @@ from agno.filters import FilterExpr
|
|
|
16
16
|
from agno.knowledge.document import Document
|
|
17
17
|
from agno.knowledge.embedder import Embedder
|
|
18
18
|
from agno.knowledge.reranker.base import Reranker
|
|
19
|
-
from agno.utils.log import log_debug, log_error,
|
|
19
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
20
20
|
from agno.utils.string import hash_string_sha256
|
|
21
21
|
from agno.vectordb.base import VectorDb
|
|
22
22
|
from agno.vectordb.distance import Distance
|
|
@@ -80,7 +80,7 @@ class RedisDB(VectorDb):
|
|
|
80
80
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
81
81
|
|
|
82
82
|
embedder = OpenAIEmbedder()
|
|
83
|
-
|
|
83
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
84
84
|
|
|
85
85
|
self.embedder: Embedder = embedder
|
|
86
86
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
@@ -56,7 +56,7 @@ class SingleStore(VectorDb):
|
|
|
56
56
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
57
57
|
|
|
58
58
|
embedder = OpenAIEmbedder()
|
|
59
|
-
|
|
59
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
60
60
|
self.embedder: Embedder = embedder
|
|
61
61
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
62
62
|
|
|
@@ -14,7 +14,7 @@ except ImportError as e:
|
|
|
14
14
|
from agno.filters import FilterExpr
|
|
15
15
|
from agno.knowledge.document import Document
|
|
16
16
|
from agno.knowledge.embedder import Embedder
|
|
17
|
-
from agno.utils.log import log_debug, log_error,
|
|
17
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
18
18
|
from agno.vectordb.base import VectorDb
|
|
19
19
|
from agno.vectordb.distance import Distance
|
|
20
20
|
|
|
@@ -135,7 +135,7 @@ class SurrealDb(VectorDb):
|
|
|
135
135
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
136
136
|
|
|
137
137
|
embedder = OpenAIEmbedder()
|
|
138
|
-
|
|
138
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
139
139
|
self.embedder: Embedder = embedder
|
|
140
140
|
self.dimensions = self.embedder.dimensions
|
|
141
141
|
self.collection = collection
|
|
@@ -81,7 +81,7 @@ class Weaviate(VectorDb):
|
|
|
81
81
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
82
82
|
|
|
83
83
|
embedder = OpenAIEmbedder()
|
|
84
|
-
|
|
84
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
85
85
|
self.embedder: Embedder = embedder
|
|
86
86
|
|
|
87
87
|
# Search setup
|
agno/workflow/remote.py
CHANGED
|
@@ -340,7 +340,7 @@ class RemoteWorkflow(BaseRemote):
|
|
|
340
340
|
)
|
|
341
341
|
return map_task_result_to_workflow_run_output(task_result, workflow_id=self.workflow_id, user_id=user_id)
|
|
342
342
|
|
|
343
|
-
async def
|
|
343
|
+
async def acancel_run(self, run_id: str, auth_token: Optional[str] = None) -> bool:
|
|
344
344
|
"""Cancel a running workflow execution.
|
|
345
345
|
|
|
346
346
|
Args:
|
agno/workflow/workflow.py
CHANGED
|
@@ -36,6 +36,9 @@ from agno.models.message import Message
|
|
|
36
36
|
from agno.models.metrics import Metrics
|
|
37
37
|
from agno.run import RunContext, RunStatus
|
|
38
38
|
from agno.run.agent import RunContentEvent, RunEvent, RunOutput
|
|
39
|
+
from agno.run.cancel import (
|
|
40
|
+
acancel_run as acancel_run_global,
|
|
41
|
+
)
|
|
39
42
|
from agno.run.cancel import (
|
|
40
43
|
acleanup_run,
|
|
41
44
|
araise_if_cancelled,
|
|
@@ -3496,6 +3499,17 @@ class Workflow:
|
|
|
3496
3499
|
"""
|
|
3497
3500
|
return cancel_run_global(run_id)
|
|
3498
3501
|
|
|
3502
|
+
async def acancel_run(self, run_id: str) -> bool:
|
|
3503
|
+
"""Cancel a running workflow execution (async version).
|
|
3504
|
+
|
|
3505
|
+
Args:
|
|
3506
|
+
run_id (str): The run_id to cancel.
|
|
3507
|
+
|
|
3508
|
+
Returns:
|
|
3509
|
+
bool: True if the run was found and marked for cancellation, False otherwise.
|
|
3510
|
+
"""
|
|
3511
|
+
return await acancel_run_global(run_id)
|
|
3512
|
+
|
|
3499
3513
|
@overload
|
|
3500
3514
|
def run(
|
|
3501
3515
|
self,
|