agno 2.2.13__py3-none-any.whl → 2.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/__init__.py +6 -0
- agno/agent/agent.py +5252 -3145
- agno/agent/remote.py +525 -0
- agno/api/api.py +2 -0
- agno/client/__init__.py +3 -0
- agno/client/a2a/__init__.py +10 -0
- agno/client/a2a/client.py +554 -0
- agno/client/a2a/schemas.py +112 -0
- agno/client/a2a/utils.py +369 -0
- agno/client/os.py +2669 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/manager.py +2 -2
- agno/db/base.py +927 -6
- agno/db/dynamo/dynamo.py +788 -2
- agno/db/dynamo/schemas.py +128 -0
- agno/db/dynamo/utils.py +26 -3
- agno/db/firestore/firestore.py +674 -50
- agno/db/firestore/schemas.py +41 -0
- agno/db/firestore/utils.py +25 -10
- agno/db/gcs_json/gcs_json_db.py +506 -3
- agno/db/gcs_json/utils.py +14 -2
- agno/db/in_memory/in_memory_db.py +203 -4
- agno/db/in_memory/utils.py +14 -2
- agno/db/json/json_db.py +498 -2
- agno/db/json/utils.py +14 -2
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/utils.py +19 -0
- agno/db/migrations/v1_to_v2.py +54 -16
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +977 -0
- agno/db/mongo/async_mongo.py +1013 -39
- agno/db/mongo/mongo.py +684 -4
- agno/db/mongo/schemas.py +48 -0
- agno/db/mongo/utils.py +17 -0
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2958 -0
- agno/db/mysql/mysql.py +722 -53
- agno/db/mysql/schemas.py +77 -11
- agno/db/mysql/utils.py +151 -8
- agno/db/postgres/async_postgres.py +1254 -137
- agno/db/postgres/postgres.py +2316 -93
- agno/db/postgres/schemas.py +153 -21
- agno/db/postgres/utils.py +22 -7
- agno/db/redis/redis.py +531 -3
- agno/db/redis/schemas.py +36 -0
- agno/db/redis/utils.py +31 -15
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +20 -9
- agno/db/singlestore/schemas.py +70 -1
- agno/db/singlestore/singlestore.py +737 -74
- agno/db/singlestore/utils.py +13 -3
- agno/db/sqlite/async_sqlite.py +1069 -89
- agno/db/sqlite/schemas.py +133 -1
- agno/db/sqlite/sqlite.py +2203 -165
- agno/db/sqlite/utils.py +21 -11
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +603 -1
- agno/db/utils.py +60 -0
- agno/eval/__init__.py +26 -3
- agno/eval/accuracy.py +25 -12
- agno/eval/agent_as_judge.py +871 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/eval/utils.py +2 -1
- agno/exceptions.py +42 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +13 -2
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +90 -0
- agno/knowledge/chunking/document.py +65 -4
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/markdown.py +102 -11
- agno/knowledge/chunking/recursive.py +2 -2
- agno/knowledge/chunking/semantic.py +130 -48
- agno/knowledge/chunking/strategy.py +18 -0
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/knowledge/embedder/mistral.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/openai.py +16 -12
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +4261 -1199
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +3 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +91 -42
- agno/knowledge/reader/docx_reader.py +9 -10
- agno/knowledge/reader/excel_reader.py +225 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
- agno/knowledge/reader/firecrawl_reader.py +3 -2
- agno/knowledge/reader/json_reader.py +16 -22
- agno/knowledge/reader/markdown_reader.py +15 -14
- agno/knowledge/reader/pdf_reader.py +33 -28
- agno/knowledge/reader/pptx_reader.py +9 -10
- agno/knowledge/reader/reader_factory.py +135 -1
- agno/knowledge/reader/s3_reader.py +8 -16
- agno/knowledge/reader/tavily_reader.py +3 -3
- agno/knowledge/reader/text_reader.py +15 -14
- agno/knowledge/reader/utils/__init__.py +17 -0
- agno/knowledge/reader/utils/spreadsheet.py +114 -0
- agno/knowledge/reader/web_search_reader.py +8 -65
- agno/knowledge/reader/website_reader.py +16 -13
- agno/knowledge/reader/wikipedia_reader.py +36 -3
- agno/knowledge/reader/youtube_reader.py +3 -2
- agno/knowledge/remote_content/__init__.py +33 -0
- agno/knowledge/remote_content/config.py +266 -0
- agno/knowledge/remote_content/remote_content.py +105 -17
- agno/knowledge/utils.py +76 -22
- agno/learn/__init__.py +71 -0
- agno/learn/config.py +463 -0
- agno/learn/curate.py +185 -0
- agno/learn/machine.py +725 -0
- agno/learn/schemas.py +1114 -0
- agno/learn/stores/__init__.py +38 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/entity_memory.py +3275 -0
- agno/learn/stores/learned_knowledge.py +1583 -0
- agno/learn/stores/protocol.py +117 -0
- agno/learn/stores/session_context.py +1217 -0
- agno/learn/stores/user_memory.py +1495 -0
- agno/learn/stores/user_profile.py +1220 -0
- agno/learn/utils.py +209 -0
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +223 -8
- 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/aimlapi.py +17 -0
- agno/models/anthropic/claude.py +434 -59
- agno/models/aws/bedrock.py +121 -20
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +10 -6
- agno/models/azure/openai_chat.py +33 -10
- agno/models/base.py +1162 -561
- agno/models/cerebras/cerebras.py +120 -24
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +65 -6
- agno/models/cometapi/cometapi.py +18 -1
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +18 -1
- agno/models/deepseek/deepseek.py +69 -3
- agno/models/fireworks/fireworks.py +18 -1
- agno/models/google/gemini.py +959 -89
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +48 -18
- agno/models/huggingface/huggingface.py +17 -6
- agno/models/ibm/watsonx.py +16 -6
- agno/models/internlm/internlm.py +18 -1
- agno/models/langdb/langdb.py +13 -1
- agno/models/litellm/chat.py +88 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +24 -5
- agno/models/meta/llama.py +40 -13
- agno/models/meta/llama_openai.py +22 -21
- agno/models/metrics.py +12 -0
- agno/models/mistral/mistral.py +8 -4
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/chat.py +17 -6
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +117 -26
- agno/models/openai/open_responses.py +46 -0
- agno/models/openai/responses.py +110 -32
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/openrouter.py +67 -2
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +19 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +19 -2
- agno/models/response.py +20 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/claude.py +124 -4
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +467 -137
- agno/os/auth.py +253 -5
- agno/os/config.py +22 -0
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +635 -26
- agno/os/interfaces/a2a/utils.py +32 -33
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +26 -16
- agno/os/interfaces/agui/utils.py +97 -57
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +16 -7
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +35 -7
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +652 -79
- agno/os/middleware/__init__.py +4 -0
- agno/os/middleware/jwt.py +718 -115
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +105 -1558
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +655 -0
- agno/os/routers/agents/schema.py +288 -0
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +475 -0
- agno/os/routers/database.py +155 -0
- agno/os/routers/evals/evals.py +111 -18
- agno/os/routers/evals/schemas.py +38 -5
- agno/os/routers/evals/utils.py +80 -11
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +284 -35
- agno/os/routers/knowledge/schemas.py +14 -2
- agno/os/routers/memory/memory.py +274 -11
- agno/os/routers/memory/schemas.py +44 -3
- agno/os/routers/metrics/metrics.py +30 -15
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/session/session.py +143 -14
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +550 -0
- agno/os/routers/teams/schema.py +280 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +549 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +757 -0
- agno/os/routers/workflows/schema.py +139 -0
- agno/os/schema.py +157 -584
- agno/os/scopes.py +469 -0
- agno/os/settings.py +3 -0
- agno/os/utils.py +574 -185
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +102 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +87 -3
- agno/reasoning/groq.py +109 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +1238 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +115 -1
- agno/reasoning/vertexai.py +85 -1
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +581 -0
- agno/run/__init__.py +2 -4
- agno/run/agent.py +134 -19
- agno/run/base.py +49 -1
- agno/run/cancel.py +65 -52
- agno/run/cancellation_management/__init__.py +9 -0
- agno/run/cancellation_management/base.py +78 -0
- agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
- agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +111 -19
- agno/run/workflow.py +2 -1
- agno/session/agent.py +57 -92
- agno/session/summary.py +1 -1
- agno/session/team.py +62 -115
- agno/session/workflow.py +353 -57
- agno/skills/__init__.py +17 -0
- agno/skills/agent_skills.py +377 -0
- agno/skills/errors.py +32 -0
- agno/skills/loaders/__init__.py +4 -0
- agno/skills/loaders/base.py +27 -0
- agno/skills/loaders/local.py +216 -0
- agno/skills/skill.py +65 -0
- agno/skills/utils.py +107 -0
- agno/skills/validator.py +277 -0
- agno/table.py +10 -0
- agno/team/__init__.py +5 -1
- agno/team/remote.py +447 -0
- agno/team/team.py +3769 -2202
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +225 -16
- agno/tools/crawl4ai.py +3 -0
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/file.py +14 -13
- agno/tools/file_generation.py +12 -6
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +94 -113
- agno/tools/google_bigquery.py +11 -2
- agno/tools/google_drive.py +4 -3
- agno/tools/knowledge.py +9 -4
- agno/tools/mcp/mcp.py +301 -18
- agno/tools/mcp/multi_mcp.py +269 -14
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/parallel.py +0 -7
- agno/tools/postgres.py +76 -36
- agno/tools/python.py +14 -6
- agno/tools/reasoning.py +30 -23
- agno/tools/redshift.py +406 -0
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +4 -1
- agno/tools/toolkit.py +253 -18
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +56 -48
- agno/tools/yfinance.py +12 -11
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +161 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +112 -0
- agno/utils/agent.py +251 -10
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +264 -7
- agno/utils/hooks.py +111 -3
- agno/utils/http.py +161 -2
- agno/utils/mcp.py +49 -8
- agno/utils/media.py +22 -1
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +20 -5
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/os.py +0 -0
- agno/utils/print_response/agent.py +99 -16
- agno/utils/print_response/team.py +223 -24
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/prompts.py +8 -6
- agno/utils/remote.py +23 -0
- agno/utils/response.py +1 -13
- agno/utils/string.py +91 -2
- agno/utils/team.py +62 -12
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +15 -2
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/__init__.py +2 -1
- agno/vectordb/chroma/chromadb.py +468 -23
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +6 -2
- agno/vectordb/lancedb/lance_db.py +7 -38
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +118 -84
- agno/vectordb/mongodb/__init__.py +2 -1
- agno/vectordb/mongodb/mongodb.py +14 -31
- agno/vectordb/pgvector/pgvector.py +120 -66
- agno/vectordb/pineconedb/pineconedb.py +2 -19
- agno/vectordb/qdrant/__init__.py +2 -1
- agno/vectordb/qdrant/qdrant.py +33 -56
- agno/vectordb/redis/__init__.py +2 -1
- agno/vectordb/redis/redisdb.py +19 -31
- agno/vectordb/singlestore/singlestore.py +17 -9
- agno/vectordb/surrealdb/surrealdb.py +2 -38
- agno/vectordb/weaviate/__init__.py +2 -1
- agno/vectordb/weaviate/weaviate.py +7 -3
- agno/workflow/__init__.py +5 -1
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +12 -10
- agno/workflow/loop.py +28 -9
- agno/workflow/parallel.py +21 -13
- agno/workflow/remote.py +362 -0
- agno/workflow/router.py +12 -9
- agno/workflow/step.py +261 -36
- agno/workflow/steps.py +12 -8
- agno/workflow/types.py +40 -77
- agno/workflow/workflow.py +939 -213
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
- agno-2.4.3.dist-info/RECORD +677 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
- agno/tools/googlesearch.py +0 -98
- agno/tools/memori.py +0 -339
- agno-2.2.13.dist-info/RECORD +0 -575
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/db/utils.py
CHANGED
|
@@ -2,10 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from datetime import date, datetime
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
|
5
6
|
from uuid import UUID
|
|
6
7
|
|
|
7
8
|
from agno.models.message import Message
|
|
8
9
|
from agno.models.metrics import Metrics
|
|
10
|
+
from agno.utils.log import log_error, log_warning
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from agno.db.base import BaseDb
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_sort_value(record: Dict[str, Any], sort_by: str) -> Any:
|
|
17
|
+
"""Get the sort value for a record, with fallback to created_at for updated_at.
|
|
18
|
+
|
|
19
|
+
When sorting by 'updated_at', this function falls back to 'created_at' if
|
|
20
|
+
'updated_at' is None. This ensures pre-2.0 records (which may have NULL
|
|
21
|
+
updated_at values) are sorted correctly by their creation time.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
record: The record dictionary to get the sort value from
|
|
25
|
+
sort_by: The field to sort by
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
The value to use for sorting
|
|
29
|
+
"""
|
|
30
|
+
value = record.get(sort_by)
|
|
31
|
+
# For updated_at, fall back to created_at if updated_at is None
|
|
32
|
+
if value is None and sort_by == "updated_at":
|
|
33
|
+
value = record.get("created_at")
|
|
34
|
+
return value
|
|
9
35
|
|
|
10
36
|
|
|
11
37
|
class CustomJSONEncoder(json.JSONEncoder):
|
|
@@ -20,6 +46,8 @@ class CustomJSONEncoder(json.JSONEncoder):
|
|
|
20
46
|
return obj.to_dict()
|
|
21
47
|
elif isinstance(obj, Metrics):
|
|
22
48
|
return obj.to_dict()
|
|
49
|
+
elif isinstance(obj, type):
|
|
50
|
+
return str(obj)
|
|
23
51
|
|
|
24
52
|
return super().default(obj)
|
|
25
53
|
|
|
@@ -114,3 +142,35 @@ def deserialize_session_json_fields(session: dict) -> dict:
|
|
|
114
142
|
log_warning(f"Warning: Could not parse runs as JSON, keeping as string: {e}")
|
|
115
143
|
|
|
116
144
|
return session
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def db_from_dict(db_data: Dict[str, Any]) -> Optional[Union["BaseDb"]]:
|
|
148
|
+
"""
|
|
149
|
+
Create a database instance from a dictionary.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
db_data: Dictionary containing database configuration
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Database instance or None if creation fails
|
|
156
|
+
"""
|
|
157
|
+
db_type = db_data.get("type")
|
|
158
|
+
if db_type == "postgres":
|
|
159
|
+
try:
|
|
160
|
+
from agno.db.postgres import PostgresDb
|
|
161
|
+
|
|
162
|
+
return PostgresDb.from_dict(db_data)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
log_error(f"Error reconstructing PostgresDb from dictionary: {e}")
|
|
165
|
+
return None
|
|
166
|
+
elif db_type == "sqlite":
|
|
167
|
+
try:
|
|
168
|
+
from agno.db.sqlite import SqliteDb
|
|
169
|
+
|
|
170
|
+
return SqliteDb.from_dict(db_data)
|
|
171
|
+
except Exception as e:
|
|
172
|
+
log_error(f"Error reconstructing SqliteDb from dictionary: {e}")
|
|
173
|
+
return None
|
|
174
|
+
else:
|
|
175
|
+
log_warning(f"Unknown database type: {db_type}")
|
|
176
|
+
return None
|
agno/eval/__init__.py
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
|
-
from agno.eval.
|
|
2
|
-
from agno.eval.performance import PerformanceEval, PerformanceResult
|
|
3
|
-
from agno.eval.reliability import ReliabilityEval, ReliabilityResult
|
|
1
|
+
from agno.eval.base import BaseEval
|
|
4
2
|
|
|
5
3
|
__all__ = [
|
|
6
4
|
"AccuracyAgentResponse",
|
|
7
5
|
"AccuracyEvaluation",
|
|
8
6
|
"AccuracyResult",
|
|
9
7
|
"AccuracyEval",
|
|
8
|
+
"AgentAsJudgeEval",
|
|
9
|
+
"AgentAsJudgeEvaluation",
|
|
10
|
+
"AgentAsJudgeResult",
|
|
11
|
+
"BaseEval",
|
|
10
12
|
"PerformanceEval",
|
|
11
13
|
"PerformanceResult",
|
|
12
14
|
"ReliabilityEval",
|
|
13
15
|
"ReliabilityResult",
|
|
14
16
|
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(name: str):
|
|
20
|
+
"""Lazy import for eval implementations to avoid circular imports with Agent."""
|
|
21
|
+
if name in ("AccuracyAgentResponse", "AccuracyEval", "AccuracyEvaluation", "AccuracyResult"):
|
|
22
|
+
from agno.eval import accuracy
|
|
23
|
+
|
|
24
|
+
return getattr(accuracy, name)
|
|
25
|
+
elif name in ("AgentAsJudgeEval", "AgentAsJudgeEvaluation", "AgentAsJudgeResult"):
|
|
26
|
+
from agno.eval import agent_as_judge
|
|
27
|
+
|
|
28
|
+
return getattr(agent_as_judge, name)
|
|
29
|
+
elif name in ("PerformanceEval", "PerformanceResult"):
|
|
30
|
+
from agno.eval import performance
|
|
31
|
+
|
|
32
|
+
return getattr(performance, name)
|
|
33
|
+
elif name in ("ReliabilityEval", "ReliabilityResult"):
|
|
34
|
+
from agno.eval import reliability
|
|
35
|
+
|
|
36
|
+
return getattr(reliability, name)
|
|
37
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
agno/eval/accuracy.py
CHANGED
|
@@ -282,7 +282,8 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
282
282
|
) -> Optional[AccuracyEvaluation]:
|
|
283
283
|
"""Orchestrate the evaluation process."""
|
|
284
284
|
try:
|
|
285
|
-
|
|
285
|
+
response = evaluator_agent.run(evaluation_input, stream=False)
|
|
286
|
+
accuracy_agent_response = response.content
|
|
286
287
|
if accuracy_agent_response is None or not isinstance(accuracy_agent_response, AccuracyAgentResponse):
|
|
287
288
|
raise EvalError(f"Evaluator Agent returned an invalid response: {accuracy_agent_response}")
|
|
288
289
|
return AccuracyEvaluation(
|
|
@@ -306,7 +307,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
306
307
|
) -> Optional[AccuracyEvaluation]:
|
|
307
308
|
"""Orchestrate the evaluation process asynchronously."""
|
|
308
309
|
try:
|
|
309
|
-
response = await evaluator_agent.arun(evaluation_input)
|
|
310
|
+
response = await evaluator_agent.arun(evaluation_input, stream=False)
|
|
310
311
|
accuracy_agent_response = response.content
|
|
311
312
|
if accuracy_agent_response is None or not isinstance(accuracy_agent_response, AccuracyAgentResponse):
|
|
312
313
|
raise EvalError(f"Evaluator Agent returned an invalid response: {accuracy_agent_response}")
|
|
@@ -359,10 +360,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
359
360
|
status = Status(f"Running evaluation {i + 1}...", spinner="dots", speed=1.0, refresh_per_second=10)
|
|
360
361
|
live_log.update(status)
|
|
361
362
|
|
|
363
|
+
agent_session_id = f"eval_{self.eval_id}_{i + 1}"
|
|
364
|
+
|
|
362
365
|
if self.agent is not None:
|
|
363
|
-
|
|
366
|
+
agent_response = self.agent.run(input=eval_input, session_id=agent_session_id, stream=False)
|
|
367
|
+
output = agent_response.content
|
|
364
368
|
elif self.team is not None:
|
|
365
|
-
|
|
369
|
+
team_response = self.team.run(input=eval_input, session_id=agent_session_id, stream=False)
|
|
370
|
+
output = team_response.content
|
|
366
371
|
|
|
367
372
|
if not output:
|
|
368
373
|
logger.error(f"Failed to generate a valid answer on iteration {i + 1}: {output}")
|
|
@@ -500,12 +505,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
500
505
|
status = Status(f"Running evaluation {i + 1}...", spinner="dots", speed=1.0, refresh_per_second=10)
|
|
501
506
|
live_log.update(status)
|
|
502
507
|
|
|
508
|
+
agent_session_id = f"eval_{self.eval_id}_{i + 1}"
|
|
509
|
+
|
|
503
510
|
if self.agent is not None:
|
|
504
|
-
|
|
505
|
-
output =
|
|
511
|
+
agent_response = await self.agent.arun(input=eval_input, session_id=agent_session_id, stream=False)
|
|
512
|
+
output = agent_response.content
|
|
506
513
|
elif self.team is not None:
|
|
507
|
-
|
|
508
|
-
output =
|
|
514
|
+
team_response = await self.team.arun(input=eval_input, session_id=agent_session_id, stream=False)
|
|
515
|
+
output = team_response.content
|
|
509
516
|
|
|
510
517
|
if not output:
|
|
511
518
|
logger.error(f"Failed to generate a valid answer on iteration {i + 1}: {output}")
|
|
@@ -612,11 +619,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
612
619
|
print_results: bool = True,
|
|
613
620
|
) -> Optional[AccuracyResult]:
|
|
614
621
|
"""Run the evaluation logic against the given answer, instead of generating an answer with the Agent"""
|
|
622
|
+
# Generate unique run_id for this execution (don't modify self.eval_id due to concurrency)
|
|
623
|
+
run_id = str(uuid4())
|
|
624
|
+
|
|
615
625
|
set_log_level_to_debug() if self.debug_mode else set_log_level_to_info()
|
|
616
626
|
|
|
617
627
|
self.result = AccuracyResult()
|
|
618
628
|
|
|
619
|
-
logger.debug(f"************ Evaluation Start: {
|
|
629
|
+
logger.debug(f"************ Evaluation Start: {run_id} ************")
|
|
620
630
|
|
|
621
631
|
evaluator_agent = self.get_evaluator_agent()
|
|
622
632
|
eval_input = self.get_eval_input()
|
|
@@ -721,7 +731,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
721
731
|
),
|
|
722
732
|
)
|
|
723
733
|
|
|
724
|
-
logger.debug(f"*********** Evaluation End: {
|
|
734
|
+
logger.debug(f"*********** Evaluation End: {run_id} ***********")
|
|
725
735
|
return self.result
|
|
726
736
|
|
|
727
737
|
async def arun_with_output(
|
|
@@ -732,11 +742,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
732
742
|
print_results: bool = True,
|
|
733
743
|
) -> Optional[AccuracyResult]:
|
|
734
744
|
"""Run the evaluation logic against the given answer, instead of generating an answer with the Agent"""
|
|
745
|
+
# Generate unique run_id for this execution (don't modify self.eval_id due to concurrency)
|
|
746
|
+
run_id = str(uuid4())
|
|
747
|
+
|
|
735
748
|
set_log_level_to_debug() if self.debug_mode else set_log_level_to_info()
|
|
736
749
|
|
|
737
750
|
self.result = AccuracyResult()
|
|
738
751
|
|
|
739
|
-
logger.debug(f"************ Evaluation Start: {
|
|
752
|
+
logger.debug(f"************ Evaluation Start: {run_id} ************")
|
|
740
753
|
|
|
741
754
|
evaluator_agent = self.get_evaluator_agent()
|
|
742
755
|
eval_input = self.get_eval_input()
|
|
@@ -820,7 +833,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
|
|
|
820
833
|
eval_input=log_eval_input,
|
|
821
834
|
)
|
|
822
835
|
|
|
823
|
-
logger.debug(f"*********** Evaluation End: {
|
|
836
|
+
logger.debug(f"*********** Evaluation End: {run_id} ***********")
|
|
824
837
|
return self.result
|
|
825
838
|
|
|
826
839
|
def _get_telemetry_data(self) -> Dict[str, Any]:
|