agno 1.8.0__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 (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  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/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +54 -41
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.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)