agno 2.0.0rc2__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/agent.py +6009 -2874
- agno/api/api.py +2 -0
- agno/api/os.py +1 -1
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +385 -6
- agno/db/dynamo/dynamo.py +388 -81
- agno/db/dynamo/schemas.py +47 -10
- agno/db/dynamo/utils.py +63 -4
- agno/db/firestore/firestore.py +435 -64
- agno/db/firestore/schemas.py +11 -0
- agno/db/firestore/utils.py +102 -4
- agno/db/gcs_json/gcs_json_db.py +384 -42
- agno/db/gcs_json/utils.py +60 -26
- agno/db/in_memory/in_memory_db.py +351 -66
- agno/db/in_memory/utils.py +60 -2
- agno/db/json/json_db.py +339 -48
- agno/db/json/utils.py +60 -26
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +510 -37
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +2036 -0
- agno/db/mongo/mongo.py +653 -76
- agno/db/mongo/schemas.py +13 -0
- agno/db/mongo/utils.py +80 -8
- agno/db/mysql/mysql.py +687 -25
- agno/db/mysql/schemas.py +61 -37
- agno/db/mysql/utils.py +60 -2
- agno/db/postgres/__init__.py +2 -1
- agno/db/postgres/async_postgres.py +2001 -0
- agno/db/postgres/postgres.py +676 -57
- agno/db/postgres/schemas.py +43 -18
- agno/db/postgres/utils.py +164 -2
- agno/db/redis/redis.py +344 -38
- agno/db/redis/schemas.py +18 -0
- agno/db/redis/utils.py +60 -2
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/memory.py +13 -0
- agno/db/singlestore/schemas.py +26 -1
- agno/db/singlestore/singlestore.py +687 -53
- agno/db/singlestore/utils.py +60 -2
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2371 -0
- agno/db/sqlite/schemas.py +24 -0
- agno/db/sqlite/sqlite.py +774 -85
- agno/db/sqlite/utils.py +168 -5
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1361 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +50 -22
- agno/eval/accuracy.py +50 -43
- agno/eval/performance.py +6 -3
- agno/eval/reliability.py +6 -3
- agno/eval/utils.py +33 -16
- agno/exceptions.py +68 -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/integrations/discord/client.py +1 -0
- agno/knowledge/chunking/agentic.py +13 -10
- agno/knowledge/chunking/fixed.py +1 -1
- agno/knowledge/chunking/semantic.py +40 -8
- agno/knowledge/chunking/strategy.py +59 -15
- agno/knowledge/embedder/aws_bedrock.py +9 -4
- agno/knowledge/embedder/azure_openai.py +54 -0
- agno/knowledge/embedder/base.py +2 -0
- agno/knowledge/embedder/cohere.py +184 -5
- agno/knowledge/embedder/fastembed.py +1 -1
- agno/knowledge/embedder/google.py +79 -1
- agno/knowledge/embedder/huggingface.py +9 -4
- agno/knowledge/embedder/jina.py +63 -0
- agno/knowledge/embedder/mistral.py +78 -11
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/ollama.py +13 -0
- agno/knowledge/embedder/openai.py +37 -65
- agno/knowledge/embedder/sentence_transformer.py +8 -4
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +69 -16
- agno/knowledge/knowledge.py +595 -187
- agno/knowledge/reader/base.py +9 -2
- agno/knowledge/reader/csv_reader.py +8 -10
- agno/knowledge/reader/docx_reader.py +5 -6
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/json_reader.py +6 -5
- agno/knowledge/reader/markdown_reader.py +13 -13
- agno/knowledge/reader/pdf_reader.py +43 -68
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +51 -6
- agno/knowledge/reader/s3_reader.py +3 -15
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +13 -13
- agno/knowledge/reader/web_search_reader.py +2 -43
- agno/knowledge/reader/website_reader.py +43 -25
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/types.py +9 -0
- agno/knowledge/utils.py +20 -0
- agno/media.py +339 -266
- agno/memory/manager.py +336 -82
- agno/models/aimlapi/aimlapi.py +2 -2
- agno/models/anthropic/claude.py +183 -37
- agno/models/aws/bedrock.py +52 -112
- agno/models/aws/claude.py +33 -1
- agno/models/azure/ai_foundry.py +33 -15
- agno/models/azure/openai_chat.py +25 -8
- agno/models/base.py +1011 -566
- agno/models/cerebras/cerebras.py +19 -13
- agno/models/cerebras/cerebras_openai.py +8 -5
- agno/models/cohere/chat.py +27 -1
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/dashscope.py +1 -0
- agno/models/deepinfra/deepinfra.py +2 -2
- agno/models/deepseek/deepseek.py +2 -2
- agno/models/fireworks/fireworks.py +2 -2
- agno/models/google/gemini.py +110 -37
- agno/models/groq/groq.py +28 -11
- agno/models/huggingface/huggingface.py +2 -1
- agno/models/internlm/internlm.py +2 -2
- agno/models/langdb/langdb.py +4 -4
- agno/models/litellm/chat.py +18 -1
- agno/models/litellm/litellm_openai.py +2 -2
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/message.py +143 -4
- agno/models/meta/llama.py +27 -10
- agno/models/meta/llama_openai.py +5 -17
- agno/models/nebius/nebius.py +6 -6
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/nvidia.py +2 -2
- agno/models/ollama/chat.py +60 -6
- agno/models/openai/chat.py +102 -43
- agno/models/openai/responses.py +103 -106
- agno/models/openrouter/openrouter.py +41 -3
- agno/models/perplexity/perplexity.py +4 -5
- agno/models/portkey/portkey.py +3 -3
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +81 -5
- agno/models/sambanova/sambanova.py +2 -2
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/together.py +2 -2
- agno/models/utils.py +254 -8
- agno/models/vercel/v0.py +2 -2
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +96 -0
- agno/models/vllm/vllm.py +1 -0
- agno/models/xai/xai.py +3 -2
- agno/os/app.py +543 -175
- agno/os/auth.py +24 -14
- agno/os/config.py +1 -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 +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/agui.py +23 -7
- agno/os/interfaces/agui/router.py +27 -3
- agno/os/interfaces/agui/utils.py +242 -142
- agno/os/interfaces/base.py +6 -2
- agno/os/interfaces/slack/router.py +81 -23
- agno/os/interfaces/slack/slack.py +29 -14
- agno/os/interfaces/whatsapp/router.py +11 -4
- agno/os/interfaces/whatsapp/whatsapp.py +14 -7
- agno/os/mcp.py +111 -54
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +556 -139
- agno/os/routers/evals/evals.py +71 -34
- agno/os/routers/evals/schemas.py +31 -31
- agno/os/routers/evals/utils.py +6 -5
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +185 -38
- agno/os/routers/knowledge/schemas.py +82 -22
- agno/os/routers/memory/memory.py +158 -53
- agno/os/routers/memory/schemas.py +20 -16
- agno/os/routers/metrics/metrics.py +20 -8
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +499 -38
- agno/os/schema.py +308 -198
- agno/os/utils.py +401 -41
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +3 -1
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +2 -2
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +7 -2
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +266 -112
- agno/run/base.py +53 -24
- agno/run/team.py +252 -111
- agno/run/workflow.py +156 -45
- agno/session/agent.py +105 -89
- agno/session/summary.py +65 -25
- agno/session/team.py +176 -96
- agno/session/workflow.py +406 -40
- agno/team/team.py +3854 -1692
- agno/tools/brightdata.py +3 -3
- agno/tools/cartesia.py +3 -5
- agno/tools/dalle.py +9 -8
- agno/tools/decorator.py +4 -2
- agno/tools/desi_vocal.py +2 -2
- agno/tools/duckduckgo.py +15 -11
- agno/tools/e2b.py +20 -13
- agno/tools/eleven_labs.py +26 -28
- agno/tools/exa.py +21 -16
- agno/tools/fal.py +4 -4
- agno/tools/file.py +153 -23
- agno/tools/file_generation.py +350 -0
- agno/tools/firecrawl.py +4 -4
- agno/tools/function.py +257 -37
- agno/tools/giphy.py +2 -2
- agno/tools/gmail.py +238 -14
- agno/tools/google_drive.py +270 -0
- agno/tools/googlecalendar.py +36 -8
- agno/tools/googlesheets.py +20 -5
- agno/tools/jira.py +20 -0
- agno/tools/knowledge.py +3 -3
- agno/tools/lumalab.py +3 -3
- 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 +11 -17
- agno/tools/memori.py +1 -53
- agno/tools/memory.py +419 -0
- agno/tools/models/azure_openai.py +2 -2
- agno/tools/models/gemini.py +3 -3
- agno/tools/models/groq.py +3 -5
- agno/tools/models/nebius.py +7 -7
- agno/tools/models_labs.py +25 -15
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +4 -9
- agno/tools/opencv.py +3 -3
- agno/tools/parallel.py +314 -0
- agno/tools/replicate.py +7 -7
- agno/tools/scrapegraph.py +58 -31
- agno/tools/searxng.py +2 -2
- agno/tools/serper.py +2 -2
- agno/tools/slack.py +18 -3
- agno/tools/spider.py +2 -2
- agno/tools/tavily.py +146 -0
- agno/tools/whatsapp.py +1 -1
- agno/tools/workflow.py +278 -0
- agno/tools/yfinance.py +12 -11
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +27 -0
- agno/utils/common.py +90 -1
- agno/utils/events.py +222 -7
- agno/utils/gemini.py +181 -23
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +111 -0
- agno/utils/knowledge.py +12 -5
- agno/utils/log.py +1 -0
- agno/utils/mcp.py +95 -5
- agno/utils/media.py +188 -10
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +60 -0
- agno/utils/models/claude.py +40 -11
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/print_response/agent.py +105 -21
- agno/utils/print_response/team.py +103 -38
- agno/utils/print_response/workflow.py +251 -34
- agno/utils/reasoning.py +22 -1
- agno/utils/serialize.py +32 -0
- agno/utils/streamlit.py +16 -10
- agno/utils/string.py +41 -0
- agno/utils/team.py +98 -9
- agno/utils/tools.py +1 -1
- agno/vectordb/base.py +23 -4
- agno/vectordb/cassandra/cassandra.py +65 -9
- agno/vectordb/chroma/chromadb.py +182 -38
- agno/vectordb/clickhouse/clickhousedb.py +64 -11
- agno/vectordb/couchbase/couchbase.py +105 -10
- agno/vectordb/lancedb/lance_db.py +183 -135
- agno/vectordb/langchaindb/langchaindb.py +25 -7
- agno/vectordb/lightrag/lightrag.py +17 -3
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +46 -7
- agno/vectordb/milvus/milvus.py +126 -9
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/mongodb/mongodb.py +112 -7
- agno/vectordb/pgvector/pgvector.py +142 -21
- agno/vectordb/pineconedb/pineconedb.py +80 -8
- agno/vectordb/qdrant/qdrant.py +125 -39
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/singlestore/singlestore.py +111 -25
- agno/vectordb/surrealdb/surrealdb.py +31 -5
- agno/vectordb/upstashdb/upstashdb.py +76 -8
- agno/vectordb/weaviate/weaviate.py +86 -15
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +112 -18
- agno/workflow/loop.py +69 -10
- agno/workflow/parallel.py +266 -118
- agno/workflow/router.py +110 -17
- agno/workflow/step.py +645 -136
- agno/workflow/steps.py +65 -6
- agno/workflow/types.py +71 -33
- agno/workflow/workflow.py +2113 -300
- agno-2.3.0.dist-info/METADATA +618 -0
- agno-2.3.0.dist-info/RECORD +577 -0
- agno-2.3.0.dist-info/licenses/LICENSE +201 -0
- agno/knowledge/reader/url_reader.py +0 -128
- agno/tools/googlesearch.py +0 -98
- agno/tools/mcp.py +0 -610
- agno/utils/models/aws_claude.py +0 -170
- agno-2.0.0rc2.dist-info/METADATA +0 -355
- agno-2.0.0rc2.dist-info/RECORD +0 -515
- agno-2.0.0rc2.dist-info/licenses/LICENSE +0 -375
- {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
- {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
agno/os/routers/evals/evals.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from copy import deepcopy
|
|
3
|
-
from typing import List, Optional
|
|
3
|
+
from typing import List, Optional, Union, cast
|
|
4
4
|
|
|
5
5
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
6
6
|
|
|
7
7
|
from agno.agent.agent import Agent
|
|
8
|
-
from agno.db.base import BaseDb
|
|
8
|
+
from agno.db.base import AsyncBaseDb, BaseDb
|
|
9
9
|
from agno.db.schemas.evals import EvalFilterType, EvalType
|
|
10
10
|
from agno.models.utils import get_model
|
|
11
11
|
from agno.os.auth import get_authentication_dependency
|
|
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def get_eval_router(
|
|
37
|
-
dbs: dict[str, BaseDb],
|
|
37
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
38
38
|
agents: Optional[List[Agent]] = None,
|
|
39
39
|
teams: Optional[List[Team]] = None,
|
|
40
40
|
settings: AgnoAPISettings = AgnoAPISettings(),
|
|
@@ -55,7 +55,10 @@ def get_eval_router(
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def attach_routes(
|
|
58
|
-
router: APIRouter,
|
|
58
|
+
router: APIRouter,
|
|
59
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
60
|
+
agents: Optional[List[Agent]] = None,
|
|
61
|
+
teams: Optional[List[Team]] = None,
|
|
59
62
|
) -> APIRouter:
|
|
60
63
|
@router.get(
|
|
61
64
|
"/eval-runs",
|
|
@@ -112,21 +115,39 @@ def attach_routes(
|
|
|
112
115
|
sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
|
|
113
116
|
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
114
117
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
118
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
115
119
|
) -> PaginatedResponse[EvalSchema]:
|
|
116
|
-
db = get_db(dbs, db_id)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
db = await get_db(dbs, db_id, table)
|
|
121
|
+
|
|
122
|
+
if isinstance(db, AsyncBaseDb):
|
|
123
|
+
db = cast(AsyncBaseDb, db)
|
|
124
|
+
eval_runs, total_count = await db.get_eval_runs(
|
|
125
|
+
limit=limit,
|
|
126
|
+
page=page,
|
|
127
|
+
sort_by=sort_by,
|
|
128
|
+
sort_order=sort_order,
|
|
129
|
+
agent_id=agent_id,
|
|
130
|
+
team_id=team_id,
|
|
131
|
+
workflow_id=workflow_id,
|
|
132
|
+
model_id=model_id,
|
|
133
|
+
eval_type=eval_types,
|
|
134
|
+
filter_type=filter_type,
|
|
135
|
+
deserialize=False,
|
|
136
|
+
)
|
|
137
|
+
else:
|
|
138
|
+
eval_runs, total_count = db.get_eval_runs( # type: ignore
|
|
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
|
+
)
|
|
130
151
|
|
|
131
152
|
return PaginatedResponse(
|
|
132
153
|
data=[EvalSchema.from_dict(eval_run) for eval_run in eval_runs], # type: ignore
|
|
@@ -178,9 +199,14 @@ def attach_routes(
|
|
|
178
199
|
async def get_eval_run(
|
|
179
200
|
eval_run_id: str,
|
|
180
201
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
202
|
+
table: Optional[str] = Query(default=None, description="Table to query eval run from"),
|
|
181
203
|
) -> EvalSchema:
|
|
182
|
-
db = get_db(dbs, db_id)
|
|
183
|
-
|
|
204
|
+
db = await get_db(dbs, db_id, table)
|
|
205
|
+
if isinstance(db, AsyncBaseDb):
|
|
206
|
+
db = cast(AsyncBaseDb, db)
|
|
207
|
+
eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
|
|
208
|
+
else:
|
|
209
|
+
eval_run = db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
|
|
184
210
|
if not eval_run:
|
|
185
211
|
raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
|
|
186
212
|
|
|
@@ -200,10 +226,15 @@ def attach_routes(
|
|
|
200
226
|
async def delete_eval_runs(
|
|
201
227
|
request: DeleteEvalRunsRequest,
|
|
202
228
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
229
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
203
230
|
) -> None:
|
|
204
231
|
try:
|
|
205
|
-
db = get_db(dbs, db_id)
|
|
206
|
-
db
|
|
232
|
+
db = await get_db(dbs, db_id, table)
|
|
233
|
+
if isinstance(db, AsyncBaseDb):
|
|
234
|
+
db = cast(AsyncBaseDb, db)
|
|
235
|
+
await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
|
|
236
|
+
else:
|
|
237
|
+
db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
|
|
207
238
|
except Exception as e:
|
|
208
239
|
raise HTTPException(status_code=500, detail=f"Failed to delete eval runs: {e}")
|
|
209
240
|
|
|
@@ -249,10 +280,15 @@ def attach_routes(
|
|
|
249
280
|
eval_run_id: str,
|
|
250
281
|
request: UpdateEvalRunRequest,
|
|
251
282
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
283
|
+
table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
|
|
252
284
|
) -> EvalSchema:
|
|
253
285
|
try:
|
|
254
|
-
db = get_db(dbs, db_id)
|
|
255
|
-
|
|
286
|
+
db = await get_db(dbs, db_id, table)
|
|
287
|
+
if isinstance(db, AsyncBaseDb):
|
|
288
|
+
db = cast(AsyncBaseDb, db)
|
|
289
|
+
eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
|
|
290
|
+
else:
|
|
291
|
+
eval_run = db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
|
|
256
292
|
except Exception as e:
|
|
257
293
|
raise HTTPException(status_code=500, detail=f"Failed to rename eval run: {e}")
|
|
258
294
|
|
|
@@ -304,8 +340,9 @@ def attach_routes(
|
|
|
304
340
|
async def run_eval(
|
|
305
341
|
eval_run_input: EvalRunInput,
|
|
306
342
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for evaluation"),
|
|
343
|
+
table: Optional[str] = Query(default=None, description="Table to use for evaluation"),
|
|
307
344
|
) -> Optional[EvalSchema]:
|
|
308
|
-
db = get_db(dbs, db_id)
|
|
345
|
+
db = await get_db(dbs, db_id, table)
|
|
309
346
|
|
|
310
347
|
if eval_run_input.agent_id and eval_run_input.team_id:
|
|
311
348
|
raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
|
|
@@ -324,10 +361,10 @@ def attach_routes(
|
|
|
324
361
|
):
|
|
325
362
|
default_model = deepcopy(agent.model)
|
|
326
363
|
if eval_run_input.model_id != agent.model.id or eval_run_input.model_provider != agent.model.provider:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
)
|
|
364
|
+
model_provider = eval_run_input.model_provider.lower()
|
|
365
|
+
model_id = eval_run_input.model_id.lower()
|
|
366
|
+
model_string = f"{model_provider}:{model_id}"
|
|
367
|
+
model = get_model(model_string)
|
|
331
368
|
agent.model = model
|
|
332
369
|
|
|
333
370
|
team = None
|
|
@@ -346,10 +383,10 @@ def attach_routes(
|
|
|
346
383
|
):
|
|
347
384
|
default_model = deepcopy(team.model)
|
|
348
385
|
if eval_run_input.model_id != team.model.id or eval_run_input.model_provider != team.model.provider:
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
386
|
+
model_provider = eval_run_input.model_provider.lower()
|
|
387
|
+
model_id = eval_run_input.model_id.lower()
|
|
388
|
+
model_string = f"{model_provider}:{model_id}"
|
|
389
|
+
model = get_model(model_string)
|
|
353
390
|
team.model = model
|
|
354
391
|
|
|
355
392
|
agent = None
|
|
@@ -380,7 +417,7 @@ def parse_eval_types_filter(
|
|
|
380
417
|
eval_types: Optional[str] = Query(
|
|
381
418
|
default=None,
|
|
382
419
|
description="Comma-separated eval types (accuracy,performance,reliability)",
|
|
383
|
-
|
|
420
|
+
examples=["accuracy,performance"],
|
|
384
421
|
),
|
|
385
422
|
) -> Optional[List[EvalType]]:
|
|
386
423
|
"""Parse comma-separated eval types into EvalType enums for filtering evaluation runs."""
|
agno/os/routers/evals/schemas.py
CHANGED
|
@@ -2,7 +2,7 @@ from dataclasses import asdict
|
|
|
2
2
|
from datetime import datetime, timezone
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
|
|
5
|
-
from pydantic import BaseModel
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
from agno.db.schemas.evals import EvalType
|
|
8
8
|
from agno.eval import AccuracyResult, PerformanceResult, ReliabilityResult
|
|
@@ -12,43 +12,43 @@ from agno.eval.reliability import ReliabilityEval
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class EvalRunInput(BaseModel):
|
|
15
|
-
agent_id: Optional[str] = None
|
|
16
|
-
team_id: Optional[str] = None
|
|
17
|
-
|
|
18
|
-
model_id: Optional[str] = None
|
|
19
|
-
model_provider: Optional[str] = None
|
|
20
|
-
eval_type: EvalType
|
|
21
|
-
input: str
|
|
22
|
-
additional_guidelines: Optional[str] = None
|
|
23
|
-
additional_context: Optional[str] = None
|
|
24
|
-
num_iterations:
|
|
25
|
-
name: Optional[str] = None
|
|
15
|
+
agent_id: Optional[str] = Field(None, description="Agent ID to evaluate")
|
|
16
|
+
team_id: Optional[str] = Field(None, description="Team ID to evaluate")
|
|
17
|
+
|
|
18
|
+
model_id: Optional[str] = Field(None, description="Model ID to use for evaluation")
|
|
19
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
20
|
+
eval_type: EvalType = Field(..., description="Type of evaluation to run (accuracy, performance, or reliability)")
|
|
21
|
+
input: str = Field(..., description="Input text/query for the evaluation", min_length=1)
|
|
22
|
+
additional_guidelines: Optional[str] = Field(None, description="Additional guidelines for the evaluation")
|
|
23
|
+
additional_context: Optional[str] = Field(None, description="Additional context for the evaluation")
|
|
24
|
+
num_iterations: int = Field(1, description="Number of times to run the evaluation", ge=1, le=100)
|
|
25
|
+
name: Optional[str] = Field(None, description="Name for this evaluation run")
|
|
26
26
|
|
|
27
27
|
# Accuracy eval specific fields
|
|
28
|
-
expected_output: Optional[str] = None
|
|
28
|
+
expected_output: Optional[str] = Field(None, description="Expected output for accuracy evaluation")
|
|
29
29
|
|
|
30
30
|
# Performance eval specific fields
|
|
31
|
-
warmup_runs:
|
|
31
|
+
warmup_runs: int = Field(0, description="Number of warmup runs before measuring performance", ge=0, le=10)
|
|
32
32
|
|
|
33
33
|
# Reliability eval specific fields
|
|
34
|
-
expected_tool_calls: Optional[List[str]] = None
|
|
34
|
+
expected_tool_calls: Optional[List[str]] = Field(None, description="Expected tool calls for reliability evaluation")
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class EvalSchema(BaseModel):
|
|
38
|
-
id: str
|
|
39
|
-
|
|
40
|
-
agent_id: Optional[str] = None
|
|
41
|
-
model_id: Optional[str] = None
|
|
42
|
-
model_provider: Optional[str] = None
|
|
43
|
-
team_id: Optional[str] = None
|
|
44
|
-
workflow_id: Optional[str] = None
|
|
45
|
-
name: Optional[str] = None
|
|
46
|
-
evaluated_component_name: Optional[str] = None
|
|
47
|
-
eval_type: EvalType
|
|
48
|
-
eval_data: Dict[str, Any]
|
|
49
|
-
eval_input: Optional[Dict[str, Any]] = None
|
|
50
|
-
created_at: Optional[datetime] = None
|
|
51
|
-
updated_at: Optional[datetime] = None
|
|
38
|
+
id: str = Field(..., description="Unique identifier for the evaluation run")
|
|
39
|
+
|
|
40
|
+
agent_id: Optional[str] = Field(None, description="Agent ID that was evaluated")
|
|
41
|
+
model_id: Optional[str] = Field(None, description="Model ID used in evaluation")
|
|
42
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
43
|
+
team_id: Optional[str] = Field(None, description="Team ID that was evaluated")
|
|
44
|
+
workflow_id: Optional[str] = Field(None, description="Workflow ID that was evaluated")
|
|
45
|
+
name: Optional[str] = Field(None, description="Name of the evaluation run")
|
|
46
|
+
evaluated_component_name: Optional[str] = Field(None, description="Name of the evaluated component")
|
|
47
|
+
eval_type: EvalType = Field(..., description="Type of evaluation (accuracy, performance, or reliability)")
|
|
48
|
+
eval_data: Dict[str, Any] = Field(..., description="Evaluation results and metrics")
|
|
49
|
+
eval_input: Optional[Dict[str, Any]] = Field(None, description="Input parameters used for the evaluation")
|
|
50
|
+
created_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was created")
|
|
51
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was last updated")
|
|
52
52
|
|
|
53
53
|
@classmethod
|
|
54
54
|
def from_dict(cls, eval_run: Dict[str, Any]) -> "EvalSchema":
|
|
@@ -135,8 +135,8 @@ class EvalSchema(BaseModel):
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
class DeleteEvalRunsRequest(BaseModel):
|
|
138
|
-
eval_run_ids: List[str]
|
|
138
|
+
eval_run_ids: List[str] = Field(..., description="List of evaluation run IDs to delete", min_length=1)
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
class UpdateEvalRunRequest(BaseModel):
|
|
142
|
-
name: str
|
|
142
|
+
name: str = Field(..., description="New name for the evaluation run", min_length=1, max_length=255)
|
agno/os/routers/evals/utils.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from typing import Optional
|
|
1
|
+
from typing import Optional, Union
|
|
2
2
|
|
|
3
3
|
from fastapi import HTTPException
|
|
4
4
|
|
|
5
5
|
from agno.agent.agent import Agent
|
|
6
|
-
from agno.db.base import BaseDb
|
|
6
|
+
from agno.db.base import AsyncBaseDb, BaseDb
|
|
7
7
|
from agno.eval.accuracy import AccuracyEval
|
|
8
8
|
from agno.eval.performance import PerformanceEval
|
|
9
9
|
from agno.eval.reliability import ReliabilityEval
|
|
@@ -14,7 +14,7 @@ from agno.team.team import Team
|
|
|
14
14
|
|
|
15
15
|
async def run_accuracy_eval(
|
|
16
16
|
eval_run_input: EvalRunInput,
|
|
17
|
-
db: BaseDb,
|
|
17
|
+
db: Union[BaseDb, AsyncBaseDb],
|
|
18
18
|
agent: Optional[Agent] = None,
|
|
19
19
|
team: Optional[Team] = None,
|
|
20
20
|
default_model: Optional[Model] = None,
|
|
@@ -33,6 +33,7 @@ async def run_accuracy_eval(
|
|
|
33
33
|
additional_context=eval_run_input.additional_context,
|
|
34
34
|
num_iterations=eval_run_input.num_iterations or 1,
|
|
35
35
|
name=eval_run_input.name,
|
|
36
|
+
model=default_model,
|
|
36
37
|
)
|
|
37
38
|
|
|
38
39
|
result = accuracy_eval.run(print_results=False, print_summary=False)
|
|
@@ -52,7 +53,7 @@ async def run_accuracy_eval(
|
|
|
52
53
|
|
|
53
54
|
async def run_performance_eval(
|
|
54
55
|
eval_run_input: EvalRunInput,
|
|
55
|
-
db: BaseDb,
|
|
56
|
+
db: Union[BaseDb, AsyncBaseDb],
|
|
56
57
|
agent: Optional[Agent] = None,
|
|
57
58
|
team: Optional[Team] = None,
|
|
58
59
|
default_model: Optional[Model] = None,
|
|
@@ -109,7 +110,7 @@ async def run_performance_eval(
|
|
|
109
110
|
|
|
110
111
|
async def run_reliability_eval(
|
|
111
112
|
eval_run_input: EvalRunInput,
|
|
112
|
-
db: BaseDb,
|
|
113
|
+
db: Union[BaseDb, AsyncBaseDb],
|
|
113
114
|
agent: Optional[Agent] = None,
|
|
114
115
|
team: Optional[Team] = None,
|
|
115
116
|
default_model: Optional[Model] = None,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter
|
|
4
|
+
|
|
5
|
+
from agno.os.schema import HealthResponse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_health_router(health_endpoint: str = "/health") -> APIRouter:
|
|
9
|
+
router = APIRouter(tags=["Health"])
|
|
10
|
+
|
|
11
|
+
started_time_stamp = datetime.now(timezone.utc).timestamp()
|
|
12
|
+
|
|
13
|
+
@router.get(
|
|
14
|
+
health_endpoint,
|
|
15
|
+
operation_id="health_check",
|
|
16
|
+
summary="Health Check",
|
|
17
|
+
description="Check the health status of the AgentOS API. Returns a simple status indicator.",
|
|
18
|
+
response_model=HealthResponse,
|
|
19
|
+
responses={
|
|
20
|
+
200: {
|
|
21
|
+
"description": "API is healthy and operational",
|
|
22
|
+
"content": {
|
|
23
|
+
"application/json": {"example": {"status": "ok", "instantiated_at": str(started_time_stamp)}}
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
)
|
|
28
|
+
async def health_check() -> HealthResponse:
|
|
29
|
+
return HealthResponse(status="ok", instantiated_at=str(started_time_stamp))
|
|
30
|
+
|
|
31
|
+
return router
|
agno/os/routers/home.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from agno.os.app import AgentOS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_home_router(os: "AgentOS") -> APIRouter:
|
|
10
|
+
router = APIRouter(tags=["Home"])
|
|
11
|
+
|
|
12
|
+
@router.get(
|
|
13
|
+
"/",
|
|
14
|
+
operation_id="get_api_info",
|
|
15
|
+
summary="API Information",
|
|
16
|
+
description=(
|
|
17
|
+
"Get basic information about this AgentOS API instance, including:\n\n"
|
|
18
|
+
"- API metadata and version\n"
|
|
19
|
+
"- Available capabilities overview\n"
|
|
20
|
+
"- Links to key endpoints and documentation"
|
|
21
|
+
),
|
|
22
|
+
responses={
|
|
23
|
+
200: {
|
|
24
|
+
"description": "API information retrieved successfully",
|
|
25
|
+
"content": {
|
|
26
|
+
"application/json": {
|
|
27
|
+
"examples": {
|
|
28
|
+
"home": {
|
|
29
|
+
"summary": "Example home response",
|
|
30
|
+
"value": {
|
|
31
|
+
"name": "AgentOS API",
|
|
32
|
+
"description": "AI Agent Operating System API",
|
|
33
|
+
"id": "demo-os",
|
|
34
|
+
"version": "1.0.0",
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
async def get_api_info():
|
|
44
|
+
"""Get basic API information and available capabilities"""
|
|
45
|
+
return {
|
|
46
|
+
"name": "AgentOS API",
|
|
47
|
+
"description": os.description or "AI Agent Operating System API",
|
|
48
|
+
"id": os.id or "agno-agentos",
|
|
49
|
+
"version": os.version or "1.0.0",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return router
|