agno 1.8.2__py3-none-any.whl → 2.0.0__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 (589) hide show
  1. agno/agent/__init__.py +19 -27
  2. agno/agent/agent.py +3143 -4170
  3. agno/api/agent.py +11 -67
  4. agno/api/api.py +5 -46
  5. agno/api/evals.py +8 -19
  6. agno/api/os.py +17 -0
  7. agno/api/routes.py +6 -41
  8. agno/api/schemas/__init__.py +9 -0
  9. agno/api/schemas/agent.py +5 -21
  10. agno/api/schemas/evals.py +7 -16
  11. agno/api/schemas/os.py +14 -0
  12. agno/api/schemas/team.py +5 -21
  13. agno/api/schemas/utils.py +21 -0
  14. agno/api/schemas/workflows.py +11 -7
  15. agno/api/settings.py +53 -0
  16. agno/api/team.py +11 -66
  17. agno/api/workflow.py +28 -0
  18. agno/cloud/aws/base.py +214 -0
  19. agno/cloud/aws/s3/__init__.py +2 -0
  20. agno/cloud/aws/s3/api_client.py +43 -0
  21. agno/cloud/aws/s3/bucket.py +195 -0
  22. agno/cloud/aws/s3/object.py +57 -0
  23. agno/db/__init__.py +24 -0
  24. agno/db/base.py +245 -0
  25. agno/db/dynamo/__init__.py +3 -0
  26. agno/db/dynamo/dynamo.py +1743 -0
  27. agno/db/dynamo/schemas.py +278 -0
  28. agno/db/dynamo/utils.py +684 -0
  29. agno/db/firestore/__init__.py +3 -0
  30. agno/db/firestore/firestore.py +1432 -0
  31. agno/db/firestore/schemas.py +130 -0
  32. agno/db/firestore/utils.py +278 -0
  33. agno/db/gcs_json/__init__.py +3 -0
  34. agno/db/gcs_json/gcs_json_db.py +1001 -0
  35. agno/db/gcs_json/utils.py +194 -0
  36. agno/db/in_memory/__init__.py +3 -0
  37. agno/db/in_memory/in_memory_db.py +882 -0
  38. agno/db/in_memory/utils.py +172 -0
  39. agno/db/json/__init__.py +3 -0
  40. agno/db/json/json_db.py +1045 -0
  41. agno/db/json/utils.py +196 -0
  42. agno/db/migrations/v1_to_v2.py +162 -0
  43. agno/db/mongo/__init__.py +3 -0
  44. agno/db/mongo/mongo.py +1416 -0
  45. agno/db/mongo/schemas.py +77 -0
  46. agno/db/mongo/utils.py +204 -0
  47. agno/db/mysql/__init__.py +3 -0
  48. agno/db/mysql/mysql.py +1719 -0
  49. agno/db/mysql/schemas.py +124 -0
  50. agno/db/mysql/utils.py +297 -0
  51. agno/db/postgres/__init__.py +3 -0
  52. agno/db/postgres/postgres.py +1710 -0
  53. agno/db/postgres/schemas.py +124 -0
  54. agno/db/postgres/utils.py +280 -0
  55. agno/db/redis/__init__.py +3 -0
  56. agno/db/redis/redis.py +1367 -0
  57. agno/db/redis/schemas.py +109 -0
  58. agno/db/redis/utils.py +288 -0
  59. agno/db/schemas/__init__.py +3 -0
  60. agno/db/schemas/evals.py +33 -0
  61. agno/db/schemas/knowledge.py +40 -0
  62. agno/db/schemas/memory.py +46 -0
  63. agno/db/singlestore/__init__.py +3 -0
  64. agno/db/singlestore/schemas.py +116 -0
  65. agno/db/singlestore/singlestore.py +1712 -0
  66. agno/db/singlestore/utils.py +326 -0
  67. agno/db/sqlite/__init__.py +3 -0
  68. agno/db/sqlite/schemas.py +119 -0
  69. agno/db/sqlite/sqlite.py +1676 -0
  70. agno/db/sqlite/utils.py +268 -0
  71. agno/db/utils.py +88 -0
  72. agno/eval/__init__.py +14 -0
  73. agno/eval/accuracy.py +154 -48
  74. agno/eval/performance.py +88 -23
  75. agno/eval/reliability.py +73 -20
  76. agno/eval/utils.py +23 -13
  77. agno/integrations/discord/__init__.py +3 -0
  78. agno/{app → integrations}/discord/client.py +10 -10
  79. agno/knowledge/__init__.py +2 -2
  80. agno/{document → knowledge}/chunking/agentic.py +2 -2
  81. agno/{document → knowledge}/chunking/document.py +2 -2
  82. agno/{document → knowledge}/chunking/fixed.py +3 -3
  83. agno/{document → knowledge}/chunking/markdown.py +2 -2
  84. agno/{document → knowledge}/chunking/recursive.py +2 -2
  85. agno/{document → knowledge}/chunking/row.py +2 -2
  86. agno/knowledge/chunking/semantic.py +59 -0
  87. agno/knowledge/chunking/strategy.py +121 -0
  88. agno/knowledge/content.py +74 -0
  89. agno/knowledge/document/__init__.py +5 -0
  90. agno/{document → knowledge/document}/base.py +12 -2
  91. agno/knowledge/embedder/__init__.py +5 -0
  92. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  93. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  94. agno/{embedder → knowledge/embedder}/base.py +6 -0
  95. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  96. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  97. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  98. agno/{embedder → knowledge/embedder}/google.py +74 -1
  99. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  100. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  101. agno/knowledge/embedder/langdb.py +22 -0
  102. agno/knowledge/embedder/mistral.py +139 -0
  103. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  104. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  105. agno/knowledge/embedder/openai.py +223 -0
  106. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  107. agno/{embedder → knowledge/embedder}/together.py +1 -1
  108. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  109. agno/knowledge/knowledge.py +1551 -0
  110. agno/knowledge/reader/__init__.py +7 -0
  111. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  112. agno/knowledge/reader/base.py +88 -0
  113. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  114. agno/knowledge/reader/docx_reader.py +83 -0
  115. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  116. agno/{document → knowledge}/reader/json_reader.py +30 -9
  117. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  118. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  119. agno/knowledge/reader/reader_factory.py +268 -0
  120. agno/knowledge/reader/s3_reader.py +101 -0
  121. agno/{document → knowledge}/reader/text_reader.py +31 -10
  122. agno/knowledge/reader/url_reader.py +128 -0
  123. agno/knowledge/reader/web_search_reader.py +366 -0
  124. agno/{document → knowledge}/reader/website_reader.py +37 -10
  125. agno/knowledge/reader/wikipedia_reader.py +59 -0
  126. agno/knowledge/reader/youtube_reader.py +78 -0
  127. agno/knowledge/remote_content/remote_content.py +88 -0
  128. agno/{reranker → knowledge/reranker}/base.py +1 -1
  129. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  130. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  131. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  132. agno/knowledge/types.py +30 -0
  133. agno/knowledge/utils.py +169 -0
  134. agno/media.py +269 -268
  135. agno/memory/__init__.py +2 -10
  136. agno/memory/manager.py +1003 -148
  137. agno/models/aimlapi/__init__.py +2 -2
  138. agno/models/aimlapi/aimlapi.py +6 -6
  139. agno/models/anthropic/claude.py +128 -72
  140. agno/models/aws/bedrock.py +107 -175
  141. agno/models/aws/claude.py +64 -18
  142. agno/models/azure/ai_foundry.py +73 -23
  143. agno/models/base.py +346 -290
  144. agno/models/cerebras/cerebras.py +84 -27
  145. agno/models/cohere/chat.py +106 -98
  146. agno/models/google/gemini.py +105 -46
  147. agno/models/groq/groq.py +97 -35
  148. agno/models/huggingface/huggingface.py +92 -27
  149. agno/models/ibm/watsonx.py +72 -13
  150. agno/models/litellm/chat.py +85 -13
  151. agno/models/message.py +46 -151
  152. agno/models/meta/llama.py +85 -49
  153. agno/models/metrics.py +120 -0
  154. agno/models/mistral/mistral.py +90 -21
  155. agno/models/ollama/__init__.py +0 -2
  156. agno/models/ollama/chat.py +85 -47
  157. agno/models/openai/chat.py +154 -37
  158. agno/models/openai/responses.py +178 -105
  159. agno/models/perplexity/perplexity.py +26 -2
  160. agno/models/portkey/portkey.py +0 -7
  161. agno/models/response.py +15 -9
  162. agno/models/utils.py +20 -0
  163. agno/models/vercel/__init__.py +2 -2
  164. agno/models/vercel/v0.py +1 -1
  165. agno/models/vllm/__init__.py +2 -2
  166. agno/models/vllm/vllm.py +3 -3
  167. agno/models/xai/xai.py +10 -10
  168. agno/os/__init__.py +3 -0
  169. agno/os/app.py +497 -0
  170. agno/os/auth.py +47 -0
  171. agno/os/config.py +103 -0
  172. agno/os/interfaces/agui/__init__.py +3 -0
  173. agno/os/interfaces/agui/agui.py +31 -0
  174. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  175. agno/{app → os/interfaces}/agui/utils.py +65 -28
  176. agno/os/interfaces/base.py +21 -0
  177. agno/os/interfaces/slack/__init__.py +3 -0
  178. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  179. agno/os/interfaces/slack/slack.py +32 -0
  180. agno/os/interfaces/whatsapp/__init__.py +3 -0
  181. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  182. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  183. agno/os/mcp.py +235 -0
  184. agno/os/router.py +1400 -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 +393 -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 +850 -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 +410 -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 +178 -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 +536 -0
  201. agno/os/schema.py +945 -0
  202. agno/{app/playground → os}/settings.py +7 -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/agent.py +633 -0
  212. agno/run/base.py +53 -77
  213. agno/run/cancel.py +81 -0
  214. agno/run/team.py +243 -96
  215. agno/run/workflow.py +550 -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 +3260 -4824
  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 +43 -23
  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 +20 -17
  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 +22 -12
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +17 -8
  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 +62 -62
  252. agno/tools/eleven_labs.py +36 -29
  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 +30 -30
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +17 -18
  260. agno/tools/function.py +127 -18
  261. agno/tools/giphy.py +23 -11
  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 +32 -20
  276. agno/tools/mcp.py +1 -2
  277. agno/tools/mem0.py +18 -12
  278. agno/tools/memori.py +14 -10
  279. agno/tools/mlx_transcribe.py +3 -2
  280. agno/tools/models/azure_openai.py +33 -15
  281. agno/tools/models/gemini.py +59 -32
  282. agno/tools/models/groq.py +30 -23
  283. agno/tools/models/nebius.py +28 -12
  284. agno/tools/models_labs.py +40 -16
  285. agno/tools/moviepy_video.py +7 -6
  286. agno/tools/neo4j.py +10 -8
  287. agno/tools/newspaper.py +7 -2
  288. agno/tools/newspaper4k.py +8 -3
  289. agno/tools/openai.py +58 -32
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +63 -47
  292. agno/tools/openweather.py +14 -12
  293. agno/tools/pandas.py +11 -3
  294. agno/tools/postgres.py +4 -12
  295. agno/tools/pubmed.py +4 -1
  296. agno/tools/python.py +9 -22
  297. agno/tools/reasoning.py +35 -27
  298. agno/tools/reddit.py +11 -26
  299. agno/tools/replicate.py +55 -42
  300. agno/tools/resend.py +4 -1
  301. agno/tools/scrapegraph.py +15 -14
  302. agno/tools/searxng.py +10 -23
  303. agno/tools/serpapi.py +6 -3
  304. agno/tools/serper.py +13 -4
  305. agno/tools/shell.py +9 -2
  306. agno/tools/slack.py +12 -11
  307. agno/tools/sleep.py +3 -2
  308. agno/tools/spider.py +24 -4
  309. agno/tools/sql.py +7 -6
  310. agno/tools/tavily.py +6 -4
  311. agno/tools/telegram.py +12 -4
  312. agno/tools/todoist.py +11 -31
  313. agno/tools/toolkit.py +1 -1
  314. agno/tools/trafilatura.py +22 -6
  315. agno/tools/trello.py +9 -22
  316. agno/tools/twilio.py +10 -3
  317. agno/tools/user_control_flow.py +6 -1
  318. agno/tools/valyu.py +34 -5
  319. agno/tools/visualization.py +19 -28
  320. agno/tools/webbrowser.py +4 -3
  321. agno/tools/webex.py +11 -7
  322. agno/tools/website.py +15 -46
  323. agno/tools/webtools.py +12 -4
  324. agno/tools/whatsapp.py +5 -9
  325. agno/tools/wikipedia.py +20 -13
  326. agno/tools/x.py +14 -13
  327. agno/tools/yfinance.py +13 -40
  328. agno/tools/youtube.py +26 -20
  329. agno/tools/zendesk.py +7 -2
  330. agno/tools/zep.py +10 -7
  331. agno/tools/zoom.py +10 -9
  332. agno/utils/common.py +1 -19
  333. agno/utils/events.py +100 -123
  334. agno/utils/gemini.py +1 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +54 -4
  337. agno/utils/mcp.py +68 -10
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/aws_claude.py +1 -1
  341. agno/utils/models/claude.py +6 -12
  342. agno/utils/models/cohere.py +1 -1
  343. agno/utils/models/mistral.py +8 -7
  344. agno/utils/models/schema_utils.py +3 -3
  345. agno/utils/models/watsonx.py +1 -1
  346. agno/utils/openai.py +1 -1
  347. agno/utils/pprint.py +33 -32
  348. agno/utils/print_response/agent.py +779 -0
  349. agno/utils/print_response/team.py +1669 -0
  350. agno/utils/print_response/workflow.py +1451 -0
  351. agno/utils/prompts.py +14 -14
  352. agno/utils/reasoning.py +87 -0
  353. agno/utils/response.py +42 -42
  354. agno/utils/streamlit.py +481 -0
  355. agno/utils/string.py +8 -22
  356. agno/utils/team.py +50 -0
  357. agno/utils/timer.py +2 -2
  358. agno/vectordb/base.py +33 -21
  359. agno/vectordb/cassandra/cassandra.py +287 -23
  360. agno/vectordb/chroma/chromadb.py +482 -59
  361. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  362. agno/vectordb/couchbase/couchbase.py +309 -29
  363. agno/vectordb/lancedb/lance_db.py +360 -21
  364. agno/vectordb/langchaindb/__init__.py +5 -0
  365. agno/vectordb/langchaindb/langchaindb.py +145 -0
  366. agno/vectordb/lightrag/__init__.py +5 -0
  367. agno/vectordb/lightrag/lightrag.py +374 -0
  368. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  369. agno/vectordb/milvus/milvus.py +242 -32
  370. agno/vectordb/mongodb/mongodb.py +200 -24
  371. agno/vectordb/pgvector/pgvector.py +319 -37
  372. agno/vectordb/pineconedb/pineconedb.py +221 -27
  373. agno/vectordb/qdrant/qdrant.py +334 -14
  374. agno/vectordb/singlestore/singlestore.py +286 -29
  375. agno/vectordb/surrealdb/surrealdb.py +187 -7
  376. agno/vectordb/upstashdb/upstashdb.py +342 -26
  377. agno/vectordb/weaviate/weaviate.py +227 -165
  378. agno/workflow/__init__.py +17 -13
  379. agno/workflow/{v2/condition.py → condition.py} +135 -32
  380. agno/workflow/{v2/loop.py → loop.py} +115 -28
  381. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  382. agno/workflow/{v2/router.py → router.py} +133 -32
  383. agno/workflow/{v2/step.py → step.py} +207 -49
  384. agno/workflow/{v2/steps.py → steps.py} +147 -66
  385. agno/workflow/types.py +482 -0
  386. agno/workflow/workflow.py +2410 -696
  387. agno-2.0.0.dist-info/METADATA +494 -0
  388. agno-2.0.0.dist-info/RECORD +515 -0
  389. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  390. agno/agent/metrics.py +0 -110
  391. agno/api/app.py +0 -35
  392. agno/api/playground.py +0 -92
  393. agno/api/schemas/app.py +0 -12
  394. agno/api/schemas/playground.py +0 -22
  395. agno/api/schemas/user.py +0 -35
  396. agno/api/schemas/workspace.py +0 -46
  397. agno/api/user.py +0 -160
  398. agno/api/workflows.py +0 -33
  399. agno/api/workspace.py +0 -175
  400. agno/app/agui/__init__.py +0 -3
  401. agno/app/agui/app.py +0 -17
  402. agno/app/agui/sync_router.py +0 -120
  403. agno/app/base.py +0 -186
  404. agno/app/discord/__init__.py +0 -3
  405. agno/app/fastapi/__init__.py +0 -3
  406. agno/app/fastapi/app.py +0 -107
  407. agno/app/fastapi/async_router.py +0 -457
  408. agno/app/fastapi/sync_router.py +0 -448
  409. agno/app/playground/app.py +0 -228
  410. agno/app/playground/async_router.py +0 -1053
  411. agno/app/playground/deploy.py +0 -249
  412. agno/app/playground/operator.py +0 -183
  413. agno/app/playground/schemas.py +0 -223
  414. agno/app/playground/serve.py +0 -55
  415. agno/app/playground/sync_router.py +0 -1045
  416. agno/app/playground/utils.py +0 -46
  417. agno/app/settings.py +0 -15
  418. agno/app/slack/__init__.py +0 -3
  419. agno/app/slack/app.py +0 -19
  420. agno/app/slack/sync_router.py +0 -92
  421. agno/app/utils.py +0 -54
  422. agno/app/whatsapp/__init__.py +0 -3
  423. agno/app/whatsapp/app.py +0 -15
  424. agno/app/whatsapp/sync_router.py +0 -197
  425. agno/cli/auth_server.py +0 -249
  426. agno/cli/config.py +0 -274
  427. agno/cli/console.py +0 -88
  428. agno/cli/credentials.py +0 -23
  429. agno/cli/entrypoint.py +0 -571
  430. agno/cli/operator.py +0 -357
  431. agno/cli/settings.py +0 -96
  432. agno/cli/ws/ws_cli.py +0 -817
  433. agno/constants.py +0 -13
  434. agno/document/__init__.py +0 -5
  435. agno/document/chunking/semantic.py +0 -45
  436. agno/document/chunking/strategy.py +0 -31
  437. agno/document/reader/__init__.py +0 -5
  438. agno/document/reader/base.py +0 -47
  439. agno/document/reader/docx_reader.py +0 -60
  440. agno/document/reader/gcs/pdf_reader.py +0 -44
  441. agno/document/reader/s3/pdf_reader.py +0 -59
  442. agno/document/reader/s3/text_reader.py +0 -63
  443. agno/document/reader/url_reader.py +0 -59
  444. agno/document/reader/youtube_reader.py +0 -58
  445. agno/embedder/__init__.py +0 -5
  446. agno/embedder/langdb.py +0 -80
  447. agno/embedder/mistral.py +0 -82
  448. agno/embedder/openai.py +0 -78
  449. agno/file/__init__.py +0 -5
  450. agno/file/file.py +0 -16
  451. agno/file/local/csv.py +0 -32
  452. agno/file/local/txt.py +0 -19
  453. agno/infra/app.py +0 -240
  454. agno/infra/base.py +0 -144
  455. agno/infra/context.py +0 -20
  456. agno/infra/db_app.py +0 -52
  457. agno/infra/resource.py +0 -205
  458. agno/infra/resources.py +0 -55
  459. agno/knowledge/agent.py +0 -702
  460. agno/knowledge/arxiv.py +0 -33
  461. agno/knowledge/combined.py +0 -36
  462. agno/knowledge/csv.py +0 -144
  463. agno/knowledge/csv_url.py +0 -124
  464. agno/knowledge/document.py +0 -223
  465. agno/knowledge/docx.py +0 -137
  466. agno/knowledge/firecrawl.py +0 -34
  467. agno/knowledge/gcs/__init__.py +0 -0
  468. agno/knowledge/gcs/base.py +0 -39
  469. agno/knowledge/gcs/pdf.py +0 -125
  470. agno/knowledge/json.py +0 -137
  471. agno/knowledge/langchain.py +0 -71
  472. agno/knowledge/light_rag.py +0 -273
  473. agno/knowledge/llamaindex.py +0 -66
  474. agno/knowledge/markdown.py +0 -154
  475. agno/knowledge/pdf.py +0 -164
  476. agno/knowledge/pdf_bytes.py +0 -42
  477. agno/knowledge/pdf_url.py +0 -148
  478. agno/knowledge/s3/__init__.py +0 -0
  479. agno/knowledge/s3/base.py +0 -64
  480. agno/knowledge/s3/pdf.py +0 -33
  481. agno/knowledge/s3/text.py +0 -34
  482. agno/knowledge/text.py +0 -141
  483. agno/knowledge/url.py +0 -46
  484. agno/knowledge/website.py +0 -179
  485. agno/knowledge/wikipedia.py +0 -32
  486. agno/knowledge/youtube.py +0 -35
  487. agno/memory/agent.py +0 -423
  488. agno/memory/classifier.py +0 -104
  489. agno/memory/db/__init__.py +0 -5
  490. agno/memory/db/base.py +0 -42
  491. agno/memory/db/mongodb.py +0 -189
  492. agno/memory/db/postgres.py +0 -203
  493. agno/memory/db/sqlite.py +0 -193
  494. agno/memory/memory.py +0 -22
  495. agno/memory/row.py +0 -36
  496. agno/memory/summarizer.py +0 -201
  497. agno/memory/summary.py +0 -19
  498. agno/memory/team.py +0 -415
  499. agno/memory/v2/__init__.py +0 -2
  500. agno/memory/v2/db/__init__.py +0 -1
  501. agno/memory/v2/db/base.py +0 -42
  502. agno/memory/v2/db/firestore.py +0 -339
  503. agno/memory/v2/db/mongodb.py +0 -196
  504. agno/memory/v2/db/postgres.py +0 -214
  505. agno/memory/v2/db/redis.py +0 -187
  506. agno/memory/v2/db/schema.py +0 -54
  507. agno/memory/v2/db/sqlite.py +0 -209
  508. agno/memory/v2/manager.py +0 -437
  509. agno/memory/v2/memory.py +0 -1097
  510. agno/memory/v2/schema.py +0 -55
  511. agno/memory/v2/summarizer.py +0 -215
  512. agno/memory/workflow.py +0 -38
  513. agno/models/ollama/tools.py +0 -430
  514. agno/models/qwen/__init__.py +0 -5
  515. agno/playground/__init__.py +0 -10
  516. agno/playground/deploy.py +0 -3
  517. agno/playground/playground.py +0 -3
  518. agno/playground/serve.py +0 -3
  519. agno/playground/settings.py +0 -3
  520. agno/reranker/__init__.py +0 -0
  521. agno/run/response.py +0 -467
  522. agno/run/v2/__init__.py +0 -0
  523. agno/run/v2/workflow.py +0 -567
  524. agno/storage/__init__.py +0 -0
  525. agno/storage/agent/__init__.py +0 -0
  526. agno/storage/agent/dynamodb.py +0 -1
  527. agno/storage/agent/json.py +0 -1
  528. agno/storage/agent/mongodb.py +0 -1
  529. agno/storage/agent/postgres.py +0 -1
  530. agno/storage/agent/singlestore.py +0 -1
  531. agno/storage/agent/sqlite.py +0 -1
  532. agno/storage/agent/yaml.py +0 -1
  533. agno/storage/base.py +0 -60
  534. agno/storage/dynamodb.py +0 -673
  535. agno/storage/firestore.py +0 -297
  536. agno/storage/gcs_json.py +0 -261
  537. agno/storage/in_memory.py +0 -234
  538. agno/storage/json.py +0 -237
  539. agno/storage/mongodb.py +0 -328
  540. agno/storage/mysql.py +0 -685
  541. agno/storage/postgres.py +0 -682
  542. agno/storage/redis.py +0 -336
  543. agno/storage/session/__init__.py +0 -16
  544. agno/storage/session/agent.py +0 -64
  545. agno/storage/session/team.py +0 -63
  546. agno/storage/session/v2/__init__.py +0 -5
  547. agno/storage/session/workflow.py +0 -61
  548. agno/storage/singlestore.py +0 -606
  549. agno/storage/sqlite.py +0 -646
  550. agno/storage/workflow/__init__.py +0 -0
  551. agno/storage/workflow/mongodb.py +0 -1
  552. agno/storage/workflow/postgres.py +0 -1
  553. agno/storage/workflow/sqlite.py +0 -1
  554. agno/storage/yaml.py +0 -241
  555. agno/tools/thinking.py +0 -73
  556. agno/utils/defaults.py +0 -57
  557. agno/utils/filesystem.py +0 -39
  558. agno/utils/git.py +0 -52
  559. agno/utils/json_io.py +0 -30
  560. agno/utils/load_env.py +0 -19
  561. agno/utils/py_io.py +0 -19
  562. agno/utils/pyproject.py +0 -18
  563. agno/utils/resource_filter.py +0 -31
  564. agno/workflow/v2/__init__.py +0 -21
  565. agno/workflow/v2/types.py +0 -357
  566. agno/workflow/v2/workflow.py +0 -3313
  567. agno/workspace/__init__.py +0 -0
  568. agno/workspace/config.py +0 -325
  569. agno/workspace/enums.py +0 -6
  570. agno/workspace/helpers.py +0 -52
  571. agno/workspace/operator.py +0 -757
  572. agno/workspace/settings.py +0 -158
  573. agno-1.8.2.dist-info/METADATA +0 -982
  574. agno-1.8.2.dist-info/RECORD +0 -566
  575. agno-1.8.2.dist-info/entry_points.txt +0 -3
  576. agno-1.8.2.dist-info/licenses/LICENSE +0 -375
  577. /agno/{app → db/migrations}/__init__.py +0 -0
  578. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  579. /agno/{cli → integrations}/__init__.py +0 -0
  580. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  581. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  582. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  583. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  584. /agno/{app → os/interfaces}/slack/security.py +0 -0
  585. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  586. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  587. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  588. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  589. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import json
2
3
  import uuid
3
4
  from hashlib import md5
@@ -17,9 +18,9 @@ try:
17
18
  except ImportError:
18
19
  raise ImportError("Weaviate is not installed. Install using 'pip install weaviate-client'.")
19
20
 
20
- from agno.document import Document
21
- from agno.embedder import Embedder
22
- from agno.reranker.base import Reranker
21
+ from agno.knowledge.document import Document
22
+ from agno.knowledge.embedder import Embedder
23
+ from agno.knowledge.reranker.base import Reranker
23
24
  from agno.utils.log import log_debug, log_info, logger
24
25
  from agno.vectordb.base import VectorDb
25
26
  from agno.vectordb.search import SearchType
@@ -62,7 +63,7 @@ class Weaviate(VectorDb):
62
63
 
63
64
  # Embedder setup
64
65
  if embedder is None:
65
- from agno.embedder.openai import OpenAIEmbedder
66
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
66
67
 
67
68
  embedder = OpenAIEmbedder()
68
69
  log_info("Embedder not provided, using OpenAIEmbedder as default.")
@@ -139,6 +140,8 @@ class Weaviate(VectorDb):
139
140
  Property(name="name", data_type=DataType.TEXT),
140
141
  Property(name="content", data_type=DataType.TEXT, tokenization=Tokenization.LOWERCASE),
141
142
  Property(name="meta_data", data_type=DataType.TEXT),
143
+ Property(name="content_id", data_type=DataType.TEXT),
144
+ Property(name="content_hash", data_type=DataType.TEXT),
142
145
  ],
143
146
  vectorizer_config=Configure.Vectorizer.none(),
144
147
  vector_index_config=self.get_vector_index_config(self.vector_index, self.distance),
@@ -154,6 +157,8 @@ class Weaviate(VectorDb):
154
157
  Property(name="name", data_type=DataType.TEXT),
155
158
  Property(name="content", data_type=DataType.TEXT, tokenization=Tokenization.LOWERCASE),
156
159
  Property(name="meta_data", data_type=DataType.TEXT),
160
+ Property(name="content_id", data_type=DataType.TEXT),
161
+ Property(name="content_hash", data_type=DataType.TEXT),
157
162
  ],
158
163
  vectorizer_config=Configure.Vectorizer.none(),
159
164
  vector_index_config=self.get_vector_index_config(self.vector_index, self.distance),
@@ -162,95 +167,14 @@ class Weaviate(VectorDb):
162
167
  finally:
163
168
  await client.close()
164
169
 
165
- def doc_content_changed(self, document: Document, check_existing: Optional[bool] = True) -> Optional[bool]:
166
- """
167
- Check if the content of the document has changed by comparing its UUID.
168
-
169
- Args:
170
- document (Document): Document to check
171
-
172
- Returns:
173
- bool: True if the document content has changed, False otherwise. None on wrong input.
174
- check_existing (bool): If True, check if the document exists before checking if the content changed.
175
- """
176
- if not document or not document.content:
177
- logger.warning("Invalid document: Missing content.")
178
- return None
179
-
180
- if check_existing and document.name and not self.name_exists(document.name):
181
- logger.warning(f"A document by this name does not exist: {document.name}")
182
- return None
183
-
184
- doc_uuid, _ = self._get_doc_uuid(document)
185
-
186
- collection = self.get_client().collections.get(self.collection)
187
- existing_doc = collection.query.fetch_object_by_id(doc_uuid)
188
-
189
- if not existing_doc:
190
- return True
191
- else:
192
- return False
193
-
194
- def doc_delete(self, name: str) -> None:
195
- """
196
- Delete all documents from Weaviate with a specific 'name' property.
197
-
198
- Args:
199
- name (str): Document name to delete.
200
- """
201
- collection = self.get_client().collections.get(self.collection)
202
- filter_expr = Filter.by_property("name").equal(name)
203
-
204
- result = collection.data.delete_many(where=filter_expr)
205
-
206
- log_debug(f"Deleted document by name: '{name}' - {result.successful} documents deleted.")
207
- if result.failed > 0:
208
- logger.warning(
209
- f"Failed to delete (some chunks of) document with name: '{name}' - "
210
- f"Failed {result.failed} out of {result.matches} times. {result.successful} successful deletions."
211
- )
212
-
213
- def doc_exists(self, document: Document) -> bool:
214
- """
215
- Validate if the document exists using consistent UUID generation.
216
-
217
- Args:
218
- document (Document): Document to validate
219
-
220
- Returns:
221
- bool: True if the document exists, False otherwise
222
- """
223
- if not document or not document.content:
224
- logger.warning("Invalid document: Missing content.")
225
- return False # Early exit for invalid input
226
-
227
- doc_uuid, _ = self._get_doc_uuid(document)
228
-
170
+ def content_hash_exists(self, content_hash: str) -> bool:
171
+ """Check if a document with the given content hash exists in the collection."""
229
172
  collection = self.get_client().collections.get(self.collection)
230
- return collection.data.exists(doc_uuid)
231
-
232
- async def async_doc_exists(self, document: Document) -> bool:
233
- """
234
- Validate if the document exists using consistent UUID generation asynchronously.
235
-
236
- Args:
237
- document (Document): Document to validate
238
-
239
- Returns:
240
- bool: True if the document exists, False otherwise
241
- """
242
- if not document or not document.content:
243
- logger.warning("Invalid document: Missing content.")
244
- return False # Early exit for invalid input
245
-
246
- doc_uuid, _ = self._get_doc_uuid(document)
247
-
248
- client = await self.get_async_client()
249
- try:
250
- collection = client.collections.get(self.collection)
251
- return await collection.data.exists(doc_uuid)
252
- finally:
253
- await client.close()
173
+ result = collection.query.fetch_objects(
174
+ limit=1,
175
+ filters=Filter.by_property("content_hash").equal(content_hash),
176
+ )
177
+ return len(result.objects) > 0
254
178
 
255
179
  def name_exists(self, name: str) -> bool:
256
180
  """
@@ -290,7 +214,7 @@ class Weaviate(VectorDb):
290
214
  finally:
291
215
  await client.close()
292
216
 
293
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
217
+ def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
294
218
  """
295
219
  Insert documents into Weaviate.
296
220
 
@@ -307,7 +231,9 @@ class Weaviate(VectorDb):
307
231
  logger.error(f"Document embedding is None: {document.name}")
308
232
  continue
309
233
 
310
- doc_uuid, cleaned_content = self._get_doc_uuid(document)
234
+ cleaned_content = document.content.replace("\x00", "\ufffd")
235
+ record_id = md5(cleaned_content.encode()).hexdigest()
236
+ doc_uuid = uuid.UUID(hex=record_id[:32])
311
237
 
312
238
  # Merge filters with metadata
313
239
  meta_data = document.meta_data or {}
@@ -322,13 +248,17 @@ class Weaviate(VectorDb):
322
248
  "name": document.name,
323
249
  "content": cleaned_content,
324
250
  "meta_data": meta_data_str,
251
+ "content_id": document.content_id,
252
+ "content_hash": content_hash,
325
253
  },
326
254
  vector=document.embedding,
327
255
  uuid=doc_uuid,
328
256
  )
329
257
  log_debug(f"Inserted document: {document.name} ({meta_data})")
330
258
 
331
- async def async_insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
259
+ async def async_insert(
260
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
261
+ ) -> None:
332
262
  """
333
263
  Insert documents into Weaviate asynchronously.
334
264
 
@@ -340,6 +270,10 @@ class Weaviate(VectorDb):
340
270
  if not documents:
341
271
  return
342
272
 
273
+ # Embed document
274
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
275
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
276
+
343
277
  client = await self.get_async_client()
344
278
  try:
345
279
  collection = client.collections.get(self.collection)
@@ -347,14 +281,14 @@ class Weaviate(VectorDb):
347
281
  # Process documents first
348
282
  for document in documents:
349
283
  try:
350
- # Embed document
351
- document.embed(embedder=self.embedder)
352
284
  if document.embedding is None:
353
285
  logger.error(f"Document embedding is None: {document.name}")
354
286
  continue
355
287
 
356
288
  # Clean content and generate UUID
357
- doc_uuid, cleaned_content = self._get_doc_uuid(document)
289
+ cleaned_content = document.content.replace("\x00", "\ufffd")
290
+ record_id = md5(cleaned_content.encode()).hexdigest()
291
+ doc_uuid = uuid.UUID(hex=record_id[:32])
358
292
 
359
293
  # Serialize meta_data to JSON string
360
294
  meta_data_str = json.dumps(document.meta_data) if document.meta_data else None
@@ -364,6 +298,8 @@ class Weaviate(VectorDb):
364
298
  "name": document.name,
365
299
  "content": cleaned_content,
366
300
  "meta_data": meta_data_str,
301
+ "content_id": document.content_id,
302
+ "content_hash": content_hash,
367
303
  }
368
304
 
369
305
  # Use the API correctly - properties, vector and uuid are separate parameters
@@ -376,7 +312,7 @@ class Weaviate(VectorDb):
376
312
  finally:
377
313
  await client.close()
378
314
 
379
- def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
315
+ def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
380
316
  """
381
317
  Upsert documents into Weaviate.
382
318
 
@@ -385,30 +321,13 @@ class Weaviate(VectorDb):
385
321
  filters (Optional[Dict[str, Any]]): Filters to apply while upserting
386
322
  """
387
323
  log_debug(f"Upserting {len(documents)} documents into Weaviate.")
324
+ if self.content_hash_exists(content_hash):
325
+ self._delete_by_content_hash(content_hash)
326
+ self.insert(content_hash=content_hash, documents=documents, filters=filters)
388
327
 
389
- _docs_to_insert = []
390
- for document in documents:
391
- assert document.name is not None, "Document name must be set for upsert operation."
392
-
393
- if self.name_exists(document.name):
394
- if self.doc_content_changed(document, check_existing=False):
395
- log_debug(
396
- f"Document already exists, but content changed. Document will be deleted and added again: {document.name}"
397
- )
398
-
399
- is_first_or_only_chunk = ("chunk" in document.meta_data and document.meta_data["chunk"] == 1) or (
400
- "chunk" not in document.meta_data
401
- )
402
- if is_first_or_only_chunk:
403
- self.doc_delete(document.name)
404
- _docs_to_insert.append(document)
405
- else:
406
- log_debug(f"Document skipped, content is unchanged: {document.name}")
407
- else:
408
- _docs_to_insert.append(document)
409
- self.insert(_docs_to_insert)
410
-
411
- async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
328
+ async def async_upsert(
329
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
330
+ ) -> None:
412
331
  """
413
332
  Upsert documents into Weaviate asynchronously.
414
333
  When documents with the same ID already exist, they will be replaced.
@@ -418,37 +337,10 @@ class Weaviate(VectorDb):
418
337
  documents (List[Document]): List of documents to upsert
419
338
  filters (Optional[Dict[str, Any]]): Filters to apply while upserting
420
339
  """
421
- if not documents:
422
- return
423
-
424
- log_debug(f"Upserting {len(documents)} documents into Weaviate asynchronously.")
425
-
426
- client = await self.get_async_client()
427
- try:
428
- collection = client.collections.get(self.collection)
429
-
430
- for document in documents:
431
- document.embed(embedder=self.embedder)
432
- if document.embedding is None:
433
- logger.error(f"Document embedding is None: {document.name}")
434
- continue
435
-
436
- doc_uuid, cleaned_content = self._get_doc_uuid(document)
437
-
438
- # Serialize meta_data to JSON string
439
- meta_data_str = json.dumps(document.meta_data) if document.meta_data else None
440
-
441
- properties = {
442
- "name": document.name,
443
- "content": cleaned_content,
444
- "meta_data": meta_data_str,
445
- }
446
-
447
- await collection.data.replace(uuid=doc_uuid, properties=properties, vector=document.embedding)
448
-
449
- log_debug(f"Upserted document asynchronously: {document.name}")
450
- finally:
451
- await client.close()
340
+ if self.content_hash_exists(content_hash):
341
+ self._delete_by_content_hash(content_hash)
342
+ await self.async_insert(content_hash=content_hash, documents=documents, filters=filters)
343
+ return
452
344
 
453
345
  def search(self, query: str, limit: int = 5, filters: Optional[Dict[str, Any]] = None) -> List[Document]:
454
346
  """
@@ -509,7 +401,7 @@ class Weaviate(VectorDb):
509
401
  response = collection.query.near_vector(
510
402
  near_vector=query_embedding,
511
403
  limit=limit,
512
- return_properties=["name", "content", "meta_data"],
404
+ return_properties=["name", "content", "meta_data", "content_id"],
513
405
  include_vector=True,
514
406
  filters=filter_expr,
515
407
  )
@@ -557,7 +449,7 @@ class Weaviate(VectorDb):
557
449
  response = await collection.query.near_vector(
558
450
  near_vector=query_embedding,
559
451
  limit=limit,
560
- return_properties=["name", "content", "meta_data"],
452
+ return_properties=["name", "content", "meta_data", "content_id"],
561
453
  include_vector=True,
562
454
  filters=filter_expr,
563
455
  )
@@ -585,7 +477,7 @@ class Weaviate(VectorDb):
585
477
  query=query,
586
478
  query_properties=["content"],
587
479
  limit=limit,
588
- return_properties=["name", "content", "meta_data"],
480
+ return_properties=["name", "content", "meta_data", "content_id"],
589
481
  include_vector=True,
590
482
  filters=filter_expr,
591
483
  )
@@ -629,7 +521,7 @@ class Weaviate(VectorDb):
629
521
  query=query,
630
522
  query_properties=["content"],
631
523
  limit=limit,
632
- return_properties=["name", "content", "meta_data"],
524
+ return_properties=["name", "content", "meta_data", "content_id"],
633
525
  include_vector=True,
634
526
  filters=filter_expr,
635
527
  )
@@ -662,7 +554,7 @@ class Weaviate(VectorDb):
662
554
  query=query,
663
555
  vector=query_embedding,
664
556
  limit=limit,
665
- return_properties=["name", "content", "meta_data"],
557
+ return_properties=["name", "content", "meta_data", "content_id"],
666
558
  include_vector=True,
667
559
  query_properties=["content"],
668
560
  alpha=self.hybrid_search_alpha,
@@ -713,7 +605,7 @@ class Weaviate(VectorDb):
713
605
  query=query,
714
606
  vector=query_embedding,
715
607
  limit=limit,
716
- return_properties=["name", "content", "meta_data"],
608
+ return_properties=["name", "content", "meta_data", "content_id"],
717
609
  include_vector=True,
718
610
  query_properties=["content"],
719
611
  alpha=self.hybrid_search_alpha,
@@ -771,6 +663,86 @@ class Weaviate(VectorDb):
771
663
  self.drop()
772
664
  return True
773
665
 
666
+ def delete_by_id(self, id: str) -> bool:
667
+ """Delete document by ID."""
668
+ try:
669
+ try:
670
+ doc_uuid = uuid.UUID(hex=id[:32]) if len(id) == 32 else uuid.UUID(id)
671
+ except ValueError:
672
+ log_info(f"Invalid UUID format for ID '{id}' - treating as non-existent")
673
+ return True
674
+
675
+ collection = self.get_client().collections.get(self.collection)
676
+
677
+ if not collection.data.exists(doc_uuid):
678
+ log_info(f"Document with ID {id} does not exist")
679
+ return True
680
+
681
+ collection.data.delete_by_id(doc_uuid)
682
+ log_info(f"Deleted document with ID '{id}' from collection '{self.collection}'.")
683
+ return True
684
+ except Exception as e:
685
+ logger.error(f"Error deleting document by ID '{id}': {e}")
686
+ return False
687
+
688
+ def delete_by_name(self, name: str) -> bool:
689
+ """Delete content by name using direct filter deletion."""
690
+ try:
691
+ collection = self.get_client().collections.get(self.collection)
692
+
693
+ collection.data.delete_many(where=Filter.by_property("name").equal(name))
694
+
695
+ log_info(f"Deleted documents with name '{name}' from collection '{self.collection}'.")
696
+ return True
697
+
698
+ except Exception as e:
699
+ logger.error(f"Error deleting documents by name '{name}': {e}")
700
+ return False
701
+
702
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
703
+ """Delete content by metadata using direct filter deletion."""
704
+ try:
705
+ collection = self.get_client().collections.get(self.collection)
706
+
707
+ # Build filter for metadata search
708
+ filter_expr = self._build_filter_expression(metadata)
709
+ if filter_expr is None:
710
+ log_info(f"No valid filter could be built for metadata: {metadata}")
711
+ return False
712
+
713
+ collection.data.delete_many(where=filter_expr)
714
+
715
+ log_info(f"Deleted documents with metadata '{metadata}' from collection '{self.collection}'.")
716
+ return True
717
+
718
+ except Exception as e:
719
+ logger.error(f"Error deleting documents by metadata '{metadata}': {e}")
720
+ return False
721
+
722
+ def delete_by_content_id(self, content_id: str) -> bool:
723
+ """Delete content by content ID using direct filter deletion."""
724
+ try:
725
+ collection = self.get_client().collections.get(self.collection)
726
+
727
+ collection.data.delete_many(where=Filter.by_property("content_id").equal(content_id))
728
+
729
+ log_info(f"Deleted documents with content_id '{content_id}' from collection '{self.collection}'.")
730
+ return True
731
+
732
+ except Exception as e:
733
+ logger.error(f"Error deleting documents by content_id '{content_id}': {e}")
734
+ return False
735
+
736
+ def delete_by_content_hash(self, content_hash: str) -> bool:
737
+ """Delete content by content hash using direct filter deletion."""
738
+ try:
739
+ collection = self.get_client().collections.get(self.collection)
740
+ collection.data.delete_many(where=Filter.by_property("content_hash").equal(content_hash))
741
+ return True
742
+ except Exception as e:
743
+ logger.error(f"Error deleting documents by content_hash '{content_hash}': {e}")
744
+ return False
745
+
774
746
  def get_vector_index_config(self, index_type: VectorIndex, distance_metric: Distance):
775
747
  """
776
748
  Returns the appropriate vector index configuration with the specified distance metric.
@@ -807,17 +779,17 @@ class Weaviate(VectorDb):
807
779
  search_results: List[Document] = []
808
780
  for obj in response.objects:
809
781
  properties = obj.properties
810
- meta_data = json.loads(properties["meta_data"]) if properties.get("meta_data") else None
782
+ meta_data = json.loads(properties["meta_data"]) if properties.get("meta_data") else {}
811
783
  embedding = obj.vector["default"] if isinstance(obj.vector, dict) else obj.vector
812
784
 
813
785
  search_results.append(
814
786
  Document(
815
- name=properties["name"],
816
- meta_data=meta_data if meta_data else {},
817
- content=properties["content"],
787
+ name=properties.get("name"),
788
+ meta_data=meta_data,
789
+ content=properties.get("content", ""),
818
790
  embedder=self.embedder,
819
791
  embedding=embedding,
820
- usage=None,
792
+ content_id=properties.get("content_id"),
821
793
  )
822
794
  )
823
795
 
@@ -827,7 +799,7 @@ class Weaviate(VectorDb):
827
799
  """Indicate that upsert functionality is available."""
828
800
  return True
829
801
 
830
- def _build_filter_expression(self, filters: Optional[Dict[str, Any]]) -> Optional[Filter]:
802
+ def _build_filter_expression(self, filters: Optional[Dict[str, Any]]):
831
803
  """
832
804
  Build a filter expression for Weaviate queries.
833
805
 
@@ -870,3 +842,93 @@ class Weaviate(VectorDb):
870
842
  return None
871
843
 
872
844
  return None
845
+
846
+ def id_exists(self, id: str) -> bool:
847
+ """Check if a document with the given ID exists in the collection.
848
+
849
+ Args:
850
+ id (str): The document ID to check.
851
+
852
+ Returns:
853
+ bool: True if the document exists, False otherwise.
854
+ """
855
+ try:
856
+ doc_uuid = uuid.UUID(hex=id[:32]) if len(id) == 32 else uuid.UUID(id)
857
+ collection = self.get_client().collections.get(self.collection)
858
+ return collection.data.exists(doc_uuid)
859
+ except ValueError:
860
+ log_info(f"Invalid UUID format for ID '{id}' - treating as non-existent")
861
+ return False
862
+ except Exception as e:
863
+ logger.error(f"Error checking if ID '{id}' exists: {e}")
864
+ return False
865
+
866
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
867
+ """
868
+ Update the metadata for documents with the given content_id.
869
+
870
+ Args:
871
+ content_id (str): The content ID to update
872
+ metadata (Dict[str, Any]): The metadata to update
873
+ """
874
+ try:
875
+ weaviate_client = self.get_client()
876
+ collection = weaviate_client.collections.get(self.collection)
877
+
878
+ # Query for objects with the given content_id
879
+ query_result = collection.query.fetch_objects( # type: ignore
880
+ where=Filter.by_property("content_id").equal(content_id),
881
+ limit=1000, # Get all matching objects
882
+ )
883
+
884
+ if not query_result.objects:
885
+ logger.debug(f"No documents found with content_id: {content_id}")
886
+ return
887
+
888
+ # Update each matching object
889
+ updated_count = 0
890
+ for obj in query_result.objects:
891
+ # Get current properties
892
+ current_properties = obj.properties or {}
893
+
894
+ # Merge existing metadata with new metadata
895
+ updated_properties = current_properties.copy()
896
+
897
+ # Handle nested metadata updates
898
+ if "meta_data" in updated_properties and isinstance(updated_properties["meta_data"], dict):
899
+ updated_properties["meta_data"].update(metadata)
900
+ else:
901
+ # If no existing meta_data or it's not a dict, set it directly
902
+ updated_properties["meta_data"] = metadata
903
+
904
+ if "filters" in updated_properties and isinstance(updated_properties["filters"], dict):
905
+ updated_properties["filters"].update(metadata)
906
+ else:
907
+ updated_properties["filters"] = metadata
908
+
909
+ # Update the object
910
+ collection.data.update(uuid=obj.uuid, properties=updated_properties)
911
+ updated_count += 1
912
+
913
+ logger.debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
914
+
915
+ except Exception as e:
916
+ logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
917
+ raise
918
+
919
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
920
+ """Delete documents by content hash using direct filter deletion."""
921
+ try:
922
+ collection = self.get_client().collections.get(self.collection)
923
+
924
+ # Build filter for content_hash search
925
+ filter_expr = Filter.by_property("content_hash").equal(content_hash)
926
+
927
+ collection.data.delete_many(where=filter_expr)
928
+
929
+ log_info(f"Deleted documents with content_hash '{content_hash}' from collection '{self.collection}'.")
930
+ return True
931
+
932
+ except Exception as e:
933
+ logger.error(f"Error deleting documents by content_hash '{content_hash}': {e}")
934
+ return False
agno/workflow/__init__.py CHANGED
@@ -1,17 +1,21 @@
1
- from agno.run.workflow import (
2
- RunEvent,
3
- WorkflowCompletedEvent,
4
- WorkflowRunResponseEvent,
5
- WorkflowRunResponseStartedEvent,
6
- )
7
- from agno.workflow.workflow import RunResponse, Workflow, WorkflowSession
1
+ from agno.workflow.condition import Condition
2
+ from agno.workflow.loop import Loop
3
+ from agno.workflow.parallel import Parallel
4
+ from agno.workflow.router import Router
5
+ from agno.workflow.step import Step
6
+ from agno.workflow.steps import Steps
7
+ from agno.workflow.types import StepInput, StepOutput, WorkflowExecutionInput
8
+ from agno.workflow.workflow import Workflow
8
9
 
9
10
  __all__ = [
10
- "RunEvent",
11
- "RunResponse",
12
11
  "Workflow",
13
- "WorkflowSession",
14
- "WorkflowRunResponseEvent",
15
- "WorkflowRunResponseStartedEvent",
16
- "WorkflowCompletedEvent",
12
+ "Steps",
13
+ "Step",
14
+ "Loop",
15
+ "Parallel",
16
+ "Condition",
17
+ "Router",
18
+ "WorkflowExecutionInput",
19
+ "StepInput",
20
+ "StepOutput",
17
21
  ]