realtimex-deeptutor 0.5.0.post1__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.
- realtimex_deeptutor/__init__.py +67 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/METADATA +1612 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/RECORD +276 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/WHEEL +5 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/entry_points.txt +2 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/licenses/LICENSE +661 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/top_level.txt +2 -0
- src/__init__.py +40 -0
- src/agents/__init__.py +24 -0
- src/agents/base_agent.py +657 -0
- src/agents/chat/__init__.py +24 -0
- src/agents/chat/chat_agent.py +435 -0
- src/agents/chat/prompts/en/chat_agent.yaml +35 -0
- src/agents/chat/prompts/zh/chat_agent.yaml +35 -0
- src/agents/chat/session_manager.py +311 -0
- src/agents/co_writer/__init__.py +0 -0
- src/agents/co_writer/edit_agent.py +260 -0
- src/agents/co_writer/narrator_agent.py +423 -0
- src/agents/co_writer/prompts/en/edit_agent.yaml +113 -0
- src/agents/co_writer/prompts/en/narrator_agent.yaml +88 -0
- src/agents/co_writer/prompts/zh/edit_agent.yaml +113 -0
- src/agents/co_writer/prompts/zh/narrator_agent.yaml +88 -0
- src/agents/guide/__init__.py +16 -0
- src/agents/guide/agents/__init__.py +11 -0
- src/agents/guide/agents/chat_agent.py +104 -0
- src/agents/guide/agents/interactive_agent.py +223 -0
- src/agents/guide/agents/locate_agent.py +149 -0
- src/agents/guide/agents/summary_agent.py +150 -0
- src/agents/guide/guide_manager.py +500 -0
- src/agents/guide/prompts/en/chat_agent.yaml +41 -0
- src/agents/guide/prompts/en/interactive_agent.yaml +202 -0
- src/agents/guide/prompts/en/locate_agent.yaml +68 -0
- src/agents/guide/prompts/en/summary_agent.yaml +157 -0
- src/agents/guide/prompts/zh/chat_agent.yaml +41 -0
- src/agents/guide/prompts/zh/interactive_agent.yaml +626 -0
- src/agents/guide/prompts/zh/locate_agent.yaml +68 -0
- src/agents/guide/prompts/zh/summary_agent.yaml +157 -0
- src/agents/ideagen/__init__.py +12 -0
- src/agents/ideagen/idea_generation_workflow.py +426 -0
- src/agents/ideagen/material_organizer_agent.py +173 -0
- src/agents/ideagen/prompts/en/idea_generation.yaml +187 -0
- src/agents/ideagen/prompts/en/material_organizer.yaml +69 -0
- src/agents/ideagen/prompts/zh/idea_generation.yaml +187 -0
- src/agents/ideagen/prompts/zh/material_organizer.yaml +69 -0
- src/agents/question/__init__.py +24 -0
- src/agents/question/agents/__init__.py +18 -0
- src/agents/question/agents/generate_agent.py +381 -0
- src/agents/question/agents/relevance_analyzer.py +207 -0
- src/agents/question/agents/retrieve_agent.py +239 -0
- src/agents/question/coordinator.py +718 -0
- src/agents/question/example.py +109 -0
- src/agents/question/prompts/en/coordinator.yaml +75 -0
- src/agents/question/prompts/en/generate_agent.yaml +77 -0
- src/agents/question/prompts/en/relevance_analyzer.yaml +41 -0
- src/agents/question/prompts/en/retrieve_agent.yaml +32 -0
- src/agents/question/prompts/zh/coordinator.yaml +75 -0
- src/agents/question/prompts/zh/generate_agent.yaml +77 -0
- src/agents/question/prompts/zh/relevance_analyzer.yaml +39 -0
- src/agents/question/prompts/zh/retrieve_agent.yaml +30 -0
- src/agents/research/agents/__init__.py +23 -0
- src/agents/research/agents/decompose_agent.py +507 -0
- src/agents/research/agents/manager_agent.py +228 -0
- src/agents/research/agents/note_agent.py +180 -0
- src/agents/research/agents/rephrase_agent.py +263 -0
- src/agents/research/agents/reporting_agent.py +1333 -0
- src/agents/research/agents/research_agent.py +714 -0
- src/agents/research/data_structures.py +451 -0
- src/agents/research/main.py +188 -0
- src/agents/research/prompts/en/decompose_agent.yaml +89 -0
- src/agents/research/prompts/en/manager_agent.yaml +24 -0
- src/agents/research/prompts/en/note_agent.yaml +121 -0
- src/agents/research/prompts/en/rephrase_agent.yaml +58 -0
- src/agents/research/prompts/en/reporting_agent.yaml +380 -0
- src/agents/research/prompts/en/research_agent.yaml +173 -0
- src/agents/research/prompts/zh/decompose_agent.yaml +89 -0
- src/agents/research/prompts/zh/manager_agent.yaml +24 -0
- src/agents/research/prompts/zh/note_agent.yaml +121 -0
- src/agents/research/prompts/zh/rephrase_agent.yaml +58 -0
- src/agents/research/prompts/zh/reporting_agent.yaml +380 -0
- src/agents/research/prompts/zh/research_agent.yaml +173 -0
- src/agents/research/research_pipeline.py +1309 -0
- src/agents/research/utils/__init__.py +60 -0
- src/agents/research/utils/citation_manager.py +799 -0
- src/agents/research/utils/json_utils.py +98 -0
- src/agents/research/utils/token_tracker.py +297 -0
- src/agents/solve/__init__.py +80 -0
- src/agents/solve/analysis_loop/__init__.py +14 -0
- src/agents/solve/analysis_loop/investigate_agent.py +414 -0
- src/agents/solve/analysis_loop/note_agent.py +190 -0
- src/agents/solve/main_solver.py +862 -0
- src/agents/solve/memory/__init__.py +34 -0
- src/agents/solve/memory/citation_memory.py +353 -0
- src/agents/solve/memory/investigate_memory.py +226 -0
- src/agents/solve/memory/solve_memory.py +340 -0
- src/agents/solve/prompts/en/analysis_loop/investigate_agent.yaml +55 -0
- src/agents/solve/prompts/en/analysis_loop/note_agent.yaml +54 -0
- src/agents/solve/prompts/en/solve_loop/manager_agent.yaml +67 -0
- src/agents/solve/prompts/en/solve_loop/precision_answer_agent.yaml +62 -0
- src/agents/solve/prompts/en/solve_loop/response_agent.yaml +90 -0
- src/agents/solve/prompts/en/solve_loop/solve_agent.yaml +75 -0
- src/agents/solve/prompts/en/solve_loop/tool_agent.yaml +38 -0
- src/agents/solve/prompts/zh/analysis_loop/investigate_agent.yaml +53 -0
- src/agents/solve/prompts/zh/analysis_loop/note_agent.yaml +54 -0
- src/agents/solve/prompts/zh/solve_loop/manager_agent.yaml +66 -0
- src/agents/solve/prompts/zh/solve_loop/precision_answer_agent.yaml +62 -0
- src/agents/solve/prompts/zh/solve_loop/response_agent.yaml +90 -0
- src/agents/solve/prompts/zh/solve_loop/solve_agent.yaml +76 -0
- src/agents/solve/prompts/zh/solve_loop/tool_agent.yaml +41 -0
- src/agents/solve/solve_loop/__init__.py +22 -0
- src/agents/solve/solve_loop/citation_manager.py +74 -0
- src/agents/solve/solve_loop/manager_agent.py +274 -0
- src/agents/solve/solve_loop/precision_answer_agent.py +96 -0
- src/agents/solve/solve_loop/response_agent.py +301 -0
- src/agents/solve/solve_loop/solve_agent.py +325 -0
- src/agents/solve/solve_loop/tool_agent.py +470 -0
- src/agents/solve/utils/__init__.py +64 -0
- src/agents/solve/utils/config_validator.py +313 -0
- src/agents/solve/utils/display_manager.py +223 -0
- src/agents/solve/utils/error_handler.py +363 -0
- src/agents/solve/utils/json_utils.py +98 -0
- src/agents/solve/utils/performance_monitor.py +407 -0
- src/agents/solve/utils/token_tracker.py +541 -0
- src/api/__init__.py +0 -0
- src/api/main.py +240 -0
- src/api/routers/__init__.py +1 -0
- src/api/routers/agent_config.py +69 -0
- src/api/routers/chat.py +296 -0
- src/api/routers/co_writer.py +337 -0
- src/api/routers/config.py +627 -0
- src/api/routers/dashboard.py +18 -0
- src/api/routers/guide.py +337 -0
- src/api/routers/ideagen.py +436 -0
- src/api/routers/knowledge.py +821 -0
- src/api/routers/notebook.py +247 -0
- src/api/routers/question.py +537 -0
- src/api/routers/research.py +394 -0
- src/api/routers/settings.py +164 -0
- src/api/routers/solve.py +305 -0
- src/api/routers/system.py +252 -0
- src/api/run_server.py +61 -0
- src/api/utils/history.py +172 -0
- src/api/utils/log_interceptor.py +21 -0
- src/api/utils/notebook_manager.py +415 -0
- src/api/utils/progress_broadcaster.py +72 -0
- src/api/utils/task_id_manager.py +100 -0
- src/config/__init__.py +0 -0
- src/config/accessors.py +18 -0
- src/config/constants.py +34 -0
- src/config/defaults.py +18 -0
- src/config/schema.py +38 -0
- src/config/settings.py +50 -0
- src/core/errors.py +62 -0
- src/knowledge/__init__.py +23 -0
- src/knowledge/add_documents.py +606 -0
- src/knowledge/config.py +65 -0
- src/knowledge/example_add_documents.py +236 -0
- src/knowledge/extract_numbered_items.py +1039 -0
- src/knowledge/initializer.py +621 -0
- src/knowledge/kb.py +22 -0
- src/knowledge/manager.py +782 -0
- src/knowledge/progress_tracker.py +182 -0
- src/knowledge/start_kb.py +535 -0
- src/logging/__init__.py +103 -0
- src/logging/adapters/__init__.py +17 -0
- src/logging/adapters/lightrag.py +184 -0
- src/logging/adapters/llamaindex.py +141 -0
- src/logging/config.py +80 -0
- src/logging/handlers/__init__.py +20 -0
- src/logging/handlers/console.py +75 -0
- src/logging/handlers/file.py +201 -0
- src/logging/handlers/websocket.py +127 -0
- src/logging/logger.py +709 -0
- src/logging/stats/__init__.py +16 -0
- src/logging/stats/llm_stats.py +179 -0
- src/services/__init__.py +56 -0
- src/services/config/__init__.py +61 -0
- src/services/config/knowledge_base_config.py +210 -0
- src/services/config/loader.py +260 -0
- src/services/config/unified_config.py +603 -0
- src/services/embedding/__init__.py +45 -0
- src/services/embedding/adapters/__init__.py +22 -0
- src/services/embedding/adapters/base.py +106 -0
- src/services/embedding/adapters/cohere.py +127 -0
- src/services/embedding/adapters/jina.py +99 -0
- src/services/embedding/adapters/ollama.py +116 -0
- src/services/embedding/adapters/openai_compatible.py +96 -0
- src/services/embedding/client.py +159 -0
- src/services/embedding/config.py +156 -0
- src/services/embedding/provider.py +119 -0
- src/services/llm/__init__.py +152 -0
- src/services/llm/capabilities.py +313 -0
- src/services/llm/client.py +302 -0
- src/services/llm/cloud_provider.py +530 -0
- src/services/llm/config.py +200 -0
- src/services/llm/error_mapping.py +103 -0
- src/services/llm/exceptions.py +152 -0
- src/services/llm/factory.py +450 -0
- src/services/llm/local_provider.py +347 -0
- src/services/llm/providers/anthropic.py +95 -0
- src/services/llm/providers/base_provider.py +93 -0
- src/services/llm/providers/open_ai.py +83 -0
- src/services/llm/registry.py +71 -0
- src/services/llm/telemetry.py +40 -0
- src/services/llm/types.py +27 -0
- src/services/llm/utils.py +333 -0
- src/services/prompt/__init__.py +25 -0
- src/services/prompt/manager.py +206 -0
- src/services/rag/__init__.py +64 -0
- src/services/rag/components/__init__.py +29 -0
- src/services/rag/components/base.py +59 -0
- src/services/rag/components/chunkers/__init__.py +18 -0
- src/services/rag/components/chunkers/base.py +34 -0
- src/services/rag/components/chunkers/fixed.py +71 -0
- src/services/rag/components/chunkers/numbered_item.py +94 -0
- src/services/rag/components/chunkers/semantic.py +97 -0
- src/services/rag/components/embedders/__init__.py +14 -0
- src/services/rag/components/embedders/base.py +32 -0
- src/services/rag/components/embedders/openai.py +63 -0
- src/services/rag/components/indexers/__init__.py +18 -0
- src/services/rag/components/indexers/base.py +35 -0
- src/services/rag/components/indexers/graph.py +172 -0
- src/services/rag/components/indexers/lightrag.py +156 -0
- src/services/rag/components/indexers/vector.py +146 -0
- src/services/rag/components/parsers/__init__.py +18 -0
- src/services/rag/components/parsers/base.py +35 -0
- src/services/rag/components/parsers/markdown.py +52 -0
- src/services/rag/components/parsers/pdf.py +115 -0
- src/services/rag/components/parsers/text.py +86 -0
- src/services/rag/components/retrievers/__init__.py +18 -0
- src/services/rag/components/retrievers/base.py +34 -0
- src/services/rag/components/retrievers/dense.py +200 -0
- src/services/rag/components/retrievers/hybrid.py +164 -0
- src/services/rag/components/retrievers/lightrag.py +169 -0
- src/services/rag/components/routing.py +286 -0
- src/services/rag/factory.py +234 -0
- src/services/rag/pipeline.py +215 -0
- src/services/rag/pipelines/__init__.py +32 -0
- src/services/rag/pipelines/academic.py +44 -0
- src/services/rag/pipelines/lightrag.py +43 -0
- src/services/rag/pipelines/llamaindex.py +313 -0
- src/services/rag/pipelines/raganything.py +384 -0
- src/services/rag/service.py +244 -0
- src/services/rag/types.py +73 -0
- src/services/search/__init__.py +284 -0
- src/services/search/base.py +87 -0
- src/services/search/consolidation.py +398 -0
- src/services/search/providers/__init__.py +128 -0
- src/services/search/providers/baidu.py +188 -0
- src/services/search/providers/exa.py +194 -0
- src/services/search/providers/jina.py +161 -0
- src/services/search/providers/perplexity.py +153 -0
- src/services/search/providers/serper.py +209 -0
- src/services/search/providers/tavily.py +161 -0
- src/services/search/types.py +114 -0
- src/services/setup/__init__.py +34 -0
- src/services/setup/init.py +285 -0
- src/services/tts/__init__.py +16 -0
- src/services/tts/config.py +99 -0
- src/tools/__init__.py +91 -0
- src/tools/code_executor.py +536 -0
- src/tools/paper_search_tool.py +171 -0
- src/tools/query_item_tool.py +310 -0
- src/tools/question/__init__.py +15 -0
- src/tools/question/exam_mimic.py +616 -0
- src/tools/question/pdf_parser.py +211 -0
- src/tools/question/question_extractor.py +397 -0
- src/tools/rag_tool.py +173 -0
- src/tools/tex_chunker.py +339 -0
- src/tools/tex_downloader.py +253 -0
- src/tools/web_search.py +71 -0
- src/utils/config_manager.py +206 -0
- src/utils/document_validator.py +168 -0
- src/utils/error_rate_tracker.py +111 -0
- src/utils/error_utils.py +82 -0
- src/utils/json_parser.py +110 -0
- src/utils/network/circuit_breaker.py +79 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Performance Monitor - Performance monitoring and tracking system
|
|
4
|
+
Records Agent execution time, Token consumption and other metrics
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Callable
|
|
8
|
+
from contextlib import contextmanager
|
|
9
|
+
from dataclasses import asdict, dataclass, field
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from functools import wraps
|
|
12
|
+
import json
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
import time
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class PerformanceMetrics:
|
|
20
|
+
"""Performance metrics"""
|
|
21
|
+
|
|
22
|
+
# Basic information
|
|
23
|
+
agent_name: str # Agent name
|
|
24
|
+
start_time: float # Start time (timestamp)
|
|
25
|
+
end_time: float | None = None # End time (timestamp)
|
|
26
|
+
duration: float | None = None # Duration (seconds)
|
|
27
|
+
|
|
28
|
+
# Token statistics
|
|
29
|
+
prompt_tokens: int = 0 # Prompt token count
|
|
30
|
+
completion_tokens: int = 0 # Generated token count
|
|
31
|
+
total_tokens: int = 0 # Total token count
|
|
32
|
+
|
|
33
|
+
# Request statistics
|
|
34
|
+
api_calls: int = 0 # API call count
|
|
35
|
+
errors: int = 0 # Error count
|
|
36
|
+
|
|
37
|
+
# Custom metrics
|
|
38
|
+
custom_metrics: dict[str, Any] = field(default_factory=dict)
|
|
39
|
+
|
|
40
|
+
def mark_end(self):
|
|
41
|
+
"""Mark end time and calculate duration"""
|
|
42
|
+
self.end_time = time.time()
|
|
43
|
+
if self.start_time:
|
|
44
|
+
self.duration = self.end_time - self.start_time
|
|
45
|
+
|
|
46
|
+
def add_tokens(self, prompt: int = 0, completion: int = 0):
|
|
47
|
+
"""Add Token statistics"""
|
|
48
|
+
self.prompt_tokens += prompt
|
|
49
|
+
self.completion_tokens += completion
|
|
50
|
+
self.total_tokens = self.prompt_tokens + self.completion_tokens
|
|
51
|
+
|
|
52
|
+
def add_api_call(self):
|
|
53
|
+
"""Increment API call count"""
|
|
54
|
+
self.api_calls += 1
|
|
55
|
+
|
|
56
|
+
def add_error(self):
|
|
57
|
+
"""Increment error count"""
|
|
58
|
+
self.errors += 1
|
|
59
|
+
|
|
60
|
+
def set_custom_metric(self, key: str, value: Any):
|
|
61
|
+
"""Set custom metric"""
|
|
62
|
+
self.custom_metrics[key] = value
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> dict[str, Any]:
|
|
65
|
+
"""Convert to dictionary"""
|
|
66
|
+
return asdict(self)
|
|
67
|
+
|
|
68
|
+
def summary(self) -> str:
|
|
69
|
+
"""Generate summary"""
|
|
70
|
+
lines = [
|
|
71
|
+
f"Agent: {self.agent_name}",
|
|
72
|
+
f"Duration: {self.duration:.2f}s" if self.duration else "Duration: N/A",
|
|
73
|
+
f"Total Tokens: {self.total_tokens}",
|
|
74
|
+
f" Prompt: {self.prompt_tokens}",
|
|
75
|
+
f" Completion: {self.completion_tokens}",
|
|
76
|
+
f"API Calls: {self.api_calls}",
|
|
77
|
+
f"Errors: {self.errors}",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
if self.custom_metrics:
|
|
81
|
+
lines.append("Custom Metrics:")
|
|
82
|
+
for k, v in self.custom_metrics.items():
|
|
83
|
+
lines.append(f" {k}: {v}")
|
|
84
|
+
|
|
85
|
+
return "\n".join(lines)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class PerformanceMonitor:
|
|
89
|
+
"""Performance monitor"""
|
|
90
|
+
|
|
91
|
+
def __init__(self, enabled: bool = True, save_dir: str | None = None):
|
|
92
|
+
"""
|
|
93
|
+
Initialize performance monitor
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
enabled: Whether to enable monitoring
|
|
97
|
+
save_dir: Save directory (None uses ./data/user/performance)
|
|
98
|
+
"""
|
|
99
|
+
self.enabled = enabled
|
|
100
|
+
|
|
101
|
+
if save_dir is None:
|
|
102
|
+
# Default to data/user/performance (relative to project root)
|
|
103
|
+
project_root = Path(__file__).parent.parent.parent.parent.parent
|
|
104
|
+
self.save_dir = project_root / "data" / "user" / "performance"
|
|
105
|
+
else:
|
|
106
|
+
self.save_dir = Path(save_dir)
|
|
107
|
+
|
|
108
|
+
if self.enabled:
|
|
109
|
+
self.save_dir.mkdir(parents=True, exist_ok=True)
|
|
110
|
+
|
|
111
|
+
# Current session metrics
|
|
112
|
+
self.metrics: dict[str, PerformanceMetrics] = {}
|
|
113
|
+
|
|
114
|
+
# Overall statistics
|
|
115
|
+
self.total_duration = 0.0
|
|
116
|
+
self.total_tokens = 0
|
|
117
|
+
self.total_api_calls = 0
|
|
118
|
+
self.total_errors = 0
|
|
119
|
+
|
|
120
|
+
def start_tracking(self, agent_name: str) -> PerformanceMetrics:
|
|
121
|
+
"""
|
|
122
|
+
Start tracking Agent performance
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
agent_name: Agent name
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
PerformanceMetrics instance
|
|
129
|
+
"""
|
|
130
|
+
if not self.enabled:
|
|
131
|
+
return PerformanceMetrics(agent_name=agent_name, start_time=time.time())
|
|
132
|
+
|
|
133
|
+
metrics = PerformanceMetrics(agent_name=agent_name, start_time=time.time())
|
|
134
|
+
|
|
135
|
+
self.metrics[agent_name] = metrics
|
|
136
|
+
return metrics
|
|
137
|
+
|
|
138
|
+
def end_tracking(self, agent_name: str):
|
|
139
|
+
"""
|
|
140
|
+
End tracking and update statistics
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
agent_name: Agent name
|
|
144
|
+
"""
|
|
145
|
+
if not self.enabled:
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
if agent_name in self.metrics:
|
|
149
|
+
metrics = self.metrics[agent_name]
|
|
150
|
+
metrics.mark_end()
|
|
151
|
+
|
|
152
|
+
# Update overall statistics
|
|
153
|
+
if metrics.duration:
|
|
154
|
+
self.total_duration += metrics.duration
|
|
155
|
+
self.total_tokens += metrics.total_tokens
|
|
156
|
+
self.total_api_calls += metrics.api_calls
|
|
157
|
+
self.total_errors += metrics.errors
|
|
158
|
+
|
|
159
|
+
@contextmanager
|
|
160
|
+
def track(self, agent_name: str):
|
|
161
|
+
"""
|
|
162
|
+
Context manager: automatically track Agent performance
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
agent_name: Agent name
|
|
166
|
+
|
|
167
|
+
Usage:
|
|
168
|
+
with monitor.track("agent_name"):
|
|
169
|
+
# Agent execution logic
|
|
170
|
+
...
|
|
171
|
+
"""
|
|
172
|
+
# Start tracking
|
|
173
|
+
metrics = self.start_tracking(agent_name)
|
|
174
|
+
try:
|
|
175
|
+
yield metrics
|
|
176
|
+
except Exception:
|
|
177
|
+
# Record error
|
|
178
|
+
if self.enabled:
|
|
179
|
+
metrics.add_error()
|
|
180
|
+
raise
|
|
181
|
+
finally:
|
|
182
|
+
# End tracking
|
|
183
|
+
self.end_tracking(agent_name)
|
|
184
|
+
|
|
185
|
+
def get_metrics(self, agent_name: str) -> PerformanceMetrics | None:
|
|
186
|
+
"""
|
|
187
|
+
Get Agent performance metrics
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
agent_name: Agent name
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
PerformanceMetrics instance, or None if not found
|
|
194
|
+
"""
|
|
195
|
+
return self.metrics.get(agent_name)
|
|
196
|
+
|
|
197
|
+
def get_all_metrics(self) -> dict[str, PerformanceMetrics]:
|
|
198
|
+
"""Get all metrics"""
|
|
199
|
+
return self.metrics
|
|
200
|
+
|
|
201
|
+
def get_summary(self) -> dict[str, Any]:
|
|
202
|
+
"""
|
|
203
|
+
Get overall statistics summary
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
{
|
|
207
|
+
'total_duration': float,
|
|
208
|
+
'total_tokens': int,
|
|
209
|
+
'total_api_calls': int,
|
|
210
|
+
'total_errors': int,
|
|
211
|
+
'agents': Dict[str, Dict]
|
|
212
|
+
}
|
|
213
|
+
"""
|
|
214
|
+
return {
|
|
215
|
+
"total_duration": self.total_duration,
|
|
216
|
+
"total_tokens": self.total_tokens,
|
|
217
|
+
"total_api_calls": self.total_api_calls,
|
|
218
|
+
"total_errors": self.total_errors,
|
|
219
|
+
"agents": {name: metrics.to_dict() for name, metrics in self.metrics.items()},
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
def generate_report(self) -> dict[str, Any]:
|
|
223
|
+
"""
|
|
224
|
+
Generate performance report (alias for get_summary)
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Performance report dictionary
|
|
228
|
+
"""
|
|
229
|
+
return self.get_summary()
|
|
230
|
+
|
|
231
|
+
def save(self, filepath: str | None = None) -> str:
|
|
232
|
+
"""
|
|
233
|
+
Save performance metrics to file
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
filepath: Save path (None for auto-generated)
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Saved file path
|
|
240
|
+
"""
|
|
241
|
+
if not self.enabled:
|
|
242
|
+
return ""
|
|
243
|
+
|
|
244
|
+
if filepath is None:
|
|
245
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
246
|
+
filepath = self.save_dir / f"performance_{timestamp}.json"
|
|
247
|
+
else:
|
|
248
|
+
filepath = Path(filepath)
|
|
249
|
+
|
|
250
|
+
summary = self.get_summary()
|
|
251
|
+
|
|
252
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
|
253
|
+
json.dump(summary, f, ensure_ascii=False, indent=2)
|
|
254
|
+
|
|
255
|
+
return str(filepath)
|
|
256
|
+
|
|
257
|
+
def print_summary(self):
|
|
258
|
+
"""Print overall statistics summary"""
|
|
259
|
+
print("=" * 60)
|
|
260
|
+
print("Performance Monitoring Summary")
|
|
261
|
+
print("=" * 60)
|
|
262
|
+
print(f"Total Duration: {self.total_duration:.2f}s")
|
|
263
|
+
print(f"Total Tokens: {self.total_tokens}")
|
|
264
|
+
print(f"Total API Calls: {self.total_api_calls}")
|
|
265
|
+
print(f"Total Errors: {self.total_errors}")
|
|
266
|
+
print()
|
|
267
|
+
print("Agent Details:")
|
|
268
|
+
print("-" * 60)
|
|
269
|
+
|
|
270
|
+
for agent_name, metrics in self.metrics.items():
|
|
271
|
+
print(f"\n{agent_name}:")
|
|
272
|
+
print(f" Duration: {metrics.duration:.2f}s" if metrics.duration else " Duration: N/A")
|
|
273
|
+
print(f" Tokens: {metrics.total_tokens}")
|
|
274
|
+
print(f" API Calls: {metrics.api_calls}")
|
|
275
|
+
print(f" Errors: {metrics.errors}")
|
|
276
|
+
|
|
277
|
+
print("=" * 60)
|
|
278
|
+
|
|
279
|
+
def reset(self):
|
|
280
|
+
"""Reset all statistics"""
|
|
281
|
+
self.metrics.clear()
|
|
282
|
+
self.total_duration = 0.0
|
|
283
|
+
self.total_tokens = 0
|
|
284
|
+
self.total_api_calls = 0
|
|
285
|
+
self.total_errors = 0
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# Decorator: automatically track Agent performance
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def track_performance(monitor: PerformanceMonitor):
|
|
292
|
+
"""
|
|
293
|
+
Performance tracking decorator
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
monitor: PerformanceMonitor instance
|
|
297
|
+
|
|
298
|
+
Usage:
|
|
299
|
+
@track_performance(monitor)
|
|
300
|
+
async def my_agent_process(...):
|
|
301
|
+
...
|
|
302
|
+
"""
|
|
303
|
+
|
|
304
|
+
def decorator(func: Callable) -> Callable:
|
|
305
|
+
@wraps(func)
|
|
306
|
+
async def wrapper(self, *args, **kwargs):
|
|
307
|
+
agent_name = getattr(self, "agent_name", func.__name__)
|
|
308
|
+
|
|
309
|
+
# Start tracking
|
|
310
|
+
metrics = monitor.start_tracking(agent_name)
|
|
311
|
+
|
|
312
|
+
try:
|
|
313
|
+
result = await func(self, *args, **kwargs)
|
|
314
|
+
return result
|
|
315
|
+
except Exception:
|
|
316
|
+
metrics.add_error()
|
|
317
|
+
raise
|
|
318
|
+
finally:
|
|
319
|
+
# End tracking
|
|
320
|
+
monitor.end_tracking(agent_name)
|
|
321
|
+
|
|
322
|
+
return wrapper
|
|
323
|
+
|
|
324
|
+
return decorator
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# Global monitor instance
|
|
328
|
+
|
|
329
|
+
_global_monitor: PerformanceMonitor | None = None
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def get_monitor(enabled: bool = True, save_dir: str | None = None) -> PerformanceMonitor:
|
|
333
|
+
"""
|
|
334
|
+
Get global monitor instance (singleton pattern)
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
enabled: Whether to enable
|
|
338
|
+
save_dir: Save directory
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
PerformanceMonitor instance
|
|
342
|
+
"""
|
|
343
|
+
global _global_monitor
|
|
344
|
+
|
|
345
|
+
if _global_monitor is None:
|
|
346
|
+
_global_monitor = PerformanceMonitor(enabled=enabled, save_dir=save_dir)
|
|
347
|
+
|
|
348
|
+
return _global_monitor
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def init_monitor_from_config(config: dict) -> PerformanceMonitor:
|
|
352
|
+
"""
|
|
353
|
+
Initialize monitor from configuration
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
config: Configuration dictionary
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
PerformanceMonitor instance
|
|
360
|
+
"""
|
|
361
|
+
monitoring_config = config.get("monitoring", {})
|
|
362
|
+
|
|
363
|
+
enabled = monitoring_config.get("enabled", True)
|
|
364
|
+
save_dir = monitoring_config.get("save_dir", "./logs/performance")
|
|
365
|
+
|
|
366
|
+
return get_monitor(enabled=enabled, save_dir=save_dir)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
if __name__ == "__main__":
|
|
370
|
+
# Test performance monitoring
|
|
371
|
+
print("Performance Monitoring Test")
|
|
372
|
+
print("=" * 60)
|
|
373
|
+
|
|
374
|
+
# Create monitor
|
|
375
|
+
monitor = PerformanceMonitor(enabled=True)
|
|
376
|
+
|
|
377
|
+
# Simulate Agent execution
|
|
378
|
+
import asyncio
|
|
379
|
+
|
|
380
|
+
async def simulate_agent(agent_name: str, duration: float, tokens: int):
|
|
381
|
+
"""Simulate Agent execution"""
|
|
382
|
+
metrics = monitor.start_tracking(agent_name)
|
|
383
|
+
|
|
384
|
+
# Simulate work
|
|
385
|
+
await asyncio.sleep(duration)
|
|
386
|
+
|
|
387
|
+
# Record tokens
|
|
388
|
+
metrics.add_tokens(prompt=tokens // 2, completion=tokens // 2)
|
|
389
|
+
metrics.add_api_call()
|
|
390
|
+
|
|
391
|
+
monitor.end_tracking(agent_name)
|
|
392
|
+
|
|
393
|
+
# Run simulation
|
|
394
|
+
async def run_simulation():
|
|
395
|
+
await simulate_agent("decompose_agent", 0.5, 100)
|
|
396
|
+
await simulate_agent("rag_agent", 1.0, 500)
|
|
397
|
+
await simulate_agent("plan_agent", 0.8, 300)
|
|
398
|
+
await simulate_agent("execute_agent", 1.5, 800)
|
|
399
|
+
|
|
400
|
+
asyncio.run(run_simulation())
|
|
401
|
+
|
|
402
|
+
# Print summary
|
|
403
|
+
monitor.print_summary()
|
|
404
|
+
|
|
405
|
+
# Save results
|
|
406
|
+
saved_path = monitor.save()
|
|
407
|
+
print(f"\nPerformance metrics saved to: {saved_path}")
|