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,475 @@
1
+ from collections.abc import AsyncIterator
2
+ from dataclasses import dataclass
3
+ from os import getenv
4
+ from typing import Any, Dict, Iterator, List, Optional, Type, Union
5
+
6
+ import httpx
7
+ from pydantic import BaseModel
8
+
9
+ from agno.exceptions import ModelProviderError
10
+ from agno.models.base import Model
11
+ from agno.models.message import Message
12
+ from agno.models.metrics import Metrics
13
+ from agno.models.response import ModelResponse
14
+ from agno.run.agent import RunOutput
15
+ from agno.utils.log import log_debug, log_error, log_warning
16
+ from agno.utils.models.llama import format_message
17
+
18
+ try:
19
+ from llama_api_client import AsyncLlamaAPIClient, LlamaAPIClient
20
+ from llama_api_client.types.create_chat_completion_response import CreateChatCompletionResponse, Metric
21
+ from llama_api_client.types.create_chat_completion_response_stream_chunk import (
22
+ CreateChatCompletionResponseStreamChunk,
23
+ EventDeltaTextDelta,
24
+ EventDeltaToolCallDelta,
25
+ EventDeltaToolCallDeltaFunction,
26
+ EventMetric,
27
+ )
28
+ from llama_api_client.types.message_text_content_item import MessageTextContentItem
29
+ except ImportError:
30
+ raise ImportError("`llama-api-client` not installed. Please install using `pip install llama-api-client`")
31
+
32
+
33
+ @dataclass
34
+ class Llama(Model):
35
+ """
36
+ A class for interacting with Llama models using the Llama API using the Llama SDK.
37
+ """
38
+
39
+ id: str = "Llama-4-Maverick-17B-128E-Instruct-FP8"
40
+ name: str = "Llama"
41
+ provider: str = "Llama"
42
+
43
+ supports_native_structured_outputs: bool = False
44
+ supports_json_schema_outputs: bool = True
45
+
46
+ # Request parameters
47
+ max_completion_tokens: Optional[int] = None
48
+ repetition_penalty: Optional[float] = None
49
+ temperature: Optional[float] = None
50
+ top_p: Optional[float] = None
51
+ top_k: Optional[int] = None
52
+ extra_headers: Optional[Any] = None
53
+ extra_query: Optional[Any] = None
54
+ extra_body: Optional[Any] = None
55
+ request_params: Optional[Dict[str, Any]] = None
56
+
57
+ # Client parameters
58
+ api_key: Optional[str] = None
59
+ base_url: Optional[Union[str, httpx.URL]] = None
60
+ timeout: Optional[float] = None
61
+ max_retries: Optional[int] = None
62
+ default_headers: Optional[Any] = None
63
+ default_query: Optional[Any] = None
64
+ http_client: Optional[Union[httpx.Client, httpx.AsyncClient]] = None
65
+ client_params: Optional[Dict[str, Any]] = None
66
+
67
+ # OpenAI clients
68
+ client: Optional[LlamaAPIClient] = None
69
+ async_client: Optional[AsyncLlamaAPIClient] = None
70
+
71
+ def _get_client_params(self) -> Dict[str, Any]:
72
+ # Fetch API key from env if not already set
73
+ if not self.api_key:
74
+ self.api_key = getenv("LLAMA_API_KEY")
75
+ if not self.api_key:
76
+ log_error("LLAMA_API_KEY not set. Please set the LLAMA_API_KEY environment variable.")
77
+
78
+ # Define base client params
79
+ base_params = {
80
+ "api_key": self.api_key,
81
+ "base_url": self.base_url,
82
+ "timeout": self.timeout,
83
+ "max_retries": self.max_retries,
84
+ "default_headers": self.default_headers,
85
+ "default_query": self.default_query,
86
+ }
87
+
88
+ # Create client_params dict with non-None values
89
+ client_params = {k: v for k, v in base_params.items() if v is not None}
90
+
91
+ # Add additional client params if provided
92
+ if self.client_params:
93
+ client_params.update(self.client_params)
94
+ return client_params
95
+
96
+ def get_client(self) -> LlamaAPIClient:
97
+ """
98
+ Returns a Llama client.
99
+
100
+ Returns:
101
+ LlamaAPIClient: An instance of the Llama client.
102
+ """
103
+ if self.client and not self.client.is_closed():
104
+ return self.client
105
+
106
+ client_params: Dict[str, Any] = self._get_client_params()
107
+ if self.http_client:
108
+ if isinstance(self.http_client, httpx.Client):
109
+ client_params["http_client"] = self.http_client
110
+ else:
111
+ log_debug("http_client is not an instance of httpx.Client.")
112
+ self.client = LlamaAPIClient(**client_params)
113
+ return self.client
114
+
115
+ def get_async_client(self) -> AsyncLlamaAPIClient:
116
+ """
117
+ Returns an asynchronous Llama client.
118
+
119
+ Returns:
120
+ AsyncLlamaAPIClient: An instance of the asynchronous Llama client.
121
+ """
122
+ if self.async_client and not self.async_client.is_closed():
123
+ return self.async_client
124
+
125
+ client_params: Dict[str, Any] = self._get_client_params()
126
+ if self.http_client and isinstance(self.http_client, httpx.AsyncClient):
127
+ client_params["http_client"] = self.http_client
128
+ else:
129
+ if self.http_client:
130
+ log_debug("The current http_client is not async. A default httpx.AsyncClient will be used instead.")
131
+ # Create a new async HTTP client with custom limits
132
+ client_params["http_client"] = httpx.AsyncClient(
133
+ limits=httpx.Limits(max_connections=1000, max_keepalive_connections=100)
134
+ )
135
+ self.async_client = AsyncLlamaAPIClient(**client_params)
136
+ return self.async_client
137
+
138
+ def get_request_params(
139
+ self,
140
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
141
+ tools: Optional[List[Dict[str, Any]]] = None,
142
+ ) -> Dict[str, Any]:
143
+ """
144
+ Returns keyword arguments for API requests.
145
+ """
146
+ # Define base request parameters
147
+ base_params = {
148
+ "max_completion_tokens": self.max_completion_tokens,
149
+ "repetition_penalty": self.repetition_penalty,
150
+ "temperature": self.temperature,
151
+ "top_p": self.top_p,
152
+ "top_k": self.top_k,
153
+ "extra_headers": self.extra_headers,
154
+ "extra_query": self.extra_query,
155
+ "extra_body": self.extra_body,
156
+ "request_params": self.request_params,
157
+ }
158
+
159
+ # Filter out None values
160
+ request_params = {k: v for k, v in base_params.items() if v is not None}
161
+
162
+ # Add tools
163
+ if tools is not None and len(tools) > 0:
164
+ request_params["tools"] = tools
165
+
166
+ if response_format is not None:
167
+ request_params["response_format"] = response_format
168
+
169
+ # Add additional request params if provided
170
+ if self.request_params:
171
+ request_params.update(self.request_params)
172
+
173
+ if request_params:
174
+ log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
175
+ return request_params
176
+
177
+ def to_dict(self) -> Dict[str, Any]:
178
+ """
179
+ Convert the model to a dictionary.
180
+
181
+ Returns:
182
+ Dict[str, Any]: The dictionary representation of the model.
183
+ """
184
+ model_dict = super().to_dict()
185
+ model_dict.update(
186
+ {
187
+ "max_completion_tokens": self.max_completion_tokens,
188
+ "repetition_penalty": self.repetition_penalty,
189
+ "temperature": self.temperature,
190
+ "top_p": self.top_p,
191
+ "top_k": self.top_k,
192
+ "extra_headers": self.extra_headers,
193
+ "extra_query": self.extra_query,
194
+ "extra_body": self.extra_body,
195
+ "request_params": self.request_params,
196
+ }
197
+ )
198
+ cleaned_dict = {k: v for k, v in model_dict.items() if v is not None}
199
+ return cleaned_dict
200
+
201
+ def invoke(
202
+ self,
203
+ messages: List[Message],
204
+ assistant_message: Message,
205
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
206
+ tools: Optional[List[Dict[str, Any]]] = None,
207
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
208
+ run_response: Optional[RunOutput] = None,
209
+ ) -> ModelResponse:
210
+ """
211
+ Send a chat completion request to the Llama API.
212
+ """
213
+ assistant_message.metrics.start_timer()
214
+
215
+ provider_response = self.get_client().chat.completions.create(
216
+ model=self.id,
217
+ messages=[format_message(m, tool_calls=bool(tools)) for m in messages], # type: ignore
218
+ **self.get_request_params(tools=tools, response_format=response_format),
219
+ )
220
+
221
+ assistant_message.metrics.stop_timer()
222
+
223
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
224
+ return model_response
225
+
226
+ async def ainvoke(
227
+ self,
228
+ messages: List[Message],
229
+ assistant_message: Message,
230
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
231
+ tools: Optional[List[Dict[str, Any]]] = None,
232
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
233
+ run_response: Optional[RunOutput] = None,
234
+ ) -> ModelResponse:
235
+ """
236
+ Sends an asynchronous chat completion request to the Llama API.
237
+ """
238
+ if run_response and run_response.metrics:
239
+ run_response.metrics.set_time_to_first_token()
240
+
241
+ assistant_message.metrics.start_timer()
242
+
243
+ provider_response = await self.get_async_client().chat.completions.create(
244
+ model=self.id,
245
+ messages=[format_message(m, tool_calls=bool(tools)) for m in messages], # type: ignore
246
+ **self.get_request_params(tools=tools, response_format=response_format),
247
+ )
248
+
249
+ assistant_message.metrics.stop_timer()
250
+
251
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
252
+ return model_response
253
+
254
+ def invoke_stream(
255
+ self,
256
+ messages: List[Message],
257
+ assistant_message: Message,
258
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
259
+ tools: Optional[List[Dict[str, Any]]] = None,
260
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
261
+ run_response: Optional[RunOutput] = None,
262
+ ) -> Iterator[ModelResponse]:
263
+ """
264
+ Send a streaming chat completion request to the Llama API.
265
+ """
266
+ if run_response and run_response.metrics:
267
+ run_response.metrics.set_time_to_first_token()
268
+
269
+ try:
270
+ assistant_message.metrics.start_timer()
271
+
272
+ for chunk in self.get_client().chat.completions.create(
273
+ model=self.id,
274
+ messages=[format_message(m, tool_calls=bool(tools)) for m in messages], # type: ignore
275
+ stream=True,
276
+ **self.get_request_params(tools=tools, response_format=response_format),
277
+ ):
278
+ yield self._parse_provider_response_delta(chunk) # type: ignore
279
+
280
+ assistant_message.metrics.stop_timer()
281
+
282
+ except Exception as e:
283
+ log_error(f"Error from Llama API: {e}")
284
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
285
+
286
+ async def ainvoke_stream(
287
+ self,
288
+ messages: List[Message],
289
+ assistant_message: Message,
290
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
291
+ tools: Optional[List[Dict[str, Any]]] = None,
292
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
293
+ run_response: Optional[RunOutput] = None,
294
+ ) -> AsyncIterator[ModelResponse]:
295
+ """
296
+ Sends an asynchronous streaming chat completion request to the Llama API.
297
+ """
298
+ if run_response and run_response.metrics:
299
+ run_response.metrics.set_time_to_first_token()
300
+
301
+ assistant_message.metrics.start_timer()
302
+
303
+ try:
304
+ async for chunk in await self.get_async_client().chat.completions.create(
305
+ model=self.id,
306
+ messages=[format_message(m, tool_calls=bool(tools)) for m in messages], # type: ignore
307
+ stream=True,
308
+ **self.get_request_params(tools=tools, response_format=response_format),
309
+ ):
310
+ yield self._parse_provider_response_delta(chunk) # type: ignore
311
+
312
+ assistant_message.metrics.stop_timer()
313
+
314
+ except Exception as e:
315
+ log_error(f"Error from Llama API: {e}")
316
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
317
+
318
+ def parse_tool_calls(self, tool_calls_data: List[EventDeltaToolCallDeltaFunction]) -> List[Dict[str, Any]]:
319
+ """
320
+ Parse the tool calls from the Llama API.
321
+
322
+ Args:
323
+ tool_calls_data (List[Tuple[str, Any]]): The tool calls data.
324
+
325
+ Returns:
326
+ List[Dict[str, Any]]: The parsed tool calls.
327
+ """
328
+ tool_calls: List[Dict[str, Any]] = []
329
+
330
+ _tool_call_id: Optional[str] = None
331
+ _function_name_parts: List[str] = []
332
+ _function_arguments_parts: List[str] = []
333
+
334
+ def _create_tool_call():
335
+ nonlocal _tool_call_id
336
+ if _tool_call_id and (_function_name_parts or _function_arguments_parts):
337
+ tool_calls.append(
338
+ {
339
+ "id": _tool_call_id,
340
+ "type": "function",
341
+ "function": {
342
+ "name": "".join(_function_name_parts),
343
+ "arguments": "".join(_function_arguments_parts),
344
+ },
345
+ }
346
+ )
347
+ _tool_call_id = None
348
+ _function_name_parts.clear()
349
+ _function_arguments_parts.clear()
350
+
351
+ for _field, _value in tool_calls_data:
352
+ if _field == "function" and isinstance(_value, EventDeltaToolCallDeltaFunction):
353
+ if _value.name and (_tool_call_id or _function_name_parts or _function_arguments_parts):
354
+ _create_tool_call()
355
+ if _value.name:
356
+ _function_name_parts.append(_value.name)
357
+ if _value.arguments:
358
+ _function_arguments_parts.append(_value.arguments)
359
+
360
+ elif _field == "id":
361
+ if _value and _tool_call_id:
362
+ _create_tool_call()
363
+ if _value:
364
+ _tool_call_id = _value # type: ignore
365
+
366
+ _create_tool_call()
367
+
368
+ return tool_calls
369
+
370
+ def _parse_provider_response(self, response: CreateChatCompletionResponse, **kwargs) -> ModelResponse:
371
+ """
372
+ Parse the Llama response into a ModelResponse.
373
+
374
+ Args:
375
+ response: Response from invoke() method
376
+
377
+ Returns:
378
+ ModelResponse: Parsed response data
379
+ """
380
+ model_response = ModelResponse()
381
+
382
+ # Get response message
383
+ response_message = response.completion_message
384
+
385
+ # Add role
386
+ if response_message.role is not None:
387
+ model_response.role = response_message.role
388
+
389
+ # Add content
390
+ if response_message.content is not None:
391
+ if isinstance(response_message.content, MessageTextContentItem):
392
+ model_response.content = response_message.content.text
393
+ else:
394
+ model_response.content = response_message.content
395
+
396
+ # Add tool calls
397
+ if response_message.tool_calls is not None and len(response_message.tool_calls) > 0:
398
+ try:
399
+ for tool_call in response_message.tool_calls:
400
+ tool_name = tool_call.function.name
401
+ tool_input = tool_call.function.arguments
402
+
403
+ function_def = {"name": tool_name}
404
+ if tool_input:
405
+ function_def["arguments"] = tool_input
406
+
407
+ model_response.tool_calls.append(
408
+ {
409
+ "id": tool_call.id,
410
+ "type": "function",
411
+ "function": function_def,
412
+ }
413
+ )
414
+
415
+ except Exception as e:
416
+ log_warning(f"Error processing tool calls: {e}")
417
+
418
+ # Add metrics from the metrics list
419
+ if hasattr(response, "metrics") and response.metrics is not None:
420
+ model_response.response_usage = self._get_metrics(response.metrics)
421
+
422
+ return model_response
423
+
424
+ def _parse_provider_response_delta(
425
+ self, response: CreateChatCompletionResponseStreamChunk, **kwargs
426
+ ) -> ModelResponse:
427
+ """
428
+ Parse the Llama streaming response into a ModelResponse.
429
+
430
+ Args:
431
+ response_delta: Raw response chunk from the Llama API
432
+
433
+ Returns:
434
+ ModelResponse: Parsed response data
435
+ """
436
+ model_response = ModelResponse()
437
+
438
+ if response is not None:
439
+ delta = response.event
440
+
441
+ # Capture metrics event
442
+ if delta.event_type == "metrics" and delta.metrics is not None:
443
+ model_response.response_usage = self._get_metrics(delta.metrics)
444
+
445
+ if isinstance(delta.delta, EventDeltaTextDelta):
446
+ model_response.content = delta.delta.text
447
+
448
+ # Add tool calls
449
+ if isinstance(delta.delta, EventDeltaToolCallDelta):
450
+ model_response.tool_calls = delta.delta # type: ignore
451
+
452
+ return model_response
453
+
454
+ def _get_metrics(self, response_usage: Union[List[Metric], List[EventMetric]]) -> Metrics:
455
+ """
456
+ Parse the given Llama usage into an Agno Metrics object.
457
+
458
+ Args:
459
+ response_usage: Usage data from Llama
460
+
461
+ Returns:
462
+ Metrics: Parsed metrics data
463
+ """
464
+ metrics = Metrics()
465
+
466
+ for metric in response_usage:
467
+ metrics_field = metric.metric
468
+ if metrics_field == "num_prompt_tokens":
469
+ metrics.input_tokens = int(metric.value)
470
+ elif metrics_field == "num_completion_tokens":
471
+ metrics.output_tokens = int(metric.value)
472
+
473
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
474
+
475
+ return metrics
@@ -0,0 +1,78 @@
1
+ from dataclasses import dataclass, field
2
+ from os import getenv
3
+ from typing import Any, Dict, Optional
4
+
5
+ import httpx
6
+
7
+ try:
8
+ from openai import AsyncOpenAI as AsyncOpenAIClient
9
+ except ImportError:
10
+ raise ImportError("`openai` not installed. Please install using `pip install openai`")
11
+
12
+ from agno.models.meta.llama import Message
13
+ from agno.models.openai.like import OpenAILike
14
+ from agno.utils.models.llama import format_message
15
+
16
+
17
+ @dataclass
18
+ class LlamaOpenAI(OpenAILike):
19
+ """
20
+ Class for interacting with the Llama API via OpenAI-like interface.
21
+
22
+ Attributes:
23
+ id (str): The ID of the language model.
24
+ name (str): The name of the API.
25
+ provider (str): The provider of the API.
26
+ api_key (Optional[str]): The API key for the xAI API.
27
+ base_url (Optional[str]): The base URL for the xAI API.
28
+ """
29
+
30
+ id: str = "Llama-4-Maverick-17B-128E-Instruct-FP8"
31
+ name: str = "LlamaOpenAI"
32
+ provider: str = "LlamaOpenAI"
33
+
34
+ api_key: Optional[str] = field(default_factory=lambda: getenv("LLAMA_API_KEY"))
35
+ base_url: Optional[str] = "https://api.llama.com/compat/v1/"
36
+
37
+ # Request parameters
38
+ max_completion_tokens: Optional[int] = None
39
+ repetition_penalty: Optional[float] = None
40
+ temperature: Optional[float] = None
41
+ top_p: Optional[float] = None
42
+ top_k: Optional[int] = None
43
+ extra_headers: Optional[Any] = None
44
+ extra_query: Optional[Any] = None
45
+ extra_body: Optional[Any] = None
46
+ request_params: Optional[Dict[str, Any]] = None
47
+
48
+ supports_native_structured_outputs: bool = False
49
+ supports_json_schema_outputs: bool = True
50
+
51
+ def _format_message(self, message: Message) -> Dict[str, Any]:
52
+ """
53
+ Format a message into the format expected by Llama API.
54
+
55
+ Args:
56
+ message (Message): The message to format.
57
+
58
+ Returns:
59
+ Dict[str, Any]: The formatted message.
60
+ """
61
+ return format_message(message, openai_like=True)
62
+
63
+ def get_async_client(self):
64
+ """Override to provide custom httpx client that properly handles redirects"""
65
+ if self.async_client and not self.async_client.is_closed():
66
+ return self.async_client
67
+
68
+ client_params = self._get_client_params()
69
+
70
+ # Llama gives a 307 redirect error, so we need to set up a custom client to allow redirects
71
+ client_params["http_client"] = httpx.AsyncClient(
72
+ limits=httpx.Limits(max_connections=1000, max_keepalive_connections=100),
73
+ follow_redirects=True,
74
+ timeout=httpx.Timeout(30.0),
75
+ )
76
+
77
+ self.async_client = AsyncOpenAIClient(**client_params)
78
+ return self.async_client
agno/models/metrics.py ADDED
@@ -0,0 +1,120 @@
1
+ from dataclasses import asdict, dataclass
2
+ from typing import Any, Dict, Optional
3
+
4
+ from agno.utils.timer import Timer
5
+
6
+
7
+ @dataclass
8
+ class Metrics:
9
+ """All relevant metrics for a session, run or message."""
10
+
11
+ # Main token consumption values
12
+ input_tokens: int = 0
13
+ output_tokens: int = 0
14
+ total_tokens: int = 0
15
+
16
+ # Audio token usage
17
+ audio_input_tokens: int = 0
18
+ audio_output_tokens: int = 0
19
+ audio_total_tokens: int = 0
20
+
21
+ # Cache token usage
22
+ cache_read_tokens: int = 0
23
+ cache_write_tokens: int = 0
24
+
25
+ # Tokens employed in reasoning
26
+ reasoning_tokens: int = 0
27
+
28
+ # Time metrics
29
+ # Internal timer utility for tracking execution time
30
+ timer: Optional[Timer] = None
31
+ # Time from run start to first token generation, in seconds
32
+ time_to_first_token: Optional[float] = None
33
+ # Total run time, in seconds
34
+ duration: Optional[float] = None
35
+
36
+ # Provider-specific metrics
37
+ provider_metrics: Optional[dict] = None
38
+
39
+ # Any additional metrics
40
+ additional_metrics: Optional[dict] = None
41
+
42
+ def to_dict(self) -> Dict[str, Any]:
43
+ metrics_dict = asdict(self)
44
+ # Remove the timer util if present
45
+ metrics_dict.pop("timer", None)
46
+ metrics_dict = {
47
+ k: v
48
+ for k, v in metrics_dict.items()
49
+ if v is not None and (not isinstance(v, (int, float)) or v != 0) and (not isinstance(v, dict) or len(v) > 0)
50
+ }
51
+ return metrics_dict
52
+
53
+ def __add__(self, other: "Metrics") -> "Metrics":
54
+ # Create new instance of the same type as self
55
+ result_class = type(self)
56
+ result = result_class(
57
+ input_tokens=self.input_tokens + other.input_tokens,
58
+ output_tokens=self.output_tokens + other.output_tokens,
59
+ total_tokens=self.total_tokens + other.total_tokens,
60
+ audio_total_tokens=self.audio_total_tokens + other.audio_total_tokens,
61
+ audio_input_tokens=self.audio_input_tokens + other.audio_input_tokens,
62
+ audio_output_tokens=self.audio_output_tokens + other.audio_output_tokens,
63
+ cache_read_tokens=self.cache_read_tokens + other.cache_read_tokens,
64
+ cache_write_tokens=self.cache_write_tokens + other.cache_write_tokens,
65
+ reasoning_tokens=self.reasoning_tokens + other.reasoning_tokens,
66
+ )
67
+
68
+ # Handle provider_metrics
69
+ if self.provider_metrics or other.provider_metrics:
70
+ result.provider_metrics = {}
71
+ if self.provider_metrics:
72
+ result.provider_metrics.update(self.provider_metrics)
73
+ if other.provider_metrics:
74
+ result.provider_metrics.update(other.provider_metrics)
75
+
76
+ # Handle additional metrics
77
+ if self.additional_metrics or other.additional_metrics:
78
+ result.additional_metrics = {}
79
+ if self.additional_metrics:
80
+ result.additional_metrics.update(self.additional_metrics)
81
+ if other.additional_metrics:
82
+ result.additional_metrics.update(other.additional_metrics)
83
+
84
+ # Sum durations if both exist
85
+ if self.duration is not None and other.duration is not None:
86
+ result.duration = self.duration + other.duration
87
+ elif self.duration is not None:
88
+ result.duration = self.duration
89
+ elif other.duration is not None:
90
+ result.duration = other.duration
91
+
92
+ # Sum time to first token if both exist
93
+ if self.time_to_first_token is not None and other.time_to_first_token is not None:
94
+ result.time_to_first_token = self.time_to_first_token + other.time_to_first_token
95
+ elif self.time_to_first_token is not None:
96
+ result.time_to_first_token = self.time_to_first_token
97
+ elif other.time_to_first_token is not None:
98
+ result.time_to_first_token = other.time_to_first_token
99
+
100
+ return result
101
+
102
+ def __radd__(self, other: "Metrics") -> "Metrics":
103
+ if other == 0: # Handle sum() starting value
104
+ return self
105
+ return self + other
106
+
107
+ def start_timer(self):
108
+ if self.timer is None:
109
+ self.timer = Timer()
110
+ self.timer.start()
111
+
112
+ def stop_timer(self, set_duration: bool = True):
113
+ if self.timer is not None:
114
+ self.timer.stop()
115
+ if set_duration:
116
+ self.duration = self.timer.elapsed
117
+
118
+ def set_time_to_first_token(self):
119
+ if self.timer is not None:
120
+ self.time_to_first_token = self.timer.elapsed
@@ -0,0 +1,5 @@
1
+ from agno.models.mistral.mistral import MistralChat
2
+
3
+ __all__ = [
4
+ "MistralChat",
5
+ ]