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.
Files changed (276) hide show
  1. realtimex_deeptutor/__init__.py +67 -0
  2. realtimex_deeptutor-0.5.0.post1.dist-info/METADATA +1612 -0
  3. realtimex_deeptutor-0.5.0.post1.dist-info/RECORD +276 -0
  4. realtimex_deeptutor-0.5.0.post1.dist-info/WHEEL +5 -0
  5. realtimex_deeptutor-0.5.0.post1.dist-info/entry_points.txt +2 -0
  6. realtimex_deeptutor-0.5.0.post1.dist-info/licenses/LICENSE +661 -0
  7. realtimex_deeptutor-0.5.0.post1.dist-info/top_level.txt +2 -0
  8. src/__init__.py +40 -0
  9. src/agents/__init__.py +24 -0
  10. src/agents/base_agent.py +657 -0
  11. src/agents/chat/__init__.py +24 -0
  12. src/agents/chat/chat_agent.py +435 -0
  13. src/agents/chat/prompts/en/chat_agent.yaml +35 -0
  14. src/agents/chat/prompts/zh/chat_agent.yaml +35 -0
  15. src/agents/chat/session_manager.py +311 -0
  16. src/agents/co_writer/__init__.py +0 -0
  17. src/agents/co_writer/edit_agent.py +260 -0
  18. src/agents/co_writer/narrator_agent.py +423 -0
  19. src/agents/co_writer/prompts/en/edit_agent.yaml +113 -0
  20. src/agents/co_writer/prompts/en/narrator_agent.yaml +88 -0
  21. src/agents/co_writer/prompts/zh/edit_agent.yaml +113 -0
  22. src/agents/co_writer/prompts/zh/narrator_agent.yaml +88 -0
  23. src/agents/guide/__init__.py +16 -0
  24. src/agents/guide/agents/__init__.py +11 -0
  25. src/agents/guide/agents/chat_agent.py +104 -0
  26. src/agents/guide/agents/interactive_agent.py +223 -0
  27. src/agents/guide/agents/locate_agent.py +149 -0
  28. src/agents/guide/agents/summary_agent.py +150 -0
  29. src/agents/guide/guide_manager.py +500 -0
  30. src/agents/guide/prompts/en/chat_agent.yaml +41 -0
  31. src/agents/guide/prompts/en/interactive_agent.yaml +202 -0
  32. src/agents/guide/prompts/en/locate_agent.yaml +68 -0
  33. src/agents/guide/prompts/en/summary_agent.yaml +157 -0
  34. src/agents/guide/prompts/zh/chat_agent.yaml +41 -0
  35. src/agents/guide/prompts/zh/interactive_agent.yaml +626 -0
  36. src/agents/guide/prompts/zh/locate_agent.yaml +68 -0
  37. src/agents/guide/prompts/zh/summary_agent.yaml +157 -0
  38. src/agents/ideagen/__init__.py +12 -0
  39. src/agents/ideagen/idea_generation_workflow.py +426 -0
  40. src/agents/ideagen/material_organizer_agent.py +173 -0
  41. src/agents/ideagen/prompts/en/idea_generation.yaml +187 -0
  42. src/agents/ideagen/prompts/en/material_organizer.yaml +69 -0
  43. src/agents/ideagen/prompts/zh/idea_generation.yaml +187 -0
  44. src/agents/ideagen/prompts/zh/material_organizer.yaml +69 -0
  45. src/agents/question/__init__.py +24 -0
  46. src/agents/question/agents/__init__.py +18 -0
  47. src/agents/question/agents/generate_agent.py +381 -0
  48. src/agents/question/agents/relevance_analyzer.py +207 -0
  49. src/agents/question/agents/retrieve_agent.py +239 -0
  50. src/agents/question/coordinator.py +718 -0
  51. src/agents/question/example.py +109 -0
  52. src/agents/question/prompts/en/coordinator.yaml +75 -0
  53. src/agents/question/prompts/en/generate_agent.yaml +77 -0
  54. src/agents/question/prompts/en/relevance_analyzer.yaml +41 -0
  55. src/agents/question/prompts/en/retrieve_agent.yaml +32 -0
  56. src/agents/question/prompts/zh/coordinator.yaml +75 -0
  57. src/agents/question/prompts/zh/generate_agent.yaml +77 -0
  58. src/agents/question/prompts/zh/relevance_analyzer.yaml +39 -0
  59. src/agents/question/prompts/zh/retrieve_agent.yaml +30 -0
  60. src/agents/research/agents/__init__.py +23 -0
  61. src/agents/research/agents/decompose_agent.py +507 -0
  62. src/agents/research/agents/manager_agent.py +228 -0
  63. src/agents/research/agents/note_agent.py +180 -0
  64. src/agents/research/agents/rephrase_agent.py +263 -0
  65. src/agents/research/agents/reporting_agent.py +1333 -0
  66. src/agents/research/agents/research_agent.py +714 -0
  67. src/agents/research/data_structures.py +451 -0
  68. src/agents/research/main.py +188 -0
  69. src/agents/research/prompts/en/decompose_agent.yaml +89 -0
  70. src/agents/research/prompts/en/manager_agent.yaml +24 -0
  71. src/agents/research/prompts/en/note_agent.yaml +121 -0
  72. src/agents/research/prompts/en/rephrase_agent.yaml +58 -0
  73. src/agents/research/prompts/en/reporting_agent.yaml +380 -0
  74. src/agents/research/prompts/en/research_agent.yaml +173 -0
  75. src/agents/research/prompts/zh/decompose_agent.yaml +89 -0
  76. src/agents/research/prompts/zh/manager_agent.yaml +24 -0
  77. src/agents/research/prompts/zh/note_agent.yaml +121 -0
  78. src/agents/research/prompts/zh/rephrase_agent.yaml +58 -0
  79. src/agents/research/prompts/zh/reporting_agent.yaml +380 -0
  80. src/agents/research/prompts/zh/research_agent.yaml +173 -0
  81. src/agents/research/research_pipeline.py +1309 -0
  82. src/agents/research/utils/__init__.py +60 -0
  83. src/agents/research/utils/citation_manager.py +799 -0
  84. src/agents/research/utils/json_utils.py +98 -0
  85. src/agents/research/utils/token_tracker.py +297 -0
  86. src/agents/solve/__init__.py +80 -0
  87. src/agents/solve/analysis_loop/__init__.py +14 -0
  88. src/agents/solve/analysis_loop/investigate_agent.py +414 -0
  89. src/agents/solve/analysis_loop/note_agent.py +190 -0
  90. src/agents/solve/main_solver.py +862 -0
  91. src/agents/solve/memory/__init__.py +34 -0
  92. src/agents/solve/memory/citation_memory.py +353 -0
  93. src/agents/solve/memory/investigate_memory.py +226 -0
  94. src/agents/solve/memory/solve_memory.py +340 -0
  95. src/agents/solve/prompts/en/analysis_loop/investigate_agent.yaml +55 -0
  96. src/agents/solve/prompts/en/analysis_loop/note_agent.yaml +54 -0
  97. src/agents/solve/prompts/en/solve_loop/manager_agent.yaml +67 -0
  98. src/agents/solve/prompts/en/solve_loop/precision_answer_agent.yaml +62 -0
  99. src/agents/solve/prompts/en/solve_loop/response_agent.yaml +90 -0
  100. src/agents/solve/prompts/en/solve_loop/solve_agent.yaml +75 -0
  101. src/agents/solve/prompts/en/solve_loop/tool_agent.yaml +38 -0
  102. src/agents/solve/prompts/zh/analysis_loop/investigate_agent.yaml +53 -0
  103. src/agents/solve/prompts/zh/analysis_loop/note_agent.yaml +54 -0
  104. src/agents/solve/prompts/zh/solve_loop/manager_agent.yaml +66 -0
  105. src/agents/solve/prompts/zh/solve_loop/precision_answer_agent.yaml +62 -0
  106. src/agents/solve/prompts/zh/solve_loop/response_agent.yaml +90 -0
  107. src/agents/solve/prompts/zh/solve_loop/solve_agent.yaml +76 -0
  108. src/agents/solve/prompts/zh/solve_loop/tool_agent.yaml +41 -0
  109. src/agents/solve/solve_loop/__init__.py +22 -0
  110. src/agents/solve/solve_loop/citation_manager.py +74 -0
  111. src/agents/solve/solve_loop/manager_agent.py +274 -0
  112. src/agents/solve/solve_loop/precision_answer_agent.py +96 -0
  113. src/agents/solve/solve_loop/response_agent.py +301 -0
  114. src/agents/solve/solve_loop/solve_agent.py +325 -0
  115. src/agents/solve/solve_loop/tool_agent.py +470 -0
  116. src/agents/solve/utils/__init__.py +64 -0
  117. src/agents/solve/utils/config_validator.py +313 -0
  118. src/agents/solve/utils/display_manager.py +223 -0
  119. src/agents/solve/utils/error_handler.py +363 -0
  120. src/agents/solve/utils/json_utils.py +98 -0
  121. src/agents/solve/utils/performance_monitor.py +407 -0
  122. src/agents/solve/utils/token_tracker.py +541 -0
  123. src/api/__init__.py +0 -0
  124. src/api/main.py +240 -0
  125. src/api/routers/__init__.py +1 -0
  126. src/api/routers/agent_config.py +69 -0
  127. src/api/routers/chat.py +296 -0
  128. src/api/routers/co_writer.py +337 -0
  129. src/api/routers/config.py +627 -0
  130. src/api/routers/dashboard.py +18 -0
  131. src/api/routers/guide.py +337 -0
  132. src/api/routers/ideagen.py +436 -0
  133. src/api/routers/knowledge.py +821 -0
  134. src/api/routers/notebook.py +247 -0
  135. src/api/routers/question.py +537 -0
  136. src/api/routers/research.py +394 -0
  137. src/api/routers/settings.py +164 -0
  138. src/api/routers/solve.py +305 -0
  139. src/api/routers/system.py +252 -0
  140. src/api/run_server.py +61 -0
  141. src/api/utils/history.py +172 -0
  142. src/api/utils/log_interceptor.py +21 -0
  143. src/api/utils/notebook_manager.py +415 -0
  144. src/api/utils/progress_broadcaster.py +72 -0
  145. src/api/utils/task_id_manager.py +100 -0
  146. src/config/__init__.py +0 -0
  147. src/config/accessors.py +18 -0
  148. src/config/constants.py +34 -0
  149. src/config/defaults.py +18 -0
  150. src/config/schema.py +38 -0
  151. src/config/settings.py +50 -0
  152. src/core/errors.py +62 -0
  153. src/knowledge/__init__.py +23 -0
  154. src/knowledge/add_documents.py +606 -0
  155. src/knowledge/config.py +65 -0
  156. src/knowledge/example_add_documents.py +236 -0
  157. src/knowledge/extract_numbered_items.py +1039 -0
  158. src/knowledge/initializer.py +621 -0
  159. src/knowledge/kb.py +22 -0
  160. src/knowledge/manager.py +782 -0
  161. src/knowledge/progress_tracker.py +182 -0
  162. src/knowledge/start_kb.py +535 -0
  163. src/logging/__init__.py +103 -0
  164. src/logging/adapters/__init__.py +17 -0
  165. src/logging/adapters/lightrag.py +184 -0
  166. src/logging/adapters/llamaindex.py +141 -0
  167. src/logging/config.py +80 -0
  168. src/logging/handlers/__init__.py +20 -0
  169. src/logging/handlers/console.py +75 -0
  170. src/logging/handlers/file.py +201 -0
  171. src/logging/handlers/websocket.py +127 -0
  172. src/logging/logger.py +709 -0
  173. src/logging/stats/__init__.py +16 -0
  174. src/logging/stats/llm_stats.py +179 -0
  175. src/services/__init__.py +56 -0
  176. src/services/config/__init__.py +61 -0
  177. src/services/config/knowledge_base_config.py +210 -0
  178. src/services/config/loader.py +260 -0
  179. src/services/config/unified_config.py +603 -0
  180. src/services/embedding/__init__.py +45 -0
  181. src/services/embedding/adapters/__init__.py +22 -0
  182. src/services/embedding/adapters/base.py +106 -0
  183. src/services/embedding/adapters/cohere.py +127 -0
  184. src/services/embedding/adapters/jina.py +99 -0
  185. src/services/embedding/adapters/ollama.py +116 -0
  186. src/services/embedding/adapters/openai_compatible.py +96 -0
  187. src/services/embedding/client.py +159 -0
  188. src/services/embedding/config.py +156 -0
  189. src/services/embedding/provider.py +119 -0
  190. src/services/llm/__init__.py +152 -0
  191. src/services/llm/capabilities.py +313 -0
  192. src/services/llm/client.py +302 -0
  193. src/services/llm/cloud_provider.py +530 -0
  194. src/services/llm/config.py +200 -0
  195. src/services/llm/error_mapping.py +103 -0
  196. src/services/llm/exceptions.py +152 -0
  197. src/services/llm/factory.py +450 -0
  198. src/services/llm/local_provider.py +347 -0
  199. src/services/llm/providers/anthropic.py +95 -0
  200. src/services/llm/providers/base_provider.py +93 -0
  201. src/services/llm/providers/open_ai.py +83 -0
  202. src/services/llm/registry.py +71 -0
  203. src/services/llm/telemetry.py +40 -0
  204. src/services/llm/types.py +27 -0
  205. src/services/llm/utils.py +333 -0
  206. src/services/prompt/__init__.py +25 -0
  207. src/services/prompt/manager.py +206 -0
  208. src/services/rag/__init__.py +64 -0
  209. src/services/rag/components/__init__.py +29 -0
  210. src/services/rag/components/base.py +59 -0
  211. src/services/rag/components/chunkers/__init__.py +18 -0
  212. src/services/rag/components/chunkers/base.py +34 -0
  213. src/services/rag/components/chunkers/fixed.py +71 -0
  214. src/services/rag/components/chunkers/numbered_item.py +94 -0
  215. src/services/rag/components/chunkers/semantic.py +97 -0
  216. src/services/rag/components/embedders/__init__.py +14 -0
  217. src/services/rag/components/embedders/base.py +32 -0
  218. src/services/rag/components/embedders/openai.py +63 -0
  219. src/services/rag/components/indexers/__init__.py +18 -0
  220. src/services/rag/components/indexers/base.py +35 -0
  221. src/services/rag/components/indexers/graph.py +172 -0
  222. src/services/rag/components/indexers/lightrag.py +156 -0
  223. src/services/rag/components/indexers/vector.py +146 -0
  224. src/services/rag/components/parsers/__init__.py +18 -0
  225. src/services/rag/components/parsers/base.py +35 -0
  226. src/services/rag/components/parsers/markdown.py +52 -0
  227. src/services/rag/components/parsers/pdf.py +115 -0
  228. src/services/rag/components/parsers/text.py +86 -0
  229. src/services/rag/components/retrievers/__init__.py +18 -0
  230. src/services/rag/components/retrievers/base.py +34 -0
  231. src/services/rag/components/retrievers/dense.py +200 -0
  232. src/services/rag/components/retrievers/hybrid.py +164 -0
  233. src/services/rag/components/retrievers/lightrag.py +169 -0
  234. src/services/rag/components/routing.py +286 -0
  235. src/services/rag/factory.py +234 -0
  236. src/services/rag/pipeline.py +215 -0
  237. src/services/rag/pipelines/__init__.py +32 -0
  238. src/services/rag/pipelines/academic.py +44 -0
  239. src/services/rag/pipelines/lightrag.py +43 -0
  240. src/services/rag/pipelines/llamaindex.py +313 -0
  241. src/services/rag/pipelines/raganything.py +384 -0
  242. src/services/rag/service.py +244 -0
  243. src/services/rag/types.py +73 -0
  244. src/services/search/__init__.py +284 -0
  245. src/services/search/base.py +87 -0
  246. src/services/search/consolidation.py +398 -0
  247. src/services/search/providers/__init__.py +128 -0
  248. src/services/search/providers/baidu.py +188 -0
  249. src/services/search/providers/exa.py +194 -0
  250. src/services/search/providers/jina.py +161 -0
  251. src/services/search/providers/perplexity.py +153 -0
  252. src/services/search/providers/serper.py +209 -0
  253. src/services/search/providers/tavily.py +161 -0
  254. src/services/search/types.py +114 -0
  255. src/services/setup/__init__.py +34 -0
  256. src/services/setup/init.py +285 -0
  257. src/services/tts/__init__.py +16 -0
  258. src/services/tts/config.py +99 -0
  259. src/tools/__init__.py +91 -0
  260. src/tools/code_executor.py +536 -0
  261. src/tools/paper_search_tool.py +171 -0
  262. src/tools/query_item_tool.py +310 -0
  263. src/tools/question/__init__.py +15 -0
  264. src/tools/question/exam_mimic.py +616 -0
  265. src/tools/question/pdf_parser.py +211 -0
  266. src/tools/question/question_extractor.py +397 -0
  267. src/tools/rag_tool.py +173 -0
  268. src/tools/tex_chunker.py +339 -0
  269. src/tools/tex_downloader.py +253 -0
  270. src/tools/web_search.py +71 -0
  271. src/utils/config_manager.py +206 -0
  272. src/utils/document_validator.py +168 -0
  273. src/utils/error_rate_tracker.py +111 -0
  274. src/utils/error_utils.py +82 -0
  275. src/utils/json_parser.py +110 -0
  276. 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}")