agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 +2781 -4126
- agno/api/agent.py +9 -65
- agno/api/api.py +5 -46
- agno/api/evals.py +6 -17
- 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 +9 -64
- 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 +1749 -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 +1438 -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 +888 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1051 -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 +1417 -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 +298 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1720 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +281 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1371 -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 +1722 -0
- agno/db/singlestore/utils.py +327 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1680 -0
- agno/db/sqlite/utils.py +269 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +142 -43
- 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 +1515 -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 +68 -15
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/knowledge/reader/gcs_reader.py +67 -0
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +36 -9
- agno/{document → knowledge}/reader/pdf_reader.py +79 -21
- agno/knowledge/reader/reader_factory.py +275 -0
- agno/knowledge/reader/s3_reader.py +171 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +84 -0
- agno/knowledge/reader/web_search_reader.py +389 -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 +2 -2
- 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 +129 -82
- 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 +347 -287
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/dashscope/dashscope.py +14 -5
- agno/models/google/gemini.py +123 -53
- 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 +38 -144
- 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 +84 -46
- agno/models/openai/chat.py +135 -27
- agno/models/openai/responses.py +233 -115
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +14 -8
- 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 +393 -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 +33 -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 +30 -0
- agno/os/router.py +843 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +204 -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 +413 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +179 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +58 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +163 -0
- agno/os/schema.py +892 -0
- agno/{app/playground → os}/settings.py +8 -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/{response.py → agent.py} +144 -72
- agno/run/base.py +44 -58
- agno/run/cancel.py +83 -0
- agno/run/team.py +133 -77
- agno/run/workflow.py +537 -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 +2967 -4243
- 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 +42 -22
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +18 -13
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +71 -18
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +18 -11
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +16 -7
- 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 +35 -28
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +29 -29
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +68 -17
- agno/tools/giphy.py +22 -10
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +46 -62
- 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 +31 -19
- 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 +32 -14
- agno/tools/models/gemini.py +58 -31
- agno/tools/models/groq.py +29 -20
- agno/tools/models/nebius.py +27 -11
- agno/tools/models_labs.py +39 -15
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +57 -26
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +62 -46
- 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 +54 -41
- 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 +95 -118
- agno/utils/knowledge.py +29 -0
- agno/utils/location.py +2 -2
- agno/utils/log.py +2 -2
- agno/utils/mcp.py +11 -5
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/claude.py +6 -4
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1565 -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/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 +356 -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} +200 -42
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2394 -696
- agno-2.0.0a1.dist-info/METADATA +355 -0
- agno-2.0.0a1.dist-info/RECORD +514 -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 -698
- 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/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.0.dist-info/METADATA +0 -979
- agno-1.8.0.dist-info/RECORD +0 -565
- agno-1.8.0.dist-info/entry_points.txt +0 -3
- /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.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.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
|
|
|
@@ -44,6 +48,7 @@ class OpenAIResponses(Model):
|
|
|
44
48
|
reasoning: Optional[Dict[str, Any]] = None
|
|
45
49
|
verbosity: Optional[Literal["low", "medium", "high"]] = None
|
|
46
50
|
reasoning_effort: Optional[Literal["minimal", "medium", "high"]] = None
|
|
51
|
+
reasoning_summary: Optional[Literal["auto", "concise", "detailed"]] = None
|
|
47
52
|
store: Optional[bool] = None
|
|
48
53
|
temperature: Optional[float] = None
|
|
49
54
|
top_p: Optional[float] = None
|
|
@@ -84,6 +89,18 @@ class OpenAIResponses(Model):
|
|
|
84
89
|
"""Return True if the contextual used model is a known reasoning model."""
|
|
85
90
|
return self.id.startswith("o3") or self.id.startswith("o4-mini") or self.id.startswith("gpt-5")
|
|
86
91
|
|
|
92
|
+
def _set_reasoning_request_param(self, base_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
93
|
+
"""Set the reasoning request parameter."""
|
|
94
|
+
base_params["reasoning"] = self.reasoning or {}
|
|
95
|
+
|
|
96
|
+
if self.reasoning_effort is not None:
|
|
97
|
+
base_params["reasoning"]["effort"] = self.reasoning_effort
|
|
98
|
+
|
|
99
|
+
if self.reasoning_summary is not None:
|
|
100
|
+
base_params["reasoning"]["summary"] = self.reasoning_summary
|
|
101
|
+
|
|
102
|
+
return base_params
|
|
103
|
+
|
|
87
104
|
def _get_client_params(self) -> Dict[str, Any]:
|
|
88
105
|
"""
|
|
89
106
|
Get client parameters for API requests.
|
|
@@ -185,12 +202,8 @@ class OpenAIResponses(Model):
|
|
|
185
202
|
"user": self.user,
|
|
186
203
|
"service_tier": self.service_tier,
|
|
187
204
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if self.reasoning is not None:
|
|
191
|
-
base_params["reasoning"] = self.reasoning
|
|
192
|
-
elif self.reasoning_effort is not None:
|
|
193
|
-
base_params["reasoning"] = {"effort": self.reasoning_effort}
|
|
205
|
+
# Populate the reasoning parameter
|
|
206
|
+
base_params = self._set_reasoning_request_param(base_params)
|
|
194
207
|
|
|
195
208
|
# Build text parameter
|
|
196
209
|
text_params: Dict[str, Any] = {}
|
|
@@ -467,10 +480,12 @@ class OpenAIResponses(Model):
|
|
|
467
480
|
def invoke(
|
|
468
481
|
self,
|
|
469
482
|
messages: List[Message],
|
|
483
|
+
assistant_message: Message,
|
|
470
484
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
471
485
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
472
486
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
473
|
-
|
|
487
|
+
run_response: Optional[RunOutput] = None,
|
|
488
|
+
) -> ModelResponse:
|
|
474
489
|
"""
|
|
475
490
|
Send a request to the OpenAI Responses API.
|
|
476
491
|
"""
|
|
@@ -479,11 +494,23 @@ class OpenAIResponses(Model):
|
|
|
479
494
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
480
495
|
)
|
|
481
496
|
|
|
482
|
-
|
|
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(
|
|
483
503
|
model=self.id,
|
|
484
504
|
input=self._format_messages(messages), # type: ignore
|
|
485
505
|
**request_params,
|
|
486
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
|
+
|
|
487
514
|
except RateLimitError as exc:
|
|
488
515
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
489
516
|
error_message = exc.response.json().get("error", {})
|
|
@@ -522,10 +549,12 @@ class OpenAIResponses(Model):
|
|
|
522
549
|
async def ainvoke(
|
|
523
550
|
self,
|
|
524
551
|
messages: List[Message],
|
|
552
|
+
assistant_message: Message,
|
|
525
553
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
526
554
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
527
555
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
528
|
-
|
|
556
|
+
run_response: Optional[RunOutput] = None,
|
|
557
|
+
) -> ModelResponse:
|
|
529
558
|
"""
|
|
530
559
|
Sends an asynchronous request to the OpenAI Responses API.
|
|
531
560
|
"""
|
|
@@ -534,11 +563,23 @@ class OpenAIResponses(Model):
|
|
|
534
563
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
535
564
|
)
|
|
536
565
|
|
|
537
|
-
|
|
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(
|
|
538
572
|
model=self.id,
|
|
539
573
|
input=self._format_messages(messages), # type: ignore
|
|
540
574
|
**request_params,
|
|
541
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
|
+
|
|
542
583
|
except RateLimitError as exc:
|
|
543
584
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
544
585
|
error_message = exc.response.json().get("error", {})
|
|
@@ -577,10 +618,12 @@ class OpenAIResponses(Model):
|
|
|
577
618
|
def invoke_stream(
|
|
578
619
|
self,
|
|
579
620
|
messages: List[Message],
|
|
621
|
+
assistant_message: Message,
|
|
580
622
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
581
623
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
582
624
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
583
|
-
|
|
625
|
+
run_response: Optional[RunOutput] = None,
|
|
626
|
+
) -> Iterator[ModelResponse]:
|
|
584
627
|
"""
|
|
585
628
|
Send a streaming request to the OpenAI Responses API.
|
|
586
629
|
"""
|
|
@@ -588,13 +631,28 @@ class OpenAIResponses(Model):
|
|
|
588
631
|
request_params = self.get_request_params(
|
|
589
632
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
590
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()
|
|
591
638
|
|
|
592
|
-
|
|
639
|
+
assistant_message.metrics.start_timer()
|
|
640
|
+
|
|
641
|
+
for chunk in self.get_client().responses.create(
|
|
593
642
|
model=self.id,
|
|
594
643
|
input=self._format_messages(messages), # type: ignore
|
|
595
644
|
stream=True,
|
|
596
645
|
**request_params,
|
|
597
|
-
)
|
|
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
|
+
|
|
598
656
|
except RateLimitError as exc:
|
|
599
657
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
600
658
|
error_message = exc.response.json().get("error", {})
|
|
@@ -633,10 +691,12 @@ class OpenAIResponses(Model):
|
|
|
633
691
|
async def ainvoke_stream(
|
|
634
692
|
self,
|
|
635
693
|
messages: List[Message],
|
|
694
|
+
assistant_message: Message,
|
|
636
695
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
637
696
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
638
697
|
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
639
|
-
|
|
698
|
+
run_response: Optional[RunOutput] = None,
|
|
699
|
+
) -> AsyncIterator[ModelResponse]:
|
|
640
700
|
"""
|
|
641
701
|
Sends an asynchronous streaming request to the OpenAI Responses API.
|
|
642
702
|
"""
|
|
@@ -644,6 +704,13 @@ class OpenAIResponses(Model):
|
|
|
644
704
|
request_params = self.get_request_params(
|
|
645
705
|
messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
|
|
646
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
|
+
|
|
647
714
|
async_stream = await self.get_async_client().responses.create(
|
|
648
715
|
model=self.id,
|
|
649
716
|
input=self._format_messages(messages), # type: ignore
|
|
@@ -651,7 +718,11 @@ class OpenAIResponses(Model):
|
|
|
651
718
|
**request_params,
|
|
652
719
|
)
|
|
653
720
|
async for chunk in async_stream: # type: ignore
|
|
654
|
-
|
|
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
|
+
|
|
655
726
|
except RateLimitError as exc:
|
|
656
727
|
log_error(f"Rate limit error from OpenAI API: {exc}")
|
|
657
728
|
error_message = exc.response.json().get("error", {})
|
|
@@ -703,7 +774,64 @@ class OpenAIResponses(Model):
|
|
|
703
774
|
_fc_message.tool_call_id = tool_call_ids[_fc_message_index]
|
|
704
775
|
messages.append(_fc_message)
|
|
705
776
|
|
|
706
|
-
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:
|
|
707
835
|
"""
|
|
708
836
|
Parse the OpenAI response into a ModelResponse.
|
|
709
837
|
|
|
@@ -730,7 +858,10 @@ class OpenAIResponses(Model):
|
|
|
730
858
|
|
|
731
859
|
# Add role
|
|
732
860
|
model_response.role = "assistant"
|
|
861
|
+
reasoning_summary: str = ""
|
|
862
|
+
|
|
733
863
|
for output in response.output:
|
|
864
|
+
# Add content
|
|
734
865
|
if output.type == "message":
|
|
735
866
|
model_response.content = response.output_text
|
|
736
867
|
|
|
@@ -746,6 +877,8 @@ class OpenAIResponses(Model):
|
|
|
746
877
|
citations.urls.append(UrlCitation(url=annotation.url, title=annotation.title))
|
|
747
878
|
if citations.urls or citations.documents:
|
|
748
879
|
model_response.citations = citations
|
|
880
|
+
|
|
881
|
+
# Add tool calls
|
|
749
882
|
elif output.type == "function_call":
|
|
750
883
|
if model_response.tool_calls is None:
|
|
751
884
|
model_response.tool_calls = []
|
|
@@ -765,80 +898,85 @@ class OpenAIResponses(Model):
|
|
|
765
898
|
model_response.extra = model_response.extra or {}
|
|
766
899
|
model_response.extra.setdefault("tool_call_ids", []).append(output.call_id)
|
|
767
900
|
|
|
768
|
-
|
|
769
|
-
|
|
901
|
+
# Add reasoning summary
|
|
902
|
+
elif output.type == "reasoning":
|
|
903
|
+
if reasoning_summaries := getattr(output, "summary", None):
|
|
904
|
+
for summary in reasoning_summaries:
|
|
905
|
+
if isinstance(summary, dict):
|
|
906
|
+
summary_text = summary.get("text")
|
|
907
|
+
else:
|
|
908
|
+
summary_text = getattr(summary, "text", None)
|
|
909
|
+
if summary_text:
|
|
910
|
+
reasoning_summary = (reasoning_summary or "") + summary_text
|
|
911
|
+
|
|
912
|
+
# Add reasoning content
|
|
913
|
+
if reasoning_summary is not None:
|
|
914
|
+
model_response.reasoning_content = reasoning_summary
|
|
915
|
+
elif self.reasoning is not None:
|
|
770
916
|
model_response.reasoning_content = response.output_text
|
|
771
917
|
|
|
918
|
+
# Add metrics
|
|
772
919
|
if response.usage is not None:
|
|
773
|
-
model_response.response_usage = response.usage
|
|
920
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
774
921
|
|
|
775
922
|
return model_response
|
|
776
923
|
|
|
777
|
-
def
|
|
778
|
-
self,
|
|
779
|
-
|
|
780
|
-
assistant_message: Message,
|
|
781
|
-
stream_data: MessageData,
|
|
782
|
-
tool_use: Dict[str, Any],
|
|
783
|
-
) -> 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]]:
|
|
784
927
|
"""
|
|
785
|
-
|
|
928
|
+
Parse the streaming response from the model provider into a ModelResponse object.
|
|
786
929
|
|
|
787
930
|
Args:
|
|
788
|
-
|
|
789
|
-
assistant_message: The assistant message being built
|
|
790
|
-
stream_data: Data accumulated during streaming
|
|
791
|
-
tool_use: Current tool use data being built
|
|
931
|
+
response: Raw response chunk from the model provider
|
|
792
932
|
|
|
793
933
|
Returns:
|
|
794
|
-
|
|
934
|
+
ModelResponse: Parsed response delta
|
|
795
935
|
"""
|
|
796
|
-
model_response =
|
|
936
|
+
model_response = ModelResponse()
|
|
797
937
|
|
|
938
|
+
# 1. Add response ID
|
|
798
939
|
if stream_event.type == "response.created":
|
|
799
|
-
model_response = ModelResponse()
|
|
800
|
-
# Store the response ID for continuity
|
|
801
940
|
if stream_event.response.id:
|
|
802
|
-
if
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
# 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
|
|
806
944
|
if not assistant_message.metrics.time_to_first_token:
|
|
807
945
|
assistant_message.metrics.set_time_to_first_token()
|
|
946
|
+
|
|
947
|
+
# 2. Add citations
|
|
808
948
|
elif stream_event.type == "response.output_text.annotation.added":
|
|
809
|
-
model_response
|
|
810
|
-
|
|
811
|
-
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])
|
|
812
951
|
else:
|
|
813
|
-
|
|
952
|
+
model_response.citations.raw.append(stream_event.annotation) # type: ignore
|
|
814
953
|
|
|
815
954
|
if isinstance(stream_event.annotation, dict):
|
|
816
955
|
if stream_event.annotation.get("type") == "url_citation":
|
|
817
|
-
if
|
|
818
|
-
|
|
819
|
-
|
|
956
|
+
if model_response.citations.urls is None:
|
|
957
|
+
model_response.citations.urls = []
|
|
958
|
+
model_response.citations.urls.append(
|
|
820
959
|
UrlCitation(url=stream_event.annotation.get("url"), title=stream_event.annotation.get("title"))
|
|
821
960
|
)
|
|
822
961
|
else:
|
|
823
962
|
if stream_event.annotation.type == "url_citation": # type: ignore
|
|
824
|
-
if
|
|
825
|
-
|
|
826
|
-
|
|
963
|
+
if model_response.citations.urls is None:
|
|
964
|
+
model_response.citations.urls = []
|
|
965
|
+
model_response.citations.urls.append(
|
|
827
966
|
UrlCitation(url=stream_event.annotation.url, title=stream_event.annotation.title) # type: ignore
|
|
828
967
|
)
|
|
829
968
|
|
|
830
|
-
|
|
831
|
-
|
|
969
|
+
# 3. Add content
|
|
832
970
|
elif stream_event.type == "response.output_text.delta":
|
|
833
|
-
model_response = ModelResponse()
|
|
834
|
-
# Add content
|
|
835
971
|
model_response.content = stream_event.delta
|
|
836
|
-
stream_data.response_content += stream_event.delta
|
|
837
972
|
|
|
838
|
-
if
|
|
973
|
+
# Treat the output_text deltas as reasoning content if the reasoning summary is not requested.
|
|
974
|
+
if self.reasoning is not None and self.reasoning_summary is None:
|
|
839
975
|
model_response.reasoning_content = stream_event.delta
|
|
840
|
-
stream_data.response_thinking += stream_event.delta
|
|
841
976
|
|
|
977
|
+
# 4. Add tool calls information
|
|
978
|
+
|
|
979
|
+
# 4.1 Add starting tool call
|
|
842
980
|
elif stream_event.type == "response.output_item.added":
|
|
843
981
|
item = stream_event.item
|
|
844
982
|
if item.type == "function_call":
|
|
@@ -852,81 +990,61 @@ class OpenAIResponses(Model):
|
|
|
852
990
|
},
|
|
853
991
|
}
|
|
854
992
|
|
|
993
|
+
# 4.2 Add tool call arguments
|
|
855
994
|
elif stream_event.type == "response.function_call_arguments.delta":
|
|
856
995
|
tool_use["function"]["arguments"] += stream_event.delta
|
|
857
996
|
|
|
997
|
+
# 4.3 Add tool call completion data
|
|
858
998
|
elif stream_event.type == "response.output_item.done" and tool_use:
|
|
859
|
-
model_response = ModelResponse()
|
|
860
999
|
model_response.tool_calls = [tool_use]
|
|
861
1000
|
if assistant_message.tool_calls is None:
|
|
862
1001
|
assistant_message.tool_calls = []
|
|
863
1002
|
assistant_message.tool_calls.append(tool_use)
|
|
864
1003
|
|
|
865
|
-
|
|
866
|
-
|
|
1004
|
+
model_response.extra = model_response.extra or {}
|
|
1005
|
+
model_response.extra.setdefault("tool_call_ids", []).append(tool_use["call_id"])
|
|
867
1006
|
tool_use = {}
|
|
868
1007
|
|
|
1008
|
+
# 5. Add metrics
|
|
869
1009
|
elif stream_event.type == "response.completed":
|
|
870
1010
|
model_response = ModelResponse()
|
|
871
|
-
# Add usage metrics if present
|
|
872
|
-
if stream_event.response.usage is not None:
|
|
873
|
-
model_response.response_usage = stream_event.response.usage
|
|
874
1011
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1012
|
+
# Add reasoning summary
|
|
1013
|
+
if self.reasoning_summary is not None:
|
|
1014
|
+
summary_text: str = ""
|
|
1015
|
+
for out in getattr(stream_event.response, "output", []) or []:
|
|
1016
|
+
if getattr(out, "type", None) == "reasoning":
|
|
1017
|
+
summaries = getattr(out, "summary", None)
|
|
1018
|
+
if summaries:
|
|
1019
|
+
for s in summaries:
|
|
1020
|
+
text_val = s.get("text") if isinstance(s, dict) else getattr(s, "text", None)
|
|
1021
|
+
if text_val:
|
|
1022
|
+
if summary_text:
|
|
1023
|
+
summary_text += "\n\n"
|
|
1024
|
+
summary_text += text_val
|
|
1025
|
+
if summary_text:
|
|
1026
|
+
model_response.reasoning_content = summary_text
|
|
1027
|
+
|
|
1028
|
+
# Add metrics
|
|
1029
|
+
if stream_event.response.usage is not None:
|
|
1030
|
+
model_response.response_usage = self._get_metrics(stream_event.response.usage)
|
|
879
1031
|
|
|
880
1032
|
return model_response, tool_use
|
|
881
1033
|
|
|
882
|
-
def
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
assistant_message: Message,
|
|
886
|
-
stream_data: MessageData,
|
|
887
|
-
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
888
|
-
tools: Optional[List[Dict[str, Any]]] = None,
|
|
889
|
-
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
890
|
-
) -> Iterator[ModelResponse]:
|
|
891
|
-
"""Process the synchronous response stream."""
|
|
892
|
-
tool_use: Dict[str, Any] = {}
|
|
893
|
-
|
|
894
|
-
for stream_event in self.invoke_stream(
|
|
895
|
-
messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
|
|
896
|
-
):
|
|
897
|
-
model_response, tool_use = self._process_stream_response(
|
|
898
|
-
stream_event=stream_event,
|
|
899
|
-
assistant_message=assistant_message,
|
|
900
|
-
stream_data=stream_data,
|
|
901
|
-
tool_use=tool_use,
|
|
902
|
-
)
|
|
1034
|
+
def _get_metrics(self, response_usage: ResponseUsage) -> Metrics:
|
|
1035
|
+
"""
|
|
1036
|
+
Parse the given OpenAI-specific usage into an Agno Metrics object.
|
|
903
1037
|
|
|
904
|
-
|
|
905
|
-
|
|
1038
|
+
Args:
|
|
1039
|
+
response: The response from the provider.
|
|
906
1040
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
stream_data: MessageData,
|
|
912
|
-
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
913
|
-
tools: Optional[List[Dict[str, Any]]] = None,
|
|
914
|
-
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
915
|
-
) -> AsyncIterator[ModelResponse]:
|
|
916
|
-
"""Process the asynchronous response stream."""
|
|
917
|
-
tool_use: Dict[str, Any] = {}
|
|
1041
|
+
Returns:
|
|
1042
|
+
Metrics: Parsed metrics data
|
|
1043
|
+
"""
|
|
1044
|
+
metrics = Metrics()
|
|
918
1045
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
model_response, tool_use = self._process_stream_response(
|
|
923
|
-
stream_event=stream_event,
|
|
924
|
-
assistant_message=assistant_message,
|
|
925
|
-
stream_data=stream_data,
|
|
926
|
-
tool_use=tool_use,
|
|
927
|
-
)
|
|
928
|
-
if model_response is not None:
|
|
929
|
-
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
|
|
930
1049
|
|
|
931
|
-
|
|
932
|
-
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,
|