agno 1.8.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (589) hide show
  1. agno/agent/__init__.py +19 -27
  2. agno/agent/agent.py +3143 -4170
  3. agno/api/agent.py +11 -67
  4. agno/api/api.py +5 -46
  5. agno/api/evals.py +8 -19
  6. agno/api/os.py +17 -0
  7. agno/api/routes.py +6 -41
  8. agno/api/schemas/__init__.py +9 -0
  9. agno/api/schemas/agent.py +5 -21
  10. agno/api/schemas/evals.py +7 -16
  11. agno/api/schemas/os.py +14 -0
  12. agno/api/schemas/team.py +5 -21
  13. agno/api/schemas/utils.py +21 -0
  14. agno/api/schemas/workflows.py +11 -7
  15. agno/api/settings.py +53 -0
  16. agno/api/team.py +11 -66
  17. agno/api/workflow.py +28 -0
  18. agno/cloud/aws/base.py +214 -0
  19. agno/cloud/aws/s3/__init__.py +2 -0
  20. agno/cloud/aws/s3/api_client.py +43 -0
  21. agno/cloud/aws/s3/bucket.py +195 -0
  22. agno/cloud/aws/s3/object.py +57 -0
  23. agno/db/__init__.py +24 -0
  24. agno/db/base.py +245 -0
  25. agno/db/dynamo/__init__.py +3 -0
  26. agno/db/dynamo/dynamo.py +1743 -0
  27. agno/db/dynamo/schemas.py +278 -0
  28. agno/db/dynamo/utils.py +684 -0
  29. agno/db/firestore/__init__.py +3 -0
  30. agno/db/firestore/firestore.py +1432 -0
  31. agno/db/firestore/schemas.py +130 -0
  32. agno/db/firestore/utils.py +278 -0
  33. agno/db/gcs_json/__init__.py +3 -0
  34. agno/db/gcs_json/gcs_json_db.py +1001 -0
  35. agno/db/gcs_json/utils.py +194 -0
  36. agno/db/in_memory/__init__.py +3 -0
  37. agno/db/in_memory/in_memory_db.py +882 -0
  38. agno/db/in_memory/utils.py +172 -0
  39. agno/db/json/__init__.py +3 -0
  40. agno/db/json/json_db.py +1045 -0
  41. agno/db/json/utils.py +196 -0
  42. agno/db/migrations/v1_to_v2.py +162 -0
  43. agno/db/mongo/__init__.py +3 -0
  44. agno/db/mongo/mongo.py +1416 -0
  45. agno/db/mongo/schemas.py +77 -0
  46. agno/db/mongo/utils.py +204 -0
  47. agno/db/mysql/__init__.py +3 -0
  48. agno/db/mysql/mysql.py +1719 -0
  49. agno/db/mysql/schemas.py +124 -0
  50. agno/db/mysql/utils.py +297 -0
  51. agno/db/postgres/__init__.py +3 -0
  52. agno/db/postgres/postgres.py +1710 -0
  53. agno/db/postgres/schemas.py +124 -0
  54. agno/db/postgres/utils.py +280 -0
  55. agno/db/redis/__init__.py +3 -0
  56. agno/db/redis/redis.py +1367 -0
  57. agno/db/redis/schemas.py +109 -0
  58. agno/db/redis/utils.py +288 -0
  59. agno/db/schemas/__init__.py +3 -0
  60. agno/db/schemas/evals.py +33 -0
  61. agno/db/schemas/knowledge.py +40 -0
  62. agno/db/schemas/memory.py +46 -0
  63. agno/db/singlestore/__init__.py +3 -0
  64. agno/db/singlestore/schemas.py +116 -0
  65. agno/db/singlestore/singlestore.py +1712 -0
  66. agno/db/singlestore/utils.py +326 -0
  67. agno/db/sqlite/__init__.py +3 -0
  68. agno/db/sqlite/schemas.py +119 -0
  69. agno/db/sqlite/sqlite.py +1676 -0
  70. agno/db/sqlite/utils.py +268 -0
  71. agno/db/utils.py +88 -0
  72. agno/eval/__init__.py +14 -0
  73. agno/eval/accuracy.py +154 -48
  74. agno/eval/performance.py +88 -23
  75. agno/eval/reliability.py +73 -20
  76. agno/eval/utils.py +23 -13
  77. agno/integrations/discord/__init__.py +3 -0
  78. agno/{app → integrations}/discord/client.py +10 -10
  79. agno/knowledge/__init__.py +2 -2
  80. agno/{document → knowledge}/chunking/agentic.py +2 -2
  81. agno/{document → knowledge}/chunking/document.py +2 -2
  82. agno/{document → knowledge}/chunking/fixed.py +3 -3
  83. agno/{document → knowledge}/chunking/markdown.py +2 -2
  84. agno/{document → knowledge}/chunking/recursive.py +2 -2
  85. agno/{document → knowledge}/chunking/row.py +2 -2
  86. agno/knowledge/chunking/semantic.py +59 -0
  87. agno/knowledge/chunking/strategy.py +121 -0
  88. agno/knowledge/content.py +74 -0
  89. agno/knowledge/document/__init__.py +5 -0
  90. agno/{document → knowledge/document}/base.py +12 -2
  91. agno/knowledge/embedder/__init__.py +5 -0
  92. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  93. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  94. agno/{embedder → knowledge/embedder}/base.py +6 -0
  95. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  96. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  97. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  98. agno/{embedder → knowledge/embedder}/google.py +74 -1
  99. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  100. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  101. agno/knowledge/embedder/langdb.py +22 -0
  102. agno/knowledge/embedder/mistral.py +139 -0
  103. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  104. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  105. agno/knowledge/embedder/openai.py +223 -0
  106. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  107. agno/{embedder → knowledge/embedder}/together.py +1 -1
  108. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  109. agno/knowledge/knowledge.py +1551 -0
  110. agno/knowledge/reader/__init__.py +7 -0
  111. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  112. agno/knowledge/reader/base.py +88 -0
  113. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  114. agno/knowledge/reader/docx_reader.py +83 -0
  115. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  116. agno/{document → knowledge}/reader/json_reader.py +30 -9
  117. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  118. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  119. agno/knowledge/reader/reader_factory.py +268 -0
  120. agno/knowledge/reader/s3_reader.py +101 -0
  121. agno/{document → knowledge}/reader/text_reader.py +31 -10
  122. agno/knowledge/reader/url_reader.py +128 -0
  123. agno/knowledge/reader/web_search_reader.py +366 -0
  124. agno/{document → knowledge}/reader/website_reader.py +37 -10
  125. agno/knowledge/reader/wikipedia_reader.py +59 -0
  126. agno/knowledge/reader/youtube_reader.py +78 -0
  127. agno/knowledge/remote_content/remote_content.py +88 -0
  128. agno/{reranker → knowledge/reranker}/base.py +1 -1
  129. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  130. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  131. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  132. agno/knowledge/types.py +30 -0
  133. agno/knowledge/utils.py +169 -0
  134. agno/media.py +269 -268
  135. agno/memory/__init__.py +2 -10
  136. agno/memory/manager.py +1003 -148
  137. agno/models/aimlapi/__init__.py +2 -2
  138. agno/models/aimlapi/aimlapi.py +6 -6
  139. agno/models/anthropic/claude.py +128 -72
  140. agno/models/aws/bedrock.py +107 -175
  141. agno/models/aws/claude.py +64 -18
  142. agno/models/azure/ai_foundry.py +73 -23
  143. agno/models/base.py +346 -290
  144. agno/models/cerebras/cerebras.py +84 -27
  145. agno/models/cohere/chat.py +106 -98
  146. agno/models/google/gemini.py +105 -46
  147. agno/models/groq/groq.py +97 -35
  148. agno/models/huggingface/huggingface.py +92 -27
  149. agno/models/ibm/watsonx.py +72 -13
  150. agno/models/litellm/chat.py +85 -13
  151. agno/models/message.py +46 -151
  152. agno/models/meta/llama.py +85 -49
  153. agno/models/metrics.py +120 -0
  154. agno/models/mistral/mistral.py +90 -21
  155. agno/models/ollama/__init__.py +0 -2
  156. agno/models/ollama/chat.py +85 -47
  157. agno/models/openai/chat.py +154 -37
  158. agno/models/openai/responses.py +178 -105
  159. agno/models/perplexity/perplexity.py +26 -2
  160. agno/models/portkey/portkey.py +0 -7
  161. agno/models/response.py +15 -9
  162. agno/models/utils.py +20 -0
  163. agno/models/vercel/__init__.py +2 -2
  164. agno/models/vercel/v0.py +1 -1
  165. agno/models/vllm/__init__.py +2 -2
  166. agno/models/vllm/vllm.py +3 -3
  167. agno/models/xai/xai.py +10 -10
  168. agno/os/__init__.py +3 -0
  169. agno/os/app.py +497 -0
  170. agno/os/auth.py +47 -0
  171. agno/os/config.py +103 -0
  172. agno/os/interfaces/agui/__init__.py +3 -0
  173. agno/os/interfaces/agui/agui.py +31 -0
  174. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  175. agno/{app → os/interfaces}/agui/utils.py +65 -28
  176. agno/os/interfaces/base.py +21 -0
  177. agno/os/interfaces/slack/__init__.py +3 -0
  178. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  179. agno/os/interfaces/slack/slack.py +32 -0
  180. agno/os/interfaces/whatsapp/__init__.py +3 -0
  181. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  182. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  183. agno/os/mcp.py +235 -0
  184. agno/os/router.py +1400 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +393 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +850 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +410 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +178 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +536 -0
  201. agno/os/schema.py +945 -0
  202. agno/{app/playground → os}/settings.py +7 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/agent.py +633 -0
  212. agno/run/base.py +53 -77
  213. agno/run/cancel.py +81 -0
  214. agno/run/team.py +243 -96
  215. agno/run/workflow.py +550 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +3260 -4824
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +43 -23
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +20 -17
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +22 -12
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +17 -8
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +62 -62
  252. agno/tools/eleven_labs.py +36 -29
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +30 -30
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +17 -18
  260. agno/tools/function.py +127 -18
  261. agno/tools/giphy.py +23 -11
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +32 -20
  276. agno/tools/mcp.py +1 -2
  277. agno/tools/mem0.py +18 -12
  278. agno/tools/memori.py +14 -10
  279. agno/tools/mlx_transcribe.py +3 -2
  280. agno/tools/models/azure_openai.py +33 -15
  281. agno/tools/models/gemini.py +59 -32
  282. agno/tools/models/groq.py +30 -23
  283. agno/tools/models/nebius.py +28 -12
  284. agno/tools/models_labs.py +40 -16
  285. agno/tools/moviepy_video.py +7 -6
  286. agno/tools/neo4j.py +10 -8
  287. agno/tools/newspaper.py +7 -2
  288. agno/tools/newspaper4k.py +8 -3
  289. agno/tools/openai.py +58 -32
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +63 -47
  292. agno/tools/openweather.py +14 -12
  293. agno/tools/pandas.py +11 -3
  294. agno/tools/postgres.py +4 -12
  295. agno/tools/pubmed.py +4 -1
  296. agno/tools/python.py +9 -22
  297. agno/tools/reasoning.py +35 -27
  298. agno/tools/reddit.py +11 -26
  299. agno/tools/replicate.py +55 -42
  300. agno/tools/resend.py +4 -1
  301. agno/tools/scrapegraph.py +15 -14
  302. agno/tools/searxng.py +10 -23
  303. agno/tools/serpapi.py +6 -3
  304. agno/tools/serper.py +13 -4
  305. agno/tools/shell.py +9 -2
  306. agno/tools/slack.py +12 -11
  307. agno/tools/sleep.py +3 -2
  308. agno/tools/spider.py +24 -4
  309. agno/tools/sql.py +7 -6
  310. agno/tools/tavily.py +6 -4
  311. agno/tools/telegram.py +12 -4
  312. agno/tools/todoist.py +11 -31
  313. agno/tools/toolkit.py +1 -1
  314. agno/tools/trafilatura.py +22 -6
  315. agno/tools/trello.py +9 -22
  316. agno/tools/twilio.py +10 -3
  317. agno/tools/user_control_flow.py +6 -1
  318. agno/tools/valyu.py +34 -5
  319. agno/tools/visualization.py +19 -28
  320. agno/tools/webbrowser.py +4 -3
  321. agno/tools/webex.py +11 -7
  322. agno/tools/website.py +15 -46
  323. agno/tools/webtools.py +12 -4
  324. agno/tools/whatsapp.py +5 -9
  325. agno/tools/wikipedia.py +20 -13
  326. agno/tools/x.py +14 -13
  327. agno/tools/yfinance.py +13 -40
  328. agno/tools/youtube.py +26 -20
  329. agno/tools/zendesk.py +7 -2
  330. agno/tools/zep.py +10 -7
  331. agno/tools/zoom.py +10 -9
  332. agno/utils/common.py +1 -19
  333. agno/utils/events.py +100 -123
  334. agno/utils/gemini.py +1 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +54 -4
  337. agno/utils/mcp.py +68 -10
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/aws_claude.py +1 -1
  341. agno/utils/models/claude.py +6 -12
  342. agno/utils/models/cohere.py +1 -1
  343. agno/utils/models/mistral.py +8 -7
  344. agno/utils/models/schema_utils.py +3 -3
  345. agno/utils/models/watsonx.py +1 -1
  346. agno/utils/openai.py +1 -1
  347. agno/utils/pprint.py +33 -32
  348. agno/utils/print_response/agent.py +779 -0
  349. agno/utils/print_response/team.py +1669 -0
  350. agno/utils/print_response/workflow.py +1451 -0
  351. agno/utils/prompts.py +14 -14
  352. agno/utils/reasoning.py +87 -0
  353. agno/utils/response.py +42 -42
  354. agno/utils/streamlit.py +481 -0
  355. agno/utils/string.py +8 -22
  356. agno/utils/team.py +50 -0
  357. agno/utils/timer.py +2 -2
  358. agno/vectordb/base.py +33 -21
  359. agno/vectordb/cassandra/cassandra.py +287 -23
  360. agno/vectordb/chroma/chromadb.py +482 -59
  361. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  362. agno/vectordb/couchbase/couchbase.py +309 -29
  363. agno/vectordb/lancedb/lance_db.py +360 -21
  364. agno/vectordb/langchaindb/__init__.py +5 -0
  365. agno/vectordb/langchaindb/langchaindb.py +145 -0
  366. agno/vectordb/lightrag/__init__.py +5 -0
  367. agno/vectordb/lightrag/lightrag.py +374 -0
  368. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  369. agno/vectordb/milvus/milvus.py +242 -32
  370. agno/vectordb/mongodb/mongodb.py +200 -24
  371. agno/vectordb/pgvector/pgvector.py +319 -37
  372. agno/vectordb/pineconedb/pineconedb.py +221 -27
  373. agno/vectordb/qdrant/qdrant.py +334 -14
  374. agno/vectordb/singlestore/singlestore.py +286 -29
  375. agno/vectordb/surrealdb/surrealdb.py +187 -7
  376. agno/vectordb/upstashdb/upstashdb.py +342 -26
  377. agno/vectordb/weaviate/weaviate.py +227 -165
  378. agno/workflow/__init__.py +17 -13
  379. agno/workflow/{v2/condition.py → condition.py} +135 -32
  380. agno/workflow/{v2/loop.py → loop.py} +115 -28
  381. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  382. agno/workflow/{v2/router.py → router.py} +133 -32
  383. agno/workflow/{v2/step.py → step.py} +207 -49
  384. agno/workflow/{v2/steps.py → steps.py} +147 -66
  385. agno/workflow/types.py +482 -0
  386. agno/workflow/workflow.py +2410 -696
  387. agno-2.0.0.dist-info/METADATA +494 -0
  388. agno-2.0.0.dist-info/RECORD +515 -0
  389. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  390. agno/agent/metrics.py +0 -110
  391. agno/api/app.py +0 -35
  392. agno/api/playground.py +0 -92
  393. agno/api/schemas/app.py +0 -12
  394. agno/api/schemas/playground.py +0 -22
  395. agno/api/schemas/user.py +0 -35
  396. agno/api/schemas/workspace.py +0 -46
  397. agno/api/user.py +0 -160
  398. agno/api/workflows.py +0 -33
  399. agno/api/workspace.py +0 -175
  400. agno/app/agui/__init__.py +0 -3
  401. agno/app/agui/app.py +0 -17
  402. agno/app/agui/sync_router.py +0 -120
  403. agno/app/base.py +0 -186
  404. agno/app/discord/__init__.py +0 -3
  405. agno/app/fastapi/__init__.py +0 -3
  406. agno/app/fastapi/app.py +0 -107
  407. agno/app/fastapi/async_router.py +0 -457
  408. agno/app/fastapi/sync_router.py +0 -448
  409. agno/app/playground/app.py +0 -228
  410. agno/app/playground/async_router.py +0 -1053
  411. agno/app/playground/deploy.py +0 -249
  412. agno/app/playground/operator.py +0 -183
  413. agno/app/playground/schemas.py +0 -223
  414. agno/app/playground/serve.py +0 -55
  415. agno/app/playground/sync_router.py +0 -1045
  416. agno/app/playground/utils.py +0 -46
  417. agno/app/settings.py +0 -15
  418. agno/app/slack/__init__.py +0 -3
  419. agno/app/slack/app.py +0 -19
  420. agno/app/slack/sync_router.py +0 -92
  421. agno/app/utils.py +0 -54
  422. agno/app/whatsapp/__init__.py +0 -3
  423. agno/app/whatsapp/app.py +0 -15
  424. agno/app/whatsapp/sync_router.py +0 -197
  425. agno/cli/auth_server.py +0 -249
  426. agno/cli/config.py +0 -274
  427. agno/cli/console.py +0 -88
  428. agno/cli/credentials.py +0 -23
  429. agno/cli/entrypoint.py +0 -571
  430. agno/cli/operator.py +0 -357
  431. agno/cli/settings.py +0 -96
  432. agno/cli/ws/ws_cli.py +0 -817
  433. agno/constants.py +0 -13
  434. agno/document/__init__.py +0 -5
  435. agno/document/chunking/semantic.py +0 -45
  436. agno/document/chunking/strategy.py +0 -31
  437. agno/document/reader/__init__.py +0 -5
  438. agno/document/reader/base.py +0 -47
  439. agno/document/reader/docx_reader.py +0 -60
  440. agno/document/reader/gcs/pdf_reader.py +0 -44
  441. agno/document/reader/s3/pdf_reader.py +0 -59
  442. agno/document/reader/s3/text_reader.py +0 -63
  443. agno/document/reader/url_reader.py +0 -59
  444. agno/document/reader/youtube_reader.py +0 -58
  445. agno/embedder/__init__.py +0 -5
  446. agno/embedder/langdb.py +0 -80
  447. agno/embedder/mistral.py +0 -82
  448. agno/embedder/openai.py +0 -78
  449. agno/file/__init__.py +0 -5
  450. agno/file/file.py +0 -16
  451. agno/file/local/csv.py +0 -32
  452. agno/file/local/txt.py +0 -19
  453. agno/infra/app.py +0 -240
  454. agno/infra/base.py +0 -144
  455. agno/infra/context.py +0 -20
  456. agno/infra/db_app.py +0 -52
  457. agno/infra/resource.py +0 -205
  458. agno/infra/resources.py +0 -55
  459. agno/knowledge/agent.py +0 -702
  460. agno/knowledge/arxiv.py +0 -33
  461. agno/knowledge/combined.py +0 -36
  462. agno/knowledge/csv.py +0 -144
  463. agno/knowledge/csv_url.py +0 -124
  464. agno/knowledge/document.py +0 -223
  465. agno/knowledge/docx.py +0 -137
  466. agno/knowledge/firecrawl.py +0 -34
  467. agno/knowledge/gcs/__init__.py +0 -0
  468. agno/knowledge/gcs/base.py +0 -39
  469. agno/knowledge/gcs/pdf.py +0 -125
  470. agno/knowledge/json.py +0 -137
  471. agno/knowledge/langchain.py +0 -71
  472. agno/knowledge/light_rag.py +0 -273
  473. agno/knowledge/llamaindex.py +0 -66
  474. agno/knowledge/markdown.py +0 -154
  475. agno/knowledge/pdf.py +0 -164
  476. agno/knowledge/pdf_bytes.py +0 -42
  477. agno/knowledge/pdf_url.py +0 -148
  478. agno/knowledge/s3/__init__.py +0 -0
  479. agno/knowledge/s3/base.py +0 -64
  480. agno/knowledge/s3/pdf.py +0 -33
  481. agno/knowledge/s3/text.py +0 -34
  482. agno/knowledge/text.py +0 -141
  483. agno/knowledge/url.py +0 -46
  484. agno/knowledge/website.py +0 -179
  485. agno/knowledge/wikipedia.py +0 -32
  486. agno/knowledge/youtube.py +0 -35
  487. agno/memory/agent.py +0 -423
  488. agno/memory/classifier.py +0 -104
  489. agno/memory/db/__init__.py +0 -5
  490. agno/memory/db/base.py +0 -42
  491. agno/memory/db/mongodb.py +0 -189
  492. agno/memory/db/postgres.py +0 -203
  493. agno/memory/db/sqlite.py +0 -193
  494. agno/memory/memory.py +0 -22
  495. agno/memory/row.py +0 -36
  496. agno/memory/summarizer.py +0 -201
  497. agno/memory/summary.py +0 -19
  498. agno/memory/team.py +0 -415
  499. agno/memory/v2/__init__.py +0 -2
  500. agno/memory/v2/db/__init__.py +0 -1
  501. agno/memory/v2/db/base.py +0 -42
  502. agno/memory/v2/db/firestore.py +0 -339
  503. agno/memory/v2/db/mongodb.py +0 -196
  504. agno/memory/v2/db/postgres.py +0 -214
  505. agno/memory/v2/db/redis.py +0 -187
  506. agno/memory/v2/db/schema.py +0 -54
  507. agno/memory/v2/db/sqlite.py +0 -209
  508. agno/memory/v2/manager.py +0 -437
  509. agno/memory/v2/memory.py +0 -1097
  510. agno/memory/v2/schema.py +0 -55
  511. agno/memory/v2/summarizer.py +0 -215
  512. agno/memory/workflow.py +0 -38
  513. agno/models/ollama/tools.py +0 -430
  514. agno/models/qwen/__init__.py +0 -5
  515. agno/playground/__init__.py +0 -10
  516. agno/playground/deploy.py +0 -3
  517. agno/playground/playground.py +0 -3
  518. agno/playground/serve.py +0 -3
  519. agno/playground/settings.py +0 -3
  520. agno/reranker/__init__.py +0 -0
  521. agno/run/response.py +0 -467
  522. agno/run/v2/__init__.py +0 -0
  523. agno/run/v2/workflow.py +0 -567
  524. agno/storage/__init__.py +0 -0
  525. agno/storage/agent/__init__.py +0 -0
  526. agno/storage/agent/dynamodb.py +0 -1
  527. agno/storage/agent/json.py +0 -1
  528. agno/storage/agent/mongodb.py +0 -1
  529. agno/storage/agent/postgres.py +0 -1
  530. agno/storage/agent/singlestore.py +0 -1
  531. agno/storage/agent/sqlite.py +0 -1
  532. agno/storage/agent/yaml.py +0 -1
  533. agno/storage/base.py +0 -60
  534. agno/storage/dynamodb.py +0 -673
  535. agno/storage/firestore.py +0 -297
  536. agno/storage/gcs_json.py +0 -261
  537. agno/storage/in_memory.py +0 -234
  538. agno/storage/json.py +0 -237
  539. agno/storage/mongodb.py +0 -328
  540. agno/storage/mysql.py +0 -685
  541. agno/storage/postgres.py +0 -682
  542. agno/storage/redis.py +0 -336
  543. agno/storage/session/__init__.py +0 -16
  544. agno/storage/session/agent.py +0 -64
  545. agno/storage/session/team.py +0 -63
  546. agno/storage/session/v2/__init__.py +0 -5
  547. agno/storage/session/workflow.py +0 -61
  548. agno/storage/singlestore.py +0 -606
  549. agno/storage/sqlite.py +0 -646
  550. agno/storage/workflow/__init__.py +0 -0
  551. agno/storage/workflow/mongodb.py +0 -1
  552. agno/storage/workflow/postgres.py +0 -1
  553. agno/storage/workflow/sqlite.py +0 -1
  554. agno/storage/yaml.py +0 -241
  555. agno/tools/thinking.py +0 -73
  556. agno/utils/defaults.py +0 -57
  557. agno/utils/filesystem.py +0 -39
  558. agno/utils/git.py +0 -52
  559. agno/utils/json_io.py +0 -30
  560. agno/utils/load_env.py +0 -19
  561. agno/utils/py_io.py +0 -19
  562. agno/utils/pyproject.py +0 -18
  563. agno/utils/resource_filter.py +0 -31
  564. agno/workflow/v2/__init__.py +0 -21
  565. agno/workflow/v2/types.py +0 -357
  566. agno/workflow/v2/workflow.py +0 -3313
  567. agno/workspace/__init__.py +0 -0
  568. agno/workspace/config.py +0 -325
  569. agno/workspace/enums.py +0 -6
  570. agno/workspace/helpers.py +0 -52
  571. agno/workspace/operator.py +0 -757
  572. agno/workspace/settings.py +0 -158
  573. agno-1.8.2.dist-info/METADATA +0 -982
  574. agno-1.8.2.dist-info/RECORD +0 -566
  575. agno-1.8.2.dist-info/entry_points.txt +0 -3
  576. agno-1.8.2.dist-info/licenses/LICENSE +0 -375
  577. /agno/{app → db/migrations}/__init__.py +0 -0
  578. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  579. /agno/{cli → integrations}/__init__.py +0 -0
  580. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  581. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  582. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  583. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  584. /agno/{app → os/interfaces}/slack/security.py +0 -0
  585. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  586. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  587. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  588. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  589. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -9,10 +9,10 @@ try:
9
9
  except ImportError:
10
10
  raise ImportError("The `pymilvus` package is not installed. Please install it via `pip install pymilvus`.")
11
11
 
12
- from agno.document import Document
13
- from agno.embedder import Embedder
14
- from agno.reranker.base import Reranker
15
- from agno.utils.log import log_debug, log_info, logger
12
+ from agno.knowledge.document import Document
13
+ from agno.knowledge.embedder import Embedder
14
+ from agno.knowledge.reranker.base import Reranker
15
+ from agno.utils.log import log_debug, log_error, log_info
16
16
  from agno.vectordb.base import VectorDb
17
17
  from agno.vectordb.distance import Distance
18
18
  from agno.vectordb.search import SearchType
@@ -66,7 +66,7 @@ class Milvus(VectorDb):
66
66
  self.collection: str = collection
67
67
 
68
68
  if embedder is None:
69
- from agno.embedder.openai import OpenAIEmbedder
69
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
70
70
 
71
71
  embedder = OpenAIEmbedder()
72
72
  log_info("Embedder not provided, using OpenAIEmbedder as default.")
@@ -153,6 +153,8 @@ class Milvus(VectorDb):
153
153
  ("id", DataType.VARCHAR, 128, True), # (name, type, max_length, is_primary)
154
154
  ("name", DataType.VARCHAR, 1000, False),
155
155
  ("content", DataType.VARCHAR, 65535, False),
156
+ ("content_id", DataType.VARCHAR, 1000, False),
157
+ ("content_hash", DataType.VARCHAR, 1000, False),
156
158
  ("text", DataType.VARCHAR, 1000, False),
157
159
  ("meta_data", DataType.VARCHAR, 65535, False),
158
160
  ("usage", DataType.VARCHAR, 65535, False),
@@ -192,7 +194,7 @@ class Milvus(VectorDb):
192
194
  return index_params
193
195
 
194
196
  def _prepare_document_data(
195
- self, document: Document, include_vectors: bool = True
197
+ self, content_hash: str, document: Document, include_vectors: bool = True
196
198
  ) -> Dict[str, Union[str, List[float], Dict[int, float], None]]:
197
199
  """
198
200
  Prepare document data for insertion.
@@ -205,11 +207,6 @@ class Milvus(VectorDb):
205
207
  Dictionary with document data where values can be strings, vectors (List[float]),
206
208
  sparse vectors (Dict[int, float]), or None
207
209
  """
208
- # Ensure document is embedded if vectors are needed
209
- if include_vectors and document.embedding is None:
210
- document.embed(embedder=self.embedder)
211
- if document.embedding is None:
212
- raise ValueError(f"Failed to embed document: {document.name}")
213
210
 
214
211
  cleaned_content = document.content.replace("\x00", "\ufffd")
215
212
  doc_id = md5(cleaned_content.encode()).hexdigest()
@@ -222,9 +219,11 @@ class Milvus(VectorDb):
222
219
  "id": doc_id,
223
220
  "text": cleaned_content,
224
221
  "name": document.name,
222
+ "content_id": document.content_id,
225
223
  "meta_data": meta_data_str,
226
224
  "content": cleaned_content,
227
225
  "usage": usage_str,
226
+ "content_hash": content_hash,
228
227
  }
229
228
 
230
229
  if include_vectors:
@@ -345,7 +344,7 @@ class Milvus(VectorDb):
345
344
  filter=expr,
346
345
  limit=1,
347
346
  )
348
- return len(scroll_result[0]) > 0
347
+ return len(scroll_result) > 0 and len(scroll_result[0]) > 0
349
348
  return False
350
349
 
351
350
  def id_exists(self, id: str) -> bool:
@@ -357,19 +356,56 @@ class Milvus(VectorDb):
357
356
  return len(collection_points) > 0
358
357
  return False
359
358
 
360
- def _insert_hybrid_document(self, document: Document) -> None:
361
- """Insert a document with both dense and sparse vectors."""
362
- data = self._prepare_document_data(document, include_vectors=True)
359
+ def content_hash_exists(self, content_hash: str) -> bool:
360
+ """
361
+ Check if a document with the given content hash exists.
363
362
 
363
+ Args:
364
+ content_hash (str): The content hash to check.
365
+
366
+ Returns:
367
+ bool: True if a document with the given content hash exists, False otherwise.
368
+ """
369
+ if self.client:
370
+ expr = f'content_hash == "{content_hash}"'
371
+ scroll_result = self.client.query(
372
+ collection_name=self.collection,
373
+ filter=expr,
374
+ limit=1,
375
+ )
376
+ return len(scroll_result) > 0 and len(scroll_result[0]) > 0
377
+ return False
378
+
379
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
380
+ """
381
+ Delete documents by content hash.
382
+
383
+ Args:
384
+ content_hash (str): The content hash to delete.
385
+
386
+ Returns:
387
+ bool: True if documents were deleted, False otherwise.
388
+ """
389
+ if self.client:
390
+ expr = f'content_hash == "{content_hash}"'
391
+ self.client.delete(collection_name=self.collection, filter=expr)
392
+ log_info(f"Deleted documents with content_hash '{content_hash}' from collection '{self.collection}'.")
393
+ return True
394
+ return False
395
+
396
+ def _insert_hybrid_document(self, content_hash: str, document: Document) -> None:
397
+ """Insert a document with both dense and sparse vectors."""
398
+ data = self._prepare_document_data(content_hash=content_hash, document=document, include_vectors=True)
399
+ document.embed(embedder=self.embedder)
364
400
  self.client.insert(
365
401
  collection_name=self.collection,
366
402
  data=data,
367
403
  )
368
404
  log_debug(f"Inserted hybrid document: {document.name} ({document.meta_data})")
369
405
 
370
- async def _async_insert_hybrid_document(self, document: Document) -> None:
406
+ async def _async_insert_hybrid_document(self, content_hash: str, document: Document) -> None:
371
407
  """Insert a document with both dense and sparse vectors asynchronously."""
372
- data = self._prepare_document_data(document, include_vectors=True)
408
+ data = self._prepare_document_data(content_hash=content_hash, document=document, include_vectors=True)
373
409
 
374
410
  await self.async_client.insert(
375
411
  collection_name=self.collection,
@@ -377,13 +413,13 @@ class Milvus(VectorDb):
377
413
  )
378
414
  log_debug(f"Inserted hybrid document asynchronously: {document.name} ({document.meta_data})")
379
415
 
380
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
416
+ def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
381
417
  """Insert documents based on search type."""
382
418
  log_debug(f"Inserting {len(documents)} documents")
383
419
 
384
420
  if self.search_type == SearchType.hybrid:
385
421
  for document in documents:
386
- self._insert_hybrid_document(document)
422
+ self._insert_hybrid_document(content_hash=content_hash, document=document)
387
423
  else:
388
424
  for document in documents:
389
425
  document.embed(embedder=self.embedder)
@@ -398,9 +434,11 @@ class Milvus(VectorDb):
398
434
  "id": doc_id,
399
435
  "vector": document.embedding,
400
436
  "name": document.name,
437
+ "content_id": document.content_id,
401
438
  "meta_data": meta_data,
402
439
  "content": cleaned_content,
403
440
  "usage": document.usage,
441
+ "content_hash": content_hash,
404
442
  }
405
443
  self.client.insert(
406
444
  collection_name=self.collection,
@@ -410,12 +448,19 @@ class Milvus(VectorDb):
410
448
 
411
449
  log_info(f"Inserted {len(documents)} documents")
412
450
 
413
- async def async_insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
451
+ async def async_insert(
452
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
453
+ ) -> None:
414
454
  """Insert documents asynchronously based on search type."""
415
- log_debug(f"Inserting {len(documents)} documents asynchronously")
455
+ log_info(f"Inserting {len(documents)} documents asynchronously")
456
+
457
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
458
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
416
459
 
417
460
  if self.search_type == SearchType.hybrid:
418
- await asyncio.gather(*[self._async_insert_hybrid_document(doc) for doc in documents])
461
+ await asyncio.gather(
462
+ *[self._async_insert_hybrid_document(content_hash=content_hash, document=doc) for doc in documents]
463
+ )
419
464
  else:
420
465
 
421
466
  async def process_document(document):
@@ -431,9 +476,11 @@ class Milvus(VectorDb):
431
476
  "id": doc_id,
432
477
  "vector": document.embedding,
433
478
  "name": document.name,
479
+ "content_id": document.content_id,
434
480
  "meta_data": meta_data,
435
481
  "content": cleaned_content,
436
482
  "usage": document.usage,
483
+ "content_hash": content_hash,
437
484
  }
438
485
  await self.async_client.insert(
439
486
  collection_name=self.collection,
@@ -455,7 +502,7 @@ class Milvus(VectorDb):
455
502
  """
456
503
  return True
457
504
 
458
- def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
505
+ def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
459
506
  """
460
507
  Upsert documents into the database.
461
508
 
@@ -468,13 +515,20 @@ class Milvus(VectorDb):
468
515
  document.embed(embedder=self.embedder)
469
516
  cleaned_content = document.content.replace("\x00", "\ufffd")
470
517
  doc_id = md5(cleaned_content.encode()).hexdigest()
518
+
519
+ meta_data = document.meta_data or {}
520
+ if filters:
521
+ meta_data.update(filters)
522
+
471
523
  data = {
472
524
  "id": doc_id,
473
525
  "vector": document.embedding,
474
526
  "name": document.name,
527
+ "content_id": document.content_id,
475
528
  "meta_data": document.meta_data,
476
529
  "content": cleaned_content,
477
530
  "usage": document.usage,
531
+ "content_hash": content_hash,
478
532
  }
479
533
  self.client.upsert(
480
534
  collection_name=self.collection,
@@ -482,20 +536,26 @@ class Milvus(VectorDb):
482
536
  )
483
537
  log_debug(f"Upserted document: {document.name} ({document.meta_data})")
484
538
 
485
- async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
539
+ async def async_upsert(
540
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
541
+ ) -> None:
486
542
  log_debug(f"Upserting {len(documents)} documents asynchronously")
487
543
 
544
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
545
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
546
+
488
547
  async def process_document(document):
489
- document.embed(embedder=self.embedder)
490
548
  cleaned_content = document.content.replace("\x00", "\ufffd")
491
549
  doc_id = md5(cleaned_content.encode()).hexdigest()
492
550
  data = {
493
551
  "id": doc_id,
494
552
  "vector": document.embedding,
495
553
  "name": document.name,
554
+ "content_id": document.content_id,
496
555
  "meta_data": document.meta_data,
497
556
  "content": cleaned_content,
498
557
  "usage": document.usage,
558
+ "content_hash": content_hash,
499
559
  }
500
560
  await self.async_client.upsert(
501
561
  collection_name=self.collection,
@@ -535,7 +595,7 @@ class Milvus(VectorDb):
535
595
 
536
596
  query_embedding = self.embedder.get_embedding(query)
537
597
  if query_embedding is None:
538
- logger.error(f"Error getting embedding for Query: {query}")
598
+ log_error(f"Error getting embedding for Query: {query}")
539
599
  return []
540
600
 
541
601
  results = self.client.search(
@@ -555,6 +615,7 @@ class Milvus(VectorDb):
555
615
  name=result["entity"].get("name", None),
556
616
  meta_data=result["entity"].get("meta_data", {}),
557
617
  content=result["entity"].get("content", ""),
618
+ content_id=result["entity"].get("content_id", None),
558
619
  embedder=self.embedder,
559
620
  embedding=result["entity"].get("vector", None),
560
621
  usage=result["entity"].get("usage", None),
@@ -572,7 +633,7 @@ class Milvus(VectorDb):
572
633
 
573
634
  query_embedding = self.embedder.get_embedding(query)
574
635
  if query_embedding is None:
575
- logger.error(f"Error getting embedding for Query: {query}")
636
+ log_error(f"Error getting embedding for Query: {query}")
576
637
  return []
577
638
 
578
639
  results = await self.async_client.search(
@@ -592,6 +653,7 @@ class Milvus(VectorDb):
592
653
  name=result["entity"].get("name", None),
593
654
  meta_data=result["entity"].get("meta_data", {}),
594
655
  content=result["entity"].get("content", ""),
656
+ content_id=result["entity"].get("content_id", None),
595
657
  embedder=self.embedder,
596
658
  embedding=result["entity"].get("vector", None),
597
659
  usage=result["entity"].get("usage", None),
@@ -620,11 +682,11 @@ class Milvus(VectorDb):
620
682
  sparse_vector = self._get_sparse_vector(query)
621
683
 
622
684
  if dense_vector is None:
623
- logger.error(f"Error getting dense embedding for Query: {query}")
685
+ log_error(f"Error getting dense embedding for Query: {query}")
624
686
  return []
625
687
 
626
688
  if self._client is None:
627
- logger.error("Milvus client not initialized")
689
+ log_error("Milvus client not initialized")
628
690
  return []
629
691
 
630
692
  try:
@@ -674,6 +736,7 @@ class Milvus(VectorDb):
674
736
  name=entity.get("name", None),
675
737
  meta_data=meta_data, # Now a dictionary
676
738
  content=entity.get("content", ""),
739
+ content_id=entity.get("content_id", None),
677
740
  embedder=self.embedder,
678
741
  embedding=entity.get("dense_vector", None),
679
742
  usage=usage, # Now a dictionary or None
@@ -688,7 +751,7 @@ class Milvus(VectorDb):
688
751
  return search_results
689
752
 
690
753
  except Exception as e:
691
- logger.error(f"Error during hybrid search: {e}")
754
+ log_error(f"Error during hybrid search: {e}")
692
755
  return []
693
756
 
694
757
  async def async_hybrid_search(
@@ -712,7 +775,7 @@ class Milvus(VectorDb):
712
775
  sparse_vector = self._get_sparse_vector(query)
713
776
 
714
777
  if dense_vector is None:
715
- logger.error(f"Error getting dense embedding for Query: {query}")
778
+ log_error(f"Error getting dense embedding for Query: {query}")
716
779
  return []
717
780
 
718
781
  try:
@@ -776,7 +839,7 @@ class Milvus(VectorDb):
776
839
  return search_results
777
840
 
778
841
  except Exception as e:
779
- logger.error(f"Error during async hybrid search: {e}")
842
+ log_error(f"Error during async hybrid search: {e}")
780
843
  return []
781
844
 
782
845
  def drop(self) -> None:
@@ -818,6 +881,101 @@ class Milvus(VectorDb):
818
881
  return True
819
882
  return False
820
883
 
884
+ def delete_by_id(self, id: str) -> bool:
885
+ """
886
+ Delete a document by its ID.
887
+
888
+ Args:
889
+ id (str): The document ID to delete
890
+
891
+ Returns:
892
+ bool: True if document was deleted, False otherwise
893
+ """
894
+ try:
895
+ log_debug(f"Milvus VectorDB : Deleting document with ID {id}")
896
+ if not self.id_exists(id):
897
+ return False
898
+
899
+ # Delete by ID using Milvus delete operation
900
+ self.client.delete(collection_name=self.collection, ids=[id])
901
+ log_info(f"Deleted document with ID '{id}' from collection '{self.collection}'.")
902
+ return True
903
+ except Exception as e:
904
+ log_info(f"Error deleting document with ID {id}: {e}")
905
+ return False
906
+
907
+ def delete_by_name(self, name: str) -> bool:
908
+ """
909
+ Delete documents by name.
910
+
911
+ Args:
912
+ name (str): The document name to delete
913
+
914
+ Returns:
915
+ bool: True if documents were deleted, False otherwise
916
+ """
917
+ try:
918
+ log_debug(f"Milvus VectorDB : Deleting documents with name {name}")
919
+ if not self.name_exists(name):
920
+ return False
921
+
922
+ # Delete by name using Milvus delete operation with filter
923
+ expr = f'name == "{name}"'
924
+ self.client.delete(collection_name=self.collection, filter=expr)
925
+ log_info(f"Deleted documents with name '{name}' from collection '{self.collection}'.")
926
+ return True
927
+ except Exception as e:
928
+ log_info(f"Error deleting documents with name {name}: {e}")
929
+ return False
930
+
931
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
932
+ """
933
+ Delete documents by metadata.
934
+
935
+ Args:
936
+ metadata (Dict[str, Any]): The metadata to match for deletion
937
+
938
+ Returns:
939
+ bool: True if documents were deleted, False otherwise
940
+ """
941
+ try:
942
+ log_debug(f"Milvus VectorDB : Deleting documents with metadata {metadata}")
943
+
944
+ # Build filter expression for metadata matching
945
+ expr = self._build_expr(metadata)
946
+ if not expr:
947
+ return False
948
+
949
+ # Delete by metadata using Milvus delete operation with filter
950
+ self.client.delete(collection_name=self.collection, filter=expr)
951
+ log_info(f"Deleted documents with metadata '{metadata}' from collection '{self.collection}'.")
952
+ return True
953
+ except Exception as e:
954
+ log_info(f"Error deleting documents with metadata {metadata}: {e}")
955
+ return False
956
+
957
+ def delete_by_content_id(self, content_id: str) -> bool:
958
+ """
959
+ Delete documents by content ID.
960
+
961
+ Args:
962
+ content_id (str): The content ID to delete
963
+
964
+ Returns:
965
+ bool: True if documents were deleted, False otherwise
966
+ """
967
+ try:
968
+ log_debug(f"Milvus VectorDB : Deleting documents with content_id {content_id}")
969
+
970
+ # Delete by content_id using Milvus delete operation with filter
971
+ expr = f'content_id == "{content_id}"'
972
+ self.client.delete(collection_name=self.collection, filter=expr)
973
+ log_info(f"Deleted documents with content_id '{content_id}' from collection '{self.collection}'.")
974
+ return True
975
+ except Exception as e:
976
+ log_info(f"Error deleting documents with content_id {content_id}: {e}")
977
+ return False
978
+
821
979
  def _build_expr(self, filters: Optional[Dict[str, Any]]) -> Optional[str]:
822
980
  """Build Milvus expression from filters."""
823
981
  if not filters:
@@ -853,3 +1011,55 @@ class Milvus(VectorDb):
853
1011
 
854
1012
  def async_name_exists(self, name: str) -> bool:
855
1013
  raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
1014
+
1015
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
1016
+ """
1017
+ Update the metadata for documents with the given content_id.
1018
+
1019
+ Args:
1020
+ content_id (str): The content ID to update
1021
+ metadata (Dict[str, Any]): The metadata to update
1022
+ """
1023
+ try:
1024
+ # Search for documents with the given content_id
1025
+ search_expr = f'content_id == "{content_id}"'
1026
+ results = self.client.query(
1027
+ collection_name=self.collection, filter=search_expr, output_fields=["id", "meta_data", "filters"]
1028
+ )
1029
+
1030
+ if not results:
1031
+ log_debug(f"No documents found with content_id: {content_id}")
1032
+ return
1033
+
1034
+ # Update each document
1035
+ updated_count = 0
1036
+ for result in results:
1037
+ doc_id = result["id"]
1038
+ current_metadata = result.get("meta_data", {})
1039
+ current_filters = result.get("filters", {})
1040
+
1041
+ # Merge existing metadata with new metadata
1042
+ if isinstance(current_metadata, dict):
1043
+ updated_metadata = current_metadata.copy()
1044
+ updated_metadata.update(metadata)
1045
+ else:
1046
+ updated_metadata = metadata
1047
+
1048
+ if isinstance(current_filters, dict):
1049
+ updated_filters = current_filters.copy()
1050
+ updated_filters.update(metadata)
1051
+ else:
1052
+ updated_filters = metadata
1053
+
1054
+ # Update the document
1055
+ self.client.upsert(
1056
+ collection_name=self.collection,
1057
+ data=[{"id": doc_id, "meta_data": updated_metadata, "filters": updated_filters}],
1058
+ )
1059
+ updated_count += 1
1060
+
1061
+ log_debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
1062
+
1063
+ except Exception as e:
1064
+ log_error(f"Error updating metadata for content_id '{content_id}': {e}")
1065
+ raise