agno 1.8.1__py3-none-any.whl → 2.0.0a1__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 (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +38 -144
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +84 -46
  158. agno/models/openai/chat.py +121 -23
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +14 -8
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +393 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +65 -28
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +33 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  184. agno/os/router.py +843 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +204 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +413 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +179 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +58 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +2961 -4253
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +42 -22
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +18 -13
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,7 @@
1
+ from agno.knowledge.reader.base import Reader
2
+ from agno.knowledge.reader.reader_factory import ReaderFactory
3
+
4
+ __all__ = [
5
+ "Reader",
6
+ "ReaderFactory",
7
+ ]
@@ -1,8 +1,11 @@
1
1
  import asyncio
2
- from typing import List
2
+ from typing import List, Optional
3
3
 
4
- from agno.document.base import Document
5
- from agno.document.reader.base import Reader
4
+ from agno.knowledge.chunking.fixed import FixedSizeChunking
5
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
6
+ from agno.knowledge.document.base import Document
7
+ from agno.knowledge.reader.base import Reader
8
+ from agno.knowledge.types import ContentType
6
9
 
7
10
  try:
8
11
  import arxiv # noqa: F401
@@ -11,9 +14,34 @@ except ImportError:
11
14
 
12
15
 
13
16
  class ArxivReader(Reader):
14
- max_results: int = 5 # Top articles
15
17
  sort_by: arxiv.SortCriterion = arxiv.SortCriterion.Relevance
16
18
 
19
+ @classmethod
20
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
21
+ """Get the list of supported chunking strategies for Arxiv readers."""
22
+ return [
23
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
24
+ ChunkingStrategyType.AGENTIC_CHUNKING,
25
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
26
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
27
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
28
+ ]
29
+
30
+ @classmethod
31
+ def get_supported_content_types(self) -> List[ContentType]:
32
+ return [ContentType.TOPIC]
33
+
34
+ def __init__(
35
+ self,
36
+ chunking_strategy: Optional[ChunkingStrategy] = FixedSizeChunking(),
37
+ sort_by: arxiv.SortCriterion = arxiv.SortCriterion.Relevance,
38
+ **kwargs,
39
+ ) -> None:
40
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
41
+
42
+ # ArxivReader-specific attributes
43
+ self.sort_by = sort_by
44
+
17
45
  def read(self, query: str) -> List[Document]:
18
46
  """
19
47
  Search a query from arXiv database
@@ -0,0 +1,88 @@
1
+ import asyncio
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, List, Optional
4
+
5
+ from agno.knowledge.chunking.fixed import FixedSizeChunking
6
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyFactory, ChunkingStrategyType
7
+ from agno.knowledge.document.base import Document
8
+ from agno.knowledge.types import ContentType
9
+
10
+
11
+ @dataclass
12
+ class Reader:
13
+ """Base class for reading documents"""
14
+
15
+ chunk: bool = True
16
+ chunk_size: int = 5000
17
+ separators: List[str] = field(default_factory=lambda: ["\n", "\n\n", "\r", "\r\n", "\n\r", "\t", " ", " "])
18
+ chunking_strategy: Optional[ChunkingStrategy] = None
19
+ name: Optional[str] = None
20
+ description: Optional[str] = None
21
+ max_results: int = 5 # Maximum number of results to return (useful for search-based readers)
22
+
23
+ def __init__(
24
+ self,
25
+ chunk: bool = True,
26
+ chunk_size: int = 5000,
27
+ separators: Optional[List[str]] = None,
28
+ chunking_strategy: Optional[ChunkingStrategy] = None,
29
+ name: Optional[str] = None,
30
+ description: Optional[str] = None,
31
+ max_results: int = 5,
32
+ **kwargs,
33
+ ) -> None:
34
+ self.chunk = chunk
35
+ self.chunk_size = chunk_size
36
+ self.separators = (
37
+ separators if separators is not None else ["\n", "\n\n", "\r", "\r\n", "\n\r", "\t", " ", " "]
38
+ )
39
+ self.chunking_strategy = chunking_strategy
40
+ self.name = name
41
+ self.description = description
42
+ self.max_results = max_results
43
+
44
+ def set_chunking_strategy_from_string(self, strategy_name: str, **kwargs) -> None:
45
+ """Set the chunking strategy from a string name."""
46
+ try:
47
+ strategy_type = ChunkingStrategyType.from_string(strategy_name)
48
+ self.chunking_strategy = ChunkingStrategyFactory.create_strategy(strategy_type, **kwargs)
49
+ except ValueError as e:
50
+ raise ValueError(f"Failed to set chunking strategy: {e}")
51
+
52
+ def read(self, obj: Any, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
53
+ raise NotImplementedError
54
+
55
+ async def async_read(self, obj: Any, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
56
+ raise NotImplementedError
57
+
58
+ @classmethod
59
+ def get_supported_chunking_strategies(cls) -> List[ChunkingStrategyType]:
60
+ raise NotImplementedError
61
+
62
+ @classmethod
63
+ def get_supported_content_types(cls) -> List[ContentType]:
64
+ raise NotImplementedError
65
+
66
+ def chunk_document(self, document: Document) -> List[Document]:
67
+ if self.chunking_strategy is None:
68
+ self.chunking_strategy = FixedSizeChunking(chunk_size=self.chunk_size)
69
+ return self.chunking_strategy.chunk(document) # type: ignore
70
+
71
+ async def chunk_documents_async(self, documents: List[Document]) -> List[Document]:
72
+ """
73
+ Asynchronously chunk a list of documents using the instance's chunk_document method.
74
+
75
+ Args:
76
+ documents: List of documents to be chunked.
77
+
78
+ Returns:
79
+ A flattened list of chunked documents.
80
+ """
81
+
82
+ async def _chunk_document_async(doc: Document) -> List[Document]:
83
+ return await asyncio.to_thread(self.chunk_document, doc)
84
+
85
+ # Process chunking in parallel for all documents
86
+ chunked_lists = await asyncio.gather(*[_chunk_document_async(doc) for doc in documents])
87
+ # Flatten the result
88
+ return [chunk for sublist in chunked_lists for chunk in sublist]
@@ -14,15 +14,38 @@ try:
14
14
  except ImportError:
15
15
  raise ImportError("`aiofiles` not installed. Please install it with `pip install aiofiles`")
16
16
 
17
- from agno.document.base import Document
18
- from agno.document.reader.base import Reader
17
+ from agno.knowledge.chunking.row import RowChunking
18
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
19
+ from agno.knowledge.document.base import Document
20
+ from agno.knowledge.reader.base import Reader
21
+ from agno.knowledge.types import ContentType
19
22
  from agno.utils.log import logger
20
23
 
21
24
 
22
25
  class CSVReader(Reader):
23
26
  """Reader for CSV files"""
24
27
 
25
- def read(self, file: Union[Path, IO[Any]], delimiter: str = ",", quotechar: str = '"') -> List[Document]:
28
+ def __init__(self, chunking_strategy: Optional[ChunkingStrategy] = RowChunking(), **kwargs):
29
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
30
+
31
+ @classmethod
32
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
33
+ """Get the list of supported chunking strategies for CSV readers."""
34
+ return [
35
+ ChunkingStrategyType.ROW_CHUNKING,
36
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
37
+ ChunkingStrategyType.AGENTIC_CHUNKING,
38
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
39
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
40
+ ]
41
+
42
+ @classmethod
43
+ def get_supported_content_types(self) -> List[ContentType]:
44
+ return [ContentType.FILE, ContentType.URL, ContentType.CSV, ContentType.XLSX, ContentType.XLS]
45
+
46
+ def read(
47
+ self, file: Union[Path, IO[Any]], delimiter: str = ",", quotechar: str = '"', name: Optional[str] = None
48
+ ) -> List[Document]:
26
49
  try:
27
50
  if isinstance(file, Path):
28
51
  if not file.exists():
@@ -30,11 +53,15 @@ class CSVReader(Reader):
30
53
  logger.info(f"Reading: {file}")
31
54
  file_content = file.open(newline="", mode="r", encoding="utf-8")
32
55
  else:
33
- logger.info(f"Reading retrieved file: {file.name}")
56
+ logger.info(f"Reading retrieved file: {name or file.name}")
34
57
  file.seek(0)
35
58
  file_content = io.StringIO(file.read().decode("utf-8")) # type: ignore
36
59
 
37
- csv_name = Path(file.name).stem if isinstance(file, Path) else file.name.split(".")[0]
60
+ csv_name = name or (
61
+ Path(file.name).stem
62
+ if isinstance(file, Path)
63
+ else (getattr(file, "name", "csv_file").split(".")[0] if hasattr(file, "name") else "csv_file")
64
+ )
38
65
  csv_content = ""
39
66
  with file_content as csvfile:
40
67
  csv_reader = csv.reader(csvfile, delimiter=delimiter, quotechar=quotechar)
@@ -55,11 +82,16 @@ class CSVReader(Reader):
55
82
  return chunked_documents
56
83
  return documents
57
84
  except Exception as e:
58
- logger.error(f"Error reading: {file.name if isinstance(file, IO) else file}: {e}")
85
+ logger.error(f"Error reading: {getattr(file, 'name', str(file)) if isinstance(file, IO) else file}: {e}")
59
86
  return []
60
87
 
61
88
  async def async_read(
62
- self, file: Union[Path, IO[Any]], delimiter: str = ",", quotechar: str = '"', page_size: int = 1000
89
+ self,
90
+ file: Union[Path, IO[Any]],
91
+ delimiter: str = ",",
92
+ quotechar: str = '"',
93
+ page_size: int = 1000,
94
+ name: Optional[str] = None,
63
95
  ) -> List[Document]:
64
96
  """
65
97
  Read a CSV file asynchronously, processing batches of rows concurrently.
@@ -86,7 +118,11 @@ class CSVReader(Reader):
86
118
  file.seek(0)
87
119
  file_content_io = io.StringIO(file.read().decode("utf-8")) # type: ignore
88
120
 
89
- csv_name = Path(file.name).stem if isinstance(file, Path) else file.name.split(".")[0]
121
+ csv_name = name or (
122
+ Path(file.name).stem
123
+ if isinstance(file, Path)
124
+ else (getattr(file, "name", "csv_file").split(".")[0] if hasattr(file, "name") else "csv_file")
125
+ )
90
126
 
91
127
  file_content_io.seek(0)
92
128
  csv_reader = csv.reader(file_content_io, delimiter=delimiter, quotechar=quotechar)
@@ -128,18 +164,35 @@ class CSVReader(Reader):
128
164
 
129
165
  return documents
130
166
  except Exception as e:
131
- logger.error(f"Error reading async: {file.name if isinstance(file, IO) else file}: {e}")
167
+ logger.error(
168
+ f"Error reading async: {getattr(file, 'name', str(file)) if isinstance(file, IO) else file}: {e}"
169
+ )
132
170
  return []
133
171
 
134
172
 
135
173
  class CSVUrlReader(Reader):
136
174
  """Reader for CSV files"""
137
175
 
138
- def __init__(self, proxy: Optional[str] = None, **kwargs):
139
- super().__init__(**kwargs)
176
+ def __init__(
177
+ self, chunking_strategy: Optional[ChunkingStrategy] = RowChunking(), proxy: Optional[str] = None, **kwargs
178
+ ):
179
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
140
180
  self.proxy = proxy
141
181
 
142
- def read(self, url: str) -> List[Document]:
182
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
183
+ """Get the list of supported chunking strategies for CSV URL readers."""
184
+ return [
185
+ ChunkingStrategyType.ROW_CHUNKING,
186
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
187
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
188
+ ChunkingStrategyType.AGENTIC_CHUNKING,
189
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
190
+ ]
191
+
192
+ def get_supported_content_types(self) -> List[ContentType]:
193
+ return [ContentType.URL]
194
+
195
+ def read(self, url: str, name: Optional[str] = None) -> List[Document]:
143
196
  if not url:
144
197
  raise ValueError("No URL provided")
145
198
 
@@ -152,13 +205,13 @@ class CSVUrlReader(Reader):
152
205
 
153
206
  file_obj = io.BytesIO(response.content)
154
207
  file_obj.name = filename
155
- documents = CSVReader().read(file=file_obj)
208
+ documents = CSVReader().read(file=file_obj, name=name)
156
209
 
157
210
  file_obj.close()
158
211
 
159
212
  return documents
160
213
 
161
- async def async_read(self, url: str) -> List[Document]:
214
+ async def async_read(self, url: str, name: Optional[str] = None) -> List[Document]:
162
215
  if not url:
163
216
  raise ValueError("No URL provided")
164
217
 
@@ -177,7 +230,7 @@ class CSVUrlReader(Reader):
177
230
  file_obj.name = filename
178
231
 
179
232
  # Use the async version of CSVReader
180
- documents = await CSVReader().async_read(file=file_obj)
233
+ documents = await CSVReader().async_read(file=file_obj, name=name)
181
234
 
182
235
  file_obj.close()
183
236
 
@@ -0,0 +1,83 @@
1
+ import asyncio
2
+ from pathlib import Path
3
+ from typing import IO, Any, List, Optional, Union
4
+ from uuid import uuid4
5
+
6
+ from agno.knowledge.chunking.document import DocumentChunking
7
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
8
+ from agno.knowledge.document.base import Document
9
+ from agno.knowledge.reader.base import Reader
10
+ from agno.knowledge.types import ContentType
11
+ from agno.utils.log import log_info, logger
12
+
13
+ try:
14
+ from docx import Document as DocxDocument # type: ignore
15
+ except ImportError:
16
+ raise ImportError("The `python-docx` package is not installed. Please install it via `pip install python-docx`.")
17
+
18
+
19
+ class DocxReader(Reader):
20
+ """Reader for Doc/Docx files"""
21
+
22
+ def __init__(self, chunking_strategy: Optional[ChunkingStrategy] = DocumentChunking(), **kwargs):
23
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
24
+
25
+ @classmethod
26
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
27
+ """Get the list of supported chunking strategies for DOCX readers."""
28
+ return [
29
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
30
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
31
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
32
+ ChunkingStrategyType.AGENTIC_CHUNKING,
33
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
34
+ ]
35
+
36
+ @classmethod
37
+ def get_supported_content_types(self) -> List[ContentType]:
38
+ return [ContentType.DOCX, ContentType.DOC]
39
+
40
+ def read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
41
+ """Read a docx file and return a list of documents"""
42
+ try:
43
+ if isinstance(file, Path):
44
+ if not file.exists():
45
+ raise FileNotFoundError(f"Could not find file: {file}")
46
+ log_info(f"Reading: {file}")
47
+ docx_document = DocxDocument(str(file))
48
+ doc_name = name or file.stem
49
+ else:
50
+ log_info(f"Reading uploaded file: {getattr(file, 'name', 'docx_file')}")
51
+ docx_document = DocxDocument(file)
52
+ doc_name = name or (
53
+ getattr(file, "name", "docx_file").split(".")[0] if hasattr(file, "name") else "docx_file"
54
+ )
55
+
56
+ doc_content = "\n\n".join([para.text for para in docx_document.paragraphs])
57
+
58
+ documents = [
59
+ Document(
60
+ name=doc_name,
61
+ id=str(uuid4()),
62
+ content=doc_content,
63
+ )
64
+ ]
65
+
66
+ if self.chunk:
67
+ chunked_documents = []
68
+ for document in documents:
69
+ chunked_documents.extend(self.chunk_document(document))
70
+ return chunked_documents
71
+ return documents
72
+
73
+ except Exception as e:
74
+ logger.error(f"Error reading file: {e}")
75
+ return []
76
+
77
+ async def async_read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
78
+ """Asynchronously read a docx file and return a list of documents"""
79
+ try:
80
+ return await asyncio.to_thread(self.read, file, name)
81
+ except Exception as e:
82
+ logger.error(f"Error reading file asynchronously: {e}")
83
+ return []
@@ -2,9 +2,11 @@ import asyncio
2
2
  from dataclasses import dataclass
3
3
  from typing import Dict, List, Literal, Optional
4
4
 
5
- from agno.document.base import Document
6
- from agno.document.chunking.strategy import ChunkingStrategy
7
- from agno.document.reader.base import Reader
5
+ from agno.knowledge.chunking.semantic import SemanticChunking
6
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
7
+ from agno.knowledge.document.base import Document
8
+ from agno.knowledge.reader.base import Reader
9
+ from agno.knowledge.types import ContentType
8
10
  from agno.utils.log import log_debug, logger
9
11
 
10
12
  try:
@@ -26,17 +28,36 @@ class FirecrawlReader(Reader):
26
28
  mode: Literal["scrape", "crawl"] = "scrape",
27
29
  chunk: bool = True,
28
30
  chunk_size: int = 5000,
29
- chunking_strategy: Optional[ChunkingStrategy] = None,
31
+ chunking_strategy: Optional[ChunkingStrategy] = SemanticChunking(),
32
+ name: Optional[str] = None,
33
+ description: Optional[str] = None,
30
34
  ) -> None:
31
35
  # Initialise base Reader (handles chunk_size / strategy)
32
- super().__init__(chunk=chunk, chunk_size=chunk_size, chunking_strategy=chunking_strategy)
36
+ super().__init__(
37
+ chunk=chunk, chunk_size=chunk_size, chunking_strategy=chunking_strategy, name=name, description=description
38
+ )
33
39
 
34
40
  # Firecrawl-specific attributes
35
41
  self.api_key = api_key
36
42
  self.params = params
37
43
  self.mode = mode
38
44
 
39
- def scrape(self, url: str) -> List[Document]:
45
+ @classmethod
46
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
47
+ """Get the list of supported chunking strategies for Firecrawl readers."""
48
+ return [
49
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
50
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
51
+ ChunkingStrategyType.AGENTIC_CHUNKING,
52
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
53
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
54
+ ]
55
+
56
+ @classmethod
57
+ def get_supported_content_types(self) -> List[ContentType]:
58
+ return [ContentType.URL]
59
+
60
+ def scrape(self, url: str, name: Optional[str] = None) -> List[Document]:
40
61
  """
41
62
  Scrapes a website and returns a list of documents.
42
63
 
@@ -71,12 +92,12 @@ class FirecrawlReader(Reader):
71
92
 
72
93
  documents = []
73
94
  if self.chunk and content: # Only chunk if there's content
74
- documents.extend(self.chunk_document(Document(name=url, id=url, content=content)))
95
+ documents.extend(self.chunk_document(Document(name=name or url, id=url, content=content)))
75
96
  else:
76
- documents.append(Document(name=url, id=url, content=content))
97
+ documents.append(Document(name=name or url, id=url, content=content))
77
98
  return documents
78
99
 
79
- async def async_scrape(self, url: str) -> List[Document]:
100
+ async def async_scrape(self, url: str, name: Optional[str] = None) -> List[Document]:
80
101
  """
81
102
  Asynchronously scrapes a website and returns a list of documents.
82
103
 
@@ -89,9 +110,9 @@ class FirecrawlReader(Reader):
89
110
  log_debug(f"Async scraping: {url}")
90
111
 
91
112
  # Use asyncio.to_thread to run the synchronous scrape in a thread
92
- return await asyncio.to_thread(self.scrape, url)
113
+ return await asyncio.to_thread(self.scrape, url, name)
93
114
 
94
- def crawl(self, url: str) -> List[Document]:
115
+ def crawl(self, url: str, name: Optional[str] = None) -> List[Document]:
95
116
  """
96
117
  Crawls a website and returns a list of documents.
97
118
 
@@ -124,13 +145,13 @@ class FirecrawlReader(Reader):
124
145
 
125
146
  if content: # Only create document if content exists
126
147
  if self.chunk:
127
- documents.extend(self.chunk_document(Document(name=url, id=url, content=content)))
148
+ documents.extend(self.chunk_document(Document(name=name or url, id=url, content=content)))
128
149
  else:
129
- documents.append(Document(name=url, id=url, content=content))
150
+ documents.append(Document(name=name or url, id=url, content=content))
130
151
 
131
152
  return documents
132
153
 
133
- async def async_crawl(self, url: str) -> List[Document]:
154
+ async def async_crawl(self, url: str, name: Optional[str] = None) -> List[Document]:
134
155
  """
135
156
  Asynchronously crawls a website and returns a list of documents.
136
157
 
@@ -143,9 +164,9 @@ class FirecrawlReader(Reader):
143
164
  log_debug(f"Async crawling: {url}")
144
165
 
145
166
  # Use asyncio.to_thread to run the synchronous crawl in a thread
146
- return await asyncio.to_thread(self.crawl, url)
167
+ return await asyncio.to_thread(self.crawl, url, name)
147
168
 
148
- def read(self, url: str) -> List[Document]:
169
+ def read(self, url: str, name: Optional[str] = None) -> List[Document]:
149
170
  """
150
171
  Reads from a URL based on the mode setting.
151
172
 
@@ -156,13 +177,13 @@ class FirecrawlReader(Reader):
156
177
  A list of documents
157
178
  """
158
179
  if self.mode == "scrape":
159
- return self.scrape(url)
180
+ return self.scrape(url, name)
160
181
  elif self.mode == "crawl":
161
- return self.crawl(url)
182
+ return self.crawl(url, name)
162
183
  else:
163
184
  raise NotImplementedError(f"Mode {self.mode} not implemented")
164
185
 
165
- async def async_read(self, url: str) -> List[Document]:
186
+ async def async_read(self, url: str, name: Optional[str] = None) -> List[Document]:
166
187
  """
167
188
  Asynchronously reads from a URL based on the mode setting.
168
189
 
@@ -173,8 +194,8 @@ class FirecrawlReader(Reader):
173
194
  A list of documents
174
195
  """
175
196
  if self.mode == "scrape":
176
- return await self.async_scrape(url)
197
+ return await self.async_scrape(url, name)
177
198
  elif self.mode == "crawl":
178
- return await self.async_crawl(url)
199
+ return await self.async_crawl(url, name)
179
200
  else:
180
201
  raise NotImplementedError(f"Mode {self.mode} not implemented")
@@ -0,0 +1,67 @@
1
+ import asyncio
2
+ from io import BytesIO
3
+ from typing import List, Optional
4
+ from uuid import uuid4
5
+
6
+ from agno.knowledge.chunking.fixed import FixedSizeChunking
7
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
8
+ from agno.knowledge.document.base import Document
9
+ from agno.knowledge.reader.base import Reader
10
+ from agno.knowledge.types import ContentType
11
+ from agno.utils.log import log_info
12
+
13
+ try:
14
+ from google.cloud import storage # type: ignore
15
+ except ImportError:
16
+ raise ImportError("`google-cloud-storage` not installed. Please install it via `pip install google-cloud-storage`.")
17
+
18
+ try:
19
+ from pypdf import PdfReader as DocumentReader
20
+ except ImportError:
21
+ raise ImportError("`pypdf` not installed. Please install it via `pip install pypdf`.")
22
+
23
+
24
+ class GCSReader(Reader):
25
+ def __init__(self, chunking_strategy: Optional[ChunkingStrategy] = FixedSizeChunking(), **kwargs):
26
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
27
+
28
+ @classmethod
29
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
30
+ """Get the list of supported chunking strategies for GCS readers."""
31
+ return [
32
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
33
+ ChunkingStrategyType.AGENTIC_CHUNKING,
34
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
35
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
36
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
37
+ ]
38
+
39
+ @classmethod
40
+ def get_supported_content_types(self) -> List[ContentType]:
41
+ return [ContentType.FILE, ContentType.URL]
42
+
43
+ def read(self, name: Optional[str], blob: storage.Blob) -> List[Document]:
44
+ log_info(f"Reading: gs://{blob.bucket.name}/{blob.name}")
45
+ data = blob.download_as_bytes()
46
+ doc_name = blob.name.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
47
+ if name is not None:
48
+ doc_name = name
49
+ doc_reader = DocumentReader(BytesIO(data))
50
+ documents = [
51
+ Document(
52
+ name=doc_name,
53
+ id=str(uuid4()),
54
+ meta_data={"page": page_number},
55
+ content=page.extract_text(),
56
+ )
57
+ for page_number, page in enumerate(doc_reader.pages, start=1)
58
+ ]
59
+ if self.chunk:
60
+ chunked_documents = []
61
+ for document in documents:
62
+ chunked_documents.extend(self.chunk_document(document))
63
+ return chunked_documents
64
+ return documents
65
+
66
+ async def async_read(self, name: Optional[str], blob: storage.Blob) -> List[Document]:
67
+ return await asyncio.to_thread(self.read, name, blob)
@@ -2,11 +2,14 @@ import asyncio
2
2
  import json
3
3
  from io import BytesIO
4
4
  from pathlib import Path
5
- from typing import IO, Any, List, Union
5
+ from typing import IO, Any, List, Optional, Union
6
6
  from uuid import uuid4
7
7
 
8
- from agno.document.base import Document
9
- from agno.document.reader.base import Reader
8
+ from agno.knowledge.chunking.fixed import FixedSizeChunking
9
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
10
+ from agno.knowledge.document.base import Document
11
+ from agno.knowledge.reader.base import Reader
12
+ from agno.knowledge.types import ContentType
10
13
  from agno.utils.log import log_info
11
14
 
12
15
 
@@ -15,18 +18,36 @@ class JSONReader(Reader):
15
18
 
16
19
  chunk: bool = False
17
20
 
18
- def read(self, path: Union[Path, IO[Any]]) -> List[Document]:
21
+ def __init__(self, chunking_strategy: Optional[ChunkingStrategy] = FixedSizeChunking(), **kwargs):
22
+ super().__init__(chunking_strategy=chunking_strategy, **kwargs)
23
+
24
+ @classmethod
25
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
26
+ """Get the list of supported chunking strategies for JSON readers."""
27
+ return [
28
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
29
+ ChunkingStrategyType.AGENTIC_CHUNKING,
30
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
31
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
32
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
33
+ ]
34
+
35
+ @classmethod
36
+ def get_supported_content_types(self) -> List[ContentType]:
37
+ return [ContentType.JSON]
38
+
39
+ def read(self, path: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
19
40
  try:
20
41
  if isinstance(path, Path):
21
42
  if not path.exists():
22
43
  raise FileNotFoundError(f"Could not find file: {path}")
23
44
  log_info(f"Reading: {path}")
24
- json_name = path.name.split(".")[0]
45
+ json_name = name or path.name.split(".")[0]
25
46
  json_contents = json.loads(path.read_text("utf-8"))
26
47
 
27
48
  elif isinstance(path, BytesIO):
28
- log_info(f"Reading uploaded file: {path.name}")
29
- json_name = path.name.split(".")[0]
49
+ json_name = name or path.name.split(".")[0]
50
+ log_info(f"Reading uploaded file: {json_name}")
30
51
  path.seek(0)
31
52
  json_contents = json.load(path)
32
53
 
@@ -54,7 +75,7 @@ class JSONReader(Reader):
54
75
  except Exception:
55
76
  raise
56
77
 
57
- async def async_read(self, path: Union[Path, IO[Any]]) -> List[Document]:
78
+ async def async_read(self, path: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
58
79
  """Asynchronously read JSON files.
59
80
 
60
81
  Args:
@@ -63,4 +84,4 @@ class JSONReader(Reader):
63
84
  Returns:
64
85
  List[Document]: List of documents from the JSON file
65
86
  """
66
- return await asyncio.to_thread(self.read, path)
87
+ return await asyncio.to_thread(self.read, path, name)