agno 0.1.2__py3-none-any.whl → 2.3.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- 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/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -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/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- 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 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- 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 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- 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/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
4
4
|
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from agno.exceptions import ModelAuthenticationError
|
|
5
8
|
from agno.models.openai.like import OpenAILike
|
|
9
|
+
from agno.run.agent import RunOutput
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
@dataclass
|
|
@@ -13,16 +17,69 @@ class OpenRouter(OpenAILike):
|
|
|
13
17
|
Attributes:
|
|
14
18
|
id (str): The model id. Defaults to "gpt-4o".
|
|
15
19
|
name (str): The model name. Defaults to "OpenRouter".
|
|
16
|
-
provider (str): The provider name. Defaults to "OpenRouter
|
|
17
|
-
api_key (Optional[str]): The API key.
|
|
20
|
+
provider (str): The provider name. Defaults to "OpenRouter".
|
|
21
|
+
api_key (Optional[str]): The API key.
|
|
18
22
|
base_url (str): The base URL. Defaults to "https://openrouter.ai/api/v1".
|
|
19
23
|
max_tokens (int): The maximum number of tokens. Defaults to 1024.
|
|
24
|
+
fallback_models (Optional[List[str]]): List of fallback model IDs to use if the primary model
|
|
25
|
+
fails due to rate limits, timeouts, or unavailability. OpenRouter will automatically try
|
|
26
|
+
these models in order. Example: ["anthropic/claude-sonnet-4", "deepseek/deepseek-r1"]
|
|
20
27
|
"""
|
|
21
28
|
|
|
22
29
|
id: str = "gpt-4o"
|
|
23
30
|
name: str = "OpenRouter"
|
|
24
|
-
provider: str = "OpenRouter
|
|
31
|
+
provider: str = "OpenRouter"
|
|
25
32
|
|
|
26
|
-
api_key: Optional[str] =
|
|
33
|
+
api_key: Optional[str] = None
|
|
27
34
|
base_url: str = "https://openrouter.ai/api/v1"
|
|
28
35
|
max_tokens: int = 1024
|
|
36
|
+
models: Optional[List[str]] = None # Dynamic model routing https://openrouter.ai/docs/features/model-routing
|
|
37
|
+
|
|
38
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
39
|
+
"""
|
|
40
|
+
Returns client parameters for API requests, checking for OPENROUTER_API_KEY.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dict[str, Any]: A dictionary of client parameters for API requests.
|
|
44
|
+
"""
|
|
45
|
+
# Fetch API key from env if not already set
|
|
46
|
+
if not self.api_key:
|
|
47
|
+
self.api_key = getenv("OPENROUTER_API_KEY")
|
|
48
|
+
if not self.api_key:
|
|
49
|
+
raise ModelAuthenticationError(
|
|
50
|
+
message="OPENROUTER_API_KEY not set. Please set the OPENROUTER_API_KEY environment variable.",
|
|
51
|
+
model_name=self.name,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return super()._get_client_params()
|
|
55
|
+
|
|
56
|
+
def get_request_params(
|
|
57
|
+
self,
|
|
58
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
59
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
60
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
61
|
+
run_response: Optional[RunOutput] = None,
|
|
62
|
+
) -> Dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Returns keyword arguments for API requests, including fallback models configuration.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Dict[str, Any]: A dictionary of keyword arguments for API requests.
|
|
68
|
+
"""
|
|
69
|
+
# Get base request params from parent class
|
|
70
|
+
request_params = super().get_request_params(
|
|
71
|
+
response_format=response_format, tools=tools, tool_choice=tool_choice, run_response=run_response
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Add fallback models to extra_body if specified
|
|
75
|
+
if self.models:
|
|
76
|
+
# Get existing extra_body or create new dict
|
|
77
|
+
extra_body = request_params.get("extra_body") or {}
|
|
78
|
+
|
|
79
|
+
# Merge fallback models into extra_body
|
|
80
|
+
extra_body["models"] = self.models
|
|
81
|
+
|
|
82
|
+
# Update request params
|
|
83
|
+
request_params["extra_body"] = extra_body
|
|
84
|
+
|
|
85
|
+
return request_params
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, Optional, Type, Union
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from agno.exceptions import ModelAuthenticationError, ModelProviderError
|
|
8
|
+
from agno.models.message import Citations, UrlCitation
|
|
9
|
+
from agno.models.metrics import Metrics
|
|
10
|
+
from agno.models.response import ModelResponse
|
|
11
|
+
from agno.utils.log import log_debug, log_warning
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from openai.types.chat.chat_completion import ChatCompletion
|
|
15
|
+
from openai.types.chat.chat_completion_chunk import (
|
|
16
|
+
ChatCompletionChunk,
|
|
17
|
+
ChoiceDelta,
|
|
18
|
+
)
|
|
19
|
+
from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
|
|
20
|
+
from openai.types.completion_usage import CompletionUsage
|
|
21
|
+
except ModuleNotFoundError:
|
|
22
|
+
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
23
|
+
|
|
24
|
+
from agno.models.openai.like import OpenAILike
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Perplexity(OpenAILike):
|
|
29
|
+
"""
|
|
30
|
+
A class for using models hosted on Perplexity.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
id (str): The model id. Defaults to "sonar".
|
|
34
|
+
name (str): The model name. Defaults to "Perplexity".
|
|
35
|
+
provider (str): The provider name. Defaults to "Perplexity".
|
|
36
|
+
api_key (Optional[str]): The API key.
|
|
37
|
+
base_url (str): The base URL. Defaults to "https://api.perplexity.ai/chat/completions".
|
|
38
|
+
max_tokens (int): The maximum number of tokens. Defaults to 1024.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
id: str = "sonar"
|
|
42
|
+
name: str = "Perplexity"
|
|
43
|
+
provider: str = "Perplexity"
|
|
44
|
+
|
|
45
|
+
api_key: Optional[str] = field(default_factory=lambda: getenv("PERPLEXITY_API_KEY"))
|
|
46
|
+
base_url: str = "https://api.perplexity.ai/"
|
|
47
|
+
max_tokens: int = 1024
|
|
48
|
+
top_k: Optional[float] = None
|
|
49
|
+
|
|
50
|
+
supports_native_structured_outputs: bool = False
|
|
51
|
+
supports_json_schema_outputs: bool = True
|
|
52
|
+
|
|
53
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
54
|
+
"""
|
|
55
|
+
Returns client parameters for API requests, checking for PERPLEXITY_API_KEY.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Dict[str, Any]: A dictionary of client parameters for API requests.
|
|
59
|
+
"""
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
self.api_key = getenv("PERPLEXITY_API_KEY")
|
|
62
|
+
if not self.api_key:
|
|
63
|
+
raise ModelAuthenticationError(
|
|
64
|
+
message="PERPLEXITY_API_KEY not set. Please set the PERPLEXITY_API_KEY environment variable.",
|
|
65
|
+
model_name=self.name,
|
|
66
|
+
)
|
|
67
|
+
return super()._get_client_params()
|
|
68
|
+
|
|
69
|
+
def get_request_params(
|
|
70
|
+
self,
|
|
71
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
72
|
+
**kwargs: Any,
|
|
73
|
+
) -> Dict[str, Any]:
|
|
74
|
+
"""
|
|
75
|
+
Returns keyword arguments for API requests.
|
|
76
|
+
"""
|
|
77
|
+
# Define base request parameters
|
|
78
|
+
base_params: Dict[str, Any] = {
|
|
79
|
+
"max_tokens": self.max_tokens,
|
|
80
|
+
"temperature": self.temperature,
|
|
81
|
+
"top_p": self.top_p,
|
|
82
|
+
"top_k": self.top_k,
|
|
83
|
+
"presence_penalty": self.presence_penalty,
|
|
84
|
+
"frequency_penalty": self.frequency_penalty,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if response_format is not None:
|
|
88
|
+
base_params["response_format"] = response_format
|
|
89
|
+
|
|
90
|
+
# Filter out None values
|
|
91
|
+
request_params = {k: v for k, v in base_params.items() if v is not None}
|
|
92
|
+
# Add additional request params if provided
|
|
93
|
+
if self.request_params:
|
|
94
|
+
request_params.update(self.request_params)
|
|
95
|
+
|
|
96
|
+
if request_params:
|
|
97
|
+
log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
|
|
98
|
+
return request_params
|
|
99
|
+
|
|
100
|
+
def parse_provider_response(self, response: Union[ChatCompletion, ParsedChatCompletion], **kwargs) -> ModelResponse:
|
|
101
|
+
"""
|
|
102
|
+
Parse the Perplexity response into a ModelResponse.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
response: Response from invoke() method
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
ModelResponse: Parsed response data
|
|
109
|
+
"""
|
|
110
|
+
model_response = ModelResponse()
|
|
111
|
+
|
|
112
|
+
if hasattr(response, "error") and response.error:
|
|
113
|
+
raise ModelProviderError(
|
|
114
|
+
message=response.error.get("message", "Unknown model error"),
|
|
115
|
+
model_name=self.name,
|
|
116
|
+
model_id=self.id,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Get response message
|
|
120
|
+
response_message = response.choices[0].message
|
|
121
|
+
|
|
122
|
+
# Add role
|
|
123
|
+
if response_message.role is not None:
|
|
124
|
+
model_response.role = response_message.role
|
|
125
|
+
|
|
126
|
+
# Add content
|
|
127
|
+
if response_message.content is not None:
|
|
128
|
+
model_response.content = response_message.content
|
|
129
|
+
|
|
130
|
+
# Add tool calls
|
|
131
|
+
if response_message.tool_calls is not None and len(response_message.tool_calls) > 0:
|
|
132
|
+
try:
|
|
133
|
+
model_response.tool_calls = [t.model_dump() for t in response_message.tool_calls]
|
|
134
|
+
except Exception as e:
|
|
135
|
+
log_warning(f"Error processing tool calls: {e}")
|
|
136
|
+
|
|
137
|
+
# Add citations if present
|
|
138
|
+
if hasattr(response, "citations") and response.citations is not None:
|
|
139
|
+
model_response.citations = Citations(
|
|
140
|
+
urls=[UrlCitation(url=c) for c in response.citations],
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if response.usage is not None:
|
|
144
|
+
model_response.response_usage = self._get_metrics(response.usage)
|
|
145
|
+
|
|
146
|
+
return model_response
|
|
147
|
+
|
|
148
|
+
def parse_provider_response_delta(self, response_delta: ChatCompletionChunk) -> ModelResponse:
|
|
149
|
+
"""
|
|
150
|
+
Parse the Perplexity streaming response into a ModelResponse.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
response_delta: Raw response chunk from Perplexity
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
ProviderResponse: Iterator of parsed response data
|
|
157
|
+
"""
|
|
158
|
+
model_response = ModelResponse()
|
|
159
|
+
if response_delta.choices and len(response_delta.choices) > 0:
|
|
160
|
+
choice_delta: ChoiceDelta = response_delta.choices[0].delta
|
|
161
|
+
|
|
162
|
+
if choice_delta:
|
|
163
|
+
# Add content
|
|
164
|
+
if choice_delta.content is not None:
|
|
165
|
+
model_response.content = choice_delta.content
|
|
166
|
+
|
|
167
|
+
# Add tool calls
|
|
168
|
+
if choice_delta.tool_calls is not None:
|
|
169
|
+
model_response.tool_calls = choice_delta.tool_calls # type: ignore
|
|
170
|
+
|
|
171
|
+
# Add citations if present
|
|
172
|
+
if hasattr(response_delta, "citations") and response_delta.citations is not None:
|
|
173
|
+
model_response.citations = Citations(
|
|
174
|
+
urls=[UrlCitation(url=c) for c in response_delta.citations],
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Add usage metrics if present
|
|
178
|
+
if response_delta.usage is not None:
|
|
179
|
+
model_response.response_usage = self._get_metrics(response_delta.usage)
|
|
180
|
+
|
|
181
|
+
return model_response
|
|
182
|
+
|
|
183
|
+
def _get_metrics(self, response_usage: CompletionUsage) -> Metrics:
|
|
184
|
+
"""
|
|
185
|
+
Parse the given Perplexity usage into an Agno Metrics object.
|
|
186
|
+
"""
|
|
187
|
+
metrics = Metrics()
|
|
188
|
+
|
|
189
|
+
metrics.input_tokens = response_usage.prompt_tokens or 0
|
|
190
|
+
metrics.output_tokens = response_usage.completion_tokens or 0
|
|
191
|
+
metrics.total_tokens = response_usage.total_tokens or 0
|
|
192
|
+
|
|
193
|
+
# Add the prompt_tokens_details field
|
|
194
|
+
if prompt_token_details := response_usage.prompt_tokens_details:
|
|
195
|
+
metrics.audio_input_tokens = prompt_token_details.audio_tokens or 0
|
|
196
|
+
metrics.cache_read_tokens = prompt_token_details.cached_tokens or 0
|
|
197
|
+
|
|
198
|
+
# Add the completion_tokens_details field
|
|
199
|
+
if completion_tokens_details := response_usage.completion_tokens_details:
|
|
200
|
+
metrics.audio_output_tokens = completion_tokens_details.audio_tokens or 0
|
|
201
|
+
metrics.reasoning_tokens = completion_tokens_details.reasoning_tokens or 0
|
|
202
|
+
|
|
203
|
+
return metrics
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, Optional, cast
|
|
4
|
+
|
|
5
|
+
from agno.exceptions import ModelAuthenticationError
|
|
6
|
+
from agno.models.openai.like import OpenAILike
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError("`portkey-ai` not installed. Please install using `pip install portkey-ai`")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class Portkey(OpenAILike):
|
|
16
|
+
"""
|
|
17
|
+
A class for using models through the Portkey AI Gateway.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
id (str): The model id. Defaults to "gpt-4o-mini".
|
|
21
|
+
name (str): The model name. Defaults to "Portkey".
|
|
22
|
+
provider (str): The provider name. Defaults to "Portkey".
|
|
23
|
+
portkey_api_key (Optional[str]): The Portkey API key.
|
|
24
|
+
virtual_key (Optional[str]): The virtual key for model routing.
|
|
25
|
+
config (Optional[Dict[str, Any]]): Portkey configuration for routing, retries, etc.
|
|
26
|
+
base_url (str): The Portkey gateway URL.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
id: str = "gpt-4o-mini"
|
|
30
|
+
name: str = "Portkey"
|
|
31
|
+
provider: str = "Portkey"
|
|
32
|
+
|
|
33
|
+
portkey_api_key: Optional[str] = None
|
|
34
|
+
virtual_key: Optional[str] = None
|
|
35
|
+
config: Optional[Dict[str, Any]] = None
|
|
36
|
+
base_url: str = PORTKEY_GATEWAY_URL
|
|
37
|
+
|
|
38
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
39
|
+
# Check for required keys
|
|
40
|
+
if not self.portkey_api_key:
|
|
41
|
+
raise ModelAuthenticationError(
|
|
42
|
+
message="PORTKEY_API_KEY not set. Please set the PORTKEY_API_KEY environment variable.",
|
|
43
|
+
model_name=self.name,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
self.virtual_key = self.virtual_key or getenv("PORTKEY_VIRTUAL_KEY")
|
|
47
|
+
|
|
48
|
+
# Create headers using Portkey's createHeaders function
|
|
49
|
+
header_params: Dict[str, Any] = {
|
|
50
|
+
"api_key": self.portkey_api_key,
|
|
51
|
+
"virtual_key": self.virtual_key,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if self.config is not None:
|
|
55
|
+
header_params["config"] = self.config
|
|
56
|
+
|
|
57
|
+
portkey_headers = cast(Dict[str, Any], createHeaders(**header_params))
|
|
58
|
+
|
|
59
|
+
# Merge with any existing default headers
|
|
60
|
+
default_headers: Dict[str, Any] = {}
|
|
61
|
+
if self.default_headers and isinstance(self.default_headers, dict):
|
|
62
|
+
default_headers.update(self.default_headers)
|
|
63
|
+
default_headers.update(portkey_headers)
|
|
64
|
+
|
|
65
|
+
# Define base client params
|
|
66
|
+
base_params = {
|
|
67
|
+
"api_key": "not-needed", # We use virtual keys instead
|
|
68
|
+
"organization": self.organization,
|
|
69
|
+
"base_url": self.base_url,
|
|
70
|
+
"timeout": self.timeout,
|
|
71
|
+
"max_retries": self.max_retries,
|
|
72
|
+
"default_headers": default_headers,
|
|
73
|
+
"default_query": self.default_query,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Create client_params dict with non-None values
|
|
77
|
+
client_params = {k: v for k, v in base_params.items() if v is not None}
|
|
78
|
+
|
|
79
|
+
# Add additional client params if provided
|
|
80
|
+
if self.client_params:
|
|
81
|
+
client_params.update(self.client_params)
|
|
82
|
+
return client_params
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from agno.exceptions import ModelAuthenticationError
|
|
8
|
+
from agno.models.openai.like import OpenAILike
|
|
9
|
+
from agno.run.agent import RunOutput
|
|
10
|
+
from agno.run.team import TeamRunOutput
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class Requesty(OpenAILike):
|
|
15
|
+
"""
|
|
16
|
+
A class for using models hosted on Requesty.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
id (str): The model id. Defaults to "openai/gpt-4.1".
|
|
20
|
+
provider (str): The provider name. Defaults to "Requesty".
|
|
21
|
+
api_key (Optional[str]): The API key.
|
|
22
|
+
base_url (str): The base URL. Defaults to "https://router.requesty.ai/v1".
|
|
23
|
+
max_tokens (int): The maximum number of tokens. Defaults to 1024.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
id: str = "openai/gpt-4.1"
|
|
27
|
+
name: str = "Requesty"
|
|
28
|
+
provider: str = "Requesty"
|
|
29
|
+
|
|
30
|
+
api_key: Optional[str] = None
|
|
31
|
+
base_url: str = "https://router.requesty.ai/v1"
|
|
32
|
+
max_tokens: int = 1024
|
|
33
|
+
|
|
34
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
35
|
+
"""
|
|
36
|
+
Returns client parameters for API requests, checking for REQUESTY_API_KEY.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dict[str, Any]: A dictionary of client parameters for API requests.
|
|
40
|
+
"""
|
|
41
|
+
if not self.api_key:
|
|
42
|
+
self.api_key = getenv("REQUESTY_API_KEY")
|
|
43
|
+
if not self.api_key:
|
|
44
|
+
raise ModelAuthenticationError(
|
|
45
|
+
message="REQUESTY_API_KEY not set. Please set the REQUESTY_API_KEY environment variable.",
|
|
46
|
+
model_name=self.name,
|
|
47
|
+
)
|
|
48
|
+
return super()._get_client_params()
|
|
49
|
+
|
|
50
|
+
def get_request_params(
|
|
51
|
+
self,
|
|
52
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
53
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
54
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
55
|
+
run_response: Optional[Union[RunOutput, TeamRunOutput]] = None,
|
|
56
|
+
) -> Dict[str, Any]:
|
|
57
|
+
params = super().get_request_params(
|
|
58
|
+
response_format=response_format, tools=tools, tool_choice=tool_choice, run_response=run_response
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if "extra_body" not in params:
|
|
62
|
+
params["extra_body"] = {}
|
|
63
|
+
params["extra_body"]["requesty"] = {}
|
|
64
|
+
if run_response and run_response.user_id:
|
|
65
|
+
params["extra_body"]["requesty"]["user_id"] = run_response.user_id
|
|
66
|
+
if run_response and run_response.session_id:
|
|
67
|
+
params["extra_body"]["requesty"]["trace_id"] = run_response.session_id
|
|
68
|
+
|
|
69
|
+
return params
|
agno/models/response.py
CHANGED
|
@@ -1,31 +1,201 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
1
|
+
from dataclasses import asdict, dataclass, field
|
|
2
2
|
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
|
|
6
|
+
from agno.media import Audio, File, Image, Video
|
|
7
|
+
from agno.models.message import Citations
|
|
8
|
+
from agno.models.metrics import Metrics
|
|
9
|
+
from agno.tools.function import UserInputField
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class ModelResponseEvent(str, Enum):
|
|
10
|
-
"""Events that can be sent by the
|
|
13
|
+
"""Events that can be sent by the model provider"""
|
|
11
14
|
|
|
15
|
+
tool_call_paused = "ToolCallPaused"
|
|
12
16
|
tool_call_started = "ToolCallStarted"
|
|
13
17
|
tool_call_completed = "ToolCallCompleted"
|
|
14
18
|
assistant_response = "AssistantResponse"
|
|
15
19
|
|
|
16
20
|
|
|
21
|
+
@dataclass
|
|
22
|
+
class ToolExecution:
|
|
23
|
+
"""Execution of a tool"""
|
|
24
|
+
|
|
25
|
+
tool_call_id: Optional[str] = None
|
|
26
|
+
tool_name: Optional[str] = None
|
|
27
|
+
tool_args: Optional[Dict[str, Any]] = None
|
|
28
|
+
tool_call_error: Optional[bool] = None
|
|
29
|
+
result: Optional[str] = None
|
|
30
|
+
metrics: Optional[Metrics] = None
|
|
31
|
+
|
|
32
|
+
# In the case where a tool call creates a run of an agent/team/workflow
|
|
33
|
+
child_run_id: Optional[str] = None
|
|
34
|
+
|
|
35
|
+
# If True, the agent will stop executing after this tool call.
|
|
36
|
+
stop_after_tool_call: bool = False
|
|
37
|
+
|
|
38
|
+
created_at: int = field(default_factory=lambda: int(time()))
|
|
39
|
+
|
|
40
|
+
# User control flow (HITL) fields
|
|
41
|
+
requires_confirmation: Optional[bool] = None
|
|
42
|
+
confirmed: Optional[bool] = None
|
|
43
|
+
confirmation_note: Optional[str] = None
|
|
44
|
+
|
|
45
|
+
requires_user_input: Optional[bool] = None
|
|
46
|
+
user_input_schema: Optional[List[UserInputField]] = None
|
|
47
|
+
answered: Optional[bool] = None
|
|
48
|
+
|
|
49
|
+
external_execution_required: Optional[bool] = None
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def is_paused(self) -> bool:
|
|
53
|
+
return bool(self.requires_confirmation or self.requires_user_input or self.external_execution_required)
|
|
54
|
+
|
|
55
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
56
|
+
_dict = asdict(self)
|
|
57
|
+
if self.metrics is not None:
|
|
58
|
+
_dict["metrics"] = self.metrics.to_dict()
|
|
59
|
+
|
|
60
|
+
if self.user_input_schema is not None:
|
|
61
|
+
_dict["user_input_schema"] = [field.to_dict() for field in self.user_input_schema]
|
|
62
|
+
|
|
63
|
+
return _dict
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ToolExecution":
|
|
67
|
+
return cls(
|
|
68
|
+
tool_call_id=data.get("tool_call_id"),
|
|
69
|
+
tool_name=data.get("tool_name"),
|
|
70
|
+
tool_args=data.get("tool_args"),
|
|
71
|
+
tool_call_error=data.get("tool_call_error"),
|
|
72
|
+
result=data.get("result"),
|
|
73
|
+
child_run_id=data.get("child_run_id"),
|
|
74
|
+
stop_after_tool_call=data.get("stop_after_tool_call", False),
|
|
75
|
+
requires_confirmation=data.get("requires_confirmation"),
|
|
76
|
+
confirmed=data.get("confirmed"),
|
|
77
|
+
confirmation_note=data.get("confirmation_note"),
|
|
78
|
+
requires_user_input=data.get("requires_user_input"),
|
|
79
|
+
user_input_schema=[UserInputField.from_dict(field) for field in data.get("user_input_schema") or []]
|
|
80
|
+
if "user_input_schema" in data
|
|
81
|
+
else None,
|
|
82
|
+
external_execution_required=data.get("external_execution_required"),
|
|
83
|
+
metrics=Metrics(**(data.get("metrics", {}) or {})),
|
|
84
|
+
**{"created_at": data["created_at"]} if "created_at" in data else {},
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
17
88
|
@dataclass
|
|
18
89
|
class ModelResponse:
|
|
19
|
-
"""Response
|
|
90
|
+
"""Response from the model provider"""
|
|
91
|
+
|
|
92
|
+
role: Optional[str] = None
|
|
20
93
|
|
|
21
|
-
content: Optional[
|
|
94
|
+
content: Optional[Any] = None
|
|
22
95
|
parsed: Optional[Any] = None
|
|
23
|
-
audio: Optional[
|
|
24
|
-
|
|
96
|
+
audio: Optional[Audio] = None
|
|
97
|
+
|
|
98
|
+
# Unified media fields for LLM-generated and tool-generated media artifacts
|
|
99
|
+
images: Optional[List[Image]] = None
|
|
100
|
+
videos: Optional[List[Video]] = None
|
|
101
|
+
audios: Optional[List[Audio]] = None
|
|
102
|
+
files: Optional[List[File]] = None
|
|
103
|
+
|
|
104
|
+
# Model tool calls
|
|
105
|
+
tool_calls: List[Dict[str, Any]] = field(default_factory=list)
|
|
106
|
+
|
|
107
|
+
# Actual tool executions
|
|
108
|
+
tool_executions: Optional[List[ToolExecution]] = field(default_factory=list)
|
|
109
|
+
|
|
25
110
|
event: str = ModelResponseEvent.assistant_response.value
|
|
111
|
+
|
|
112
|
+
provider_data: Optional[Dict[str, Any]] = None
|
|
113
|
+
|
|
114
|
+
redacted_reasoning_content: Optional[str] = None
|
|
115
|
+
reasoning_content: Optional[str] = None
|
|
116
|
+
|
|
117
|
+
citations: Optional[Citations] = None
|
|
118
|
+
|
|
119
|
+
response_usage: Optional[Metrics] = None
|
|
120
|
+
|
|
26
121
|
created_at: int = int(time())
|
|
27
122
|
|
|
123
|
+
extra: Optional[Dict[str, Any]] = None
|
|
124
|
+
|
|
125
|
+
updated_session_state: Optional[Dict[str, Any]] = None
|
|
126
|
+
|
|
127
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
128
|
+
"""Serialize ModelResponse to dictionary for caching."""
|
|
129
|
+
_dict = asdict(self)
|
|
130
|
+
|
|
131
|
+
# Handle special serialization for audio
|
|
132
|
+
if self.audio is not None:
|
|
133
|
+
_dict["audio"] = self.audio.to_dict()
|
|
134
|
+
|
|
135
|
+
# Handle lists of media objects
|
|
136
|
+
if self.images is not None:
|
|
137
|
+
_dict["images"] = [img.to_dict() for img in self.images]
|
|
138
|
+
if self.videos is not None:
|
|
139
|
+
_dict["videos"] = [vid.to_dict() for vid in self.videos]
|
|
140
|
+
if self.audios is not None:
|
|
141
|
+
_dict["audios"] = [aud.to_dict() for aud in self.audios]
|
|
142
|
+
if self.files is not None:
|
|
143
|
+
_dict["files"] = [f.to_dict() for f in self.files]
|
|
144
|
+
|
|
145
|
+
# Handle tool executions
|
|
146
|
+
if self.tool_executions is not None:
|
|
147
|
+
_dict["tool_executions"] = [tool_execution.to_dict() for tool_execution in self.tool_executions]
|
|
148
|
+
|
|
149
|
+
# Handle response usage which might be a Pydantic BaseModel
|
|
150
|
+
response_usage = _dict.pop("response_usage", None)
|
|
151
|
+
if response_usage is not None:
|
|
152
|
+
try:
|
|
153
|
+
from pydantic import BaseModel
|
|
154
|
+
|
|
155
|
+
if isinstance(response_usage, BaseModel):
|
|
156
|
+
_dict["response_usage"] = response_usage.model_dump()
|
|
157
|
+
else:
|
|
158
|
+
_dict["response_usage"] = response_usage
|
|
159
|
+
except ImportError:
|
|
160
|
+
_dict["response_usage"] = response_usage
|
|
161
|
+
|
|
162
|
+
return _dict
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ModelResponse":
|
|
166
|
+
"""Reconstruct ModelResponse from cached dictionary."""
|
|
167
|
+
# Reconstruct media objects
|
|
168
|
+
if data.get("audio"):
|
|
169
|
+
data["audio"] = Audio(**data["audio"])
|
|
170
|
+
|
|
171
|
+
if data.get("images"):
|
|
172
|
+
data["images"] = [Image(**img) for img in data["images"]]
|
|
173
|
+
if data.get("videos"):
|
|
174
|
+
data["videos"] = [Video(**vid) for vid in data["videos"]]
|
|
175
|
+
if data.get("audios"):
|
|
176
|
+
data["audios"] = [Audio(**aud) for aud in data["audios"]]
|
|
177
|
+
if data.get("files"):
|
|
178
|
+
data["files"] = [File(**f) for f in data["files"]]
|
|
179
|
+
|
|
180
|
+
# Reconstruct tool executions
|
|
181
|
+
if data.get("tool_executions"):
|
|
182
|
+
data["tool_executions"] = [ToolExecution.from_dict(te) for te in data["tool_executions"]]
|
|
183
|
+
|
|
184
|
+
# Reconstruct citations
|
|
185
|
+
if data.get("citations") and isinstance(data["citations"], dict):
|
|
186
|
+
data["citations"] = Citations(**data["citations"])
|
|
187
|
+
|
|
188
|
+
# Reconstruct response usage (Metrics)
|
|
189
|
+
if data.get("response_usage") and isinstance(data["response_usage"], dict):
|
|
190
|
+
from agno.models.metrics import Metrics
|
|
191
|
+
|
|
192
|
+
data["response_usage"] = Metrics(**data["response_usage"])
|
|
193
|
+
|
|
194
|
+
return cls(**data)
|
|
195
|
+
|
|
28
196
|
|
|
29
197
|
class FileType(str, Enum):
|
|
30
198
|
MP4 = "mp4"
|
|
31
199
|
GIF = "gif"
|
|
200
|
+
MP3 = "mp3"
|
|
201
|
+
WAV = "wav"
|