agno 0.1.2__py3-none-any.whl → 2.3.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 (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  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/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -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 +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -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 +1791 -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 +1312 -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 +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
@@ -1 +1,5 @@
1
- from agno.vectordb.pineconedb.pineconedb import PineconeDB
1
+ from agno.vectordb.pineconedb.pineconedb import PineconeDb
2
+
3
+ __all__ = [
4
+ "PineconeDb",
5
+ ]
@@ -1,19 +1,36 @@
1
+ import asyncio
1
2
  from typing import Any, Dict, List, Optional, Union
2
3
 
3
4
  try:
5
+ from packaging import version
6
+ from pinecone import __version__
7
+
8
+ if version.parse(__version__).major >= 6:
9
+ import warnings
10
+
11
+ warnings.warn(
12
+ "We do not yet support Pinecone v6.x.x. We are actively working to achieve compatibility. "
13
+ "In the meantime, we recommend using Pinecone v5.4.2 for the best experience. Please run `pip install pinecone==5.4.2`",
14
+ UserWarning,
15
+ )
16
+ raise RuntimeError("Incompatible Pinecone version detected. Execution halted.")
17
+
4
18
  from pinecone import Pinecone, PodSpec, ServerlessSpec
5
19
  from pinecone.config import Config
20
+
6
21
  except ImportError:
7
22
  raise ImportError("The `pinecone` package is not installed, please install using `pip install pinecone`.")
8
23
 
9
- from agno.document import Document
10
- from agno.embedder import Embedder
11
- from agno.reranker.base import Reranker
12
- from agno.utils.log import logger
24
+
25
+ from agno.filters import FilterExpr
26
+ from agno.knowledge.document import Document
27
+ from agno.knowledge.embedder import Embedder
28
+ from agno.knowledge.reranker.base import Reranker
29
+ from agno.utils.log import log_debug, log_info, log_warning, logger
13
30
  from agno.vectordb.base import VectorDb
14
31
 
15
32
 
16
- class PineconeDB(VectorDb):
33
+ class PineconeDb(VectorDb):
17
34
  """A class representing a Pinecone database.
18
35
 
19
36
  Args:
@@ -23,6 +40,7 @@ class PineconeDB(VectorDb):
23
40
  metric (Optional[str], optional): The metric used for similarity search. Defaults to "cosine".
24
41
  additional_headers (Optional[Dict[str, str]], optional): Additional headers to pass to the Pinecone client. Defaults to {}.
25
42
  pool_threads (Optional[int], optional): The number of threads to use for the Pinecone client. Defaults to 1.
43
+ namespace: (Optional[str], optional): The namespace partition within the index that will be used. Defaults to None.
26
44
  timeout (Optional[int], optional): The timeout for Pinecone operations. Defaults to None.
27
45
  index_api (Optional[Any], optional): The Index API object. Defaults to None.
28
46
  api_key (Optional[str], optional): The Pinecone API key. Defaults to None.
@@ -49,9 +67,11 @@ class PineconeDB(VectorDb):
49
67
 
50
68
  def __init__(
51
69
  self,
52
- name: str,
53
70
  dimension: int,
54
71
  spec: Union[Dict, ServerlessSpec, PodSpec],
72
+ name: Optional[str] = None,
73
+ description: Optional[str] = None,
74
+ id: Optional[str] = None,
55
75
  embedder: Optional[Embedder] = None,
56
76
  metric: Optional[str] = "cosine",
57
77
  additional_headers: Optional[Dict[str, str]] = None,
@@ -67,6 +87,23 @@ class PineconeDB(VectorDb):
67
87
  reranker: Optional[Reranker] = None,
68
88
  **kwargs,
69
89
  ):
90
+ # Validate required parameters
91
+ if dimension is None or dimension <= 0:
92
+ raise ValueError("Dimension must be provided and greater than 0.")
93
+ if spec is None:
94
+ raise ValueError("Spec must be provided for Pinecone index.")
95
+
96
+ # Dynamic ID generation based on unique identifiers
97
+ if id is None:
98
+ from agno.utils.string import generate_id
99
+
100
+ index_name = name or "default_index"
101
+ seed = f"{host or 'pinecone'}#{index_name}#{dimension}"
102
+ id = generate_id(seed)
103
+
104
+ # Initialize base class with name, description, and generated ID
105
+ super().__init__(id=id, name=name, description=description)
106
+
70
107
  self._client = None
71
108
  self._index = None
72
109
  self.api_key: Optional[str] = api_key
@@ -76,7 +113,6 @@ class PineconeDB(VectorDb):
76
113
  self.pool_threads: Optional[int] = pool_threads
77
114
  self.namespace: Optional[str] = namespace
78
115
  self.index_api: Optional[Any] = index_api
79
- self.name: str = name
80
116
  self.dimension: Optional[int] = dimension
81
117
  self.spec: Union[Dict, ServerlessSpec, PodSpec] = spec
82
118
  self.metric: Optional[str] = metric
@@ -97,9 +133,10 @@ class PineconeDB(VectorDb):
97
133
  # Embedder for embedding the document contents
98
134
  _embedder = embedder
99
135
  if _embedder is None:
100
- from agno.embedder.openai import OpenAIEmbedder
136
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
101
137
 
102
138
  _embedder = OpenAIEmbedder()
139
+ log_info("Embedder not provided, using OpenAIEmbedder as default.")
103
140
  self.embedder: Embedder = _embedder
104
141
  self.reranker: Optional[Reranker] = reranker
105
142
 
@@ -112,7 +149,7 @@ class PineconeDB(VectorDb):
112
149
 
113
150
  """
114
151
  if self._client is None:
115
- logger.debug("Creating Pinecone Client")
152
+ log_debug("Creating Pinecone Client")
116
153
  self._client = Pinecone(
117
154
  api_key=self.api_key,
118
155
  host=self.host,
@@ -133,7 +170,7 @@ class PineconeDB(VectorDb):
133
170
 
134
171
  """
135
172
  if self._index is None:
136
- logger.debug(f"Connecting to Pinecone Index: {self.name}")
173
+ log_debug(f"Connecting to Pinecone Index: {self.name}")
137
174
  self._index = self.client.Index(self.name)
138
175
  return self._index
139
176
 
@@ -147,14 +184,21 @@ class PineconeDB(VectorDb):
147
184
  list_indexes = self.client.list_indexes()
148
185
  return self.name in list_indexes.names()
149
186
 
187
+ async def async_exists(self) -> bool:
188
+ """Check if the index exists asynchronously."""
189
+ return await asyncio.to_thread(self.exists)
190
+
150
191
  def create(self) -> None:
151
192
  """Create the index if it does not exist."""
152
193
  if not self.exists():
153
- logger.debug(f"Creating index: {self.name}")
194
+ log_debug(f"Creating index: {self.name}")
154
195
 
155
196
  if self.use_hybrid_search:
156
197
  self.metric = "dotproduct"
157
198
 
199
+ if self.dimension is None:
200
+ raise ValueError("Dimension is not set for this Pinecone index")
201
+
158
202
  self.client.create_index(
159
203
  name=self.name,
160
204
  dimension=self.dimension,
@@ -163,25 +207,16 @@ class PineconeDB(VectorDb):
163
207
  timeout=self.timeout,
164
208
  )
165
209
 
210
+ async def async_create(self) -> None:
211
+ """Create the index asynchronously if it does not exist."""
212
+ await asyncio.to_thread(self.create)
213
+
166
214
  def drop(self) -> None:
167
215
  """Delete the index if it exists."""
168
216
  if self.exists():
169
- logger.debug(f"Deleting index: {self.name}")
217
+ log_debug(f"Deleting index: {self.name}")
170
218
  self.client.delete_index(name=self.name, timeout=self.timeout)
171
219
 
172
- def doc_exists(self, document: Document) -> bool:
173
- """Check if a document exists in the index.
174
-
175
- Args:
176
- document (Document): The document to check.
177
-
178
- Returns:
179
- bool: True if the document exists, False otherwise.
180
-
181
- """
182
- response = self.index.fetch(ids=[document.id])
183
- return len(response.vectors) > 0
184
-
185
220
  def name_exists(self, name: str) -> bool:
186
221
  """Check if an index with the given name exists.
187
222
 
@@ -198,8 +233,23 @@ class PineconeDB(VectorDb):
198
233
  except Exception:
199
234
  return False
200
235
 
236
+ async def async_name_exists(self, name: str) -> bool:
237
+ """Check if an index with the given name exists asynchronously."""
238
+ return await asyncio.to_thread(self.name_exists, name)
239
+
201
240
  def upsert(
202
241
  self,
242
+ content_hash: str,
243
+ documents: List[Document],
244
+ filters: Optional[Dict[str, Any]] = None,
245
+ ) -> None:
246
+ if self.content_hash_exists(content_hash):
247
+ self._delete_by_content_hash(content_hash)
248
+ self._upsert(content_hash=content_hash, documents=documents, filters=filters)
249
+
250
+ def _upsert(
251
+ self,
252
+ content_hash: str,
203
253
  documents: List[Document],
204
254
  filters: Optional[Dict[str, Any]] = None,
205
255
  namespace: Optional[str] = None,
@@ -221,15 +271,145 @@ class PineconeDB(VectorDb):
221
271
  for document in documents:
222
272
  document.embed(embedder=self.embedder)
223
273
  document.meta_data["text"] = document.content
274
+ # Include name and content_id in metadata
275
+ metadata = document.meta_data.copy()
276
+ if filters:
277
+ metadata.update(filters)
278
+
279
+ if document.name:
280
+ metadata["name"] = document.name
281
+ if document.content_id:
282
+ metadata["content_id"] = document.content_id
283
+
284
+ metadata["content_hash"] = content_hash
285
+
224
286
  data_to_upsert = {
225
287
  "id": document.id,
226
288
  "values": document.embedding,
227
- "metadata": document.meta_data,
289
+ "metadata": metadata,
228
290
  }
229
291
  if self.use_hybrid_search:
230
292
  data_to_upsert["sparse_values"] = self.sparse_encoder.encode_documents(document.content)
231
293
  vectors.append(data_to_upsert)
232
294
 
295
+ self.index.upsert(
296
+ vectors=vectors,
297
+ namespace=namespace or self.namespace,
298
+ batch_size=batch_size,
299
+ show_progress=show_progress,
300
+ )
301
+
302
+ async def async_upsert(
303
+ self,
304
+ content_hash: str,
305
+ documents: List[Document],
306
+ filters: Optional[Dict[str, Any]] = None,
307
+ namespace: Optional[str] = None,
308
+ batch_size: Optional[int] = None,
309
+ show_progress: bool = False,
310
+ ) -> None:
311
+ """Upsert documents into the index asynchronously with batching."""
312
+ if self.content_hash_exists(content_hash):
313
+ await asyncio.to_thread(self._delete_by_content_hash, content_hash)
314
+ if not documents:
315
+ return
316
+
317
+ # Pinecone has its own batching mechanism, but we'll add an additional layer
318
+ # to process document embedding in parallel
319
+ _batch_size = batch_size or 100
320
+
321
+ # Split documents into batches
322
+ batches = [documents[i : i + _batch_size] for i in range(0, len(documents), _batch_size)]
323
+ log_debug(f"Processing {len(documents)} documents in {len(batches)} batches for upsert")
324
+
325
+ # Process each batch in parallel
326
+ async def process_batch(batch_docs):
327
+ return await self._prepare_vectors(batch_docs, content_hash, filters)
328
+
329
+ # Run all batches in parallel
330
+ batch_vectors = await asyncio.gather(*[process_batch(batch) for batch in batches])
331
+
332
+ # Flatten vectors
333
+ all_vectors = [vector for batch in batch_vectors for vector in batch]
334
+
335
+ # Upsert all vectors
336
+ await asyncio.to_thread(
337
+ self._upsert_vectors, all_vectors, namespace or self.namespace, batch_size, show_progress
338
+ )
339
+
340
+ log_debug(f"Finished async upsert of {len(documents)} documents")
341
+
342
+ async def _prepare_vectors(
343
+ self, documents: List[Document], content_hash: str, filters: Optional[Dict[str, Any]] = None
344
+ ) -> List[Dict[str, Any]]:
345
+ """Prepare vectors for upsert."""
346
+ vectors = []
347
+
348
+ if self.embedder.enable_batch and hasattr(self.embedder, "async_get_embeddings_batch_and_usage"):
349
+ # Use batch embedding when enabled and supported
350
+ try:
351
+ # Extract content from all documents
352
+ doc_contents = [doc.content for doc in documents]
353
+
354
+ # Get batch embeddings and usage
355
+ embeddings, usages = await self.embedder.async_get_embeddings_batch_and_usage(doc_contents)
356
+
357
+ # Process documents with pre-computed embeddings
358
+ for j, doc in enumerate(documents):
359
+ try:
360
+ if j < len(embeddings):
361
+ doc.embedding = embeddings[j]
362
+ doc.usage = usages[j] if j < len(usages) else None
363
+ except Exception as e:
364
+ logger.error(f"Error assigning batch embedding to document '{doc.name}': {e}")
365
+
366
+ except Exception as e:
367
+ # Check if this is a rate limit error - don't fall back as it would make things worse
368
+ error_str = str(e).lower()
369
+ is_rate_limit = any(
370
+ phrase in error_str
371
+ for phrase in ["rate limit", "too many requests", "429", "trial key", "api calls / minute"]
372
+ )
373
+
374
+ if is_rate_limit:
375
+ logger.error(f"Rate limit detected during batch embedding. {e}")
376
+ raise e
377
+ else:
378
+ logger.warning(f"Async batch embedding failed, falling back to individual embeddings: {e}")
379
+ # Fall back to individual embedding
380
+ embed_tasks = [doc.async_embed(embedder=self.embedder) for doc in documents]
381
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
382
+ else:
383
+ # Use individual embedding
384
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
385
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
386
+
387
+ for doc in documents:
388
+ doc.meta_data["text"] = doc.content
389
+ # Include name and content_id in metadata
390
+ metadata = doc.meta_data.copy()
391
+ if filters:
392
+ metadata.update(filters)
393
+
394
+ if doc.name:
395
+ metadata["name"] = doc.name
396
+ if doc.content_id:
397
+ metadata["content_id"] = doc.content_id
398
+
399
+ metadata["content_hash"] = content_hash
400
+
401
+ data_to_upsert = {
402
+ "id": doc.id,
403
+ "values": doc.embedding,
404
+ "metadata": metadata,
405
+ }
406
+ if self.use_hybrid_search:
407
+ data_to_upsert["sparse_values"] = self.sparse_encoder.encode_documents(doc.content)
408
+ vectors.append(data_to_upsert)
409
+ return vectors
410
+
411
+ def _upsert_vectors(self, vectors, namespace, batch_size, show_progress):
412
+ """Upsert vectors to the index."""
233
413
  self.index.upsert(
234
414
  vectors=vectors,
235
415
  namespace=namespace,
@@ -237,6 +417,12 @@ class PineconeDB(VectorDb):
237
417
  show_progress=show_progress,
238
418
  )
239
419
 
420
+ async def async_insert(
421
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
422
+ ) -> None:
423
+ log_warning("Pinecone does not support insert operations. Redirecting to async_upsert instead.")
424
+ await self.async_upsert(content_hash=content_hash, documents=documents, filters=filters)
425
+
240
426
  def upsert_available(self) -> bool:
241
427
  """Check if upsert operation is available.
242
428
 
@@ -246,20 +432,9 @@ class PineconeDB(VectorDb):
246
432
  """
247
433
  return True
248
434
 
249
- def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
250
- """Insert documents into the index.
251
-
252
- This method is not supported by Pinecone. Use `upsert` instead.
253
-
254
- Args:
255
- documents (List[Document]): The documents to insert.
256
- filters (Optional[Dict[str, Any]], optional): The filters for the insert. Defaults to None.
257
-
258
- Raises:
259
- NotImplementedError: This method is not supported by Pinecone.
260
-
261
- """
262
- raise NotImplementedError("Pinecone does not support insert operations. Use upsert instead.")
435
+ def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
436
+ log_warning("Pinecone does not support insert operations. Redirecting to upsert instead.")
437
+ self.upsert(content_hash=content_hash, documents=documents, filters=filters)
263
438
 
264
439
  def _hybrid_scale(self, dense: List[float], sparse: Dict[str, Any], alpha: float):
265
440
  """Hybrid vector scaling using a convex combination
@@ -283,7 +458,7 @@ class PineconeDB(VectorDb):
283
458
  self,
284
459
  query: str,
285
460
  limit: int = 5,
286
- filters: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
461
+ filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
287
462
  namespace: Optional[str] = None,
288
463
  include_values: Optional[bool] = None,
289
464
  ) -> List[Document]:
@@ -301,6 +476,9 @@ class PineconeDB(VectorDb):
301
476
  List[Document]: The list of matching documents.
302
477
 
303
478
  """
479
+ if isinstance(filters, List):
480
+ log_warning("Filters Expressions are not supported in PineconeDB. No filters will be applied.")
481
+ filters = None
304
482
  dense_embedding = self.embedder.get_embedding(query)
305
483
 
306
484
  if self.use_hybrid_search:
@@ -316,7 +494,7 @@ class PineconeDB(VectorDb):
316
494
  vector=hdense,
317
495
  sparse_vector=hsparse,
318
496
  top_k=limit,
319
- namespace=namespace,
497
+ namespace=namespace or self.namespace,
320
498
  filter=filters,
321
499
  include_values=include_values,
322
500
  include_metadata=True,
@@ -325,7 +503,7 @@ class PineconeDB(VectorDb):
325
503
  response = self.index.query(
326
504
  vector=dense_embedding,
327
505
  top_k=limit,
328
- namespace=namespace,
506
+ namespace=namespace or self.namespace,
329
507
  filter=filters,
330
508
  include_values=include_values,
331
509
  include_metadata=True,
@@ -345,6 +523,17 @@ class PineconeDB(VectorDb):
345
523
  search_results = self.reranker.rerank(query=query, documents=search_results)
346
524
  return search_results
347
525
 
526
+ async def async_search(
527
+ self,
528
+ query: str,
529
+ limit: int = 5,
530
+ filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
531
+ namespace: Optional[str] = None,
532
+ include_values: Optional[bool] = None,
533
+ ) -> List[Document]:
534
+ """Search for similar documents in the index asynchronously."""
535
+ return await asyncio.to_thread(self.search, query, limit, filters, namespace, include_values)
536
+
348
537
  def optimize(self) -> None:
349
538
  """Optimize the index.
350
539
 
@@ -365,3 +554,177 @@ class PineconeDB(VectorDb):
365
554
  return True
366
555
  except Exception:
367
556
  return False
557
+
558
+ async def async_drop(self) -> None:
559
+ raise NotImplementedError(f"Async not supported on {self.__class__.__name__}.")
560
+
561
+ def delete_by_id(self, id: str) -> bool:
562
+ """Delete a document by ID."""
563
+ try:
564
+ self.index.delete(ids=[id])
565
+ return True
566
+ except Exception as e:
567
+ log_warning(f"Error deleting document with ID {id}: {e}")
568
+ return False
569
+
570
+ def delete_by_name(self, name: str) -> bool:
571
+ """Delete documents by name (stored in metadata)."""
572
+ try:
573
+ # Delete all documents where metadata.name equals the given name
574
+ self.index.delete(filter={"name": {"$eq": name}})
575
+ return True
576
+ except Exception as e:
577
+ log_warning(f"Error deleting documents with name {name}: {e}")
578
+ return False
579
+
580
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
581
+ """Delete documents by metadata."""
582
+ try:
583
+ # Build filter for metadata matching
584
+ filter_conditions = {}
585
+ for key, value in metadata.items():
586
+ filter_conditions[key] = {"$eq": value}
587
+
588
+ self.index.delete(filter=filter_conditions)
589
+ return True
590
+ except Exception as e:
591
+ log_warning(f"Error deleting documents with metadata {metadata}: {e}")
592
+ return False
593
+
594
+ def delete_by_content_id(self, content_id: str) -> bool:
595
+ """Delete documents by content ID (stored in metadata)."""
596
+ try:
597
+ # Delete all documents where metadata.content_id equals the given content_id
598
+ self.index.delete(filter={"content_id": {"$eq": content_id}})
599
+ return True
600
+ except Exception as e:
601
+ log_warning(f"Error deleting documents with content_id {content_id}: {e}")
602
+ return False
603
+
604
+ def get_count(self) -> int:
605
+ """Get the count of documents in the index."""
606
+ try:
607
+ # Pinecone doesn't have a direct count method, so we use describe_index_stats
608
+ stats = self.index.describe_index_stats()
609
+ # The stats include total_vector_count which gives us the count
610
+ return stats.total_vector_count
611
+ except Exception as e:
612
+ log_warning(f"Error getting document count: {e}")
613
+ return 0
614
+
615
+ def id_exists(self, id: str) -> bool:
616
+ """Check if a document with the given ID exists in the index.
617
+
618
+ Args:
619
+ id (str): The ID to check.
620
+
621
+ Returns:
622
+ bool: True if the document exists, False otherwise.
623
+ """
624
+ try:
625
+ response = self.index.fetch(ids=[id], namespace=self.namespace)
626
+ return len(response.vectors) > 0
627
+ except Exception as e:
628
+ log_warning(f"Error checking if ID {id} exists: {e}")
629
+ return False
630
+
631
+ def content_hash_exists(self, content_hash: str) -> bool:
632
+ """Check if documents with the given content hash exist in the index.
633
+
634
+ Args:
635
+ content_hash (str): The content hash to check.
636
+
637
+ Returns:
638
+ bool: True if documents with the content hash exist, False otherwise.
639
+ """
640
+ try:
641
+ # Use a dummy vector to perform a minimal query with filter
642
+ # We only need to check if any results exist
643
+ if self.dimension is None:
644
+ raise ValueError("Dimension is not set for this Pinecone index")
645
+ dummy_vector = [0.0] * self.dimension
646
+ response = self.index.query(
647
+ vector=dummy_vector,
648
+ top_k=1,
649
+ namespace=self.namespace,
650
+ filter={"content_hash": {"$eq": content_hash}},
651
+ include_metadata=False,
652
+ include_values=False,
653
+ )
654
+ return len(response.matches) > 0
655
+ except Exception as e:
656
+ log_warning(f"Error checking if content_hash {content_hash} exists: {e}")
657
+ return False
658
+
659
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
660
+ """Delete documents by content hash (stored in metadata).
661
+
662
+ Args:
663
+ content_hash (str): The content hash to delete.
664
+
665
+ Returns:
666
+ bool: True if documents were deleted, False otherwise.
667
+ """
668
+ try:
669
+ # Delete all documents where metadata.content_hash equals the given content_hash
670
+ self.index.delete(filter={"content_hash": {"$eq": content_hash}}, namespace=self.namespace)
671
+ return True
672
+ except Exception as e:
673
+ log_warning(f"Error deleting documents with content_hash {content_hash}: {e}")
674
+ return False
675
+
676
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
677
+ """
678
+ Update the metadata for documents with the given content_id.
679
+
680
+ Args:
681
+ content_id (str): The content ID to update
682
+ metadata (Dict[str, Any]): The metadata to update
683
+ """
684
+ try:
685
+ # Query for vectors with the given content_id
686
+ query_response = self.index.query(
687
+ filter={"content_id": {"$eq": content_id}},
688
+ top_k=10000, # Get all matching vectors
689
+ include_metadata=True,
690
+ namespace=self.namespace,
691
+ )
692
+
693
+ if not query_response.matches:
694
+ logger.debug(f"No documents found with content_id: {content_id}")
695
+ return
696
+
697
+ # Prepare updates for each matching vector
698
+ update_data = []
699
+ for match in query_response.matches:
700
+ vector_id = match.id
701
+ current_metadata = match.metadata or {}
702
+
703
+ # Merge existing metadata with new metadata
704
+ updated_metadata = current_metadata.copy()
705
+ updated_metadata.update(metadata)
706
+
707
+ if "filters" not in updated_metadata:
708
+ updated_metadata["filters"] = {}
709
+ if isinstance(updated_metadata["filters"], dict):
710
+ updated_metadata["filters"].update(metadata)
711
+ else:
712
+ updated_metadata["filters"] = metadata
713
+
714
+ update_data.append({"id": vector_id, "metadata": updated_metadata})
715
+
716
+ # Update vectors in batches
717
+ batch_size = 100
718
+ for i in range(0, len(update_data), batch_size):
719
+ batch = update_data[i : i + batch_size]
720
+ self.index.update(vectors=batch, namespace=self.namespace)
721
+
722
+ logger.debug(f"Updated metadata for {len(update_data)} documents with content_id: {content_id}")
723
+
724
+ except Exception as e:
725
+ logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
726
+ raise
727
+
728
+ def get_supported_search_types(self) -> List[str]:
729
+ """Get the supported search types for this vector database."""
730
+ return [] # PineconeDb doesn't use SearchType enum
@@ -1 +1,5 @@
1
1
  from agno.vectordb.qdrant.qdrant import Qdrant
2
+
3
+ __all__ = [
4
+ "Qdrant",
5
+ ]