agno 2.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/agent/agent.py +5540 -2273
- agno/api/api.py +2 -0
- agno/api/os.py +1 -1
- 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/async_postgres/__init__.py +3 -0
- agno/db/base.py +689 -6
- agno/db/dynamo/dynamo.py +933 -37
- agno/db/dynamo/schemas.py +174 -10
- agno/db/dynamo/utils.py +63 -4
- agno/db/firestore/firestore.py +831 -9
- agno/db/firestore/schemas.py +51 -0
- agno/db/firestore/utils.py +102 -4
- agno/db/gcs_json/gcs_json_db.py +660 -12
- agno/db/gcs_json/utils.py +60 -26
- agno/db/in_memory/in_memory_db.py +287 -14
- agno/db/in_memory/utils.py +60 -2
- agno/db/json/json_db.py +590 -14
- agno/db/json/utils.py +60 -26
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +43 -13
- 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 +2760 -0
- agno/db/mongo/mongo.py +879 -11
- agno/db/mongo/schemas.py +42 -0
- agno/db/mongo/utils.py +80 -8
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +946 -68
- agno/db/mysql/schemas.py +72 -10
- agno/db/mysql/utils.py +198 -7
- agno/db/postgres/__init__.py +2 -1
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +942 -57
- agno/db/postgres/schemas.py +81 -18
- agno/db/postgres/utils.py +164 -2
- agno/db/redis/redis.py +671 -7
- agno/db/redis/schemas.py +50 -0
- agno/db/redis/utils.py +65 -7
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +17 -2
- agno/db/singlestore/schemas.py +63 -0
- agno/db/singlestore/singlestore.py +949 -83
- agno/db/singlestore/utils.py +60 -2
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +62 -0
- agno/db/sqlite/sqlite.py +965 -46
- agno/db/sqlite/utils.py +169 -8
- 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 +2 -0
- agno/eval/__init__.py +10 -0
- agno/eval/accuracy.py +75 -55
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +16 -7
- agno/eval/reliability.py +28 -16
- agno/eval/utils.py +35 -17
- agno/exceptions.py +27 -2
- agno/filters.py +354 -0
- agno/guardrails/prompt_injection.py +1 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +1 -1
- agno/knowledge/chunking/agentic.py +13 -10
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/semantic.py +9 -4
- agno/knowledge/chunking/strategy.py +59 -15
- agno/knowledge/embedder/fastembed.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/ollama.py +8 -0
- agno/knowledge/embedder/openai.py +8 -8
- agno/knowledge/embedder/sentence_transformer.py +6 -2
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/knowledge.py +1618 -318
- agno/knowledge/reader/base.py +6 -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 +16 -20
- agno/knowledge/reader/json_reader.py +5 -4
- agno/knowledge/reader/markdown_reader.py +8 -8
- agno/knowledge/reader/pdf_reader.py +17 -19
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +32 -3
- agno/knowledge/reader/s3_reader.py +3 -3
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +22 -10
- agno/knowledge/reader/web_search_reader.py +1 -48
- agno/knowledge/reader/website_reader.py +10 -10
- agno/knowledge/reader/wikipedia_reader.py +33 -1
- agno/knowledge/types.py +1 -0
- agno/knowledge/utils.py +72 -7
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +544 -83
- 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 +515 -40
- agno/models/aws/bedrock.py +102 -21
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +41 -19
- agno/models/azure/openai_chat.py +39 -8
- agno/models/base.py +1249 -525
- agno/models/cerebras/cerebras.py +91 -21
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +40 -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 +877 -80
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +51 -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 +44 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +28 -5
- agno/models/meta/llama.py +47 -14
- agno/models/meta/llama_openai.py +22 -17
- agno/models/mistral/mistral.py +8 -4
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/chat.py +24 -8
- agno/models/openai/chat.py +104 -29
- agno/models/openai/responses.py +101 -81
- agno/models/openrouter/openrouter.py +60 -3
- agno/models/perplexity/perplexity.py +17 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +24 -4
- agno/models/response.py +73 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/utils.py +254 -8
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +549 -152
- agno/os/auth.py +190 -3
- agno/os/config.py +23 -0
- agno/os/interfaces/a2a/router.py +8 -11
- agno/os/interfaces/a2a/utils.py +1 -1
- agno/os/interfaces/agui/router.py +18 -3
- agno/os/interfaces/agui/utils.py +152 -39
- agno/os/interfaces/slack/router.py +55 -37
- agno/os/interfaces/slack/slack.py +9 -1
- agno/os/interfaces/whatsapp/router.py +0 -1
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/mcp.py +110 -52
- agno/os/middleware/__init__.py +2 -0
- agno/os/middleware/jwt.py +676 -112
- agno/os/router.py +40 -1478
- 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/evals.py +96 -39
- agno/os/routers/evals/schemas.py +65 -33
- agno/os/routers/evals/utils.py +80 -10
- agno/os/routers/health.py +10 -4
- agno/os/routers/knowledge/knowledge.py +196 -38
- agno/os/routers/knowledge/schemas.py +82 -22
- agno/os/routers/memory/memory.py +279 -52
- agno/os/routers/memory/schemas.py +46 -17
- agno/os/routers/metrics/metrics.py +20 -8
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +462 -34
- 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 +256 -693
- agno/os/scopes.py +469 -0
- agno/os/utils.py +514 -36
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/openai.py +5 -0
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +155 -32
- agno/run/base.py +55 -3
- agno/run/requirement.py +181 -0
- agno/run/team.py +125 -38
- agno/run/workflow.py +72 -18
- agno/session/agent.py +102 -89
- agno/session/summary.py +56 -15
- agno/session/team.py +164 -90
- agno/session/workflow.py +405 -40
- agno/table.py +10 -0
- agno/team/team.py +3974 -1903
- agno/tools/dalle.py +2 -4
- agno/tools/eleven_labs.py +23 -25
- agno/tools/exa.py +21 -16
- agno/tools/file.py +153 -23
- agno/tools/file_generation.py +16 -10
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +193 -38
- agno/tools/gmail.py +238 -14
- agno/tools/google_drive.py +271 -0
- agno/tools/googlecalendar.py +36 -8
- agno/tools/googlesheets.py +20 -5
- agno/tools/jira.py +20 -0
- 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 +3 -3
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/notion.py +204 -0
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +76 -36
- agno/tools/redshift.py +406 -0
- agno/tools/scrapegraph.py +1 -1
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +18 -3
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +146 -0
- agno/tools/toolkit.py +25 -0
- agno/tools/workflow.py +8 -1
- agno/tools/yfinance.py +12 -11
- 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/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +151 -3
- agno/utils/gemini.py +15 -5
- agno/utils/hooks.py +118 -4
- agno/utils/http.py +113 -2
- agno/utils/knowledge.py +12 -5
- agno/utils/log.py +1 -0
- agno/utils/mcp.py +92 -2
- agno/utils/media.py +187 -1
- agno/utils/merge_dict.py +3 -3
- agno/utils/message.py +60 -0
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +49 -14
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/print_response/agent.py +109 -16
- agno/utils/print_response/team.py +223 -30
- agno/utils/print_response/workflow.py +251 -34
- agno/utils/streamlit.py +1 -1
- agno/utils/team.py +98 -9
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +39 -7
- agno/vectordb/cassandra/cassandra.py +21 -5
- agno/vectordb/chroma/chromadb.py +43 -12
- agno/vectordb/clickhouse/clickhousedb.py +21 -5
- agno/vectordb/couchbase/couchbase.py +29 -5
- agno/vectordb/lancedb/lance_db.py +92 -181
- agno/vectordb/langchaindb/langchaindb.py +24 -4
- agno/vectordb/lightrag/lightrag.py +17 -3
- agno/vectordb/llamaindex/llamaindexdb.py +25 -5
- agno/vectordb/milvus/milvus.py +50 -37
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/mongodb/mongodb.py +36 -30
- agno/vectordb/pgvector/pgvector.py +201 -77
- agno/vectordb/pineconedb/pineconedb.py +41 -23
- agno/vectordb/qdrant/qdrant.py +67 -54
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/singlestore.py +50 -29
- agno/vectordb/surrealdb/surrealdb.py +31 -41
- agno/vectordb/upstashdb/upstashdb.py +34 -6
- agno/vectordb/weaviate/weaviate.py +53 -14
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +120 -18
- agno/workflow/loop.py +77 -10
- agno/workflow/parallel.py +231 -143
- agno/workflow/router.py +118 -17
- agno/workflow/step.py +609 -170
- agno/workflow/steps.py +73 -6
- agno/workflow/types.py +96 -21
- agno/workflow/workflow.py +2039 -262
- {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/METADATA +201 -66
- agno-2.3.13.dist-info/RECORD +613 -0
- agno/tools/googlesearch.py +0 -98
- agno/tools/mcp.py +0 -679
- agno/tools/memori.py +0 -339
- agno-2.1.2.dist-info/RECORD +0 -543
- {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +0 -0
- {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/licenses/LICENSE +0 -0
- {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DeleteMemoriesRequest(BaseModel):
|
|
8
|
-
memory_ids: List[str]
|
|
9
|
-
user_id: Optional[str] = None
|
|
8
|
+
memory_ids: List[str] = Field(..., description="List of memory IDs to delete", min_length=1)
|
|
9
|
+
user_id: Optional[str] = Field(None, description="User ID to filter memories for deletion")
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class UserMemorySchema(BaseModel):
|
|
13
|
-
memory_id: str
|
|
14
|
-
memory: str
|
|
15
|
-
topics: Optional[List[str]]
|
|
13
|
+
memory_id: str = Field(..., description="Unique identifier for the memory")
|
|
14
|
+
memory: str = Field(..., description="Memory content text")
|
|
15
|
+
topics: Optional[List[str]] = Field(None, description="Topics or tags associated with the memory")
|
|
16
16
|
|
|
17
|
-
agent_id: Optional[str]
|
|
18
|
-
team_id: Optional[str]
|
|
19
|
-
user_id: Optional[str]
|
|
17
|
+
agent_id: Optional[str] = Field(None, description="Agent ID associated with this memory")
|
|
18
|
+
team_id: Optional[str] = Field(None, description="Team ID associated with this memory")
|
|
19
|
+
user_id: Optional[str] = Field(None, description="User ID who owns this memory")
|
|
20
20
|
|
|
21
|
-
updated_at: Optional[datetime]
|
|
21
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when memory was last updated")
|
|
22
22
|
|
|
23
23
|
@classmethod
|
|
24
|
-
def from_dict(cls, memory_dict: Dict[str, Any]) -> "UserMemorySchema":
|
|
24
|
+
def from_dict(cls, memory_dict: Dict[str, Any]) -> Optional["UserMemorySchema"]:
|
|
25
|
+
if memory_dict["memory"] == "":
|
|
26
|
+
return None
|
|
27
|
+
|
|
25
28
|
return cls(
|
|
26
29
|
memory_id=memory_dict["memory_id"],
|
|
27
30
|
user_id=str(memory_dict["user_id"]),
|
|
@@ -36,17 +39,17 @@ class UserMemorySchema(BaseModel):
|
|
|
36
39
|
class UserMemoryCreateSchema(BaseModel):
|
|
37
40
|
"""Define the payload expected for creating a new user memory"""
|
|
38
41
|
|
|
39
|
-
memory: str
|
|
40
|
-
user_id: Optional[str] = None
|
|
41
|
-
topics: Optional[List[str]] = None
|
|
42
|
+
memory: str = Field(..., description="Memory content text", min_length=1, max_length=5000)
|
|
43
|
+
user_id: Optional[str] = Field(None, description="User ID who owns this memory")
|
|
44
|
+
topics: Optional[List[str]] = Field(None, description="Topics or tags to categorize the memory")
|
|
42
45
|
|
|
43
46
|
|
|
44
47
|
class UserStatsSchema(BaseModel):
|
|
45
48
|
"""Schema for user memory statistics"""
|
|
46
49
|
|
|
47
|
-
user_id: str
|
|
48
|
-
total_memories: int
|
|
49
|
-
last_memory_updated_at: Optional[datetime] = None
|
|
50
|
+
user_id: str = Field(..., description="User ID")
|
|
51
|
+
total_memories: int = Field(..., description="Total number of memories for this user", ge=0)
|
|
52
|
+
last_memory_updated_at: Optional[datetime] = Field(None, description="Timestamp of the most recent memory update")
|
|
50
53
|
|
|
51
54
|
@classmethod
|
|
52
55
|
def from_dict(cls, user_stats_dict: Dict[str, Any]) -> "UserStatsSchema":
|
|
@@ -57,3 +60,29 @@ class UserStatsSchema(BaseModel):
|
|
|
57
60
|
total_memories=user_stats_dict["total_memories"],
|
|
58
61
|
last_memory_updated_at=datetime.fromtimestamp(updated_at, tz=timezone.utc) if updated_at else None,
|
|
59
62
|
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class OptimizeMemoriesRequest(BaseModel):
|
|
66
|
+
"""Schema for memory optimization request"""
|
|
67
|
+
|
|
68
|
+
user_id: str = Field(..., description="User ID to optimize memories for")
|
|
69
|
+
model: Optional[str] = Field(
|
|
70
|
+
default=None,
|
|
71
|
+
description="Model to use for optimization in format 'provider:model_id' (e.g., 'openai:gpt-4o-mini', 'anthropic:claude-3-5-sonnet-20241022', 'google:gemini-2.0-flash-exp'). If not specified, uses MemoryManager's default model (gpt-4o).",
|
|
72
|
+
)
|
|
73
|
+
apply: bool = Field(
|
|
74
|
+
default=True,
|
|
75
|
+
description="If True, apply optimization changes to database. If False, return preview only without saving.",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class OptimizeMemoriesResponse(BaseModel):
|
|
80
|
+
"""Schema for memory optimization response"""
|
|
81
|
+
|
|
82
|
+
memories: List[UserMemorySchema] = Field(..., description="List of optimized memory objects")
|
|
83
|
+
memories_before: int = Field(..., description="Number of memories before optimization", ge=0)
|
|
84
|
+
memories_after: int = Field(..., description="Number of memories after optimization", ge=0)
|
|
85
|
+
tokens_before: int = Field(..., description="Token count before optimization", ge=0)
|
|
86
|
+
tokens_after: int = Field(..., description="Token count after optimization", ge=0)
|
|
87
|
+
tokens_saved: int = Field(..., description="Number of tokens saved through optimization", ge=0)
|
|
88
|
+
reduction_percentage: float = Field(..., description="Percentage of token reduction achieved", ge=0.0, le=100.0)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from datetime import date, datetime, timezone
|
|
3
|
-
from typing import List, Optional
|
|
3
|
+
from typing import List, Optional, Union, cast
|
|
4
4
|
|
|
5
5
|
from fastapi import Depends, HTTPException, Query
|
|
6
6
|
from fastapi.routing import APIRouter
|
|
7
7
|
|
|
8
|
-
from agno.db.base import BaseDb
|
|
8
|
+
from agno.db.base import AsyncBaseDb, BaseDb
|
|
9
9
|
from agno.os.auth import get_authentication_dependency
|
|
10
10
|
from agno.os.routers.metrics.schemas import DayAggregatedMetrics, MetricsResponse
|
|
11
11
|
from agno.os.schema import (
|
|
@@ -21,7 +21,9 @@ from agno.os.utils import get_db
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def get_metrics_router(
|
|
24
|
+
def get_metrics_router(
|
|
25
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
|
|
26
|
+
) -> APIRouter:
|
|
25
27
|
"""Create metrics router with comprehensive OpenAPI documentation for system metrics and analytics endpoints."""
|
|
26
28
|
router = APIRouter(
|
|
27
29
|
dependencies=[Depends(get_authentication_dependency(settings))],
|
|
@@ -37,7 +39,7 @@ def get_metrics_router(dbs: dict[str, BaseDb], settings: AgnoAPISettings = AgnoA
|
|
|
37
39
|
return attach_routes(router=router, dbs=dbs)
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
42
|
+
def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
|
|
41
43
|
@router.get(
|
|
42
44
|
"/metrics",
|
|
43
45
|
response_model=MetricsResponse,
|
|
@@ -97,10 +99,15 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
97
99
|
default=None, description="Ending date for metrics range (YYYY-MM-DD format)"
|
|
98
100
|
),
|
|
99
101
|
db_id: Optional[str] = Query(default=None, description="Database ID to query metrics from"),
|
|
102
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
100
103
|
) -> MetricsResponse:
|
|
101
104
|
try:
|
|
102
|
-
db = get_db(dbs, db_id)
|
|
103
|
-
|
|
105
|
+
db = await get_db(dbs, db_id, table)
|
|
106
|
+
if isinstance(db, AsyncBaseDb):
|
|
107
|
+
db = cast(AsyncBaseDb, db)
|
|
108
|
+
metrics, latest_updated_at = await db.get_metrics(starting_date=starting_date, ending_date=ending_date)
|
|
109
|
+
else:
|
|
110
|
+
metrics, latest_updated_at = db.get_metrics(starting_date=starting_date, ending_date=ending_date)
|
|
104
111
|
|
|
105
112
|
return MetricsResponse(
|
|
106
113
|
metrics=[DayAggregatedMetrics.from_dict(metric) for metric in metrics],
|
|
@@ -163,10 +170,15 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
163
170
|
)
|
|
164
171
|
async def calculate_metrics(
|
|
165
172
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for metrics calculation"),
|
|
173
|
+
table: Optional[str] = Query(default=None, description="Table to use for metrics calculation"),
|
|
166
174
|
) -> List[DayAggregatedMetrics]:
|
|
167
175
|
try:
|
|
168
|
-
db = get_db(dbs, db_id)
|
|
169
|
-
|
|
176
|
+
db = await get_db(dbs, db_id, table)
|
|
177
|
+
if isinstance(db, AsyncBaseDb):
|
|
178
|
+
db = cast(AsyncBaseDb, db)
|
|
179
|
+
result = await db.calculate_metrics()
|
|
180
|
+
else:
|
|
181
|
+
result = db.calculate_metrics()
|
|
170
182
|
if result is None:
|
|
171
183
|
return []
|
|
172
184
|
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DayAggregatedMetrics(BaseModel):
|
|
8
8
|
"""Aggregated metrics for a given day"""
|
|
9
9
|
|
|
10
|
-
id: str
|
|
10
|
+
id: str = Field(..., description="Unique identifier for the metrics record")
|
|
11
11
|
|
|
12
|
-
agent_runs_count: int
|
|
13
|
-
agent_sessions_count: int
|
|
14
|
-
team_runs_count: int
|
|
15
|
-
team_sessions_count: int
|
|
16
|
-
workflow_runs_count: int
|
|
17
|
-
workflow_sessions_count: int
|
|
18
|
-
users_count: int
|
|
19
|
-
token_metrics: Dict[str, Any]
|
|
20
|
-
model_metrics: List[Dict[str, Any]]
|
|
12
|
+
agent_runs_count: int = Field(..., description="Total number of agent runs", ge=0)
|
|
13
|
+
agent_sessions_count: int = Field(..., description="Total number of agent sessions", ge=0)
|
|
14
|
+
team_runs_count: int = Field(..., description="Total number of team runs", ge=0)
|
|
15
|
+
team_sessions_count: int = Field(..., description="Total number of team sessions", ge=0)
|
|
16
|
+
workflow_runs_count: int = Field(..., description="Total number of workflow runs", ge=0)
|
|
17
|
+
workflow_sessions_count: int = Field(..., description="Total number of workflow sessions", ge=0)
|
|
18
|
+
users_count: int = Field(..., description="Total number of unique users", ge=0)
|
|
19
|
+
token_metrics: Dict[str, Any] = Field(..., description="Token usage metrics (input, output, cached, etc.)")
|
|
20
|
+
model_metrics: List[Dict[str, Any]] = Field(..., description="Metrics grouped by model (model_id, provider, count)")
|
|
21
21
|
|
|
22
|
-
date: datetime
|
|
23
|
-
created_at: int
|
|
24
|
-
updated_at: int
|
|
22
|
+
date: datetime = Field(..., description="Date for which these metrics are aggregated")
|
|
23
|
+
created_at: int = Field(..., description="Unix timestamp when metrics were created", ge=0)
|
|
24
|
+
updated_at: int = Field(..., description="Unix timestamp when metrics were last updated", ge=0)
|
|
25
25
|
|
|
26
26
|
@classmethod
|
|
27
27
|
def from_dict(cls, metrics_dict: Dict[str, Any]) -> "DayAggregatedMetrics":
|
|
@@ -43,5 +43,5 @@ class DayAggregatedMetrics(BaseModel):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class MetricsResponse(BaseModel):
|
|
46
|
-
metrics: List[DayAggregatedMetrics]
|
|
47
|
-
updated_at: Optional[datetime]
|
|
46
|
+
metrics: List[DayAggregatedMetrics] = Field(..., description="List of daily aggregated metrics")
|
|
47
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp of the most recent metrics update")
|