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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3181 -4169
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  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 +11 -66
  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 +1743 -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 +1432 -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 +882 -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 +1045 -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 +1411 -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 +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -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 +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -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 +15 -11
  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 +131 -131
  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 +45 -150
  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 +489 -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 +77 -33
  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 +32 -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 +29 -0
  184. agno/os/mcp.py +255 -0
  185. agno/os/router.py +869 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +208 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +436 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +188 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +60 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +168 -0
  202. agno/os/schema.py +892 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/{response.py → agent.py} +231 -74
  213. agno/run/base.py +44 -58
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +133 -77
  216. agno/run/workflow.py +537 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +2960 -4252
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +42 -22
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +18 -13
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +18 -11
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +16 -7
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +61 -61
  253. agno/tools/eleven_labs.py +35 -28
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +29 -29
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +22 -10
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +31 -19
  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 +32 -14
  281. agno/tools/models/gemini.py +58 -31
  282. agno/tools/models/groq.py +29 -20
  283. agno/tools/models/nebius.py +27 -11
  284. agno/tools/models_labs.py +39 -15
  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 +57 -26
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +62 -46
  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 +54 -41
  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 +95 -118
  334. agno/utils/gemini.py +31 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +2 -2
  337. agno/utils/mcp.py +11 -5
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/claude.py +55 -4
  341. agno/utils/models/mistral.py +8 -7
  342. agno/utils/models/schema_utils.py +3 -3
  343. agno/utils/pprint.py +33 -32
  344. agno/utils/print_response/agent.py +779 -0
  345. agno/utils/print_response/team.py +1565 -0
  346. agno/utils/print_response/workflow.py +1451 -0
  347. agno/utils/prompts.py +14 -14
  348. agno/utils/reasoning.py +87 -0
  349. agno/utils/response.py +42 -42
  350. agno/utils/streamlit.py +454 -0
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +334 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2401 -696
  383. agno-2.0.0rc1.dist-info/METADATA +355 -0
  384. agno-2.0.0rc1.dist-info/RECORD +516 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -702
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.1.dist-info/METADATA +0 -982
  568. agno-1.8.1.dist-info/RECORD +0 -566
  569. agno-1.8.1.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.1.dist-info → agno-2.0.0rc1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.1.dist-info → agno-2.0.0rc1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.1.dist-info → agno-2.0.0rc1.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
  ]