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 @@ except ImportError:
9
9
  "The `qdrant-client` package is not installed. Please install it via `pip install qdrant-client`."
10
10
  )
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
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, log_warning
16
16
  from agno.vectordb.base import VectorDb
17
17
  from agno.vectordb.distance import Distance
18
18
  from agno.vectordb.search import SearchType
@@ -78,7 +78,7 @@ class Qdrant(VectorDb):
78
78
 
79
79
  # Embedder for embedding the document contents
80
80
  if embedder is None:
81
- from agno.embedder.openai import OpenAIEmbedder
81
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
82
82
 
83
83
  embedder = OpenAIEmbedder()
84
84
  log_info("Embedder not provided, using OpenAIEmbedder as default.")
@@ -302,7 +302,13 @@ class Qdrant(VectorDb):
302
302
  return len(scroll_result[0]) > 0
303
303
  return False
304
304
 
305
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None, batch_size: int = 10) -> None:
305
+ def insert(
306
+ self,
307
+ content_hash: str,
308
+ documents: List[Document],
309
+ filters: Optional[Dict[str, Any]] = None,
310
+ batch_size: int = 10,
311
+ ) -> None:
306
312
  """
307
313
  Insert documents into the database.
308
314
 
@@ -343,6 +349,8 @@ class Qdrant(VectorDb):
343
349
  "meta_data": document.meta_data,
344
350
  "content": cleaned_content,
345
351
  "usage": document.usage,
352
+ "content_id": document.content_id,
353
+ "content_hash": content_hash,
346
354
  }
347
355
 
348
356
  # Add filters as metadata if provided
@@ -364,7 +372,9 @@ class Qdrant(VectorDb):
364
372
  self.client.upsert(collection_name=self.collection, wait=False, points=points)
365
373
  log_debug(f"Upsert {len(points)} documents")
366
374
 
367
- async def async_insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
375
+ async def async_insert(
376
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
377
+ ) -> None:
368
378
  """
369
379
  Insert documents asynchronously.
370
380
 
@@ -401,6 +411,8 @@ class Qdrant(VectorDb):
401
411
  "meta_data": document.meta_data,
402
412
  "content": cleaned_content,
403
413
  "usage": document.usage,
414
+ "content_id": document.content_id,
415
+ "content_hash": content_hash,
404
416
  }
405
417
 
406
418
  # Add filters as metadata if provided
@@ -426,7 +438,7 @@ class Qdrant(VectorDb):
426
438
  await self.async_client.upsert(collection_name=self.collection, wait=False, points=points)
427
439
  log_debug(f"Upserted {len(points)} documents asynchronously")
428
440
 
429
- def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
441
+ def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
430
442
  """
431
443
  Upsert documents into the database.
432
444
 
@@ -435,12 +447,16 @@ class Qdrant(VectorDb):
435
447
  filters (Optional[Dict[str, Any]]): Filters to apply while upserting
436
448
  """
437
449
  log_debug("Redirecting the request to insert")
438
- self.insert(documents, filters)
450
+ if self.content_hash_exists(content_hash):
451
+ self._delete_by_content_hash(content_hash)
452
+ self.insert(content_hash=content_hash, documents=documents, filters=filters)
439
453
 
440
- async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
454
+ async def async_upsert(
455
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
456
+ ) -> None:
441
457
  """Upsert documents asynchronously."""
442
458
  log_debug("Redirecting the async request to async_insert")
443
- await self.async_insert(documents, filters)
459
+ await self.async_insert(content_hash=content_hash, documents=documents, filters=filters)
444
460
 
445
461
  def search(self, query: str, limit: int = 5, filters: Optional[Dict[str, Any]] = None) -> List[Document]:
446
462
  """
@@ -641,7 +657,8 @@ class Qdrant(VectorDb):
641
657
  content=result.payload["content"],
642
658
  embedder=self.embedder,
643
659
  embedding=result.vector, # type: ignore
644
- usage=result.payload["usage"],
660
+ usage=result.payload.get("usage"),
661
+ content_id=result.payload.get("content_id"),
645
662
  )
646
663
  )
647
664
 
@@ -676,6 +693,9 @@ class Qdrant(VectorDb):
676
693
 
677
694
  return None
678
695
 
696
+ def optimize(self) -> None:
697
+ pass
698
+
679
699
  def drop(self) -> None:
680
700
  if self.exists():
681
701
  log_debug(f"Deleting collection: {self.collection}")
@@ -699,12 +719,312 @@ class Qdrant(VectorDb):
699
719
  count_result: models.CountResult = self.client.count(collection_name=self.collection, exact=True)
700
720
  return count_result.count
701
721
 
702
- def optimize(self) -> None:
703
- pass
722
+ def point_exists(self, id: str) -> bool:
723
+ """Check if a point with the given ID exists in the collection."""
724
+ try:
725
+ log_info(f"Checking if point with ID '{id}' (type: {type(id)}) exists in collection '{self.collection}'")
726
+ points = self.client.retrieve(
727
+ collection_name=self.collection, ids=[id], with_payload=False, with_vectors=False
728
+ )
729
+ log_info(f"Retrieved {len(points)} points for ID '{id}'")
730
+ if len(points) > 0:
731
+ log_info(f"Found point with ID: {points[0].id} (type: {type(points[0].id)})")
732
+ return len(points) > 0
733
+ except Exception as e:
734
+ log_info(f"Error checking if point {id} exists: {e}")
735
+ return False
704
736
 
705
737
  def delete(self) -> bool:
706
738
  return self.client.delete_collection(collection_name=self.collection)
707
739
 
740
+ def delete_by_id(self, id: str) -> bool:
741
+ try:
742
+ # Check if point exists before deletion
743
+ if not self.point_exists(id):
744
+ log_warning(f"Point with ID {id} does not exist")
745
+ return True
746
+
747
+ self.client.delete(
748
+ collection_name=self.collection,
749
+ points_selector=models.PointIdsList(points=[id]),
750
+ wait=True, # Wait for the operation to complete
751
+ )
752
+ return True
753
+
754
+ except Exception as e:
755
+ log_info(f"Error deleting point with ID {id}: {e}")
756
+ return False
757
+
758
+ def delete_by_name(self, name: str) -> bool:
759
+ """Delete all points that have the specified name in their payload (precise match)."""
760
+ try:
761
+ log_info(f"Attempting to delete all points with name: {name}")
762
+
763
+ # Create a filter to find all points with the specified name (precise match)
764
+ filter_condition = models.Filter(
765
+ must=[models.FieldCondition(key="name", match=models.MatchValue(value=name))]
766
+ )
767
+
768
+ # First, count how many points will be deleted
769
+ count_result = self.client.count(collection_name=self.collection, count_filter=filter_condition, exact=True)
770
+
771
+ if count_result.count == 0:
772
+ log_warning(f"No points found with name: {name}")
773
+ return True
774
+
775
+ log_info(f"Found {count_result.count} points to delete with name: {name}")
776
+
777
+ # Delete all points matching the filter
778
+ result = self.client.delete(
779
+ collection_name=self.collection,
780
+ points_selector=filter_condition,
781
+ wait=True, # Wait for the operation to complete
782
+ )
783
+
784
+ # Check if the deletion was successful
785
+ if result.status == models.UpdateStatus.COMPLETED:
786
+ log_info(f"Successfully deleted {count_result.count} points with name: {name}")
787
+ return True
788
+ else:
789
+ log_warning(f"Deletion failed for name {name}. Status: {result.status}")
790
+ return False
791
+
792
+ except Exception as e:
793
+ log_warning(f"Error deleting points with name {name}: {e}")
794
+ return False
795
+
796
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
797
+ """Delete all points where the given metadata is contained in the meta_data payload field."""
798
+ try:
799
+ log_info(f"Attempting to delete all points with metadata: {metadata}")
800
+
801
+ # Create filter conditions for each metadata key-value pair
802
+ filter_conditions = []
803
+ for key, value in metadata.items():
804
+ # Use the meta_data prefix since that's how metadata is stored in the payload
805
+ filter_conditions.append(
806
+ models.FieldCondition(key=f"meta_data.{key}", match=models.MatchValue(value=value))
807
+ )
808
+
809
+ # Create a filter that requires ALL metadata conditions to match
810
+ filter_condition = models.Filter(must=filter_conditions)
811
+
812
+ # First, count how many points will be deleted
813
+ count_result = self.client.count(collection_name=self.collection, count_filter=filter_condition, exact=True)
814
+
815
+ if count_result.count == 0:
816
+ log_warning(f"No points found with metadata: {metadata}")
817
+ return True
818
+
819
+ log_info(f"Found {count_result.count} points to delete with metadata: {metadata}")
820
+
821
+ # Delete all points matching the filter
822
+ result = self.client.delete(
823
+ collection_name=self.collection,
824
+ points_selector=filter_condition,
825
+ wait=True, # Wait for the operation to complete
826
+ )
827
+
828
+ # Check if the deletion was successful
829
+ if result.status == models.UpdateStatus.COMPLETED:
830
+ log_info(f"Successfully deleted {count_result.count} points with metadata: {metadata}")
831
+ return True
832
+ else:
833
+ log_warning(f"Deletion failed for metadata {metadata}. Status: {result.status}")
834
+ return False
835
+
836
+ except Exception as e:
837
+ log_warning(f"Error deleting points with metadata {metadata}: {e}")
838
+ return False
839
+
840
+ def delete_by_content_id(self, content_id: str) -> bool:
841
+ """Delete all points that have the specified content_id in their payload."""
842
+ try:
843
+ log_info(f"Attempting to delete all points with content_id: {content_id}")
844
+
845
+ # Create a filter to find all points with the specified content_id
846
+ filter_condition = models.Filter(
847
+ must=[models.FieldCondition(key="content_id", match=models.MatchValue(value=content_id))]
848
+ )
849
+
850
+ # First, count how many points will be deleted
851
+ count_result = self.client.count(collection_name=self.collection, count_filter=filter_condition, exact=True)
852
+
853
+ if count_result.count == 0:
854
+ log_warning(f"No points found with content_id: {content_id}")
855
+ return True
856
+
857
+ log_info(f"Found {count_result.count} points to delete with content_id: {content_id}")
858
+
859
+ # Delete all points matching the filter
860
+ result = self.client.delete(
861
+ collection_name=self.collection,
862
+ points_selector=filter_condition,
863
+ wait=True, # Wait for the operation to complete
864
+ )
865
+
866
+ # Check if the deletion was successful
867
+ if result.status == models.UpdateStatus.COMPLETED:
868
+ log_info(f"Successfully deleted {count_result.count} points with content_id: {content_id}")
869
+ return True
870
+ else:
871
+ log_warning(f"Deletion failed for content_id {content_id}. Status: {result.status}")
872
+ return False
873
+
874
+ except Exception as e:
875
+ log_warning(f"Error deleting points with content_id {content_id}: {e}")
876
+ return False
877
+
878
+ def id_exists(self, id: str) -> bool:
879
+ """Check if a point with the given ID exists in the collection.
880
+
881
+ Args:
882
+ id (str): The ID to check.
883
+
884
+ Returns:
885
+ bool: True if the point exists, False otherwise.
886
+ """
887
+ try:
888
+ points = self.client.retrieve(
889
+ collection_name=self.collection, ids=[id], with_payload=False, with_vectors=False
890
+ )
891
+ return len(points) > 0
892
+ except Exception as e:
893
+ log_info(f"Error checking if point {id} exists: {e}")
894
+ return False
895
+
896
+ def content_hash_exists(self, content_hash: str) -> bool:
897
+ """Check if any points with the given content hash exist in the collection.
898
+
899
+ Args:
900
+ content_hash (str): The content hash to check.
901
+
902
+ Returns:
903
+ bool: True if points with the content hash exist, False otherwise.
904
+ """
905
+ try:
906
+ # Create a filter to find points with the specified content_hash
907
+ filter_condition = models.Filter(
908
+ must=[models.FieldCondition(key="content_hash", match=models.MatchValue(value=content_hash))]
909
+ )
910
+
911
+ # Count how many points match the filter
912
+ count_result = self.client.count(collection_name=self.collection, count_filter=filter_condition, exact=True)
913
+ return count_result.count > 0
914
+ except Exception as e:
915
+ log_info(f"Error checking if content_hash {content_hash} exists: {e}")
916
+ return False
917
+
918
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
919
+ """Delete all points that have the specified content_hash in their payload.
920
+
921
+ Args:
922
+ content_hash (str): The content hash to delete.
923
+
924
+ Returns:
925
+ bool: True if points were deleted successfully, False otherwise.
926
+ """
927
+ try:
928
+ log_info(f"Attempting to delete all points with content_hash: {content_hash}")
929
+
930
+ # Create a filter to find all points with the specified content_hash
931
+ filter_condition = models.Filter(
932
+ must=[models.FieldCondition(key="content_hash", match=models.MatchValue(value=content_hash))]
933
+ )
934
+
935
+ # First, count how many points will be deleted
936
+ count_result = self.client.count(collection_name=self.collection, count_filter=filter_condition, exact=True)
937
+
938
+ if count_result.count == 0:
939
+ log_warning(f"No points found with content_hash: {content_hash}")
940
+ return True
941
+
942
+ log_info(f"Found {count_result.count} points to delete with content_hash: {content_hash}")
943
+
944
+ # Delete all points matching the filter
945
+ result = self.client.delete(
946
+ collection_name=self.collection,
947
+ points_selector=filter_condition,
948
+ wait=True, # Wait for the operation to complete
949
+ )
950
+
951
+ # Check if the deletion was successful
952
+ if result.status == models.UpdateStatus.COMPLETED:
953
+ log_info(f"Successfully deleted {count_result.count} points with content_hash: {content_hash}")
954
+ return True
955
+ else:
956
+ log_warning(f"Deletion failed for content_hash {content_hash}. Status: {result.status}")
957
+ return False
958
+
959
+ except Exception as e:
960
+ log_warning(f"Error deleting points with content_hash {content_hash}: {e}")
961
+ return False
962
+
963
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
964
+ """
965
+ Update the metadata for documents with the given content_id.
966
+
967
+ Args:
968
+ content_id (str): The content ID to update
969
+ metadata (Dict[str, Any]): The metadata to update
970
+ """
971
+ try:
972
+ if not self.client:
973
+ log_error("Client not initialized")
974
+ return
975
+
976
+ # Create filter for content_id
977
+ filter_condition = models.Filter(
978
+ must=[models.FieldCondition(key="content_id", match=models.MatchValue(value=content_id))]
979
+ )
980
+
981
+ # Search for points with the given content_id
982
+ search_result = self.client.scroll(
983
+ collection_name=self.collection,
984
+ scroll_filter=filter_condition,
985
+ limit=10000, # Get all matching points
986
+ with_payload=True,
987
+ with_vectors=False,
988
+ )
989
+
990
+ if not search_result[0]: # search_result is a tuple (points, next_page_offset)
991
+ log_error(f"No documents found with content_id: {content_id}")
992
+ return
993
+
994
+ points = search_result[0]
995
+ update_operations = []
996
+
997
+ # Prepare update operations for each point
998
+ for point in points:
999
+ point_id = point.id
1000
+ current_payload = point.payload or {}
1001
+
1002
+ # Merge existing metadata with new metadata
1003
+ updated_payload = current_payload.copy()
1004
+ updated_payload.update(metadata)
1005
+
1006
+ if "filters" not in updated_payload:
1007
+ updated_payload["filters"] = {}
1008
+ if isinstance(updated_payload["filters"], dict):
1009
+ updated_payload["filters"].update(metadata)
1010
+ else:
1011
+ updated_payload["filters"] = metadata
1012
+
1013
+ # Create set payload operation
1014
+ update_operations.append(models.SetPayload(payload=updated_payload, points=[point_id]))
1015
+
1016
+ # Execute all updates
1017
+ for operation in update_operations:
1018
+ self.client.set_payload(
1019
+ collection_name=self.collection, payload=operation.payload, points=operation.points
1020
+ )
1021
+
1022
+ log_debug(f"Updated metadata for {len(update_operations)} documents with content_id: {content_id}")
1023
+
1024
+ except Exception as e:
1025
+ log_error(f"Error updating metadata for content_id '{content_id}': {e}")
1026
+ raise
1027
+
708
1028
  def close(self) -> None:
709
1029
  """Close the Qdrant client connections."""
710
1030
  if self._client is not None: