Browse Source

8-1-2连接

Zzcoded 2 days ago
parent
commit
0f2c50f0b0

+ 142 - 0
main/server/core/connnection.py

@@ -0,0 +1,142 @@
+import os
+import sys
+import copy
+import json
+import uuid
+import time
+import queue
+import asyncio
+import threading
+import traceback
+import subprocess
+import websockets
+from config.logger import setup_logging
+from core.auth import AuthMiddleware, AuthenticationError
+from concurrent.futures import ThreadPoolExecutor
+from core.utils.voiceprint_provider import VoiceprintProvider
+from collections import deque
+from core.utils.dialogue import Dialogue
+from core.utils.prompt_manager import PromptManager
+
+
+
+TAG = __name__
+
+auto_import_modules("plugins_func.functions")
+
+class TTSSException(RuntimeError):
+    pass
+
+
+class ConnnectionHandler:
+    def __init_(
+        self,
+        config: Dict[str, Any],
+        _vad,
+        _asr,
+        _llm,
+        _memory,
+        _intent.
+        server=None,
+    ):
+        self.common_config = config
+        self.config = copy.deepcopy(config)
+        self.session_id = str(uuid.uuid4())
+        self.logger = setup_logging()
+        self.server = server # 保存server实例的引用
+
+        self.auth = AuthMiddleware(config)
+        self.need_bind = False
+        self.bind_code = None
+        self.read_config_from_api = self.config.get("read_config_from_api",False)
+
+        self.websocket = None
+        self.headers = None
+        self.device_id = None
+        self.client_ip = None
+        self.prompt = None
+        self.welcome_msg = None
+        self.max_output_size = 0
+        self.chat_history_conf = 0
+        self.audio_format = "opus"
+
+        # 客户端状态相关
+        self.client_abort = False
+        self.client_is_speaking = False
+        self.client_listen_mode = "auto"
+
+        # 线程任务相关
+        self.loop = asyncio.get_event_loop()
+        self.stop_event = threading.Event()
+        self.executor = ThreadPoolExecutor(max_workers=5)
+
+        # 添加上报线程池
+        self.report_queue = queue.Queue()
+        self.report_thread = None
+        # 未来可以通过修改此处,调节asr的上报和tts的上报,目前默认都开启
+        self.report_asr_enable = self.read_config_from_api
+        self.report_tts_enable = self.read_config_from_api
+
+        # 依赖的组件
+        self.vad = None
+        self.asr = None
+        self.tts = None
+        self._asr = _asr
+        self._vad = _vad
+        self.llm = _llm
+        self.memory = _memory
+        self.intent = _intent
+
+        # 为每个连接单独管理声纹识别
+        self.voiceprint_provider = None
+
+        # vad相关变量
+        self.client_audio_buffer = bytearray()
+        self.client_have_voice = False
+        self.last_activity_time = 0.0 # 统一的活动时间戳(毫秒)
+        self.client_voice_stop = False
+        self.client_voice_window = deque(maxlen=5)
+        self.last_is_voice = False
+
+         # asr相关变量
+        # 因为实际部署时可能会用到公共的本地ASR,不能把变量暴露给公共ASR
+        # 所以涉及到ASR的变量,需要在这里定义,属于connection的私有变量
+        self.asr_audio = []
+        self.asr_audio_queue = queue.Queue()
+
+        # llm相关变量
+        self.llm_finish_task = True
+        self.dialogue = Dialogue()
+
+        # tts相关变量
+        self.sentence_id = None
+        self.tts_MessageText = ""
+
+        # iot相关变量
+        self.iot_descriptors = {}
+        self.func_handler = None
+
+        self.cmd_exit = self.config["exit_commands"]
+        self.max_cmd_length = 0
+        for cmd in self.cmd_exit:
+            if len(cmd) > self.max_cmd_length:
+                self.max_cmd_length = len(cmd)
+
+        # 是否在聊天结束后关闭连接
+        self.close_after_chat = False
+        self.load_function_plugins = False
+        self.intent_type = "nointent"
+
+        self.timeout_seconds = (
+            int(self.config.get("close_connection_no_voice_time", 120)) + 60
+        ) # 在第一道语音结束后的60秒后,如果用户没有说话,则关闭连接
+        self.timeout_task = None
+
+        # {"mcp": true} 表示启用MCP功能
+        self.features = None
+
+        # 初始化提示词管理器
+        self.prompt_manager = PromptManager(config, self.logger)
+
+
+

+ 74 - 0
main/server/core/http_server.py

@@ -0,0 +1,74 @@
+import asyncio
+from aiohttp import web
+from config.logger import setup_logging
+from core.api.ota_handler import OTAHandler 
+from core.api.vision_handler import VisionHandler
+
+TAG = __name__
+
+
+class SimpleHttpServer:
+    def __init__(self,config:dict):
+        self.config = config
+        self.logger = setup_logging()
+        self.ota_handler = OTAHandler(config)
+        self.vision_handler = VisionHandler(config)
+
+    def _get_websocket_url(self, local_ip: str, port: int) -> str:
+        """
+        获取WebSocket URL
+
+        Args:
+            local_ip (str): 本地IP地址
+            port (int): 端口号
+
+        Returns:
+            str: WebSocket URL
+        """
+        server_config = self.config["server"]
+        websocket_config = server_config.get("websocket",{})
+
+        # 需要修改的点
+        if websocket_config and "你" not in websocket_config:
+            return websocket_config
+        else:
+            return f"ws://{local_ip}:{websocket_config['port']}"
+        
+    async def start(self):
+        server_config = self.config["server"]
+        host = server_config.get("ip", "0.0.0.0")
+        port = server_config.get("port", 8083)
+
+        if port:
+            app = web.Application()
+            read_config_from_api = server_config.get("read_config_from_api",False)
+
+            if not read_config_from_api:
+                # 如果没有开启智控台, 只是单模块运行, 就需要再添加简单的OTA接口, 用于下发websocket接口
+                app.add_routes(
+                    [
+                        web.get("/xiaozhi/ota", self.ota_handler.handle_get),
+                        web.post("/xiaozhi/ota", self.ota_handler.handle_post),
+                        web.options("/xiaozhi/ota", self.ota_handler.handle_post),
+                    ]
+                )
+
+            # 添加路由
+            app.add_routes(
+                [
+                    web.get("/mcp/vision/explain", self.vision_handler.handle_get),
+                    web.post("/mcp/vision/explain", self.vision_handler.handle_post),
+                    web.options("/mcp/vision/explain", self.vision_handler.handle_post),
+                ]
+            )
+
+            # 运行服务
+            runner = web.AppRunner(app)
+            await runner.setup()
+            site = web.TCPSite(runner, host, port)
+            await site.start()
+            
+
+            # 保持服务运行
+            while True:
+                await asyncio.sleep(3600) # 每隔1小时检查一次

+ 63 - 0
main/server/core/utils/prompt_manager.py

@@ -0,0 +1,63 @@
+"""
+系统提示词管理器模块,
+负责管理和更新系统提示词,包括快速初始化和异步增强功能
+"""
+
+import os
+import cnlunar
+from typing import Dict, Any
+from config.logger import setup_logging
+
+TAG = __name__
+
+WEEKDAY_MAP = {
+    "Monday": "星期一",
+    "Tuesday": "星期二",
+    "Wednesday": "星期三",
+    "Thursday": "星期四",
+    "Friday": "星期五",
+    "Saturday": "星期六",
+    "Sunday": "星期日",
+}
+
+EMOJI_List = [
+    "😶",
+    "🙂",
+    "😆",
+    "😂",
+    "😔",
+    "😠",
+    "😭",
+    "😍",
+    "😳",
+    "😲",
+    "😱",
+    "🤔",
+    "😉",
+    "😎",
+    "😌",
+    "🤤",
+    "😘",
+    "😏",
+    "😴",
+    "😜",
+    "🙄",
+]
+
+class PromptManager:
+    """系统提示词管理器,负责管理和更新系统提示词"""
+    def __init__(self, config: Dict[str, Any], logger):
+        self.config = config
+        self.logger = logger or setup_logging()
+        self.base_prompt_template = None
+        self.last_update_time = 0
+
+        # 导入全局缓存管理器
+        from core.utils.cathe.manager import cache_manager, CacheType
+
+        self.cache_manager = cache_manager
+        self.CacheType = CacheType
+        
+        self._load_base_template()
+
+    def