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
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from copy import deepcopy
|
|
3
|
+
from typing import List, Optional, Union, cast
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
6
|
+
|
|
7
|
+
from agno.agent.agent import Agent
|
|
8
|
+
from agno.db.base import AsyncBaseDb, BaseDb
|
|
9
|
+
from agno.db.schemas.evals import EvalFilterType, EvalType
|
|
10
|
+
from agno.models.utils import get_model
|
|
11
|
+
from agno.os.auth import get_authentication_dependency
|
|
12
|
+
from agno.os.routers.evals.schemas import (
|
|
13
|
+
DeleteEvalRunsRequest,
|
|
14
|
+
EvalRunInput,
|
|
15
|
+
EvalSchema,
|
|
16
|
+
UpdateEvalRunRequest,
|
|
17
|
+
)
|
|
18
|
+
from agno.os.routers.evals.utils import (
|
|
19
|
+
run_accuracy_eval,
|
|
20
|
+
run_agent_as_judge_eval,
|
|
21
|
+
run_performance_eval,
|
|
22
|
+
run_reliability_eval,
|
|
23
|
+
)
|
|
24
|
+
from agno.os.schema import (
|
|
25
|
+
BadRequestResponse,
|
|
26
|
+
InternalServerErrorResponse,
|
|
27
|
+
NotFoundResponse,
|
|
28
|
+
PaginatedResponse,
|
|
29
|
+
PaginationInfo,
|
|
30
|
+
SortOrder,
|
|
31
|
+
UnauthenticatedResponse,
|
|
32
|
+
ValidationErrorResponse,
|
|
33
|
+
)
|
|
34
|
+
from agno.os.settings import AgnoAPISettings
|
|
35
|
+
from agno.os.utils import get_agent_by_id, get_db, get_team_by_id
|
|
36
|
+
from agno.team.team import Team
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_eval_router(
|
|
42
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
43
|
+
agents: Optional[List[Agent]] = None,
|
|
44
|
+
teams: Optional[List[Team]] = None,
|
|
45
|
+
settings: AgnoAPISettings = AgnoAPISettings(),
|
|
46
|
+
) -> APIRouter:
|
|
47
|
+
"""Create eval router with comprehensive OpenAPI documentation for agent/team evaluation endpoints."""
|
|
48
|
+
router = APIRouter(
|
|
49
|
+
dependencies=[Depends(get_authentication_dependency(settings))],
|
|
50
|
+
tags=["Evals"],
|
|
51
|
+
responses={
|
|
52
|
+
400: {"description": "Bad Request", "model": BadRequestResponse},
|
|
53
|
+
401: {"description": "Unauthorized", "model": UnauthenticatedResponse},
|
|
54
|
+
404: {"description": "Not Found", "model": NotFoundResponse},
|
|
55
|
+
422: {"description": "Validation Error", "model": ValidationErrorResponse},
|
|
56
|
+
500: {"description": "Internal Server Error", "model": InternalServerErrorResponse},
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
return attach_routes(router=router, dbs=dbs, agents=agents, teams=teams)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def attach_routes(
|
|
63
|
+
router: APIRouter,
|
|
64
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
65
|
+
agents: Optional[List[Agent]] = None,
|
|
66
|
+
teams: Optional[List[Team]] = None,
|
|
67
|
+
) -> APIRouter:
|
|
68
|
+
@router.get(
|
|
69
|
+
"/eval-runs",
|
|
70
|
+
response_model=PaginatedResponse[EvalSchema],
|
|
71
|
+
status_code=200,
|
|
72
|
+
operation_id="get_eval_runs",
|
|
73
|
+
summary="List Evaluation Runs",
|
|
74
|
+
description=(
|
|
75
|
+
"Retrieve paginated evaluation runs with filtering and sorting options. "
|
|
76
|
+
"Filter by agent, team, workflow, model, or evaluation type."
|
|
77
|
+
),
|
|
78
|
+
responses={
|
|
79
|
+
200: {
|
|
80
|
+
"description": "Evaluation runs retrieved successfully",
|
|
81
|
+
"content": {
|
|
82
|
+
"application/json": {
|
|
83
|
+
"example": {
|
|
84
|
+
"data": [
|
|
85
|
+
{
|
|
86
|
+
"id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
|
|
87
|
+
"agent_id": "basic-agent",
|
|
88
|
+
"model_id": "gpt-4o",
|
|
89
|
+
"model_provider": "OpenAI",
|
|
90
|
+
"team_id": None,
|
|
91
|
+
"workflow_id": None,
|
|
92
|
+
"name": "Test ",
|
|
93
|
+
"evaluated_component_name": None,
|
|
94
|
+
"eval_type": "reliability",
|
|
95
|
+
"eval_data": {
|
|
96
|
+
"eval_status": "PASSED",
|
|
97
|
+
"failed_tool_calls": [],
|
|
98
|
+
"passed_tool_calls": ["multiply"],
|
|
99
|
+
},
|
|
100
|
+
"eval_input": {"expected_tool_calls": ["multiply"]},
|
|
101
|
+
"created_at": "2025-08-27T15:41:59Z",
|
|
102
|
+
"updated_at": "2025-08-27T15:41:59Z",
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
async def get_eval_runs(
|
|
112
|
+
agent_id: Optional[str] = Query(default=None, description="Agent ID"),
|
|
113
|
+
team_id: Optional[str] = Query(default=None, description="Team ID"),
|
|
114
|
+
workflow_id: Optional[str] = Query(default=None, description="Workflow ID"),
|
|
115
|
+
model_id: Optional[str] = Query(default=None, description="Model ID"),
|
|
116
|
+
filter_type: Optional[EvalFilterType] = Query(default=None, description="Filter type", alias="type"),
|
|
117
|
+
eval_types: Optional[List[EvalType]] = Depends(parse_eval_types_filter),
|
|
118
|
+
limit: Optional[int] = Query(default=20, description="Number of eval runs to return"),
|
|
119
|
+
page: Optional[int] = Query(default=1, description="Page number"),
|
|
120
|
+
sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
|
|
121
|
+
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
122
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
123
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
124
|
+
) -> PaginatedResponse[EvalSchema]:
|
|
125
|
+
db = await get_db(dbs, db_id, table)
|
|
126
|
+
|
|
127
|
+
# TODO: Delete me:
|
|
128
|
+
# Filtering out agent-as-judge by default for now,
|
|
129
|
+
# as they are not supported yet in the AgentOS UI.
|
|
130
|
+
eval_types = eval_types or [
|
|
131
|
+
EvalType.ACCURACY,
|
|
132
|
+
EvalType.PERFORMANCE,
|
|
133
|
+
EvalType.RELIABILITY,
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
if isinstance(db, AsyncBaseDb):
|
|
137
|
+
db = cast(AsyncBaseDb, db)
|
|
138
|
+
eval_runs, total_count = await db.get_eval_runs(
|
|
139
|
+
limit=limit,
|
|
140
|
+
page=page,
|
|
141
|
+
sort_by=sort_by,
|
|
142
|
+
sort_order=sort_order,
|
|
143
|
+
agent_id=agent_id,
|
|
144
|
+
team_id=team_id,
|
|
145
|
+
workflow_id=workflow_id,
|
|
146
|
+
model_id=model_id,
|
|
147
|
+
eval_type=eval_types,
|
|
148
|
+
filter_type=filter_type,
|
|
149
|
+
deserialize=False,
|
|
150
|
+
)
|
|
151
|
+
else:
|
|
152
|
+
eval_runs, total_count = db.get_eval_runs( # type: ignore
|
|
153
|
+
limit=limit,
|
|
154
|
+
page=page,
|
|
155
|
+
sort_by=sort_by,
|
|
156
|
+
sort_order=sort_order,
|
|
157
|
+
agent_id=agent_id,
|
|
158
|
+
team_id=team_id,
|
|
159
|
+
workflow_id=workflow_id,
|
|
160
|
+
model_id=model_id,
|
|
161
|
+
eval_type=eval_types,
|
|
162
|
+
filter_type=filter_type,
|
|
163
|
+
deserialize=False,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return PaginatedResponse(
|
|
167
|
+
data=[EvalSchema.from_dict(eval_run) for eval_run in eval_runs], # type: ignore
|
|
168
|
+
meta=PaginationInfo(
|
|
169
|
+
page=page,
|
|
170
|
+
limit=limit,
|
|
171
|
+
total_count=total_count, # type: ignore
|
|
172
|
+
total_pages=(total_count + limit - 1) // limit if limit is not None and limit > 0 else 0, # type: ignore
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
@router.get(
|
|
177
|
+
"/eval-runs/{eval_run_id}",
|
|
178
|
+
response_model=EvalSchema,
|
|
179
|
+
status_code=200,
|
|
180
|
+
operation_id="get_eval_run",
|
|
181
|
+
summary="Get Evaluation Run",
|
|
182
|
+
description="Retrieve detailed results and metrics for a specific evaluation run.",
|
|
183
|
+
responses={
|
|
184
|
+
200: {
|
|
185
|
+
"description": "Evaluation run details retrieved successfully",
|
|
186
|
+
"content": {
|
|
187
|
+
"application/json": {
|
|
188
|
+
"example": {
|
|
189
|
+
"id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
|
|
190
|
+
"agent_id": "basic-agent",
|
|
191
|
+
"model_id": "gpt-4o",
|
|
192
|
+
"model_provider": "OpenAI",
|
|
193
|
+
"team_id": None,
|
|
194
|
+
"workflow_id": None,
|
|
195
|
+
"name": "Test ",
|
|
196
|
+
"evaluated_component_name": None,
|
|
197
|
+
"eval_type": "reliability",
|
|
198
|
+
"eval_data": {
|
|
199
|
+
"eval_status": "PASSED",
|
|
200
|
+
"failed_tool_calls": [],
|
|
201
|
+
"passed_tool_calls": ["multiply"],
|
|
202
|
+
},
|
|
203
|
+
"eval_input": {"expected_tool_calls": ["multiply"]},
|
|
204
|
+
"created_at": "2025-08-27T15:41:59Z",
|
|
205
|
+
"updated_at": "2025-08-27T15:41:59Z",
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
404: {"description": "Evaluation run not found", "model": NotFoundResponse},
|
|
211
|
+
},
|
|
212
|
+
)
|
|
213
|
+
async def get_eval_run(
|
|
214
|
+
eval_run_id: str,
|
|
215
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
216
|
+
table: Optional[str] = Query(default=None, description="Table to query eval run from"),
|
|
217
|
+
) -> EvalSchema:
|
|
218
|
+
db = await get_db(dbs, db_id, table)
|
|
219
|
+
if isinstance(db, AsyncBaseDb):
|
|
220
|
+
db = cast(AsyncBaseDb, db)
|
|
221
|
+
eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
|
|
222
|
+
else:
|
|
223
|
+
eval_run = db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
|
|
224
|
+
if not eval_run:
|
|
225
|
+
raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
|
|
226
|
+
|
|
227
|
+
return EvalSchema.from_dict(eval_run) # type: ignore
|
|
228
|
+
|
|
229
|
+
@router.delete(
|
|
230
|
+
"/eval-runs",
|
|
231
|
+
status_code=204,
|
|
232
|
+
operation_id="delete_eval_runs",
|
|
233
|
+
summary="Delete Evaluation Runs",
|
|
234
|
+
description="Delete multiple evaluation runs by their IDs. This action cannot be undone.",
|
|
235
|
+
responses={
|
|
236
|
+
204: {},
|
|
237
|
+
500: {"description": "Failed to delete evaluation runs", "model": InternalServerErrorResponse},
|
|
238
|
+
},
|
|
239
|
+
)
|
|
240
|
+
async def delete_eval_runs(
|
|
241
|
+
request: DeleteEvalRunsRequest,
|
|
242
|
+
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
243
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
244
|
+
) -> None:
|
|
245
|
+
try:
|
|
246
|
+
db = await get_db(dbs, db_id, table)
|
|
247
|
+
if isinstance(db, AsyncBaseDb):
|
|
248
|
+
db = cast(AsyncBaseDb, db)
|
|
249
|
+
await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
|
|
250
|
+
else:
|
|
251
|
+
db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
|
|
252
|
+
except Exception as e:
|
|
253
|
+
raise HTTPException(status_code=500, detail=f"Failed to delete eval runs: {e}")
|
|
254
|
+
|
|
255
|
+
@router.patch(
|
|
256
|
+
"/eval-runs/{eval_run_id}",
|
|
257
|
+
response_model=EvalSchema,
|
|
258
|
+
status_code=200,
|
|
259
|
+
operation_id="update_eval_run",
|
|
260
|
+
summary="Update Evaluation Run",
|
|
261
|
+
description="Update the name or other properties of an existing evaluation run.",
|
|
262
|
+
responses={
|
|
263
|
+
200: {
|
|
264
|
+
"description": "Evaluation run updated successfully",
|
|
265
|
+
"content": {
|
|
266
|
+
"application/json": {
|
|
267
|
+
"example": {
|
|
268
|
+
"id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
|
|
269
|
+
"agent_id": "basic-agent",
|
|
270
|
+
"model_id": "gpt-4o",
|
|
271
|
+
"model_provider": "OpenAI",
|
|
272
|
+
"team_id": None,
|
|
273
|
+
"workflow_id": None,
|
|
274
|
+
"name": "Test ",
|
|
275
|
+
"evaluated_component_name": None,
|
|
276
|
+
"eval_type": "reliability",
|
|
277
|
+
"eval_data": {
|
|
278
|
+
"eval_status": "PASSED",
|
|
279
|
+
"failed_tool_calls": [],
|
|
280
|
+
"passed_tool_calls": ["multiply"],
|
|
281
|
+
},
|
|
282
|
+
"eval_input": {"expected_tool_calls": ["multiply"]},
|
|
283
|
+
"created_at": "2025-08-27T15:41:59Z",
|
|
284
|
+
"updated_at": "2025-08-27T15:41:59Z",
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
404: {"description": "Evaluation run not found", "model": NotFoundResponse},
|
|
290
|
+
500: {"description": "Failed to update evaluation run", "model": InternalServerErrorResponse},
|
|
291
|
+
},
|
|
292
|
+
)
|
|
293
|
+
async def update_eval_run(
|
|
294
|
+
eval_run_id: str,
|
|
295
|
+
request: UpdateEvalRunRequest,
|
|
296
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
297
|
+
table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
|
|
298
|
+
) -> EvalSchema:
|
|
299
|
+
try:
|
|
300
|
+
db = await get_db(dbs, db_id, table)
|
|
301
|
+
if isinstance(db, AsyncBaseDb):
|
|
302
|
+
db = cast(AsyncBaseDb, db)
|
|
303
|
+
eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
|
|
304
|
+
else:
|
|
305
|
+
eval_run = db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
|
|
306
|
+
except Exception as e:
|
|
307
|
+
raise HTTPException(status_code=500, detail=f"Failed to rename eval run: {e}")
|
|
308
|
+
|
|
309
|
+
if not eval_run:
|
|
310
|
+
raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
|
|
311
|
+
|
|
312
|
+
return EvalSchema.from_dict(eval_run) # type: ignore
|
|
313
|
+
|
|
314
|
+
@router.post(
|
|
315
|
+
"/eval-runs",
|
|
316
|
+
response_model=EvalSchema,
|
|
317
|
+
status_code=200,
|
|
318
|
+
operation_id="run_eval",
|
|
319
|
+
summary="Execute Evaluation",
|
|
320
|
+
description=(
|
|
321
|
+
"Run evaluation tests on agents or teams. Supports accuracy, agent-as-judge, performance, and reliability evaluations. "
|
|
322
|
+
"Requires either agent_id or team_id, but not both."
|
|
323
|
+
),
|
|
324
|
+
responses={
|
|
325
|
+
200: {
|
|
326
|
+
"description": "Evaluation executed successfully",
|
|
327
|
+
"content": {
|
|
328
|
+
"application/json": {
|
|
329
|
+
"example": {
|
|
330
|
+
"id": "f2b2d72f-e9e2-4f0e-8810-0a7e1ff58614",
|
|
331
|
+
"agent_id": "basic-agent",
|
|
332
|
+
"model_id": "gpt-4o",
|
|
333
|
+
"model_provider": "OpenAI",
|
|
334
|
+
"team_id": None,
|
|
335
|
+
"workflow_id": None,
|
|
336
|
+
"name": None,
|
|
337
|
+
"evaluated_component_name": None,
|
|
338
|
+
"eval_type": "reliability",
|
|
339
|
+
"eval_data": {
|
|
340
|
+
"eval_status": "PASSED",
|
|
341
|
+
"failed_tool_calls": [],
|
|
342
|
+
"passed_tool_calls": ["multiply"],
|
|
343
|
+
},
|
|
344
|
+
"created_at": "2025-08-27T15:41:59Z",
|
|
345
|
+
"updated_at": "2025-08-27T15:41:59Z",
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
400: {"description": "Invalid request - provide either agent_id or team_id", "model": BadRequestResponse},
|
|
351
|
+
404: {"description": "Agent or team not found", "model": NotFoundResponse},
|
|
352
|
+
},
|
|
353
|
+
)
|
|
354
|
+
async def run_eval(
|
|
355
|
+
eval_run_input: EvalRunInput,
|
|
356
|
+
db_id: Optional[str] = Query(default=None, description="Database ID to use for evaluation"),
|
|
357
|
+
table: Optional[str] = Query(default=None, description="Table to use for evaluation"),
|
|
358
|
+
) -> Optional[EvalSchema]:
|
|
359
|
+
db = await get_db(dbs, db_id, table)
|
|
360
|
+
|
|
361
|
+
if eval_run_input.agent_id and eval_run_input.team_id:
|
|
362
|
+
raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
|
|
363
|
+
|
|
364
|
+
if eval_run_input.agent_id:
|
|
365
|
+
agent = get_agent_by_id(agent_id=eval_run_input.agent_id, agents=agents)
|
|
366
|
+
if not agent:
|
|
367
|
+
raise HTTPException(status_code=404, detail=f"Agent with id '{eval_run_input.agent_id}' not found")
|
|
368
|
+
|
|
369
|
+
default_model = None
|
|
370
|
+
if (
|
|
371
|
+
hasattr(agent, "model")
|
|
372
|
+
and agent.model is not None
|
|
373
|
+
and eval_run_input.model_id is not None
|
|
374
|
+
and eval_run_input.model_provider is not None
|
|
375
|
+
):
|
|
376
|
+
default_model = deepcopy(agent.model)
|
|
377
|
+
if eval_run_input.model_id != agent.model.id or eval_run_input.model_provider != agent.model.provider:
|
|
378
|
+
model_provider = eval_run_input.model_provider.lower()
|
|
379
|
+
model_id = eval_run_input.model_id.lower()
|
|
380
|
+
model_string = f"{model_provider}:{model_id}"
|
|
381
|
+
model = get_model(model_string)
|
|
382
|
+
agent.model = model
|
|
383
|
+
|
|
384
|
+
team = None
|
|
385
|
+
|
|
386
|
+
elif eval_run_input.team_id:
|
|
387
|
+
team = get_team_by_id(team_id=eval_run_input.team_id, teams=teams)
|
|
388
|
+
if not team:
|
|
389
|
+
raise HTTPException(status_code=404, detail=f"Team with id '{eval_run_input.team_id}' not found")
|
|
390
|
+
|
|
391
|
+
# If model_id/model_provider specified, override team's model temporarily
|
|
392
|
+
default_model = None
|
|
393
|
+
if (
|
|
394
|
+
hasattr(team, "model")
|
|
395
|
+
and team.model is not None
|
|
396
|
+
and eval_run_input.model_id is not None
|
|
397
|
+
and eval_run_input.model_provider is not None
|
|
398
|
+
):
|
|
399
|
+
default_model = deepcopy(team.model) # Save original
|
|
400
|
+
if eval_run_input.model_id != team.model.id or eval_run_input.model_provider != team.model.provider:
|
|
401
|
+
model_provider = eval_run_input.model_provider.lower()
|
|
402
|
+
model_id = eval_run_input.model_id.lower()
|
|
403
|
+
model_string = f"{model_provider}:{model_id}"
|
|
404
|
+
model = get_model(model_string)
|
|
405
|
+
team.model = model # Override temporarily
|
|
406
|
+
|
|
407
|
+
agent = None
|
|
408
|
+
|
|
409
|
+
else:
|
|
410
|
+
raise HTTPException(status_code=400, detail="One of agent_id or team_id must be provided")
|
|
411
|
+
|
|
412
|
+
# Run the evaluation
|
|
413
|
+
if eval_run_input.eval_type == EvalType.ACCURACY:
|
|
414
|
+
return await run_accuracy_eval(
|
|
415
|
+
eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
elif eval_run_input.eval_type == EvalType.AGENT_AS_JUDGE:
|
|
419
|
+
return await run_agent_as_judge_eval(
|
|
420
|
+
eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
elif eval_run_input.eval_type == EvalType.PERFORMANCE:
|
|
424
|
+
return await run_performance_eval(
|
|
425
|
+
eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
else:
|
|
429
|
+
return await run_reliability_eval(
|
|
430
|
+
eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
return router
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def parse_eval_types_filter(
|
|
437
|
+
eval_types: Optional[str] = Query(
|
|
438
|
+
default=None,
|
|
439
|
+
description="Comma-separated eval types (accuracy,agent_as_judge,performance,reliability)",
|
|
440
|
+
examples=["accuracy,agent_as_judge,performance,reliability"],
|
|
441
|
+
),
|
|
442
|
+
) -> Optional[List[EvalType]]:
|
|
443
|
+
"""Parse comma-separated eval types into EvalType enums for filtering evaluation runs."""
|
|
444
|
+
if not eval_types:
|
|
445
|
+
return None
|
|
446
|
+
try:
|
|
447
|
+
return [EvalType(item.strip()) for item in eval_types.split(",")]
|
|
448
|
+
except ValueError as e:
|
|
449
|
+
valid_types = ", ".join([t.value for t in EvalType])
|
|
450
|
+
raise HTTPException(status_code=422, detail=f"Invalid eval_type: {e}. Valid types: {valid_types}")
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from dataclasses import asdict
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from agno.db.schemas.evals import EvalType
|
|
8
|
+
from agno.eval import AccuracyResult, AgentAsJudgeResult, PerformanceResult, ReliabilityResult
|
|
9
|
+
from agno.eval.accuracy import AccuracyEval
|
|
10
|
+
from agno.eval.agent_as_judge import AgentAsJudgeEval
|
|
11
|
+
from agno.eval.performance import PerformanceEval
|
|
12
|
+
from agno.eval.reliability import ReliabilityEval
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EvalRunInput(BaseModel):
|
|
16
|
+
agent_id: Optional[str] = Field(None, description="Agent ID to evaluate")
|
|
17
|
+
team_id: Optional[str] = Field(None, description="Team ID to evaluate")
|
|
18
|
+
|
|
19
|
+
model_id: Optional[str] = Field(None, description="Model ID to use for evaluation")
|
|
20
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
21
|
+
eval_type: EvalType = Field(..., description="Type of evaluation to run (accuracy, performance, or reliability)")
|
|
22
|
+
input: str = Field(..., description="Input text/query for the evaluation", min_length=1)
|
|
23
|
+
additional_guidelines: Optional[str] = Field(None, description="Additional guidelines for the evaluation")
|
|
24
|
+
additional_context: Optional[str] = Field(None, description="Additional context for the evaluation")
|
|
25
|
+
num_iterations: int = Field(1, description="Number of times to run the evaluation", ge=1, le=100)
|
|
26
|
+
name: Optional[str] = Field(None, description="Name for this evaluation run")
|
|
27
|
+
|
|
28
|
+
# Accuracy eval specific fields
|
|
29
|
+
expected_output: Optional[str] = Field(None, description="Expected output for accuracy evaluation")
|
|
30
|
+
|
|
31
|
+
# AgentAsJudge eval specific fields
|
|
32
|
+
criteria: Optional[str] = Field(None, description="Evaluation criteria for agent-as-judge evaluation")
|
|
33
|
+
scoring_strategy: Optional[Literal["numeric", "binary"]] = Field(
|
|
34
|
+
"binary", description="Scoring strategy: 'numeric' (1-10 with threshold) or 'binary' (PASS/FAIL)"
|
|
35
|
+
)
|
|
36
|
+
threshold: Optional[int] = Field(
|
|
37
|
+
7, description="Score threshold for pass/fail (1-10), only used with numeric scoring", ge=1, le=10
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Performance eval specific fields
|
|
41
|
+
warmup_runs: int = Field(0, description="Number of warmup runs before measuring performance", ge=0, le=10)
|
|
42
|
+
|
|
43
|
+
# Reliability eval specific fields
|
|
44
|
+
expected_tool_calls: Optional[List[str]] = Field(None, description="Expected tool calls for reliability evaluation")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class EvalSchema(BaseModel):
|
|
48
|
+
id: str = Field(..., description="Unique identifier for the evaluation run")
|
|
49
|
+
|
|
50
|
+
agent_id: Optional[str] = Field(None, description="Agent ID that was evaluated")
|
|
51
|
+
model_id: Optional[str] = Field(None, description="Model ID used in evaluation")
|
|
52
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
53
|
+
team_id: Optional[str] = Field(None, description="Team ID that was evaluated")
|
|
54
|
+
workflow_id: Optional[str] = Field(None, description="Workflow ID that was evaluated")
|
|
55
|
+
name: Optional[str] = Field(None, description="Name of the evaluation run")
|
|
56
|
+
evaluated_component_name: Optional[str] = Field(None, description="Name of the evaluated component")
|
|
57
|
+
eval_type: EvalType = Field(..., description="Type of evaluation (accuracy, performance, or reliability)")
|
|
58
|
+
eval_data: Dict[str, Any] = Field(..., description="Evaluation results and metrics")
|
|
59
|
+
eval_input: Optional[Dict[str, Any]] = Field(None, description="Input parameters used for the evaluation")
|
|
60
|
+
created_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was created")
|
|
61
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was last updated")
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_dict(cls, eval_run: Dict[str, Any]) -> "EvalSchema":
|
|
65
|
+
return cls(
|
|
66
|
+
id=eval_run["run_id"],
|
|
67
|
+
name=eval_run.get("name"),
|
|
68
|
+
agent_id=eval_run.get("agent_id"),
|
|
69
|
+
model_id=eval_run.get("model_id"),
|
|
70
|
+
model_provider=eval_run.get("model_provider"),
|
|
71
|
+
team_id=eval_run.get("team_id"),
|
|
72
|
+
workflow_id=eval_run.get("workflow_id"),
|
|
73
|
+
evaluated_component_name=eval_run.get("evaluated_component_name"),
|
|
74
|
+
eval_type=eval_run["eval_type"],
|
|
75
|
+
eval_data=eval_run["eval_data"],
|
|
76
|
+
eval_input=eval_run.get("eval_input"),
|
|
77
|
+
created_at=datetime.fromtimestamp(eval_run["created_at"], tz=timezone.utc),
|
|
78
|
+
updated_at=datetime.fromtimestamp(eval_run["updated_at"], tz=timezone.utc),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def from_accuracy_eval(cls, accuracy_eval: AccuracyEval, result: AccuracyResult) -> "EvalSchema":
|
|
83
|
+
model_provider = (
|
|
84
|
+
accuracy_eval.agent.model.provider
|
|
85
|
+
if accuracy_eval.agent and accuracy_eval.agent.model
|
|
86
|
+
else accuracy_eval.team.model.provider
|
|
87
|
+
if accuracy_eval.team and accuracy_eval.team.model
|
|
88
|
+
else None
|
|
89
|
+
)
|
|
90
|
+
return cls(
|
|
91
|
+
id=accuracy_eval.eval_id,
|
|
92
|
+
name=accuracy_eval.name,
|
|
93
|
+
agent_id=accuracy_eval.agent.id if accuracy_eval.agent else None,
|
|
94
|
+
team_id=accuracy_eval.team.id if accuracy_eval.team else None,
|
|
95
|
+
workflow_id=None,
|
|
96
|
+
model_id=accuracy_eval.agent.model.id if accuracy_eval.agent else accuracy_eval.team.model.id, # type: ignore
|
|
97
|
+
model_provider=model_provider,
|
|
98
|
+
eval_type=EvalType.ACCURACY,
|
|
99
|
+
eval_data=asdict(result),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def from_agent_as_judge_eval(
|
|
104
|
+
cls,
|
|
105
|
+
agent_as_judge_eval: AgentAsJudgeEval,
|
|
106
|
+
result: AgentAsJudgeResult,
|
|
107
|
+
model_id: Optional[str] = None,
|
|
108
|
+
model_provider: Optional[str] = None,
|
|
109
|
+
agent_id: Optional[str] = None,
|
|
110
|
+
team_id: Optional[str] = None,
|
|
111
|
+
) -> "EvalSchema":
|
|
112
|
+
return cls(
|
|
113
|
+
id=result.run_id,
|
|
114
|
+
name=agent_as_judge_eval.name,
|
|
115
|
+
agent_id=agent_id,
|
|
116
|
+
team_id=team_id,
|
|
117
|
+
workflow_id=None,
|
|
118
|
+
model_id=model_id,
|
|
119
|
+
model_provider=model_provider,
|
|
120
|
+
eval_type=EvalType.AGENT_AS_JUDGE,
|
|
121
|
+
eval_data=asdict(result),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def from_performance_eval(
|
|
126
|
+
cls,
|
|
127
|
+
performance_eval: PerformanceEval,
|
|
128
|
+
result: PerformanceResult,
|
|
129
|
+
model_id: Optional[str] = None,
|
|
130
|
+
model_provider: Optional[str] = None,
|
|
131
|
+
agent_id: Optional[str] = None,
|
|
132
|
+
team_id: Optional[str] = None,
|
|
133
|
+
) -> "EvalSchema":
|
|
134
|
+
return cls(
|
|
135
|
+
id=performance_eval.eval_id,
|
|
136
|
+
name=performance_eval.name,
|
|
137
|
+
agent_id=agent_id,
|
|
138
|
+
team_id=team_id,
|
|
139
|
+
workflow_id=None,
|
|
140
|
+
model_id=model_id,
|
|
141
|
+
model_provider=model_provider,
|
|
142
|
+
eval_type=EvalType.PERFORMANCE,
|
|
143
|
+
eval_data=asdict(result),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def from_reliability_eval(
|
|
148
|
+
cls,
|
|
149
|
+
reliability_eval: ReliabilityEval,
|
|
150
|
+
result: ReliabilityResult,
|
|
151
|
+
model_id: Optional[str] = None,
|
|
152
|
+
model_provider: Optional[str] = None,
|
|
153
|
+
agent_id: Optional[str] = None,
|
|
154
|
+
team_id: Optional[str] = None,
|
|
155
|
+
) -> "EvalSchema":
|
|
156
|
+
return cls(
|
|
157
|
+
id=reliability_eval.eval_id,
|
|
158
|
+
name=reliability_eval.name,
|
|
159
|
+
agent_id=agent_id,
|
|
160
|
+
team_id=team_id,
|
|
161
|
+
workflow_id=None,
|
|
162
|
+
model_id=model_id,
|
|
163
|
+
model_provider=model_provider,
|
|
164
|
+
eval_type=EvalType.RELIABILITY,
|
|
165
|
+
eval_data=asdict(result),
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class DeleteEvalRunsRequest(BaseModel):
|
|
170
|
+
eval_run_ids: List[str] = Field(..., description="List of evaluation run IDs to delete", min_length=1)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class UpdateEvalRunRequest(BaseModel):
|
|
174
|
+
name: str = Field(..., description="New name for the evaluation run", min_length=1, max_length=255)
|