agno 1.8.1__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 (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  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/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 +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +38 -144
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +84 -46
  158. agno/models/openai/chat.py +121 -23
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +14 -8
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +393 -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 +65 -28
  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 +33 -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 +30 -0
  184. agno/os/router.py +843 -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 +204 -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 +413 -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 +179 -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 +58 -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 +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -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/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -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 +2961 -4253
  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 +42 -22
  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 +18 -13
  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 +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  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 +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  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 +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  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 +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  from typing import Any, Dict, List, Optional
2
3
 
3
4
  try:
@@ -8,9 +9,9 @@ except ImportError:
8
9
  "The `upstash-vector` package is not installed, please install using `pip install upstash-vector`"
9
10
  )
10
11
 
11
- from agno.document import Document
12
- from agno.embedder import Embedder
13
- from agno.reranker.base import Reranker
12
+ from agno.knowledge.document import Document
13
+ from agno.knowledge.embedder import Embedder
14
+ from agno.knowledge.reranker.base import Reranker
14
15
  from agno.utils.log import log_info, logger
15
16
  from agno.vectordb.base import VectorDb
16
17
 
@@ -139,19 +140,52 @@ class UpstashVectorDb(VectorDb):
139
140
  """
140
141
  return self.index.list_namespaces()
141
142
 
142
- def doc_exists(self, document: Document) -> bool:
143
- """Check if a document exists in the index.
143
+ def content_hash_exists(self, content_hash: str) -> bool:
144
+ """Check if documents with the given content hash exist in the index.
145
+
144
146
  Args:
145
- document (Document): The document to check.
147
+ content_hash (str): The content hash to check.
148
+
146
149
  Returns:
147
- bool: True if the document exists, False otherwise.
150
+ bool: True if documents with the content hash exist, False otherwise.
148
151
  """
149
- if document.id is None:
150
- logger.error("Document ID cannot be None")
152
+ try:
153
+ # Use query with a filter to check if any documents exist with this content_hash
154
+ # We only need to check existence, so limit to 1 result
155
+ filter_str = f'content_hash = "{content_hash}"'
156
+
157
+ if not self.use_upstash_embeddings and self.embedder is not None:
158
+ # For custom embeddings, we need a dummy vector for the query
159
+ # Use a zero vector as we only care about the filter match
160
+ info = self.index.info()
161
+ dimension = info.dimension
162
+ dummy_vector = [0.0] * dimension
163
+
164
+ response = self.index.query(
165
+ vector=dummy_vector,
166
+ namespace=self.namespace,
167
+ top_k=1,
168
+ filter=filter_str,
169
+ include_data=False,
170
+ include_metadata=False,
171
+ include_vectors=False,
172
+ )
173
+ else:
174
+ # For hosted embeddings, use a minimal text query
175
+ response = self.index.query(
176
+ data="", # Empty query since we only care about the filter
177
+ namespace=self.namespace,
178
+ top_k=1,
179
+ filter=filter_str,
180
+ include_data=False,
181
+ include_metadata=False,
182
+ include_vectors=False,
183
+ )
184
+
185
+ return response is not None and len(response) > 0
186
+ except Exception as e:
187
+ logger.error(f"Error checking if content_hash {content_hash} exists: {e}")
151
188
  return False
152
- documents_to_fetch = [document.id]
153
- response = self.index.fetch(ids=documents_to_fetch)
154
- return len(response) > 0
155
189
 
156
190
  def name_exists(self, name: str) -> bool:
157
191
  """You can check if an index exists in Upstash Console.
@@ -177,7 +211,11 @@ class UpstashVectorDb(VectorDb):
177
211
  return namespace in namespaces
178
212
 
179
213
  def upsert(
180
- self, documents: List[Document], filters: Optional[Dict[str, Any]] = None, namespace: Optional[str] = None
214
+ self,
215
+ content_hash: str,
216
+ documents: List[Document],
217
+ filters: Optional[Dict[str, Any]] = None,
218
+ namespace: Optional[str] = None,
181
219
  ) -> None:
182
220
  """Upsert documents into the index.
183
221
 
@@ -189,12 +227,38 @@ class UpstashVectorDb(VectorDb):
189
227
  _namespace = self.namespace if namespace is None else namespace
190
228
  vectors = []
191
229
 
192
- for document in documents:
230
+ for i, document in enumerate(documents):
193
231
  if document.id is None:
194
232
  logger.error(f"Document ID must not be None. Skipping document: {document.content[:100]}...")
195
233
  continue
196
234
 
197
- document.meta_data["text"] = document.content
235
+ logger.debug(
236
+ f"Processing document {i + 1}: ID={document.id}, name={document.name}, "
237
+ f"content_id={getattr(document, 'content_id', 'N/A')}"
238
+ )
239
+
240
+ # Create a copy of metadata to avoid modifying the original document
241
+ meta_data = document.meta_data.copy() if document.meta_data else {}
242
+
243
+ # Add filters to document metadata if provided
244
+ if filters:
245
+ meta_data.update(filters)
246
+
247
+ meta_data["text"] = document.content
248
+
249
+ # Add content_id to metadata if it exists
250
+ if hasattr(document, "content_id") and document.content_id:
251
+ meta_data["content_id"] = document.content_id
252
+ else:
253
+ logger.warning(f"Document {document.id} has no content_id")
254
+
255
+ meta_data["content_hash"] = content_hash
256
+
257
+ # Add name to metadata if it exists
258
+ if document.name:
259
+ meta_data["name"] = document.name
260
+ else:
261
+ logger.warning(f"Document {document.id} has no name")
198
262
 
199
263
  if not self.use_upstash_embeddings:
200
264
  if self.embedder is None:
@@ -206,17 +270,16 @@ class UpstashVectorDb(VectorDb):
206
270
  logger.error(f"Failed to generate embedding for document: {document.id}")
207
271
  continue
208
272
 
209
- vector = Vector(
210
- id=document.id, vector=document.embedding, metadata=document.meta_data, data=document.content
211
- )
273
+ vector = Vector(id=document.id, vector=document.embedding, metadata=meta_data, data=document.content)
212
274
  else:
213
- vector = Vector(id=document.id, data=document.content, metadata=document.meta_data)
275
+ vector = Vector(id=document.id, data=document.content, metadata=meta_data)
214
276
  vectors.append(vector)
215
277
 
216
278
  if not vectors:
217
279
  logger.warning("No valid documents to upsert")
218
280
  return
219
281
 
282
+ logger.info(f"Upserting {len(vectors)} vectors to Upstash with IDs: {[v.id for v in vectors[:5]]}...")
220
283
  self.index.upsert(vectors, namespace=_namespace)
221
284
 
222
285
  def upsert_available(self) -> bool:
@@ -226,16 +289,15 @@ class UpstashVectorDb(VectorDb):
226
289
  """
227
290
  return True
228
291
 
229
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
292
+ def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
230
293
  """Insert documents into the index.
231
294
  This method is not supported by Upstash. Use `upsert` instead.
232
295
  Args:
233
296
  documents (List[Document]): The documents to insert.
234
297
  filters (Optional[Dict[str, Any]], optional): The filters for the insert. Defaults to None.
235
- Raises:
236
- NotImplementedError: This method is not supported by Upstash.
237
298
  """
238
- raise NotImplementedError("Upstash does not support insert operations. Use upsert instead.")
299
+ logger.warning("Upstash does not support insert operations. Using upsert instead.")
300
+ self.upsert(content_hash=content_hash, documents=documents, filters=filters)
239
301
 
240
302
  def search(
241
303
  self,
@@ -255,7 +317,7 @@ class UpstashVectorDb(VectorDb):
255
317
  """
256
318
  _namespace = self.namespace if namespace is None else namespace
257
319
 
258
- # filter_str = "" if filters is None else str(filters)
320
+ filter_str = "" if filters is None else str(filters)
259
321
 
260
322
  if not self.use_upstash_embeddings and self.embedder is not None:
261
323
  dense_embedding = self.embedder.get_embedding(query)
@@ -268,7 +330,7 @@ class UpstashVectorDb(VectorDb):
268
330
  vector=dense_embedding,
269
331
  namespace=_namespace,
270
332
  top_k=limit,
271
- # filter=filter_str,
333
+ filter=filter_str,
272
334
  include_data=True,
273
335
  include_metadata=True,
274
336
  include_vectors=True,
@@ -278,7 +340,7 @@ class UpstashVectorDb(VectorDb):
278
340
  data=query,
279
341
  namespace=_namespace,
280
342
  top_k=limit,
281
- # filter=filter_str,
343
+ filter=filter_str,
282
344
  include_data=True,
283
345
  include_metadata=True,
284
346
  include_vectors=True,
@@ -303,6 +365,7 @@ class UpstashVectorDb(VectorDb):
303
365
  if self.reranker:
304
366
  search_results = self.reranker.rerank(query=query, documents=search_results)
305
367
 
368
+ log_info(f"Found {len(search_results)} results")
306
369
  return search_results
307
370
 
308
371
  def delete(self, namespace: Optional[str] = None, delete_all: bool = False) -> bool:
@@ -330,5 +393,258 @@ class UpstashVectorDb(VectorDb):
330
393
  """
331
394
  pass
332
395
 
396
+ def delete_by_id(self, id: str) -> bool:
397
+ """Delete document by ID.
398
+
399
+ Args:
400
+ id (str): The document ID to delete
401
+
402
+ Returns:
403
+ bool: True if deletion was successful, False otherwise
404
+ """
405
+ try:
406
+ response = self.index.delete(ids=[id], namespace=self.namespace)
407
+ deleted_count = getattr(response, "deleted", 0)
408
+ logger.info(f"Deleted {deleted_count} document(s) with ID: {id}")
409
+ return True
410
+ except Exception as e:
411
+ logger.error(f"Error deleting document by ID {id}: {e}")
412
+ return False
413
+
414
+ def delete_by_name(self, name: str) -> bool:
415
+ """Delete documents by name using metadata filter.
416
+
417
+ Args:
418
+ name (str): The document name to delete
419
+
420
+ Returns:
421
+ bool: True if deletion was successful, False otherwise
422
+ """
423
+ try:
424
+ # Use Upstash's delete with metadata filter
425
+ response = self.index.delete(filter=f'name = "{name}"', namespace=self.namespace)
426
+ deleted_count = getattr(response, "deleted", 0)
427
+ logger.info(f"Deleted {deleted_count} document(s) with name: {name}")
428
+ return True
429
+ except Exception as e:
430
+ logger.error(f"Error deleting documents by name {name}: {e}")
431
+ return False
432
+
433
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
434
+ """Delete documents by metadata filter.
435
+
436
+ Args:
437
+ metadata (Dict[str, Any]): Metadata criteria for deletion
438
+
439
+ Returns:
440
+ bool: True if deletion was successful, False otherwise
441
+ """
442
+ try:
443
+ # Build filter string for Upstash metadata filtering
444
+ filter_parts = []
445
+ for key, value in metadata.items():
446
+ if isinstance(value, str):
447
+ filter_parts.append(f'{key} = "{value}"')
448
+ else:
449
+ filter_parts.append(f"{key} = {value}")
450
+
451
+ filter_str = " AND ".join(filter_parts)
452
+
453
+ response = self.index.delete(filter=filter_str, namespace=self.namespace)
454
+ deleted_count = getattr(response, "deleted", 0)
455
+ logger.info(f"Deleted {deleted_count} document(s) matching metadata: {metadata}")
456
+ return True
457
+ except Exception as e:
458
+ logger.error(f"Error deleting documents by metadata {metadata}: {e}")
459
+ return False
460
+
461
+ def delete_by_content_id(self, content_id: str) -> bool:
462
+ """Delete documents by content_id.
463
+
464
+ Args:
465
+ content_id (str): The content ID to delete
466
+
467
+ Returns:
468
+ bool: True if deletion was successful, False otherwise
469
+ """
470
+ return self.delete_by_metadata({"content_id": content_id})
471
+
472
+ async def async_insert(
473
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
474
+ ) -> None:
475
+ logger.warning("Upstash does not support async insert operations. Using upsert instead.")
476
+ await self.async_upsert(content_hash=content_hash, documents=documents, filters=filters)
477
+
478
+ async def async_exists(self) -> bool:
479
+ raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
480
+
333
481
  async def async_name_exists(self, name: str) -> bool:
334
482
  raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
483
+
484
+ async def async_create(self) -> None:
485
+ raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
486
+
487
+ async def async_drop(self) -> None:
488
+ raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
489
+
490
+ async def async_upsert(
491
+ self,
492
+ content_hash: str,
493
+ documents: List[Document],
494
+ filters: Optional[Dict[str, Any]] = None,
495
+ namespace: Optional[str] = None,
496
+ ) -> None:
497
+ """Async Upsert documents into the index.
498
+
499
+ Args:
500
+ documents (List[Document]): The documents to upsert.
501
+ filters (Optional[Dict[str, Any]], optional): The filters for the upsert. Defaults to None.
502
+ namespace (Optional[str], optional): The namespace for the documents. Defaults to None, which uses the instance namespace.
503
+ """
504
+ _namespace = self.namespace if namespace is None else namespace
505
+ vectors = []
506
+
507
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
508
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
509
+
510
+ for i, document in enumerate(documents):
511
+ if document.id is None:
512
+ logger.error(f"Document ID must not be None. Skipping document: {document.content[:100]}...")
513
+ continue
514
+
515
+ logger.debug(
516
+ f"Processing document {i + 1}: ID={document.id}, name={document.name}, "
517
+ f"content_id={getattr(document, 'content_id', 'N/A')}"
518
+ )
519
+
520
+ # Create a copy of metadata to avoid modifying the original document
521
+ meta_data = document.meta_data.copy() if document.meta_data else {}
522
+
523
+ # Add filters to document metadata if provided
524
+ if filters:
525
+ meta_data.update(filters)
526
+
527
+ meta_data["text"] = document.content
528
+
529
+ # Add content_id to metadata if it exists
530
+ if hasattr(document, "content_id") and document.content_id:
531
+ meta_data["content_id"] = document.content_id
532
+ else:
533
+ logger.warning(f"Document {document.id} has no content_id")
534
+
535
+ meta_data["content_hash"] = content_hash
536
+
537
+ # Add name to metadata if it exists
538
+ if document.name:
539
+ meta_data["name"] = document.name
540
+ else:
541
+ logger.warning(f"Document {document.id} has no name")
542
+
543
+ if not self.use_upstash_embeddings:
544
+ if self.embedder is None:
545
+ logger.error("Embedder is None but use_upstash_embeddings is False")
546
+ continue
547
+
548
+ if document.embedding is None:
549
+ logger.error(f"Failed to generate embedding for document: {document.id}")
550
+ continue
551
+
552
+ vector = Vector(id=document.id, vector=document.embedding, metadata=meta_data, data=document.content)
553
+ else:
554
+ vector = Vector(id=document.id, data=document.content, metadata=meta_data)
555
+ vectors.append(vector)
556
+
557
+ if not vectors:
558
+ logger.warning("No valid documents to upsert")
559
+ return
560
+
561
+ logger.info(f"Upserting {len(vectors)} vectors to Upstash with IDs: {[v.id for v in vectors[:5]]}...")
562
+ self.index.upsert(vectors, namespace=_namespace)
563
+
564
+ async def async_search(
565
+ self, query: str, limit: int = 5, filters: Optional[Dict[str, Any]] = None
566
+ ) -> List[Document]:
567
+ raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
568
+
569
+ def id_exists(self, id: str) -> bool:
570
+ """Check if a document with the given ID exists in the index.
571
+
572
+ Args:
573
+ id (str): The document ID to check.
574
+
575
+ Returns:
576
+ bool: True if the document exists, False otherwise.
577
+ """
578
+ try:
579
+ response = self.index.fetch(ids=[id], namespace=self.namespace)
580
+ return len(response) > 0
581
+ except Exception as e:
582
+ logger.error(f"Error checking if ID {id} exists: {e}")
583
+ return False
584
+
585
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
586
+ """Delete documents by content hash using metadata filter.
587
+
588
+ Args:
589
+ content_hash (str): The content hash to delete.
590
+
591
+ Returns:
592
+ bool: True if deletion was successful, False otherwise.
593
+ """
594
+ try:
595
+ response = self.index.delete(filter=f'content_hash = "{content_hash}"', namespace=self.namespace)
596
+ deleted_count = getattr(response, "deleted", 0)
597
+ logger.info(f"Deleted {deleted_count} document(s) with content_hash: {content_hash}")
598
+ return True
599
+ except Exception as e:
600
+ logger.error(f"Error deleting documents by content_hash {content_hash}: {e}")
601
+ return False
602
+
603
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
604
+ """
605
+ Update the metadata for documents with the given content_id.
606
+
607
+ Args:
608
+ content_id (str): The content ID to update
609
+ metadata (Dict[str, Any]): The metadata to update
610
+ """
611
+ try:
612
+ # Query for vectors with the given content_id
613
+ query_response = self.index.query(
614
+ filter=f'content_id = "{content_id}"',
615
+ top_k=1000, # Get all matching vectors
616
+ include_metadata=True,
617
+ namespace=self.namespace,
618
+ )
619
+
620
+ if not query_response or not hasattr(query_response, "__iter__"):
621
+ logger.debug(f"No documents found with content_id: {content_id}")
622
+ return
623
+
624
+ # Update each matching vector
625
+ updated_count = 0
626
+ for result in query_response:
627
+ if hasattr(result, "id") and hasattr(result, "metadata"):
628
+ vector_id = result.id
629
+ current_metadata = result.metadata or {}
630
+
631
+ # Merge existing metadata with new metadata
632
+ updated_metadata = current_metadata.copy()
633
+ updated_metadata.update(metadata)
634
+
635
+ if "filters" not in updated_metadata:
636
+ updated_metadata["filters"] = {}
637
+ if isinstance(updated_metadata["filters"], dict):
638
+ updated_metadata["filters"].update(metadata)
639
+ else:
640
+ updated_metadata["filters"] = metadata
641
+
642
+ # Update the vector metadata
643
+ self.index.update(id=vector_id, metadata=updated_metadata, namespace=self.namespace)
644
+ updated_count += 1
645
+
646
+ logger.debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
647
+
648
+ except Exception as e:
649
+ logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
650
+ raise