agno 1.8.1__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 (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  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 +1416 -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 +154 -48
  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 +1551 -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 +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  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 +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  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 +46 -151
  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 +85 -47
  158. agno/models/openai/chat.py +154 -37
  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 +15 -9
  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 +497 -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 +235 -0
  185. agno/os/router.py +1400 -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 +393 -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 +850 -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 +410 -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 +178 -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 +536 -0
  202. agno/os/schema.py +945 -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/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -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 +3260 -4824
  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 +43 -23
  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 +20 -17
  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 +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  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 +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  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 +30 -30
  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 +23 -11
  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 +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.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