2222import base64
2323from io import BytesIO
2424from PIL import Image
25- from config import MASTER_NAME , MEMORY_SERVER_PORT , CORE_API_KEY , CORE_URL , CORE_MODEL , USE_TTS
25+ from config import get_character_data , CORE_URL , CORE_MODEL , CORE_API_KEY , MEMORY_SERVER_PORT , AUDIO_API_KEY
2626from multiprocessing import Process , Queue as MPQueue
2727from uuid import uuid4
2828import numpy as np
@@ -62,7 +62,27 @@ def __init__(self, sync_message_queue, lanlan_name, lanlan_prompt):
6262
6363 self .lanlan_prompt = lanlan_prompt
6464 self .lanlan_name = lanlan_name
65- self .MODEL = CORE_MODEL
65+ # 获取角色相关配置
66+ (
67+ self .master_name ,
68+ self .her_name ,
69+ self .master_basic_config ,
70+ self .lanlan_basic_config ,
71+ self .name_mapping ,
72+ self .lanlan_prompt_map ,
73+ self .semantic_store ,
74+ self .time_store ,
75+ self .setting_store ,
76+ self .recent_log
77+ ) = get_character_data ()
78+ # 获取API相关配置
79+ self .model = CORE_MODEL
80+ self .core_url = CORE_URL
81+ self .core_api_key = CORE_API_KEY
82+ self .memory_server_port = MEMORY_SERVER_PORT
83+ self .audio_api_key = AUDIO_API_KEY
84+ self .voice_id = self .lanlan_basic_config [self .lanlan_name ].get ('voice_id' , '' )
85+ self .use_tts = False if not self .voice_id else True
6686 self .generation_config = {} # Qwen暂时不用
6787 self .message_cache_for_new_session = []
6888 self .is_preparing_new_session = False
@@ -75,9 +95,6 @@ def __init__(self, sync_message_queue, lanlan_name, lanlan_prompt):
7595 self .pending_session = None
7696 self .is_hot_swap_imminent = False
7797 self .tts_handler_task = None
78- self .use_tts = USE_TTS
79- # 将TTS相关的导入移到外部,确保始终可用
80-
8198 # 热切换相关变量
8299 self .background_preparation_task = None
83100 self .final_swap_task = None
@@ -86,9 +103,9 @@ def __init__(self, sync_message_queue, lanlan_name, lanlan_prompt):
86103
87104 # 注册回调
88105 self .session = OmniRealtimeClient (
89- base_url = CORE_URL ,
90- api_key = CORE_API_KEY ,
91- model = self .MODEL ,
106+ base_url = self . core_url ,
107+ api_key = self . core_api_key ,
108+ model = self .model ,
92109 voice = "Chelsie" ,
93110 on_text_delta = self .handle_text_data ,
94111 on_audio_delta = self .handle_audio_data ,
@@ -188,8 +205,8 @@ async def handle_input_transcript(self, transcript: str):
188205 if not hasattr (self , 'message_cache_for_new_session' ):
189206 self .message_cache_for_new_session = []
190207 if len (self .message_cache_for_new_session ) == 0 or self .message_cache_for_new_session [- 1 ]['role' ] == self .lanlan_name :
191- self .message_cache_for_new_session .append ({"role" : MASTER_NAME , "text" : transcript .strip ()})
192- elif self .message_cache_for_new_session [- 1 ]['role' ] == MASTER_NAME :
208+ self .message_cache_for_new_session .append ({"role" : self . master_name , "text" : transcript .strip ()})
209+ elif self .message_cache_for_new_session [- 1 ]['role' ] == self . master_name :
193210 self .message_cache_for_new_session [- 1 ]['text' ] += transcript .strip ()
194211 # 可选:推送用户活动
195212 with self .lock :
@@ -215,7 +232,7 @@ async def send_lanlan_response(self, text: str, is_first_chunk: bool = False):
215232 if hasattr (self , 'is_preparing_new_session' ) and self .is_preparing_new_session :
216233 if not hasattr (self , 'message_cache_for_new_session' ):
217234 self .message_cache_for_new_session = []
218- if len (self .message_cache_for_new_session ) == 0 or self .message_cache_for_new_session [- 1 ]['role' ]== MASTER_NAME :
235+ if len (self .message_cache_for_new_session ) == 0 or self .message_cache_for_new_session [- 1 ]['role' ]== self . master_name :
219236 self .message_cache_for_new_session .append (
220237 {"role" : self .lanlan_name , "text" : text })
221238 elif self .message_cache_for_new_session [- 1 ]['role' ] == self .lanlan_name :
@@ -289,10 +306,9 @@ async def start_session(self, websocket: WebSocket, new=False):
289306 if self .use_tts :
290307 # 启动TTS子进程
291308 if self .tts_process is None or not self .tts_process .is_alive ():
292- from config import AUDIO_API_KEY , VOICE_ID
293309 self .tts_process = Process (
294310 target = speech_synthesis_worker ,
295- args = (self .tts_request_queue , self .tts_response_queue , AUDIO_API_KEY , VOICE_ID )
311+ args = (self .tts_request_queue , self .tts_response_queue , self . audio_api_key , self . voice_id )
296312 )
297313 self .tts_process .daemon = True
298314 self .tts_process .start ()
@@ -309,9 +325,9 @@ async def start_session(self, websocket: WebSocket, new=False):
309325 try :
310326 # 获取初始 prompt
311327 initial_prompt = self .lanlan_prompt
312- initial_prompt += requests .get (f"http://localhost:{ MEMORY_SERVER_PORT } /new_dialog/{ self .lanlan_name } " ).text
313- logger .info ("====Initial Prompt=====" )
314- logger .info (initial_prompt )
328+ initial_prompt += requests .get (f"http://localhost:{ self . memory_server_port } /new_dialog/{ self .lanlan_name } " ).text
329+ # logger.info("====Initial Prompt=====")
330+ # logger.info(initial_prompt)
315331
316332 # 标记 session 激活
317333 if self .session :
@@ -361,9 +377,9 @@ async def _background_prepare_pending_session(self):
361377 try :
362378 # 创建新的pending session
363379 self .pending_session = OmniRealtimeClient (
364- base_url = CORE_URL ,
365- api_key = CORE_API_KEY ,
366- model = self .MODEL ,
380+ base_url = self . core_url ,
381+ api_key = self . core_api_key ,
382+ model = self .model ,
367383 voice = "Chelsie" ,
368384 on_text_delta = self .handle_text_data ,
369385 on_audio_delta = self .handle_audio_data ,
@@ -377,7 +393,7 @@ async def _background_prepare_pending_session(self):
377393 initial_prompt = self .lanlan_prompt
378394 self .initial_cache_snapshot_len = len (self .message_cache_for_new_session )
379395 async with httpx .AsyncClient () as client :
380- resp = await client .get (f"http://localhost:{ MEMORY_SERVER_PORT } /new_dialog/{ self .lanlan_name } " )
396+ resp = await client .get (f"http://localhost:{ self . memory_server_port } /new_dialog/{ self .lanlan_name } " )
381397 initial_prompt += resp .text + self ._convert_cache_to_str (self .message_cache_for_new_session )
382398 # print(initial_prompt)
383399 await self .pending_session .connect (initial_prompt , native_audio = not self .use_tts )
@@ -415,7 +431,7 @@ async def _perform_final_swap_sequence(self):
415431 # 1. Send incremental cache (or a heartbeat) to PENDING session for its *second* ignored response
416432 if incremental_cache :
417433 final_prime_text = f"SYSTEM_MESSAGE | " + self ._convert_cache_to_str (incremental_cache ) + \
418- f'=======以上为前情概要。现在请{ self .lanlan_name } 准备,即将开始用语音与{ MASTER_NAME } 继续对话。\n '
434+ f'=======以上为前情概要。现在请{ self .lanlan_name } 准备,即将开始用语音与{ self . master_name } 继续对话。\n '
419435 else : # Ensure session cycles a turn even if no incremental cache
420436 logger .error (f"💥 Unexpected: No incremental cache found. { len (self .message_cache_for_new_session )} , { self .initial_cache_snapshot_len } " )
421437 final_prime_text = f"SYSTEM_MESSAGE | 系统自动报时,当前时间: " + str (
@@ -717,14 +733,14 @@ async def tts_response_handler(self):
717733
718734# TTS多进程worker函数,供主进程Process(target=...)调用
719735
720- def speech_synthesis_worker (request_queue , response_queue , AUDIO_API_KEY , VOICE_ID ):
736+ def speech_synthesis_worker (request_queue , response_queue , audio_api_key , voice_id ):
721737 import dashscope
722738 from dashscope .audio .tts_v2 import ResultCallback , SpeechSynthesizer , AudioFormat
723739 import numpy as np
724740 from librosa import resample
725741 import re
726742 import time
727- dashscope .api_key = AUDIO_API_KEY
743+ dashscope .api_key = audio_api_key
728744 class Callback (ResultCallback ):
729745 def __init__ (self , response_queue ):
730746 self .response_queue = response_queue
@@ -766,7 +782,7 @@ def on_data(self, data: bytes) -> None:
766782 pass
767783 synthesizer = SpeechSynthesizer (
768784 model = "cosyvoice-v2" ,
769- voice = VOICE_ID ,
785+ voice = voice_id ,
770786 speech_rate = 1.1 ,
771787 format = AudioFormat .PCM_24000HZ_MONO_16BIT ,
772788 callback = callback ,
0 commit comments