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

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