agno 1.8.1__py3-none-any.whl → 2.0.0__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 (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +11 -66
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1743 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1432 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +882 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1045 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1416 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +15 -11
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1551 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +46 -151
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +85 -47
  158. agno/models/openai/chat.py +154 -37
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +15 -9
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +497 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +77 -33
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +32 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,15 @@
1
1
  from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Any, Dict, Iterator, List, Optional, Type, Union
3
+ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
7
  from agno.exceptions import ModelProviderError
8
8
  from agno.models.base import Model
9
9
  from agno.models.message import Message
10
+ from agno.models.metrics import Metrics
10
11
  from agno.models.response import ModelResponse
12
+ from agno.run.agent import RunOutput
11
13
  from agno.utils.log import log_debug, log_error
12
14
  from agno.utils.models.mistral import format_messages
13
15
 
@@ -24,7 +26,9 @@ try:
24
26
  ToolMessage,
25
27
  UserMessage,
26
28
  )
27
- from mistralai.models.chatcompletionresponse import ChatCompletionResponse
29
+ from mistralai.models.chatcompletionresponse import (
30
+ ChatCompletionResponse,
31
+ )
28
32
  from mistralai.models.deltamessage import DeltaMessage
29
33
  from mistralai.types.basemodel import Unset
30
34
 
@@ -165,10 +169,12 @@ class MistralChat(Model):
165
169
  def invoke(
166
170
  self,
167
171
  messages: List[Message],
172
+ assistant_message: Message,
168
173
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
169
174
  tools: Optional[List[Dict[str, Any]]] = None,
170
175
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
171
- ) -> Union[ChatCompletionResponse, ParsedChatCompletionResponse]:
176
+ run_response: Optional[RunOutput] = None,
177
+ ) -> ModelResponse:
172
178
  """
173
179
  Send a chat completion request to the Mistral model.
174
180
  """
@@ -180,6 +186,11 @@ class MistralChat(Model):
180
186
  and isinstance(response_format, type)
181
187
  and issubclass(response_format, BaseModel)
182
188
  ):
189
+ if run_response and run_response.metrics:
190
+ run_response.metrics.set_time_to_first_token()
191
+
192
+ assistant_message.metrics.start_timer()
193
+
183
194
  response = self.get_client().chat.complete(
184
195
  model=self.id,
185
196
  messages=mistral_messages,
@@ -187,12 +198,21 @@ class MistralChat(Model):
187
198
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
188
199
  )
189
200
  else:
201
+ if run_response and run_response.metrics:
202
+ run_response.metrics.set_time_to_first_token()
203
+
204
+ assistant_message.metrics.start_timer()
190
205
  response = self.get_client().chat.complete(
191
206
  model=self.id,
192
207
  messages=mistral_messages,
193
208
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
194
209
  )
195
- return response
210
+
211
+ assistant_message.metrics.stop_timer()
212
+
213
+ model_response = self._parse_provider_response(response, response_format=response_format)
214
+
215
+ return model_response
196
216
 
197
217
  except HTTPValidationError as e:
198
218
  log_error(f"HTTPValidationError from Mistral: {e}")
@@ -204,21 +224,32 @@ class MistralChat(Model):
204
224
  def invoke_stream(
205
225
  self,
206
226
  messages: List[Message],
227
+ assistant_message: Message,
207
228
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
208
229
  tools: Optional[List[Dict[str, Any]]] = None,
209
230
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
210
- ) -> Iterator[Any]:
231
+ run_response: Optional[RunOutput] = None,
232
+ ) -> Iterator[ModelResponse]:
211
233
  """
212
234
  Stream the response from the Mistral model.
213
235
  """
214
236
  mistral_messages = format_messages(messages)
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
+
215
243
  try:
216
- stream = self.get_client().chat.stream(
244
+ for chunk in self.get_client().chat.stream(
217
245
  model=self.id,
218
246
  messages=mistral_messages,
219
247
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
220
- )
221
- return stream
248
+ ):
249
+ yield self._parse_provider_response_delta(chunk)
250
+
251
+ assistant_message.metrics.stop_timer()
252
+
222
253
  except HTTPValidationError as e:
223
254
  log_error(f"HTTPValidationError from Mistral: {e}")
224
255
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -229,10 +260,12 @@ class MistralChat(Model):
229
260
  async def ainvoke(
230
261
  self,
231
262
  messages: List[Message],
263
+ assistant_message: Message,
232
264
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
233
265
  tools: Optional[List[Dict[str, Any]]] = None,
234
266
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
235
- ) -> Union[ChatCompletionResponse, ParsedChatCompletionResponse]:
267
+ run_response: Optional[RunOutput] = None,
268
+ ) -> ModelResponse:
236
269
  """
237
270
  Send an asynchronous chat completion request to the Mistral API.
238
271
  """
@@ -244,6 +277,9 @@ class MistralChat(Model):
244
277
  and isinstance(response_format, type)
245
278
  and issubclass(response_format, BaseModel)
246
279
  ):
280
+ if run_response and run_response.metrics:
281
+ run_response.metrics.set_time_to_first_token()
282
+ assistant_message.metrics.start_timer()
247
283
  response = await self.get_client().chat.complete_async(
248
284
  model=self.id,
249
285
  messages=mistral_messages,
@@ -251,12 +287,20 @@ class MistralChat(Model):
251
287
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
252
288
  )
253
289
  else:
290
+ if run_response and run_response.metrics:
291
+ run_response.metrics.set_time_to_first_token()
292
+ assistant_message.metrics.start_timer()
254
293
  response = await self.get_client().chat.complete_async(
255
294
  model=self.id,
256
295
  messages=mistral_messages,
257
296
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
258
297
  )
259
- return response
298
+
299
+ assistant_message.metrics.stop_timer()
300
+
301
+ model_response = self._parse_provider_response(response, response_format=response_format)
302
+
303
+ return model_response
260
304
  except HTTPValidationError as e:
261
305
  log_error(f"HTTPValidationError from Mistral: {e}")
262
306
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -267,24 +311,31 @@ class MistralChat(Model):
267
311
  async def ainvoke_stream(
268
312
  self,
269
313
  messages: List[Message],
314
+ assistant_message: Message,
270
315
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
271
316
  tools: Optional[List[Dict[str, Any]]] = None,
272
317
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
273
- ) -> Any:
318
+ run_response: Optional[RunOutput] = None,
319
+ ) -> AsyncIterator[ModelResponse]:
274
320
  """
275
321
  Stream an asynchronous response from the Mistral API.
276
322
  """
277
323
  mistral_messages = format_messages(messages)
278
324
  try:
279
- stream = await self.get_client().chat.stream_async(
325
+ if run_response and run_response.metrics:
326
+ run_response.metrics.set_time_to_first_token()
327
+
328
+ assistant_message.metrics.start_timer()
329
+
330
+ async for chunk in await self.get_client().chat.stream_async(
280
331
  model=self.id,
281
332
  messages=mistral_messages,
282
333
  **self.get_request_params(tools=tools, tool_choice=tool_choice),
283
- )
284
- if stream is None:
285
- raise ValueError("Chat stream returned None")
286
- async for chunk in stream:
287
- yield chunk
334
+ ):
335
+ yield self._parse_provider_response_delta(chunk)
336
+
337
+ assistant_message.metrics.stop_timer()
338
+
288
339
  except HTTPValidationError as e:
289
340
  log_error(f"HTTPValidationError from Mistral: {e}")
290
341
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -292,7 +343,7 @@ class MistralChat(Model):
292
343
  log_error(f"SDKError from Mistral: {e}")
293
344
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
294
345
 
295
- def parse_provider_response(self, response: ChatCompletionResponse, **kwargs) -> ModelResponse:
346
+ def _parse_provider_response(self, response: ChatCompletionResponse, **kwargs) -> ModelResponse:
296
347
  """
297
348
  Parse the response from the Mistral model.
298
349
 
@@ -322,11 +373,11 @@ class MistralChat(Model):
322
373
  )
323
374
 
324
375
  if response.usage is not None:
325
- model_response.response_usage = response.usage
376
+ model_response.response_usage = self._get_metrics(response.usage)
326
377
 
327
378
  return model_response
328
379
 
329
- def parse_provider_response_delta(self, response_delta: CompletionEvent) -> Optional[ModelResponse]:
380
+ def _parse_provider_response_delta(self, response_delta: CompletionEvent) -> ModelResponse:
330
381
  """
331
382
  Parse the response delta from the Mistral model.
332
383
  """
@@ -358,6 +409,24 @@ class MistralChat(Model):
358
409
  )
359
410
 
360
411
  if response_delta.data.usage is not None:
361
- model_response.response_usage = response_delta.data.usage
412
+ model_response.response_usage = self._get_metrics(response_delta.data.usage)
362
413
 
363
414
  return model_response
415
+
416
+ def _get_metrics(self, response_usage: Any) -> Metrics:
417
+ """
418
+ Parse the given Mistral usage into an Agno Metrics object.
419
+
420
+ Args:
421
+ response_usage: Usage data from Mistral
422
+
423
+ Returns:
424
+ Metrics: Parsed metrics data
425
+ """
426
+ metrics = Metrics()
427
+
428
+ metrics.input_tokens = response_usage.prompt_tokens or 0
429
+ metrics.output_tokens = response_usage.completion_tokens or 0
430
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
431
+
432
+ return metrics
@@ -1,7 +1,5 @@
1
1
  from agno.models.ollama.chat import Ollama
2
- from agno.models.ollama.tools import OllamaTools
3
2
 
4
3
  __all__ = [
5
4
  "Ollama",
6
- "OllamaTools",
7
5
  ]
@@ -1,11 +1,13 @@
1
1
  import json
2
2
  from dataclasses import dataclass
3
- from typing import Any, Dict, Iterator, List, Mapping, Optional, Type, Union
3
+ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
+ from agno.agent import RunOutput
7
8
  from agno.models.base import Model
8
9
  from agno.models.message import Message
10
+ from agno.models.metrics import Metrics
9
11
  from agno.models.response import ModelResponse
10
12
  from agno.utils.log import log_debug, log_warning
11
13
 
@@ -147,7 +149,7 @@ class Ollama(Model):
147
149
  message_images = []
148
150
  for image in message.images:
149
151
  if image.url is not None:
150
- message_images.append(image.image_url_content)
152
+ message_images.append(image.get_content_bytes())
151
153
  if image.filepath is not None:
152
154
  message_images.append(image.filepath) # type: ignore
153
155
  if image.content is not None and isinstance(image.content, bytes):
@@ -182,86 +184,124 @@ class Ollama(Model):
182
184
  def invoke(
183
185
  self,
184
186
  messages: List[Message],
187
+ assistant_message: Message,
185
188
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
186
189
  tools: Optional[List[Dict[str, Any]]] = None,
187
190
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
188
- ) -> Mapping[str, Any]:
191
+ run_response: Optional[RunOutput] = None,
192
+ ) -> ModelResponse:
189
193
  """
190
194
  Send a chat request to the Ollama API.
191
195
  """
192
196
  request_kwargs = self._prepare_request_kwargs_for_invoke(response_format=response_format, tools=tools)
193
197
 
194
- return self.get_client().chat(
198
+ if run_response and run_response.metrics:
199
+ run_response.metrics.set_time_to_first_token()
200
+
201
+ assistant_message.metrics.start_timer()
202
+
203
+ provider_response = self.get_client().chat(
195
204
  model=self.id.strip(),
196
205
  messages=[self._format_message(m) for m in messages], # type: ignore
197
206
  **request_kwargs,
198
207
  ) # type: ignore
199
208
 
209
+ assistant_message.metrics.stop_timer()
210
+
211
+ model_response = self._parse_provider_response(provider_response) # type: ignore
212
+ return model_response
213
+
200
214
  async def ainvoke(
201
215
  self,
202
216
  messages: List[Message],
217
+ assistant_message: Message,
203
218
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
204
219
  tools: Optional[List[Dict[str, Any]]] = None,
205
220
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
206
- ) -> Mapping[str, Any]:
221
+ run_response: Optional[RunOutput] = None,
222
+ ) -> ModelResponse:
207
223
  """
208
224
  Sends an asynchronous chat request to the Ollama API.
209
225
  """
210
226
  request_kwargs = self._prepare_request_kwargs_for_invoke(response_format=response_format, tools=tools)
211
227
 
212
- return await self.get_async_client().chat(
228
+ if run_response and run_response.metrics:
229
+ run_response.metrics.set_time_to_first_token()
230
+
231
+ assistant_message.metrics.start_timer()
232
+
233
+ provider_response = await self.get_async_client().chat(
213
234
  model=self.id.strip(),
214
235
  messages=[self._format_message(m) for m in messages], # type: ignore
215
236
  **request_kwargs,
216
237
  ) # type: ignore
217
238
 
239
+ assistant_message.metrics.stop_timer()
240
+
241
+ model_response = self._parse_provider_response(provider_response) # type: ignore
242
+ return model_response
243
+
218
244
  def invoke_stream(
219
245
  self,
220
246
  messages: List[Message],
247
+ assistant_message: Message,
221
248
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
222
249
  tools: Optional[List[Dict[str, Any]]] = None,
223
250
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
224
- ) -> Iterator[Mapping[str, Any]]:
251
+ run_response: Optional[RunOutput] = None,
252
+ ) -> Iterator[ModelResponse]:
225
253
  """
226
254
  Sends a streaming chat request to the Ollama API.
227
255
  """
228
- yield from self.get_client().chat(
256
+ if run_response and run_response.metrics:
257
+ run_response.metrics.set_time_to_first_token()
258
+
259
+ assistant_message.metrics.start_timer()
260
+
261
+ for chunk in self.get_client().chat(
229
262
  model=self.id,
230
263
  messages=[self._format_message(m) for m in messages], # type: ignore
231
264
  stream=True,
232
265
  **self.get_request_params(tools=tools),
233
- ) # type: ignore
266
+ ):
267
+ yield self._parse_provider_response_delta(chunk)
268
+
269
+ assistant_message.metrics.stop_timer()
234
270
 
235
271
  async def ainvoke_stream(
236
272
  self,
237
273
  messages: List[Message],
274
+ assistant_message: Message,
238
275
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
239
276
  tools: Optional[List[Dict[str, Any]]] = None,
240
277
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
241
- ) -> Any:
278
+ run_response: Optional[RunOutput] = None,
279
+ ) -> AsyncIterator[ModelResponse]:
242
280
  """
243
281
  Sends an asynchronous streaming chat completion request to the Ollama API.
244
282
  """
245
- async_stream = await self.get_async_client().chat(
283
+ if run_response and run_response.metrics:
284
+ run_response.metrics.set_time_to_first_token()
285
+
286
+ assistant_message.metrics.start_timer()
287
+
288
+ async for chunk in await self.get_async_client().chat(
246
289
  model=self.id.strip(),
247
290
  messages=[self._format_message(m) for m in messages], # type: ignore
248
291
  stream=True,
249
292
  **self.get_request_params(tools=tools),
250
- )
251
- async for chunk in async_stream: # type: ignore
252
- yield chunk
293
+ ):
294
+ yield self._parse_provider_response_delta(chunk)
253
295
 
254
- def parse_provider_response(
255
- self,
256
- response: ChatResponse,
257
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
258
- ) -> ModelResponse:
296
+ assistant_message.metrics.stop_timer()
297
+
298
+ def _parse_provider_response(self, response: dict) -> ModelResponse:
259
299
  """
260
300
  Parse the provider response.
261
301
  """
262
302
  model_response = ModelResponse()
263
303
  # Get response message
264
- response_message: OllamaMessage = response.get("message")
304
+ response_message: OllamaMessage = response.get("message") # type: ignore
265
305
 
266
306
  if response_message.get("role") is not None:
267
307
  model_response.role = response_message.get("role")
@@ -272,7 +312,7 @@ class Ollama(Model):
272
312
  if response_message.get("tool_calls") is not None:
273
313
  if model_response.tool_calls is None:
274
314
  model_response.tool_calls = []
275
- for block in response_message.get("tool_calls"):
315
+ for block in response_message.get("tool_calls", []):
276
316
  tool_call = block.get("function")
277
317
  tool_name = tool_call.get("name")
278
318
  tool_args = tool_call.get("arguments")
@@ -288,33 +328,23 @@ class Ollama(Model):
288
328
 
289
329
  # Get response usage
290
330
  if response.get("done"):
291
- model_response.response_usage = {
292
- "input_tokens": response.get("prompt_eval_count", 0),
293
- "output_tokens": response.get("eval_count", 0),
294
- "total_tokens": response.get("prompt_eval_count", 0) + response.get("eval_count", 0),
295
- "additional_metrics": {
296
- "total_duration": response.get("total_duration", 0),
297
- "load_duration": response.get("load_duration", 0),
298
- "prompt_eval_duration": response.get("prompt_eval_duration", 0),
299
- "eval_duration": response.get("eval_duration", 0),
300
- },
301
- }
331
+ model_response.response_usage = self._get_metrics(response)
302
332
 
303
333
  return model_response
304
334
 
305
- def parse_provider_response_delta(self, response_delta: ChatResponse) -> ModelResponse:
335
+ def _parse_provider_response_delta(self, response: ChatResponse) -> ModelResponse:
306
336
  """
307
337
  Parse the provider response delta.
308
338
 
309
339
  Args:
310
- response_delta (ChatResponse): The response from the provider.
340
+ response (ChatResponse): The response from the provider.
311
341
 
312
342
  Returns:
313
343
  Iterator[ModelResponse]: An iterator of the model response.
314
344
  """
315
345
  model_response = ModelResponse()
316
346
 
317
- response_message = response_delta.get("message")
347
+ response_message = response.get("message")
318
348
 
319
349
  if response_message is not None:
320
350
  content_delta = response_message.get("content")
@@ -333,17 +363,25 @@ class Ollama(Model):
333
363
  }
334
364
  model_response.tool_calls.append({"type": "function", "function": function_def})
335
365
 
336
- if response_delta.get("done"):
337
- model_response.response_usage = {
338
- "input_tokens": response_delta.get("prompt_eval_count", 0),
339
- "output_tokens": response_delta.get("eval_count", 0),
340
- "total_tokens": response_delta.get("prompt_eval_count", 0) + response_delta.get("eval_count", 0),
341
- "additional_metrics": {
342
- "total_duration": response_delta.get("total_duration", 0),
343
- "load_duration": response_delta.get("load_duration", 0),
344
- "prompt_eval_duration": response_delta.get("prompt_eval_duration", 0),
345
- "eval_duration": response_delta.get("eval_duration", 0),
346
- },
347
- }
366
+ if response.get("done"):
367
+ model_response.response_usage = self._get_metrics(response)
348
368
 
349
369
  return model_response
370
+
371
+ def _get_metrics(self, response: Union[dict, ChatResponse]) -> Metrics:
372
+ """
373
+ Parse the given Ollama usage into an Agno Metrics object.
374
+
375
+ Args:
376
+ response: The response from the provider.
377
+
378
+ Returns:
379
+ Metrics: Parsed metrics data
380
+ """
381
+ metrics = Metrics()
382
+
383
+ metrics.input_tokens = response.get("prompt_eval_count", 0)
384
+ metrics.output_tokens = response.get("eval_count", 0)
385
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
386
+
387
+ return metrics