agno 1.8.1__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +19 -27
- agno/agent/agent.py +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +11 -66
- 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/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1743 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1432 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1416 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +15 -11
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -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/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1551 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +269 -268
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +131 -131
- agno/models/aws/bedrock.py +110 -182
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +46 -151
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +497 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +77 -33
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +32 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +3260 -4824
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +19 -34
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +32 -20
- agno/tools/mcp.py +1 -2
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +55 -42
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +100 -123
- agno/utils/gemini.py +32 -2
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +47 -4
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/streamlit.py +481 -0
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +334 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -0
- agno/agent/metrics.py +0 -107
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- 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 -702
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- 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 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/response.py +0 -467
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- 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/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3312
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.1.dist-info/METADATA +0 -982
- agno-1.8.1.dist-info/RECORD +0 -566
- agno-1.8.1.dist-info/entry_points.txt +0 -3
- agno-1.8.1.dist-info/licenses/LICENSE +0 -375
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/models/google/gemini.py
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import time
|
|
3
|
+
from collections.abc import AsyncIterator
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from os import getenv
|
|
5
6
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Dict, List, Optional, Type, Union
|
|
7
|
+
from typing import Any, Dict, Iterator, List, Optional, Type, Union
|
|
7
8
|
from uuid import uuid4
|
|
8
9
|
|
|
9
10
|
from pydantic import BaseModel
|
|
10
11
|
|
|
11
12
|
from agno.exceptions import ModelProviderError
|
|
12
|
-
from agno.media import Audio, File,
|
|
13
|
+
from agno.media import Audio, File, Image, Video
|
|
13
14
|
from agno.models.base import Model
|
|
14
|
-
from agno.models.message import Citations, Message,
|
|
15
|
+
from agno.models.message import Citations, Message, UrlCitation
|
|
16
|
+
from agno.models.metrics import Metrics
|
|
15
17
|
from agno.models.response import ModelResponse
|
|
18
|
+
from agno.run.agent import RunOutput
|
|
16
19
|
from agno.utils.gemini import convert_schema, format_function_definitions, format_image_for_message
|
|
17
20
|
from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
18
21
|
from agno.utils.models.schema_utils import get_response_schema_for_provider
|
|
@@ -262,21 +265,33 @@ class Gemini(Model):
|
|
|
262
265
|
def invoke(
|
|
263
266
|
self,
|
|
264
267
|
messages: List[Message],
|
|
268
|
+
assistant_message: Message,
|
|
265
269
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
266
270
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
267
271
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
268
|
-
|
|
272
|
+
run_response: Optional[RunOutput] = None,
|
|
273
|
+
) -> ModelResponse:
|
|
269
274
|
"""
|
|
270
275
|
Invokes the model with a list of messages and returns the response.
|
|
271
276
|
"""
|
|
272
277
|
formatted_messages, system_message = self._format_messages(messages)
|
|
273
278
|
request_kwargs = self.get_request_params(system_message, response_format=response_format, tools=tools)
|
|
274
279
|
try:
|
|
275
|
-
|
|
280
|
+
if run_response and run_response.metrics:
|
|
281
|
+
run_response.metrics.set_time_to_first_token()
|
|
282
|
+
|
|
283
|
+
assistant_message.metrics.start_timer()
|
|
284
|
+
provider_response = self.get_client().models.generate_content(
|
|
276
285
|
model=self.id,
|
|
277
286
|
contents=formatted_messages,
|
|
278
287
|
**request_kwargs,
|
|
279
288
|
)
|
|
289
|
+
assistant_message.metrics.stop_timer()
|
|
290
|
+
|
|
291
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
292
|
+
|
|
293
|
+
return model_response
|
|
294
|
+
|
|
280
295
|
except (ClientError, ServerError) as e:
|
|
281
296
|
log_error(f"Error from Gemini API: {e}")
|
|
282
297
|
error_message = str(e.response) if hasattr(e, "response") else str(e)
|
|
@@ -293,10 +308,12 @@ class Gemini(Model):
|
|
|
293
308
|
def invoke_stream(
|
|
294
309
|
self,
|
|
295
310
|
messages: List[Message],
|
|
311
|
+
assistant_message: Message,
|
|
296
312
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
297
313
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
298
314
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
299
|
-
|
|
315
|
+
run_response: Optional[RunOutput] = None,
|
|
316
|
+
) -> Iterator[ModelResponse]:
|
|
300
317
|
"""
|
|
301
318
|
Invokes the model with a list of messages and returns the response as a stream.
|
|
302
319
|
"""
|
|
@@ -304,11 +321,19 @@ class Gemini(Model):
|
|
|
304
321
|
|
|
305
322
|
request_kwargs = self.get_request_params(system_message, response_format=response_format, tools=tools)
|
|
306
323
|
try:
|
|
307
|
-
|
|
324
|
+
if run_response and run_response.metrics:
|
|
325
|
+
run_response.metrics.set_time_to_first_token()
|
|
326
|
+
|
|
327
|
+
assistant_message.metrics.start_timer()
|
|
328
|
+
for response in self.get_client().models.generate_content_stream(
|
|
308
329
|
model=self.id,
|
|
309
330
|
contents=formatted_messages,
|
|
310
331
|
**request_kwargs,
|
|
311
|
-
)
|
|
332
|
+
):
|
|
333
|
+
yield self._parse_provider_response_delta(response)
|
|
334
|
+
|
|
335
|
+
assistant_message.metrics.stop_timer()
|
|
336
|
+
|
|
312
337
|
except (ClientError, ServerError) as e:
|
|
313
338
|
log_error(f"Error from Gemini API: {e}")
|
|
314
339
|
raise ModelProviderError(
|
|
@@ -324,10 +349,12 @@ class Gemini(Model):
|
|
|
324
349
|
async def ainvoke(
|
|
325
350
|
self,
|
|
326
351
|
messages: List[Message],
|
|
352
|
+
assistant_message: Message,
|
|
327
353
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
328
354
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
329
355
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
330
|
-
|
|
356
|
+
run_response: Optional[RunOutput] = None,
|
|
357
|
+
) -> ModelResponse:
|
|
331
358
|
"""
|
|
332
359
|
Invokes the model with a list of messages and returns the response.
|
|
333
360
|
"""
|
|
@@ -336,11 +363,21 @@ class Gemini(Model):
|
|
|
336
363
|
request_kwargs = self.get_request_params(system_message, response_format=response_format, tools=tools)
|
|
337
364
|
|
|
338
365
|
try:
|
|
339
|
-
|
|
366
|
+
if run_response and run_response.metrics:
|
|
367
|
+
run_response.metrics.set_time_to_first_token()
|
|
368
|
+
|
|
369
|
+
assistant_message.metrics.start_timer()
|
|
370
|
+
provider_response = await self.get_client().aio.models.generate_content(
|
|
340
371
|
model=self.id,
|
|
341
372
|
contents=formatted_messages,
|
|
342
373
|
**request_kwargs,
|
|
343
374
|
)
|
|
375
|
+
assistant_message.metrics.stop_timer()
|
|
376
|
+
|
|
377
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
378
|
+
|
|
379
|
+
return model_response
|
|
380
|
+
|
|
344
381
|
except (ClientError, ServerError) as e:
|
|
345
382
|
log_error(f"Error from Gemini API: {e}")
|
|
346
383
|
raise ModelProviderError(
|
|
@@ -356,10 +393,12 @@ class Gemini(Model):
|
|
|
356
393
|
async def ainvoke_stream(
|
|
357
394
|
self,
|
|
358
395
|
messages: List[Message],
|
|
396
|
+
assistant_message: Message,
|
|
359
397
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
360
398
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
361
399
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
362
|
-
|
|
400
|
+
run_response: Optional[RunOutput] = None,
|
|
401
|
+
) -> AsyncIterator[ModelResponse]:
|
|
363
402
|
"""
|
|
364
403
|
Invokes the model with a list of messages and returns the response as a stream.
|
|
365
404
|
"""
|
|
@@ -368,13 +407,21 @@ class Gemini(Model):
|
|
|
368
407
|
request_kwargs = self.get_request_params(system_message, response_format=response_format, tools=tools)
|
|
369
408
|
|
|
370
409
|
try:
|
|
410
|
+
if run_response and run_response.metrics:
|
|
411
|
+
run_response.metrics.set_time_to_first_token()
|
|
412
|
+
|
|
413
|
+
assistant_message.metrics.start_timer()
|
|
414
|
+
|
|
371
415
|
async_stream = await self.get_client().aio.models.generate_content_stream(
|
|
372
416
|
model=self.id,
|
|
373
417
|
contents=formatted_messages,
|
|
374
418
|
**request_kwargs,
|
|
375
419
|
)
|
|
376
420
|
async for chunk in async_stream:
|
|
377
|
-
yield chunk
|
|
421
|
+
yield self._parse_provider_response_delta(chunk)
|
|
422
|
+
|
|
423
|
+
assistant_message.metrics.stop_timer()
|
|
424
|
+
|
|
378
425
|
except (ClientError, ServerError) as e:
|
|
379
426
|
log_error(f"Error from Gemini API: {e}")
|
|
380
427
|
raise ModelProviderError(
|
|
@@ -512,9 +559,14 @@ class Gemini(Model):
|
|
|
512
559
|
return Part.from_bytes(mime_type=mime_type, data=audio.content)
|
|
513
560
|
|
|
514
561
|
# Case 2: Audio is an url
|
|
515
|
-
elif audio.url is not None
|
|
516
|
-
|
|
517
|
-
|
|
562
|
+
elif audio.url is not None:
|
|
563
|
+
audio_bytes = audio.get_content_bytes() # type: ignore
|
|
564
|
+
if audio_bytes is not None:
|
|
565
|
+
mime_type = f"audio/{audio.format}" if audio.format else "audio/mp3"
|
|
566
|
+
return Part.from_bytes(mime_type=mime_type, data=audio_bytes)
|
|
567
|
+
else:
|
|
568
|
+
log_warning(f"Failed to download audio from {audio}")
|
|
569
|
+
return None
|
|
518
570
|
|
|
519
571
|
# Case 3: Audio is a local file path
|
|
520
572
|
elif audio.filepath is not None:
|
|
@@ -696,7 +748,7 @@ class Gemini(Model):
|
|
|
696
748
|
"""
|
|
697
749
|
combined_content: List = []
|
|
698
750
|
combined_function_result: List = []
|
|
699
|
-
message_metrics =
|
|
751
|
+
message_metrics = Metrics()
|
|
700
752
|
if len(function_call_results) > 0:
|
|
701
753
|
for result in function_call_results:
|
|
702
754
|
combined_content.append(result.content)
|
|
@@ -710,7 +762,7 @@ class Gemini(Model):
|
|
|
710
762
|
)
|
|
711
763
|
)
|
|
712
764
|
|
|
713
|
-
def
|
|
765
|
+
def _parse_provider_response(self, response: GenerateContentResponse, **kwargs) -> ModelResponse:
|
|
714
766
|
"""
|
|
715
767
|
Parse the OpenAI response into a ModelResponse.
|
|
716
768
|
|
|
@@ -765,8 +817,10 @@ class Gemini(Model):
|
|
|
765
817
|
model_response.content += content_str
|
|
766
818
|
|
|
767
819
|
if hasattr(part, "inline_data") and part.inline_data is not None:
|
|
768
|
-
model_response.
|
|
769
|
-
|
|
820
|
+
if model_response.images is None:
|
|
821
|
+
model_response.images = []
|
|
822
|
+
model_response.images.append(
|
|
823
|
+
Image(id=str(uuid4()), content=part.inline_data.data, mime_type=part.inline_data.mime_type)
|
|
770
824
|
)
|
|
771
825
|
|
|
772
826
|
# Extract function call if present
|
|
@@ -836,18 +890,7 @@ class Gemini(Model):
|
|
|
836
890
|
|
|
837
891
|
# Extract usage metadata if present
|
|
838
892
|
if hasattr(response, "usage_metadata") and response.usage_metadata is not None:
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
output_tokens = usage.candidates_token_count or 0
|
|
842
|
-
if hasattr(usage, "thoughts_token_count") and usage.thoughts_token_count is not None:
|
|
843
|
-
output_tokens += usage.thoughts_token_count or 0
|
|
844
|
-
|
|
845
|
-
model_response.response_usage = {
|
|
846
|
-
"input_tokens": usage.prompt_token_count or 0,
|
|
847
|
-
"output_tokens": output_tokens,
|
|
848
|
-
"total_tokens": usage.total_token_count or 0,
|
|
849
|
-
"cached_tokens": usage.cached_content_token_count or 0,
|
|
850
|
-
}
|
|
893
|
+
model_response.response_usage = self._get_metrics(response.usage_metadata)
|
|
851
894
|
|
|
852
895
|
# If we have no content but have a role, add a default empty content
|
|
853
896
|
if model_response.role and model_response.content is None and not model_response.tool_calls:
|
|
@@ -855,7 +898,7 @@ class Gemini(Model):
|
|
|
855
898
|
|
|
856
899
|
return model_response
|
|
857
900
|
|
|
858
|
-
def
|
|
901
|
+
def _parse_provider_response_delta(self, response_delta: GenerateContentResponse) -> ModelResponse:
|
|
859
902
|
model_response = ModelResponse()
|
|
860
903
|
|
|
861
904
|
if response_delta.candidates and len(response_delta.candidates) > 0:
|
|
@@ -886,8 +929,10 @@ class Gemini(Model):
|
|
|
886
929
|
model_response.content += text_content
|
|
887
930
|
|
|
888
931
|
if hasattr(part, "inline_data") and part.inline_data is not None:
|
|
889
|
-
model_response.
|
|
890
|
-
|
|
932
|
+
if model_response.images is None:
|
|
933
|
+
model_response.images = []
|
|
934
|
+
model_response.images.append(
|
|
935
|
+
Image(id=str(uuid4()), content=part.inline_data.data, mime_type=part.inline_data.mime_type)
|
|
891
936
|
)
|
|
892
937
|
|
|
893
938
|
# Extract function call if present
|
|
@@ -932,18 +977,7 @@ class Gemini(Model):
|
|
|
932
977
|
|
|
933
978
|
# Extract usage metadata if present
|
|
934
979
|
if hasattr(response_delta, "usage_metadata") and response_delta.usage_metadata is not None:
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
output_tokens = usage.candidates_token_count or 0
|
|
938
|
-
if hasattr(usage, "thoughts_token_count") and usage.thoughts_token_count is not None:
|
|
939
|
-
output_tokens += usage.thoughts_token_count or 0
|
|
940
|
-
|
|
941
|
-
model_response.response_usage = {
|
|
942
|
-
"input_tokens": usage.prompt_token_count or 0,
|
|
943
|
-
"output_tokens": output_tokens,
|
|
944
|
-
"total_tokens": usage.total_token_count or 0,
|
|
945
|
-
"cached_tokens": usage.cached_content_token_count or 0,
|
|
946
|
-
}
|
|
980
|
+
model_response.response_usage = self._get_metrics(response_delta.usage_metadata)
|
|
947
981
|
|
|
948
982
|
return model_response
|
|
949
983
|
|
|
@@ -984,3 +1018,28 @@ class Gemini(Model):
|
|
|
984
1018
|
setattr(new_instance, "client", None)
|
|
985
1019
|
|
|
986
1020
|
return new_instance
|
|
1021
|
+
|
|
1022
|
+
def _get_metrics(self, response_usage: GenerateContentResponseUsageMetadata) -> Metrics:
|
|
1023
|
+
"""
|
|
1024
|
+
Parse the given Google Gemini usage into an Agno Metrics object.
|
|
1025
|
+
|
|
1026
|
+
Args:
|
|
1027
|
+
response_usage: Usage data from Google Gemini
|
|
1028
|
+
|
|
1029
|
+
Returns:
|
|
1030
|
+
Metrics: Parsed metrics data
|
|
1031
|
+
"""
|
|
1032
|
+
metrics = Metrics()
|
|
1033
|
+
|
|
1034
|
+
metrics.input_tokens = response_usage.prompt_token_count or 0
|
|
1035
|
+
metrics.output_tokens = response_usage.candidates_token_count or 0
|
|
1036
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
1037
|
+
if response_usage.thoughts_token_count is not None:
|
|
1038
|
+
metrics.output_tokens += response_usage.thoughts_token_count or 0
|
|
1039
|
+
|
|
1040
|
+
metrics.cache_read_tokens = response_usage.cached_content_token_count or 0
|
|
1041
|
+
|
|
1042
|
+
if response_usage.traffic_type is not None:
|
|
1043
|
+
metrics.provider_metrics = {"traffic_type": response_usage.traffic_type}
|
|
1044
|
+
|
|
1045
|
+
return metrics
|
agno/models/groq/groq.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
from os import getenv
|
|
3
4
|
from typing import Any, Dict, Iterator, List, Optional, Type, Union
|
|
@@ -8,7 +9,9 @@ from pydantic import BaseModel
|
|
|
8
9
|
from agno.exceptions import ModelProviderError
|
|
9
10
|
from agno.models.base import Model
|
|
10
11
|
from agno.models.message import Message
|
|
12
|
+
from agno.models.metrics import Metrics
|
|
11
13
|
from agno.models.response import ModelResponse
|
|
14
|
+
from agno.run.agent import RunOutput
|
|
12
15
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
13
16
|
from agno.utils.openai import images_to_message
|
|
14
17
|
|
|
@@ -18,6 +21,7 @@ try:
|
|
|
18
21
|
from groq import Groq as GroqClient
|
|
19
22
|
from groq.types.chat import ChatCompletion
|
|
20
23
|
from groq.types.chat.chat_completion_chunk import ChatCompletionChunk, ChoiceDelta, ChoiceDeltaToolCall
|
|
24
|
+
from groq.types.completion_usage import CompletionUsage
|
|
21
25
|
except ImportError:
|
|
22
26
|
raise ImportError("`groq` not installed. Please install using `pip install groq`")
|
|
23
27
|
|
|
@@ -250,19 +254,31 @@ class Groq(Model):
|
|
|
250
254
|
def invoke(
|
|
251
255
|
self,
|
|
252
256
|
messages: List[Message],
|
|
257
|
+
assistant_message: Message,
|
|
253
258
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
254
259
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
255
260
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
256
|
-
|
|
261
|
+
run_response: Optional[RunOutput] = None,
|
|
262
|
+
) -> ModelResponse:
|
|
257
263
|
"""
|
|
258
264
|
Send a chat completion request to the Groq API.
|
|
259
265
|
"""
|
|
260
266
|
try:
|
|
261
|
-
|
|
267
|
+
if run_response and run_response.metrics:
|
|
268
|
+
run_response.metrics.set_time_to_first_token()
|
|
269
|
+
|
|
270
|
+
assistant_message.metrics.start_timer()
|
|
271
|
+
provider_response = self.get_client().chat.completions.create(
|
|
262
272
|
model=self.id,
|
|
263
273
|
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
264
274
|
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
265
275
|
)
|
|
276
|
+
assistant_message.metrics.stop_timer()
|
|
277
|
+
|
|
278
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
279
|
+
|
|
280
|
+
return model_response
|
|
281
|
+
|
|
266
282
|
except (APIResponseValidationError, APIStatusError) as e:
|
|
267
283
|
log_error(f"Error calling Groq API: {str(e)}")
|
|
268
284
|
raise ModelProviderError(
|
|
@@ -278,19 +294,31 @@ class Groq(Model):
|
|
|
278
294
|
async def ainvoke(
|
|
279
295
|
self,
|
|
280
296
|
messages: List[Message],
|
|
297
|
+
assistant_message: Message,
|
|
281
298
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
282
299
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
283
300
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
284
|
-
|
|
301
|
+
run_response: Optional[RunOutput] = None,
|
|
302
|
+
) -> ModelResponse:
|
|
285
303
|
"""
|
|
286
304
|
Sends an asynchronous chat completion request to the Groq API.
|
|
287
305
|
"""
|
|
288
306
|
try:
|
|
289
|
-
|
|
307
|
+
if run_response and run_response.metrics:
|
|
308
|
+
run_response.metrics.set_time_to_first_token()
|
|
309
|
+
|
|
310
|
+
assistant_message.metrics.start_timer()
|
|
311
|
+
response = await self.get_async_client().chat.completions.create(
|
|
290
312
|
model=self.id,
|
|
291
313
|
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
292
314
|
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
293
315
|
)
|
|
316
|
+
assistant_message.metrics.stop_timer()
|
|
317
|
+
|
|
318
|
+
model_response = self._parse_provider_response(response, response_format=response_format)
|
|
319
|
+
|
|
320
|
+
return model_response
|
|
321
|
+
|
|
294
322
|
except (APIResponseValidationError, APIStatusError) as e:
|
|
295
323
|
log_error(f"Error calling Groq API: {str(e)}")
|
|
296
324
|
raise ModelProviderError(
|
|
@@ -306,20 +334,31 @@ class Groq(Model):
|
|
|
306
334
|
def invoke_stream(
|
|
307
335
|
self,
|
|
308
336
|
messages: List[Message],
|
|
337
|
+
assistant_message: Message,
|
|
309
338
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
310
339
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
311
340
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
312
|
-
|
|
341
|
+
run_response: Optional[RunOutput] = None,
|
|
342
|
+
) -> Iterator[ModelResponse]:
|
|
313
343
|
"""
|
|
314
344
|
Send a streaming chat completion request to the Groq API.
|
|
315
345
|
"""
|
|
316
346
|
try:
|
|
317
|
-
|
|
347
|
+
if run_response and run_response.metrics:
|
|
348
|
+
run_response.metrics.set_time_to_first_token()
|
|
349
|
+
|
|
350
|
+
assistant_message.metrics.start_timer()
|
|
351
|
+
|
|
352
|
+
for chunk in self.get_client().chat.completions.create(
|
|
318
353
|
model=self.id,
|
|
319
354
|
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
320
355
|
stream=True,
|
|
321
356
|
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
322
|
-
)
|
|
357
|
+
):
|
|
358
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
359
|
+
|
|
360
|
+
assistant_message.metrics.stop_timer()
|
|
361
|
+
|
|
323
362
|
except (APIResponseValidationError, APIStatusError) as e:
|
|
324
363
|
log_error(f"Error calling Groq API: {str(e)}")
|
|
325
364
|
raise ModelProviderError(
|
|
@@ -335,23 +374,33 @@ class Groq(Model):
|
|
|
335
374
|
async def ainvoke_stream(
|
|
336
375
|
self,
|
|
337
376
|
messages: List[Message],
|
|
377
|
+
assistant_message: Message,
|
|
338
378
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
339
379
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
340
380
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
341
|
-
|
|
381
|
+
run_response: Optional[RunOutput] = None,
|
|
382
|
+
) -> AsyncIterator[ModelResponse]:
|
|
342
383
|
"""
|
|
343
384
|
Sends an asynchronous streaming chat completion request to the Groq API.
|
|
344
385
|
"""
|
|
345
386
|
|
|
346
387
|
try:
|
|
347
|
-
|
|
388
|
+
if run_response and run_response.metrics:
|
|
389
|
+
run_response.metrics.set_time_to_first_token()
|
|
390
|
+
|
|
391
|
+
assistant_message.metrics.start_timer()
|
|
392
|
+
|
|
393
|
+
async_stream = await self.get_async_client().chat.completions.create(
|
|
348
394
|
model=self.id,
|
|
349
395
|
messages=[self.format_message(m) for m in messages], # type: ignore
|
|
350
396
|
stream=True,
|
|
351
397
|
**self.get_request_params(response_format=response_format, tools=tools, tool_choice=tool_choice),
|
|
352
398
|
)
|
|
353
|
-
async for chunk in
|
|
354
|
-
yield chunk
|
|
399
|
+
async for chunk in async_stream: # type: ignore
|
|
400
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
401
|
+
|
|
402
|
+
assistant_message.metrics.stop_timer()
|
|
403
|
+
|
|
355
404
|
except (APIResponseValidationError, APIStatusError) as e:
|
|
356
405
|
log_error(f"Error calling Groq API: {str(e)}")
|
|
357
406
|
raise ModelProviderError(
|
|
@@ -405,7 +454,7 @@ class Groq(Model):
|
|
|
405
454
|
tool_call_entry["type"] = _tool_call_type
|
|
406
455
|
return tool_calls
|
|
407
456
|
|
|
408
|
-
def
|
|
457
|
+
def _parse_provider_response(self, response: ChatCompletion, **kwargs) -> ModelResponse:
|
|
409
458
|
"""
|
|
410
459
|
Parse the Groq response into a ModelResponse.
|
|
411
460
|
|
|
@@ -437,20 +486,11 @@ class Groq(Model):
|
|
|
437
486
|
|
|
438
487
|
# Add usage metrics if present
|
|
439
488
|
if response.usage is not None:
|
|
440
|
-
model_response.response_usage =
|
|
441
|
-
|
|
442
|
-
"output_tokens": response.usage.completion_tokens,
|
|
443
|
-
"total_tokens": response.usage.total_tokens,
|
|
444
|
-
"additional_metrics": {
|
|
445
|
-
"completion_time": response.usage.completion_time,
|
|
446
|
-
"prompt_time": response.usage.prompt_time,
|
|
447
|
-
"queue_time": response.usage.queue_time,
|
|
448
|
-
"total_time": response.usage.total_time,
|
|
449
|
-
},
|
|
450
|
-
}
|
|
489
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
490
|
+
|
|
451
491
|
return model_response
|
|
452
492
|
|
|
453
|
-
def
|
|
493
|
+
def _parse_provider_response_delta(self, response: ChatCompletionChunk) -> ModelResponse:
|
|
454
494
|
"""
|
|
455
495
|
Parse the Groq streaming response into ModelResponse objects.
|
|
456
496
|
|
|
@@ -476,16 +516,38 @@ class Groq(Model):
|
|
|
476
516
|
|
|
477
517
|
# Add usage metrics if present
|
|
478
518
|
if response.x_groq is not None and response.x_groq.usage is not None:
|
|
479
|
-
model_response.response_usage =
|
|
480
|
-
"input_tokens": response.x_groq.usage.prompt_tokens,
|
|
481
|
-
"output_tokens": response.x_groq.usage.completion_tokens,
|
|
482
|
-
"total_tokens": response.x_groq.usage.total_tokens,
|
|
483
|
-
"additional_metrics": {
|
|
484
|
-
"completion_time": response.x_groq.usage.completion_time,
|
|
485
|
-
"prompt_time": response.x_groq.usage.prompt_time,
|
|
486
|
-
"queue_time": response.x_groq.usage.queue_time,
|
|
487
|
-
"total_time": response.x_groq.usage.total_time,
|
|
488
|
-
},
|
|
489
|
-
}
|
|
519
|
+
model_response.response_usage = self._get_metrics(response.x_groq.usage)
|
|
490
520
|
|
|
491
521
|
return model_response
|
|
522
|
+
|
|
523
|
+
def _get_metrics(self, response_usage: CompletionUsage) -> Metrics:
|
|
524
|
+
"""
|
|
525
|
+
Parse the given Groq usage into an Agno Metrics object.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
response_usage: Usage data from Groq
|
|
529
|
+
|
|
530
|
+
Returns:
|
|
531
|
+
Metrics: Parsed metrics data
|
|
532
|
+
"""
|
|
533
|
+
metrics = Metrics()
|
|
534
|
+
|
|
535
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
536
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
537
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
538
|
+
|
|
539
|
+
# Additional time metrics offered by Groq
|
|
540
|
+
if completion_time := response_usage.completion_time:
|
|
541
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
542
|
+
metrics.provider_metrics["completion_time"] = completion_time
|
|
543
|
+
if prompt_time := response_usage.prompt_time:
|
|
544
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
545
|
+
metrics.provider_metrics["prompt_time"] = prompt_time
|
|
546
|
+
if queue_time := response_usage.queue_time:
|
|
547
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
548
|
+
metrics.provider_metrics["queue_time"] = queue_time
|
|
549
|
+
if total_time := response_usage.total_time:
|
|
550
|
+
metrics.provider_metrics = metrics.provider_metrics or {}
|
|
551
|
+
metrics.provider_metrics["total_time"] = total_time
|
|
552
|
+
|
|
553
|
+
return metrics
|