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
@@ -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