agno 1.8.2__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/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 +10 -10
- 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 +128 -72
- agno/models/aws/bedrock.py +107 -175
- 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 +65 -28
- 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 +17 -18
- 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 +18 -33
- 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 +1 -1
- 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 +6 -12
- 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 -110
- 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 -1053
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -223
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1045
- 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 -3313
- 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.2.dist-info/METADATA +0 -982
- agno-1.8.2.dist-info/RECORD +0 -566
- agno-1.8.2.dist-info/entry_points.txt +0 -3
- agno-1.8.2.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.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/models/openai/responses.py
CHANGED
|
@@ -8,16 +8,20 @@ from typing_extensions import Literal
|
|
|
8
8
|
|
|
9
9
|
from agno.exceptions import ModelProviderError
|
|
10
10
|
from agno.media import File
|
|
11
|
-
from agno.models.base import MessageData, Model
|
|
11
|
+
from agno.models.base import MessageData, Model
|
|
12
12
|
from agno.models.message import Citations, Message, UrlCitation
|
|
13
|
+
from agno.models.metrics import Metrics
|
|
13
14
|
from agno.models.response import ModelResponse
|
|
15
|
+
from agno.run.agent import RunOutput
|
|
14
16
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
15
17
|
from agno.utils.models.openai_responses import images_to_message
|
|
16
18
|
from agno.utils.models.schema_utils import get_response_schema_for_provider
|
|
17
19
|
|
|
18
20
|
try:
|
|
19
21
|
from openai import APIConnectionError, APIStatusError, AsyncOpenAI, OpenAI, RateLimitError
|
|
20
|
-
from openai.
|
|
22
|
+
from openai.types.responses.response import Response
|
|
23
|
+
from openai.types.responses.response_stream_event import ResponseStreamEvent
|
|
24
|
+
from openai.types.responses.response_usage import ResponseUsage
|
|
21
25
|
except (ImportError, ModuleNotFoundError) as e:
|
|
22
26
|
raise ImportError("`openai` not installed. Please install using `pip install openai -U`") from e
|
|
23
27
|
|
|
@@ -476,10 +480,12 @@ class OpenAIResponses(Model):
|
|
|
476
480
|
def invoke(
|
|
477
481
|
self,
|
|
478
482
|
messages: List[Message],
|
|
483
|
+
assistant_message: Message,
|
|
479
484
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
480
485
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
481
486
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
482
|
-
|
|
487
|
+
run_response: Optional[RunOutput] = None,
|
|
488
|
+
) -> ModelResponse:
|
|
483
489
|
"""
|
|
484
490
|
Send a request to the OpenAI Responses API.
|
|
485
491
|
"""
|
|
@@ -487,11 +493,24 @@ class OpenAIResponses(Model):
|
|
|
487
493
|
request_params = self.get_request_params(
|
|
488
494
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
489
495
|
)
|
|
490
|
-
|
|
496
|
+
|
|
497
|
+
if run_response and run_response.metrics:
|
|
498
|
+
run_response.metrics.set_time_to_first_token()
|
|
499
|
+
|
|
500
|
+
assistant_message.metrics.start_timer()
|
|
501
|
+
|
|
502
|
+
provider_response = self.get_client().responses.create(
|
|
491
503
|
model=self.id,
|
|
492
504
|
input=self._format_messages(messages), # type: ignore
|
|
493
505
|
**request_params,
|
|
494
506
|
)
|
|
507
|
+
|
|
508
|
+
assistant_message.metrics.stop_timer()
|
|
509
|
+
|
|
510
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
511
|
+
|
|
512
|
+
return model_response
|
|
513
|
+
|
|
495
514
|
except RateLimitError as exc:
|
|
496
515
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
497
516
|
error_message = exc.response.json().get("error", {})
|
|
@@ -530,10 +549,12 @@ class OpenAIResponses(Model):
|
|
|
530
549
|
async def ainvoke(
|
|
531
550
|
self,
|
|
532
551
|
messages: List[Message],
|
|
552
|
+
assistant_message: Message,
|
|
533
553
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
534
554
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
535
555
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
536
|
-
|
|
556
|
+
run_response: Optional[RunOutput] = None,
|
|
557
|
+
) -> ModelResponse:
|
|
537
558
|
"""
|
|
538
559
|
Sends an asynchronous request to the OpenAI Responses API.
|
|
539
560
|
"""
|
|
@@ -542,11 +563,23 @@ class OpenAIResponses(Model):
|
|
|
542
563
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
543
564
|
)
|
|
544
565
|
|
|
545
|
-
|
|
566
|
+
if run_response and run_response.metrics:
|
|
567
|
+
run_response.metrics.set_time_to_first_token()
|
|
568
|
+
|
|
569
|
+
assistant_message.metrics.start_timer()
|
|
570
|
+
|
|
571
|
+
provider_response = await self.get_async_client().responses.create(
|
|
546
572
|
model=self.id,
|
|
547
573
|
input=self._format_messages(messages), # type: ignore
|
|
548
574
|
**request_params,
|
|
549
575
|
)
|
|
576
|
+
|
|
577
|
+
assistant_message.metrics.stop_timer()
|
|
578
|
+
|
|
579
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
580
|
+
|
|
581
|
+
return model_response
|
|
582
|
+
|
|
550
583
|
except RateLimitError as exc:
|
|
551
584
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
552
585
|
error_message = exc.response.json().get("error", {})
|
|
@@ -585,10 +618,12 @@ class OpenAIResponses(Model):
|
|
|
585
618
|
def invoke_stream(
|
|
586
619
|
self,
|
|
587
620
|
messages: List[Message],
|
|
621
|
+
assistant_message: Message,
|
|
588
622
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
589
623
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
590
624
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
591
|
-
|
|
625
|
+
run_response: Optional[RunOutput] = None,
|
|
626
|
+
) -> Iterator[ModelResponse]:
|
|
592
627
|
"""
|
|
593
628
|
Send a streaming request to the OpenAI Responses API.
|
|
594
629
|
"""
|
|
@@ -596,13 +631,28 @@ class OpenAIResponses(Model):
|
|
|
596
631
|
request_params = self.get_request_params(
|
|
597
632
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
598
633
|
)
|
|
634
|
+
tool_use: Dict[str, Any] = {}
|
|
635
|
+
|
|
636
|
+
if run_response and run_response.metrics:
|
|
637
|
+
run_response.metrics.set_time_to_first_token()
|
|
638
|
+
|
|
639
|
+
assistant_message.metrics.start_timer()
|
|
599
640
|
|
|
600
|
-
|
|
641
|
+
for chunk in self.get_client().responses.create(
|
|
601
642
|
model=self.id,
|
|
602
643
|
input=self._format_messages(messages), # type: ignore
|
|
603
644
|
stream=True,
|
|
604
645
|
**request_params,
|
|
605
|
-
)
|
|
646
|
+
):
|
|
647
|
+
model_response, tool_use = self._parse_provider_response_delta(
|
|
648
|
+
stream_event=chunk, # type: ignore
|
|
649
|
+
assistant_message=assistant_message,
|
|
650
|
+
tool_use=tool_use, # type: ignore
|
|
651
|
+
)
|
|
652
|
+
yield model_response
|
|
653
|
+
|
|
654
|
+
assistant_message.metrics.stop_timer()
|
|
655
|
+
|
|
606
656
|
except RateLimitError as exc:
|
|
607
657
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
608
658
|
error_message = exc.response.json().get("error", {})
|
|
@@ -641,10 +691,12 @@ class OpenAIResponses(Model):
|
|
|
641
691
|
async def ainvoke_stream(
|
|
642
692
|
self,
|
|
643
693
|
messages: List[Message],
|
|
694
|
+
assistant_message: Message,
|
|
644
695
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
645
696
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
646
697
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
647
|
-
|
|
698
|
+
run_response: Optional[RunOutput] = None,
|
|
699
|
+
) -> AsyncIterator[ModelResponse]:
|
|
648
700
|
"""
|
|
649
701
|
Sends an asynchronous streaming request to the OpenAI Responses API.
|
|
650
702
|
"""
|
|
@@ -652,6 +704,13 @@ class OpenAIResponses(Model):
|
|
|
652
704
|
request_params = self.get_request_params(
|
|
653
705
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
654
706
|
)
|
|
707
|
+
tool_use: Dict[str, Any] = {}
|
|
708
|
+
|
|
709
|
+
if run_response and run_response.metrics:
|
|
710
|
+
run_response.metrics.set_time_to_first_token()
|
|
711
|
+
|
|
712
|
+
assistant_message.metrics.start_timer()
|
|
713
|
+
|
|
655
714
|
async_stream = await self.get_async_client().responses.create(
|
|
656
715
|
model=self.id,
|
|
657
716
|
input=self._format_messages(messages), # type: ignore
|
|
@@ -659,7 +718,11 @@ class OpenAIResponses(Model):
|
|
|
659
718
|
**request_params,
|
|
660
719
|
)
|
|
661
720
|
async for chunk in async_stream: # type: ignore
|
|
662
|
-
|
|
721
|
+
model_response, tool_use = self._parse_provider_response_delta(chunk, assistant_message, tool_use) # type: ignore
|
|
722
|
+
yield model_response
|
|
723
|
+
|
|
724
|
+
assistant_message.metrics.stop_timer()
|
|
725
|
+
|
|
663
726
|
except RateLimitError as exc:
|
|
664
727
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
665
728
|
error_message = exc.response.json().get("error", {})
|
|
@@ -711,7 +774,64 @@ class OpenAIResponses(Model):
|
|
|
711
774
|
_fc_message.tool_call_id = tool_call_ids[_fc_message_index]
|
|
712
775
|
messages.append(_fc_message)
|
|
713
776
|
|
|
714
|
-
def
|
|
777
|
+
def process_response_stream(
|
|
778
|
+
self,
|
|
779
|
+
messages: List[Message],
|
|
780
|
+
assistant_message: Message,
|
|
781
|
+
stream_data: MessageData,
|
|
782
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
783
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
784
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
785
|
+
run_response: Optional[RunOutput] = None,
|
|
786
|
+
) -> Iterator[ModelResponse]:
|
|
787
|
+
"""Process the synchronous response stream."""
|
|
788
|
+
for model_response_delta in self.invoke_stream(
|
|
789
|
+
messages=messages,
|
|
790
|
+
assistant_message=assistant_message,
|
|
791
|
+
tools=tools,
|
|
792
|
+
response_format=response_format,
|
|
793
|
+
tool_choice=tool_choice,
|
|
794
|
+
run_response=run_response,
|
|
795
|
+
):
|
|
796
|
+
yield from self._populate_stream_data_and_assistant_message(
|
|
797
|
+
stream_data=stream_data,
|
|
798
|
+
assistant_message=assistant_message,
|
|
799
|
+
model_response_delta=model_response_delta,
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
# Add final metrics to assistant message
|
|
803
|
+
self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
|
|
804
|
+
|
|
805
|
+
async def aprocess_response_stream(
|
|
806
|
+
self,
|
|
807
|
+
messages: List[Message],
|
|
808
|
+
assistant_message: Message,
|
|
809
|
+
stream_data: MessageData,
|
|
810
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
811
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
812
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
813
|
+
run_response: Optional[RunOutput] = None,
|
|
814
|
+
) -> AsyncIterator[ModelResponse]:
|
|
815
|
+
"""Process the asynchronous response stream."""
|
|
816
|
+
async for model_response_delta in self.ainvoke_stream(
|
|
817
|
+
messages=messages,
|
|
818
|
+
assistant_message=assistant_message,
|
|
819
|
+
tools=tools,
|
|
820
|
+
response_format=response_format,
|
|
821
|
+
tool_choice=tool_choice,
|
|
822
|
+
run_response=run_response,
|
|
823
|
+
):
|
|
824
|
+
for model_response in self._populate_stream_data_and_assistant_message(
|
|
825
|
+
stream_data=stream_data,
|
|
826
|
+
assistant_message=assistant_message,
|
|
827
|
+
model_response_delta=model_response_delta,
|
|
828
|
+
):
|
|
829
|
+
yield model_response
|
|
830
|
+
|
|
831
|
+
# Add final metrics to assistant message
|
|
832
|
+
self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
|
|
833
|
+
|
|
834
|
+
def _parse_provider_response(self, response: Response, **kwargs) -> ModelResponse:
|
|
715
835
|
"""
|
|
716
836
|
Parse the OpenAI response into a ModelResponse.
|
|
717
837
|
|
|
@@ -797,76 +917,66 @@ class OpenAIResponses(Model):
|
|
|
797
917
|
|
|
798
918
|
# Add metrics
|
|
799
919
|
if response.usage is not None:
|
|
800
|
-
model_response.response_usage = response.usage
|
|
920
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
801
921
|
|
|
802
922
|
return model_response
|
|
803
923
|
|
|
804
|
-
def
|
|
805
|
-
self,
|
|
806
|
-
|
|
807
|
-
assistant_message: Message,
|
|
808
|
-
stream_data: MessageData,
|
|
809
|
-
tool_use: Dict[str, Any],
|
|
810
|
-
) -> Tuple[Optional[ModelResponse], Dict[str, Any]]:
|
|
924
|
+
def _parse_provider_response_delta(
|
|
925
|
+
self, stream_event: ResponseStreamEvent, assistant_message: Message, tool_use: Dict[str, Any]
|
|
926
|
+
) -> Tuple[ModelResponse, Dict[str, Any]]:
|
|
811
927
|
"""
|
|
812
|
-
|
|
928
|
+
Parse the streaming response from the model provider into a ModelResponse object.
|
|
813
929
|
|
|
814
930
|
Args:
|
|
815
|
-
|
|
816
|
-
assistant_message: The assistant message being built
|
|
817
|
-
stream_data: Data accumulated during streaming
|
|
818
|
-
tool_use: Current tool use data being built
|
|
931
|
+
response: Raw response chunk from the model provider
|
|
819
932
|
|
|
820
933
|
Returns:
|
|
821
|
-
|
|
934
|
+
ModelResponse: Parsed response delta
|
|
822
935
|
"""
|
|
823
|
-
model_response =
|
|
936
|
+
model_response = ModelResponse()
|
|
824
937
|
|
|
938
|
+
# 1. Add response ID
|
|
825
939
|
if stream_event.type == "response.created":
|
|
826
|
-
model_response = ModelResponse()
|
|
827
|
-
# Store the response ID for continuity
|
|
828
940
|
if stream_event.response.id:
|
|
829
|
-
if
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
# Update metrics
|
|
941
|
+
if model_response.provider_data is None:
|
|
942
|
+
model_response.provider_data = {}
|
|
943
|
+
model_response.provider_data["response_id"] = stream_event.response.id
|
|
833
944
|
if not assistant_message.metrics.time_to_first_token:
|
|
834
945
|
assistant_message.metrics.set_time_to_first_token()
|
|
946
|
+
|
|
947
|
+
# 2. Add citations
|
|
835
948
|
elif stream_event.type == "response.output_text.annotation.added":
|
|
836
|
-
model_response
|
|
837
|
-
|
|
838
|
-
stream_data.response_citations = Citations(raw=[stream_event.annotation])
|
|
949
|
+
if model_response.citations is None:
|
|
950
|
+
model_response.citations = Citations(raw=[stream_event.annotation])
|
|
839
951
|
else:
|
|
840
|
-
|
|
952
|
+
model_response.citations.raw.append(stream_event.annotation) # type: ignore
|
|
841
953
|
|
|
842
954
|
if isinstance(stream_event.annotation, dict):
|
|
843
955
|
if stream_event.annotation.get("type") == "url_citation":
|
|
844
|
-
if
|
|
845
|
-
|
|
846
|
-
|
|
956
|
+
if model_response.citations.urls is None:
|
|
957
|
+
model_response.citations.urls = []
|
|
958
|
+
model_response.citations.urls.append(
|
|
847
959
|
UrlCitation(url=stream_event.annotation.get("url"), title=stream_event.annotation.get("title"))
|
|
848
960
|
)
|
|
849
961
|
else:
|
|
850
962
|
if stream_event.annotation.type == "url_citation": # type: ignore
|
|
851
|
-
if
|
|
852
|
-
|
|
853
|
-
|
|
963
|
+
if model_response.citations.urls is None:
|
|
964
|
+
model_response.citations.urls = []
|
|
965
|
+
model_response.citations.urls.append(
|
|
854
966
|
UrlCitation(url=stream_event.annotation.url, title=stream_event.annotation.title) # type: ignore
|
|
855
967
|
)
|
|
856
968
|
|
|
857
|
-
|
|
858
|
-
|
|
969
|
+
# 3. Add content
|
|
859
970
|
elif stream_event.type == "response.output_text.delta":
|
|
860
|
-
model_response = ModelResponse()
|
|
861
|
-
# Add content
|
|
862
971
|
model_response.content = stream_event.delta
|
|
863
|
-
stream_data.response_content += stream_event.delta
|
|
864
972
|
|
|
865
973
|
# Treat the output_text deltas as reasoning content if the reasoning summary is not requested.
|
|
866
974
|
if self.reasoning is not None and self.reasoning_summary is None:
|
|
867
975
|
model_response.reasoning_content = stream_event.delta
|
|
868
|
-
stream_data.response_thinking += stream_event.delta
|
|
869
976
|
|
|
977
|
+
# 4. Add tool calls information
|
|
978
|
+
|
|
979
|
+
# 4.1 Add starting tool call
|
|
870
980
|
elif stream_event.type == "response.output_item.added":
|
|
871
981
|
item = stream_event.item
|
|
872
982
|
if item.type == "function_call":
|
|
@@ -880,20 +990,22 @@ class OpenAIResponses(Model):
|
|
|
880
990
|
},
|
|
881
991
|
}
|
|
882
992
|
|
|
993
|
+
# 4.2 Add tool call arguments
|
|
883
994
|
elif stream_event.type == "response.function_call_arguments.delta":
|
|
884
995
|
tool_use["function"]["arguments"] += stream_event.delta
|
|
885
996
|
|
|
997
|
+
# 4.3 Add tool call completion data
|
|
886
998
|
elif stream_event.type == "response.output_item.done" and tool_use:
|
|
887
|
-
model_response = ModelResponse()
|
|
888
999
|
model_response.tool_calls = [tool_use]
|
|
889
1000
|
if assistant_message.tool_calls is None:
|
|
890
1001
|
assistant_message.tool_calls = []
|
|
891
1002
|
assistant_message.tool_calls.append(tool_use)
|
|
892
1003
|
|
|
893
|
-
|
|
894
|
-
|
|
1004
|
+
model_response.extra = model_response.extra or {}
|
|
1005
|
+
model_response.extra.setdefault("tool_call_ids", []).append(tool_use["call_id"])
|
|
895
1006
|
tool_use = {}
|
|
896
1007
|
|
|
1008
|
+
# 5. Add metrics
|
|
897
1009
|
elif stream_event.type == "response.completed":
|
|
898
1010
|
model_response = ModelResponse()
|
|
899
1011
|
|
|
@@ -915,63 +1027,24 @@ class OpenAIResponses(Model):
|
|
|
915
1027
|
|
|
916
1028
|
# Add metrics
|
|
917
1029
|
if stream_event.response.usage is not None:
|
|
918
|
-
model_response.response_usage = stream_event.response.usage
|
|
919
|
-
|
|
920
|
-
_add_usage_metrics_to_assistant_message(
|
|
921
|
-
assistant_message=assistant_message,
|
|
922
|
-
response_usage=model_response.response_usage,
|
|
923
|
-
)
|
|
1030
|
+
model_response.response_usage = self._get_metrics(stream_event.response.usage)
|
|
924
1031
|
|
|
925
1032
|
return model_response, tool_use
|
|
926
1033
|
|
|
927
|
-
def
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
assistant_message: Message,
|
|
931
|
-
stream_data: MessageData,
|
|
932
|
-
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
933
|
-
tools: Optional[List[Dict[str, Any]]] = None,
|
|
934
|
-
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
935
|
-
) -> Iterator[ModelResponse]:
|
|
936
|
-
"""Process the synchronous response stream."""
|
|
937
|
-
tool_use: Dict[str, Any] = {}
|
|
938
|
-
|
|
939
|
-
for stream_event in self.invoke_stream(
|
|
940
|
-
messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
|
|
941
|
-
):
|
|
942
|
-
model_response, tool_use = self._process_stream_response(
|
|
943
|
-
stream_event=stream_event,
|
|
944
|
-
assistant_message=assistant_message,
|
|
945
|
-
stream_data=stream_data,
|
|
946
|
-
tool_use=tool_use,
|
|
947
|
-
)
|
|
1034
|
+
def _get_metrics(self, response_usage: ResponseUsage) -> Metrics:
|
|
1035
|
+
"""
|
|
1036
|
+
Parse the given OpenAI-specific usage into an Agno Metrics object.
|
|
948
1037
|
|
|
949
|
-
|
|
950
|
-
|
|
1038
|
+
Args:
|
|
1039
|
+
response: The response from the provider.
|
|
951
1040
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
stream_data: MessageData,
|
|
957
|
-
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
958
|
-
tools: Optional[List[Dict[str, Any]]] = None,
|
|
959
|
-
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
960
|
-
) -> AsyncIterator[ModelResponse]:
|
|
961
|
-
"""Process the asynchronous response stream."""
|
|
962
|
-
tool_use: Dict[str, Any] = {}
|
|
1041
|
+
Returns:
|
|
1042
|
+
Metrics: Parsed metrics data
|
|
1043
|
+
"""
|
|
1044
|
+
metrics = Metrics()
|
|
963
1045
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
model_response, tool_use = self._process_stream_response(
|
|
968
|
-
stream_event=stream_event,
|
|
969
|
-
assistant_message=assistant_message,
|
|
970
|
-
stream_data=stream_data,
|
|
971
|
-
tool_use=tool_use,
|
|
972
|
-
)
|
|
973
|
-
if model_response is not None:
|
|
974
|
-
yield model_response
|
|
1046
|
+
metrics.input_tokens = response_usage.input_tokens or 0
|
|
1047
|
+
metrics.output_tokens = response_usage.output_tokens or 0
|
|
1048
|
+
metrics.total_tokens = response_usage.total_tokens or 0
|
|
975
1049
|
|
|
976
|
-
|
|
977
|
-
pass
|
|
1050
|
+
return metrics
|
|
@@ -6,6 +6,7 @@ from pydantic import BaseModel
|
|
|
6
6
|
|
|
7
7
|
from agno.exceptions import ModelProviderError
|
|
8
8
|
from agno.models.message import Citations, UrlCitation
|
|
9
|
+
from agno.models.metrics import Metrics
|
|
9
10
|
from agno.models.response import ModelResponse
|
|
10
11
|
from agno.utils.log import log_debug, log_warning
|
|
11
12
|
|
|
@@ -16,6 +17,7 @@ try:
|
|
|
16
17
|
ChoiceDelta,
|
|
17
18
|
)
|
|
18
19
|
from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
|
|
20
|
+
from openai.types.completion_usage import CompletionUsage
|
|
19
21
|
except ModuleNotFoundError:
|
|
20
22
|
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
21
23
|
|
|
@@ -124,7 +126,7 @@ class Perplexity(OpenAILike):
|
|
|
124
126
|
)
|
|
125
127
|
|
|
126
128
|
if response.usage is not None:
|
|
127
|
-
model_response.response_usage = response.usage
|
|
129
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
128
130
|
|
|
129
131
|
return model_response
|
|
130
132
|
|
|
@@ -159,6 +161,28 @@ class Perplexity(OpenAILike):
|
|
|
159
161
|
|
|
160
162
|
# Add usage metrics if present
|
|
161
163
|
if response_delta.usage is not None:
|
|
162
|
-
model_response.response_usage = response_delta.usage
|
|
164
|
+
model_response.response_usage = self._get_metrics(response_delta.usage)
|
|
163
165
|
|
|
164
166
|
return model_response
|
|
167
|
+
|
|
168
|
+
def _get_metrics(self, response_usage: CompletionUsage) -> Metrics:
|
|
169
|
+
"""
|
|
170
|
+
Parse the given Perplexity usage into an Agno Metrics object.
|
|
171
|
+
"""
|
|
172
|
+
metrics = Metrics()
|
|
173
|
+
|
|
174
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
175
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
176
|
+
metrics.total_tokens = response_usage.total_tokens or 0
|
|
177
|
+
|
|
178
|
+
# Add the prompt_tokens_details field
|
|
179
|
+
if prompt_token_details := response_usage.prompt_tokens_details:
|
|
180
|
+
metrics.audio_input_tokens = prompt_token_details.audio_tokens or 0
|
|
181
|
+
metrics.cache_read_tokens = prompt_token_details.cached_tokens or 0
|
|
182
|
+
|
|
183
|
+
# Add the completion_tokens_details field
|
|
184
|
+
if completion_tokens_details := response_usage.completion_tokens_details:
|
|
185
|
+
metrics.audio_output_tokens = completion_tokens_details.audio_tokens or 0
|
|
186
|
+
metrics.reasoning_tokens = completion_tokens_details.reasoning_tokens or 0
|
|
187
|
+
|
|
188
|
+
return metrics
|
agno/models/portkey/portkey.py
CHANGED
|
@@ -44,13 +44,6 @@ class Portkey(OpenAILike):
|
|
|
44
44
|
model_id=self.id,
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
if not self.virtual_key:
|
|
48
|
-
raise ModelProviderError(
|
|
49
|
-
message="PORTKEY_VIRTUAL_KEY not set. Please set the PORTKEY_VIRTUAL_KEY environment variable.",
|
|
50
|
-
model_name=self.name,
|
|
51
|
-
model_id=self.id,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
47
|
# Create headers using Portkey's createHeaders function
|
|
55
48
|
header_params: Dict[str, Any] = {
|
|
56
49
|
"api_key": self.portkey_api_key,
|
agno/models/response.py
CHANGED
|
@@ -3,8 +3,9 @@ from enum import Enum
|
|
|
3
3
|
from time import time
|
|
4
4
|
from typing import Any, Dict, List, Optional
|
|
5
5
|
|
|
6
|
-
from agno.media import
|
|
7
|
-
from agno.models.message import Citations
|
|
6
|
+
from agno.media import Audio, Image, Video
|
|
7
|
+
from agno.models.message import Citations
|
|
8
|
+
from agno.models.metrics import Metrics
|
|
8
9
|
from agno.tools.function import UserInputField
|
|
9
10
|
|
|
10
11
|
|
|
@@ -26,7 +27,7 @@ class ToolExecution:
|
|
|
26
27
|
tool_args: Optional[Dict[str, Any]] = None
|
|
27
28
|
tool_call_error: Optional[bool] = None
|
|
28
29
|
result: Optional[str] = None
|
|
29
|
-
metrics: Optional[
|
|
30
|
+
metrics: Optional[Metrics] = None
|
|
30
31
|
|
|
31
32
|
# If True, the agent will stop executing after this tool call.
|
|
32
33
|
stop_after_tool_call: bool = False
|
|
@@ -74,7 +75,7 @@ class ToolExecution:
|
|
|
74
75
|
if "user_input_schema" in data
|
|
75
76
|
else None,
|
|
76
77
|
external_execution_required=data.get("external_execution_required"),
|
|
77
|
-
metrics=
|
|
78
|
+
metrics=Metrics(**(data.get("metrics", {}) or {})),
|
|
78
79
|
)
|
|
79
80
|
|
|
80
81
|
|
|
@@ -86,8 +87,12 @@ class ModelResponse:
|
|
|
86
87
|
|
|
87
88
|
content: Optional[Any] = None
|
|
88
89
|
parsed: Optional[Any] = None
|
|
89
|
-
audio: Optional[
|
|
90
|
-
|
|
90
|
+
audio: Optional[Audio] = None
|
|
91
|
+
|
|
92
|
+
# Unified media fields for LLM-generated and tool-generated media artifacts
|
|
93
|
+
images: Optional[List[Image]] = None
|
|
94
|
+
videos: Optional[List[Video]] = None
|
|
95
|
+
audios: Optional[List[Audio]] = None
|
|
91
96
|
|
|
92
97
|
# Model tool calls
|
|
93
98
|
tool_calls: List[Dict[str, Any]] = field(default_factory=list)
|
|
@@ -99,18 +104,19 @@ class ModelResponse:
|
|
|
99
104
|
|
|
100
105
|
provider_data: Optional[Dict[str, Any]] = None
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
redacted_thinking: Optional[str] = None
|
|
107
|
+
redacted_reasoning_content: Optional[str] = None
|
|
104
108
|
reasoning_content: Optional[str] = None
|
|
105
109
|
|
|
106
110
|
citations: Optional[Citations] = None
|
|
107
111
|
|
|
108
|
-
response_usage: Optional[
|
|
112
|
+
response_usage: Optional[Metrics] = None
|
|
109
113
|
|
|
110
114
|
created_at: int = int(time())
|
|
111
115
|
|
|
112
116
|
extra: Optional[Dict[str, Any]] = None
|
|
113
117
|
|
|
118
|
+
updated_session_state: Optional[Dict[str, Any]] = None
|
|
119
|
+
|
|
114
120
|
|
|
115
121
|
class FileType(str, Enum):
|
|
116
122
|
MP4 = "mp4"
|
agno/models/utils.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from agno.models.base import Model
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# TODO: add all supported models
|
|
5
|
+
def get_model(model_id: str, model_provider: str) -> Model:
|
|
6
|
+
"""Return the right Agno model instance given a pair of model provider and id"""
|
|
7
|
+
if model_provider == "openai":
|
|
8
|
+
from agno.models.openai import OpenAIChat
|
|
9
|
+
|
|
10
|
+
return OpenAIChat(id=model_id)
|
|
11
|
+
elif model_provider == "anthropic":
|
|
12
|
+
from agno.models.anthropic import Claude
|
|
13
|
+
|
|
14
|
+
return Claude(id=model_id)
|
|
15
|
+
elif model_provider == "gemini":
|
|
16
|
+
from agno.models.google import Gemini
|
|
17
|
+
|
|
18
|
+
return Gemini(id=model_id)
|
|
19
|
+
else:
|
|
20
|
+
raise ValueError(f"Model provider {model_provider} not supported")
|
agno/models/vercel/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from agno.models.vercel.v0 import
|
|
1
|
+
from agno.models.vercel.v0 import V0
|
|
2
2
|
|
|
3
|
-
__all__ = ["
|
|
3
|
+
__all__ = ["V0"]
|
agno/models/vercel/v0.py
CHANGED
agno/models/vllm/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from agno.models.vllm.vllm import
|
|
1
|
+
from agno.models.vllm.vllm import VLLM
|
|
2
2
|
|
|
3
|
-
__all__ = ["
|
|
3
|
+
__all__ = ["VLLM"]
|
agno/models/vllm/vllm.py
CHANGED
|
@@ -9,7 +9,7 @@ from agno.utils.log import log_debug
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@dataclass
|
|
12
|
-
class
|
|
12
|
+
class VLLM(OpenAILike):
|
|
13
13
|
"""
|
|
14
14
|
Class for interacting with vLLM models via OpenAI-compatible API.
|
|
15
15
|
|
|
@@ -26,8 +26,8 @@ class vLLM(OpenAILike):
|
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
28
|
id: str = "not-set"
|
|
29
|
-
name: str = "
|
|
30
|
-
provider: str = "
|
|
29
|
+
name: str = "VLLM"
|
|
30
|
+
provider: str = "VLLM"
|
|
31
31
|
|
|
32
32
|
api_key: Optional[str] = getenv("VLLM_API_KEY") or "EMPTY"
|
|
33
33
|
base_url: Optional[str] = getenv("VLLM_BASE_URL", "http://localhost:8000/v1/")
|