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
@@ -0,0 +1,195 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict, List, Optional, Tuple
3
+
4
+ from typing_extensions import Literal
5
+
6
+ from agno.knowledge.embedder.base import Embedder
7
+ from agno.utils.log import log_info, log_warning
8
+
9
+ try:
10
+ from openai import AsyncOpenAI
11
+ from openai import OpenAI as OpenAIClient
12
+ from openai.types.create_embedding_response import CreateEmbeddingResponse
13
+ except ImportError:
14
+ raise ImportError("`openai` not installed")
15
+
16
+
17
+ @dataclass
18
+ class OpenAIEmbedder(Embedder):
19
+ id: str = "text-embedding-3-small"
20
+ dimensions: Optional[int] = None
21
+ encoding_format: Literal["float", "base64"] = "float"
22
+ user: Optional[str] = None
23
+ api_key: Optional[str] = None
24
+ organization: Optional[str] = None
25
+ base_url: Optional[str] = None
26
+ request_params: Optional[Dict[str, Any]] = None
27
+ client_params: Optional[Dict[str, Any]] = None
28
+ openai_client: Optional[OpenAIClient] = None
29
+ async_client: Optional[AsyncOpenAI] = None
30
+
31
+ def __post_init__(self):
32
+ if self.dimensions is None:
33
+ self.dimensions = 3072 if self.id == "text-embedding-3-large" else 1536
34
+
35
+ @property
36
+ def client(self) -> OpenAIClient:
37
+ if self.openai_client:
38
+ return self.openai_client
39
+
40
+ _client_params: Dict[str, Any] = {
41
+ "api_key": self.api_key,
42
+ "organization": self.organization,
43
+ "base_url": self.base_url,
44
+ }
45
+ _client_params = {k: v for k, v in _client_params.items() if v is not None}
46
+ if self.client_params:
47
+ _client_params.update(self.client_params)
48
+ self.openai_client = OpenAIClient(**_client_params)
49
+ return self.openai_client
50
+
51
+ @property
52
+ def aclient(self) -> AsyncOpenAI:
53
+ if self.async_client:
54
+ return self.async_client
55
+ params = {
56
+ "api_key": self.api_key,
57
+ "organization": self.organization,
58
+ "base_url": self.base_url,
59
+ }
60
+ filtered_params: Dict[str, Any] = {k: v for k, v in params.items() if v is not None}
61
+ if self.client_params:
62
+ filtered_params.update(self.client_params)
63
+ self.async_client = AsyncOpenAI(**filtered_params)
64
+ return self.async_client
65
+
66
+ def response(self, text: str) -> CreateEmbeddingResponse:
67
+ _request_params: Dict[str, Any] = {
68
+ "input": text,
69
+ "model": self.id,
70
+ "encoding_format": self.encoding_format,
71
+ }
72
+ if self.user is not None:
73
+ _request_params["user"] = self.user
74
+ if self.id.startswith("text-embedding-3"):
75
+ _request_params["dimensions"] = self.dimensions
76
+ if self.request_params:
77
+ _request_params.update(self.request_params)
78
+ return self.client.embeddings.create(**_request_params)
79
+
80
+ def get_embedding(self, text: str) -> List[float]:
81
+ try:
82
+ response: CreateEmbeddingResponse = self.response(text=text)
83
+ return response.data[0].embedding
84
+ except Exception as e:
85
+ log_warning(e)
86
+ return []
87
+
88
+ def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
89
+ try:
90
+ response: CreateEmbeddingResponse = self.response(text=text)
91
+
92
+ embedding = response.data[0].embedding
93
+ usage = response.usage
94
+ if usage:
95
+ return embedding, usage.model_dump()
96
+ return embedding, None
97
+ except Exception as e:
98
+ log_warning(e)
99
+ return [], None
100
+
101
+ async def async_get_embedding(self, text: str) -> List[float]:
102
+ req: Dict[str, Any] = {
103
+ "input": text,
104
+ "model": self.id,
105
+ "encoding_format": self.encoding_format,
106
+ }
107
+ if self.user is not None:
108
+ req["user"] = self.user
109
+ if self.id.startswith("text-embedding-3"):
110
+ req["dimensions"] = self.dimensions
111
+ if self.request_params:
112
+ req.update(self.request_params)
113
+
114
+ try:
115
+ response: CreateEmbeddingResponse = await self.aclient.embeddings.create(**req)
116
+ return response.data[0].embedding
117
+ except Exception as e:
118
+ log_warning(e)
119
+ return []
120
+
121
+ async def async_get_embedding_and_usage(self, text: str):
122
+ req: Dict[str, Any] = {
123
+ "input": text,
124
+ "model": self.id,
125
+ "encoding_format": self.encoding_format,
126
+ }
127
+ if self.user is not None:
128
+ req["user"] = self.user
129
+ if self.id.startswith("text-embedding-3"):
130
+ req["dimensions"] = self.dimensions
131
+ if self.request_params:
132
+ req.update(self.request_params)
133
+
134
+ try:
135
+ response = await self.aclient.embeddings.create(**req)
136
+ embedding = response.data[0].embedding
137
+ usage = response.usage
138
+ return embedding, usage.model_dump() if usage else None
139
+ except Exception as e:
140
+ log_warning(f"Error getting embedding: {e}")
141
+ return [], None
142
+
143
+ async def async_get_embeddings_batch_and_usage(
144
+ self, texts: List[str]
145
+ ) -> Tuple[List[List[float]], List[Optional[Dict]]]:
146
+ """
147
+ Get embeddings and usage for multiple texts in batches (async version).
148
+
149
+ Args:
150
+ texts: List of text strings to embed
151
+
152
+ Returns:
153
+ Tuple of (List of embedding vectors, List of usage dictionaries)
154
+ """
155
+ all_embeddings = []
156
+ all_usage = []
157
+ log_info(f"Getting embeddings and usage for {len(texts)} texts in batches of {self.batch_size} (async)")
158
+
159
+ for i in range(0, len(texts), self.batch_size):
160
+ batch_texts = texts[i : i + self.batch_size]
161
+
162
+ req: Dict[str, Any] = {
163
+ "input": batch_texts,
164
+ "model": self.id,
165
+ "encoding_format": self.encoding_format,
166
+ }
167
+ if self.user is not None:
168
+ req["user"] = self.user
169
+ if self.id.startswith("text-embedding-3"):
170
+ req["dimensions"] = self.dimensions
171
+ if self.request_params:
172
+ req.update(self.request_params)
173
+
174
+ try:
175
+ response: CreateEmbeddingResponse = await self.aclient.embeddings.create(**req)
176
+ batch_embeddings = [data.embedding for data in response.data]
177
+ all_embeddings.extend(batch_embeddings)
178
+
179
+ # For each embedding in the batch, add the same usage information
180
+ usage_dict = response.usage.model_dump() if response.usage else None
181
+ all_usage.extend([usage_dict] * len(batch_embeddings))
182
+ except Exception as e:
183
+ log_warning(f"Error in async batch embedding: {e}")
184
+ # Fallback to individual calls for this batch
185
+ for text in batch_texts:
186
+ try:
187
+ embedding, usage = await self.async_get_embedding_and_usage(text)
188
+ all_embeddings.append(embedding)
189
+ all_usage.append(usage)
190
+ except Exception as e2:
191
+ log_warning(f"Error in individual async embedding fallback: {e2}")
192
+ all_embeddings.append([])
193
+ all_usage.append(None)
194
+
195
+ return all_embeddings, all_usage
@@ -0,0 +1,63 @@
1
+ from dataclasses import dataclass
2
+ from typing import Dict, List, Optional, Tuple, Union
3
+
4
+ from agno.knowledge.embedder.base import Embedder
5
+ from agno.utils.log import logger
6
+
7
+ try:
8
+ from sentence_transformers import SentenceTransformer
9
+
10
+ except ImportError:
11
+ raise ImportError("`sentence-transformers` not installed, please run `pip install sentence-transformers`")
12
+
13
+ try:
14
+ import numpy as np
15
+
16
+ except ImportError:
17
+ raise ImportError("numpy not installed, use `pip install numpy`")
18
+
19
+
20
+ @dataclass
21
+ class SentenceTransformerEmbedder(Embedder):
22
+ id: str = "sentence-transformers/all-MiniLM-L6-v2"
23
+ dimensions: int = 384
24
+ sentence_transformer_client: Optional[SentenceTransformer] = None
25
+ prompt: Optional[str] = None
26
+ normalize_embeddings: bool = False
27
+
28
+ def __post_init__(self):
29
+ # Initialize the SentenceTransformer model eagerly to avoid race conditions in async contexts
30
+ if self.sentence_transformer_client is None:
31
+ self.sentence_transformer_client = SentenceTransformer(model_name_or_path=self.id)
32
+
33
+ def get_embedding(self, text: Union[str, List[str]]) -> List[float]:
34
+ if self.sentence_transformer_client is None:
35
+ raise RuntimeError("SentenceTransformer model not initialized")
36
+ model = self.sentence_transformer_client
37
+ embedding = model.encode(text, prompt=self.prompt, normalize_embeddings=self.normalize_embeddings)
38
+ try:
39
+ if isinstance(embedding, np.ndarray):
40
+ return embedding.tolist()
41
+
42
+ return embedding # type: ignore
43
+ except Exception as e:
44
+ logger.warning(e)
45
+ return []
46
+
47
+ def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
48
+ return self.get_embedding(text=text), None
49
+
50
+ async def async_get_embedding(self, text: Union[str, List[str]]) -> List[float]:
51
+ """Async version using thread executor for CPU-bound operations."""
52
+ import asyncio
53
+
54
+ loop = asyncio.get_event_loop()
55
+ # Run the CPU-bound operation in a thread executor
56
+ return await loop.run_in_executor(None, self.get_embedding, text)
57
+
58
+ async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
59
+ """Async version using thread executor for CPU-bound operations."""
60
+ import asyncio
61
+
62
+ loop = asyncio.get_event_loop()
63
+ return await loop.run_in_executor(None, self.get_embedding_and_usage, text)
@@ -2,7 +2,7 @@ from dataclasses import dataclass
2
2
  from os import getenv
3
3
  from typing import Optional
4
4
 
5
- from agno.embedder.openai import OpenAIEmbedder
5
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
6
6
 
7
7
 
8
8
  @dataclass
@@ -0,0 +1,262 @@
1
+ import asyncio
2
+ from dataclasses import dataclass
3
+ from os import getenv
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
5
+
6
+ from agno.knowledge.embedder.base import Embedder
7
+ from agno.utils.log import logger
8
+
9
+ try:
10
+ from vllm import LLM # type: ignore
11
+ from vllm.outputs import EmbeddingRequestOutput # type: ignore
12
+ except ImportError:
13
+ raise ImportError("`vllm` not installed. Please install using `pip install vllm`.")
14
+
15
+ if TYPE_CHECKING:
16
+ from openai import AsyncOpenAI
17
+ from openai import OpenAI as OpenAIClient
18
+ from openai.types.create_embedding_response import CreateEmbeddingResponse
19
+
20
+
21
+ @dataclass
22
+ class VLLMEmbedder(Embedder):
23
+ """
24
+ VLLM Embedder supporting both local and remote deployment modes.
25
+
26
+ Local Mode (default):
27
+ - Loads model locally and runs inference on your GPU/CPU
28
+ - No API key required
29
+ - Example: VLLMEmbedder(id="intfloat/e5-mistral-7b-instruct")
30
+
31
+ Remote Mode:
32
+ - Connects to a remote vLLM server via OpenAI-compatible API
33
+ - Uses OpenAI SDK to communicate with vLLM's OpenAI-compatible endpoint
34
+ - Requires base_url and optionally api_key
35
+ - Example: VLLMEmbedder(base_url="http://localhost:8000/v1", api_key="your-key")
36
+ - Ref: https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html
37
+ """
38
+
39
+ id: str = "sentence-transformers/all-MiniLM-L6-v2"
40
+ dimensions: int = 4096
41
+ # Local mode parameters
42
+ enforce_eager: bool = True
43
+ vllm_kwargs: Optional[Dict[str, Any]] = None
44
+ vllm_client: Optional[LLM] = None
45
+ # Remote mode parameters
46
+ api_key: Optional[str] = getenv("VLLM_API_KEY")
47
+ base_url: Optional[str] = None
48
+ request_params: Optional[Dict[str, Any]] = None
49
+ client_params: Optional[Dict[str, Any]] = None
50
+ remote_client: Optional["OpenAIClient"] = None # OpenAI-compatible client for vLLM server
51
+ async_remote_client: Optional["AsyncOpenAI"] = None # Async OpenAI-compatible client for vLLM server
52
+
53
+ @property
54
+ def is_remote(self) -> bool:
55
+ """Determine if we should use remote mode."""
56
+ return self.base_url is not None
57
+
58
+ def _get_vllm_client(self) -> LLM:
59
+ """Get local VLLM client."""
60
+ if self.vllm_client:
61
+ return self.vllm_client
62
+
63
+ _vllm_params: Dict[str, Any] = {
64
+ "model": self.id,
65
+ "task": "embed",
66
+ "enforce_eager": self.enforce_eager,
67
+ }
68
+ if self.vllm_kwargs:
69
+ _vllm_params.update(self.vllm_kwargs)
70
+ self.vllm_client = LLM(**_vllm_params)
71
+ return self.vllm_client
72
+
73
+ def _get_remote_client(self) -> "OpenAIClient":
74
+ """Get OpenAI-compatible client for remote vLLM server."""
75
+ if self.remote_client:
76
+ return self.remote_client
77
+
78
+ try:
79
+ from openai import OpenAI as OpenAIClient
80
+ except ImportError:
81
+ raise ImportError("`openai` package required for remote vLLM mode. ")
82
+
83
+ _client_params: Dict[str, Any] = {
84
+ "api_key": self.api_key or "EMPTY", # VLLM can run without API key
85
+ "base_url": self.base_url,
86
+ }
87
+ if self.client_params:
88
+ _client_params.update(self.client_params)
89
+ self.remote_client = OpenAIClient(**_client_params)
90
+ return self.remote_client
91
+
92
+ def _get_async_remote_client(self) -> "AsyncOpenAI":
93
+ """Get async OpenAI-compatible client for remote vLLM server."""
94
+ if self.async_remote_client:
95
+ return self.async_remote_client
96
+
97
+ try:
98
+ from openai import AsyncOpenAI
99
+ except ImportError:
100
+ raise ImportError("`openai` package required for remote vLLM mode. ")
101
+
102
+ _client_params: Dict[str, Any] = {
103
+ "api_key": self.api_key or "EMPTY",
104
+ "base_url": self.base_url,
105
+ }
106
+ if self.client_params:
107
+ _client_params.update(self.client_params)
108
+ self.async_remote_client = AsyncOpenAI(**_client_params)
109
+ return self.async_remote_client
110
+
111
+ def _create_embedding_local(self, text: str) -> Optional[EmbeddingRequestOutput]:
112
+ """Create embedding using local VLLM."""
113
+ try:
114
+ outputs = self._get_vllm_client().embed([text])
115
+ return outputs[0] if outputs else None
116
+ except Exception as e:
117
+ logger.warning(f"Error creating local embedding: {e}")
118
+ return None
119
+
120
+ def _create_embedding_remote(self, text: str) -> "CreateEmbeddingResponse":
121
+ """Create embedding using remote vLLM server."""
122
+ _request_params: Dict[str, Any] = {
123
+ "input": text,
124
+ "model": self.id,
125
+ }
126
+ if self.request_params:
127
+ _request_params.update(self.request_params)
128
+ return self._get_remote_client().embeddings.create(**_request_params)
129
+
130
+ def get_embedding(self, text: str) -> List[float]:
131
+ try:
132
+ if self.is_remote:
133
+ # Remote mode: OpenAI-compatible API
134
+ response: "CreateEmbeddingResponse" = self._create_embedding_remote(text=text)
135
+ return response.data[0].embedding
136
+ else:
137
+ # Local mode: Direct VLLM
138
+ output = self._create_embedding_local(text=text)
139
+ if output and hasattr(output, "outputs") and hasattr(output.outputs, "embedding"):
140
+ embedding = output.outputs.embedding
141
+ if len(embedding) != self.dimensions:
142
+ logger.warning(f"Expected embedding dimension {self.dimensions}, but got {len(embedding)}")
143
+ return embedding
144
+ return []
145
+ except Exception as e:
146
+ logger.warning(f"Error extracting embedding: {e}")
147
+ return []
148
+
149
+ def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
150
+ if self.is_remote:
151
+ try:
152
+ response: "CreateEmbeddingResponse" = self._create_embedding_remote(text=text)
153
+ embedding = response.data[0].embedding
154
+ usage = response.usage
155
+ if usage:
156
+ return embedding, usage.model_dump()
157
+ return embedding, None
158
+ except Exception as e:
159
+ logger.warning(f"Error in remote embedding: {e}")
160
+ return [], None
161
+ else:
162
+ embedding = self.get_embedding(text=text)
163
+ # Local VLLM doesn't provide usage information
164
+ return embedding, None
165
+
166
+ async def async_get_embedding(self, text: str) -> List[float]:
167
+ """Async version of get_embedding using thread executor for local mode."""
168
+ if self.is_remote:
169
+ # Remote mode: async client for vLLM server
170
+ try:
171
+ req: Dict[str, Any] = {
172
+ "input": text,
173
+ "model": self.id,
174
+ }
175
+ if self.request_params:
176
+ req.update(self.request_params)
177
+ response: "CreateEmbeddingResponse" = await self._get_async_remote_client().embeddings.create(**req)
178
+ return response.data[0].embedding
179
+ except Exception as e:
180
+ logger.warning(f"Error in async remote embedding: {e}")
181
+ return []
182
+ else:
183
+ # Local mode: use thread executor for CPU-bound operations
184
+ loop = asyncio.get_event_loop()
185
+ return await loop.run_in_executor(None, self.get_embedding, text)
186
+
187
+ async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
188
+ """Async version of get_embedding_and_usage using thread executor for local mode."""
189
+ if self.is_remote:
190
+ try:
191
+ req: Dict[str, Any] = {
192
+ "input": text,
193
+ "model": self.id,
194
+ }
195
+ if self.request_params:
196
+ req.update(self.request_params)
197
+ response: "CreateEmbeddingResponse" = await self._get_async_remote_client().embeddings.create(**req)
198
+ embedding = response.data[0].embedding
199
+ usage = response.usage
200
+ return embedding, usage.model_dump() if usage else None
201
+ except Exception as e:
202
+ logger.warning(f"Error in async remote embedding: {e}")
203
+ return [], None
204
+ else:
205
+ # Local mode: use thread executor for CPU-bound operations
206
+ try:
207
+ loop = asyncio.get_event_loop()
208
+ return await loop.run_in_executor(None, self.get_embedding_and_usage, text)
209
+ except Exception as e:
210
+ logger.warning(f"Error in async local embedding: {e}")
211
+ return [], None
212
+
213
+ async def async_get_embeddings_batch_and_usage(
214
+ self, texts: List[str]
215
+ ) -> Tuple[List[List[float]], List[Optional[Dict]]]:
216
+ """
217
+ Get embeddings and usage for multiple texts in batches (async version).
218
+
219
+ Args:
220
+ texts: List of text strings to embed
221
+
222
+ Returns:
223
+ Tuple of (List of embedding vectors, List of usage dictionaries)
224
+ """
225
+ all_embeddings = []
226
+ all_usage = []
227
+ logger.info(f"Getting embeddings for {len(texts)} texts in batches of {self.batch_size} (async)")
228
+
229
+ for i in range(0, len(texts), self.batch_size):
230
+ batch_texts = texts[i : i + self.batch_size]
231
+
232
+ try:
233
+ if self.is_remote:
234
+ # Remote mode: use batch API
235
+ req: Dict[str, Any] = {
236
+ "input": batch_texts,
237
+ "model": self.id,
238
+ }
239
+ if self.request_params:
240
+ req.update(self.request_params)
241
+ response: "CreateEmbeddingResponse" = await self._get_async_remote_client().embeddings.create(**req)
242
+ batch_embeddings = [data.embedding for data in response.data]
243
+ all_embeddings.extend(batch_embeddings)
244
+
245
+ # For each embedding in the batch, add the same usage information
246
+ usage_dict = response.usage.model_dump() if response.usage else None
247
+ all_usage.extend([usage_dict] * len(batch_embeddings))
248
+ else:
249
+ # Local mode: process individually using thread executor
250
+ for text in batch_texts:
251
+ embedding, usage = await self.async_get_embedding_and_usage(text)
252
+ all_embeddings.append(embedding)
253
+ all_usage.append(usage)
254
+
255
+ except Exception as e:
256
+ logger.warning(f"Error in async batch embedding: {e}")
257
+ # Fallback: add empty results for failed batch
258
+ for _ in batch_texts:
259
+ all_embeddings.append([])
260
+ all_usage.append(None)
261
+
262
+ return all_embeddings, all_usage
@@ -0,0 +1,165 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict, List, Optional, Tuple
3
+
4
+ from agno.knowledge.embedder.base import Embedder
5
+ from agno.utils.log import logger
6
+
7
+ try:
8
+ from voyageai import AsyncClient as AsyncVoyageClient
9
+ from voyageai import Client as VoyageClient
10
+ from voyageai.object import EmbeddingsObject
11
+ except ImportError:
12
+ raise ImportError("`voyageai` not installed. Please install using `pip install voyageai`")
13
+
14
+
15
+ @dataclass
16
+ class VoyageAIEmbedder(Embedder):
17
+ id: str = "voyage-2"
18
+ dimensions: int = 1024
19
+ request_params: Optional[Dict[str, Any]] = None
20
+ api_key: Optional[str] = None
21
+ base_url: str = "https://api.voyageai.com/v1/embeddings"
22
+ max_retries: Optional[int] = None
23
+ timeout: Optional[float] = None
24
+ client_params: Optional[Dict[str, Any]] = None
25
+ voyage_client: Optional[VoyageClient] = None
26
+ async_client: Optional[AsyncVoyageClient] = None
27
+
28
+ @property
29
+ def client(self) -> VoyageClient:
30
+ if self.voyage_client:
31
+ return self.voyage_client
32
+
33
+ _client_params: Dict[str, Any] = {}
34
+ if self.api_key is not None:
35
+ _client_params["api_key"] = self.api_key
36
+ if self.max_retries is not None:
37
+ _client_params["max_retries"] = self.max_retries
38
+ if self.timeout is not None:
39
+ _client_params["timeout"] = self.timeout
40
+ if self.client_params:
41
+ _client_params.update(self.client_params)
42
+ self.voyage_client = VoyageClient(**_client_params)
43
+ return self.voyage_client
44
+
45
+ @property
46
+ def aclient(self) -> AsyncVoyageClient:
47
+ if self.async_client:
48
+ return self.async_client
49
+
50
+ _client_params: Dict[str, Any] = {}
51
+ if self.api_key is not None:
52
+ _client_params["api_key"] = self.api_key
53
+ if self.max_retries is not None:
54
+ _client_params["max_retries"] = self.max_retries
55
+ if self.timeout is not None:
56
+ _client_params["timeout"] = self.timeout
57
+ if self.client_params:
58
+ _client_params.update(self.client_params)
59
+ self.async_client = AsyncVoyageClient(**_client_params)
60
+ return self.async_client
61
+
62
+ def _response(self, text: str) -> EmbeddingsObject:
63
+ _request_params: Dict[str, Any] = {
64
+ "texts": [text],
65
+ "model": self.id,
66
+ }
67
+ if self.request_params:
68
+ _request_params.update(self.request_params)
69
+ return self.client.embed(**_request_params)
70
+
71
+ def get_embedding(self, text: str) -> List[float]:
72
+ response: EmbeddingsObject = self._response(text=text)
73
+ try:
74
+ embedding = response.embeddings[0]
75
+ return [float(x) for x in embedding] # Ensure all values are float
76
+ except Exception as e:
77
+ logger.warning(e)
78
+ return []
79
+
80
+ def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
81
+ response: EmbeddingsObject = self._response(text=text)
82
+
83
+ embedding = response.embeddings[0]
84
+ usage = {"total_tokens": response.total_tokens}
85
+ return [float(x) for x in embedding], usage
86
+
87
+ async def _async_response(self, text: str) -> EmbeddingsObject:
88
+ """Async version of _response using AsyncVoyageClient."""
89
+ _request_params: Dict[str, Any] = {
90
+ "texts": [text],
91
+ "model": self.id,
92
+ }
93
+ if self.request_params:
94
+ _request_params.update(self.request_params)
95
+ return await self.aclient.embed(**_request_params)
96
+
97
+ async def async_get_embedding(self, text: str) -> List[float]:
98
+ """Async version of get_embedding."""
99
+ try:
100
+ response: EmbeddingsObject = await self._async_response(text=text)
101
+ embedding = response.embeddings[0]
102
+ return [float(x) for x in embedding] # Ensure all values are float
103
+ except Exception as e:
104
+ logger.warning(f"Error getting embedding: {e}")
105
+ return []
106
+
107
+ async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
108
+ """Async version of get_embedding_and_usage."""
109
+ try:
110
+ response: EmbeddingsObject = await self._async_response(text=text)
111
+ embedding = response.embeddings[0]
112
+ usage = {"total_tokens": response.total_tokens}
113
+ return [float(x) for x in embedding], usage
114
+ except Exception as e:
115
+ logger.warning(f"Error getting embedding and usage: {e}")
116
+ return [], None
117
+
118
+ async def async_get_embeddings_batch_and_usage(
119
+ self, texts: List[str]
120
+ ) -> Tuple[List[List[float]], List[Optional[Dict]]]:
121
+ """
122
+ Get embeddings and usage for multiple texts in batches.
123
+
124
+ Args:
125
+ texts: List of text strings to embed
126
+
127
+ Returns:
128
+ Tuple of (List of embedding vectors, List of usage dictionaries)
129
+ """
130
+ all_embeddings: List[List[float]] = []
131
+ all_usage: List[Optional[Dict]] = []
132
+ logger.info(f"Getting embeddings and usage for {len(texts)} texts in batches of {self.batch_size}")
133
+
134
+ for i in range(0, len(texts), self.batch_size):
135
+ batch_texts = texts[i : i + self.batch_size]
136
+
137
+ req: Dict[str, Any] = {
138
+ "texts": batch_texts,
139
+ "model": self.id,
140
+ }
141
+ if self.request_params:
142
+ req.update(self.request_params)
143
+
144
+ try:
145
+ response: EmbeddingsObject = await self.aclient.embed(**req)
146
+ batch_embeddings = [[float(x) for x in emb] for emb in response.embeddings]
147
+ all_embeddings.extend(batch_embeddings)
148
+
149
+ # For each embedding in the batch, add the same usage information
150
+ usage_dict = {"total_tokens": response.total_tokens}
151
+ all_usage.extend([usage_dict] * len(batch_embeddings))
152
+ except Exception as e:
153
+ logger.warning(f"Error in async batch embedding: {e}")
154
+ # Fallback to individual calls for this batch
155
+ for text in batch_texts:
156
+ try:
157
+ embedding, usage = await self.async_get_embedding_and_usage(text)
158
+ all_embeddings.append(embedding)
159
+ all_usage.append(usage)
160
+ except Exception as e2:
161
+ logger.warning(f"Error in individual async embedding fallback: {e2}")
162
+ all_embeddings.append([])
163
+ all_usage.append(None)
164
+
165
+ return all_embeddings, all_usage