agno 2.0.0rc1__py3-none-any.whl → 2.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.
Files changed (85) hide show
  1. agno/agent/agent.py +101 -140
  2. agno/db/mongo/mongo.py +8 -3
  3. agno/eval/accuracy.py +12 -5
  4. agno/knowledge/chunking/strategy.py +14 -14
  5. agno/knowledge/knowledge.py +156 -120
  6. agno/knowledge/reader/arxiv_reader.py +5 -5
  7. agno/knowledge/reader/csv_reader.py +6 -77
  8. agno/knowledge/reader/docx_reader.py +5 -5
  9. agno/knowledge/reader/firecrawl_reader.py +5 -5
  10. agno/knowledge/reader/json_reader.py +5 -5
  11. agno/knowledge/reader/markdown_reader.py +31 -9
  12. agno/knowledge/reader/pdf_reader.py +10 -123
  13. agno/knowledge/reader/reader_factory.py +65 -72
  14. agno/knowledge/reader/s3_reader.py +44 -114
  15. agno/knowledge/reader/text_reader.py +5 -5
  16. agno/knowledge/reader/url_reader.py +75 -31
  17. agno/knowledge/reader/web_search_reader.py +6 -29
  18. agno/knowledge/reader/website_reader.py +5 -5
  19. agno/knowledge/reader/wikipedia_reader.py +5 -5
  20. agno/knowledge/reader/youtube_reader.py +6 -6
  21. agno/knowledge/reranker/__init__.py +9 -0
  22. agno/knowledge/utils.py +10 -10
  23. agno/media.py +269 -268
  24. agno/models/aws/bedrock.py +3 -7
  25. agno/models/base.py +50 -54
  26. agno/models/google/gemini.py +11 -10
  27. agno/models/message.py +4 -4
  28. agno/models/ollama/chat.py +1 -1
  29. agno/models/openai/chat.py +33 -14
  30. agno/models/response.py +5 -5
  31. agno/os/app.py +40 -29
  32. agno/os/mcp.py +39 -59
  33. agno/os/router.py +547 -16
  34. agno/os/routers/evals/evals.py +197 -12
  35. agno/os/routers/knowledge/knowledge.py +428 -14
  36. agno/os/routers/memory/memory.py +250 -28
  37. agno/os/routers/metrics/metrics.py +125 -7
  38. agno/os/routers/session/session.py +393 -25
  39. agno/os/schema.py +55 -2
  40. agno/run/agent.py +37 -28
  41. agno/run/base.py +9 -19
  42. agno/run/team.py +110 -19
  43. agno/run/workflow.py +41 -28
  44. agno/team/team.py +808 -1080
  45. agno/tools/brightdata.py +3 -3
  46. agno/tools/cartesia.py +3 -5
  47. agno/tools/dalle.py +7 -4
  48. agno/tools/desi_vocal.py +2 -2
  49. agno/tools/e2b.py +6 -6
  50. agno/tools/eleven_labs.py +3 -3
  51. agno/tools/fal.py +4 -4
  52. agno/tools/function.py +7 -7
  53. agno/tools/giphy.py +2 -2
  54. agno/tools/lumalab.py +3 -3
  55. agno/tools/mcp.py +1 -2
  56. agno/tools/models/azure_openai.py +2 -2
  57. agno/tools/models/gemini.py +3 -3
  58. agno/tools/models/groq.py +3 -5
  59. agno/tools/models/nebius.py +2 -2
  60. agno/tools/models_labs.py +5 -5
  61. agno/tools/openai.py +4 -9
  62. agno/tools/opencv.py +3 -3
  63. agno/tools/replicate.py +7 -7
  64. agno/utils/events.py +5 -5
  65. agno/utils/gemini.py +1 -1
  66. agno/utils/log.py +52 -2
  67. agno/utils/mcp.py +57 -5
  68. agno/utils/models/aws_claude.py +1 -1
  69. agno/utils/models/claude.py +0 -8
  70. agno/utils/models/cohere.py +1 -1
  71. agno/utils/models/watsonx.py +1 -1
  72. agno/utils/openai.py +1 -1
  73. agno/utils/print_response/team.py +177 -73
  74. agno/utils/streamlit.py +27 -0
  75. agno/vectordb/lancedb/lance_db.py +82 -25
  76. agno/workflow/step.py +7 -7
  77. agno/workflow/types.py +13 -13
  78. agno/workflow/workflow.py +37 -28
  79. {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/METADATA +140 -1
  80. {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/RECORD +83 -84
  81. agno-2.0.1.dist-info/licenses/LICENSE +201 -0
  82. agno/knowledge/reader/gcs_reader.py +0 -67
  83. agno-2.0.0rc1.dist-info/licenses/LICENSE +0 -375
  84. {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/WHEEL +0 -0
  85. {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/top_level.txt +0 -0
@@ -21,11 +21,11 @@ class TextReader(Reader):
21
21
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
22
22
  """Get the list of supported chunking strategies for Text readers."""
23
23
  return [
24
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
25
- ChunkingStrategyType.AGENTIC_CHUNKING,
26
- ChunkingStrategyType.DOCUMENT_CHUNKING,
27
- ChunkingStrategyType.RECURSIVE_CHUNKING,
28
- ChunkingStrategyType.SEMANTIC_CHUNKING,
24
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
25
+ ChunkingStrategyType.AGENTIC_CHUNKER,
26
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
27
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
28
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
29
29
  ]
30
30
 
31
31
  @classmethod
@@ -1,3 +1,6 @@
1
+ from io import BytesIO
2
+ from os.path import basename
3
+ from pathlib import Path
1
4
  from typing import List, Optional
2
5
  from urllib.parse import urlparse
3
6
 
@@ -7,6 +10,8 @@ from agno.knowledge.chunking.fixed import FixedSizeChunking
7
10
  from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
8
11
  from agno.knowledge.document.base import Document
9
12
  from agno.knowledge.reader.base import Reader
13
+ from agno.knowledge.reader.csv_reader import CSVReader
14
+ from agno.knowledge.reader.pdf_reader import PDFReader
10
15
  from agno.knowledge.types import ContentType
11
16
  from agno.utils.http import async_fetch_with_retry, fetch_with_retry
12
17
  from agno.utils.log import log_debug
@@ -25,31 +30,43 @@ class URLReader(Reader):
25
30
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
26
31
  """Get the list of supported chunking strategies for URL readers."""
27
32
  return [
28
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
29
- ChunkingStrategyType.AGENTIC_CHUNKING,
30
- ChunkingStrategyType.DOCUMENT_CHUNKING,
31
- ChunkingStrategyType.RECURSIVE_CHUNKING,
32
- ChunkingStrategyType.SEMANTIC_CHUNKING,
33
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
34
+ ChunkingStrategyType.AGENTIC_CHUNKER,
35
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
36
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
37
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
33
38
  ]
34
39
 
35
40
  @classmethod
36
41
  def get_supported_content_types(self) -> List[ContentType]:
37
42
  return [ContentType.URL]
38
43
 
39
- def read(self, url: str, id: Optional[str] = None, name: Optional[str] = None) -> List[Document]:
44
+ def read(
45
+ self, url: str, id: Optional[str] = None, name: Optional[str] = None, password: Optional[str] = None
46
+ ) -> List[Document]:
40
47
  if not url:
41
48
  raise ValueError("No url provided")
42
49
 
43
50
  log_debug(f"Reading: {url}")
51
+
44
52
  # Retry the request up to 3 times with exponential backoff
45
53
  response = fetch_with_retry(url, proxy=self.proxy)
46
54
 
47
- document = self._create_document(url, response.text, id, name)
48
- if self.chunk:
49
- return self.chunk_document(document)
50
- return [document]
55
+ documents = self._create_documents(
56
+ url=url, text=response.text, content=response.content, id=id, name=name, password=password
57
+ )
58
+
59
+ if not self.chunk:
60
+ return documents
61
+
62
+ chunked_documents = []
63
+ for document in documents:
64
+ chunked_documents.append(self.chunk_document(document))
65
+ return [doc for sublist in chunked_documents for doc in sublist]
51
66
 
52
- async def async_read(self, url: str, id: Optional[str] = None, name: Optional[str] = None) -> List[Document]:
67
+ async def async_read(
68
+ self, url: str, id: Optional[str] = None, name: Optional[str] = None, password: Optional[str] = None
69
+ ) -> List[Document]:
53
70
  """Async version of read method"""
54
71
  if not url:
55
72
  raise ValueError("No url provided")
@@ -59,26 +76,53 @@ class URLReader(Reader):
59
76
  async with httpx.AsyncClient(**client_args) as client: # type: ignore
60
77
  response = await async_fetch_with_retry(url, client=client)
61
78
 
62
- document = self._create_document(url, response.text, id, name)
63
- if self.chunk:
64
- return await self.chunk_documents_async([document])
65
- return [document]
79
+ documents = self._create_documents(
80
+ url=url, text=response.text, content=response.content, id=id, name=name, password=password
81
+ )
82
+
83
+ if not self.chunk:
84
+ return documents
85
+
86
+ return await self.chunk_documents_async(documents)
66
87
 
67
- def _create_document(
68
- self, url: str, content: str, id: Optional[str] = None, name: Optional[str] = None
69
- ) -> Document:
88
+ def _create_documents(
89
+ self,
90
+ url: str,
91
+ text: str,
92
+ content: bytes,
93
+ id: Optional[str] = None,
94
+ name: Optional[str] = None,
95
+ password: Optional[str] = None,
96
+ ) -> List[Document]:
70
97
  """Helper method to create a document from URL content"""
98
+
99
+ # Determine file extension from URL
71
100
  parsed_url = urlparse(url)
72
- doc_name = name or parsed_url.path.strip("/").replace("/", "_").replace(" ", "_")
73
- if not doc_name:
74
- doc_name = parsed_url.netloc
75
- if not doc_name:
76
- doc_name = url
77
-
78
- return Document(
79
- name=doc_name,
80
- id=id or doc_name,
81
- meta_data={"url": url},
82
- content=content,
83
- size=len(content),
84
- )
101
+ url_path = Path(parsed_url.path) # type: ignore
102
+ file_extension = url_path.suffix.lower()
103
+
104
+ # Read the document using the appropriate reader
105
+ if file_extension == ".csv":
106
+ filename = basename(parsed_url.path) or "data.csv"
107
+ return CSVReader().read(file=BytesIO(content), name=filename)
108
+ elif file_extension == ".pdf":
109
+ if password:
110
+ return PDFReader().read(pdf=BytesIO(content), name=name, password=password)
111
+ else:
112
+ return PDFReader().read(pdf=BytesIO(content), name=name)
113
+ else:
114
+ doc_name = name or parsed_url.path.strip("/").replace("/", "_").replace(" ", "_")
115
+ if not doc_name:
116
+ doc_name = parsed_url.netloc
117
+ if not doc_name:
118
+ doc_name = url
119
+
120
+ return [
121
+ Document(
122
+ name=doc_name,
123
+ id=id or doc_name,
124
+ meta_data={"url": url},
125
+ content=text,
126
+ size=len(text),
127
+ )
128
+ ]
@@ -11,7 +11,6 @@ from agno.knowledge.chunking.semantic import SemanticChunking
11
11
  from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
12
12
  from agno.knowledge.document.base import Document
13
13
  from agno.knowledge.reader.base import Reader
14
- from agno.knowledge.reader.url_reader import URLReader
15
14
  from agno.knowledge.types import ContentType
16
15
  from agno.utils.log import log_debug, logger
17
16
 
@@ -48,30 +47,25 @@ class WebSearchReader(Reader):
48
47
 
49
48
  # Internal state
50
49
  _visited_urls: Set[str] = field(default_factory=set)
51
- _url_reader: Optional[URLReader] = None
52
50
  _last_search_time: float = field(default=0.0, init=False)
53
51
 
54
52
  # Override default chunking strategy
55
53
  chunking_strategy: Optional[ChunkingStrategy] = SemanticChunking()
56
54
 
57
- def __post_init__(self):
58
- """Initialize the URL reader and chunking strategy after dataclass initialization"""
59
- self._url_reader = URLReader()
60
-
61
55
  @classmethod
62
56
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
63
57
  """Get the list of supported chunking strategies for Web Search readers."""
64
58
  return [
65
- ChunkingStrategyType.AGENTIC_CHUNKING,
66
- ChunkingStrategyType.DOCUMENT_CHUNKING,
67
- ChunkingStrategyType.RECURSIVE_CHUNKING,
68
- ChunkingStrategyType.SEMANTIC_CHUNKING,
69
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
59
+ ChunkingStrategyType.AGENTIC_CHUNKER,
60
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
61
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
62
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
63
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
70
64
  ]
71
65
 
72
66
  @classmethod
73
67
  def get_supported_content_types(self) -> List[ContentType]:
74
- return [ContentType.URL, ContentType.TEXT]
68
+ return [ContentType.TOPIC]
75
69
 
76
70
  def _respect_rate_limits(self):
77
71
  """Ensure we don't exceed rate limits"""
@@ -328,23 +322,6 @@ class WebSearchReader(Reader):
328
322
  self._visited_urls.add(url)
329
323
 
330
324
  try:
331
- # Use the URL reader for async fetching
332
- if self._url_reader:
333
- docs = await self._url_reader.async_read(url)
334
- if docs:
335
- # Use the first document and add search metadata
336
- doc = docs[0]
337
- doc.meta_data.update(
338
- {
339
- "search_title": result.get("title", ""),
340
- "search_description": result.get("description", ""),
341
- "source": "web_search",
342
- "search_engine": self.search_engine,
343
- }
344
- )
345
- return doc
346
-
347
- # Fallback to manual async fetching
348
325
  headers = {"User-Agent": self.user_agent}
349
326
  async with httpx.AsyncClient(timeout=self.request_timeout) as client:
350
327
  response = await client.get(url, headers=headers, follow_redirects=True)
@@ -52,11 +52,11 @@ class WebsiteReader(Reader):
52
52
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
53
53
  """Get the list of supported chunking strategies for Website readers."""
54
54
  return [
55
- ChunkingStrategyType.AGENTIC_CHUNKING,
56
- ChunkingStrategyType.DOCUMENT_CHUNKING,
57
- ChunkingStrategyType.RECURSIVE_CHUNKING,
58
- ChunkingStrategyType.SEMANTIC_CHUNKING,
59
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
55
+ ChunkingStrategyType.AGENTIC_CHUNKER,
56
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
57
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
58
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
59
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
60
60
  ]
61
61
 
62
62
  @classmethod
@@ -26,11 +26,11 @@ class WikipediaReader(Reader):
26
26
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
27
27
  """Get the list of supported chunking strategies for Wikipedia readers."""
28
28
  return [
29
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
30
- ChunkingStrategyType.AGENTIC_CHUNKING,
31
- ChunkingStrategyType.DOCUMENT_CHUNKING,
32
- ChunkingStrategyType.RECURSIVE_CHUNKING,
33
- ChunkingStrategyType.SEMANTIC_CHUNKING,
29
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
30
+ ChunkingStrategyType.AGENTIC_CHUNKER,
31
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
32
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
33
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
34
34
  ]
35
35
 
36
36
  @classmethod
@@ -26,16 +26,16 @@ class YouTubeReader(Reader):
26
26
  def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
27
27
  """Get the list of supported chunking strategies for YouTube readers."""
28
28
  return [
29
- ChunkingStrategyType.RECURSIVE_CHUNKING,
30
- ChunkingStrategyType.AGENTIC_CHUNKING,
31
- ChunkingStrategyType.DOCUMENT_CHUNKING,
32
- ChunkingStrategyType.SEMANTIC_CHUNKING,
33
- ChunkingStrategyType.FIXED_SIZE_CHUNKING,
29
+ ChunkingStrategyType.RECURSIVE_CHUNKER,
30
+ ChunkingStrategyType.AGENTIC_CHUNKER,
31
+ ChunkingStrategyType.DOCUMENT_CHUNKER,
32
+ ChunkingStrategyType.SEMANTIC_CHUNKER,
33
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER,
34
34
  ]
35
35
 
36
36
  @classmethod
37
37
  def get_supported_content_types(self) -> List[ContentType]:
38
- return [ContentType.URL, ContentType.YOUTUBE]
38
+ return [ContentType.YOUTUBE]
39
39
 
40
40
  def read(self, url: str, name: Optional[str] = None) -> List[Document]:
41
41
  try:
@@ -0,0 +1,9 @@
1
+ from agno.knowledge.reranker.cohere import CohereReranker
2
+ from agno.knowledge.reranker.infinity import InfinityReranker
3
+ from agno.knowledge.reranker.sentence_transformer import SentenceTransformerReranker
4
+
5
+ __all__ = [
6
+ "CohereReranker",
7
+ "InfinityReranker",
8
+ "SentenceTransformerReranker",
9
+ ]
agno/knowledge/utils.py CHANGED
@@ -11,23 +11,23 @@ def _get_chunker_class(strategy_type):
11
11
 
12
12
  # Map strategy types to their corresponding classes
13
13
  strategy_class_mapping = {
14
- ChunkingStrategyType.AGENTIC_CHUNKING: lambda: _import_class(
14
+ ChunkingStrategyType.AGENTIC_CHUNKER: lambda: _import_class(
15
15
  "agno.knowledge.chunking.agentic", "AgenticChunking"
16
16
  ),
17
- ChunkingStrategyType.DOCUMENT_CHUNKING: lambda: _import_class(
17
+ ChunkingStrategyType.DOCUMENT_CHUNKER: lambda: _import_class(
18
18
  "agno.knowledge.chunking.document", "DocumentChunking"
19
19
  ),
20
- ChunkingStrategyType.RECURSIVE_CHUNKING: lambda: _import_class(
20
+ ChunkingStrategyType.RECURSIVE_CHUNKER: lambda: _import_class(
21
21
  "agno.knowledge.chunking.recursive", "RecursiveChunking"
22
22
  ),
23
- ChunkingStrategyType.SEMANTIC_CHUNKING: lambda: _import_class(
23
+ ChunkingStrategyType.SEMANTIC_CHUNKER: lambda: _import_class(
24
24
  "agno.knowledge.chunking.semantic", "SemanticChunking"
25
25
  ),
26
- ChunkingStrategyType.FIXED_SIZE_CHUNKING: lambda: _import_class(
26
+ ChunkingStrategyType.FIXED_SIZE_CHUNKER: lambda: _import_class(
27
27
  "agno.knowledge.chunking.fixed", "FixedSizeChunking"
28
28
  ),
29
- ChunkingStrategyType.ROW_CHUNKING: lambda: _import_class("agno.knowledge.chunking.row", "RowChunking"),
30
- ChunkingStrategyType.MARKDOWN_CHUNKING: lambda: _import_class(
29
+ ChunkingStrategyType.ROW_CHUNKER: lambda: _import_class("agno.knowledge.chunking.row", "RowChunking"),
30
+ ChunkingStrategyType.MARKDOWN_CHUNKER: lambda: _import_class(
31
31
  "agno.knowledge.chunking.markdown", "MarkdownChunking"
32
32
  ),
33
33
  }
@@ -61,8 +61,8 @@ def get_reader_info(reader_key: str) -> Dict:
61
61
 
62
62
  return {
63
63
  "id": reader_key,
64
- "name": reader_key.replace("_", " ").title() + " Reader",
65
- "description": f"Reads {reader_key} files",
64
+ "name": "".join(word.capitalize() for word in reader_key.split("_")) + "Reader",
65
+ "description": reader_instance.description,
66
66
  "chunking_strategies": [
67
67
  strategy.value for strategy in supported_strategies
68
68
  ], # Convert enums to string values
@@ -132,7 +132,7 @@ def get_chunker_info(chunker_key: str) -> Dict:
132
132
  return {
133
133
  "key": chunker_key,
134
134
  "class_name": class_name,
135
- "name": class_name.replace("Chunking", "").replace("Strategy", ""),
135
+ "name": chunker_key,
136
136
  "description": docstring.strip(),
137
137
  "strategy_type": strategy_type.value,
138
138
  }