realtimex-deeptutor 0.5.0.post1__py3-none-any.whl → 0.5.0.post3__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 (145) hide show
  1. {realtimex_deeptutor-0.5.0.post1.dist-info → realtimex_deeptutor-0.5.0.post3.dist-info}/METADATA +24 -17
  2. {realtimex_deeptutor-0.5.0.post1.dist-info → realtimex_deeptutor-0.5.0.post3.dist-info}/RECORD +143 -123
  3. {realtimex_deeptutor-0.5.0.post1.dist-info → realtimex_deeptutor-0.5.0.post3.dist-info}/WHEEL +1 -1
  4. realtimex_deeptutor-0.5.0.post3.dist-info/entry_points.txt +4 -0
  5. {realtimex_deeptutor-0.5.0.post1.dist-info → realtimex_deeptutor-0.5.0.post3.dist-info}/top_level.txt +1 -0
  6. scripts/__init__.py +1 -0
  7. scripts/audit_prompts.py +179 -0
  8. scripts/check_install.py +460 -0
  9. scripts/generate_roster.py +327 -0
  10. scripts/install_all.py +653 -0
  11. scripts/migrate_kb.py +655 -0
  12. scripts/start.py +807 -0
  13. scripts/start_web.py +632 -0
  14. scripts/sync_prompts_from_en.py +147 -0
  15. src/__init__.py +2 -2
  16. src/agents/ideagen/material_organizer_agent.py +2 -0
  17. src/agents/solve/__init__.py +6 -0
  18. src/agents/solve/main_solver.py +9 -0
  19. src/agents/solve/prompts/zh/analysis_loop/investigate_agent.yaml +9 -7
  20. src/agents/solve/session_manager.py +345 -0
  21. src/api/main.py +14 -0
  22. src/api/routers/chat.py +3 -3
  23. src/api/routers/co_writer.py +12 -7
  24. src/api/routers/config.py +1 -0
  25. src/api/routers/guide.py +3 -1
  26. src/api/routers/ideagen.py +7 -0
  27. src/api/routers/knowledge.py +64 -12
  28. src/api/routers/question.py +2 -0
  29. src/api/routers/realtimex.py +137 -0
  30. src/api/routers/research.py +9 -0
  31. src/api/routers/solve.py +120 -2
  32. src/cli/__init__.py +13 -0
  33. src/cli/start.py +209 -0
  34. src/config/constants.py +11 -9
  35. src/knowledge/add_documents.py +453 -213
  36. src/knowledge/extract_numbered_items.py +9 -10
  37. src/knowledge/initializer.py +102 -101
  38. src/knowledge/manager.py +251 -74
  39. src/knowledge/progress_tracker.py +43 -2
  40. src/knowledge/start_kb.py +11 -2
  41. src/logging/__init__.py +5 -0
  42. src/logging/adapters/__init__.py +1 -0
  43. src/logging/adapters/lightrag.py +25 -18
  44. src/logging/adapters/llamaindex.py +1 -0
  45. src/logging/config.py +30 -27
  46. src/logging/handlers/__init__.py +1 -0
  47. src/logging/handlers/console.py +7 -50
  48. src/logging/handlers/file.py +5 -20
  49. src/logging/handlers/websocket.py +23 -19
  50. src/logging/logger.py +161 -126
  51. src/logging/stats/__init__.py +1 -0
  52. src/logging/stats/llm_stats.py +37 -17
  53. src/services/__init__.py +17 -1
  54. src/services/config/__init__.py +1 -0
  55. src/services/config/knowledge_base_config.py +1 -0
  56. src/services/config/loader.py +1 -1
  57. src/services/config/unified_config.py +211 -4
  58. src/services/embedding/__init__.py +1 -0
  59. src/services/embedding/adapters/__init__.py +3 -0
  60. src/services/embedding/adapters/base.py +1 -0
  61. src/services/embedding/adapters/cohere.py +1 -0
  62. src/services/embedding/adapters/jina.py +1 -0
  63. src/services/embedding/adapters/ollama.py +1 -0
  64. src/services/embedding/adapters/openai_compatible.py +1 -0
  65. src/services/embedding/adapters/realtimex.py +125 -0
  66. src/services/embedding/client.py +27 -0
  67. src/services/embedding/config.py +3 -0
  68. src/services/embedding/provider.py +1 -0
  69. src/services/llm/__init__.py +17 -3
  70. src/services/llm/capabilities.py +47 -0
  71. src/services/llm/client.py +32 -0
  72. src/services/llm/cloud_provider.py +21 -4
  73. src/services/llm/config.py +36 -2
  74. src/services/llm/error_mapping.py +1 -0
  75. src/services/llm/exceptions.py +30 -0
  76. src/services/llm/factory.py +55 -16
  77. src/services/llm/local_provider.py +1 -0
  78. src/services/llm/providers/anthropic.py +1 -0
  79. src/services/llm/providers/base_provider.py +1 -0
  80. src/services/llm/providers/open_ai.py +1 -0
  81. src/services/llm/realtimex_provider.py +240 -0
  82. src/services/llm/registry.py +1 -0
  83. src/services/llm/telemetry.py +1 -0
  84. src/services/llm/types.py +1 -0
  85. src/services/llm/utils.py +1 -0
  86. src/services/prompt/__init__.py +1 -0
  87. src/services/prompt/manager.py +3 -2
  88. src/services/rag/__init__.py +27 -5
  89. src/services/rag/components/__init__.py +1 -0
  90. src/services/rag/components/base.py +1 -0
  91. src/services/rag/components/chunkers/__init__.py +1 -0
  92. src/services/rag/components/chunkers/base.py +1 -0
  93. src/services/rag/components/chunkers/fixed.py +1 -0
  94. src/services/rag/components/chunkers/numbered_item.py +1 -0
  95. src/services/rag/components/chunkers/semantic.py +1 -0
  96. src/services/rag/components/embedders/__init__.py +1 -0
  97. src/services/rag/components/embedders/base.py +1 -0
  98. src/services/rag/components/embedders/openai.py +1 -0
  99. src/services/rag/components/indexers/__init__.py +1 -0
  100. src/services/rag/components/indexers/base.py +1 -0
  101. src/services/rag/components/indexers/graph.py +5 -44
  102. src/services/rag/components/indexers/lightrag.py +5 -44
  103. src/services/rag/components/indexers/vector.py +1 -0
  104. src/services/rag/components/parsers/__init__.py +1 -0
  105. src/services/rag/components/parsers/base.py +1 -0
  106. src/services/rag/components/parsers/markdown.py +1 -0
  107. src/services/rag/components/parsers/pdf.py +1 -0
  108. src/services/rag/components/parsers/text.py +1 -0
  109. src/services/rag/components/retrievers/__init__.py +1 -0
  110. src/services/rag/components/retrievers/base.py +1 -0
  111. src/services/rag/components/retrievers/dense.py +1 -0
  112. src/services/rag/components/retrievers/hybrid.py +5 -44
  113. src/services/rag/components/retrievers/lightrag.py +5 -44
  114. src/services/rag/components/routing.py +48 -0
  115. src/services/rag/factory.py +112 -46
  116. src/services/rag/pipeline.py +1 -0
  117. src/services/rag/pipelines/__init__.py +27 -18
  118. src/services/rag/pipelines/lightrag.py +1 -0
  119. src/services/rag/pipelines/llamaindex.py +99 -0
  120. src/services/rag/pipelines/raganything.py +67 -100
  121. src/services/rag/pipelines/raganything_docling.py +368 -0
  122. src/services/rag/service.py +5 -12
  123. src/services/rag/types.py +1 -0
  124. src/services/rag/utils/__init__.py +17 -0
  125. src/services/rag/utils/image_migration.py +279 -0
  126. src/services/search/__init__.py +1 -0
  127. src/services/search/base.py +1 -0
  128. src/services/search/consolidation.py +1 -0
  129. src/services/search/providers/__init__.py +1 -0
  130. src/services/search/providers/baidu.py +1 -0
  131. src/services/search/providers/exa.py +1 -0
  132. src/services/search/providers/jina.py +1 -0
  133. src/services/search/providers/perplexity.py +1 -0
  134. src/services/search/providers/serper.py +1 -0
  135. src/services/search/providers/tavily.py +1 -0
  136. src/services/search/types.py +1 -0
  137. src/services/settings/__init__.py +1 -0
  138. src/services/settings/interface_settings.py +78 -0
  139. src/services/setup/__init__.py +1 -0
  140. src/services/tts/__init__.py +1 -0
  141. src/services/tts/config.py +1 -0
  142. src/utils/realtimex.py +284 -0
  143. realtimex_deeptutor-0.5.0.post1.dist-info/entry_points.txt +0 -2
  144. src/services/rag/pipelines/academic.py +0 -44
  145. {realtimex_deeptutor-0.5.0.post1.dist-info → realtimex_deeptutor-0.5.0.post3.dist-info}/licenses/LICENSE +0 -0
src/logging/config.py CHANGED
@@ -1,43 +1,38 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  Logging Configuration
3
4
  =====================
4
5
 
5
- Configuration settings for the logging system.
6
+ Unified logging configuration for the entire DeepTutor system.
7
+ A single `level` parameter controls all logging (including RAG modules).
6
8
  """
7
9
 
8
10
  from dataclasses import dataclass
9
11
  from pathlib import Path
10
- from typing import Optional
12
+ from typing import Dict, Optional
11
13
 
12
14
 
13
15
  @dataclass
14
16
  class LoggingConfig:
15
17
  """Configuration for the logging system."""
16
18
 
19
+ # Global log level (controls entire system including RAG modules)
20
+ level: str = "DEBUG"
21
+
17
22
  # Output settings
18
23
  console_output: bool = True
19
24
  file_output: bool = True
20
25
 
21
- # Log levels
22
- console_level: str = "INFO"
23
- file_level: str = "DEBUG"
24
-
25
26
  # Log directory (relative to project root or absolute)
26
27
  log_dir: Optional[str] = None
27
28
 
29
+ # RAG module logger name mapping
30
+ rag_logger_names: Optional[Dict[str, str]] = None
31
+
28
32
  # File rotation settings
29
33
  max_bytes: int = 10 * 1024 * 1024 # 10MB
30
34
  backup_count: int = 5
31
35
 
32
- # WebSocket streaming
33
- websocket_enabled: bool = True
34
- websocket_queue_size: int = 1000
35
-
36
- # LightRAG forwarding
37
- lightrag_forwarding_enabled: bool = True
38
- lightrag_min_level: str = "INFO"
39
- lightrag_add_prefix: bool = True
40
-
41
36
 
42
37
  def get_default_log_dir() -> Path:
43
38
  """Get the default log directory."""
@@ -45,6 +40,22 @@ def get_default_log_dir() -> Path:
45
40
  return project_root / "data" / "user" / "logs"
46
41
 
47
42
 
43
+ def get_global_log_level() -> str:
44
+ """
45
+ Get the global log level from config/main.yaml -> logging.level
46
+ Default: DEBUG
47
+ """
48
+ try:
49
+ from src.services.config import load_config_with_main
50
+
51
+ project_root = Path(__file__).resolve().parent.parent.parent
52
+ config = load_config_with_main("solve_config.yaml", project_root)
53
+ logging_config = config.get("logging", {})
54
+ return logging_config.get("level", "DEBUG").upper()
55
+ except Exception:
56
+ return "DEBUG"
57
+
58
+
48
59
  def load_logging_config() -> LoggingConfig:
49
60
  """
50
61
  Load logging configuration from config files.
@@ -59,22 +70,14 @@ def load_logging_config() -> LoggingConfig:
59
70
  config = load_config_with_main("solve_config.yaml", project_root)
60
71
 
61
72
  logging_config = config.get("logging", {})
73
+ level = get_global_log_level()
62
74
 
63
75
  return LoggingConfig(
76
+ level=level,
64
77
  console_output=logging_config.get("console_output", True),
65
- file_output=logging_config.get("file_output", True),
66
- console_level=logging_config.get("console_level", "INFO"),
67
- file_level=logging_config.get("file_level", "DEBUG"),
78
+ file_output=logging_config.get("save_to_file", True),
68
79
  log_dir=get_path_from_config(config, "user_log_dir"),
69
- lightrag_forwarding_enabled=logging_config.get("lightrag_forwarding", {}).get(
70
- "enabled", True
71
- ),
72
- lightrag_min_level=logging_config.get("lightrag_forwarding", {}).get(
73
- "min_level", "INFO"
74
- ),
75
- lightrag_add_prefix=logging_config.get("lightrag_forwarding", {}).get(
76
- "add_prefix", True
77
- ),
80
+ rag_logger_names=logging_config.get("rag_logger_names"),
78
81
  )
79
82
  except Exception:
80
83
  return LoggingConfig()
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  Log Handlers
3
4
  ============
@@ -3,59 +3,15 @@
3
3
  Console Log Handler
4
4
  ===================
5
5
 
6
- Color-coded console output with symbols.
6
+ Color-coded console output with standard level tags.
7
7
  """
8
8
 
9
9
  import logging
10
10
  import sys
11
+ from typing import Optional
11
12
 
12
-
13
- class ConsoleFormatter(logging.Formatter):
14
- """
15
- Clean console formatter with colors and symbols.
16
- Format: [Module] Symbol Message
17
- """
18
-
19
- # ANSI color codes
20
- COLORS = {
21
- "DEBUG": "\033[90m", # Gray
22
- "INFO": "\033[37m", # White
23
- "SUCCESS": "\033[32m", # Green
24
- "WARNING": "\033[33m", # Yellow
25
- "ERROR": "\033[31m", # Red
26
- "CRITICAL": "\033[35m", # Magenta
27
- }
28
- RESET = "\033[0m"
29
- BOLD = "\033[1m"
30
- DIM = "\033[2m"
31
-
32
- # Symbols for different log types
33
- SYMBOLS = {
34
- "DEBUG": "·",
35
- "INFO": "●",
36
- "SUCCESS": "✓",
37
- "WARNING": "⚠",
38
- "ERROR": "✗",
39
- "CRITICAL": "✗",
40
- }
41
-
42
- def format(self, record: logging.LogRecord) -> str:
43
- # Get module name (padded to 12 chars for alignment)
44
- module = getattr(record, "module_name", record.name)
45
- module_padded = f"[{module}]".ljust(14)
46
-
47
- # Get symbol (can be overridden via record.symbol)
48
- symbol = getattr(record, "symbol", self.SYMBOLS.get(record.levelname, "●"))
49
-
50
- # Get color
51
- level = getattr(record, "display_level", record.levelname)
52
- color = self.COLORS.get(level, self.COLORS["INFO"])
53
-
54
- # Format message
55
- message = record.getMessage()
56
-
57
- # Build output: [Module] ● Message
58
- return f"{self.DIM}{module_padded}{self.RESET} {color}{symbol}{self.RESET} {message}"
13
+ # Import ConsoleFormatter from the main logger module to avoid duplication
14
+ from ..logger import ConsoleFormatter
59
15
 
60
16
 
61
17
  class ConsoleHandler(logging.StreamHandler):
@@ -63,13 +19,14 @@ class ConsoleHandler(logging.StreamHandler):
63
19
  Console handler with color-coded output.
64
20
  """
65
21
 
66
- def __init__(self, level: int = logging.INFO):
22
+ def __init__(self, level: int = logging.INFO, service_prefix: Optional[str] = None):
67
23
  """
68
24
  Initialize console handler.
69
25
 
70
26
  Args:
71
27
  level: Minimum log level to display
28
+ service_prefix: Optional service layer prefix (e.g., "Backend", "Frontend")
72
29
  """
73
30
  super().__init__(sys.stdout)
74
31
  self.setLevel(level)
75
- self.setFormatter(ConsoleFormatter())
32
+ self.setFormatter(ConsoleFormatter(service_prefix=service_prefix))
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  File Log Handlers
3
4
  =================
@@ -13,24 +14,8 @@ from logging.handlers import RotatingFileHandler as BaseRotatingFileHandler
13
14
  from pathlib import Path
14
15
  from typing import Optional
15
16
 
16
-
17
- class FileFormatter(logging.Formatter):
18
- """
19
- Detailed file formatter for log files.
20
- Format: TIMESTAMP [LEVEL] [Module] Message
21
- """
22
-
23
- def __init__(self):
24
- super().__init__(
25
- fmt="%(asctime)s [%(levelname)-8s] [%(module_name)-12s] %(message)s",
26
- datefmt="%Y-%m-%d %H:%M:%S",
27
- )
28
-
29
- def format(self, record: logging.LogRecord) -> str:
30
- # Ensure module_name exists
31
- if not hasattr(record, "module_name"):
32
- record.module_name = record.name
33
- return super().format(record)
17
+ # Import FileFormatter from the main logger module to avoid duplication
18
+ from ..logger import FileFormatter
34
19
 
35
20
 
36
21
  class FileHandler(logging.FileHandler):
@@ -143,7 +128,7 @@ class JSONFileHandler(logging.Handler):
143
128
  }
144
129
 
145
130
  # Add extra fields if present
146
- for key in ["symbol", "display_level", "tool_name", "elapsed_ms", "tokens"]:
131
+ for key in ["display_level", "tool_name", "elapsed_ms", "tokens"]:
147
132
  if hasattr(record, key):
148
133
  entry[key] = getattr(record, key)
149
134
 
@@ -180,7 +165,7 @@ def create_task_logger(
180
165
  log_path.mkdir(parents=True, exist_ok=True)
181
166
 
182
167
  # Create logger
183
- logger = logging.getLogger(f"ai_tutor.{module_name}.{task_id}")
168
+ logger = logging.getLogger(f"deeptutor.{module_name}.{task_id}")
184
169
  logger.setLevel(logging.DEBUG)
185
170
  logger.handlers.clear()
186
171
  logger.propagate = False
@@ -8,6 +8,7 @@ Handlers for streaming logs to WebSocket clients.
8
8
 
9
9
  import asyncio
10
10
  import logging
11
+ from typing import Optional
11
12
 
12
13
 
13
14
  class WebSocketLogHandler(logging.Handler):
@@ -25,27 +26,24 @@ class WebSocketLogHandler(logging.Handler):
25
26
  await websocket.send_json(log_entry)
26
27
  """
27
28
 
28
- # Symbols for different log types (matching ConsoleFormatter)
29
- SYMBOLS = {
30
- "DEBUG": "·",
31
- "INFO": "●",
32
- "SUCCESS": "✓",
33
- "WARNING": "⚠",
34
- "ERROR": "✗",
35
- "CRITICAL": "✗",
36
- }
37
-
38
- def __init__(self, queue: asyncio.Queue, include_module: bool = True):
29
+ def __init__(
30
+ self,
31
+ queue: asyncio.Queue,
32
+ include_module: bool = True,
33
+ service_prefix: Optional[str] = None,
34
+ ):
39
35
  """
40
36
  Initialize WebSocket log handler.
41
37
 
42
38
  Args:
43
39
  queue: asyncio.Queue to put log entries into
44
40
  include_module: Whether to include module name in output
41
+ service_prefix: Optional service layer prefix (e.g., "Backend")
45
42
  """
46
43
  super().__init__()
47
44
  self.queue = queue
48
45
  self.include_module = include_module
46
+ self.service_prefix = service_prefix
49
47
  self.setFormatter(logging.Formatter("%(message)s"))
50
48
 
51
49
  def emit(self, record: logging.LogRecord):
@@ -53,25 +51,31 @@ class WebSocketLogHandler(logging.Handler):
53
51
  try:
54
52
  msg = self.format(record)
55
53
 
56
- # Get symbol
54
+ # Get display level
57
55
  display_level = getattr(record, "display_level", record.levelname)
58
- symbol = getattr(record, "symbol", self.SYMBOLS.get(display_level, "●"))
59
56
 
60
57
  # Get module name
61
58
  module_name = getattr(record, "module_name", record.name)
62
59
 
63
- # Build formatted content
64
- if self.include_module:
65
- content = f"[{module_name}] {symbol} {msg}"
60
+ # Build formatted content with standard level tags (compact format)
61
+ level_tag = display_level
62
+ if self.service_prefix:
63
+ service_tag = f"[{self.service_prefix}]"
64
+ if self.include_module:
65
+ content = f"{service_tag} {level_tag} [{module_name}] {msg}"
66
+ else:
67
+ content = f"{service_tag} {level_tag} {msg}"
66
68
  else:
67
- content = f"{symbol} {msg}"
69
+ if self.include_module:
70
+ content = f"{level_tag} [{module_name}] {msg}"
71
+ else:
72
+ content = f"{level_tag} {msg}"
68
73
 
69
74
  # Construct structured message
70
75
  log_entry = {
71
76
  "type": "log",
72
77
  "level": display_level,
73
78
  "module": module_name,
74
- "symbol": symbol,
75
79
  "content": content,
76
80
  "message": msg,
77
81
  "timestamp": record.created,
@@ -93,7 +97,7 @@ class LogInterceptor:
93
97
 
94
98
  Usage:
95
99
  queue = asyncio.Queue()
96
- logger = logging.getLogger("ai_tutor.Solver")
100
+ logger = logging.getLogger("deeptutor.Solver")
97
101
 
98
102
  with LogInterceptor(logger, queue):
99
103
  # All logs from this logger will be streamed to queue