agno 2.2.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,468 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from os import getenv
4
+ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from agno.models.base import Model
9
+ from agno.models.message import Message
10
+ from agno.models.metrics import Metrics
11
+ from agno.models.response import ModelResponse
12
+ from agno.run.agent import RunOutput
13
+ from agno.utils.log import log_debug, log_error, log_warning
14
+ from agno.utils.openai import _format_file_for_message, audio_to_message, images_to_message
15
+
16
+ try:
17
+ import litellm
18
+ from litellm import validate_environment
19
+ except ImportError:
20
+ raise ImportError("`litellm` not installed. Please install it via `pip install litellm`")
21
+
22
+
23
+ @dataclass
24
+ class LiteLLM(Model):
25
+ """
26
+ A class for interacting with LiteLLM Python SDK.
27
+
28
+ LiteLLM allows you to use a unified interface for various LLM providers.
29
+ For more information, see: https://docs.litellm.ai/docs/
30
+ """
31
+
32
+ id: str = "gpt-4o"
33
+ name: str = "LiteLLM"
34
+ provider: str = "LiteLLM"
35
+
36
+ api_key: Optional[str] = None
37
+ api_base: Optional[str] = None
38
+ max_tokens: Optional[int] = None
39
+ temperature: float = 0.7
40
+ top_p: float = 1.0
41
+ metadata: Optional[Dict[str, Any]] = None
42
+ extra_headers: Optional[Dict[str, Any]] = None
43
+ extra_query: Optional[Dict[str, Any]] = None
44
+ extra_body: Optional[Dict[str, Any]] = None
45
+ request_params: Optional[Dict[str, Any]] = None
46
+
47
+ client: Optional[Any] = None
48
+
49
+ def __post_init__(self):
50
+ """Initialize the model after the dataclass initialization."""
51
+ super().__post_init__()
52
+
53
+ # Set up API key from environment variable if not already set
54
+ if not self.client and not self.api_key:
55
+ self.api_key = getenv("LITELLM_API_KEY")
56
+ if not self.api_key:
57
+ # Check for other present valid keys, e.g. OPENAI_API_KEY if self.id is an OpenAI model
58
+ env_validation = validate_environment(model=self.id, api_base=self.api_base)
59
+ if not env_validation.get("keys_in_environment"):
60
+ log_warning(
61
+ "Missing required key. Please set the LITELLM_API_KEY or other valid environment variables."
62
+ )
63
+
64
+ def get_client(self) -> Any:
65
+ """
66
+ Returns a LiteLLM client.
67
+
68
+ Returns:
69
+ Any: An instance of the LiteLLM client.
70
+ """
71
+ if self.client is not None:
72
+ return self.client
73
+
74
+ self.client = litellm
75
+ return self.client
76
+
77
+ def _format_messages(self, messages: List[Message]) -> List[Dict[str, Any]]:
78
+ """Format messages for LiteLLM API."""
79
+ formatted_messages = []
80
+ for m in messages:
81
+ msg = {"role": m.role, "content": m.content if m.content is not None else ""}
82
+
83
+ # Handle media
84
+ if (m.images is not None and len(m.images) > 0) or (m.audio is not None and len(m.audio) > 0):
85
+ if isinstance(m.content, str):
86
+ content_list = [{"type": "text", "text": m.content}]
87
+ if m.images is not None:
88
+ content_list.extend(images_to_message(images=m.images))
89
+ if m.audio is not None:
90
+ content_list.extend(audio_to_message(audio=m.audio))
91
+ msg["content"] = content_list
92
+
93
+ if m.videos is not None and len(m.videos) > 0:
94
+ log_warning("Video input is currently unsupported by LLM providers.")
95
+
96
+ # Handle files
97
+ if m.files is not None:
98
+ if isinstance(msg["content"], str):
99
+ content_list = [{"type": "text", "text": msg["content"]}]
100
+ else:
101
+ content_list = msg["content"]
102
+ for file in m.files:
103
+ file_part = _format_file_for_message(file)
104
+ if file_part:
105
+ content_list.append(file_part)
106
+ msg["content"] = content_list
107
+
108
+ # Handle tool calls in assistant messages
109
+ if m.role == "assistant" and m.tool_calls:
110
+ msg["tool_calls"] = [
111
+ {
112
+ "id": tc.get("id", f"call_{i}"),
113
+ "type": "function",
114
+ "function": {"name": tc["function"]["name"], "arguments": tc["function"]["arguments"]},
115
+ }
116
+ for i, tc in enumerate(m.tool_calls)
117
+ ]
118
+
119
+ # Handle tool responses
120
+ if m.role == "tool":
121
+ msg["tool_call_id"] = m.tool_call_id or ""
122
+ msg["name"] = m.name or ""
123
+
124
+ if m.audio is not None and len(m.audio) > 0:
125
+ log_warning("Audio input is currently unsupported.")
126
+
127
+ if m.images is not None and len(m.images) > 0:
128
+ log_warning("Image input is currently unsupported.")
129
+
130
+ if m.videos is not None and len(m.videos) > 0:
131
+ log_warning("Video input is currently unsupported.")
132
+ formatted_messages.append(msg)
133
+
134
+ return formatted_messages
135
+
136
+ def get_request_params(self, tools: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
137
+ """
138
+ Returns keyword arguments for API requests.
139
+
140
+ Returns:
141
+ Dict[str, Any]: The API kwargs for the model.
142
+ """
143
+ base_params: Dict[str, Any] = {
144
+ "model": self.id,
145
+ "temperature": self.temperature,
146
+ "top_p": self.top_p,
147
+ }
148
+
149
+ if self.max_tokens:
150
+ base_params["max_tokens"] = self.max_tokens
151
+ if self.api_key:
152
+ base_params["api_key"] = self.api_key
153
+ if self.api_base:
154
+ base_params["api_base"] = self.api_base
155
+ if self.extra_headers:
156
+ base_params["extra_headers"] = self.extra_headers
157
+ if self.extra_query:
158
+ base_params["extra_query"] = self.extra_query
159
+ if tools:
160
+ base_params["tools"] = tools
161
+ base_params["tool_choice"] = "auto"
162
+
163
+ # Handle metadata via extra_body as per LiteLLM docs
164
+ if self.metadata:
165
+ if self.extra_body:
166
+ base_params["extra_body"] = {**self.extra_body, "metadata": self.metadata}
167
+ else:
168
+ base_params["extra_body"] = {"metadata": self.metadata}
169
+ elif self.extra_body:
170
+ base_params["extra_body"] = self.extra_body
171
+
172
+ # Add additional request params if provided
173
+ request_params: Dict[str, Any] = {k: v for k, v in base_params.items() if v is not None}
174
+ if self.request_params:
175
+ request_params.update(self.request_params)
176
+
177
+ if request_params:
178
+ log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
179
+ return request_params
180
+
181
+ def invoke(
182
+ self,
183
+ messages: List[Message],
184
+ assistant_message: Message,
185
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
186
+ tools: Optional[List[Dict[str, Any]]] = None,
187
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
188
+ run_response: Optional[RunOutput] = None,
189
+ ) -> ModelResponse:
190
+ """Sends a chat completion request to the LiteLLM API."""
191
+ completion_kwargs = self.get_request_params(tools=tools)
192
+ completion_kwargs["messages"] = self._format_messages(messages)
193
+
194
+ if run_response and run_response.metrics:
195
+ run_response.metrics.set_time_to_first_token()
196
+
197
+ assistant_message.metrics.start_timer()
198
+
199
+ provider_response = self.get_client().completion(**completion_kwargs)
200
+
201
+ assistant_message.metrics.stop_timer()
202
+
203
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
204
+ return model_response
205
+
206
+ def invoke_stream(
207
+ self,
208
+ messages: List[Message],
209
+ assistant_message: Message,
210
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
211
+ tools: Optional[List[Dict[str, Any]]] = None,
212
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
213
+ run_response: Optional[RunOutput] = None,
214
+ ) -> Iterator[ModelResponse]:
215
+ """Sends a streaming chat completion request to the LiteLLM API."""
216
+ completion_kwargs = self.get_request_params(tools=tools)
217
+ completion_kwargs["messages"] = self._format_messages(messages)
218
+ completion_kwargs["stream"] = True
219
+ completion_kwargs["stream_options"] = {"include_usage": True}
220
+
221
+ if run_response and run_response.metrics:
222
+ run_response.metrics.set_time_to_first_token()
223
+
224
+ assistant_message.metrics.start_timer()
225
+
226
+ for chunk in self.get_client().completion(**completion_kwargs):
227
+ yield self._parse_provider_response_delta(chunk)
228
+
229
+ assistant_message.metrics.stop_timer()
230
+
231
+ async def ainvoke(
232
+ self,
233
+ messages: List[Message],
234
+ assistant_message: Message,
235
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
236
+ tools: Optional[List[Dict[str, Any]]] = None,
237
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
238
+ run_response: Optional[RunOutput] = None,
239
+ ) -> ModelResponse:
240
+ """Sends an asynchronous chat completion request to the LiteLLM API."""
241
+ completion_kwargs = self.get_request_params(tools=tools)
242
+ completion_kwargs["messages"] = self._format_messages(messages)
243
+
244
+ if run_response and run_response.metrics:
245
+ run_response.metrics.set_time_to_first_token()
246
+
247
+ assistant_message.metrics.start_timer()
248
+
249
+ provider_response = await self.get_client().acompletion(**completion_kwargs)
250
+
251
+ assistant_message.metrics.stop_timer()
252
+
253
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
254
+ return model_response
255
+
256
+ async def ainvoke_stream(
257
+ self,
258
+ messages: List[Message],
259
+ assistant_message: Message,
260
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
261
+ tools: Optional[List[Dict[str, Any]]] = None,
262
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
263
+ run_response: Optional[RunOutput] = None,
264
+ ) -> AsyncIterator[ModelResponse]:
265
+ """Sends an asynchronous streaming chat request to the LiteLLM API."""
266
+ completion_kwargs = self.get_request_params(tools=tools)
267
+ completion_kwargs["messages"] = self._format_messages(messages)
268
+ completion_kwargs["stream"] = True
269
+ completion_kwargs["stream_options"] = {"include_usage": True}
270
+
271
+ if run_response and run_response.metrics:
272
+ run_response.metrics.set_time_to_first_token()
273
+
274
+ assistant_message.metrics.start_timer()
275
+
276
+ try:
277
+ # litellm.acompletion returns a coroutine that resolves to an async iterator
278
+ # We need to await it first to get the actual async iterator
279
+ async_stream = await self.get_client().acompletion(**completion_kwargs)
280
+ async for chunk in async_stream:
281
+ yield self._parse_provider_response_delta(chunk)
282
+
283
+ assistant_message.metrics.stop_timer()
284
+
285
+ except Exception as e:
286
+ log_error(f"Error in streaming response: {e}")
287
+ raise
288
+
289
+ def _parse_provider_response(self, response: Any, **kwargs) -> ModelResponse:
290
+ """Parse the provider response."""
291
+ model_response = ModelResponse()
292
+
293
+ response_message = response.choices[0].message
294
+
295
+ if response_message.content is not None:
296
+ model_response.content = response_message.content
297
+
298
+ if hasattr(response_message, "tool_calls") and response_message.tool_calls:
299
+ model_response.tool_calls = []
300
+ for tool_call in response_message.tool_calls:
301
+ model_response.tool_calls.append(
302
+ {
303
+ "id": tool_call.id,
304
+ "type": "function",
305
+ "function": {"name": tool_call.function.name, "arguments": tool_call.function.arguments},
306
+ }
307
+ )
308
+
309
+ if response.usage is not None:
310
+ model_response.response_usage = self._get_metrics(response.usage)
311
+
312
+ return model_response
313
+
314
+ def _parse_provider_response_delta(self, response_delta: Any) -> ModelResponse:
315
+ """Parse the provider response delta for streaming responses."""
316
+ model_response = ModelResponse()
317
+
318
+ if hasattr(response_delta, "choices") and len(response_delta.choices) > 0:
319
+ choice_delta = response_delta.choices[0].delta
320
+
321
+ if choice_delta:
322
+ if hasattr(choice_delta, "content") and choice_delta.content is not None:
323
+ model_response.content = choice_delta.content
324
+
325
+ if hasattr(choice_delta, "tool_calls") and choice_delta.tool_calls:
326
+ processed_tool_calls = []
327
+ for tool_call in choice_delta.tool_calls:
328
+ # Get the actual index from the tool call, defaulting to 0 if not available
329
+ actual_index = getattr(tool_call, "index", 0) if hasattr(tool_call, "index") else 0
330
+
331
+ # Create a basic structure with the correct index
332
+ tool_call_dict = {"index": actual_index, "type": "function"}
333
+
334
+ # Extract ID if available
335
+ if hasattr(tool_call, "id") and tool_call.id is not None:
336
+ tool_call_dict["id"] = tool_call.id
337
+
338
+ # Extract function data
339
+ function_data = {}
340
+ if hasattr(tool_call, "function"):
341
+ if hasattr(tool_call.function, "name") and tool_call.function.name is not None:
342
+ function_data["name"] = tool_call.function.name
343
+ if hasattr(tool_call.function, "arguments") and tool_call.function.arguments is not None:
344
+ function_data["arguments"] = tool_call.function.arguments
345
+
346
+ tool_call_dict["function"] = function_data
347
+ processed_tool_calls.append(tool_call_dict)
348
+
349
+ model_response.tool_calls = processed_tool_calls
350
+
351
+ # Add usage metrics if present in streaming response
352
+ if hasattr(response_delta, "usage") and response_delta.usage is not None:
353
+ model_response.response_usage = self._get_metrics(response_delta.usage)
354
+
355
+ return model_response
356
+
357
+ @staticmethod
358
+ def parse_tool_calls(tool_calls_data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
359
+ """
360
+ Build tool calls from streamed tool call data.
361
+
362
+ Args:
363
+ tool_calls_data (List[Dict[str, Any]]): The tool call data to build from.
364
+
365
+ Returns:
366
+ List[Dict[str, Any]]: The built tool calls.
367
+ """
368
+ # Early return for empty list
369
+ if not tool_calls_data:
370
+ return []
371
+
372
+ # Group tool calls by index
373
+ tool_calls_by_index: Dict[int, Dict[str, Any]] = {}
374
+
375
+ for tc in tool_calls_data:
376
+ # Get index (default to 0)
377
+ index = tc.get("index", 0)
378
+ if not isinstance(index, int):
379
+ index = 0
380
+
381
+ # Initialize if first time seeing this index
382
+ if index not in tool_calls_by_index:
383
+ tool_calls_by_index[index] = {"id": None, "type": "function", "function": {"name": "", "arguments": ""}}
384
+
385
+ # Update with new information
386
+ if tc.get("id") is not None:
387
+ tool_calls_by_index[index]["id"] = tc["id"]
388
+
389
+ if tc.get("type") is not None:
390
+ tool_calls_by_index[index]["type"] = tc["type"]
391
+
392
+ # Update function information
393
+ function_data = tc.get("function", {})
394
+ if not isinstance(function_data, dict):
395
+ function_data = {}
396
+
397
+ # Update function name if provided
398
+ if function_data.get("name") is not None:
399
+ name = function_data.get("name", "")
400
+ if isinstance(tool_calls_by_index[index]["function"], dict):
401
+ # type: ignore
402
+ tool_calls_by_index[index]["function"]["name"] = name
403
+
404
+ # Update function arguments if provided
405
+ if function_data.get("arguments") is not None:
406
+ args = function_data.get("arguments", "")
407
+ if isinstance(tool_calls_by_index[index]["function"], dict):
408
+ current_args = tool_calls_by_index[index]["function"].get("arguments", "") # type: ignore
409
+ if isinstance(current_args, str) and isinstance(args, str):
410
+ # type: ignore
411
+ tool_calls_by_index[index]["function"]["arguments"] = current_args + args
412
+
413
+ # Process arguments - Ensure they're valid JSON for the Message.log() method
414
+ result = []
415
+ for tc in tool_calls_by_index.values():
416
+ # Make a safe copy to avoid modifying the original
417
+ tc_copy = {
418
+ "id": tc.get("id"),
419
+ "type": tc.get("type", "function"),
420
+ "function": {"name": "", "arguments": ""},
421
+ }
422
+
423
+ # Safely copy function data
424
+ if isinstance(tc.get("function"), dict):
425
+ func_dict = tc.get("function", {})
426
+ tc_copy["function"]["name"] = func_dict.get("name", "")
427
+
428
+ # Process arguments
429
+ args = func_dict.get("arguments", "")
430
+ if args and isinstance(args, str):
431
+ try:
432
+ # Check if arguments are already valid JSON
433
+ parsed = json.loads(args)
434
+ # If it's not a dict, convert to a JSON string of a dict
435
+ if not isinstance(parsed, dict):
436
+ tc_copy["function"]["arguments"] = json.dumps({"value": parsed})
437
+ else:
438
+ tc_copy["function"]["arguments"] = args
439
+ except json.JSONDecodeError:
440
+ # If not valid JSON, make it a JSON dict
441
+ tc_copy["function"]["arguments"] = json.dumps({"text": args})
442
+
443
+ result.append(tc_copy)
444
+
445
+ return result
446
+
447
+ def _get_metrics(self, response_usage: Any) -> Metrics:
448
+ """
449
+ Parse the given LiteLLM usage into an Agno Metrics object.
450
+
451
+ Args:
452
+ response_usage: Usage data from LiteLLM
453
+
454
+ Returns:
455
+ Metrics: Parsed metrics data
456
+ """
457
+ metrics = Metrics()
458
+
459
+ if isinstance(response_usage, dict):
460
+ metrics.input_tokens = response_usage.get("prompt_tokens") or 0
461
+ metrics.output_tokens = response_usage.get("completion_tokens") or 0
462
+ else:
463
+ metrics.input_tokens = response_usage.prompt_tokens or 0
464
+ metrics.output_tokens = response_usage.completion_tokens or 0
465
+
466
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
467
+
468
+ return metrics
@@ -0,0 +1,25 @@
1
+ from dataclasses import dataclass, field
2
+ from os import getenv
3
+ from typing import Optional
4
+
5
+ from agno.models.openai.like import OpenAILike
6
+
7
+
8
+ @dataclass
9
+ class LiteLLMOpenAI(OpenAILike):
10
+ """
11
+ A class for interacting with LiteLLM.
12
+
13
+ Attributes:
14
+ id (str): The id of the LiteLLM model. Default is "gpt-4o".
15
+ name (str): The name of this chat model instance. Default is "LiteLLM".
16
+ provider (str): The provider of the model. Default is "LiteLLM".
17
+ base_url (str): The base url to which the requests are sent.
18
+ """
19
+
20
+ id: str = "gpt-4o"
21
+ name: str = "LiteLLM"
22
+ provider: str = "LiteLLM"
23
+
24
+ api_key: Optional[str] = field(default_factory=lambda: getenv("LITELLM_API_KEY"))
25
+ base_url: str = "http://0.0.0.0:4000"
@@ -0,0 +1,5 @@
1
+ from agno.models.llama_cpp.llama_cpp import LlamaCpp
2
+
3
+ __all__ = [
4
+ "LlamaCpp",
5
+ ]
@@ -0,0 +1,22 @@
1
+ from dataclasses import dataclass
2
+
3
+ from agno.models.openai.like import OpenAILike
4
+
5
+
6
+ @dataclass
7
+ class LlamaCpp(OpenAILike):
8
+ """
9
+ A class for interacting with LLMs using Llama CPP.
10
+
11
+ Attributes:
12
+ id (str): The id of the Llama CPP model. Default is "ggml-org/gpt-oss-20b-GGUF".
13
+ name (str): The name of this chat model instance. Default is "LlamaCpp".
14
+ provider (str): The provider of the model. Default is "LlamaCpp".
15
+ base_url (str): The base url to which the requests are sent.
16
+ """
17
+
18
+ id: str = "ggml-org/gpt-oss-20b-GGUF"
19
+ name: str = "LlamaCpp"
20
+ provider: str = "LlamaCpp"
21
+
22
+ base_url: str = "http://127.0.0.1:8080/v1"
@@ -0,0 +1,5 @@
1
+ from agno.models.lmstudio.lmstudio import LMStudio
2
+
3
+ __all__ = [
4
+ "LMStudio",
5
+ ]
@@ -0,0 +1,25 @@
1
+ from dataclasses import dataclass
2
+
3
+ from agno.models.openai.like import OpenAILike
4
+
5
+
6
+ @dataclass
7
+ class LMStudio(OpenAILike):
8
+ """
9
+ A class for interacting with LM Studio.
10
+
11
+ Attributes:
12
+ id (str): The id of the LM Studio model. Default is "qwen2.5-7b-instruct-1m".
13
+ name (str): The name of this chat model instance. Default is "LMStudio".
14
+ provider (str): The provider of the model. Default is "LMStudio".
15
+ base_url (str): The base url to which the requests are sent.
16
+ """
17
+
18
+ id: str = "qwen2.5-7b-instruct-1m"
19
+ name: str = "LMStudio"
20
+ provider: str = "LMStudio"
21
+
22
+ base_url: str = "http://127.0.0.1:1234/v1"
23
+
24
+ supports_native_structured_outputs: bool = False
25
+ supports_json_schema_outputs: bool = True