agno 2.3.23__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.
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional, Union
5
5
 
6
6
  from fastapi import APIRouter, BackgroundTasks, Depends, File, Form, HTTPException, Path, Query, Request, UploadFile
7
7
 
8
+ from agno.db.base import AsyncBaseDb
8
9
  from agno.knowledge.content import Content, FileData
9
10
  from agno.knowledge.knowledge import Knowledge
10
11
  from agno.knowledge.reader import ReaderFactory
@@ -36,7 +37,7 @@ from agno.os.schema import (
36
37
  from agno.os.settings import AgnoAPISettings
37
38
  from agno.os.utils import get_knowledge_instance_by_db_id
38
39
  from agno.remote.base import RemoteKnowledge
39
- from agno.utils.log import log_debug, log_info
40
+ from agno.utils.log import log_debug, log_error, log_info
40
41
  from agno.utils.string import generate_id
41
42
 
42
43
  logger = logging.getLogger(__name__)
@@ -297,7 +298,17 @@ def attach_routes(router: APIRouter, knowledge_instances: List[Union[Knowledge,
297
298
  else:
298
299
  raise HTTPException(status_code=400, detail=f"Invalid reader_id: {update_data.reader_id}")
299
300
 
300
- updated_content_dict = await knowledge.apatch_content(content)
301
+ # Use async patch method if contents_db is an AsyncBaseDb, otherwise use sync patch method
302
+ updated_content_dict = None
303
+ try:
304
+ if knowledge.contents_db is not None and isinstance(knowledge.contents_db, AsyncBaseDb):
305
+ updated_content_dict = await knowledge.apatch_content(content)
306
+ else:
307
+ updated_content_dict = knowledge.patch_content(content)
308
+ except Exception as e:
309
+ log_error(f"Error updating content: {str(e)}")
310
+ raise HTTPException(status_code=500, detail=f"Error updating content: {str(e)}")
311
+
301
312
  if not updated_content_dict:
302
313
  raise HTTPException(status_code=404, detail=f"Content not found: {content_id}")
303
314
 
@@ -1090,7 +1101,12 @@ async def process_content(
1090
1101
 
1091
1102
  content.status = KnowledgeContentStatus.FAILED
1092
1103
  content.status_message = str(e)
1093
- knowledge.patch_content(content)
1104
+ # Use async patch method if contents_db is an AsyncBaseDb, otherwise use sync patch method
1105
+ if knowledge.contents_db is not None and isinstance(knowledge.contents_db, AsyncBaseDb):
1106
+ await knowledge.apatch_content(content)
1107
+ else:
1108
+ knowledge.patch_content(content)
1109
+
1094
1110
  except Exception:
1095
1111
  # Swallow any secondary errors to avoid crashing the background task
1096
1112
  pass
agno/os/utils.py CHANGED
@@ -343,7 +343,7 @@ def get_session_name(session: Dict[str, Any]) -> str:
343
343
 
344
344
  run_input = r.get("input")
345
345
  if run_input is not None:
346
- return run_input.get("input_content")
346
+ return stringify_input_content(run_input)
347
347
 
348
348
  return ""
349
349
 
agno/team/team.py CHANGED
@@ -1569,6 +1569,7 @@ class Team:
1569
1569
  tools=_tools,
1570
1570
  tool_choice=self.tool_choice,
1571
1571
  tool_call_limit=self.tool_call_limit,
1572
+ run_response=run_response,
1572
1573
  send_media_to_model=self.send_media_to_model,
1573
1574
  compression_manager=self.compression_manager if self.compress_tool_results else None,
1574
1575
  )
@@ -3392,6 +3393,7 @@ class Team:
3392
3393
  tool_choice=self.tool_choice,
3393
3394
  tool_call_limit=self.tool_call_limit,
3394
3395
  stream_model_response=stream_model_response,
3396
+ run_response=run_response,
3395
3397
  send_media_to_model=self.send_media_to_model,
3396
3398
  compression_manager=self.compression_manager if self.compress_tool_results else None,
3397
3399
  ):
@@ -8447,7 +8449,7 @@ class Team:
8447
8449
  gen_session_name_prompt = "Team Conversation\n"
8448
8450
 
8449
8451
  # Get team session messages for generating the name
8450
- messages_for_generating_session_name = self.get_session_messages()
8452
+ messages_for_generating_session_name = session.get_messages()
8451
8453
 
8452
8454
  for message in messages_for_generating_session_name:
8453
8455
  gen_session_name_prompt += f"{message.role.upper()}: {message.content}\n"
@@ -8997,7 +8999,7 @@ class Team:
8997
8999
  log_warning("No valid filters remain after validation. Search will proceed without filters.")
8998
9000
 
8999
9001
  if invalid_keys == [] and valid_filters == {}:
9000
- log_warning("No valid filters provided. Search will proceed without filters.")
9002
+ log_debug("No valid filters provided. Search will proceed without filters.")
9001
9003
  filters = None
9002
9004
 
9003
9005
  if self.knowledge_retriever is not None and callable(self.knowledge_retriever):
@@ -9073,7 +9075,7 @@ class Team:
9073
9075
  log_warning("No valid filters remain after validation. Search will proceed without filters.")
9074
9076
 
9075
9077
  if invalid_keys == [] and valid_filters == {}:
9076
- log_warning("No valid filters provided. Search will proceed without filters.")
9078
+ log_debug("No valid filters provided. Search will proceed without filters.")
9077
9079
  filters = None
9078
9080
 
9079
9081
  if self.knowledge_retriever is not None and callable(self.knowledge_retriever):
agno/tools/crawl4ai.py CHANGED
@@ -20,6 +20,7 @@ class Crawl4aiTools(Toolkit):
20
20
  bm25_threshold: float = 1.0,
21
21
  headless: bool = True,
22
22
  wait_until: str = "domcontentloaded",
23
+ proxy_config: Optional[Dict[str, Any]] = None,
23
24
  enable_crawl: bool = True,
24
25
  all: bool = False,
25
26
  **kwargs,
@@ -36,6 +37,7 @@ class Crawl4aiTools(Toolkit):
36
37
  self.bm25_threshold = bm25_threshold
37
38
  self.wait_until = wait_until
38
39
  self.headless = headless
40
+ self.proxy_config = proxy_config or {}
39
41
 
40
42
  def _build_config(self, search_query: Optional[str] = None) -> Dict[str, Any]:
41
43
  """Build CrawlerRunConfig parameters from toolkit settings."""
@@ -103,6 +105,7 @@ class Crawl4aiTools(Toolkit):
103
105
  browser_config = BrowserConfig(
104
106
  headless=self.headless,
105
107
  verbose=False,
108
+ **self.proxy_config,
106
109
  )
107
110
 
108
111
  async with AsyncWebCrawler(config=browser_config) as crawler:
agno/tools/file.py CHANGED
@@ -24,8 +24,7 @@ class FileTools(Toolkit):
24
24
  all: bool = False,
25
25
  **kwargs,
26
26
  ):
27
- self.base_dir: Path = base_dir or Path.cwd()
28
- self.base_dir = self.base_dir.resolve()
27
+ self.base_dir: Path = (base_dir or Path.cwd()).resolve()
29
28
 
30
29
  tools: List[Any] = []
31
30
  self.max_file_length = max_file_length
@@ -49,6 +48,19 @@ class FileTools(Toolkit):
49
48
 
50
49
  super().__init__(name="file_tools", tools=tools, **kwargs)
51
50
 
51
+ def check_escape(self, relative_path: str) -> Tuple[bool, Path]:
52
+ """Check if the file path is within the base directory.
53
+
54
+ Alias for _check_path maintained for backward compatibility.
55
+
56
+ Args:
57
+ relative_path: The file name or relative path to check.
58
+
59
+ Returns:
60
+ Tuple of (is_safe, resolved_path). If not safe, returns base_dir as the path.
61
+ """
62
+ return self._check_path(relative_path, self.base_dir)
63
+
52
64
  def save_file(self, contents: str, file_name: str, overwrite: bool = True, encoding: str = "utf-8") -> str:
53
65
  """Saves the contents to a file called `file_name` and returns the file name if successful.
54
66
 
@@ -173,17 +185,6 @@ class FileTools(Toolkit):
173
185
  log_error(f"Error removing {file_name}: {e}")
174
186
  return f"Error removing file: {e}"
175
187
 
176
- def check_escape(self, relative_path: str) -> Tuple[bool, Path]:
177
- d = self.base_dir.joinpath(Path(relative_path)).resolve()
178
- if self.base_dir == d:
179
- return True, d
180
- try:
181
- d.relative_to(self.base_dir)
182
- except ValueError:
183
- log_error("Attempted to escape base_dir")
184
- return False, self.base_dir
185
- return True, d
186
-
187
188
  def list_files(self, **kwargs) -> str:
188
189
  """Returns a list of files in directory
189
190
  :param directory: (Optional) name of directory to list.
agno/tools/function.py CHANGED
@@ -54,9 +54,17 @@ class UserInputField:
54
54
 
55
55
  @classmethod
56
56
  def from_dict(cls, data: Dict[str, Any]) -> "UserInputField":
57
+ type_mapping = {"str": str, "int": int, "float": float, "bool": bool, "list": list, "dict": dict}
58
+ field_type_raw = data["field_type"]
59
+ if isinstance(field_type_raw, str):
60
+ field_type = type_mapping.get(field_type_raw, str)
61
+ elif isinstance(field_type_raw, type):
62
+ field_type = field_type_raw
63
+ else:
64
+ field_type = str
57
65
  return cls(
58
66
  name=data["name"],
59
- field_type=eval(data["field_type"]), # Convert string type name to actual type
67
+ field_type=field_type,
60
68
  description=data["description"],
61
69
  value=data["value"],
62
70
  )
@@ -17,7 +17,7 @@ provides high-quality transcription capabilities.
17
17
 
18
18
  import json
19
19
  from pathlib import Path
20
- from typing import Any, Dict, List, Optional, Tuple, Union
20
+ from typing import Any, Dict, List, Optional, Union
21
21
 
22
22
  from agno.tools import Toolkit
23
23
  from agno.utils.log import log_info, logger
@@ -33,9 +33,10 @@ class MLXTranscribeTools(Toolkit):
33
33
  self,
34
34
  base_dir: Optional[Path] = None,
35
35
  enable_read_files_in_base_dir: bool = True,
36
+ restrict_to_base_dir: bool = True,
36
37
  path_or_hf_repo: str = "mlx-community/whisper-large-v3-turbo",
37
38
  verbose: Optional[bool] = None,
38
- temperature: Optional[Union[float, Tuple[float, ...]]] = None,
39
+ temperature: Optional[Union[float, tuple[float, ...]]] = None,
39
40
  compression_ratio_threshold: Optional[float] = None,
40
41
  logprob_threshold: Optional[float] = None,
41
42
  no_speech_threshold: Optional[float] = None,
@@ -50,10 +51,11 @@ class MLXTranscribeTools(Toolkit):
50
51
  all: bool = False,
51
52
  **kwargs,
52
53
  ):
53
- self.base_dir: Path = base_dir or Path.cwd()
54
+ self.base_dir: Path = (base_dir or Path.cwd()).resolve()
55
+ self.restrict_to_base_dir = restrict_to_base_dir
54
56
  self.path_or_hf_repo: str = path_or_hf_repo
55
57
  self.verbose: Optional[bool] = verbose
56
- self.temperature: Optional[Union[float, Tuple[float, ...]]] = temperature
58
+ self.temperature: Optional[Union[float, tuple[float, ...]]] = temperature
57
59
  self.compression_ratio_threshold: Optional[float] = compression_ratio_threshold
58
60
  self.logprob_threshold: Optional[float] = logprob_threshold
59
61
  self.no_speech_threshold: Optional[float] = no_speech_threshold
@@ -83,9 +85,10 @@ class MLXTranscribeTools(Toolkit):
83
85
  str: The transcribed text or an error message if the transcription fails.
84
86
  """
85
87
  try:
86
- audio_file_path = str(self.base_dir.joinpath(file_name))
87
- if audio_file_path is None:
88
- return "No audio file path provided"
88
+ safe, file_path = self._check_path(file_name, self.base_dir, self.restrict_to_base_dir)
89
+ if not safe:
90
+ return f"Error: Path '{file_name}' is outside the allowed base directory"
91
+ audio_file_path = str(file_path)
89
92
 
90
93
  log_info(f"Transcribing audio file {audio_file_path}")
91
94
  transcription_kwargs: Dict[str, Any] = {
agno/tools/python.py CHANGED
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from typing import Any, List, Optional
5
5
 
6
6
  from agno.tools import Toolkit
7
- from agno.utils.log import log_debug, log_info, logger
7
+ from agno.utils.log import log_debug, log_error, log_info, logger
8
8
 
9
9
 
10
10
  @functools.lru_cache(maxsize=None)
@@ -18,9 +18,11 @@ class PythonTools(Toolkit):
18
18
  base_dir: Optional[Path] = None,
19
19
  safe_globals: Optional[dict] = None,
20
20
  safe_locals: Optional[dict] = None,
21
+ restrict_to_base_dir: bool = True,
21
22
  **kwargs,
22
23
  ):
23
- self.base_dir: Path = base_dir or Path.cwd()
24
+ self.base_dir: Path = (base_dir or Path.cwd()).resolve()
25
+ self.restrict_to_base_dir = restrict_to_base_dir
24
26
 
25
27
  # Restricted global and local scope
26
28
  self.safe_globals: dict = safe_globals or globals()
@@ -55,7 +57,9 @@ class PythonTools(Toolkit):
55
57
  """
56
58
  try:
57
59
  warn()
58
- file_path = self.base_dir.joinpath(file_name)
60
+ safe, file_path = self._check_path(file_name, self.base_dir, self.restrict_to_base_dir)
61
+ if not safe:
62
+ return f"Error: Path '{file_name}' is outside the allowed base directory"
59
63
  log_debug(f"Saving code to {file_path}")
60
64
  if not file_path.parent.exists():
61
65
  file_path.parent.mkdir(parents=True, exist_ok=True)
@@ -89,8 +93,9 @@ class PythonTools(Toolkit):
89
93
  """
90
94
  try:
91
95
  warn()
92
- file_path = self.base_dir.joinpath(file_name)
93
-
96
+ safe, file_path = self._check_path(file_name, self.base_dir, self.restrict_to_base_dir)
97
+ if not safe:
98
+ return f"Error: Path '{file_name}' is outside the allowed base directory"
94
99
  log_info(f"Running {file_path}")
95
100
  globals_after_run = runpy.run_path(str(file_path), init_globals=self.safe_globals, run_name="__main__")
96
101
  if variable_to_return:
@@ -113,7 +118,10 @@ class PythonTools(Toolkit):
113
118
  """
114
119
  try:
115
120
  log_info(f"Reading file: {file_name}")
116
- file_path = self.base_dir.joinpath(file_name)
121
+ safe, file_path = self._check_path(file_name, self.base_dir, self.restrict_to_base_dir)
122
+ if not safe:
123
+ log_error(f"Attempted to read file outside base directory: {file_name}")
124
+ return "Error reading file: path outside allowed directory"
117
125
  contents = file_path.read_text(encoding="utf-8")
118
126
  return str(contents)
119
127
  except Exception as e:
agno/tools/toolkit.py CHANGED
@@ -1,9 +1,10 @@
1
1
  from collections import OrderedDict
2
2
  from inspect import iscoroutinefunction
3
- from typing import Any, Callable, Dict, List, Optional, Sequence, Union
3
+ from pathlib import Path
4
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
4
5
 
5
6
  from agno.tools.function import Function
6
- from agno.utils.log import log_debug, log_warning, logger
7
+ from agno.utils.log import log_debug, log_error, log_warning, logger
7
8
 
8
9
 
9
10
  class Toolkit:
@@ -343,6 +344,36 @@ class Toolkit:
343
344
  """
344
345
  pass
345
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
+
346
377
  def __repr__(self):
347
378
  return f"<{self.__class__.__name__} name={self.name} functions={list(self.functions.keys())}>"
348
379
 
@@ -32,7 +32,7 @@ class Cassandra(VectorDb):
32
32
  from agno.knowledge.embedder.openai import OpenAIEmbedder
33
33
 
34
34
  embedder = OpenAIEmbedder()
35
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
 
@@ -117,7 +117,7 @@ class ChromaDb(VectorDb):
117
117
  from agno.knowledge.embedder.openai import OpenAIEmbedder
118
118
 
119
119
  embedder = OpenAIEmbedder()
120
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
@@ -89,7 +89,7 @@ class Milvus(VectorDb):
89
89
  from agno.knowledge.embedder.openai import OpenAIEmbedder
90
90
 
91
91
  embedder = OpenAIEmbedder()
92
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
 
@@ -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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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, log_info, log_warning, logger
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
 
@@ -102,7 +102,7 @@ class Qdrant(VectorDb):
102
102
  from agno.knowledge.embedder.openai import OpenAIEmbedder
103
103
 
104
104
  embedder = OpenAIEmbedder()
105
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
@@ -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, log_info, log_warning
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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, log_info, log_warning
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
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
- log_info("Embedder not provided, using OpenAIEmbedder as default.")
84
+ log_debug("Embedder not provided, using OpenAIEmbedder as default.")
85
85
  self.embedder: Embedder = embedder
86
86
 
87
87
  # Search setup
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 2.3.23
3
+ Version: 2.3.24
4
4
  Summary: Agno: a lightweight library for building Multi-Agent Systems
5
5
  Author-email: Ashpreet Bedi <ashpreet@agno.com>
6
6
  Project-URL: homepage, https://agno.com