agno 1.8.1__py3-none-any.whl → 2.0.0a1__py3-none-any.whl

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