agno 0.1.2__py3-none-any.whl → 2.3.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- 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/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -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 +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -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 +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -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 +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- 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/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- 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/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -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 +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -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 +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- 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 +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -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 +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -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 +249 -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 +147 -0
- agno/os/interfaces/agui/utils.py +574 -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 +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -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 +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -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/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -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 +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- 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 +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- 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/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- 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 +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- 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 +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -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 +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -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/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- 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 +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -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 +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/models/mistral/mistral.py
CHANGED
|
@@ -1,25 +1,41 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Any, Dict, Iterator, List, Optional, Union
|
|
3
|
+
from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from agno.exceptions import ModelProviderError
|
|
8
|
+
from agno.models.base import Model
|
|
6
9
|
from agno.models.message import Message
|
|
7
|
-
from agno.models.
|
|
8
|
-
from agno.
|
|
9
|
-
from agno.
|
|
10
|
-
from agno.utils.
|
|
11
|
-
from agno.utils.
|
|
10
|
+
from agno.models.metrics import Metrics
|
|
11
|
+
from agno.models.response import ModelResponse
|
|
12
|
+
from agno.run.agent import RunOutput
|
|
13
|
+
from agno.utils.log import log_debug, log_error
|
|
14
|
+
from agno.utils.models.mistral import format_messages
|
|
12
15
|
|
|
13
16
|
try:
|
|
17
|
+
from mistralai import CompletionEvent
|
|
14
18
|
from mistralai import Mistral as MistralClient
|
|
15
|
-
from mistralai.
|
|
16
|
-
from mistralai.
|
|
19
|
+
from mistralai.extra import response_format_from_pydantic_model
|
|
20
|
+
from mistralai.extra.struct_chat import ParsedChatCompletionResponse
|
|
21
|
+
from mistralai.models import (
|
|
22
|
+
AssistantMessage,
|
|
23
|
+
HTTPValidationError,
|
|
24
|
+
SDKError,
|
|
25
|
+
SystemMessage,
|
|
26
|
+
ToolMessage,
|
|
27
|
+
UserMessage,
|
|
28
|
+
)
|
|
29
|
+
from mistralai.models.chatcompletionresponse import (
|
|
30
|
+
ChatCompletionResponse,
|
|
31
|
+
)
|
|
17
32
|
from mistralai.models.deltamessage import DeltaMessage
|
|
18
33
|
from mistralai.types.basemodel import Unset
|
|
19
|
-
except (ModuleNotFoundError, ImportError):
|
|
20
|
-
raise ImportError("`mistralai` not installed. Please install using `pip install mistralai`")
|
|
21
34
|
|
|
22
|
-
MistralMessage = Union[UserMessage, AssistantMessage, SystemMessage, ToolMessage]
|
|
35
|
+
MistralMessage = Union[UserMessage, AssistantMessage, SystemMessage, ToolMessage]
|
|
36
|
+
|
|
37
|
+
except ImportError:
|
|
38
|
+
raise ImportError("`mistralai` not installed. Please install using `pip install mistralai`")
|
|
23
39
|
|
|
24
40
|
|
|
25
41
|
@dataclass
|
|
@@ -27,31 +43,15 @@ class MistralChat(Model):
|
|
|
27
43
|
"""
|
|
28
44
|
MistralChat is a model that uses the Mistral API to generate responses to messages.
|
|
29
45
|
|
|
30
|
-
|
|
31
|
-
id (str): The ID of the model.
|
|
32
|
-
name (str): The name of the model.
|
|
33
|
-
provider (str): The provider of the model.
|
|
34
|
-
temperature (Optional[float]): The temperature of the model.
|
|
35
|
-
max_tokens (Optional[int]): The maximum number of tokens to generate.
|
|
36
|
-
top_p (Optional[float]): The top p of the model.
|
|
37
|
-
random_seed (Optional[int]): The random seed of the model.
|
|
38
|
-
safe_mode (bool): The safe mode of the model.
|
|
39
|
-
safe_prompt (bool): The safe prompt of the model.
|
|
40
|
-
response_format (Optional[Union[Dict[str, Any], ChatCompletionResponse]]): The response format of the model.
|
|
41
|
-
request_params (Optional[Dict[str, Any]]): The request parameters of the model.
|
|
42
|
-
api_key (Optional[str]): The API key of the model.
|
|
43
|
-
endpoint (Optional[str]): The endpoint of the model.
|
|
44
|
-
max_retries (Optional[int]): The maximum number of retries of the model.
|
|
45
|
-
timeout (Optional[int]): The timeout of the model.
|
|
46
|
-
client_params (Optional[Dict[str, Any]]): The client parameters of the model.
|
|
47
|
-
mistral_client (Optional[Mistral]): The Mistral client of the model.
|
|
48
|
-
|
|
46
|
+
For more information, see the Mistral API documentation: https://docs.mistral.ai/capabilities/completion/
|
|
49
47
|
"""
|
|
50
48
|
|
|
51
49
|
id: str = "mistral-large-latest"
|
|
52
50
|
name: str = "MistralChat"
|
|
53
51
|
provider: str = "Mistral"
|
|
54
52
|
|
|
53
|
+
supports_native_structured_outputs: bool = True
|
|
54
|
+
|
|
55
55
|
# -*- Request parameters
|
|
56
56
|
temperature: Optional[float] = None
|
|
57
57
|
max_tokens: Optional[int] = None
|
|
@@ -59,7 +59,6 @@ class MistralChat(Model):
|
|
|
59
59
|
random_seed: Optional[int] = None
|
|
60
60
|
safe_mode: bool = False
|
|
61
61
|
safe_prompt: bool = False
|
|
62
|
-
response_format: Optional[Union[Dict[str, Any], ChatCompletionResponse]] = None
|
|
63
62
|
request_params: Optional[Dict[str, Any]] = None
|
|
64
63
|
# -*- Client parameters
|
|
65
64
|
api_key: Optional[str] = None
|
|
@@ -70,36 +69,51 @@ class MistralChat(Model):
|
|
|
70
69
|
# -*- Provide the Mistral Client manually
|
|
71
70
|
mistral_client: Optional[MistralClient] = None
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
def client(self) -> MistralClient:
|
|
72
|
+
def get_client(self) -> MistralClient:
|
|
75
73
|
"""
|
|
76
74
|
Get the Mistral client.
|
|
77
75
|
|
|
78
76
|
Returns:
|
|
79
|
-
|
|
77
|
+
MistralClient: The Mistral client instance.
|
|
80
78
|
"""
|
|
81
79
|
if self.mistral_client:
|
|
82
80
|
return self.mistral_client
|
|
83
81
|
|
|
82
|
+
_client_params = self._get_client_params()
|
|
83
|
+
self.mistral_client = MistralClient(**_client_params)
|
|
84
|
+
return self.mistral_client
|
|
85
|
+
|
|
86
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
87
|
+
"""
|
|
88
|
+
Get the client parameters for initializing Mistral clients.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Dict[str, Any]: The client parameters.
|
|
92
|
+
"""
|
|
93
|
+
client_params: Dict[str, Any] = {}
|
|
94
|
+
|
|
84
95
|
self.api_key = self.api_key or getenv("MISTRAL_API_KEY")
|
|
85
96
|
if not self.api_key:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if self.client_params:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
log_error("MISTRAL_API_KEY not set. Please set the MISTRAL_API_KEY environment variable.")
|
|
98
|
+
|
|
99
|
+
client_params.update(
|
|
100
|
+
{
|
|
101
|
+
"api_key": self.api_key,
|
|
102
|
+
"endpoint": self.endpoint,
|
|
103
|
+
"max_retries": self.max_retries,
|
|
104
|
+
"timeout": self.timeout,
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if self.client_params is not None:
|
|
109
|
+
client_params.update(self.client_params)
|
|
110
|
+
|
|
111
|
+
# Remove None values
|
|
112
|
+
return {k: v for k, v in client_params.items() if v is not None}
|
|
113
|
+
|
|
114
|
+
def get_request_params(
|
|
115
|
+
self, tools: Optional[List[Dict[str, Any]]] = None, tool_choice: Optional[Union[str, Dict[str, Any]]] = None
|
|
116
|
+
) -> Dict[str, Any]:
|
|
103
117
|
"""
|
|
104
118
|
Get the API kwargs for the Mistral model.
|
|
105
119
|
|
|
@@ -119,14 +133,17 @@ class MistralChat(Model):
|
|
|
119
133
|
_request_params["safe_mode"] = self.safe_mode
|
|
120
134
|
if self.safe_prompt:
|
|
121
135
|
_request_params["safe_prompt"] = self.safe_prompt
|
|
122
|
-
if
|
|
123
|
-
_request_params["tools"] =
|
|
124
|
-
if
|
|
136
|
+
if tools:
|
|
137
|
+
_request_params["tools"] = tools
|
|
138
|
+
if tool_choice is None:
|
|
125
139
|
_request_params["tool_choice"] = "auto"
|
|
126
140
|
else:
|
|
127
|
-
_request_params["tool_choice"] =
|
|
141
|
+
_request_params["tool_choice"] = tool_choice
|
|
128
142
|
if self.request_params:
|
|
129
143
|
_request_params.update(self.request_params)
|
|
144
|
+
|
|
145
|
+
if _request_params:
|
|
146
|
+
log_debug(f"Calling {self.provider} with request parameters: {_request_params}", log_level=2)
|
|
130
147
|
return _request_params
|
|
131
148
|
|
|
132
149
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -144,393 +161,276 @@ class MistralChat(Model):
|
|
|
144
161
|
"random_seed": self.random_seed,
|
|
145
162
|
"safe_mode": self.safe_mode,
|
|
146
163
|
"safe_prompt": self.safe_prompt,
|
|
147
|
-
"response_format": self.response_format,
|
|
148
164
|
}
|
|
149
165
|
)
|
|
150
166
|
cleaned_dict = {k: v for k, v in _dict.items() if v is not None}
|
|
151
167
|
return cleaned_dict
|
|
152
168
|
|
|
153
|
-
def
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
mistral_message = AssistantMessage(role=m.role, content=m.content)
|
|
164
|
-
elif m.role == "system":
|
|
165
|
-
mistral_message = SystemMessage(role=m.role, content=m.content)
|
|
166
|
-
elif m.role == "tool":
|
|
167
|
-
mistral_message = ToolMessage(name=m.name, content=m.content, tool_call_id=m.tool_call_id)
|
|
168
|
-
else:
|
|
169
|
-
raise ValueError(f"Unknown role: {m.role}")
|
|
170
|
-
mistral_messages.append(mistral_message)
|
|
171
|
-
return mistral_messages
|
|
172
|
-
|
|
173
|
-
def invoke(self, messages: List[Message]) -> ChatCompletionResponse:
|
|
169
|
+
def invoke(
|
|
170
|
+
self,
|
|
171
|
+
messages: List[Message],
|
|
172
|
+
assistant_message: Message,
|
|
173
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
174
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
175
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
176
|
+
run_response: Optional[RunOutput] = None,
|
|
177
|
+
compress_tool_results: bool = False,
|
|
178
|
+
) -> ModelResponse:
|
|
174
179
|
"""
|
|
175
180
|
Send a chat completion request to the Mistral model.
|
|
181
|
+
"""
|
|
182
|
+
mistral_messages = format_messages(messages, compress_tool_results)
|
|
183
|
+
try:
|
|
184
|
+
response: Union[ChatCompletionResponse, ParsedChatCompletionResponse]
|
|
185
|
+
if (
|
|
186
|
+
response_format is not None
|
|
187
|
+
and isinstance(response_format, type)
|
|
188
|
+
and issubclass(response_format, BaseModel)
|
|
189
|
+
):
|
|
190
|
+
if run_response and run_response.metrics:
|
|
191
|
+
run_response.metrics.set_time_to_first_token()
|
|
176
192
|
|
|
177
|
-
|
|
178
|
-
messages (List[Message]): The messages to send to the model.
|
|
193
|
+
assistant_message.metrics.start_timer()
|
|
179
194
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
)
|
|
190
|
-
if response is None:
|
|
191
|
-
raise ValueError("Chat completion returned None")
|
|
192
|
-
return response
|
|
195
|
+
response = self.get_client().chat.complete(
|
|
196
|
+
model=self.id,
|
|
197
|
+
messages=mistral_messages,
|
|
198
|
+
response_format=response_format_from_pydantic_model(response_format),
|
|
199
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
if run_response and run_response.metrics:
|
|
203
|
+
run_response.metrics.set_time_to_first_token()
|
|
193
204
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
assistant_message.metrics.start_timer()
|
|
206
|
+
response = self.get_client().chat.complete(
|
|
207
|
+
model=self.id,
|
|
208
|
+
messages=mistral_messages,
|
|
209
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
210
|
+
)
|
|
197
211
|
|
|
198
|
-
|
|
199
|
-
messages (List[Message]): The messages to send to the model.
|
|
212
|
+
assistant_message.metrics.stop_timer()
|
|
200
213
|
|
|
201
|
-
|
|
202
|
-
|
|
214
|
+
model_response = self._parse_provider_response(response, response_format=response_format)
|
|
215
|
+
|
|
216
|
+
return model_response
|
|
217
|
+
|
|
218
|
+
except HTTPValidationError as e:
|
|
219
|
+
log_error(f"HTTPValidationError from Mistral: {e}")
|
|
220
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
221
|
+
except SDKError as e:
|
|
222
|
+
log_error(f"SDKError from Mistral: {e}")
|
|
223
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
224
|
+
|
|
225
|
+
def invoke_stream(
|
|
226
|
+
self,
|
|
227
|
+
messages: List[Message],
|
|
228
|
+
assistant_message: Message,
|
|
229
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
230
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
231
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
232
|
+
run_response: Optional[RunOutput] = None,
|
|
233
|
+
compress_tool_results: bool = False,
|
|
234
|
+
) -> Iterator[ModelResponse]:
|
|
203
235
|
"""
|
|
204
|
-
|
|
205
|
-
logger.debug(f"Mistral messages sending to stream endpoint: {mistral_messages}")
|
|
206
|
-
response = self.client.chat.stream(
|
|
207
|
-
messages=mistral_messages,
|
|
208
|
-
model=self.id,
|
|
209
|
-
**self.api_kwargs,
|
|
210
|
-
)
|
|
211
|
-
if response is None:
|
|
212
|
-
raise ValueError("Chat stream returned None")
|
|
213
|
-
# Since response is a generator, use 'yield from' to yield its items
|
|
214
|
-
yield from response
|
|
215
|
-
|
|
216
|
-
def _handle_tool_calls(
|
|
217
|
-
self, assistant_message: Message, messages: List[Message], model_response: ModelResponse
|
|
218
|
-
) -> Optional[ModelResponse]:
|
|
236
|
+
Stream the response from the Mistral model.
|
|
219
237
|
"""
|
|
220
|
-
|
|
238
|
+
mistral_messages = format_messages(messages, compress_tool_results)
|
|
221
239
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
messages (List[Message]): The messages to send to the model.
|
|
225
|
-
model_response (ModelResponse): The model response.
|
|
240
|
+
if run_response and run_response.metrics:
|
|
241
|
+
run_response.metrics.set_time_to_first_token()
|
|
226
242
|
|
|
227
|
-
|
|
228
|
-
|
|
243
|
+
assistant_message.metrics.start_timer()
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
for chunk in self.get_client().chat.stream(
|
|
247
|
+
model=self.id,
|
|
248
|
+
messages=mistral_messages,
|
|
249
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
250
|
+
):
|
|
251
|
+
yield self._parse_provider_response_delta(chunk)
|
|
252
|
+
|
|
253
|
+
assistant_message.metrics.stop_timer()
|
|
254
|
+
|
|
255
|
+
except HTTPValidationError as e:
|
|
256
|
+
log_error(f"HTTPValidationError from Mistral: {e}")
|
|
257
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
258
|
+
except SDKError as e:
|
|
259
|
+
log_error(f"SDKError from Mistral: {e}")
|
|
260
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
261
|
+
|
|
262
|
+
async def ainvoke(
|
|
263
|
+
self,
|
|
264
|
+
messages: List[Message],
|
|
265
|
+
assistant_message: Message,
|
|
266
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
267
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
268
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
269
|
+
run_response: Optional[RunOutput] = None,
|
|
270
|
+
compress_tool_results: bool = False,
|
|
271
|
+
) -> ModelResponse:
|
|
229
272
|
"""
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
_tool_call_id = tool_call.get("id")
|
|
240
|
-
_function_call = get_function_call_for_tool_call(tool_call, self._functions)
|
|
241
|
-
if _function_call is None:
|
|
242
|
-
messages.append(
|
|
243
|
-
Message(role="tool", tool_call_id=_tool_call_id, content="Could not find function to call.")
|
|
244
|
-
)
|
|
245
|
-
continue
|
|
246
|
-
if _function_call.error is not None:
|
|
247
|
-
messages.append(
|
|
248
|
-
Message(
|
|
249
|
-
role="tool", tool_call_id=_tool_call_id, tool_call_error=True, content=_function_call.error
|
|
250
|
-
)
|
|
251
|
-
)
|
|
252
|
-
continue
|
|
253
|
-
function_calls_to_run.append(_function_call)
|
|
254
|
-
|
|
255
|
-
if self.show_tool_calls:
|
|
256
|
-
if len(function_calls_to_run) == 1:
|
|
257
|
-
model_response.content += f"\n - Running: {function_calls_to_run[0].get_call_str()}\n\n"
|
|
258
|
-
elif len(function_calls_to_run) > 1:
|
|
259
|
-
model_response.content += "\nRunning:"
|
|
260
|
-
for _f in function_calls_to_run:
|
|
261
|
-
model_response.content += f"\n - {_f.get_call_str()}"
|
|
262
|
-
model_response.content += "\n\n"
|
|
263
|
-
|
|
264
|
-
for function_call_response in self.run_function_calls(
|
|
265
|
-
function_calls=function_calls_to_run, function_call_results=function_call_results, tool_role=tool_role
|
|
273
|
+
Send an asynchronous chat completion request to the Mistral API.
|
|
274
|
+
"""
|
|
275
|
+
mistral_messages = format_messages(messages, compress_tool_results)
|
|
276
|
+
try:
|
|
277
|
+
response: Union[ChatCompletionResponse, ParsedChatCompletionResponse]
|
|
278
|
+
if (
|
|
279
|
+
response_format is not None
|
|
280
|
+
and isinstance(response_format, type)
|
|
281
|
+
and issubclass(response_format, BaseModel)
|
|
266
282
|
):
|
|
267
|
-
if
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
)
|
|
271
|
-
|
|
283
|
+
if run_response and run_response.metrics:
|
|
284
|
+
run_response.metrics.set_time_to_first_token()
|
|
285
|
+
assistant_message.metrics.start_timer()
|
|
286
|
+
response = await self.get_client().chat.complete_async(
|
|
287
|
+
model=self.id,
|
|
288
|
+
messages=mistral_messages,
|
|
289
|
+
response_format=response_format_from_pydantic_model(response_format),
|
|
290
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
291
|
+
)
|
|
292
|
+
else:
|
|
293
|
+
if run_response and run_response.metrics:
|
|
294
|
+
run_response.metrics.set_time_to_first_token()
|
|
295
|
+
assistant_message.metrics.start_timer()
|
|
296
|
+
response = await self.get_client().chat.complete_async(
|
|
297
|
+
model=self.id,
|
|
298
|
+
messages=mistral_messages,
|
|
299
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
300
|
+
)
|
|
272
301
|
|
|
273
|
-
|
|
274
|
-
messages.extend(function_call_results)
|
|
302
|
+
assistant_message.metrics.stop_timer()
|
|
275
303
|
|
|
276
|
-
|
|
277
|
-
return None
|
|
304
|
+
model_response = self._parse_provider_response(response, response_format=response_format)
|
|
278
305
|
|
|
279
|
-
|
|
306
|
+
return model_response
|
|
307
|
+
except HTTPValidationError as e:
|
|
308
|
+
log_error(f"HTTPValidationError from Mistral: {e}")
|
|
309
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
310
|
+
except SDKError as e:
|
|
311
|
+
log_error(f"SDKError from Mistral: {e}")
|
|
312
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
313
|
+
|
|
314
|
+
async def ainvoke_stream(
|
|
315
|
+
self,
|
|
316
|
+
messages: List[Message],
|
|
317
|
+
assistant_message: Message,
|
|
318
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
319
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
320
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
321
|
+
run_response: Optional[RunOutput] = None,
|
|
322
|
+
compress_tool_results: bool = False,
|
|
323
|
+
) -> AsyncIterator[ModelResponse]:
|
|
280
324
|
"""
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
Args:
|
|
284
|
-
response (ChatCompletionResponse): The response from the model.
|
|
285
|
-
|
|
286
|
-
Returns:
|
|
287
|
-
Message: The assistant message.
|
|
325
|
+
Stream an asynchronous response from the Mistral API.
|
|
288
326
|
"""
|
|
289
|
-
|
|
290
|
-
|
|
327
|
+
mistral_messages = format_messages(messages, compress_tool_results)
|
|
328
|
+
try:
|
|
329
|
+
if run_response and run_response.metrics:
|
|
330
|
+
run_response.metrics.set_time_to_first_token()
|
|
291
331
|
|
|
292
|
-
|
|
332
|
+
assistant_message.metrics.start_timer()
|
|
293
333
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
334
|
+
async for chunk in await self.get_client().chat.stream_async(
|
|
335
|
+
model=self.id,
|
|
336
|
+
messages=mistral_messages,
|
|
337
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
338
|
+
):
|
|
339
|
+
yield self._parse_provider_response_delta(chunk)
|
|
299
340
|
|
|
300
|
-
|
|
301
|
-
assistant_message.tool_calls = [t.model_dump() for t in response_message.tool_calls]
|
|
341
|
+
assistant_message.metrics.stop_timer()
|
|
302
342
|
|
|
303
|
-
|
|
343
|
+
except HTTPValidationError as e:
|
|
344
|
+
log_error(f"HTTPValidationError from Mistral: {e}")
|
|
345
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
346
|
+
except SDKError as e:
|
|
347
|
+
log_error(f"SDKError from Mistral: {e}")
|
|
348
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
304
349
|
|
|
305
|
-
def
|
|
306
|
-
self, assistant_message: Message, response: ChatCompletionResponse, response_timer: Timer
|
|
307
|
-
) -> None:
|
|
350
|
+
def _parse_provider_response(self, response: ChatCompletionResponse, **kwargs) -> ModelResponse:
|
|
308
351
|
"""
|
|
309
|
-
|
|
352
|
+
Parse the response from the Mistral model.
|
|
310
353
|
|
|
311
354
|
Args:
|
|
312
|
-
assistant_message (Message): The assistant message.
|
|
313
355
|
response (ChatCompletionResponse): The response from the model.
|
|
314
|
-
response_timer (Timer): The timer for the response.
|
|
315
356
|
"""
|
|
316
|
-
# -*- Update usage metrics
|
|
317
|
-
# Add response time to metrics
|
|
318
|
-
assistant_message.metrics["time"] = response_timer.elapsed
|
|
319
|
-
if "response_times" not in self.metrics:
|
|
320
|
-
self.metrics["response_times"] = []
|
|
321
|
-
self.metrics["response_times"].append(response_timer.elapsed)
|
|
322
|
-
# Add token usage to metrics
|
|
323
|
-
self.metrics.update(response.usage.model_dump())
|
|
324
|
-
|
|
325
|
-
def response(self, messages: List[Message]) -> ModelResponse:
|
|
326
|
-
"""
|
|
327
|
-
Send a chat completion request to the Mistral model.
|
|
328
|
-
|
|
329
|
-
Args:
|
|
330
|
-
messages (List[Message]): The messages to send to the model.
|
|
331
|
-
|
|
332
|
-
Returns:
|
|
333
|
-
ModelResponse: The response from the model.
|
|
334
|
-
"""
|
|
335
|
-
logger.debug("---------- Mistral Response Start ----------")
|
|
336
|
-
# -*- Log messages for debugging
|
|
337
|
-
self._log_messages(messages)
|
|
338
357
|
model_response = ModelResponse()
|
|
358
|
+
if response.choices is not None and len(response.choices) > 0:
|
|
359
|
+
response_message: AssistantMessage = response.choices[0].message
|
|
339
360
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
response: ChatCompletionResponse = self.invoke(messages=messages)
|
|
343
|
-
response_timer.stop()
|
|
344
|
-
logger.debug(f"Time to generate response: {response_timer.elapsed:.4f}s")
|
|
345
|
-
|
|
346
|
-
# -*- Ensure response.choices is not None
|
|
347
|
-
if response.choices is None or len(response.choices) == 0:
|
|
348
|
-
raise ValueError("Chat completion response has no choices")
|
|
349
|
-
|
|
350
|
-
# -*- Create assistant message
|
|
351
|
-
assistant_message = self._create_assistant_message(response)
|
|
352
|
-
|
|
353
|
-
# -*- Update usage metrics
|
|
354
|
-
self._update_usage_metrics(assistant_message, response, response_timer)
|
|
355
|
-
|
|
356
|
-
# -*- Add assistant message to messages
|
|
357
|
-
messages.append(assistant_message)
|
|
358
|
-
assistant_message.log()
|
|
361
|
+
# -*- Set content
|
|
362
|
+
model_response.content = response_message.content # type: ignore
|
|
359
363
|
|
|
360
|
-
|
|
361
|
-
|
|
364
|
+
# -*- Set role
|
|
365
|
+
model_response.role = response_message.role
|
|
362
366
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
367
|
+
# -*- Set tool calls
|
|
368
|
+
if isinstance(response_message.tool_calls, list) and len(response_message.tool_calls) > 0:
|
|
369
|
+
model_response.tool_calls = []
|
|
370
|
+
for tool_call in response_message.tool_calls:
|
|
371
|
+
model_response.tool_calls.append(
|
|
372
|
+
{
|
|
373
|
+
"id": tool_call.id,
|
|
374
|
+
"type": "function",
|
|
375
|
+
"function": tool_call.function.model_dump(),
|
|
376
|
+
}
|
|
377
|
+
)
|
|
371
378
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
model_response.content = assistant_message.get_content_string()
|
|
379
|
+
if response.usage is not None:
|
|
380
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
375
381
|
|
|
376
|
-
logger.debug("---------- Mistral Response End ----------")
|
|
377
382
|
return model_response
|
|
378
383
|
|
|
379
|
-
def
|
|
384
|
+
def _parse_provider_response_delta(self, response_delta: CompletionEvent) -> ModelResponse:
|
|
380
385
|
"""
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
Args:
|
|
384
|
-
stream_data (StreamData): The streaming data
|
|
385
|
-
assistant_message (Message): The assistant message.
|
|
386
|
+
Parse the response delta from the Mistral model.
|
|
386
387
|
"""
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
388
|
+
model_response = ModelResponse()
|
|
389
|
+
|
|
390
|
+
delta_message: DeltaMessage = response_delta.data.choices[0].delta
|
|
391
|
+
if delta_message.role is not None and not isinstance(delta_message.role, Unset):
|
|
392
|
+
model_response.role = delta_message.role # type: ignore
|
|
393
|
+
|
|
394
|
+
if (
|
|
395
|
+
delta_message.content is not None
|
|
396
|
+
and not isinstance(delta_message.content, Unset)
|
|
397
|
+
and isinstance(delta_message.content, str)
|
|
398
|
+
):
|
|
399
|
+
model_response.content = delta_message.content
|
|
400
|
+
|
|
401
|
+
if delta_message.tool_calls is not None:
|
|
402
|
+
model_response.tool_calls = []
|
|
403
|
+
for tool_call in delta_message.tool_calls:
|
|
404
|
+
model_response.tool_calls.append(
|
|
405
|
+
{
|
|
406
|
+
"id": tool_call.id, # type: ignore
|
|
407
|
+
"type": "function",
|
|
408
|
+
"function": {
|
|
409
|
+
"name": tool_call.function.name, # type: ignore
|
|
410
|
+
"arguments": tool_call.function.arguments, # type: ignore
|
|
411
|
+
},
|
|
412
|
+
}
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
if response_delta.data.usage is not None:
|
|
416
|
+
model_response.response_usage = self._get_metrics(response_delta.data.usage)
|
|
410
417
|
|
|
411
|
-
|
|
412
|
-
self.metrics["total_tokens"] = self.metrics.get("total_tokens", 0) + stream_data.response_total_tokens
|
|
418
|
+
return model_response
|
|
413
419
|
|
|
414
|
-
def
|
|
420
|
+
def _get_metrics(self, response_usage: Any) -> Metrics:
|
|
415
421
|
"""
|
|
416
|
-
|
|
422
|
+
Parse the given Mistral usage into an Agno Metrics object.
|
|
417
423
|
|
|
418
424
|
Args:
|
|
419
|
-
|
|
425
|
+
response_usage: Usage data from Mistral
|
|
420
426
|
|
|
421
427
|
Returns:
|
|
422
|
-
|
|
428
|
+
Metrics: Parsed metrics data
|
|
423
429
|
"""
|
|
424
|
-
|
|
425
|
-
# -*- Log messages for debugging
|
|
426
|
-
self._log_messages(messages)
|
|
427
|
-
|
|
428
|
-
stream_data: StreamData = StreamData()
|
|
429
|
-
stream_data.response_timer.start()
|
|
430
|
-
|
|
431
|
-
assistant_message_role = None
|
|
432
|
-
for response in self.invoke_stream(messages=messages):
|
|
433
|
-
# -*- Parse response
|
|
434
|
-
response_delta: DeltaMessage = response.data.choices[0].delta
|
|
435
|
-
if assistant_message_role is None and response_delta.role is not None:
|
|
436
|
-
assistant_message_role = response_delta.role
|
|
437
|
-
|
|
438
|
-
response_content: Optional[str] = None
|
|
439
|
-
if (
|
|
440
|
-
response_delta.content is not None
|
|
441
|
-
and not isinstance(response_delta.content, Unset)
|
|
442
|
-
and isinstance(response_delta.content, str)
|
|
443
|
-
):
|
|
444
|
-
response_content = response_delta.content
|
|
445
|
-
response_tool_calls = response_delta.tool_calls
|
|
446
|
-
|
|
447
|
-
# -*- Return content if present, otherwise get tool call
|
|
448
|
-
if response_content is not None:
|
|
449
|
-
stream_data.response_content += response_content
|
|
450
|
-
stream_data.completion_tokens += 1
|
|
451
|
-
if stream_data.completion_tokens == 1:
|
|
452
|
-
stream_data.time_to_first_token = stream_data.response_timer.elapsed
|
|
453
|
-
logger.debug(f"Time to first token: {stream_data.time_to_first_token:.4f}s")
|
|
454
|
-
yield ModelResponse(content=response_content)
|
|
455
|
-
|
|
456
|
-
# -*- Parse tool calls
|
|
457
|
-
if response_tool_calls is not None:
|
|
458
|
-
if stream_data.response_tool_calls is None:
|
|
459
|
-
stream_data.response_tool_calls = []
|
|
460
|
-
stream_data.response_tool_calls.extend(response_tool_calls)
|
|
461
|
-
|
|
462
|
-
stream_data.response_timer.stop()
|
|
463
|
-
completion_tokens = stream_data.completion_tokens
|
|
464
|
-
if completion_tokens > 0:
|
|
465
|
-
logger.debug(f"Time per output token: {stream_data.response_timer.elapsed / completion_tokens:.4f}s")
|
|
466
|
-
logger.debug(f"Throughput: {completion_tokens / stream_data.response_timer.elapsed:.4f} tokens/s")
|
|
467
|
-
|
|
468
|
-
# -*- Create assistant message
|
|
469
|
-
assistant_message = Message(role=(assistant_message_role or "assistant"))
|
|
470
|
-
if stream_data.response_content != "":
|
|
471
|
-
assistant_message.content = stream_data.response_content
|
|
472
|
-
|
|
473
|
-
# -*- Add tool calls to assistant message
|
|
474
|
-
if stream_data.response_tool_calls is not None:
|
|
475
|
-
assistant_message.tool_calls = [t.model_dump() for t in stream_data.response_tool_calls]
|
|
476
|
-
|
|
477
|
-
# -*- Update usage metrics
|
|
478
|
-
self._update_stream_metrics(stream_data, assistant_message)
|
|
479
|
-
messages.append(assistant_message)
|
|
480
|
-
assistant_message.log()
|
|
481
|
-
|
|
482
|
-
# -*- Parse and run tool calls
|
|
483
|
-
if assistant_message.tool_calls is not None and len(assistant_message.tool_calls) > 0:
|
|
484
|
-
tool_role: str = "tool"
|
|
485
|
-
function_calls_to_run: List[FunctionCall] = []
|
|
486
|
-
function_call_results: List[Message] = []
|
|
487
|
-
|
|
488
|
-
for tool_call in assistant_message.tool_calls:
|
|
489
|
-
_tool_call_id = tool_call.get("id")
|
|
490
|
-
tool_call["type"] = "function"
|
|
491
|
-
_function_call = get_function_call_for_tool_call(tool_call, self._functions)
|
|
492
|
-
if _function_call is None:
|
|
493
|
-
messages.append(
|
|
494
|
-
Message(role="tool", tool_call_id=_tool_call_id, content="Could not find function to call.")
|
|
495
|
-
)
|
|
496
|
-
continue
|
|
497
|
-
if _function_call.error is not None:
|
|
498
|
-
messages.append(
|
|
499
|
-
Message(
|
|
500
|
-
role="tool", tool_call_id=_tool_call_id, tool_call_error=True, content=_function_call.error
|
|
501
|
-
)
|
|
502
|
-
)
|
|
503
|
-
continue
|
|
504
|
-
function_calls_to_run.append(_function_call)
|
|
505
|
-
|
|
506
|
-
if self.show_tool_calls:
|
|
507
|
-
if len(function_calls_to_run) == 1:
|
|
508
|
-
yield ModelResponse(content=f"\n - Running: {function_calls_to_run[0].get_call_str()}\n\n")
|
|
509
|
-
elif len(function_calls_to_run) > 1:
|
|
510
|
-
yield ModelResponse(content="\nRunning:")
|
|
511
|
-
for _f in function_calls_to_run:
|
|
512
|
-
yield ModelResponse(content=f"\n - {_f.get_call_str()}")
|
|
513
|
-
yield ModelResponse(content="\n\n")
|
|
514
|
-
|
|
515
|
-
for intermediate_model_response in self.run_function_calls(
|
|
516
|
-
function_calls=function_calls_to_run, function_call_results=function_call_results, tool_role=tool_role
|
|
517
|
-
):
|
|
518
|
-
yield intermediate_model_response
|
|
519
|
-
|
|
520
|
-
if len(function_call_results) > 0:
|
|
521
|
-
messages.extend(function_call_results)
|
|
522
|
-
|
|
523
|
-
yield from self.response_stream(messages=messages)
|
|
524
|
-
logger.debug("---------- Mistral Response End ----------")
|
|
525
|
-
|
|
526
|
-
async def ainvoke(self, *args, **kwargs) -> Any:
|
|
527
|
-
raise NotImplementedError(f"Async not supported on {self.name}.")
|
|
528
|
-
|
|
529
|
-
async def ainvoke_stream(self, *args, **kwargs) -> Any:
|
|
530
|
-
raise NotImplementedError(f"Async not supported on {self.name}.")
|
|
430
|
+
metrics = Metrics()
|
|
531
431
|
|
|
532
|
-
|
|
533
|
-
|
|
432
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
433
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
434
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
534
435
|
|
|
535
|
-
|
|
536
|
-
raise NotImplementedError(f"Async not supported on {self.name}.")
|
|
436
|
+
return metrics
|