liumaolin commited on
Commit
851495c
·
1 Parent(s): 013a9e4

Replace `logging` with centralized `loguru`-based logger across all modules.

Browse files
Files changed (29) hide show
  1. src/voice_dialogue/api/app.py +1 -8
  2. src/voice_dialogue/api/core/config.py +1 -3
  3. src/voice_dialogue/api/core/lifespan.py +3 -7
  4. src/voice_dialogue/api/core/service_manager.py +1 -2
  5. src/voice_dialogue/api/middleware/logging.py +2 -3
  6. src/voice_dialogue/api/routes/asr_routes.py +1 -3
  7. src/voice_dialogue/api/routes/system_routes.py +1 -2
  8. src/voice_dialogue/api/routes/tts_routes.py +1 -2
  9. src/voice_dialogue/api/routes/websocket_routes.py +1 -3
  10. src/voice_dialogue/api/server.py +15 -9
  11. src/voice_dialogue/core/launcher.py +5 -4
  12. src/voice_dialogue/services/audio/capture.py +2 -1
  13. src/voice_dialogue/services/audio/generators/configs/__init__.py +6 -6
  14. src/voice_dialogue/services/audio/generators/manager.py +11 -11
  15. src/voice_dialogue/services/audio/generators/models/__init__.py +8 -8
  16. src/voice_dialogue/services/audio/generators/models/base.py +1 -2
  17. src/voice_dialogue/services/audio/generators/runtime/__init__.py +4 -4
  18. src/voice_dialogue/services/audio/generators/runtime/kokoro.py +3 -2
  19. src/voice_dialogue/services/audio/generators/runtime/moyoyo.py +3 -2
  20. src/voice_dialogue/services/audio/player.py +3 -2
  21. src/voice_dialogue/services/speech/monitor.py +2 -1
  22. src/voice_dialogue/services/speech/recognizers/manager.py +17 -17
  23. src/voice_dialogue/services/speech/recognizers/models/__init__.py +4 -4
  24. src/voice_dialogue/services/speech/recognizers/models/funasr.py +5 -4
  25. src/voice_dialogue/services/speech/recognizers/models/whisper.py +4 -3
  26. src/voice_dialogue/services/text/generator.py +9 -8
  27. src/voice_dialogue/services/text/processor.py +3 -2
  28. src/voice_dialogue/utils/__init__.py +2 -0
  29. src/voice_dialogue/utils/logger.py +23 -67
src/voice_dialogue/api/app.py CHANGED
@@ -1,4 +1,3 @@
1
- import logging
2
  from typing import Dict, Any
3
 
4
  from fastapi import FastAPI, HTTPException, APIRouter
@@ -7,19 +6,13 @@ from fastapi.responses import RedirectResponse
7
  from fastapi.staticfiles import StaticFiles
8
 
9
  from voice_dialogue.config.paths import FRONTEND_ASSETS_PATH
 
10
  from .core.config import AppConfig
11
  from .core.lifespan import lifespan
12
  from .middleware.logging import LoggingMiddleware
13
  from .middleware.rate_limit import RateLimitMiddleware
14
  from .routes import tts_routes, asr_routes, system_routes, websocket_routes
15
 
16
- # 配置日志
17
- logging.basicConfig(
18
- level=logging.INFO,
19
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
20
- )
21
- logger = logging.getLogger(__name__)
22
-
23
 
24
  def create_app() -> FastAPI:
25
  """创建并配置FastAPI应用"""
 
 
1
  from typing import Dict, Any
2
 
3
  from fastapi import FastAPI, HTTPException, APIRouter
 
6
  from fastapi.staticfiles import StaticFiles
7
 
8
  from voice_dialogue.config.paths import FRONTEND_ASSETS_PATH
9
+ from voice_dialogue.utils.logger import logger
10
  from .core.config import AppConfig
11
  from .core.lifespan import lifespan
12
  from .middleware.logging import LoggingMiddleware
13
  from .middleware.rate_limit import RateLimitMiddleware
14
  from .routes import tts_routes, asr_routes, system_routes, websocket_routes
15
 
 
 
 
 
 
 
 
16
 
17
  def create_app() -> FastAPI:
18
  """创建并配置FastAPI应用"""
src/voice_dialogue/api/core/config.py CHANGED
@@ -1,9 +1,7 @@
1
- import logging
2
  from typing import Dict, Any
3
 
4
  from voice_dialogue.services.audio.generators import tts_config_registry
5
-
6
- logger = logging.getLogger(__name__)
7
 
8
 
9
  class TTSConfigInitializer:
 
 
1
  from typing import Dict, Any
2
 
3
  from voice_dialogue.services.audio.generators import tts_config_registry
4
+ from voice_dialogue.utils.logger import logger
 
5
 
6
 
7
  class TTSConfigInitializer:
src/voice_dialogue/api/core/lifespan.py CHANGED
@@ -1,18 +1,15 @@
1
- import logging
2
  import time
3
  from contextlib import asynccontextmanager
4
 
5
  from fastapi import FastAPI
6
 
7
  from voice_dialogue.services.audio.generators import tts_config_registry
8
- from voice_dialogue.utils import get_system_language
9
  from .config import TTSConfigInitializer
10
  from .service_factories import get_core_voice_service_definitions
11
  from .service_manager import ServiceManager
12
  from ..schemas.tts_schemas import generate_model_id
13
 
14
- logger = logging.getLogger(__name__)
15
-
16
 
17
  class LifespanManager:
18
  """应用生命周期管理器"""
@@ -38,16 +35,15 @@ class LifespanManager:
38
  default_tts_config = tts_config_registry.get_default_config_for_system()
39
  current_tts_model_id = None
40
  current_tts_character_name = None
41
-
42
  if default_tts_config:
43
  current_tts_model_id = generate_model_id(
44
- default_tts_config.tts_type.value,
45
  default_tts_config.character_name
46
  )
47
  current_tts_character_name = default_tts_config.character_name
48
  logger.info(f"系统默认TTS模型: {current_tts_character_name} (ID: {current_tts_model_id})")
49
 
50
-
51
  # 获取服务定义
52
  service_definitions = get_core_voice_service_definitions(system_language)
53
 
 
 
1
  import time
2
  from contextlib import asynccontextmanager
3
 
4
  from fastapi import FastAPI
5
 
6
  from voice_dialogue.services.audio.generators import tts_config_registry
7
+ from voice_dialogue.utils import get_system_language, logger
8
  from .config import TTSConfigInitializer
9
  from .service_factories import get_core_voice_service_definitions
10
  from .service_manager import ServiceManager
11
  from ..schemas.tts_schemas import generate_model_id
12
 
 
 
13
 
14
  class LifespanManager:
15
  """应用生命周期管理器"""
 
35
  default_tts_config = tts_config_registry.get_default_config_for_system()
36
  current_tts_model_id = None
37
  current_tts_character_name = None
38
+
39
  if default_tts_config:
40
  current_tts_model_id = generate_model_id(
41
+ default_tts_config.tts_type.value,
42
  default_tts_config.character_name
43
  )
44
  current_tts_character_name = default_tts_config.character_name
45
  logger.info(f"系统默认TTS模型: {current_tts_character_name} (ID: {current_tts_model_id})")
46
 
 
47
  # 获取服务定义
48
  service_definitions = get_core_voice_service_definitions(system_language)
49
 
src/voice_dialogue/api/core/service_manager.py CHANGED
@@ -1,9 +1,8 @@
1
- import logging
2
  import time
3
  from dataclasses import dataclass
4
  from typing import Dict, List, Callable, Any, Optional
5
 
6
- logger = logging.getLogger(__name__)
7
 
8
 
9
  @dataclass
 
 
1
  import time
2
  from dataclasses import dataclass
3
  from typing import Dict, List, Callable, Any, Optional
4
 
5
+ from voice_dialogue.utils.logger import logger
6
 
7
 
8
  @dataclass
src/voice_dialogue/api/middleware/logging.py CHANGED
@@ -1,10 +1,9 @@
1
- import logging
2
  import time
3
 
4
- from fastapi import Request, Response
5
  from starlette.middleware.base import BaseHTTPMiddleware
6
 
7
- logger = logging.getLogger(__name__)
8
 
9
 
10
  class LoggingMiddleware(BaseHTTPMiddleware):
 
 
1
  import time
2
 
3
+ from fastapi import Request
4
  from starlette.middleware.base import BaseHTTPMiddleware
5
 
6
+ from voice_dialogue.utils.logger import logger
7
 
8
 
9
  class LoggingMiddleware(BaseHTTPMiddleware):
src/voice_dialogue/api/routes/asr_routes.py CHANGED
@@ -1,14 +1,12 @@
1
- import logging
2
-
3
  from fastapi import APIRouter, HTTPException, Request, BackgroundTasks
4
 
5
  from voice_dialogue.services.speech.recognizers import asr_manager
 
6
  from ..core.service_factories import get_asr_worker_service_definition
7
  from ..schemas.asr_schemas import (
8
  SupportedLanguagesResponse, ASRInstanceRequest, ASRInstanceResponse
9
  )
10
 
11
- logger = logging.getLogger(__name__)
12
  router = APIRouter()
13
 
14
  _asr_creation_status = {
 
 
 
1
  from fastapi import APIRouter, HTTPException, Request, BackgroundTasks
2
 
3
  from voice_dialogue.services.speech.recognizers import asr_manager
4
+ from voice_dialogue.utils.logger import logger
5
  from ..core.service_factories import get_asr_worker_service_definition
6
  from ..schemas.asr_schemas import (
7
  SupportedLanguagesResponse, ASRInstanceRequest, ASRInstanceResponse
8
  )
9
 
 
10
  router = APIRouter()
11
 
12
  _asr_creation_status = {
src/voice_dialogue/api/routes/system_routes.py CHANGED
@@ -1,16 +1,15 @@
1
  import asyncio
2
- import logging
3
  import time
4
 
5
  from fastapi import APIRouter, HTTPException, BackgroundTasks, Request
6
 
7
  from voice_dialogue.core.constants import session_manager
 
8
  from ..core.service_factories import get_audio_capture_service_definition
9
  from ..schemas.system_schemas import (
10
  SystemStatusResponse, SystemResponse
11
  )
12
 
13
- logger = logging.getLogger(__name__)
14
  router = APIRouter()
15
 
16
  # 全局系统状态
 
1
  import asyncio
 
2
  import time
3
 
4
  from fastapi import APIRouter, HTTPException, BackgroundTasks, Request
5
 
6
  from voice_dialogue.core.constants import session_manager
7
+ from voice_dialogue.utils.logger import logger
8
  from ..core.service_factories import get_audio_capture_service_definition
9
  from ..schemas.system_schemas import (
10
  SystemStatusResponse, SystemResponse
11
  )
12
 
 
13
  router = APIRouter()
14
 
15
  # 全局系统状态
src/voice_dialogue/api/routes/tts_routes.py CHANGED
@@ -1,16 +1,15 @@
1
- import logging
2
  from typing import Optional
3
 
4
  from fastapi import APIRouter, HTTPException, BackgroundTasks, Request
5
 
6
  from voice_dialogue.services.audio.generators import tts_config_registry
 
7
  from ..core.service_factories import get_tts_audio_generator_service_definition
8
  from ..schemas.tts_schemas import (
9
  TTSModelInfo, TTSModelListResponse, TTSModelLoadRequest,
10
  TTSModelLoadResponse, TTSModelStatusResponse, generate_model_id
11
  )
12
 
13
- logger = logging.getLogger(__name__)
14
  router = APIRouter()
15
 
16
  # TTS模型加载状态管理
 
 
1
  from typing import Optional
2
 
3
  from fastapi import APIRouter, HTTPException, BackgroundTasks, Request
4
 
5
  from voice_dialogue.services.audio.generators import tts_config_registry
6
+ from voice_dialogue.utils.logger import logger
7
  from ..core.service_factories import get_tts_audio_generator_service_definition
8
  from ..schemas.tts_schemas import (
9
  TTSModelInfo, TTSModelListResponse, TTSModelLoadRequest,
10
  TTSModelLoadResponse, TTSModelStatusResponse, generate_model_id
11
  )
12
 
 
13
  router = APIRouter()
14
 
15
  # TTS模型加载状态管理
src/voice_dialogue/api/routes/websocket_routes.py CHANGED
@@ -1,13 +1,11 @@
1
- import logging
2
  from queue import Empty
3
 
4
-
5
  from fastapi import APIRouter, WebSocket, WebSocketDisconnect
6
 
7
  from voice_dialogue.core.constants import websocket_message_queue, session_manager
 
8
 
9
  ws = APIRouter()
10
- logger = logging.getLogger(__name__)
11
 
12
 
13
  @ws.websocket("/api/v1/ws")
 
 
1
  from queue import Empty
2
 
 
3
  from fastapi import APIRouter, WebSocket, WebSocketDisconnect
4
 
5
  from voice_dialogue.core.constants import websocket_message_queue, session_manager
6
+ from voice_dialogue.utils.logger import logger
7
 
8
  ws = APIRouter()
 
9
 
10
 
11
  @ws.websocket("/api/v1/ws")
src/voice_dialogue/api/server.py CHANGED
@@ -6,6 +6,8 @@ API服务器启动器
6
 
7
  import uvicorn
8
 
 
 
9
 
10
  def launch_api_server(host: str = "0.0.0.0", port: int = 8000, reload: bool = False):
11
  """
@@ -16,20 +18,24 @@ def launch_api_server(host: str = "0.0.0.0", port: int = 8000, reload: bool = Fa
16
  port (int): 服务器端口,默认为 8000
17
  reload (bool): 是否启用热重载,默认为 False
18
  """
19
- print(f'{"=" * 80}\n正在启动API服务器...\n{"=" * 80}')
20
- print(f"服务器地址: http://{host}:{port}")
21
- print(f"API文档: http://{host}:{port}/docs")
22
- print(f"热重载: {'启用' if reload else '禁用'}")
23
- print(f'{"=" * 80}')
24
-
25
- # 导入并启动FastAPI应用
26
- uvicorn.run(
27
  "voice_dialogue.api.app:app",
28
  host=host,
29
  port=port,
30
  reload=reload,
31
- log_level="info"
 
 
32
  )
 
 
33
 
34
 
35
  if __name__ == "__main__":
 
6
 
7
  import uvicorn
8
 
9
+ from voice_dialogue.utils.logger import logger
10
+
11
 
12
  def launch_api_server(host: str = "0.0.0.0", port: int = 8000, reload: bool = False):
13
  """
 
18
  port (int): 服务器端口,默认为 8000
19
  reload (bool): 是否启用热重载,默认为 False
20
  """
21
+ logger.info(f'{"=" * 80}')
22
+ logger.info(f'正在启动API服务器...')
23
+ logger.info(f"服务器地址: http://{host}:{port}")
24
+ logger.info(f"API文档: http://{host}:{port}/docs")
25
+ logger.info(f"热重载: {'启用' if reload else '禁用'}")
26
+ logger.info(f'{"=" * 80}')
27
+
28
+ uvicorn_config = uvicorn.Config(
29
  "voice_dialogue.api.app:app",
30
  host=host,
31
  port=port,
32
  reload=reload,
33
+ log_level="info",
34
+ log_config=None, # 不使用uvicorn的日志配置文件
35
+ use_colors=True, # 启用彩色日志
36
  )
37
+ server = uvicorn.Server(uvicorn_config)
38
+ server.run()
39
 
40
 
41
  if __name__ == "__main__":
src/voice_dialogue/core/launcher.py CHANGED
@@ -20,6 +20,7 @@ from voice_dialogue.services.audio.player import AudioStreamPlayer
20
  from voice_dialogue.services.speech.monitor import SpeechStateMonitor
21
  from voice_dialogue.services.speech.recognizer import ASRWorker
22
  from voice_dialogue.services.text.generator import LLMResponseGenerator
 
23
 
24
 
25
  def launch_system(
@@ -58,7 +59,7 @@ def launch_system(
58
  # 导入speaker配置相关功能
59
 
60
  threads = []
61
-
62
  # 音频采集
63
  audio_frame_probe = EchoCancellingAudioCapture(audio_frames_queue=audio_frames_queue)
64
  audio_frame_probe.start()
@@ -74,7 +75,7 @@ def launch_system(
74
 
75
  # 语音识别
76
  whisper_worker = ASRWorker(
77
- user_voice_queue=user_voice_queue,
78
  transcribed_text_queue=transcribed_text_queue,
79
  language=user_language
80
  )
@@ -114,8 +115,8 @@ def launch_system(
114
  while not all([thread.is_ready for thread in threads]):
115
  time.sleep(0.1)
116
 
117
- print(f'{"=" * 80}\n服务启动成功\n{"=" * 80}')
118
-
119
  # 等待所有线程结束
120
  for thread in threads:
121
  thread.join()
 
20
  from voice_dialogue.services.speech.monitor import SpeechStateMonitor
21
  from voice_dialogue.services.speech.recognizer import ASRWorker
22
  from voice_dialogue.services.text.generator import LLMResponseGenerator
23
+ from voice_dialogue.utils.logger import logger
24
 
25
 
26
  def launch_system(
 
59
  # 导入speaker配置相关功能
60
 
61
  threads = []
62
+
63
  # 音频采集
64
  audio_frame_probe = EchoCancellingAudioCapture(audio_frames_queue=audio_frames_queue)
65
  audio_frame_probe.start()
 
75
 
76
  # 语音识别
77
  whisper_worker = ASRWorker(
78
+ user_voice_queue=user_voice_queue,
79
  transcribed_text_queue=transcribed_text_queue,
80
  language=user_language
81
  )
 
115
  while not all([thread.is_ready for thread in threads]):
116
  time.sleep(0.1)
117
 
118
+ logger.info(f'{"=" * 80}\n服务启动成功\n{"=" * 80}')
119
+
120
  # 等待所有线程结束
121
  for thread in threads:
122
  thread.join()
src/voice_dialogue/services/audio/capture.py CHANGED
@@ -11,6 +11,7 @@ import numpy as np
11
 
12
  from voice_dialogue.config.paths import LIBRARIES_PATH
13
  from voice_dialogue.core.base import BaseThread
 
14
 
15
 
16
  class EchoCancellingAudioCapture(BaseThread):
@@ -66,6 +67,6 @@ class EchoCancellingAudioCapture(BaseThread):
66
  # 无数据时等待
67
  time.sleep(0.01)
68
  except Exception as e:
69
- print(f'回声消除音频捕获器运行时发生错误: {e}')
70
  finally:
71
  audio_recorder.stopRecord()
 
11
 
12
  from voice_dialogue.config.paths import LIBRARIES_PATH
13
  from voice_dialogue.core.base import BaseThread
14
+ from voice_dialogue.utils.logger import logger
15
 
16
 
17
  class EchoCancellingAudioCapture(BaseThread):
 
67
  # 无数据时等待
68
  time.sleep(0.01)
69
  except Exception as e:
70
+ logger.error(f'回声消除音频捕获器运行时发生错误: {e}')
71
  finally:
72
  audio_recorder.stopRecord()
src/voice_dialogue/services/audio/generators/configs/__init__.py CHANGED
@@ -20,9 +20,9 @@ try:
20
  }
21
 
22
  except ImportError as e:
23
- import logging
24
 
25
- logging.warning(f"Failed to import some config modules: {e}")
26
  __all__ = []
27
  CONFIG_GETTERS = {}
28
 
@@ -35,8 +35,8 @@ def get_all_configs():
35
  configs = getter_func()
36
  all_configs.extend(configs)
37
  except Exception as e:
38
- import logging
39
- logging.error(f"Failed to load configs from {getter_func.__name__}: {e}")
40
  return all_configs
41
 
42
 
@@ -46,7 +46,7 @@ def get_configs_by_type(tts_type: str):
46
  try:
47
  return CONFIG_GETTERS[tts_type]()
48
  except Exception as e:
49
- import logging
50
- logging.error(f"Failed to load configs for {tts_type}: {e}")
51
  return []
52
  return []
 
20
  }
21
 
22
  except ImportError as e:
23
+ from voice_dialogue.utils.logger import logger
24
 
25
+ logger.warning(f"Failed to import some config modules: {e}")
26
  __all__ = []
27
  CONFIG_GETTERS = {}
28
 
 
35
  configs = getter_func()
36
  all_configs.extend(configs)
37
  except Exception as e:
38
+ from voice_dialogue.utils.logger import logger
39
+ logger.error(f"Failed to load configs from {getter_func.__name__}: {e}")
40
  return all_configs
41
 
42
 
 
46
  try:
47
  return CONFIG_GETTERS[tts_type]()
48
  except Exception as e:
49
+ from voice_dialogue.utils.logger import logger
50
+ logger.error(f"Failed to load configs for {tts_type}: {e}")
51
  return []
52
  return []
src/voice_dialogue/services/audio/generators/manager.py CHANGED
@@ -1,11 +1,11 @@
1
  import importlib.util
2
  import inspect
3
- import logging
4
  import re
5
  from dataclasses import dataclass
6
  from pathlib import Path
7
  from typing import Dict, Type
8
 
 
9
  from .models.base import BaseTTSConfig
10
  from .runtime.interface import TTSInterface
11
 
@@ -22,11 +22,11 @@ class TTSRegistryTables:
22
 
23
  def print(self, key: str = None) -> None:
24
  """打印已注册的TTS类"""
25
- print("\nTTS Registry Tables: \n")
26
  headers = ["register name", "class name", "class location"]
27
 
28
  if self.tts_classes and (key is None or "tts_classes" in key):
29
- print(f"----------- ** tts_classes ** --------------")
30
  metas = []
31
  for register_key, tts_class in self.tts_classes.items():
32
  class_file = inspect.getfile(tts_class)
@@ -46,12 +46,12 @@ class TTSRegistryTables:
46
  col_widths = [max(len(str(item)) for item in col) for col in zip(*data)]
47
 
48
  for row in data:
49
- print(
50
  "| "
51
  + " | ".join(str(item).ljust(width) for item, width in zip(row, col_widths))
52
  + " |"
53
  )
54
- print("\n")
55
 
56
  def register(self, register_table_key: str, key: str = None) -> callable:
57
  """装饰器,用于注册TTS类"""
@@ -59,18 +59,18 @@ class TTSRegistryTables:
59
  def decorator(target_class):
60
  if not hasattr(self, register_table_key):
61
  setattr(self, register_table_key, {})
62
- logging.debug(f"New TTS registry table added: {register_table_key}")
63
 
64
  registry = getattr(self, register_table_key)
65
  registry_key = key if key is not None else target_class.__name__
66
 
67
  if registry_key in registry:
68
- logging.debug(
69
  f"Key {registry_key} already exists in {register_table_key}, re-register"
70
  )
71
 
72
  registry[registry_key] = target_class
73
- logging.info(f"Registered TTS class: {registry_key} -> {target_class.__name__}")
74
  return target_class
75
 
76
  return decorator
@@ -160,11 +160,11 @@ def register_all_tts():
160
  )
161
  module = importlib.util.module_from_spec(spec)
162
  spec.loader.exec_module(module)
163
- logging.info(f"Successfully imported TTS module: {module_name}")
164
  except ImportError as e:
165
- logging.warning(f"Failed to import TTS module {module_name}: {e}")
166
  except Exception as e:
167
- logging.error(f"Unexpected error importing TTS module {module_name}: {e}")
168
 
169
 
170
  # 在模块导入时自动注册所有TTS
 
1
  import importlib.util
2
  import inspect
 
3
  import re
4
  from dataclasses import dataclass
5
  from pathlib import Path
6
  from typing import Dict, Type
7
 
8
+ from voice_dialogue.utils.logger import logger
9
  from .models.base import BaseTTSConfig
10
  from .runtime.interface import TTSInterface
11
 
 
22
 
23
  def print(self, key: str = None) -> None:
24
  """打印已注册的TTS类"""
25
+ logger.info("\nTTS Registry Tables: \n")
26
  headers = ["register name", "class name", "class location"]
27
 
28
  if self.tts_classes and (key is None or "tts_classes" in key):
29
+ logger.info(f"----------- ** tts_classes ** --------------")
30
  metas = []
31
  for register_key, tts_class in self.tts_classes.items():
32
  class_file = inspect.getfile(tts_class)
 
46
  col_widths = [max(len(str(item)) for item in col) for col in zip(*data)]
47
 
48
  for row in data:
49
+ logger.info(
50
  "| "
51
  + " | ".join(str(item).ljust(width) for item, width in zip(row, col_widths))
52
  + " |"
53
  )
54
+ logger.info("\n")
55
 
56
  def register(self, register_table_key: str, key: str = None) -> callable:
57
  """装饰器,用于注册TTS类"""
 
59
  def decorator(target_class):
60
  if not hasattr(self, register_table_key):
61
  setattr(self, register_table_key, {})
62
+ logger.debug(f"New TTS registry table added: {register_table_key}")
63
 
64
  registry = getattr(self, register_table_key)
65
  registry_key = key if key is not None else target_class.__name__
66
 
67
  if registry_key in registry:
68
+ logger.debug(
69
  f"Key {registry_key} already exists in {register_table_key}, re-register"
70
  )
71
 
72
  registry[registry_key] = target_class
73
+ logger.info(f"Registered TTS class: {registry_key} -> {target_class.__name__}")
74
  return target_class
75
 
76
  return decorator
 
160
  )
161
  module = importlib.util.module_from_spec(spec)
162
  spec.loader.exec_module(module)
163
+ logger.info(f"Successfully imported TTS module: {module_name}")
164
  except ImportError as e:
165
+ logger.warning(f"Failed to import TTS module {module_name}: {e}")
166
  except Exception as e:
167
+ logger.error(f"Unexpected error importing TTS module {module_name}: {e}")
168
 
169
 
170
  # 在模块导入时自动注册所有TTS
src/voice_dialogue/services/audio/generators/models/__init__.py CHANGED
@@ -22,9 +22,9 @@ try:
22
  _moyoyo_available = True
23
  except ImportError:
24
  _moyoyo_available = False
25
- import logging
26
 
27
- logging.warning("MoYoYo TTS config not available")
28
 
29
  try:
30
  from .kokoro import KokoroTTSConfig
@@ -32,9 +32,9 @@ try:
32
  _kokoro_available = True
33
  except ImportError:
34
  _kokoro_available = False
35
- import logging
36
 
37
- logging.warning("Kokoro TTS config not available")
38
 
39
  # 动态构建导出列表
40
  __all__ = [
@@ -60,8 +60,8 @@ def _auto_register_configs():
60
  for config in get_moyoyo_configs():
61
  tts_config_registry.register_config(config)
62
  except Exception as e:
63
- import logging
64
- logging.error(f"Failed to auto-register configs: {e}")
65
 
66
  try:
67
  if _kokoro_available:
@@ -69,8 +69,8 @@ def _auto_register_configs():
69
  for config in get_kokoro_configs():
70
  tts_config_registry.register_config(config)
71
  except Exception as e:
72
- import logging
73
- logging.error(f"Failed to auto-register configs: {e}")
74
 
75
 
76
  # 模块加载时自动注册配置
 
22
  _moyoyo_available = True
23
  except ImportError:
24
  _moyoyo_available = False
25
+ from voice_dialogue.utils.logger import logger
26
 
27
+ logger.warning("MoYoYo TTS config not available")
28
 
29
  try:
30
  from .kokoro import KokoroTTSConfig
 
32
  _kokoro_available = True
33
  except ImportError:
34
  _kokoro_available = False
35
+ from voice_dialogue.utils.logger import logger
36
 
37
+ logger.warning("Kokoro TTS config not available")
38
 
39
  # 动态构建导出列表
40
  __all__ = [
 
60
  for config in get_moyoyo_configs():
61
  tts_config_registry.register_config(config)
62
  except Exception as e:
63
+ from voice_dialogue.utils.logger import logger
64
+ logger.error(f"Failed to auto-register configs: {e}")
65
 
66
  try:
67
  if _kokoro_available:
 
69
  for config in get_kokoro_configs():
70
  tts_config_registry.register_config(config)
71
  except Exception as e:
72
+ from voice_dialogue.utils.logger import logger
73
+ logger.error(f"Failed to auto-register configs: {e}")
74
 
75
 
76
  # 模块加载时自动注册配置
src/voice_dialogue/services/audio/generators/models/base.py CHANGED
@@ -1,4 +1,3 @@
1
- import logging
2
  import typing
3
  from abc import ABC, abstractmethod
4
  from enum import Enum
@@ -6,7 +5,7 @@ from pathlib import Path
6
 
7
  from pydantic import BaseModel
8
 
9
- logger = logging.getLogger(__name__)
10
 
11
 
12
  class TTSConfigType(Enum):
 
 
1
  import typing
2
  from abc import ABC, abstractmethod
3
  from enum import Enum
 
5
 
6
  from pydantic import BaseModel
7
 
8
+ from voice_dialogue.utils.logger import logger
9
 
10
 
11
  class TTSConfigType(Enum):
src/voice_dialogue/services/audio/generators/runtime/__init__.py CHANGED
@@ -21,9 +21,9 @@ try:
21
  __all__.append('MoYoYoTTS')
22
  except ImportError as e:
23
  # 如果某些TTS实现无法导入,不影响整体功能
24
- import logging
25
 
26
- logging.warning(f"Failed to import some TTS implementations: {e}")
27
 
28
  try:
29
  from .kokoro import KokoroTTS
@@ -31,6 +31,6 @@ try:
31
  __all__.append('KokoroTTS')
32
  except ImportError as e:
33
  # 如果某些TTS实现无法导入,不影响整体功能
34
- import logging
35
 
36
- logging.warning(f"Failed to import some TTS implementations: {e}")
 
21
  __all__.append('MoYoYoTTS')
22
  except ImportError as e:
23
  # 如果某些TTS实现无法导入,不影响整体功能
24
+ from voice_dialogue.utils.logger import logger
25
 
26
+ logger.warning(f"Failed to import some TTS implementations: {e}")
27
 
28
  try:
29
  from .kokoro import KokoroTTS
 
31
  __all__.append('KokoroTTS')
32
  except ImportError as e:
33
  # 如果某些TTS实现无法导入,不影响整体功能
34
+ from voice_dialogue.utils.logger import logger
35
 
36
+ logger.warning(f"Failed to import some TTS implementations: {e}")
src/voice_dialogue/services/audio/generators/runtime/kokoro.py CHANGED
@@ -6,6 +6,7 @@ from kokoro_onnx import Kokoro
6
  from voice_dialogue.services.audio.generators.configs.kokoro import KokoroTTSConfig
7
  from voice_dialogue.services.audio.generators.manager import tts_tables
8
  from voice_dialogue.services.audio.generators.runtime.interface import TTSInterface
 
9
 
10
 
11
  @tts_tables.register("tts_classes", "kokoro")
@@ -35,12 +36,12 @@ class KokoroTTS(TTSInterface):
35
  self.espeak_ng = en.G2P(trf=False, british=False, fallback=fallback)
36
 
37
  def warmup(self, warmup_steps: int = 1) -> None:
38
- print('[INFO:] Warming up Kokoro TTS engine...')
39
  warmup_texts = ['Warming up TTS engine.', '预热文字转音频引擎。']
40
  for _ in range(warmup_steps):
41
  for warmup_text in warmup_texts:
42
  self.synthesize(warmup_text)
43
- print('[INFO:] Warm up Kokoro TTS engine finished.')
44
 
45
  def synthesize(self, text: str, **kwargs) -> Tuple[np.ndarray, int]:
46
  phonemes, _ = self.espeak_ng(text)
 
6
  from voice_dialogue.services.audio.generators.configs.kokoro import KokoroTTSConfig
7
  from voice_dialogue.services.audio.generators.manager import tts_tables
8
  from voice_dialogue.services.audio.generators.runtime.interface import TTSInterface
9
+ from voice_dialogue.utils.logger import logger
10
 
11
 
12
  @tts_tables.register("tts_classes", "kokoro")
 
36
  self.espeak_ng = en.G2P(trf=False, british=False, fallback=fallback)
37
 
38
  def warmup(self, warmup_steps: int = 1) -> None:
39
+ logger.info('[INFO:] Warming up Kokoro TTS engine...')
40
  warmup_texts = ['Warming up TTS engine.', '预热文字转音频引擎。']
41
  for _ in range(warmup_steps):
42
  for warmup_text in warmup_texts:
43
  self.synthesize(warmup_text)
44
+ logger.info('[INFO:] Warm up Kokoro TTS engine finished.')
45
 
46
  def synthesize(self, text: str, **kwargs) -> Tuple[np.ndarray, int]:
47
  phonemes, _ = self.espeak_ng(text)
src/voice_dialogue/services/audio/generators/runtime/moyoyo.py CHANGED
@@ -8,6 +8,7 @@ from voice_dialogue.config.paths import load_third_party
8
  from voice_dialogue.services.audio.generators.manager import tts_tables
9
  from voice_dialogue.services.audio.generators.models.moyoyo import MoYoYoTTSConfig
10
  from voice_dialogue.services.audio.generators.runtime.interface import TTSInterface
 
11
 
12
  load_third_party()
13
 
@@ -43,12 +44,12 @@ class MoYoYoTTS(TTSInterface):
43
 
44
  def warmup(self, warmup_steps: int = 1) -> None:
45
  """预热TTS引擎"""
46
- print('[INFO:] Warming up MoYoYo TTS engine...')
47
  warmup_texts = ['Warming up TTS engine.', '预热文字转音频引擎。']
48
  for _ in range(warmup_steps):
49
  for warmup_text in warmup_texts:
50
  self.tts_module.generate_audio(warmup_text, warmup=True)
51
- print('[INFO:] Warm up MoYoYo TTS engine finished.')
52
 
53
  def synthesize(self, text: str, **kwargs) -> Tuple[np.ndarray, int]:
54
  """合成语音"""
 
8
  from voice_dialogue.services.audio.generators.manager import tts_tables
9
  from voice_dialogue.services.audio.generators.models.moyoyo import MoYoYoTTSConfig
10
  from voice_dialogue.services.audio.generators.runtime.interface import TTSInterface
11
+ from voice_dialogue.utils.logger import logger
12
 
13
  load_third_party()
14
 
 
44
 
45
  def warmup(self, warmup_steps: int = 1) -> None:
46
  """预热TTS引擎"""
47
+ logger.info('[INFO:] Warming up MoYoYo TTS engine...')
48
  warmup_texts = ['Warming up TTS engine.', '预热文字转音频引擎。']
49
  for _ in range(warmup_steps):
50
  for warmup_text in warmup_texts:
51
  self.tts_module.generate_audio(warmup_text, warmup=True)
52
+ logger.info('[INFO:] Warm up MoYoYo TTS engine finished.')
53
 
54
  def synthesize(self, text: str, **kwargs) -> Tuple[np.ndarray, int]:
55
  """合成语音"""
src/voice_dialogue/services/audio/player.py CHANGED
@@ -12,6 +12,7 @@ from voice_dialogue.core.constants import (
12
  silence_over_threshold_event
13
  )
14
  from voice_dialogue.models.voice_task import VoiceTask, AnswerDisplayMessage
 
15
 
16
 
17
  class AudioStreamPlayer(BaseThread):
@@ -40,7 +41,7 @@ class AudioStreamPlayer(BaseThread):
40
  task_id = voice_task.id
41
  answer_id = voice_task.answer_id
42
  if user_still_speaking_event.is_set():
43
- print('用户还有说话')
44
  voice_state_manager.drop_audio_task(task_id)
45
  dropped_audio_cache[answer_id] = answer_id
46
  user_still_speaking_event.clear()
@@ -84,7 +85,7 @@ class AudioStreamPlayer(BaseThread):
84
  self.playing_audio(audio_data, sample_rate)
85
 
86
  if self.audio_playing_queue.empty():
87
- print(f'回答播放完了')
88
 
89
  break
90
 
 
12
  silence_over_threshold_event
13
  )
14
  from voice_dialogue.models.voice_task import VoiceTask, AnswerDisplayMessage
15
+ from voice_dialogue.utils.logger import logger
16
 
17
 
18
  class AudioStreamPlayer(BaseThread):
 
41
  task_id = voice_task.id
42
  answer_id = voice_task.answer_id
43
  if user_still_speaking_event.is_set():
44
+ logger.info('用户还有说话')
45
  voice_state_manager.drop_audio_task(task_id)
46
  dropped_audio_cache[answer_id] = answer_id
47
  user_still_speaking_event.clear()
 
85
  self.playing_audio(audio_data, sample_rate)
86
 
87
  if self.audio_playing_queue.empty():
88
+ logger.info(f'回答播放完了')
89
 
90
  break
91
 
src/voice_dialogue/services/speech/monitor.py CHANGED
@@ -19,6 +19,7 @@ from voice_dialogue.core.constants import (
19
  )
20
  from voice_dialogue.core.enums import AudioState
21
  from voice_dialogue.models.voice_task import VoiceTask
 
22
 
23
 
24
  class SpeechMonitorConfig:
@@ -280,6 +281,6 @@ class SpeechStateMonitor(BaseThread):
280
 
281
  except Exception as e:
282
  # 错误处理,防止线程崩溃
283
- print(f"SpeechStateMonitor 处理错误: {e}")
284
  time.sleep(0.1) # 避免错误循环
285
  continue
 
19
  )
20
  from voice_dialogue.core.enums import AudioState
21
  from voice_dialogue.models.voice_task import VoiceTask
22
+ from voice_dialogue.utils.logger import logger
23
 
24
 
25
  class SpeechMonitorConfig:
 
281
 
282
  except Exception as e:
283
  # 错误处理,防止线程崩溃
284
+ logger.error(f"SpeechStateMonitor 处理错误: {e}")
285
  time.sleep(0.1) # 避免错误循环
286
  continue
src/voice_dialogue/services/speech/recognizers/manager.py CHANGED
@@ -1,10 +1,10 @@
1
  import importlib.util
2
  import inspect
3
- import logging
4
  import re
5
  from dataclasses import dataclass
6
  from typing import Dict, Type, List, Literal, Optional
7
 
 
8
  from .models import ASRInterface
9
 
10
 
@@ -20,11 +20,11 @@ class ASRRegistryTables:
20
 
21
  def print(self, key: str = None) -> None:
22
  """打印已注册的ASR类"""
23
- print("\nASR Registry Tables: \n")
24
  headers = ["register name", "class name", "class location", "supported languages"]
25
 
26
  if self.asr_classes and (key is None or "asr_classes" in key):
27
- print(f"----------- ** asr_classes ** --------------")
28
  metas = []
29
  for register_key, asr_class in self.asr_classes.items():
30
  class_file = inspect.getfile(asr_class)
@@ -53,12 +53,12 @@ class ASRRegistryTables:
53
  col_widths = [max(len(str(item)) for item in col) for col in zip(*data)]
54
 
55
  for row in data:
56
- print(
57
  "| "
58
  + " | ".join(str(item).ljust(width) for item, width in zip(row, col_widths))
59
  + " |"
60
  )
61
- print("\n")
62
 
63
  def register(self, register_table_key: str, key: str = None) -> callable:
64
  """装饰器,用于注册ASR类"""
@@ -66,18 +66,18 @@ class ASRRegistryTables:
66
  def decorator(target_class):
67
  if not hasattr(self, register_table_key):
68
  setattr(self, register_table_key, {})
69
- logging.debug(f"New ASR registry table added: {register_table_key}")
70
 
71
  registry = getattr(self, register_table_key)
72
  registry_key = key if key is not None else target_class.__name__
73
 
74
  if registry_key in registry:
75
- logging.debug(
76
  f"Key {registry_key} already exists in {register_table_key}, re-register"
77
  )
78
 
79
  registry[registry_key] = target_class
80
- logging.info(f"Registered ASR class: {registry_key} -> {target_class.__name__}")
81
  return target_class
82
 
83
  return decorator
@@ -121,11 +121,11 @@ class ASRManager:
121
  asr_class = asr_tables.asr_classes[asr_type]
122
  instance = asr_class()
123
 
124
- logging.info(f"成功创建ASR实例: {asr_type} for language: {language}")
125
  return instance
126
 
127
  except Exception as e:
128
- logging.error(f"创建ASR实例失败: {e}")
129
  raise
130
 
131
  def get_or_create_asr(self, language: Literal['auto', 'zh', 'en']) -> ASRInterface:
@@ -165,7 +165,7 @@ class ASRManager:
165
  raise ValueError(f"ASR类型 '{asr_type}' 未注册")
166
 
167
  self._language_to_asr_mapping[language] = asr_type
168
- logging.info(f"更新语言映射: {language} -> {asr_type}")
169
 
170
  def list_registered_asr(self) -> Dict[str, Type[ASRInterface]]:
171
  """列出所有已注册的ASR类型"""
@@ -190,7 +190,7 @@ class ASRManager:
190
  # languages = asr_tables._get_asr_supported_languages(asr_key)
191
  # supported_languages[asr_key] = languages
192
  except Exception as e:
193
- logging.warning(f"获取ASR引擎 '{asr_key}' 支持的语言失败: {e}")
194
  supported_languages[asr_key] = ['unknown']
195
 
196
  return supported_languages
@@ -251,9 +251,9 @@ class ASRManager:
251
 
252
  def cleanup(self) -> None:
253
  """清理所有ASR实例"""
254
- logging.info("清理ASR实例...")
255
  self._asr_instances.clear()
256
- logging.info("ASR实例清理完成")
257
 
258
  def print_registry(self) -> None:
259
  """打印注册表信息"""
@@ -301,11 +301,11 @@ def register_all_asr():
301
  )
302
  module = importlib.util.module_from_spec(spec)
303
  spec.loader.exec_module(module)
304
- logging.info(f"Successfully imported ASR module: {module_name}")
305
  except ImportError as e:
306
- logging.warning(f"Failed to import ASR module {module_name}: {e}")
307
  except Exception as e:
308
- logging.error(f"Unexpected error importing ASR module {module_name}: {e}")
309
 
310
 
311
  # 在模块导入时自动注册所有ASR
 
1
  import importlib.util
2
  import inspect
 
3
  import re
4
  from dataclasses import dataclass
5
  from typing import Dict, Type, List, Literal, Optional
6
 
7
+ from voice_dialogue.utils.logger import logger
8
  from .models import ASRInterface
9
 
10
 
 
20
 
21
  def print(self, key: str = None) -> None:
22
  """打印已注册的ASR类"""
23
+ logger.info("\nASR Registry Tables: \n")
24
  headers = ["register name", "class name", "class location", "supported languages"]
25
 
26
  if self.asr_classes and (key is None or "asr_classes" in key):
27
+ logger.info(f"----------- ** asr_classes ** --------------")
28
  metas = []
29
  for register_key, asr_class in self.asr_classes.items():
30
  class_file = inspect.getfile(asr_class)
 
53
  col_widths = [max(len(str(item)) for item in col) for col in zip(*data)]
54
 
55
  for row in data:
56
+ logger.info(
57
  "| "
58
  + " | ".join(str(item).ljust(width) for item, width in zip(row, col_widths))
59
  + " |"
60
  )
61
+ logger.info("\n")
62
 
63
  def register(self, register_table_key: str, key: str = None) -> callable:
64
  """装饰器,用于注册ASR类"""
 
66
  def decorator(target_class):
67
  if not hasattr(self, register_table_key):
68
  setattr(self, register_table_key, {})
69
+ logger.debug(f"New ASR registry table added: {register_table_key}")
70
 
71
  registry = getattr(self, register_table_key)
72
  registry_key = key if key is not None else target_class.__name__
73
 
74
  if registry_key in registry:
75
+ logger.debug(
76
  f"Key {registry_key} already exists in {register_table_key}, re-register"
77
  )
78
 
79
  registry[registry_key] = target_class
80
+ logger.info(f"Registered ASR class: {registry_key} -> {target_class.__name__}")
81
  return target_class
82
 
83
  return decorator
 
121
  asr_class = asr_tables.asr_classes[asr_type]
122
  instance = asr_class()
123
 
124
+ logger.info(f"成功创建ASR实例: {asr_type} for language: {language}")
125
  return instance
126
 
127
  except Exception as e:
128
+ logger.error(f"创建ASR实例失败: {e}")
129
  raise
130
 
131
  def get_or_create_asr(self, language: Literal['auto', 'zh', 'en']) -> ASRInterface:
 
165
  raise ValueError(f"ASR类型 '{asr_type}' 未注册")
166
 
167
  self._language_to_asr_mapping[language] = asr_type
168
+ logger.info(f"更新语言映射: {language} -> {asr_type}")
169
 
170
  def list_registered_asr(self) -> Dict[str, Type[ASRInterface]]:
171
  """列出所有已注册的ASR类型"""
 
190
  # languages = asr_tables._get_asr_supported_languages(asr_key)
191
  # supported_languages[asr_key] = languages
192
  except Exception as e:
193
+ logger.warning(f"获取ASR引擎 '{asr_key}' 支持的语言失败: {e}")
194
  supported_languages[asr_key] = ['unknown']
195
 
196
  return supported_languages
 
251
 
252
  def cleanup(self) -> None:
253
  """清理所有ASR实例"""
254
+ logger.info("清理ASR实例...")
255
  self._asr_instances.clear()
256
+ logger.info("ASR实例清理完成")
257
 
258
  def print_registry(self) -> None:
259
  """打印注册表信息"""
 
301
  )
302
  module = importlib.util.module_from_spec(spec)
303
  spec.loader.exec_module(module)
304
+ logger.info(f"Successfully imported ASR module: {module_name}")
305
  except ImportError as e:
306
+ logger.warning(f"Failed to import ASR module {module_name}: {e}")
307
  except Exception as e:
308
+ logger.error(f"Unexpected error importing ASR module {module_name}: {e}")
309
 
310
 
311
  # 在模块导入时自动注册所有ASR
src/voice_dialogue/services/speech/recognizers/models/__init__.py CHANGED
@@ -7,15 +7,15 @@ try:
7
 
8
  __all__.append('FunASRClient')
9
  except ImportError as e:
10
- import logging
11
 
12
- logging.warning(f"Failed to import some FunASR implementations: {e}")
13
 
14
  try:
15
  from .whisper import WhisperCppClient
16
 
17
  __all__.append('WhisperCppClient')
18
  except ImportError as e:
19
- import logging
20
 
21
- logging.warning(f"Failed to import some Whisper implementations: {e}")
 
7
 
8
  __all__.append('FunASRClient')
9
  except ImportError as e:
10
+ from voice_dialogue.utils.logger import logger
11
 
12
+ logger.warning(f"Failed to import some FunASR implementations: {e}")
13
 
14
  try:
15
  from .whisper import WhisperCppClient
16
 
17
  __all__.append('WhisperCppClient')
18
  except ImportError as e:
19
+ from voice_dialogue.utils.logger import logger
20
 
21
+ logger.warning(f"Failed to import some Whisper implementations: {e}")
src/voice_dialogue/services/speech/recognizers/models/funasr.py CHANGED
@@ -8,6 +8,7 @@ from voice_dialogue.config import paths
8
  from voice_dialogue.services.speech.recognizers.manager import asr_tables
9
  from voice_dialogue.services.speech.recognizers.models.base import ASRInterface
10
  from voice_dialogue.services.speech.recognizers.utils import ensure_minimum_audio_duration
 
11
 
12
 
13
  @asr_tables.register('asr_classes', 'funasr')
@@ -29,12 +30,12 @@ class FunASRClient(ASRInterface):
29
  self.punc_model = CT_Transformer(punc_model_path, quantize=True)
30
 
31
  def warmup(self) -> None:
32
- print('[INFO] Warming up FunASR model...')
33
  try:
34
  self.transcribe(self.warmup_audiodata)
35
- print('[INFO] FunASR model warmed up.')
36
  except Exception as e:
37
- print(f'[WARNING] FunASR model warmup failed: {e}')
38
 
39
  def _fix_spaced_uppercase(self, text: str) -> str:
40
  """
@@ -60,7 +61,7 @@ class FunASRClient(ASRInterface):
60
  try:
61
  content, _ = self.punc_model(content)
62
  except UnboundLocalError as e:
63
- print(f'[WARNING] Punctuation model failed: {e}')
64
  content = self._fix_spaced_uppercase(content)
65
  transcibed_texts.append(content)
66
  return " ".join(transcibed_texts)
 
8
  from voice_dialogue.services.speech.recognizers.manager import asr_tables
9
  from voice_dialogue.services.speech.recognizers.models.base import ASRInterface
10
  from voice_dialogue.services.speech.recognizers.utils import ensure_minimum_audio_duration
11
+ from voice_dialogue.utils.logger import logger
12
 
13
 
14
  @asr_tables.register('asr_classes', 'funasr')
 
30
  self.punc_model = CT_Transformer(punc_model_path, quantize=True)
31
 
32
  def warmup(self) -> None:
33
+ logger.info('[INFO] Warming up FunASR model...')
34
  try:
35
  self.transcribe(self.warmup_audiodata)
36
+ logger.info('[INFO] FunASR model warmed up.')
37
  except Exception as e:
38
+ logger.warning(f'[WARNING] FunASR model warmup failed: {e}')
39
 
40
  def _fix_spaced_uppercase(self, text: str) -> str:
41
  """
 
61
  try:
62
  content, _ = self.punc_model(content)
63
  except UnboundLocalError as e:
64
+ logger.warning(f'[WARNING] Punctuation model failed: {e}')
65
  content = self._fix_spaced_uppercase(content)
66
  transcibed_texts.append(content)
67
  return " ".join(transcibed_texts)
src/voice_dialogue/services/speech/recognizers/models/whisper.py CHANGED
@@ -7,6 +7,7 @@ from voice_dialogue.config import paths
7
  from voice_dialogue.services.speech.recognizers.manager import asr_tables
8
  from voice_dialogue.services.speech.recognizers.models.base import ASRInterface
9
  from voice_dialogue.services.speech.recognizers.utils import ensure_minimum_audio_duration
 
10
 
11
 
12
  @asr_tables.register('asr_classes', 'whisper')
@@ -30,12 +31,12 @@ class WhisperCppClient(ASRInterface):
30
  self.whisper = Model(model=model, models_dir=models_dir)
31
 
32
  def warmup(self) -> None:
33
- print('[INFO] Warming up Whisper model...')
34
  try:
35
  self.transcribe(self.warmup_audiodata)
36
- print('[INFO] Whisper model warmed up.')
37
  except Exception as e:
38
- print(f'[WARNING] Whisper model warmup failed: {e}')
39
 
40
  def transcribe(self, audio_array: np.ndarray, language="en"):
41
  if language == "zh":
 
7
  from voice_dialogue.services.speech.recognizers.manager import asr_tables
8
  from voice_dialogue.services.speech.recognizers.models.base import ASRInterface
9
  from voice_dialogue.services.speech.recognizers.utils import ensure_minimum_audio_duration
10
+ from voice_dialogue.utils.logger import logger
11
 
12
 
13
  @asr_tables.register('asr_classes', 'whisper')
 
31
  self.whisper = Model(model=model, models_dir=models_dir)
32
 
33
  def warmup(self) -> None:
34
+ logger.info('[INFO] Warming up Whisper model...')
35
  try:
36
  self.transcribe(self.warmup_audiodata)
37
+ logger.info('[INFO] Whisper model warmed up.')
38
  except Exception as e:
39
+ logger.warning(f'[WARNING] Whisper model warmup failed: {e}')
40
 
41
  def transcribe(self, audio_array: np.ndarray, language="en"):
42
  if language == "zh":
src/voice_dialogue/services/text/generator.py CHANGED
@@ -12,6 +12,7 @@ from voice_dialogue.core.constants import chat_history_cache
12
  from voice_dialogue.models.voice_task import VoiceTask, QuestionDisplayMessage
13
  from voice_dialogue.services.text.processor import preprocess_sentence_text, \
14
  create_langchain_chat_llamacpp_instance, create_langchain_pipeline, warmup_langchain_pipeline
 
15
 
16
  CHINESE_SYSTEM_PROMPT = (
17
  "你是善于模拟真实的思考过程的AI助手。"
@@ -129,7 +130,7 @@ class LLMResponseGenerator(BaseThread):
129
  is_first_sentence = True
130
 
131
  user_question = voice_task.transcribed_text
132
- print(f'用户问题: {user_question}')
133
  if self.websocket_message_queue:
134
  self.websocket_message_queue.put_nowait(
135
  QuestionDisplayMessage(
@@ -177,7 +178,7 @@ class LLMResponseGenerator(BaseThread):
177
  self._handle_remaining_chunks(voice_task, chunks, answer_index)
178
 
179
  except Exception as e:
180
- print(f'处理语音任务时发生错误: {e}')
181
 
182
  def _handle_remaining_chunks(self, voice_task: VoiceTask, chunks: list, answer_index: int) -> None:
183
  """处理剩余的 chunks"""
@@ -197,11 +198,11 @@ class LLMResponseGenerator(BaseThread):
197
 
198
  # 打印芯片信息和优化配置
199
  chip_summary = get_apple_silicon_summary()
200
- print(f"检测到芯片: {chip_summary['chip_name']}")
201
- print(f"性能核心数: {chip_summary['performance_cores']}")
202
- print(f"使用线程数: {chip_summary['optimal_n_threads']} (仅使用性能核心)")
203
- print(f"上下文窗口: {chip_summary['optimal_n_ctx']}")
204
- print(f"配置说明: {chip_summary['config_note']}")
205
 
206
  self.model_instance = create_langchain_chat_llamacpp_instance(
207
  local_model_path=model_path, model_params=model_params
@@ -219,4 +220,4 @@ class LLMResponseGenerator(BaseThread):
219
  except Empty:
220
  continue
221
  except Exception as e:
222
- print(f'AnswerGeneratorWorker 运行时发生错误: {e}')
 
12
  from voice_dialogue.models.voice_task import VoiceTask, QuestionDisplayMessage
13
  from voice_dialogue.services.text.processor import preprocess_sentence_text, \
14
  create_langchain_chat_llamacpp_instance, create_langchain_pipeline, warmup_langchain_pipeline
15
+ from voice_dialogue.utils.logger import logger
16
 
17
  CHINESE_SYSTEM_PROMPT = (
18
  "你是善于模拟真实的思考过程的AI助手。"
 
130
  is_first_sentence = True
131
 
132
  user_question = voice_task.transcribed_text
133
+ logger.info(f'用户问题: {user_question}')
134
  if self.websocket_message_queue:
135
  self.websocket_message_queue.put_nowait(
136
  QuestionDisplayMessage(
 
178
  self._handle_remaining_chunks(voice_task, chunks, answer_index)
179
 
180
  except Exception as e:
181
+ logger.error(f'处理语音任务时发生错误: {e}')
182
 
183
  def _handle_remaining_chunks(self, voice_task: VoiceTask, chunks: list, answer_index: int) -> None:
184
  """处理剩余的 chunks"""
 
198
 
199
  # 打印芯片信息和优化配置
200
  chip_summary = get_apple_silicon_summary()
201
+ logger.info(f"检测到芯片: {chip_summary['chip_name']}")
202
+ logger.info(f"性能核心数: {chip_summary['performance_cores']}")
203
+ logger.info(f"使用线程数: {chip_summary['optimal_n_threads']} (仅使用性能核心)")
204
+ logger.info(f"上下文窗口: {chip_summary['optimal_n_ctx']}")
205
+ logger.info(f"配置说明: {chip_summary['config_note']}")
206
 
207
  self.model_instance = create_langchain_chat_llamacpp_instance(
208
  local_model_path=model_path, model_params=model_params
 
220
  except Empty:
221
  continue
222
  except Exception as e:
223
+ logger.error(f'AnswerGeneratorWorker 运行时发生错误: {e}')
src/voice_dialogue/services/text/processor.py CHANGED
@@ -9,6 +9,7 @@ from langchain_core.prompts import (
9
  )
10
  from langchain_core.runnables import RunnableWithMessageHistory
11
 
 
12
  from voice_dialogue.utils.strings import (
13
  remove_emojis, convert_comma_separated_numbers, convert_uppercase_words_to_lowercase
14
  )
@@ -18,7 +19,7 @@ def create_langchain_chat_llamacpp_instance(
18
  local_model_path: str,
19
  model_params: dict | None = None
20
  ) -> ChatLlamaCpp:
21
- print(">>>>>>> Initializing LlamaCpp Langchain instance...")
22
 
23
  model_path = pathlib.Path(local_model_path)
24
  callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
@@ -55,7 +56,7 @@ def create_langchain_pipeline(langchain_instance, system_prompt: str, get_sessio
55
 
56
 
57
  def warmup_langchain_pipeline(pipeline):
58
- print("Warmup chat pipeline...")
59
 
60
  user_input = 'Hello, this is warming up step, if you understand, output "Ok".'
61
  config = {"configurable": {"session_id": 'warmup'}}
 
9
  )
10
  from langchain_core.runnables import RunnableWithMessageHistory
11
 
12
+ from voice_dialogue.utils.logger import logger
13
  from voice_dialogue.utils.strings import (
14
  remove_emojis, convert_comma_separated_numbers, convert_uppercase_words_to_lowercase
15
  )
 
19
  local_model_path: str,
20
  model_params: dict | None = None
21
  ) -> ChatLlamaCpp:
22
+ logger.info(">>>>>>> Initializing LlamaCpp Langchain instance...")
23
 
24
  model_path = pathlib.Path(local_model_path)
25
  callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
 
56
 
57
 
58
  def warmup_langchain_pipeline(pipeline):
59
+ logger.info("Warmup chat pipeline...")
60
 
61
  user_input = 'Hello, this is warming up step, if you understand, output "Ok".'
62
  config = {"configurable": {"session_id": 'warmup'}}
src/voice_dialogue/utils/__init__.py CHANGED
@@ -4,6 +4,7 @@ from .download_utils import (
4
  download_model_from_huggingface, download_file_from_huggingface, check_file_exists_on_huggingface,
5
  download_lora_from_huggingface, download_civitai_file
6
  )
 
7
  from .strings import remove_emojis
8
  from .system import get_system_language, get_system_info
9
 
@@ -63,4 +64,5 @@ __all__ = (
63
  'LRUCacheDict',
64
  'get_system_language',
65
  'get_system_info',
 
66
  )
 
4
  download_model_from_huggingface, download_file_from_huggingface, check_file_exists_on_huggingface,
5
  download_lora_from_huggingface, download_civitai_file
6
  )
7
+ from .logger import logger
8
  from .strings import remove_emojis
9
  from .system import get_system_language, get_system_info
10
 
 
64
  'LRUCacheDict',
65
  'get_system_language',
66
  'get_system_info',
67
+ 'logger',
68
  )
src/voice_dialogue/utils/logger.py CHANGED
@@ -1,81 +1,37 @@
1
- import logging
2
  import sys
3
- from logging.handlers import RotatingFileHandler
4
- from pathlib import Path
 
 
5
 
6
 
7
  def setup_logger(
8
- logger_name: str = "app",
9
- log_file: str = "app.log",
10
- level: int = logging.INFO,
11
- log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
12
- max_bytes: int = 5_242_880, # 5MB
13
- backup_count: int = 3
14
- ) -> logging.Logger:
15
  """
16
- Configure and return a logger with both file and console handlers.
17
 
18
  Args:
19
- logger_name: Name of the logger
20
- log_file: Path to the log file
21
- level: Logging level
22
- log_format: Format string for log messages
23
- max_bytes: Maximum size of log file before rotation
24
- backup_count: Number of backup files to keep
25
 
26
  Returns:
27
- logging.Logger: Configured logger instance
28
  """
29
- # Create logger
30
- logger = logging.getLogger(logger_name)
31
- logger.setLevel(level)
32
-
33
- # Create formatters
34
- formatter = logging.Formatter(log_format)
35
-
36
- # Ensure log directory exists
37
- log_path = Path(log_file)
38
- log_path.parent.mkdir(parents=True, exist_ok=True)
39
-
40
- # Create and configure file handler with rotation
41
- file_handler = RotatingFileHandler(
42
- log_file,
43
- maxBytes=max_bytes,
44
- backupCount=backup_count,
45
- encoding='utf-8'
46
  )
47
- file_handler.setFormatter(formatter)
48
- file_handler.setLevel(level)
49
 
50
- # Create and configure console handler
51
- console_handler = logging.StreamHandler(sys.stdout)
52
- console_handler.setFormatter(formatter)
53
- console_handler.setLevel(level)
54
 
55
- # Add handlers to logger if they haven't been added already
56
- if not logger.handlers:
57
- logger.addHandler(file_handler)
58
- logger.addHandler(console_handler)
59
 
60
- return logger
61
-
62
-
63
- # Example usage
64
- if __name__ == "__main__":
65
- # Basic setup
66
- logger = setup_logger()
67
- logger.info("Basic logger initialized")
68
-
69
- # Custom setup example
70
- custom_logger = setup_logger(
71
- logger_name="custom_app",
72
- log_file="logs/custom.log",
73
- level=logging.DEBUG,
74
- log_format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
75
- max_bytes=1_048_576, # 1MB
76
- backup_count=5
77
- )
78
- custom_logger.debug("Custom logger initialized")
79
- custom_logger.info("This is an info message")
80
- custom_logger.warning("This is a warning message")
81
- custom_logger.error("This is an error message")
 
 
1
  import sys
2
+
3
+ from loguru import logger as _logger
4
+
5
+ __all__ = ("logger",)
6
 
7
 
8
  def setup_logger(
9
+ level: str = "INFO",
10
+ log_format: str = "<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
11
+ ) -> object:
 
 
 
 
12
  """
13
+ Configure and return a loguru logger with console output only.
14
 
15
  Args:
16
+ level: 日志级别 (INFO, DEBUG, WARNING, ERROR, CRITICAL)
17
+ log_format: 日志格式字符串
 
 
 
 
18
 
19
  Returns:
20
+ loguru.logger: 配置好的logger实例
21
  """
22
+ # 移除所有现有的处理器
23
+ _logger.remove()
24
+
25
+ # 添加控制台处理器
26
+ _logger.add(
27
+ sys.stdout,
28
+ level=level.upper(),
29
+ format=log_format,
30
+ colorize=True,
31
+ enqueue=True # 使日志线程安全
 
 
 
 
 
 
 
32
  )
 
 
33
 
34
+ return _logger
 
 
 
35
 
 
 
 
 
36
 
37
+ logger = setup_logger()