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.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +51 -0
- agno/agent/agent.py +10405 -0
- agno/api/__init__.py +0 -0
- agno/api/agent.py +28 -0
- agno/api/api.py +40 -0
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +13 -0
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +16 -0
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/response.py +6 -0
- agno/api/schemas/team.py +16 -0
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +30 -0
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +598 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2042 -0
- agno/db/dynamo/schemas.py +314 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1795 -0
- agno/db/firestore/schemas.py +140 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1335 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1160 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1328 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/__init__.py +0 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2026 -0
- agno/db/mongo/mongo.py +1982 -0
- agno/db/mongo/schemas.py +87 -0
- agno/db/mongo/utils.py +259 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +2308 -0
- agno/db/mysql/schemas.py +138 -0
- agno/db/mysql/utils.py +355 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +1927 -0
- agno/db/postgres/postgres.py +2260 -0
- agno/db/postgres/schemas.py +139 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1660 -0
- agno/db/redis/schemas.py +123 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/schemas/metrics.py +0 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +130 -0
- agno/db/singlestore/singlestore.py +2272 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2293 -0
- agno/db/sqlite/schemas.py +133 -0
- agno/db/sqlite/sqlite.py +2288 -0
- agno/db/sqlite/utils.py +431 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1353 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +116 -0
- agno/debug.py +18 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +834 -0
- agno/eval/performance.py +773 -0
- agno/eval/reliability.py +306 -0
- agno/eval/utils.py +119 -0
- agno/exceptions.py +161 -0
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/integrations/__init__.py +0 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -0
- agno/knowledge/chunking/__init__.py +0 -0
- agno/knowledge/chunking/agentic.py +79 -0
- agno/knowledge/chunking/document.py +91 -0
- agno/knowledge/chunking/fixed.py +57 -0
- agno/knowledge/chunking/markdown.py +151 -0
- agno/knowledge/chunking/recursive.py +63 -0
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +86 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/knowledge/document/base.py +58 -0
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/knowledge/embedder/base.py +23 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/knowledge/embedder/fireworks.py +13 -0
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/knowledge/embedder/together.py +13 -0
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +1988 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +166 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +87 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +115 -0
- agno/knowledge/reader/web_search_reader.py +372 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/__init__.py +0 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/reranker/base.py +14 -0
- agno/knowledge/reranker/cohere.py +64 -0
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +189 -0
- agno/media.py +462 -0
- agno/memory/__init__.py +3 -0
- agno/memory/manager.py +1327 -0
- agno/models/__init__.py +0 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +45 -0
- agno/models/anthropic/__init__.py +5 -0
- agno/models/anthropic/claude.py +757 -0
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +701 -0
- agno/models/aws/claude.py +378 -0
- agno/models/azure/__init__.py +18 -0
- agno/models/azure/ai_foundry.py +485 -0
- agno/models/azure/openai_chat.py +131 -0
- agno/models/base.py +2175 -0
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +501 -0
- agno/models/cerebras/cerebras_openai.py +112 -0
- agno/models/cohere/__init__.py +5 -0
- agno/models/cohere/chat.py +389 -0
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +91 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +28 -0
- agno/models/deepseek/__init__.py +5 -0
- agno/models/deepseek/deepseek.py +61 -0
- agno/models/defaults.py +1 -0
- agno/models/fireworks/__init__.py +5 -0
- agno/models/fireworks/fireworks.py +26 -0
- agno/models/google/__init__.py +5 -0
- agno/models/google/gemini.py +1085 -0
- agno/models/groq/__init__.py +5 -0
- agno/models/groq/groq.py +556 -0
- agno/models/huggingface/__init__.py +5 -0
- agno/models/huggingface/huggingface.py +491 -0
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +422 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +26 -0
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +48 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +468 -0
- agno/models/litellm/litellm_openai.py +25 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +434 -0
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +475 -0
- agno/models/meta/llama_openai.py +78 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +5 -0
- agno/models/mistral/mistral.py +432 -0
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +54 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +5 -0
- agno/models/nvidia/nvidia.py +28 -0
- agno/models/ollama/__init__.py +5 -0
- agno/models/ollama/chat.py +441 -0
- agno/models/openai/__init__.py +9 -0
- agno/models/openai/chat.py +883 -0
- agno/models/openai/like.py +27 -0
- agno/models/openai/responses.py +1050 -0
- agno/models/openrouter/__init__.py +5 -0
- agno/models/openrouter/openrouter.py +66 -0
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +187 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +81 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +199 -0
- agno/models/sambanova/__init__.py +5 -0
- agno/models/sambanova/sambanova.py +28 -0
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/__init__.py +5 -0
- agno/models/together/together.py +25 -0
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +26 -0
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +70 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +78 -0
- agno/models/xai/__init__.py +3 -0
- agno/models/xai/xai.py +113 -0
- agno/os/__init__.py +3 -0
- agno/os/app.py +876 -0
- agno/os/auth.py +57 -0
- agno/os/config.py +104 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +144 -0
- agno/os/interfaces/agui/utils.py +534 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +211 -0
- agno/os/interfaces/whatsapp/security.py +53 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +292 -0
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +1763 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +430 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +162 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +997 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +515 -0
- agno/os/routers/memory/schemas.py +62 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/schema.py +1055 -0
- agno/os/settings.py +43 -0
- agno/os/utils.py +630 -0
- agno/py.typed +0 -0
- agno/reasoning/__init__.py +0 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +63 -0
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +31 -0
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +787 -0
- agno/run/base.py +229 -0
- agno/run/cancel.py +81 -0
- agno/run/messages.py +32 -0
- agno/run/team.py +753 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +295 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +392 -0
- agno/session/workflow.py +205 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +8793 -0
- agno/tools/__init__.py +10 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +69 -0
- agno/tools/api.py +122 -0
- agno/tools/apify.py +314 -0
- agno/tools/arxiv.py +127 -0
- agno/tools/aws_lambda.py +53 -0
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +89 -0
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +255 -0
- agno/tools/calculator.py +151 -0
- agno/tools/cartesia.py +187 -0
- agno/tools/clickup.py +244 -0
- agno/tools/confluence.py +240 -0
- agno/tools/crawl4ai.py +158 -0
- agno/tools/csv_toolkit.py +185 -0
- agno/tools/dalle.py +110 -0
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +262 -0
- agno/tools/desi_vocal.py +108 -0
- agno/tools/discord.py +161 -0
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +379 -0
- agno/tools/duckduckgo.py +91 -0
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +196 -0
- agno/tools/email.py +67 -0
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +396 -0
- agno/tools/fal.py +127 -0
- agno/tools/file.py +240 -0
- agno/tools/file_generation.py +350 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +143 -0
- agno/tools/function.py +1187 -0
- agno/tools/giphy.py +93 -0
- agno/tools/github.py +1760 -0
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +270 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +674 -0
- agno/tools/googlesearch.py +98 -0
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +77 -0
- agno/tools/jina.py +101 -0
- agno/tools/jira.py +170 -0
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +426 -0
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +90 -0
- agno/tools/lumalab.py +183 -0
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memori.py +339 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +139 -0
- agno/tools/models/__init__.py +0 -0
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +195 -0
- agno/tools/moviepy_video.py +349 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +46 -0
- agno/tools/newspaper4k.py +93 -0
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +202 -0
- agno/tools/openbb.py +160 -0
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +102 -0
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +257 -0
- agno/tools/pubmed.py +188 -0
- agno/tools/python.py +205 -0
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +467 -0
- agno/tools/replicate.py +117 -0
- agno/tools/resend.py +62 -0
- agno/tools/scrapegraph.py +222 -0
- agno/tools/searxng.py +152 -0
- agno/tools/serpapi.py +116 -0
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +53 -0
- agno/tools/slack.py +136 -0
- agno/tools/sleep.py +20 -0
- agno/tools/spider.py +116 -0
- agno/tools/sql.py +154 -0
- agno/tools/streamlit/__init__.py +0 -0
- agno/tools/streamlit/components.py +113 -0
- agno/tools/tavily.py +254 -0
- agno/tools/telegram.py +48 -0
- agno/tools/todoist.py +218 -0
- agno/tools/tool_registry.py +1 -0
- agno/tools/toolkit.py +146 -0
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +274 -0
- agno/tools/twilio.py +186 -0
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +54 -0
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +63 -0
- agno/tools/workflow.py +278 -0
- agno/tools/x.py +335 -0
- agno/tools/yfinance.py +257 -0
- agno/tools/youtube.py +184 -0
- agno/tools/zendesk.py +82 -0
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +382 -0
- agno/utils/__init__.py +0 -0
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +49 -0
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +132 -0
- agno/utils/dttm.py +13 -0
- agno/utils/enum.py +22 -0
- agno/utils/env.py +11 -0
- agno/utils/events.py +696 -0
- agno/utils/format_str.py +16 -0
- agno/utils/functions.py +166 -0
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +74 -0
- agno/utils/json_schema.py +234 -0
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +255 -0
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +352 -0
- agno/utils/merge_dict.py +41 -0
- agno/utils/message.py +118 -0
- agno/utils/models/__init__.py +0 -0
- agno/utils/models/ai_foundry.py +43 -0
- agno/utils/models/claude.py +358 -0
- agno/utils/models/cohere.py +87 -0
- agno/utils/models/llama.py +78 -0
- agno/utils/models/mistral.py +98 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +32 -0
- agno/utils/pprint.py +178 -0
- agno/utils/print_response/__init__.py +0 -0
- agno/utils/print_response/agent.py +842 -0
- agno/utils/print_response/team.py +1724 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/response_iterator.py +17 -0
- agno/utils/safe_formatter.py +24 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +22 -0
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +231 -0
- agno/utils/team.py +139 -0
- agno/utils/timer.py +41 -0
- agno/utils/tools.py +102 -0
- agno/utils/web.py +23 -0
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +25 -0
- agno/vectordb/__init__.py +3 -0
- agno/vectordb/base.py +127 -0
- agno/vectordb/cassandra/__init__.py +5 -0
- agno/vectordb/cassandra/cassandra.py +501 -0
- agno/vectordb/cassandra/extra_param_mixin.py +11 -0
- agno/vectordb/cassandra/index.py +13 -0
- agno/vectordb/chroma/__init__.py +5 -0
- agno/vectordb/chroma/chromadb.py +929 -0
- agno/vectordb/clickhouse/__init__.py +9 -0
- agno/vectordb/clickhouse/clickhousedb.py +835 -0
- agno/vectordb/clickhouse/index.py +9 -0
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1442 -0
- agno/vectordb/distance.py +7 -0
- agno/vectordb/lancedb/__init__.py +6 -0
- agno/vectordb/lancedb/lance_db.py +995 -0
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +4 -0
- agno/vectordb/milvus/milvus.py +1182 -0
- agno/vectordb/mongodb/__init__.py +9 -0
- agno/vectordb/mongodb/mongodb.py +1417 -0
- agno/vectordb/pgvector/__init__.py +12 -0
- agno/vectordb/pgvector/index.py +23 -0
- agno/vectordb/pgvector/pgvector.py +1462 -0
- agno/vectordb/pineconedb/__init__.py +5 -0
- agno/vectordb/pineconedb/pineconedb.py +747 -0
- agno/vectordb/qdrant/__init__.py +5 -0
- agno/vectordb/qdrant/qdrant.py +1134 -0
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/search.py +7 -0
- agno/vectordb/singlestore/__init__.py +10 -0
- agno/vectordb/singlestore/index.py +41 -0
- agno/vectordb/singlestore/singlestore.py +763 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +699 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1005 -0
- agno/workflow/__init__.py +23 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +738 -0
- agno/workflow/loop.py +735 -0
- agno/workflow/parallel.py +824 -0
- agno/workflow/router.py +702 -0
- agno/workflow/step.py +1432 -0
- agno/workflow/steps.py +592 -0
- agno/workflow/types.py +520 -0
- agno/workflow/workflow.py +4321 -0
- agno-2.2.13.dist-info/METADATA +614 -0
- agno-2.2.13.dist-info/RECORD +575 -0
- agno-2.2.13.dist-info/WHEEL +5 -0
- agno-2.2.13.dist-info/licenses/LICENSE +201 -0
- agno-2.2.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from os import getenv
|
|
4
|
+
from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from agno.agent import RunOutput
|
|
9
|
+
from agno.models.base import Model
|
|
10
|
+
from agno.models.message import Message
|
|
11
|
+
from agno.models.metrics import Metrics
|
|
12
|
+
from agno.models.response import ModelResponse
|
|
13
|
+
from agno.utils.log import log_debug, log_warning
|
|
14
|
+
from agno.utils.reasoning import extract_thinking_content
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
from ollama import AsyncClient as AsyncOllamaClient
|
|
18
|
+
from ollama import Client as OllamaClient
|
|
19
|
+
from ollama._types import ChatResponse
|
|
20
|
+
from ollama._types import Message as OllamaMessage
|
|
21
|
+
except ImportError:
|
|
22
|
+
raise ImportError("`ollama` not installed. Please install using `pip install ollama`")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class Ollama(Model):
|
|
27
|
+
"""
|
|
28
|
+
A class for interacting with Ollama models.
|
|
29
|
+
|
|
30
|
+
For more information, see: https://github.com/ollama/ollama/blob/main/docs/api.md
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
id: str = "llama3.1"
|
|
34
|
+
name: str = "Ollama"
|
|
35
|
+
provider: str = "Ollama"
|
|
36
|
+
|
|
37
|
+
supports_native_structured_outputs: bool = True
|
|
38
|
+
|
|
39
|
+
# Request parameters
|
|
40
|
+
format: Optional[Any] = None
|
|
41
|
+
options: Optional[Any] = None
|
|
42
|
+
keep_alive: Optional[Union[float, str]] = None
|
|
43
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
44
|
+
|
|
45
|
+
# Client parameters
|
|
46
|
+
host: Optional[str] = None
|
|
47
|
+
timeout: Optional[Any] = None
|
|
48
|
+
api_key: Optional[str] = field(default_factory=lambda: getenv("OLLAMA_API_KEY"))
|
|
49
|
+
client_params: Optional[Dict[str, Any]] = None
|
|
50
|
+
|
|
51
|
+
# Ollama clients
|
|
52
|
+
client: Optional[OllamaClient] = None
|
|
53
|
+
async_client: Optional[AsyncOllamaClient] = None
|
|
54
|
+
|
|
55
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
56
|
+
host = self.host
|
|
57
|
+
headers = {}
|
|
58
|
+
|
|
59
|
+
if self.api_key:
|
|
60
|
+
if not host:
|
|
61
|
+
host = "https://ollama.com"
|
|
62
|
+
headers["authorization"] = f"Bearer {self.api_key}"
|
|
63
|
+
log_debug(f"Using Ollama cloud endpoint: {host}")
|
|
64
|
+
|
|
65
|
+
base_params = {
|
|
66
|
+
"host": host,
|
|
67
|
+
"timeout": self.timeout,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if headers:
|
|
71
|
+
base_params["headers"] = headers
|
|
72
|
+
|
|
73
|
+
# Create client_params dict with non-None values
|
|
74
|
+
client_params = {k: v for k, v in base_params.items() if v is not None}
|
|
75
|
+
# Add additional client params if provided
|
|
76
|
+
if self.client_params:
|
|
77
|
+
client_params.update(self.client_params)
|
|
78
|
+
return client_params
|
|
79
|
+
|
|
80
|
+
def get_client(self) -> OllamaClient:
|
|
81
|
+
"""
|
|
82
|
+
Returns an Ollama client.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
OllamaClient: An instance of the Ollama client.
|
|
86
|
+
"""
|
|
87
|
+
if self.client is not None:
|
|
88
|
+
return self.client
|
|
89
|
+
|
|
90
|
+
self.client = OllamaClient(**self._get_client_params())
|
|
91
|
+
return self.client
|
|
92
|
+
|
|
93
|
+
def get_async_client(self) -> AsyncOllamaClient:
|
|
94
|
+
"""
|
|
95
|
+
Returns an asynchronous Ollama client.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
AsyncOllamaClient: An instance of the Ollama client.
|
|
99
|
+
"""
|
|
100
|
+
if self.async_client is not None:
|
|
101
|
+
return self.async_client
|
|
102
|
+
|
|
103
|
+
self.async_client = AsyncOllamaClient(**self._get_client_params())
|
|
104
|
+
return self.async_client
|
|
105
|
+
|
|
106
|
+
def get_request_params(
|
|
107
|
+
self,
|
|
108
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
109
|
+
) -> Dict[str, Any]:
|
|
110
|
+
"""
|
|
111
|
+
Returns keyword arguments for API requests.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Dict[str, Any]: The API kwargs for the model.
|
|
115
|
+
"""
|
|
116
|
+
base_params = {"format": self.format, "options": self.options, "keep_alive": self.keep_alive}
|
|
117
|
+
# Filter out None values
|
|
118
|
+
request_params = {k: v for k, v in base_params.items() if v is not None}
|
|
119
|
+
# Add tools
|
|
120
|
+
if tools is not None and len(tools) > 0:
|
|
121
|
+
request_params["tools"] = tools
|
|
122
|
+
|
|
123
|
+
# Add additional request params if provided
|
|
124
|
+
if self.request_params:
|
|
125
|
+
request_params.update(self.request_params)
|
|
126
|
+
|
|
127
|
+
if request_params:
|
|
128
|
+
log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
|
|
129
|
+
return request_params
|
|
130
|
+
|
|
131
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
132
|
+
"""
|
|
133
|
+
Convert the model to a dictionary.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Dict[str, Any]: A dictionary representation of the model.
|
|
137
|
+
"""
|
|
138
|
+
model_dict = super().to_dict()
|
|
139
|
+
model_dict.update(
|
|
140
|
+
{
|
|
141
|
+
"format": self.format,
|
|
142
|
+
"options": self.options,
|
|
143
|
+
"keep_alive": self.keep_alive,
|
|
144
|
+
"request_params": self.request_params,
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
cleaned_dict = {k: v for k, v in model_dict.items() if v is not None}
|
|
148
|
+
return cleaned_dict
|
|
149
|
+
|
|
150
|
+
def _format_message(self, message: Message) -> Dict[str, Any]:
|
|
151
|
+
"""
|
|
152
|
+
Format a message into the format expected by Ollama.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
message (Message): The message to format.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
Dict[str, Any]: The formatted message.
|
|
159
|
+
"""
|
|
160
|
+
_message: Dict[str, Any] = {
|
|
161
|
+
"role": message.role,
|
|
162
|
+
"content": message.content,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if message.role == "assistant" and message.tool_calls is not None:
|
|
166
|
+
# Format tool calls for assistant messages
|
|
167
|
+
formatted_tool_calls = []
|
|
168
|
+
for tool_call in message.tool_calls:
|
|
169
|
+
if "function" in tool_call:
|
|
170
|
+
function_data = tool_call["function"]
|
|
171
|
+
formatted_tool_call = {
|
|
172
|
+
"id": tool_call.get("id"),
|
|
173
|
+
"type": "function",
|
|
174
|
+
"function": {
|
|
175
|
+
"name": function_data["name"],
|
|
176
|
+
"arguments": json.loads(function_data["arguments"])
|
|
177
|
+
if isinstance(function_data["arguments"], str)
|
|
178
|
+
else function_data["arguments"],
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
formatted_tool_calls.append(formatted_tool_call)
|
|
182
|
+
|
|
183
|
+
if formatted_tool_calls:
|
|
184
|
+
_message["tool_calls"] = formatted_tool_calls
|
|
185
|
+
|
|
186
|
+
if message.role == "user":
|
|
187
|
+
if message.images is not None:
|
|
188
|
+
message_images = []
|
|
189
|
+
for image in message.images:
|
|
190
|
+
if image.url is not None:
|
|
191
|
+
message_images.append(image.get_content_bytes())
|
|
192
|
+
if image.filepath is not None:
|
|
193
|
+
message_images.append(image.filepath) # type: ignore
|
|
194
|
+
if image.content is not None and isinstance(image.content, bytes):
|
|
195
|
+
message_images.append(image.content)
|
|
196
|
+
if message_images:
|
|
197
|
+
_message["images"] = message_images
|
|
198
|
+
|
|
199
|
+
if message.audio is not None and len(message.audio) > 0:
|
|
200
|
+
log_warning("Audio input is currently unsupported.")
|
|
201
|
+
|
|
202
|
+
if message.files is not None and len(message.files) > 0:
|
|
203
|
+
log_warning("File input is currently unsupported.")
|
|
204
|
+
|
|
205
|
+
if message.videos is not None and len(message.videos) > 0:
|
|
206
|
+
log_warning("Video input is currently unsupported.")
|
|
207
|
+
|
|
208
|
+
return _message
|
|
209
|
+
|
|
210
|
+
def _prepare_request_kwargs_for_invoke(
|
|
211
|
+
self,
|
|
212
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
213
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
214
|
+
) -> Dict[str, Any]:
|
|
215
|
+
request_kwargs = self.get_request_params(tools=tools)
|
|
216
|
+
if response_format is not None and isinstance(response_format, type) and issubclass(response_format, BaseModel):
|
|
217
|
+
log_debug("Using structured outputs")
|
|
218
|
+
format_schema = response_format.model_json_schema()
|
|
219
|
+
if "format" not in request_kwargs:
|
|
220
|
+
request_kwargs["format"] = format_schema
|
|
221
|
+
return request_kwargs
|
|
222
|
+
|
|
223
|
+
def invoke(
|
|
224
|
+
self,
|
|
225
|
+
messages: List[Message],
|
|
226
|
+
assistant_message: Message,
|
|
227
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
228
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
229
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
230
|
+
run_response: Optional[RunOutput] = None,
|
|
231
|
+
) -> ModelResponse:
|
|
232
|
+
"""
|
|
233
|
+
Send a chat request to the Ollama API.
|
|
234
|
+
"""
|
|
235
|
+
request_kwargs = self._prepare_request_kwargs_for_invoke(response_format=response_format, tools=tools)
|
|
236
|
+
|
|
237
|
+
if run_response and run_response.metrics:
|
|
238
|
+
run_response.metrics.set_time_to_first_token()
|
|
239
|
+
|
|
240
|
+
assistant_message.metrics.start_timer()
|
|
241
|
+
|
|
242
|
+
provider_response = self.get_client().chat(
|
|
243
|
+
model=self.id.strip(),
|
|
244
|
+
messages=[self._format_message(m) for m in messages], # type: ignore
|
|
245
|
+
**request_kwargs,
|
|
246
|
+
) # type: ignore
|
|
247
|
+
|
|
248
|
+
assistant_message.metrics.stop_timer()
|
|
249
|
+
|
|
250
|
+
model_response = self._parse_provider_response(provider_response) # type: ignore
|
|
251
|
+
return model_response
|
|
252
|
+
|
|
253
|
+
async def ainvoke(
|
|
254
|
+
self,
|
|
255
|
+
messages: List[Message],
|
|
256
|
+
assistant_message: Message,
|
|
257
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
258
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
259
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
260
|
+
run_response: Optional[RunOutput] = None,
|
|
261
|
+
) -> ModelResponse:
|
|
262
|
+
"""
|
|
263
|
+
Sends an asynchronous chat request to the Ollama API.
|
|
264
|
+
"""
|
|
265
|
+
request_kwargs = self._prepare_request_kwargs_for_invoke(response_format=response_format, tools=tools)
|
|
266
|
+
|
|
267
|
+
if run_response and run_response.metrics:
|
|
268
|
+
run_response.metrics.set_time_to_first_token()
|
|
269
|
+
|
|
270
|
+
assistant_message.metrics.start_timer()
|
|
271
|
+
|
|
272
|
+
provider_response = await self.get_async_client().chat(
|
|
273
|
+
model=self.id.strip(),
|
|
274
|
+
messages=[self._format_message(m) for m in messages], # type: ignore
|
|
275
|
+
**request_kwargs,
|
|
276
|
+
) # type: ignore
|
|
277
|
+
|
|
278
|
+
assistant_message.metrics.stop_timer()
|
|
279
|
+
|
|
280
|
+
model_response = self._parse_provider_response(provider_response) # type: ignore
|
|
281
|
+
return model_response
|
|
282
|
+
|
|
283
|
+
def invoke_stream(
|
|
284
|
+
self,
|
|
285
|
+
messages: List[Message],
|
|
286
|
+
assistant_message: Message,
|
|
287
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
288
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
289
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
290
|
+
run_response: Optional[RunOutput] = None,
|
|
291
|
+
) -> Iterator[ModelResponse]:
|
|
292
|
+
"""
|
|
293
|
+
Sends a streaming chat request to the Ollama API.
|
|
294
|
+
"""
|
|
295
|
+
if run_response and run_response.metrics:
|
|
296
|
+
run_response.metrics.set_time_to_first_token()
|
|
297
|
+
|
|
298
|
+
assistant_message.metrics.start_timer()
|
|
299
|
+
|
|
300
|
+
for chunk in self.get_client().chat(
|
|
301
|
+
model=self.id,
|
|
302
|
+
messages=[self._format_message(m) for m in messages], # type: ignore
|
|
303
|
+
stream=True,
|
|
304
|
+
**self.get_request_params(tools=tools),
|
|
305
|
+
):
|
|
306
|
+
yield self._parse_provider_response_delta(chunk)
|
|
307
|
+
|
|
308
|
+
assistant_message.metrics.stop_timer()
|
|
309
|
+
|
|
310
|
+
async def ainvoke_stream(
|
|
311
|
+
self,
|
|
312
|
+
messages: List[Message],
|
|
313
|
+
assistant_message: Message,
|
|
314
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
315
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
316
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
317
|
+
run_response: Optional[RunOutput] = None,
|
|
318
|
+
) -> AsyncIterator[ModelResponse]:
|
|
319
|
+
"""
|
|
320
|
+
Sends an asynchronous streaming chat completion request to the Ollama API.
|
|
321
|
+
"""
|
|
322
|
+
if run_response and run_response.metrics:
|
|
323
|
+
run_response.metrics.set_time_to_first_token()
|
|
324
|
+
|
|
325
|
+
assistant_message.metrics.start_timer()
|
|
326
|
+
|
|
327
|
+
async for chunk in await self.get_async_client().chat(
|
|
328
|
+
model=self.id.strip(),
|
|
329
|
+
messages=[self._format_message(m) for m in messages], # type: ignore
|
|
330
|
+
stream=True,
|
|
331
|
+
**self.get_request_params(tools=tools),
|
|
332
|
+
):
|
|
333
|
+
yield self._parse_provider_response_delta(chunk)
|
|
334
|
+
|
|
335
|
+
assistant_message.metrics.stop_timer()
|
|
336
|
+
|
|
337
|
+
def _parse_provider_response(self, response: dict) -> ModelResponse:
|
|
338
|
+
"""
|
|
339
|
+
Parse the provider response.
|
|
340
|
+
"""
|
|
341
|
+
model_response = ModelResponse()
|
|
342
|
+
# Get response message
|
|
343
|
+
response_message: OllamaMessage = response.get("message") # type: ignore
|
|
344
|
+
|
|
345
|
+
if response_message.get("role") is not None:
|
|
346
|
+
model_response.role = response_message.get("role")
|
|
347
|
+
|
|
348
|
+
if response_message.get("content") is not None:
|
|
349
|
+
model_response.content = response_message.get("content")
|
|
350
|
+
|
|
351
|
+
# Extract thinking content between <think> tags if present
|
|
352
|
+
if model_response.content and model_response.content.find("<think>") != -1:
|
|
353
|
+
reasoning_content, clean_content = extract_thinking_content(model_response.content)
|
|
354
|
+
|
|
355
|
+
if reasoning_content:
|
|
356
|
+
# Store extracted thinking content separately
|
|
357
|
+
model_response.reasoning_content = reasoning_content
|
|
358
|
+
# Update main content with clean version
|
|
359
|
+
model_response.content = clean_content
|
|
360
|
+
|
|
361
|
+
if response_message.get("tool_calls") is not None:
|
|
362
|
+
if model_response.tool_calls is None:
|
|
363
|
+
model_response.tool_calls = []
|
|
364
|
+
for block in response_message.get("tool_calls", []):
|
|
365
|
+
tool_call = block.get("function")
|
|
366
|
+
tool_name = tool_call.get("name")
|
|
367
|
+
tool_args = tool_call.get("arguments")
|
|
368
|
+
|
|
369
|
+
function_def = {
|
|
370
|
+
"name": tool_name,
|
|
371
|
+
"arguments": (json.dumps(tool_args) if tool_args is not None else None),
|
|
372
|
+
}
|
|
373
|
+
model_response.tool_calls.append({"type": "function", "function": function_def})
|
|
374
|
+
|
|
375
|
+
# if response_message.get("images") is not None:
|
|
376
|
+
# model_response.images = response_message.get("images")
|
|
377
|
+
|
|
378
|
+
# Get response usage
|
|
379
|
+
if response.get("done"):
|
|
380
|
+
model_response.response_usage = self._get_metrics(response)
|
|
381
|
+
|
|
382
|
+
return model_response
|
|
383
|
+
|
|
384
|
+
def _parse_provider_response_delta(self, response: ChatResponse) -> ModelResponse:
|
|
385
|
+
"""
|
|
386
|
+
Parse the provider response delta.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
response (ChatResponse): The response from the provider.
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
Iterator[ModelResponse]: An iterator of the model response.
|
|
393
|
+
"""
|
|
394
|
+
model_response = ModelResponse()
|
|
395
|
+
|
|
396
|
+
response_message = response.get("message")
|
|
397
|
+
|
|
398
|
+
if response_message is not None:
|
|
399
|
+
content_delta = response_message.get("content")
|
|
400
|
+
if content_delta is not None and content_delta != "":
|
|
401
|
+
model_response.content = content_delta
|
|
402
|
+
|
|
403
|
+
tool_calls = response_message.get("tool_calls")
|
|
404
|
+
if tool_calls is not None:
|
|
405
|
+
for tool_call in tool_calls:
|
|
406
|
+
tc = tool_call.get("function")
|
|
407
|
+
tool_name = tc.get("name")
|
|
408
|
+
tool_args = tc.get("arguments")
|
|
409
|
+
function_def = {
|
|
410
|
+
"name": tool_name,
|
|
411
|
+
"arguments": json.dumps(tool_args) if tool_args is not None else None,
|
|
412
|
+
}
|
|
413
|
+
model_response.tool_calls.append({"type": "function", "function": function_def})
|
|
414
|
+
|
|
415
|
+
if response.get("done"):
|
|
416
|
+
model_response.response_usage = self._get_metrics(response)
|
|
417
|
+
|
|
418
|
+
return model_response
|
|
419
|
+
|
|
420
|
+
def _get_metrics(self, response: Union[dict, ChatResponse]) -> Metrics:
|
|
421
|
+
"""
|
|
422
|
+
Parse the given Ollama usage into an Agno Metrics object.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
response: The response from the provider.
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
Metrics: Parsed metrics data
|
|
429
|
+
"""
|
|
430
|
+
metrics = Metrics()
|
|
431
|
+
|
|
432
|
+
# Safely handle None values from Ollama Cloud responses
|
|
433
|
+
input_tokens = response.get("prompt_eval_count")
|
|
434
|
+
output_tokens = response.get("eval_count")
|
|
435
|
+
|
|
436
|
+
# Default to 0 if None
|
|
437
|
+
metrics.input_tokens = input_tokens if input_tokens is not None else 0
|
|
438
|
+
metrics.output_tokens = output_tokens if output_tokens is not None else 0
|
|
439
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
440
|
+
|
|
441
|
+
return metrics
|