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
agno/models/groq/groq.py
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from os import getenv
|
|
4
|
+
from typing import Any, Dict, Iterator, List, Optional, Type, Union
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from agno.exceptions import ModelProviderError
|
|
10
|
+
from agno.models.base import Model
|
|
11
|
+
from agno.models.message import Message
|
|
12
|
+
from agno.models.metrics import Metrics
|
|
13
|
+
from agno.models.response import ModelResponse
|
|
14
|
+
from agno.run.agent import RunOutput
|
|
15
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
16
|
+
from agno.utils.openai import images_to_message
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from groq import APIError, APIResponseValidationError, APIStatusError
|
|
20
|
+
from groq import AsyncGroq as AsyncGroqClient
|
|
21
|
+
from groq import Groq as GroqClient
|
|
22
|
+
from groq.types.chat import ChatCompletion
|
|
23
|
+
from groq.types.chat.chat_completion_chunk import ChatCompletionChunk, ChoiceDelta, ChoiceDeltaToolCall
|
|
24
|
+
from groq.types.completion_usage import CompletionUsage
|
|
25
|
+
except ImportError:
|
|
26
|
+
raise ImportError("`groq` not installed. Please install using `pip install groq`")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class Groq(Model):
|
|
31
|
+
"""
|
|
32
|
+
A class for interacting with Groq models.
|
|
33
|
+
|
|
34
|
+
For more information, see: https://console.groq.com/docs/libraries
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
id: str = "llama-3.3-70b-versatile"
|
|
38
|
+
name: str = "Groq"
|
|
39
|
+
provider: str = "Groq"
|
|
40
|
+
|
|
41
|
+
# Request parameters
|
|
42
|
+
frequency_penalty: Optional[float] = None
|
|
43
|
+
logit_bias: Optional[Any] = None
|
|
44
|
+
logprobs: Optional[bool] = None
|
|
45
|
+
max_tokens: Optional[int] = None
|
|
46
|
+
presence_penalty: Optional[float] = None
|
|
47
|
+
seed: Optional[int] = None
|
|
48
|
+
stop: Optional[Union[str, List[str]]] = None
|
|
49
|
+
temperature: Optional[float] = None
|
|
50
|
+
top_logprobs: Optional[int] = None
|
|
51
|
+
top_p: Optional[float] = None
|
|
52
|
+
user: Optional[str] = None
|
|
53
|
+
extra_headers: Optional[Any] = None
|
|
54
|
+
extra_query: Optional[Any] = None
|
|
55
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
56
|
+
|
|
57
|
+
# Client parameters
|
|
58
|
+
api_key: Optional[str] = None
|
|
59
|
+
base_url: Optional[Union[str, httpx.URL]] = None
|
|
60
|
+
timeout: Optional[int] = None
|
|
61
|
+
max_retries: Optional[int] = None
|
|
62
|
+
default_headers: Optional[Any] = None
|
|
63
|
+
default_query: Optional[Any] = None
|
|
64
|
+
http_client: Optional[Union[httpx.Client, httpx.AsyncClient]] = None
|
|
65
|
+
client_params: Optional[Dict[str, Any]] = None
|
|
66
|
+
|
|
67
|
+
# Groq clients
|
|
68
|
+
client: Optional[GroqClient] = None
|
|
69
|
+
async_client: Optional[AsyncGroqClient] = None
|
|
70
|
+
|
|
71
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
72
|
+
# Fetch API key from env if not already set
|
|
73
|
+
if not self.api_key:
|
|
74
|
+
self.api_key = getenv("GROQ_API_KEY")
|
|
75
|
+
if not self.api_key:
|
|
76
|
+
log_error("GROQ_API_KEY not set. Please set the GROQ_API_KEY environment variable.")
|
|
77
|
+
|
|
78
|
+
# Define base client params
|
|
79
|
+
base_params = {
|
|
80
|
+
"api_key": self.api_key,
|
|
81
|
+
"base_url": self.base_url,
|
|
82
|
+
"timeout": self.timeout,
|
|
83
|
+
"max_retries": self.max_retries,
|
|
84
|
+
"default_headers": self.default_headers,
|
|
85
|
+
"default_query": self.default_query,
|
|
86
|
+
}
|
|
87
|
+
# Create client_params dict with non-None values
|
|
88
|
+
client_params = {k: v for k, v in base_params.items() if v is not None}
|
|
89
|
+
# Add additional client params if provided
|
|
90
|
+
if self.client_params:
|
|
91
|
+
client_params.update(self.client_params)
|
|
92
|
+
return client_params
|
|
93
|
+
|
|
94
|
+
def get_client(self) -> GroqClient:
|
|
95
|
+
"""
|
|
96
|
+
Returns a Groq client.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
GroqClient: An instance of the Groq client.
|
|
100
|
+
"""
|
|
101
|
+
if self.client and not self.client.is_closed():
|
|
102
|
+
return self.client
|
|
103
|
+
|
|
104
|
+
client_params: Dict[str, Any] = self._get_client_params()
|
|
105
|
+
if self.http_client is not None:
|
|
106
|
+
client_params["http_client"] = self.http_client
|
|
107
|
+
|
|
108
|
+
self.client = GroqClient(**client_params)
|
|
109
|
+
return self.client
|
|
110
|
+
|
|
111
|
+
def get_async_client(self) -> AsyncGroqClient:
|
|
112
|
+
"""
|
|
113
|
+
Returns an asynchronous Groq client.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
AsyncGroqClient: An instance of the asynchronous Groq client.
|
|
117
|
+
"""
|
|
118
|
+
if self.async_client and not self.async_client.is_closed():
|
|
119
|
+
return self.async_client
|
|
120
|
+
|
|
121
|
+
client_params: Dict[str, Any] = self._get_client_params()
|
|
122
|
+
if self.http_client and isinstance(self.http_client, httpx.AsyncClient):
|
|
123
|
+
client_params["http_client"] = self.http_client
|
|
124
|
+
else:
|
|
125
|
+
if self.http_client:
|
|
126
|
+
log_debug("The current http_client is not async. A default httpx.AsyncClient will be used instead.")
|
|
127
|
+
# Create a new async HTTP client with custom limits
|
|
128
|
+
client_params["http_client"] = httpx.AsyncClient(
|
|
129
|
+
limits=httpx.Limits(max_connections=1000, max_keepalive_connections=100)
|
|
130
|
+
)
|
|
131
|
+
self.async_client = AsyncGroqClient(**client_params)
|
|
132
|
+
return self.async_client
|
|
133
|
+
|
|
134
|
+
def get_request_params(
|
|
135
|
+
self,
|
|
136
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
137
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
138
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
139
|
+
) -> Dict[str, Any]:
|
|
140
|
+
"""
|
|
141
|
+
Returns keyword arguments for API requests.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Dict[str, Any]: A dictionary of keyword arguments for API requests.
|
|
145
|
+
"""
|
|
146
|
+
# Define base request parameters
|
|
147
|
+
base_params = {
|
|
148
|
+
"frequency_penalty": self.frequency_penalty,
|
|
149
|
+
"logit_bias": self.logit_bias,
|
|
150
|
+
"logprobs": self.logprobs,
|
|
151
|
+
"max_tokens": self.max_tokens,
|
|
152
|
+
"presence_penalty": self.presence_penalty,
|
|
153
|
+
"response_format": response_format,
|
|
154
|
+
"seed": self.seed,
|
|
155
|
+
"stop": self.stop,
|
|
156
|
+
"temperature": self.temperature,
|
|
157
|
+
"top_logprobs": self.top_logprobs,
|
|
158
|
+
"top_p": self.top_p,
|
|
159
|
+
"user": self.user,
|
|
160
|
+
"extra_headers": self.extra_headers,
|
|
161
|
+
"extra_query": self.extra_query,
|
|
162
|
+
}
|
|
163
|
+
# Filter out None values
|
|
164
|
+
request_params = {k: v for k, v in base_params.items() if v is not None}
|
|
165
|
+
# Add tools
|
|
166
|
+
if tools is not None:
|
|
167
|
+
request_params["tools"] = tools
|
|
168
|
+
if tool_choice is not None:
|
|
169
|
+
request_params["tool_choice"] = tool_choice
|
|
170
|
+
# Add additional request params if provided
|
|
171
|
+
if self.request_params:
|
|
172
|
+
request_params.update(self.request_params)
|
|
173
|
+
|
|
174
|
+
if request_params:
|
|
175
|
+
log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
|
|
176
|
+
return request_params
|
|
177
|
+
|
|
178
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
179
|
+
"""
|
|
180
|
+
Convert the model to a dictionary.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dict[str, Any]: The dictionary representation of the model.
|
|
184
|
+
"""
|
|
185
|
+
model_dict = super().to_dict()
|
|
186
|
+
model_dict.update(
|
|
187
|
+
{
|
|
188
|
+
"frequency_penalty": self.frequency_penalty,
|
|
189
|
+
"logit_bias": self.logit_bias,
|
|
190
|
+
"logprobs": self.logprobs,
|
|
191
|
+
"max_tokens": self.max_tokens,
|
|
192
|
+
"presence_penalty": self.presence_penalty,
|
|
193
|
+
"seed": self.seed,
|
|
194
|
+
"stop": self.stop,
|
|
195
|
+
"temperature": self.temperature,
|
|
196
|
+
"top_logprobs": self.top_logprobs,
|
|
197
|
+
"top_p": self.top_p,
|
|
198
|
+
"user": self.user,
|
|
199
|
+
"extra_headers": self.extra_headers,
|
|
200
|
+
"extra_query": self.extra_query,
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
cleaned_dict = {k: v for k, v in model_dict.items() if v is not None}
|
|
204
|
+
return cleaned_dict
|
|
205
|
+
|
|
206
|
+
def format_message(
|
|
207
|
+
self,
|
|
208
|
+
message: Message,
|
|
209
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
210
|
+
) -> Dict[str, Any]:
|
|
211
|
+
"""
|
|
212
|
+
Format a message into the format expected by Groq.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
message (Message): The message to format.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Dict[str, Any]: The formatted message.
|
|
219
|
+
"""
|
|
220
|
+
message_dict: Dict[str, Any] = {
|
|
221
|
+
"role": message.role,
|
|
222
|
+
"content": message.content,
|
|
223
|
+
"name": message.name,
|
|
224
|
+
"tool_call_id": message.tool_call_id,
|
|
225
|
+
"tool_calls": message.tool_calls,
|
|
226
|
+
}
|
|
227
|
+
message_dict = {k: v for k, v in message_dict.items() if v is not None}
|
|
228
|
+
|
|
229
|
+
if (
|
|
230
|
+
message.role == "system"
|
|
231
|
+
and isinstance(message.content, str)
|
|
232
|
+
and response_format is not None
|
|
233
|
+
and isinstance(response_format, dict)
|
|
234
|
+
and response_format.get("type") == "json_object"
|
|
235
|
+
):
|
|
236
|
+
# This is required by Groq to ensure the model outputs in the correct format
|
|
237
|
+
message.content += "\n\nYour output should be in JSON format."
|
|
238
|
+
|
|
239
|
+
if message.images is not None and len(message.images) > 0:
|
|
240
|
+
# Ignore non-string message content
|
|
241
|
+
# because we assume that the images/audio are already added to the message
|
|
242
|
+
if isinstance(message.content, str):
|
|
243
|
+
message_dict["content"] = [{"type": "text", "text": message.content}]
|
|
244
|
+
message_dict["content"].extend(images_to_message(images=message.images))
|
|
245
|
+
|
|
246
|
+
if message.files is not None and len(message.files) > 0:
|
|
247
|
+
log_warning("File input is currently unsupported.")
|
|
248
|
+
|
|
249
|
+
if message.audio is not None and len(message.audio) > 0:
|
|
250
|
+
log_warning("Audio input is currently unsupported.")
|
|
251
|
+
|
|
252
|
+
if message.videos is not None and len(message.videos) > 0:
|
|
253
|
+
log_warning("Video input is currently unsupported.")
|
|
254
|
+
|
|
255
|
+
return message_dict
|
|
256
|
+
|
|
257
|
+
def invoke(
|
|
258
|
+
self,
|
|
259
|
+
messages: List[Message],
|
|
260
|
+
assistant_message: Message,
|
|
261
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
262
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
263
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
264
|
+
run_response: Optional[RunOutput] = None,
|
|
265
|
+
) -> ModelResponse:
|
|
266
|
+
"""
|
|
267
|
+
Send a chat completion request to the Groq API.
|
|
268
|
+
"""
|
|
269
|
+
try:
|
|
270
|
+
if run_response and run_response.metrics:
|
|
271
|
+
run_response.metrics.set_time_to_first_token()
|
|
272
|
+
|
|
273
|
+
assistant_message.metrics.start_timer()
|
|
274
|
+
provider_response = self.get_client().chat.completions.create(
|
|
275
|
+
model=self.id,
|
|
276
|
+
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
277
|
+
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
278
|
+
)
|
|
279
|
+
assistant_message.metrics.stop_timer()
|
|
280
|
+
|
|
281
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
282
|
+
|
|
283
|
+
return model_response
|
|
284
|
+
|
|
285
|
+
except (APIResponseValidationError, APIStatusError) as e:
|
|
286
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
287
|
+
raise ModelProviderError(
|
|
288
|
+
message=e.response.text, status_code=e.response.status_code, model_name=self.name, model_id=self.id
|
|
289
|
+
) from e
|
|
290
|
+
except APIError as e:
|
|
291
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
292
|
+
raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
|
|
293
|
+
except Exception as e:
|
|
294
|
+
log_error(f"Unexpected error calling Groq API: {str(e)}")
|
|
295
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
296
|
+
|
|
297
|
+
async def ainvoke(
|
|
298
|
+
self,
|
|
299
|
+
messages: List[Message],
|
|
300
|
+
assistant_message: Message,
|
|
301
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
302
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
303
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
304
|
+
run_response: Optional[RunOutput] = None,
|
|
305
|
+
) -> ModelResponse:
|
|
306
|
+
"""
|
|
307
|
+
Sends an asynchronous chat completion request to the Groq API.
|
|
308
|
+
"""
|
|
309
|
+
try:
|
|
310
|
+
if run_response and run_response.metrics:
|
|
311
|
+
run_response.metrics.set_time_to_first_token()
|
|
312
|
+
|
|
313
|
+
assistant_message.metrics.start_timer()
|
|
314
|
+
response = await self.get_async_client().chat.completions.create(
|
|
315
|
+
model=self.id,
|
|
316
|
+
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
317
|
+
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
318
|
+
)
|
|
319
|
+
assistant_message.metrics.stop_timer()
|
|
320
|
+
|
|
321
|
+
model_response = self._parse_provider_response(response, response_format=response_format)
|
|
322
|
+
|
|
323
|
+
return model_response
|
|
324
|
+
|
|
325
|
+
except (APIResponseValidationError, APIStatusError) as e:
|
|
326
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
327
|
+
raise ModelProviderError(
|
|
328
|
+
message=e.response.text, status_code=e.response.status_code, model_name=self.name, model_id=self.id
|
|
329
|
+
) from e
|
|
330
|
+
except APIError as e:
|
|
331
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
332
|
+
raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
|
|
333
|
+
except Exception as e:
|
|
334
|
+
log_error(f"Unexpected error calling Groq API: {str(e)}")
|
|
335
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
336
|
+
|
|
337
|
+
def invoke_stream(
|
|
338
|
+
self,
|
|
339
|
+
messages: List[Message],
|
|
340
|
+
assistant_message: Message,
|
|
341
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
342
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
343
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
344
|
+
run_response: Optional[RunOutput] = None,
|
|
345
|
+
) -> Iterator[ModelResponse]:
|
|
346
|
+
"""
|
|
347
|
+
Send a streaming chat completion request to the Groq API.
|
|
348
|
+
"""
|
|
349
|
+
try:
|
|
350
|
+
if run_response and run_response.metrics:
|
|
351
|
+
run_response.metrics.set_time_to_first_token()
|
|
352
|
+
|
|
353
|
+
assistant_message.metrics.start_timer()
|
|
354
|
+
|
|
355
|
+
for chunk in self.get_client().chat.completions.create(
|
|
356
|
+
model=self.id,
|
|
357
|
+
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
358
|
+
stream=True,
|
|
359
|
+
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
360
|
+
):
|
|
361
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
362
|
+
|
|
363
|
+
assistant_message.metrics.stop_timer()
|
|
364
|
+
|
|
365
|
+
except (APIResponseValidationError, APIStatusError) as e:
|
|
366
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
367
|
+
raise ModelProviderError(
|
|
368
|
+
message=e.response.text, status_code=e.response.status_code, model_name=self.name, model_id=self.id
|
|
369
|
+
) from e
|
|
370
|
+
except APIError as e:
|
|
371
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
372
|
+
raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
|
|
373
|
+
except Exception as e:
|
|
374
|
+
log_error(f"Unexpected error calling Groq API: {str(e)}")
|
|
375
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
376
|
+
|
|
377
|
+
async def ainvoke_stream(
|
|
378
|
+
self,
|
|
379
|
+
messages: List[Message],
|
|
380
|
+
assistant_message: Message,
|
|
381
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
382
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
383
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
384
|
+
run_response: Optional[RunOutput] = None,
|
|
385
|
+
) -> AsyncIterator[ModelResponse]:
|
|
386
|
+
"""
|
|
387
|
+
Sends an asynchronous streaming chat completion request to the Groq API.
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
if run_response and run_response.metrics:
|
|
392
|
+
run_response.metrics.set_time_to_first_token()
|
|
393
|
+
|
|
394
|
+
assistant_message.metrics.start_timer()
|
|
395
|
+
|
|
396
|
+
async_stream = await self.get_async_client().chat.completions.create(
|
|
397
|
+
model=self.id,
|
|
398
|
+
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
399
|
+
stream=True,
|
|
400
|
+
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
401
|
+
)
|
|
402
|
+
async for chunk in async_stream: # type: ignore
|
|
403
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
404
|
+
|
|
405
|
+
assistant_message.metrics.stop_timer()
|
|
406
|
+
|
|
407
|
+
except (APIResponseValidationError, APIStatusError) as e:
|
|
408
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
409
|
+
raise ModelProviderError(
|
|
410
|
+
message=e.response.text, status_code=e.response.status_code, model_name=self.name, model_id=self.id
|
|
411
|
+
) from e
|
|
412
|
+
except APIError as e:
|
|
413
|
+
log_error(f"Error calling Groq API: {str(e)}")
|
|
414
|
+
raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
|
|
415
|
+
except Exception as e:
|
|
416
|
+
log_error(f"Unexpected error calling Groq API: {str(e)}")
|
|
417
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
418
|
+
|
|
419
|
+
# Override base method
|
|
420
|
+
@staticmethod
|
|
421
|
+
def parse_tool_calls(tool_calls_data: List[ChoiceDeltaToolCall]) -> List[Dict[str, Any]]:
|
|
422
|
+
"""
|
|
423
|
+
Build tool calls from streamed tool call data.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
tool_calls_data (List[ChoiceDeltaToolCall]): The tool call data to build from.
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
List[Dict[str, Any]]: The built tool calls.
|
|
430
|
+
"""
|
|
431
|
+
tool_calls: List[Dict[str, Any]] = []
|
|
432
|
+
for _tool_call in tool_calls_data:
|
|
433
|
+
_index = _tool_call.index
|
|
434
|
+
_tool_call_id = _tool_call.id
|
|
435
|
+
_tool_call_type = _tool_call.type
|
|
436
|
+
_function_name = _tool_call.function.name if _tool_call.function else None
|
|
437
|
+
_function_arguments = _tool_call.function.arguments if _tool_call.function else None
|
|
438
|
+
|
|
439
|
+
if len(tool_calls) <= _index:
|
|
440
|
+
tool_calls.extend([{}] * (_index - len(tool_calls) + 1))
|
|
441
|
+
tool_call_entry = tool_calls[_index]
|
|
442
|
+
if not tool_call_entry:
|
|
443
|
+
tool_call_entry["id"] = _tool_call_id
|
|
444
|
+
tool_call_entry["type"] = _tool_call_type
|
|
445
|
+
tool_call_entry["function"] = {
|
|
446
|
+
"name": _function_name or "",
|
|
447
|
+
"arguments": _function_arguments or "",
|
|
448
|
+
}
|
|
449
|
+
else:
|
|
450
|
+
if _function_name:
|
|
451
|
+
tool_call_entry["function"]["name"] += _function_name
|
|
452
|
+
if _function_arguments:
|
|
453
|
+
tool_call_entry["function"]["arguments"] += _function_arguments
|
|
454
|
+
if _tool_call_id:
|
|
455
|
+
tool_call_entry["id"] = _tool_call_id
|
|
456
|
+
if _tool_call_type:
|
|
457
|
+
tool_call_entry["type"] = _tool_call_type
|
|
458
|
+
return tool_calls
|
|
459
|
+
|
|
460
|
+
def _parse_provider_response(self, response: ChatCompletion, **kwargs) -> ModelResponse:
|
|
461
|
+
"""
|
|
462
|
+
Parse the Groq response into a ModelResponse.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
response: Raw response from Groq
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
ModelResponse: Parsed response data
|
|
469
|
+
"""
|
|
470
|
+
model_response = ModelResponse()
|
|
471
|
+
|
|
472
|
+
# Get response message
|
|
473
|
+
response_message = response.choices[0].message
|
|
474
|
+
|
|
475
|
+
# Add role
|
|
476
|
+
if response_message.role is not None:
|
|
477
|
+
model_response.role = response_message.role
|
|
478
|
+
|
|
479
|
+
# Add content
|
|
480
|
+
if response_message.content is not None:
|
|
481
|
+
model_response.content = response_message.content
|
|
482
|
+
|
|
483
|
+
# Add tool calls
|
|
484
|
+
if response_message.tool_calls is not None and len(response_message.tool_calls) > 0:
|
|
485
|
+
try:
|
|
486
|
+
model_response.tool_calls = [t.model_dump() for t in response_message.tool_calls]
|
|
487
|
+
except Exception as e:
|
|
488
|
+
log_warning(f"Error processing tool calls: {e}")
|
|
489
|
+
|
|
490
|
+
# Add usage metrics if present
|
|
491
|
+
if response.usage is not None:
|
|
492
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
493
|
+
|
|
494
|
+
return model_response
|
|
495
|
+
|
|
496
|
+
def _parse_provider_response_delta(self, response: ChatCompletionChunk) -> ModelResponse:
|
|
497
|
+
"""
|
|
498
|
+
Parse the Groq streaming response into ModelResponse objects.
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
response: Raw response chunk from Groq
|
|
502
|
+
|
|
503
|
+
Returns:
|
|
504
|
+
ModelResponse: Iterator of parsed response data
|
|
505
|
+
"""
|
|
506
|
+
model_response = ModelResponse()
|
|
507
|
+
|
|
508
|
+
if len(response.choices) > 0:
|
|
509
|
+
choice_delta: ChoiceDelta = response.choices[0].delta
|
|
510
|
+
|
|
511
|
+
if choice_delta:
|
|
512
|
+
# Add content
|
|
513
|
+
if choice_delta.content is not None:
|
|
514
|
+
model_response.content = choice_delta.content
|
|
515
|
+
|
|
516
|
+
# Add tool calls
|
|
517
|
+
if choice_delta.tool_calls is not None:
|
|
518
|
+
model_response.tool_calls = choice_delta.tool_calls # type: ignore
|
|
519
|
+
|
|
520
|
+
# Add usage metrics if present
|
|
521
|
+
if response.x_groq is not None and response.x_groq.usage is not None:
|
|
522
|
+
model_response.response_usage = self._get_metrics(response.x_groq.usage)
|
|
523
|
+
|
|
524
|
+
return model_response
|
|
525
|
+
|
|
526
|
+
def _get_metrics(self, response_usage: CompletionUsage) -> Metrics:
|
|
527
|
+
"""
|
|
528
|
+
Parse the given Groq usage into an Agno Metrics object.
|
|
529
|
+
|
|
530
|
+
Args:
|
|
531
|
+
response_usage: Usage data from Groq
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
Metrics: Parsed metrics data
|
|
535
|
+
"""
|
|
536
|
+
metrics = Metrics()
|
|
537
|
+
|
|
538
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
539
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
540
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
541
|
+
|
|
542
|
+
# Additional time metrics offered by Groq
|
|
543
|
+
if completion_time := response_usage.completion_time:
|
|
544
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
545
|
+
metrics.provider_metrics["completion_time"] = completion_time
|
|
546
|
+
if prompt_time := response_usage.prompt_time:
|
|
547
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
548
|
+
metrics.provider_metrics["prompt_time"] = prompt_time
|
|
549
|
+
if queue_time := response_usage.queue_time:
|
|
550
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
551
|
+
metrics.provider_metrics["queue_time"] = queue_time
|
|
552
|
+
if total_time := response_usage.total_time:
|
|
553
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
554
|
+
metrics.provider_metrics["total_time"] = total_time
|
|
555
|
+
|
|
556
|
+
return metrics
|