agno 2.2.13__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 (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,501 @@
1
+ import asyncio
2
+ from typing import Any, Dict, Iterable, List, Optional, Union
3
+
4
+ from agno.filters import FilterExpr
5
+ from agno.knowledge.document import Document
6
+ from agno.knowledge.embedder import Embedder
7
+ from agno.utils.log import log_debug, log_error, log_info, log_warning
8
+ from agno.vectordb.base import VectorDb
9
+ from agno.vectordb.cassandra.index import AgnoMetadataVectorCassandraTable
10
+
11
+
12
+ class Cassandra(VectorDb):
13
+ def __init__(
14
+ self,
15
+ table_name: str,
16
+ keyspace: str,
17
+ embedder: Optional[Embedder] = None,
18
+ session=None,
19
+ name: Optional[str] = None,
20
+ description: Optional[str] = None,
21
+ ) -> None:
22
+ if not table_name:
23
+ raise ValueError("Table name must be provided.")
24
+
25
+ if not session:
26
+ raise ValueError("Session is not provided")
27
+
28
+ if not keyspace:
29
+ raise ValueError("Keyspace must be provided")
30
+
31
+ if embedder is None:
32
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
33
+
34
+ embedder = OpenAIEmbedder()
35
+ log_info("Embedder not provided, using OpenAIEmbedder as default.")
36
+ # Initialize base class with name and description
37
+ super().__init__(name=name, description=description)
38
+
39
+ self.table_name: str = table_name
40
+ self.embedder: Embedder = embedder
41
+ self.session = session
42
+ self.keyspace: str = keyspace
43
+ self.initialize_table()
44
+
45
+ def initialize_table(self):
46
+ self.table = AgnoMetadataVectorCassandraTable(
47
+ session=self.session,
48
+ keyspace=self.keyspace,
49
+ vector_dimension=1024,
50
+ table=self.table_name,
51
+ primary_key_type="TEXT",
52
+ )
53
+
54
+ def create(self) -> None:
55
+ """Create the table in Cassandra for storing vectors and metadata."""
56
+ if not self.exists():
57
+ log_debug(f"Cassandra VectorDB : Creating table {self.table_name}")
58
+ self.initialize_table()
59
+
60
+ async def async_create(self) -> None:
61
+ """Create the table asynchronously by running in a thread."""
62
+ await asyncio.to_thread(self.create)
63
+
64
+ def _row_to_document(self, row: Dict[str, Any]) -> Document:
65
+ metadata = row["metadata"]
66
+ return Document(
67
+ id=row["row_id"],
68
+ content=row["body_blob"],
69
+ meta_data=metadata,
70
+ embedding=row["vector"],
71
+ name=row["document_name"],
72
+ content_id=metadata.get("content_id"),
73
+ )
74
+
75
+ def name_exists(self, name: str) -> bool:
76
+ """Check if a document exists by name."""
77
+ query = f"SELECT COUNT(*) FROM {self.keyspace}.{self.table_name} WHERE document_name = %s ALLOW FILTERING"
78
+ result = self.session.execute(query, (name,))
79
+ return result.one()[0] > 0
80
+
81
+ async def async_name_exists(self, name: str) -> bool:
82
+ """Check if a document with given name exists asynchronously."""
83
+ return await asyncio.to_thread(self.name_exists, name)
84
+
85
+ def id_exists(self, id: str) -> bool:
86
+ """Check if a document exists by ID."""
87
+ query = f"SELECT COUNT(*) FROM {self.keyspace}.{self.table_name} WHERE row_id = %s ALLOW FILTERING"
88
+ result = self.session.execute(query, (id,))
89
+ return result.one()[0] > 0
90
+
91
+ def content_hash_exists(self, content_hash: str) -> bool:
92
+ """Check if a document exists by content hash."""
93
+ query = f"SELECT COUNT(*) FROM {self.keyspace}.{self.table_name} WHERE metadata_s['content_hash'] = %s ALLOW FILTERING"
94
+ result = self.session.execute(query, (content_hash,))
95
+ return result.one()[0] > 0
96
+
97
+ def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
98
+ log_info(f"Cassandra VectorDB : Inserting Documents to the table {self.table_name}")
99
+ futures = []
100
+ for doc in documents:
101
+ doc.embed(embedder=self.embedder)
102
+ metadata = {key: str(value) for key, value in doc.meta_data.items()}
103
+ metadata.update(filters or {})
104
+ metadata["content_id"] = doc.content_id or ""
105
+ metadata["content_hash"] = content_hash
106
+ futures.append(
107
+ self.table.put_async(
108
+ row_id=doc.id,
109
+ vector=doc.embedding,
110
+ metadata=metadata or {},
111
+ body_blob=doc.content,
112
+ document_name=doc.name,
113
+ )
114
+ )
115
+
116
+ for f in futures:
117
+ f.result()
118
+
119
+ async def async_insert(
120
+ self,
121
+ content_hash: str,
122
+ documents: List[Document],
123
+ filters: Optional[Dict[str, Any]] = None,
124
+ ) -> None:
125
+ """Insert documents asynchronously by running in a thread."""
126
+ log_info(f"Cassandra VectorDB : Inserting Documents to the table {self.table_name}")
127
+
128
+ if self.embedder.enable_batch and hasattr(self.embedder, "async_get_embeddings_batch_and_usage"):
129
+ # Use batch embedding when enabled and supported
130
+ try:
131
+ # Extract content from all documents
132
+ doc_contents = [doc.content for doc in documents]
133
+
134
+ # Get batch embeddings and usage
135
+ embeddings, usages = await self.embedder.async_get_embeddings_batch_and_usage(doc_contents)
136
+
137
+ # Process documents with pre-computed embeddings
138
+ for j, doc in enumerate(documents):
139
+ try:
140
+ if j < len(embeddings):
141
+ doc.embedding = embeddings[j]
142
+ doc.usage = usages[j] if j < len(usages) else None
143
+ except Exception as e:
144
+ log_error(f"Error assigning batch embedding to document '{doc.name}': {e}")
145
+
146
+ except Exception as e:
147
+ # Check if this is a rate limit error - don't fall back as it would make things worse
148
+ error_str = str(e).lower()
149
+ is_rate_limit = any(
150
+ phrase in error_str
151
+ for phrase in ["rate limit", "too many requests", "429", "trial key", "api calls / minute"]
152
+ )
153
+
154
+ if is_rate_limit:
155
+ log_error(f"Rate limit detected during batch embedding. {e}")
156
+ raise e
157
+ else:
158
+ log_error(f"Async batch embedding failed, falling back to individual embeddings: {e}")
159
+ # Fall back to individual embedding
160
+ for doc in documents:
161
+ try:
162
+ embed_tasks = [doc.async_embed(embedder=self.embedder)]
163
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
164
+ except Exception as e:
165
+ log_error(f"Error processing document '{doc.name}': {e}")
166
+ else:
167
+ # Use individual embedding (original behavior)
168
+ for doc in documents:
169
+ try:
170
+ embed_tasks = [doc.async_embed(embedder=self.embedder)]
171
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
172
+ except Exception as e:
173
+ log_error(f"Error processing document '{doc.name}': {e}")
174
+
175
+ futures = []
176
+ for doc in documents:
177
+ metadata = {key: str(value) for key, value in doc.meta_data.items()}
178
+ metadata.update(filters or {})
179
+ metadata["content_id"] = doc.content_id or ""
180
+ metadata["content_hash"] = content_hash
181
+ futures.append(
182
+ self.table.put_async(
183
+ row_id=doc.id,
184
+ vector=doc.embedding,
185
+ metadata=metadata or {},
186
+ body_blob=doc.content,
187
+ document_name=doc.name,
188
+ )
189
+ )
190
+
191
+ for f in futures:
192
+ f.result()
193
+
194
+ def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
195
+ """Insert or update documents based on primary key."""
196
+ if self.content_hash_exists(content_hash):
197
+ self.delete_by_content_hash(content_hash)
198
+ self.insert(content_hash, documents, filters)
199
+
200
+ async def async_upsert(
201
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
202
+ ) -> None:
203
+ """Upsert documents asynchronously by running in a thread."""
204
+ if self.content_hash_exists(content_hash):
205
+ self.delete_by_content_hash(content_hash)
206
+ await self.async_insert(content_hash, documents, filters)
207
+
208
+ def search(
209
+ self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
210
+ ) -> List[Document]:
211
+ """Keyword-based search on document metadata."""
212
+ log_debug(f"Cassandra VectorDB : Performing Vector Search on {self.table_name} with query {query}")
213
+ if filters is not None:
214
+ log_warning("Filters are not yet supported in Cassandra. No filters will be applied.")
215
+ return self.vector_search(query=query, limit=limit)
216
+
217
+ async def async_search(
218
+ self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
219
+ ) -> List[Document]:
220
+ """Search asynchronously by running in a thread."""
221
+ return await asyncio.to_thread(self.search, query, limit, filters)
222
+
223
+ def _search_to_documents(
224
+ self,
225
+ hits: Iterable[Dict[str, Any]],
226
+ ) -> List[Document]:
227
+ return [self._row_to_document(row=hit) for hit in hits]
228
+
229
+ def vector_search(
230
+ self, query: str, limit: int = 5, filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None
231
+ ) -> List[Document]:
232
+ """Vector similarity search implementation."""
233
+ query_embedding = self.embedder.get_embedding(query)
234
+ hits = list(
235
+ self.table.metric_ann_search(
236
+ vector=query_embedding,
237
+ n=limit,
238
+ metric="cos",
239
+ )
240
+ )
241
+ d = self._search_to_documents(hits)
242
+ return d
243
+
244
+ def drop(self) -> None:
245
+ """Drop the vector table in Cassandra."""
246
+ log_debug(f"Cassandra VectorDB : Dropping Table {self.table_name}")
247
+ drop_table_query = f"DROP TABLE IF EXISTS {self.keyspace}.{self.table_name}"
248
+ self.session.execute(drop_table_query)
249
+
250
+ async def async_drop(self) -> None:
251
+ """Drop the table asynchronously by running in a thread."""
252
+ await asyncio.to_thread(self.drop)
253
+
254
+ def exists(self) -> bool:
255
+ """Check if the table exists in Cassandra."""
256
+ check_table_query = """
257
+ SELECT * FROM system_schema.tables
258
+ WHERE keyspace_name = %s AND table_name = %s
259
+ """
260
+ result = self.session.execute(check_table_query, (self.keyspace, self.table_name))
261
+ return bool(result.one())
262
+
263
+ async def async_exists(self) -> bool:
264
+ """Check if table exists asynchronously by running in a thread."""
265
+ return await asyncio.to_thread(self.exists)
266
+
267
+ def delete(self) -> bool:
268
+ """Delete all documents in the table."""
269
+ log_debug(f"Cassandra VectorDB : Clearing the table {self.table_name}")
270
+ self.table.clear()
271
+ return True
272
+
273
+ def delete_by_id(self, id: str) -> bool:
274
+ """
275
+ Delete a document by its ID.
276
+
277
+ Args:
278
+ id (str): The document ID to delete
279
+
280
+ Returns:
281
+ bool: True if document was deleted, False otherwise
282
+ """
283
+ try:
284
+ log_debug(f"Cassandra VectorDB : Deleting document with ID {id}")
285
+ # Check if document exists before deletion
286
+ if not self.id_exists(id):
287
+ return False
288
+
289
+ query = f"DELETE FROM {self.keyspace}.{self.table_name} WHERE row_id = %s"
290
+ self.session.execute(query, (id,))
291
+ return True
292
+ except Exception as e:
293
+ log_info(f"Error deleting document with ID {id}: {e}")
294
+ return False
295
+
296
+ def delete_by_name(self, name: str) -> bool:
297
+ """
298
+ Delete documents by name.
299
+
300
+ Args:
301
+ name (str): The document name to delete
302
+
303
+ Returns:
304
+ bool: True if documents were deleted, False otherwise
305
+ """
306
+ try:
307
+ log_debug(f"Cassandra VectorDB : Deleting documents with name {name}")
308
+ # Check if document exists before deletion
309
+ if not self.name_exists(name):
310
+ return False
311
+
312
+ # Query to find documents with matching name
313
+ query = f"SELECT row_id, document_name FROM {self.keyspace}.{self.table_name} ALLOW FILTERING"
314
+ result = self.session.execute(query)
315
+
316
+ deleted_count = 0
317
+ for row in result:
318
+ # Check if the row's document_name matches our criteria
319
+ # Use attribute access for Row objects
320
+ row_name = getattr(row, "document_name", None)
321
+ if row_name == name:
322
+ # Delete this specific document
323
+ delete_query = f"DELETE FROM {self.keyspace}.{self.table_name} WHERE row_id = %s"
324
+ self.session.execute(delete_query, (getattr(row, "row_id"),))
325
+ deleted_count += 1
326
+
327
+ return deleted_count > 0
328
+ except Exception as e:
329
+ log_info(f"Error deleting documents with name {name}: {e}")
330
+ return False
331
+
332
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
333
+ """
334
+ Delete documents by metadata.
335
+
336
+ Args:
337
+ metadata (Dict[str, Any]): The metadata to match for deletion
338
+
339
+ Returns:
340
+ bool: True if documents were deleted, False otherwise
341
+ """
342
+ try:
343
+ log_debug(f"Cassandra VectorDB : Deleting documents with metadata {metadata}")
344
+ # For metadata deletion, we need to query first to find matching documents
345
+ # Then delete them by their IDs
346
+ query = f"SELECT row_id, metadata_s FROM {self.keyspace}.{self.table_name} ALLOW FILTERING"
347
+ result = self.session.execute(query)
348
+
349
+ deleted_count = 0
350
+ for row in result:
351
+ # Check if the row's metadata matches our criteria
352
+ # Use attribute access for Row objects
353
+ row_metadata = getattr(row, "metadata_s", {})
354
+ if self._metadata_matches(row_metadata, metadata):
355
+ # Delete this specific document
356
+ delete_query = f"DELETE FROM {self.keyspace}.{self.table_name} WHERE row_id = %s"
357
+ self.session.execute(delete_query, (getattr(row, "row_id"),))
358
+ deleted_count += 1
359
+
360
+ return deleted_count > 0
361
+ except Exception as e:
362
+ log_debug(f"Error deleting documents with metadata {metadata}: {e}")
363
+ return False
364
+
365
+ def delete_by_content_id(self, content_id: str) -> bool:
366
+ """
367
+ Delete documents by content ID.
368
+
369
+ Args:
370
+ content_id (str): The content ID to delete
371
+
372
+ Returns:
373
+ bool: True if documents were deleted, False otherwise
374
+ """
375
+ try:
376
+ log_debug(f"Cassandra VectorDB : Deleting documents with content_id {content_id}")
377
+ # Query to find documents with matching content_id in metadata
378
+ query = f"SELECT row_id, metadata_s FROM {self.keyspace}.{self.table_name} ALLOW FILTERING"
379
+ result = self.session.execute(query)
380
+ deleted_count = 0
381
+ for row in result:
382
+ # Check if the row's metadata contains the content_id
383
+ # Use attribute access for Row objects
384
+ row_metadata = getattr(row, "metadata_s", {})
385
+ if row_metadata.get("content_id") == content_id:
386
+ # Delete this specific document
387
+ delete_query = f"DELETE FROM {self.keyspace}.{self.table_name} WHERE row_id = %s"
388
+ self.session.execute(delete_query, (getattr(row, "row_id"),))
389
+ deleted_count += 1
390
+
391
+ return deleted_count > 0
392
+ except Exception as e:
393
+ log_info(f"Error deleting documents with content_id {content_id}: {e}")
394
+ return False
395
+
396
+ def delete_by_content_hash(self, content_hash: str) -> bool:
397
+ """
398
+ Delete documents by content hash.
399
+
400
+ Args:
401
+ content_hash (str): The content hash to delete
402
+
403
+ Returns:
404
+ bool: True if documents were deleted, False otherwise
405
+ """
406
+ try:
407
+ log_debug(f"Cassandra VectorDB : Deleting documents with content_hash {content_hash}")
408
+ # Query to find documents with matching content_hash in metadata
409
+ query = f"SELECT row_id, metadata_s FROM {self.keyspace}.{self.table_name} ALLOW FILTERING"
410
+ result = self.session.execute(query)
411
+ deleted_count = 0
412
+ for row in result:
413
+ # Check if the row's metadata contains the content_hash
414
+ # Use attribute access for Row objects
415
+ row_metadata = getattr(row, "metadata_s", {})
416
+ if row_metadata.get("content_hash") == content_hash:
417
+ # Delete this specific document
418
+ delete_query = f"DELETE FROM {self.keyspace}.{self.table_name} WHERE row_id = %s"
419
+ self.session.execute(delete_query, (getattr(row, "row_id"),))
420
+ deleted_count += 1
421
+
422
+ return deleted_count > 0
423
+ except Exception as e:
424
+ log_info(f"Error deleting documents with content_hash {content_hash}: {e}")
425
+ return False
426
+
427
+ def _metadata_matches(self, row_metadata: Dict[str, Any], target_metadata: Dict[str, Any]) -> bool:
428
+ """
429
+ Check if row metadata matches target metadata criteria.
430
+
431
+ Args:
432
+ row_metadata (Dict[str, Any]): The metadata from the database row
433
+ target_metadata (Dict[str, Any]): The target metadata to match against
434
+
435
+ Returns:
436
+ bool: True if metadata matches, False otherwise
437
+ """
438
+ try:
439
+ for key, value in target_metadata.items():
440
+ if key not in row_metadata:
441
+ return False
442
+
443
+ # Handle boolean values specially
444
+ if isinstance(value, bool):
445
+ if row_metadata[key] != value:
446
+ return False
447
+ else:
448
+ # For non-boolean values, convert to string for comparison
449
+ if row_metadata[key] != str(value):
450
+ return False
451
+ return True
452
+ except Exception:
453
+ return False
454
+
455
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
456
+ """
457
+ Update the metadata for a document.
458
+
459
+ Args:
460
+ content_id (str): The content ID to update
461
+ metadata (Dict[str, Any]): The metadata to update
462
+ """
463
+ try:
464
+ log_debug(f"Cassandra VectorDB : Updating metadata for content_id {content_id}")
465
+
466
+ # First, find all documents with the given content_id
467
+ query = f"SELECT row_id, metadata_s FROM {self.keyspace}.{self.table_name} ALLOW FILTERING"
468
+ result = self.session.execute(query)
469
+
470
+ updated_count = 0
471
+ for row in result:
472
+ row_metadata = getattr(row, "metadata_s", {})
473
+ if row_metadata.get("content_id") == content_id:
474
+ # Merge existing metadata with new metadata
475
+ updated_metadata = row_metadata.copy()
476
+ # Convert new metadata values to strings (Cassandra requirement)
477
+ string_metadata = {key: str(value) for key, value in metadata.items()}
478
+ updated_metadata.update(string_metadata)
479
+
480
+ # Update the document with merged metadata
481
+ row_id = getattr(row, "row_id")
482
+ update_query = f"""
483
+ UPDATE {self.keyspace}.{self.table_name}
484
+ SET metadata_s = %s
485
+ WHERE row_id = %s
486
+ """
487
+ self.session.execute(update_query, (updated_metadata, row_id))
488
+ updated_count += 1
489
+
490
+ if updated_count == 0:
491
+ log_debug(f"No documents found with content_id {content_id}")
492
+ else:
493
+ log_debug(f"Updated metadata for {updated_count} documents with content_id {content_id}")
494
+
495
+ except Exception as e:
496
+ log_error(f"Error updating metadata for content_id {content_id}: {e}")
497
+ raise
498
+
499
+ def get_supported_search_types(self) -> List[str]:
500
+ """Get the supported search types for this vector database."""
501
+ return [] # Cassandra doesn't use SearchType enum
@@ -0,0 +1,11 @@
1
+ from typing import List
2
+
3
+ from cassio.table.mixins.base_table import BaseTableMixin
4
+ from cassio.table.table_types import ColumnSpecType
5
+
6
+
7
+ class ExtraParamMixin(BaseTableMixin):
8
+ def _schema_da(self) -> List[ColumnSpecType]:
9
+ return super()._schema_da() + [
10
+ ("document_name", "TEXT"),
11
+ ]
@@ -0,0 +1,13 @@
1
+ try:
2
+ from cassio.table.base_table import BaseTable
3
+ from cassio.table.mixins.metadata import MetadataMixin
4
+ from cassio.table.mixins.type_normalizer import TypeNormalizerMixin
5
+ from cassio.table.mixins.vector import VectorMixin
6
+
7
+ from .extra_param_mixin import ExtraParamMixin
8
+ except (ImportError, ModuleNotFoundError):
9
+ raise ImportError("Could not import cassio python package. Please install it with pip install cassio.")
10
+
11
+
12
+ class AgnoMetadataVectorCassandraTable(ExtraParamMixin, TypeNormalizerMixin, MetadataMixin, VectorMixin, BaseTable):
13
+ pass
@@ -0,0 +1,5 @@
1
+ from agno.vectordb.chroma.chromadb import ChromaDb
2
+
3
+ __all__ = [
4
+ "ChromaDb",
5
+ ]