agno 1.8.1__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +11 -66
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1743 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1432 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +882 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1045 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1416 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +15 -11
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1551 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +46 -151
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +85 -47
  158. agno/models/openai/chat.py +154 -37
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +15 -9
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +497 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +77 -33
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +32 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import json
2
3
  from hashlib import md5
3
4
  from typing import Any, Dict, List, Optional
@@ -8,17 +9,15 @@ try:
8
9
  from sqlalchemy.inspection import inspect
9
10
  from sqlalchemy.orm import Session, sessionmaker
10
11
  from sqlalchemy.schema import Column, MetaData, Table
11
- from sqlalchemy.sql.expression import func, select, text
12
+ from sqlalchemy.sql.expression import func, select, text, update
12
13
  from sqlalchemy.types import DateTime
13
14
  except ImportError:
14
15
  raise ImportError("`sqlalchemy` not installed")
15
16
 
16
- from agno.document import Document
17
- from agno.embedder import Embedder
18
- from agno.reranker.base import Reranker
19
-
20
- # from agno.vectordb.singlestore.index import Ivfflat, HNSWFlat
21
- from agno.utils.log import log_debug, log_info, logger
17
+ from agno.knowledge.document import Document
18
+ from agno.knowledge.embedder import Embedder
19
+ from agno.knowledge.reranker.base import Reranker
20
+ from agno.utils.log import log_debug, log_error, log_info
22
21
  from agno.vectordb.base import VectorDb
23
22
  from agno.vectordb.distance import Distance
24
23
 
@@ -49,7 +48,7 @@ class SingleStore(VectorDb):
49
48
  self.metadata: MetaData = MetaData(schema=self.schema)
50
49
 
51
50
  if embedder is None:
52
- from agno.embedder.openai import OpenAIEmbedder
51
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
53
52
 
54
53
  embedder = OpenAIEmbedder()
55
54
  log_info("Embedder not provided, using OpenAIEmbedder as default.")
@@ -81,6 +80,7 @@ class SingleStore(VectorDb):
81
80
  Column("created_at", DateTime(timezone=True), server_default=text("now()")),
82
81
  Column("updated_at", DateTime(timezone=True), onupdate=text("now()")),
83
82
  Column("content_hash", mysql.TEXT),
83
+ Column("content_id", mysql.TEXT),
84
84
  extend_existing=True,
85
85
  )
86
86
 
@@ -102,7 +102,8 @@ class SingleStore(VectorDb):
102
102
  `usage` TEXT,
103
103
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
104
104
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
105
- content_hash TEXT
105
+ content_hash TEXT,
106
+ content_id TEXT
106
107
  );
107
108
  """)
108
109
  )
@@ -120,20 +121,18 @@ class SingleStore(VectorDb):
120
121
  try:
121
122
  return inspect(self.db_engine).has_table(self.table.name, schema=self.schema)
122
123
  except Exception as e:
123
- logger.error(e)
124
+ log_error(e)
124
125
  return False
125
126
 
126
- def doc_exists(self, document: Document) -> bool:
127
+ def content_hash_exists(self, content_hash: str) -> bool:
127
128
  """
128
129
  Validating if the document exists or not
129
130
 
130
131
  Args:
131
132
  document (Document): Document to validate
132
133
  """
133
- columns = [self.table.c.name, self.table.c.content_hash]
134
134
  with self.Session.begin() as sess:
135
- cleaned_content = document.content.replace("\x00", "\ufffd")
136
- stmt = select(*columns).where(self.table.c.content_hash == md5(cleaned_content.encode()).hexdigest())
135
+ stmt = select(self.table.c.name).where(self.table.c.content_hash == content_hash)
137
136
  result = sess.execute(stmt).first()
138
137
  return result is not None
139
138
 
@@ -161,7 +160,13 @@ class SingleStore(VectorDb):
161
160
  result = sess.execute(stmt).first()
162
161
  return result is not None
163
162
 
164
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None, batch_size: int = 10) -> None:
163
+ def insert(
164
+ self,
165
+ content_hash: str,
166
+ documents: List[Document],
167
+ filters: Optional[Dict[str, Any]] = None,
168
+ batch_size: int = 10,
169
+ ) -> None:
165
170
  """
166
171
  Insert documents into the table.
167
172
 
@@ -175,8 +180,8 @@ class SingleStore(VectorDb):
175
180
  for document in documents:
176
181
  document.embed(embedder=self.embedder)
177
182
  cleaned_content = document.content.replace("\x00", "\ufffd")
178
- content_hash = md5(cleaned_content.encode()).hexdigest()
179
- _id = document.id or content_hash
183
+ record_id = md5(cleaned_content.encode()).hexdigest()
184
+ _id = document.id or record_id
180
185
 
181
186
  meta_data_json = json.dumps(document.meta_data)
182
187
  usage_json = json.dumps(document.usage)
@@ -192,6 +197,7 @@ class SingleStore(VectorDb):
192
197
  embedding=embeddings,
193
198
  usage=usage_json,
194
199
  content_hash=content_hash,
200
+ content_id=document.content_id,
195
201
  )
196
202
  sess.execute(stmt)
197
203
  counter += 1
@@ -204,7 +210,24 @@ class SingleStore(VectorDb):
204
210
  """Indicate that upsert functionality is available."""
205
211
  return True
206
212
 
207
- def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None, batch_size: int = 20) -> None:
213
+ def upsert(
214
+ self,
215
+ content_hash: str,
216
+ documents: List[Document],
217
+ filters: Optional[Dict[str, Any]] = None,
218
+ batch_size: int = 20,
219
+ ) -> None:
220
+ if self.content_hash_exists(content_hash):
221
+ self._delete_by_content_hash(content_hash)
222
+ self._upsert(content_hash=content_hash, documents=documents, filters=filters, batch_size=batch_size)
223
+
224
+ def _upsert(
225
+ self,
226
+ content_hash: str,
227
+ documents: List[Document],
228
+ filters: Optional[Dict[str, Any]] = None,
229
+ batch_size: int = 20,
230
+ ) -> None:
208
231
  """
209
232
  Upsert (insert or update) documents in the table.
210
233
 
@@ -218,8 +241,8 @@ class SingleStore(VectorDb):
218
241
  for document in documents:
219
242
  document.embed(embedder=self.embedder)
220
243
  cleaned_content = document.content.replace("\x00", "\ufffd")
221
- content_hash = md5(cleaned_content.encode()).hexdigest()
222
- _id = document.id or content_hash
244
+ record_id = md5(cleaned_content.encode()).hexdigest()
245
+ _id = document.id or record_id
223
246
 
224
247
  meta_data_json = json.dumps(document.meta_data)
225
248
  usage_json = json.dumps(document.usage)
@@ -236,6 +259,7 @@ class SingleStore(VectorDb):
236
259
  embedding=embeddings,
237
260
  usage=usage_json,
238
261
  content_hash=content_hash,
262
+ content_id=document.content_id,
239
263
  )
240
264
  .on_duplicate_key_update(
241
265
  name=document.name,
@@ -244,6 +268,7 @@ class SingleStore(VectorDb):
244
268
  embedding=embeddings,
245
269
  usage=usage_json,
246
270
  content_hash=content_hash,
271
+ content_id=document.content_id,
247
272
  )
248
273
  )
249
274
  sess.execute(stmt)
@@ -267,7 +292,7 @@ class SingleStore(VectorDb):
267
292
  """
268
293
  query_embedding = self.embedder.get_embedding(query)
269
294
  if query_embedding is None:
270
- logger.error(f"Error getting embedding for Query: {query}")
295
+ log_error(f"Error getting embedding for Query: {query}")
271
296
  return []
272
297
 
273
298
  columns = [
@@ -276,6 +301,7 @@ class SingleStore(VectorDb):
276
301
  self.table.c.content,
277
302
  self.table.c.embedding,
278
303
  self.table.c.usage,
304
+ self.table.c.content_id,
279
305
  ]
280
306
 
281
307
  stmt = select(*columns)
@@ -326,7 +352,7 @@ class SingleStore(VectorDb):
326
352
  try:
327
353
  embedding_list = json.loads(neighbor.embedding)
328
354
  except Exception as e:
329
- logger.error(f"Error extracting vector: {e}")
355
+ log_error(f"Error extracting vector: {e}")
330
356
  embedding_list = []
331
357
 
332
358
  search_results.append(
@@ -393,22 +419,178 @@ class SingleStore(VectorDb):
393
419
  sess.execute(stmt)
394
420
  return True
395
421
 
422
+ def delete_by_id(self, id: str) -> bool:
423
+ """
424
+ Delete a document by its ID.
425
+ """
426
+ from sqlalchemy import delete
427
+
428
+ try:
429
+ with self.Session.begin() as sess:
430
+ stmt = delete(self.table).where(self.table.c.id == id)
431
+ result = sess.execute(stmt)
432
+ log_info(f"Deleted {result.rowcount} records with ID {id} from table '{self.table.name}'.")
433
+ return result.rowcount > 0
434
+ except Exception as e:
435
+ log_error(f"Error deleting document with ID {id}: {e}")
436
+ return False
437
+
438
+ def delete_by_content_id(self, content_id: str) -> bool:
439
+ """
440
+ Delete a document by its content ID.
441
+ """
442
+ from sqlalchemy import delete
443
+
444
+ try:
445
+ with self.Session.begin() as sess:
446
+ stmt = delete(self.table).where(self.table.c.content_id == content_id)
447
+ result = sess.execute(stmt)
448
+ log_info(
449
+ f"Deleted {result.rowcount} records with content_id {content_id} from table '{self.table.name}'."
450
+ )
451
+ return result.rowcount > 0
452
+ except Exception as e:
453
+ log_error(f"Error deleting document with content_id {content_id}: {e}")
454
+ return False
455
+
456
+ def delete_by_name(self, name: str) -> bool:
457
+ """
458
+ Delete a document by its name.
459
+ """
460
+ from sqlalchemy import delete
461
+
462
+ try:
463
+ with self.Session.begin() as sess:
464
+ stmt = delete(self.table).where(self.table.c.name == name)
465
+ result = sess.execute(stmt)
466
+ log_info(f"Deleted {result.rowcount} records with name '{name}' from table '{self.table.name}'.")
467
+ return result.rowcount > 0
468
+ except Exception as e:
469
+ log_error(f"Error deleting document with name {name}: {e}")
470
+ return False
471
+
472
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
473
+ """
474
+ Delete documents by metadata.
475
+ """
476
+ from sqlalchemy import delete
477
+
478
+ try:
479
+ with self.Session.begin() as sess:
480
+ # Convert metadata to JSON string for comparison
481
+ metadata_json = json.dumps(metadata, sort_keys=True)
482
+ stmt = delete(self.table).where(self.table.c.meta_data == metadata_json)
483
+ result = sess.execute(stmt)
484
+ log_info(f"Deleted {result.rowcount} records with metadata {metadata} from table '{self.table.name}'.")
485
+ return result.rowcount > 0
486
+ except Exception as e:
487
+ log_error(f"Error deleting documents with metadata {metadata}: {e}")
488
+ return False
489
+
396
490
  async def async_create(self) -> None:
397
491
  raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
398
492
 
399
- async def async_doc_exists(self, document: Document) -> bool:
400
- raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
493
+ async def async_insert(
494
+ self,
495
+ content_hash: str,
496
+ documents: List[Document],
497
+ filters: Optional[Dict[str, Any]] = None,
498
+ ) -> None:
499
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
500
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
401
501
 
402
- async def async_insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
403
- raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
502
+ with self.Session.begin() as sess:
503
+ counter = 0
504
+ for document in documents:
505
+ cleaned_content = document.content.replace("\x00", "\ufffd")
506
+ record_id = md5(cleaned_content.encode()).hexdigest()
507
+ _id = document.id or record_id
404
508
 
405
- async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
406
- raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
509
+ meta_data_json = json.dumps(document.meta_data)
510
+ usage_json = json.dumps(document.usage)
511
+
512
+ # Convert embedding list to SingleStore VECTOR format
513
+ embeddings = f"[{','.join(map(str, document.embedding))}]" if document.embedding else None
514
+
515
+ stmt = mysql.insert(self.table).values(
516
+ id=_id,
517
+ name=document.name,
518
+ meta_data=meta_data_json,
519
+ content=cleaned_content,
520
+ embedding=embeddings,
521
+ usage=usage_json,
522
+ content_hash=content_hash,
523
+ content_id=document.content_id,
524
+ )
525
+ sess.execute(stmt)
526
+ counter += 1
527
+ log_debug(f"Inserted document: {document.name} ({document.meta_data})")
528
+
529
+ sess.commit()
530
+ log_debug(f"Committed {counter} documents")
531
+
532
+ async def async_upsert(
533
+ self,
534
+ content_hash: str,
535
+ documents: List[Document],
536
+ filters: Optional[Dict[str, Any]] = None,
537
+ ) -> None:
538
+ """
539
+ Upsert (insert or update) documents in the table.
540
+
541
+ Args:
542
+ documents (List[Document]): List of documents to upsert.
543
+ filters (Optional[Dict[str, Any]]): Optional filters for the upsert.
544
+ batch_size (int): Number of documents to upsert in each batch.
545
+ """
546
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
547
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
548
+
549
+ with self.Session.begin() as sess:
550
+ counter = 0
551
+ for document in documents:
552
+ cleaned_content = document.content.replace("\x00", "\ufffd")
553
+ record_id = md5(cleaned_content.encode()).hexdigest()
554
+ _id = document.id or record_id
555
+
556
+ meta_data_json = json.dumps(document.meta_data)
557
+ usage_json = json.dumps(document.usage)
558
+
559
+ # Convert embedding list to SingleStore VECTOR format
560
+ embeddings = f"[{','.join(map(str, document.embedding))}]" if document.embedding else None
561
+ stmt = (
562
+ mysql.insert(self.table)
563
+ .values(
564
+ id=_id,
565
+ name=document.name,
566
+ meta_data=meta_data_json,
567
+ content=cleaned_content,
568
+ embedding=embeddings,
569
+ usage=usage_json,
570
+ content_hash=content_hash,
571
+ content_id=document.content_id,
572
+ )
573
+ .on_duplicate_key_update(
574
+ name=document.name,
575
+ meta_data=meta_data_json,
576
+ content=cleaned_content,
577
+ embedding=embeddings,
578
+ usage=usage_json,
579
+ content_hash=content_hash,
580
+ content_id=document.content_id,
581
+ )
582
+ )
583
+ sess.execute(stmt)
584
+ counter += 1
585
+ log_debug(f"Upserted document: {document.name} ({document.meta_data})")
586
+
587
+ sess.commit()
588
+ log_debug(f"Committed {counter} documents")
407
589
 
408
590
  async def async_search(
409
591
  self, query: str, limit: int = 5, filters: Optional[Dict[str, Any]] = None
410
592
  ) -> List[Document]:
411
- raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
593
+ return self.search(query=query, limit=limit, filters=filters)
412
594
 
413
595
  async def async_drop(self) -> None:
414
596
  raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
@@ -418,3 +600,78 @@ class SingleStore(VectorDb):
418
600
 
419
601
  async def async_name_exists(self, name: str) -> bool:
420
602
  raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
603
+
604
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
605
+ """
606
+ Delete documents by their content hash.
607
+
608
+ Args:
609
+ content_hash (str): The content hash to delete.
610
+
611
+ Returns:
612
+ bool: True if documents were deleted, False otherwise.
613
+ """
614
+ from sqlalchemy import delete
615
+
616
+ try:
617
+ with self.Session.begin() as sess:
618
+ stmt = delete(self.table).where(self.table.c.content_hash == content_hash)
619
+ result = sess.execute(stmt)
620
+ log_info(
621
+ f"Deleted {result.rowcount} records with content_hash '{content_hash}' from table '{self.table.name}'."
622
+ )
623
+ return result.rowcount > 0
624
+ except Exception as e:
625
+ log_error(f"Error deleting documents with content_hash {content_hash}: {e}")
626
+ return False
627
+
628
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
629
+ """
630
+ Update the metadata for documents with the given content_id.
631
+
632
+ Args:
633
+ content_id (str): The content ID to update
634
+ metadata (Dict[str, Any]): The metadata to update
635
+ """
636
+ import json
637
+
638
+ try:
639
+ with self.Session.begin() as sess:
640
+ # Find documents with the given content_id
641
+ stmt = select(self.table).where(self.table.c.content_id == content_id)
642
+ result = sess.execute(stmt)
643
+
644
+ updated_count = 0
645
+ for row in result:
646
+ # Parse existing metadata
647
+ current_metadata = json.loads(row.meta_data) if row.meta_data else {}
648
+
649
+ # Merge existing metadata with new metadata
650
+ updated_metadata = current_metadata.copy()
651
+ updated_metadata.update(metadata)
652
+
653
+ # Also update filters field within the metadata JSON
654
+ if "filters" not in updated_metadata:
655
+ updated_metadata["filters"] = {}
656
+ if isinstance(updated_metadata["filters"], dict):
657
+ updated_metadata["filters"].update(metadata)
658
+ else:
659
+ updated_metadata["filters"] = metadata
660
+
661
+ # Update the document (only meta_data column exists)
662
+ update_stmt = (
663
+ update(self.table)
664
+ .where(self.table.c.id == row.id)
665
+ .values(meta_data=json.dumps(updated_metadata))
666
+ )
667
+ sess.execute(update_stmt)
668
+ updated_count += 1
669
+
670
+ if updated_count == 0:
671
+ log_debug(f"No documents found with content_id: {content_id}")
672
+ else:
673
+ log_debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
674
+
675
+ except Exception as e:
676
+ log_error(f"Error updating metadata for content_id '{content_id}': {e}")
677
+ raise