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
|
@@ -5,12 +5,15 @@ from os import getenv
|
|
|
5
5
|
from typing import Any, Dict, Iterator, List, Optional, Type, Union
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
|
+
from huggingface_hub import ChatCompletionInputStreamOptions
|
|
8
9
|
from pydantic import BaseModel
|
|
9
10
|
|
|
10
11
|
from agno.exceptions import ModelProviderError
|
|
11
12
|
from agno.models.base import Model
|
|
12
13
|
from agno.models.message import Message
|
|
14
|
+
from agno.models.metrics import Metrics
|
|
13
15
|
from agno.models.response import ModelResponse
|
|
16
|
+
from agno.run.agent import RunOutput
|
|
14
17
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
15
18
|
|
|
16
19
|
try:
|
|
@@ -228,19 +231,29 @@ class HuggingFace(Model):
|
|
|
228
231
|
def invoke(
|
|
229
232
|
self,
|
|
230
233
|
messages: List[Message],
|
|
234
|
+
assistant_message: Message,
|
|
231
235
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
232
236
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
233
237
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
234
|
-
|
|
238
|
+
run_response: Optional[RunOutput] = None,
|
|
239
|
+
) -> ModelResponse:
|
|
235
240
|
"""
|
|
236
241
|
Send a chat completion request to the HuggingFace Hub.
|
|
237
242
|
"""
|
|
238
243
|
try:
|
|
239
|
-
|
|
244
|
+
if run_response and run_response.metrics:
|
|
245
|
+
run_response.metrics.set_time_to_first_token()
|
|
246
|
+
|
|
247
|
+
assistant_message.metrics.start_timer()
|
|
248
|
+
provider_response = self.get_client().chat.completions.create(
|
|
240
249
|
model=self.id,
|
|
241
250
|
messages=[self._format_message(m) for m in messages],
|
|
242
251
|
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
243
252
|
)
|
|
253
|
+
assistant_message.metrics.stop_timer()
|
|
254
|
+
|
|
255
|
+
return self._parse_provider_response(provider_response, response_format=response_format)
|
|
256
|
+
|
|
244
257
|
except InferenceTimeoutError as e:
|
|
245
258
|
log_error(f"Error invoking HuggingFace model: {e}")
|
|
246
259
|
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
@@ -251,20 +264,29 @@ class HuggingFace(Model):
|
|
|
251
264
|
async def ainvoke(
|
|
252
265
|
self,
|
|
253
266
|
messages: List[Message],
|
|
267
|
+
assistant_message: Message,
|
|
254
268
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
255
269
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
256
270
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
257
|
-
|
|
271
|
+
run_response: Optional[RunOutput] = None,
|
|
272
|
+
) -> ModelResponse:
|
|
258
273
|
"""
|
|
259
274
|
Sends an asynchronous chat completion request to the HuggingFace Hub Inference.
|
|
260
275
|
"""
|
|
261
276
|
try:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
277
|
+
if run_response and run_response.metrics:
|
|
278
|
+
run_response.metrics.set_time_to_first_token()
|
|
279
|
+
|
|
280
|
+
assistant_message.metrics.start_timer()
|
|
281
|
+
provider_response = await self.get_async_client().chat.completions.create(
|
|
282
|
+
model=self.id,
|
|
283
|
+
messages=[self._format_message(m) for m in messages],
|
|
284
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
285
|
+
)
|
|
286
|
+
assistant_message.metrics.stop_timer()
|
|
287
|
+
|
|
288
|
+
return self._parse_provider_response(provider_response, response_format=response_format)
|
|
289
|
+
|
|
268
290
|
except InferenceTimeoutError as e:
|
|
269
291
|
log_error(f"Error invoking HuggingFace model: {e}")
|
|
270
292
|
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
@@ -275,21 +297,34 @@ class HuggingFace(Model):
|
|
|
275
297
|
def invoke_stream(
|
|
276
298
|
self,
|
|
277
299
|
messages: List[Message],
|
|
300
|
+
assistant_message: Message,
|
|
278
301
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
279
302
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
280
303
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
281
|
-
|
|
304
|
+
run_response: Optional[RunOutput] = None,
|
|
305
|
+
) -> Iterator[ModelResponse]:
|
|
282
306
|
"""
|
|
283
307
|
Send a streaming chat completion request to the HuggingFace API.
|
|
284
308
|
"""
|
|
285
309
|
try:
|
|
286
|
-
|
|
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
|
+
|
|
315
|
+
stream = self.get_client().chat.completions.create(
|
|
287
316
|
model=self.id,
|
|
288
317
|
messages=[self._format_message(m) for m in messages],
|
|
289
318
|
stream=True,
|
|
290
|
-
stream_options=
|
|
319
|
+
stream_options=ChatCompletionInputStreamOptions(include_usage=True), # type: ignore
|
|
291
320
|
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
292
|
-
)
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
for chunk in stream:
|
|
324
|
+
yield self._parse_provider_response_delta(chunk)
|
|
325
|
+
|
|
326
|
+
assistant_message.metrics.stop_timer()
|
|
327
|
+
|
|
293
328
|
except InferenceTimeoutError as e:
|
|
294
329
|
log_error(f"Error invoking HuggingFace model: {e}")
|
|
295
330
|
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
@@ -300,24 +335,33 @@ class HuggingFace(Model):
|
|
|
300
335
|
async def ainvoke_stream(
|
|
301
336
|
self,
|
|
302
337
|
messages: List[Message],
|
|
338
|
+
assistant_message: Message,
|
|
303
339
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
304
340
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
305
341
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
342
|
+
run_response: Optional[RunOutput] = None,
|
|
306
343
|
) -> AsyncIterator[Any]:
|
|
307
344
|
"""
|
|
308
345
|
Sends an asynchronous streaming chat completion request to the HuggingFace API.
|
|
309
346
|
"""
|
|
310
347
|
try:
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
348
|
+
if run_response and run_response.metrics:
|
|
349
|
+
run_response.metrics.set_time_to_first_token()
|
|
350
|
+
|
|
351
|
+
assistant_message.metrics.start_timer()
|
|
352
|
+
provider_response = await self.get_async_client().chat.completions.create(
|
|
353
|
+
model=self.id,
|
|
354
|
+
messages=[self._format_message(m) for m in messages],
|
|
355
|
+
stream=True,
|
|
356
|
+
stream_options=ChatCompletionInputStreamOptions(include_usage=True), # type: ignore
|
|
357
|
+
**self.get_request_params(tools=tools, tool_choice=tool_choice),
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
async for chunk in provider_response:
|
|
361
|
+
yield self._parse_provider_response_delta(chunk)
|
|
362
|
+
|
|
363
|
+
assistant_message.metrics.stop_timer()
|
|
364
|
+
|
|
321
365
|
except InferenceTimeoutError as e:
|
|
322
366
|
log_error(f"Error invoking HuggingFace model: {e}")
|
|
323
367
|
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
@@ -366,7 +410,7 @@ class HuggingFace(Model):
|
|
|
366
410
|
tool_call_entry["type"] = _tool_call_type
|
|
367
411
|
return tool_calls
|
|
368
412
|
|
|
369
|
-
def
|
|
413
|
+
def _parse_provider_response(
|
|
370
414
|
self,
|
|
371
415
|
response: ChatCompletionOutput,
|
|
372
416
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
@@ -401,11 +445,11 @@ class HuggingFace(Model):
|
|
|
401
445
|
log_warning(f"Error retrieving structured outputs: {e}")
|
|
402
446
|
|
|
403
447
|
if response.usage is not None:
|
|
404
|
-
model_response.response_usage = response
|
|
448
|
+
model_response.response_usage = self._get_metrics(response)
|
|
405
449
|
|
|
406
450
|
return model_response
|
|
407
451
|
|
|
408
|
-
def
|
|
452
|
+
def _parse_provider_response_delta(self, response_delta: ChatCompletionStreamOutput) -> ModelResponse:
|
|
409
453
|
"""
|
|
410
454
|
Parse the provider response delta into a ModelResponse.
|
|
411
455
|
"""
|
|
@@ -420,6 +464,27 @@ class HuggingFace(Model):
|
|
|
420
464
|
if response_delta_message.tool_calls is not None and len(response_delta_message.tool_calls) > 0:
|
|
421
465
|
model_response.tool_calls = [response_delta_message.tool_calls] # type: ignore
|
|
422
466
|
if response_delta.usage is not None:
|
|
423
|
-
model_response.response_usage = response_delta
|
|
467
|
+
model_response.response_usage = self._get_metrics(response_delta)
|
|
424
468
|
|
|
425
469
|
return model_response
|
|
470
|
+
|
|
471
|
+
def _get_metrics(self, response: Union[ChatCompletionOutput, ChatCompletionStreamOutput]) -> Metrics:
|
|
472
|
+
"""
|
|
473
|
+
Parse the given HuggingFace-specific usage into an Agno Metrics object.
|
|
474
|
+
|
|
475
|
+
Args:
|
|
476
|
+
response: The HuggingFace response to parse.
|
|
477
|
+
|
|
478
|
+
Returns:
|
|
479
|
+
Metrics: Parsed metrics data
|
|
480
|
+
"""
|
|
481
|
+
metrics = Metrics()
|
|
482
|
+
|
|
483
|
+
if not response.usage:
|
|
484
|
+
return metrics
|
|
485
|
+
|
|
486
|
+
metrics.input_tokens = response.usage.prompt_tokens or 0
|
|
487
|
+
metrics.output_tokens = response.usage.completion_tokens or 0
|
|
488
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
489
|
+
|
|
490
|
+
return metrics
|
agno/models/ibm/watsonx.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
7
|
from agno.exceptions import ModelProviderError
|
|
8
8
|
from agno.models.base import Model
|
|
9
9
|
from agno.models.message import Message
|
|
10
|
+
from agno.models.metrics import Metrics
|
|
10
11
|
from agno.models.response import ModelResponse
|
|
12
|
+
from agno.run.agent import RunOutput
|
|
11
13
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
12
14
|
from agno.utils.models.watsonx import format_images_for_message
|
|
13
15
|
|
|
@@ -154,14 +156,19 @@ class WatsonX(Model):
|
|
|
154
156
|
def invoke(
|
|
155
157
|
self,
|
|
156
158
|
messages: List[Message],
|
|
159
|
+
assistant_message: Message,
|
|
157
160
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
158
161
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
159
162
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
160
|
-
|
|
163
|
+
run_response: Optional[RunOutput] = None,
|
|
164
|
+
) -> ModelResponse:
|
|
161
165
|
"""
|
|
162
166
|
Send a chat completion request to the WatsonX API.
|
|
163
167
|
"""
|
|
164
168
|
try:
|
|
169
|
+
if run_response and run_response.metrics:
|
|
170
|
+
run_response.metrics.set_time_to_first_token()
|
|
171
|
+
|
|
165
172
|
client = self.get_client()
|
|
166
173
|
|
|
167
174
|
formatted_messages = [self._format_message(m) for m in messages]
|
|
@@ -169,9 +176,13 @@ class WatsonX(Model):
|
|
|
169
176
|
response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
170
177
|
)
|
|
171
178
|
|
|
172
|
-
|
|
179
|
+
assistant_message.metrics.start_timer()
|
|
173
180
|
response = client.chat(messages=formatted_messages, **request_params)
|
|
174
|
-
|
|
181
|
+
assistant_message.metrics.stop_timer()
|
|
182
|
+
|
|
183
|
+
model_response = self._parse_provider_response(response, response_format=response_format)
|
|
184
|
+
|
|
185
|
+
return model_response
|
|
175
186
|
|
|
176
187
|
except Exception as e:
|
|
177
188
|
log_error(f"Error calling WatsonX API: {str(e)}")
|
|
@@ -180,14 +191,19 @@ class WatsonX(Model):
|
|
|
180
191
|
async def ainvoke(
|
|
181
192
|
self,
|
|
182
193
|
messages: List[Message],
|
|
194
|
+
assistant_message: Message,
|
|
183
195
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
184
196
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
185
197
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
198
|
+
run_response: Optional[RunOutput] = None,
|
|
186
199
|
) -> Any:
|
|
187
200
|
"""
|
|
188
201
|
Sends an asynchronous chat completion request to the WatsonX API.
|
|
189
202
|
"""
|
|
190
203
|
try:
|
|
204
|
+
if run_response and run_response.metrics:
|
|
205
|
+
run_response.metrics.set_time_to_first_token()
|
|
206
|
+
|
|
191
207
|
client = self.get_client()
|
|
192
208
|
formatted_messages = [self._format_message(m) for m in messages]
|
|
193
209
|
|
|
@@ -195,7 +211,13 @@ class WatsonX(Model):
|
|
|
195
211
|
response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
196
212
|
)
|
|
197
213
|
|
|
198
|
-
|
|
214
|
+
assistant_message.metrics.start_timer()
|
|
215
|
+
provider_response = await client.achat(messages=formatted_messages, **request_params)
|
|
216
|
+
assistant_message.metrics.stop_timer()
|
|
217
|
+
|
|
218
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
219
|
+
|
|
220
|
+
return model_response
|
|
199
221
|
|
|
200
222
|
except Exception as e:
|
|
201
223
|
log_error(f"Error calling WatsonX API: {str(e)}")
|
|
@@ -204,10 +226,12 @@ class WatsonX(Model):
|
|
|
204
226
|
def invoke_stream(
|
|
205
227
|
self,
|
|
206
228
|
messages: List[Message],
|
|
229
|
+
assistant_message: Message,
|
|
207
230
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
208
231
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
209
232
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
210
|
-
|
|
233
|
+
run_response: Optional[RunOutput] = None,
|
|
234
|
+
) -> Iterator[ModelResponse]:
|
|
211
235
|
"""
|
|
212
236
|
Send a streaming chat completion request to the WatsonX API.
|
|
213
237
|
"""
|
|
@@ -219,7 +243,15 @@ class WatsonX(Model):
|
|
|
219
243
|
response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
220
244
|
)
|
|
221
245
|
|
|
222
|
-
|
|
246
|
+
if run_response and run_response.metrics:
|
|
247
|
+
run_response.metrics.set_time_to_first_token()
|
|
248
|
+
|
|
249
|
+
assistant_message.metrics.start_timer()
|
|
250
|
+
|
|
251
|
+
for chunk in client.chat_stream(messages=formatted_messages, **request_params):
|
|
252
|
+
yield self._parse_provider_response_delta(chunk)
|
|
253
|
+
|
|
254
|
+
assistant_message.metrics.stop_timer()
|
|
223
255
|
|
|
224
256
|
except Exception as e:
|
|
225
257
|
log_error(f"Error calling WatsonX API: {str(e)}")
|
|
@@ -228,14 +260,19 @@ class WatsonX(Model):
|
|
|
228
260
|
async def ainvoke_stream(
|
|
229
261
|
self,
|
|
230
262
|
messages: List[Message],
|
|
263
|
+
assistant_message: Message,
|
|
231
264
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
232
265
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
233
266
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
234
|
-
|
|
267
|
+
run_response: Optional[RunOutput] = None,
|
|
268
|
+
) -> AsyncIterator[ModelResponse]:
|
|
235
269
|
"""
|
|
236
270
|
Sends an asynchronous streaming chat completion request to the WatsonX API.
|
|
237
271
|
"""
|
|
238
272
|
try:
|
|
273
|
+
if run_response and run_response.metrics:
|
|
274
|
+
run_response.metrics.set_time_to_first_token()
|
|
275
|
+
|
|
239
276
|
client = self.get_client()
|
|
240
277
|
formatted_messages = [self._format_message(m) for m in messages]
|
|
241
278
|
|
|
@@ -244,9 +281,13 @@ class WatsonX(Model):
|
|
|
244
281
|
response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
245
282
|
)
|
|
246
283
|
|
|
284
|
+
assistant_message.metrics.start_timer()
|
|
285
|
+
|
|
247
286
|
async_stream = await client.achat_stream(messages=formatted_messages, **request_params)
|
|
248
287
|
async for chunk in async_stream:
|
|
249
|
-
yield chunk
|
|
288
|
+
yield self._parse_provider_response_delta(chunk)
|
|
289
|
+
|
|
290
|
+
assistant_message.metrics.stop_timer()
|
|
250
291
|
|
|
251
292
|
except Exception as e:
|
|
252
293
|
log_error(f"Error in async streaming from WatsonX API: {str(e)}")
|
|
@@ -293,7 +334,7 @@ class WatsonX(Model):
|
|
|
293
334
|
tool_call_entry["type"] = _tool_call_type
|
|
294
335
|
return tool_calls
|
|
295
336
|
|
|
296
|
-
def
|
|
337
|
+
def _parse_provider_response(
|
|
297
338
|
self,
|
|
298
339
|
response: Dict[str, Any],
|
|
299
340
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
@@ -334,11 +375,11 @@ class WatsonX(Model):
|
|
|
334
375
|
log_warning(f"Error processing tool calls: {e}")
|
|
335
376
|
|
|
336
377
|
if response.get("usage") is not None:
|
|
337
|
-
model_response.response_usage = response["usage"]
|
|
378
|
+
model_response.response_usage = self._get_metrics(response["usage"])
|
|
338
379
|
|
|
339
380
|
return model_response
|
|
340
381
|
|
|
341
|
-
def
|
|
382
|
+
def _parse_provider_response_delta(self, response_delta: Dict[str, Any]) -> ModelResponse:
|
|
342
383
|
"""
|
|
343
384
|
Parse the OpenAI streaming response into a ModelResponse.
|
|
344
385
|
"""
|
|
@@ -358,6 +399,24 @@ class WatsonX(Model):
|
|
|
358
399
|
|
|
359
400
|
# Add usage metrics if present
|
|
360
401
|
if response_delta.get("usage") is not None:
|
|
361
|
-
model_response.response_usage = response_delta["usage"]
|
|
402
|
+
model_response.response_usage = self._get_metrics(response_delta["usage"])
|
|
362
403
|
|
|
363
404
|
return model_response
|
|
405
|
+
|
|
406
|
+
def _get_metrics(self, response_usage: Dict[str, Any]) -> Metrics:
|
|
407
|
+
"""
|
|
408
|
+
Parse the given WatsonX usage into an Agno Metrics object.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
response_usage: Usage data from WatsonX
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
Metrics: Parsed metrics data
|
|
415
|
+
"""
|
|
416
|
+
metrics = Metrics()
|
|
417
|
+
|
|
418
|
+
metrics.input_tokens = response_usage.get("prompt_tokens") or 0
|
|
419
|
+
metrics.output_tokens = response_usage.get("completion_tokens") or 0
|
|
420
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
421
|
+
|
|
422
|
+
return metrics
|
agno/models/litellm/chat.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from os import getenv
|
|
4
|
-
from typing import Any, AsyncIterator, Dict, Iterator, List,
|
|
4
|
+
from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel
|
|
7
7
|
|
|
8
8
|
from agno.models.base import Model
|
|
9
9
|
from agno.models.message import Message
|
|
10
|
+
from agno.models.metrics import Metrics
|
|
10
11
|
from agno.models.response import ModelResponse
|
|
12
|
+
from agno.run.agent import RunOutput
|
|
11
13
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
12
14
|
from agno.utils.openai import _format_file_for_message, audio_to_message, images_to_message
|
|
13
15
|
|
|
@@ -162,65 +164,112 @@ class LiteLLM(Model):
|
|
|
162
164
|
def invoke(
|
|
163
165
|
self,
|
|
164
166
|
messages: List[Message],
|
|
167
|
+
assistant_message: Message,
|
|
165
168
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
166
169
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
167
170
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
168
|
-
|
|
171
|
+
run_response: Optional[RunOutput] = None,
|
|
172
|
+
) -> ModelResponse:
|
|
169
173
|
"""Sends a chat completion request to the LiteLLM API."""
|
|
170
174
|
completion_kwargs = self.get_request_params(tools=tools)
|
|
171
175
|
completion_kwargs["messages"] = self._format_messages(messages)
|
|
172
|
-
|
|
176
|
+
|
|
177
|
+
if run_response and run_response.metrics:
|
|
178
|
+
run_response.metrics.set_time_to_first_token()
|
|
179
|
+
|
|
180
|
+
assistant_message.metrics.start_timer()
|
|
181
|
+
|
|
182
|
+
provider_response = self.get_client().completion(**completion_kwargs)
|
|
183
|
+
|
|
184
|
+
assistant_message.metrics.stop_timer()
|
|
185
|
+
|
|
186
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
187
|
+
return model_response
|
|
173
188
|
|
|
174
189
|
def invoke_stream(
|
|
175
190
|
self,
|
|
176
191
|
messages: List[Message],
|
|
192
|
+
assistant_message: Message,
|
|
177
193
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
178
194
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
179
195
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
180
|
-
|
|
196
|
+
run_response: Optional[RunOutput] = None,
|
|
197
|
+
) -> Iterator[ModelResponse]:
|
|
181
198
|
"""Sends a streaming chat completion request to the LiteLLM API."""
|
|
182
199
|
completion_kwargs = self.get_request_params(tools=tools)
|
|
183
200
|
completion_kwargs["messages"] = self._format_messages(messages)
|
|
184
201
|
completion_kwargs["stream"] = True
|
|
185
202
|
completion_kwargs["stream_options"] = {"include_usage": True}
|
|
186
|
-
|
|
203
|
+
|
|
204
|
+
if run_response and run_response.metrics:
|
|
205
|
+
run_response.metrics.set_time_to_first_token()
|
|
206
|
+
|
|
207
|
+
assistant_message.metrics.start_timer()
|
|
208
|
+
|
|
209
|
+
for chunk in self.get_client().completion(**completion_kwargs):
|
|
210
|
+
yield self._parse_provider_response_delta(chunk)
|
|
211
|
+
|
|
212
|
+
assistant_message.metrics.stop_timer()
|
|
187
213
|
|
|
188
214
|
async def ainvoke(
|
|
189
215
|
self,
|
|
190
216
|
messages: List[Message],
|
|
217
|
+
assistant_message: Message,
|
|
191
218
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
192
219
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
193
220
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
194
|
-
|
|
221
|
+
run_response: Optional[RunOutput] = None,
|
|
222
|
+
) -> ModelResponse:
|
|
195
223
|
"""Sends an asynchronous chat completion request to the LiteLLM API."""
|
|
196
224
|
completion_kwargs = self.get_request_params(tools=tools)
|
|
197
225
|
completion_kwargs["messages"] = self._format_messages(messages)
|
|
198
|
-
|
|
226
|
+
|
|
227
|
+
if run_response and run_response.metrics:
|
|
228
|
+
run_response.metrics.set_time_to_first_token()
|
|
229
|
+
|
|
230
|
+
assistant_message.metrics.start_timer()
|
|
231
|
+
|
|
232
|
+
provider_response = await self.get_client().acompletion(**completion_kwargs)
|
|
233
|
+
|
|
234
|
+
assistant_message.metrics.stop_timer()
|
|
235
|
+
|
|
236
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
237
|
+
return model_response
|
|
199
238
|
|
|
200
239
|
async def ainvoke_stream(
|
|
201
240
|
self,
|
|
202
241
|
messages: List[Message],
|
|
242
|
+
assistant_message: Message,
|
|
203
243
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
204
244
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
205
245
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
206
|
-
|
|
246
|
+
run_response: Optional[RunOutput] = None,
|
|
247
|
+
) -> AsyncIterator[ModelResponse]:
|
|
207
248
|
"""Sends an asynchronous streaming chat request to the LiteLLM API."""
|
|
208
249
|
completion_kwargs = self.get_request_params(tools=tools)
|
|
209
250
|
completion_kwargs["messages"] = self._format_messages(messages)
|
|
210
251
|
completion_kwargs["stream"] = True
|
|
211
252
|
completion_kwargs["stream_options"] = {"include_usage": True}
|
|
212
253
|
|
|
254
|
+
if run_response and run_response.metrics:
|
|
255
|
+
run_response.metrics.set_time_to_first_token()
|
|
256
|
+
|
|
257
|
+
assistant_message.metrics.start_timer()
|
|
258
|
+
|
|
213
259
|
try:
|
|
214
260
|
# litellm.acompletion returns a coroutine that resolves to an async iterator
|
|
215
261
|
# We need to await it first to get the actual async iterator
|
|
216
262
|
async_stream = await self.get_client().acompletion(**completion_kwargs)
|
|
217
263
|
async for chunk in async_stream:
|
|
218
|
-
yield chunk
|
|
264
|
+
yield self._parse_provider_response_delta(chunk)
|
|
265
|
+
|
|
266
|
+
assistant_message.metrics.stop_timer()
|
|
267
|
+
|
|
219
268
|
except Exception as e:
|
|
220
269
|
log_error(f"Error in streaming response: {e}")
|
|
221
270
|
raise
|
|
222
271
|
|
|
223
|
-
def
|
|
272
|
+
def _parse_provider_response(self, response: Any, **kwargs) -> ModelResponse:
|
|
224
273
|
"""Parse the provider response."""
|
|
225
274
|
model_response = ModelResponse()
|
|
226
275
|
|
|
@@ -241,11 +290,11 @@ class LiteLLM(Model):
|
|
|
241
290
|
)
|
|
242
291
|
|
|
243
292
|
if response.usage is not None:
|
|
244
|
-
model_response.response_usage = response.usage
|
|
293
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
245
294
|
|
|
246
295
|
return model_response
|
|
247
296
|
|
|
248
|
-
def
|
|
297
|
+
def _parse_provider_response_delta(self, response_delta: Any) -> ModelResponse:
|
|
249
298
|
"""Parse the provider response delta for streaming responses."""
|
|
250
299
|
model_response = ModelResponse()
|
|
251
300
|
|
|
@@ -284,7 +333,7 @@ class LiteLLM(Model):
|
|
|
284
333
|
|
|
285
334
|
# Add usage metrics if present in streaming response
|
|
286
335
|
if hasattr(response_delta, "usage") and response_delta.usage is not None:
|
|
287
|
-
model_response.response_usage = response_delta.usage
|
|
336
|
+
model_response.response_usage = self._get_metrics(response_delta.usage)
|
|
288
337
|
|
|
289
338
|
return model_response
|
|
290
339
|
|
|
@@ -377,3 +426,26 @@ class LiteLLM(Model):
|
|
|
377
426
|
result.append(tc_copy)
|
|
378
427
|
|
|
379
428
|
return result
|
|
429
|
+
|
|
430
|
+
def _get_metrics(self, response_usage: Any) -> Metrics:
|
|
431
|
+
"""
|
|
432
|
+
Parse the given LiteLLM usage into an Agno Metrics object.
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
response_usage: Usage data from LiteLLM
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
Metrics: Parsed metrics data
|
|
439
|
+
"""
|
|
440
|
+
metrics = Metrics()
|
|
441
|
+
|
|
442
|
+
if isinstance(response_usage, dict):
|
|
443
|
+
metrics.input_tokens = response_usage.get("prompt_tokens") or 0
|
|
444
|
+
metrics.output_tokens = response_usage.get("completion_tokens") or 0
|
|
445
|
+
else:
|
|
446
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
447
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
448
|
+
|
|
449
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
450
|
+
|
|
451
|
+
return metrics
|