{"id":1285,"date":"2025-12-04T14:44:25","date_gmt":"2025-12-04T06:44:25","guid":{"rendered":"http:\/\/www.preluna.xyz\/?p=1285"},"modified":"2025-12-06T08:57:10","modified_gmt":"2025-12-06T00:57:10","slug":"nagaagent-mainapiserver","status":"publish","type":"post","link":"http:\/\/www.preluna.xyz\/index.php\/2025\/12\/04\/nagaagent-mainapiserver\/preluna\/technology\/career-skills\/open-source-analysis\/","title":{"rendered":"NagaAgent-main\\apiserver"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">llm_service.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n\"\"\"\nLLM\u670d\u52a1\u6a21\u5757\n\u63d0\u4f9b\u7edf\u4e00\u7684LLM\u8c03\u7528\u63a5\u53e3\uff0c\u66ff\u4ee3conversation_core.py\u4e2d\u7684get_response\u65b9\u6cd5\n\"\"\"\n\nimport logging\nimport sys\nimport os\nfrom typing import Optional, Dict, Any, List\n'''\n\u7c7b\u578b\u63d0\u793a\uff08\u7b2c8\u884c\uff09\uff1a\nOptional\uff1a\u8868\u793a\u8fd9\u4e2a\u53d8\u91cf\u53ef\u80fd\u6709\u503c\uff0c\u4e5f\u53ef\u80fd\u662fNone\uff08\u7a7a\uff09\nDict\uff1a\u5b57\u5178\u7c7b\u578b\uff08\u952e\u503c\u5bf9\uff09\nAny\uff1a\u4efb\u610f\u7c7b\u578b\nList\uff1a\u5217\u8868\u7c7b\u578b\n'''\n\n# \u6dfb\u52a0\u9879\u76ee\u6839\u76ee\u5f55\u5230Python\u8def\u5f84\nsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n\nfrom nagaagent_core.core import AsyncOpenAI\nfrom nagaagent_core.api import FastAPI, HTTPException\nfrom system.config import config\n'''\n\u81ea\u5b9a\u4e49\u6a21\u5757\uff1a\nAsyncOpenAI\uff1a\u5f02\u6b65\u7684OpenAI\u5ba2\u6237\u7aef\uff08\u7528\u6765\u548cAI\u5bf9\u8bdd\uff09\nFastAPI\uff1a\u521b\u5efaWeb API\u7684\u5de5\u5177\nHTTPException\uff1aHTTP\u5f02\u5e38\u5904\u7406\nconfig\uff1a\u914d\u7f6e\u6587\u4ef6\uff0c\u5b58\u50a8API\u5bc6\u94a5\u7b49\u8bbe\u7f6e\n'''\n\n# \u914d\u7f6e\u65e5\u5fd7\nlogger = logging.getLogger(\"LLMService\")\n\nclass LLMService:\n    \"\"\"LLM\u670d\u52a1\u7c7b - \u63d0\u4f9b\u7edf\u4e00\u7684LLM\u8c03\u7528\u63a5\u53e3\"\"\"\n    \n    def __init__(self):\n        self.async_client: Optional&#91;AsyncOpenAI] = None  #\u521b\u5efa\u4e86\u4e00\u4e2a\u53d8\u91cf async_client\uff0c\u521d\u59cb\u503c\u662fNone\n        self._initialize_client()  #\u8c03\u7528 _initialize_client() \u65b9\u6cd5\u6765\u521d\u59cb\u5316\u5ba2\u6237\u7aef\n    \n    def _initialize_client(self):\n        \"\"\"\u521d\u59cb\u5316OpenAI\u5ba2\u6237\u7aef\"\"\"\n        try:\n            self.async_client = AsyncOpenAI(\n                api_key=config.api.api_key, \n                base_url=config.api.base_url.rstrip('\/') + '\/'\n            )\n            logger.info(\"LLM\u670d\u52a1\u5ba2\u6237\u7aef\u521d\u59cb\u5316\u6210\u529f\")\n        except Exception as e:\n            logger.error(f\"LLM\u670d\u52a1\u5ba2\u6237\u7aef\u521d\u59cb\u5316\u5931\u8d25: {e}\")\n            self.async_client = None\n            '''\n            \u8fd9\u4e2a\u65b9\u6cd5\u7684\u903b\u8f91\uff1a\n               \u5c1d\u8bd5\u521b\u5efaOpenAI\u5ba2\u6237\u7aef\n               \u5982\u679c\u6210\u529f\uff1a\u8bb0\u5f55\u6210\u529f\u65e5\u5fd7\n               \u5982\u679c\u5931\u8d25\uff1a\u8bb0\u5f55\u9519\u8bef\u65e5\u5fd7\uff0c\u628a\u5ba2\u6237\u7aef\u8bbe\u4e3aNone\n            '''\n   \n# ====== 4\u4e2a\u4e3b\u8981\u7684\u65b9\u6cd5=======  \n'''\n\u65b9\u6cd5\u540d                      |  \u4f5c\u7528            | \u7279\u70b9\nget_response               | \u83b7\u53d6AI\u7684\u56de\u590d      | \u6700\u7b80\u5355\u7684\uff0c\u53ea\u53d1\u4e00\u4e2a\u95ee\u9898\nchat_with_context          | \u5e26\u4e0a\u4e0b\u6587\u7684\u804a\u5929     | \u53ef\u4ee5\u8bb0\u4f4f\u4e4b\u524d\u7684\u5bf9\u8bdd\nstream_chat_with_context   | \u6d41\u5f0f\u804a\u5929          | \u4e00\u4e2a\u5b57\u4e00\u4e2a\u5b57\u5730\u8fd4\u56de\uff0c\u50cf\u6253\u5b57\u4e00\u6837\nis_available               | \u68c0\u67e5\u670d\u52a1\u662f\u5426\u53ef\u7528   | \u8fd4\u56deTrue\u6216False\n'''   \n\n    \n    async def get_response(self, prompt: str, temperature: float = 0.7) -&gt; str:\n        \"\"\"\u4e3a\u5176\u4ed6\u6a21\u5757\u63d0\u4f9bAPI\u8c03\u7528\u63a5\u53e3\"\"\"\n        #\u8fd9\u662f\u4e00\u4e2a\u53cc\u91cd\u68c0\u67e5\uff1a\n        if not self.async_client:  # \u5982\u679c\u5ba2\u6237\u7aef\u4e0d\u5b58\u5728\n            self._initialize_client()  # \u5c1d\u8bd5\u521d\u59cb\u5316\n            if not self.async_client: # \u5982\u679c\u8fd8\u662f\u4e0d\u5b58\u5728\n                return f\"LLM\u670d\u52a1\u4e0d\u53ef\u7528: \u5ba2\u6237\u7aef\u521d\u59cb\u5316\u5931\u8d25\" # \u8fd4\u56de\u9519\u8bef\u4fe1\u606f\n        \n        try:\n            response = await self.async_client.chat.completions.create(\n                model=config.api.model,\n                messages=&#91;{\"role\": \"user\", \"content\": prompt}],\n                temperature=temperature,\n                max_tokens=config.api.max_tokens\n            )\n            return response.choices&#91;0].message.content\n        except RuntimeError as e:\n            if \"handler is closed\" in str(e):  # \u5982\u679c\u662f\u8fde\u63a5\u5173\u95ed\u7684\u9519\u8bef\n                logger.debug(f\"\u5ffd\u7565\u8fde\u63a5\u5173\u95ed\u5f02\u5e38\uff0c\u91cd\u65b0\u521b\u5efa\u5ba2\u6237\u7aef: {e}\")\n                # \u91cd\u65b0\u521b\u5efa\u5ba2\u6237\u7aef\u5e76\u91cd\u8bd5\n                self._initialize_client()\n                if self.async_client:   # \u5982\u679c\u91cd\u65b0\u521b\u5efa\u6210\u529f\n                    # \u91cd\u65b0\u5c1d\u8bd5\u8bf7\u6c42\n                    response = await self.async_client.chat.completions.create(\n                        model=config.api.model,\n                        messages=&#91;{\"role\": \"user\", \"content\": prompt}],\n                        temperature=temperature,\n                        max_tokens=config.api.max_tokens\n                    )\n                    return response.choices&#91;0].message.content\n                else:   # \u5982\u679c\u91cd\u65b0\u521b\u5efa\u5931\u8d25\n                    return f\"LLM\u670d\u52a1\u4e0d\u53ef\u7528: \u91cd\u8fde\u5931\u8d25\"\n            else:\n                logger.error(f\"API\u8c03\u7528\u5931\u8d25: {e}\")\n                return f\"API\u8c03\u7528\u51fa\u9519: {str(e)}\"\n        except Exception as e:\n            logger.error(f\"API\u8c03\u7528\u5931\u8d25: {e}\")\n            return f\"API\u8c03\u7528\u51fa\u9519: {str(e)}\"\n    \n    def is_available(self) -&gt; bool:\n        \"\"\"\u68c0\u67e5LLM\u670d\u52a1\u662f\u5426\u53ef\u7528\"\"\"\n        return self.async_client is not None\n    \n    async def chat_with_context(self, messages: List&#91;Dict], temperature: float = 0.7) -&gt; str:\n        \"\"\"\u5e26\u4e0a\u4e0b\u6587\u7684\u804a\u5929\u8c03\u7528\"\"\"\n        if not self.async_client:\n            self._initialize_client()\n            if not self.async_client:\n                return f\"LLM\u670d\u52a1\u4e0d\u53ef\u7528: \u5ba2\u6237\u7aef\u521d\u59cb\u5316\u5931\u8d25\"\n        \n        try:\n            response = await self.async_client.chat.completions.create(\n                model=config.api.model,\n                messages=messages,\n                temperature=temperature,\n                max_tokens=config.api.max_tokens\n            )\n            return response.choices&#91;0].message.content\n        except Exception as e:\n            logger.error(f\"\u4e0a\u4e0b\u6587\u804a\u5929\u8c03\u7528\u5931\u8d25: {e}\")\n            return f\"\u804a\u5929\u8c03\u7528\u51fa\u9519: {str(e)}\"\n    \n    #stream_chat_with_context\uff1a\u65b9\u6cd5\u540d\uff0c\u610f\u601d\u662f\"\u6d41\u5f0f\u804a\u5929\u5e26\u4e0a\u4e0b\u6587\"\n    #messages\uff1a\u53c2\u65701\uff0c\u804a\u5929\u8bb0\u5f55\u5217\u8868\uff08\u5305\u542b\u4e4b\u524d\u7684\u6240\u6709\u5bf9\u8bdd\uff09\n    #temperature\uff1a\u53c2\u65702\uff0c\u6e29\u5ea6\u503c\uff08\u63a7\u5236AI\u56de\u7b54\u7684\u968f\u673a\u6027\uff09\uff0c\u9ed8\u8ba40.7\n    async def stream_chat_with_context(self, messages: List&#91;Dict], temperature: float = 0.7):\n        \"\"\"\u5e26\u4e0a\u4e0b\u6587\u7684\u6d41\u5f0f\u804a\u5929\u8c03\u7528\"\"\"\n        #\u68c0\u67e5\u5ba2\u6237\u7aef\u662f\u5426\u53ef\u7528\n        if not self.async_client:  #\u5982\u679c\u5ba2\u6237\u7aef\u4e0d\u5b58\u5728\n            self._initialize_client()  #\u5c1d\u8bd5\u521d\u59cb\u5316\u5ba2\u6237\u7aef\n            if not self.async_client:  #\u518d\u6b21\u68c0\u67e5\uff1a\u5982\u679c\u521d\u59cb\u5316\u540e\u8fd8\u662f\u4e0d\u5b58\u5728\n                yield f\"LLM\u670d\u52a1\u4e0d\u53ef\u7528: \u5ba2\u6237\u7aef\u521d\u59cb\u5316\u5931\u8d25\"  #\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\n                return\n        \n        try:\n            import aiohttp  #\u5bfc\u5165HTTP\u5ba2\u6237\u7aef\u5e93\n            timeout = aiohttp.ClientTimeout(total=180, connect=60, sock_read=120)\n            async with aiohttp.ClientSession(timeout=timeout) as session: #\u521b\u5efa\u4e00\u4e2aHTTP\u4f1a\u8bdd,async with \u4f1a\u81ea\u52a8\u7ba1\u7406\u8d44\u6e90\uff0c\u7ed3\u675f\u65f6\u81ea\u52a8\u5173\u95ed\n                async with session.post(  #\u53d1\u9001POST\u8bf7\u6c42\u5230AI\u670d\u52a1,\u8bf7\u6c42\u5730\u5740\u662f\uff1a\u57fa\u7840URL\/chat\/completions\n                    f\"{config.api.base_url}\/chat\/completions\",\n                    headers={                                              #headers={...}\uff1a\u8bf7\u6c42\u5934\uff0c\u5305\u542b\uff1a\n                        \"Authorization\": f\"Bearer {config.api.api_key}\",   #\u8ba4\u8bc1\u4fe1\u606f\uff08API\u5bc6\u94a5\uff09\n                        \"Content-Type\": \"application\/json\",                #\u5185\u5bb9\u7c7b\u578b\u662fJSON\n                        \"Accept\": \"text\/event-stream\",                     #\u63a5\u53d7\u4e8b\u4ef6\u6d41\u683c\u5f0f\uff08\u6d41\u5f0f\u4f20\u8f93\uff09\n                        \"Connection\": \"keep-alive\"                         #\u4fdd\u6301\u8fde\u63a5\n                    },\n                    json={                                                 #\u8bf7\u6c42\u4f53\uff0c\u5305\u542b\uff1a\n                        \"model\": config.api.model,                         #\u4f7f\u7528\u54ea\u4e2aAI\u6a21\u578b\n                        \"messages\": messages,                              #\u804a\u5929\u8bb0\u5f55\n                        \"temperature\": temperature,                        #\u6e29\u5ea6\u503c\n                        \"max_tokens\": config.api.max_tokens,               #\u6700\u5927\u4ee4\u724c\u6570\n                        \"stream\": True                                     #\u5f00\u542f\u6d41\u5f0f\u4f20\u8f93\n                    }\n                ) as resp:\n                    if resp.status != 200:  #\u83b7\u53d6HTTP\u72b6\u6001\u7801\uff08200\u8868\u793a\u6210\u529f\uff09\uff0c\u5982\u679c\u4e0d\u662f200\uff0c\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\u5e76\u7ed3\u675f\n                        yield f\"LLM API\u8c03\u7528\u5931\u8d25 (\u72b6\u6001\u7801: {resp.status})\"\n                        return\n                    \n # ======\u5904\u7406\u6d41\u5f0f\u54cd\u5e94==========\n'''\n\u4ee3\u7801\u5c42\u7ea7 |             \u4ee3\u7801\u884c                                               |  \u4f5c\u7528        |   \u89e3\u91ca\n\u7b2c1\u5c42   |async for chunk in resp.content.iter_chunked(1024):              | \u8bfb\u53d6\u6570\u636e\u5757    | \u6bcf\u6b21\u8bfb\u53d61024\u5b57\u8282\u7684\u6570\u636e\n\u7b2c2\u5c42   | if not chunk: break                                             | \u68c0\u67e5\u6570\u636e\u5757    | \u5982\u679c\u6570\u636e\u5757\u4e3a\u7a7a\uff0c\u505c\u6b62\u5faa\u73af\n\u7b2c3\u5c42   | try:                                                            | \u5c1d\u8bd5\u89e3\u7801      | \u5f00\u59cb\u5c1d\u8bd5\u5904\u7406\u6570\u636e\n\u7b2c4\u5c42   | data = chunk.decode('utf-8')                                    | \u89e3\u7801\u6570\u636e      | \u628a\u5b57\u8282\u6570\u636e\u8f6c\u6210\u5b57\u7b26\u4e32\n\u7b2c4\u5c42   | lines = data.split('\\n')                                        | \u5206\u5272\u6210\u884c      | \u6309\u6362\u884c\u7b26\u5206\u5272\n\u7b2c5\u5c42   | for line in lines:                                              | \u904d\u5386\u6bcf\u4e00\u884c    | \u5904\u7406\u6bcf\u4e00\u884c\u6570\u636e\n\u7b2c6\u5c42   | line = line.strip()                                             | \u53bb\u9664\u7a7a\u683c      | \u53bb\u6389\u5f00\u5934\u7ed3\u5c3e\u7684\u7a7a\u683c\n\u7b2c7\u5c42   | if line.startswith('data: '):                                   | \u68c0\u67e5\u6570\u636e\u884c     | \u53ea\u5904\u7406\u4ee5\"data: \"\u5f00\u5934\u7684\u884c\n\u7b2c8\u5c42   | data_str = line&#91;6:]                                             | \u63d0\u53d6\u6570\u636e      | \u53bb\u6389\u524d6\u4e2a\u5b57\u7b26(\"data: \")\n\u7b2c9\u5c42   | if data_str == '&#91;DONE]': return                                 | \u68c0\u67e5\u7ed3\u675f\u6807\u5fd7   | \u5982\u679c\u662f\"&#91;DONE]\"\uff0c\u7ed3\u675f\u65b9\u6cd5\n\u7b2c10\u5c42  | try:                                                            | \u5c1d\u8bd5\u89e3\u6790JSON  | \u5f00\u59cb\u89e3\u6790JSON\u6570\u636e\n\u7b2c11\u5c42  | import json                                                     | \u5bfc\u5165json\u6a21\u5757  | \u7528\u4e8e\u89e3\u6790JSON\n\u7b2c12\u5c42  | data = json.loads(data_str)                                     | \u89e3\u6790JSON     | \u628a\u5b57\u7b26\u4e32\u8f6c\u6210JSON\u5bf9\u8c61\n\u7b2c13\u5c42  | if 'choices' in data and len(data&#91;'choices']) &gt; 0:              | \u68c0\u67e5choices  | \u786e\u4fdd\u6709choices\u5b57\u6bb5\u4e14\u4e0d\u4e3a\u7a7a\n\u7b2c14\u5c42  | delta = data&#91;'choices']&#91;0].get('delta', {})                     | \u83b7\u53d6delta    | \u83b7\u53d6\u7b2c\u4e00\u4e2achoice\u7684delta\u90e8\u5206\n\u7b2c15\u5c42  | if 'content' in delta:                                          | \u68c0\u67e5\u662f\u5426\u6709\u5185\u5bb9 | delta\u4e2d\u662f\u5426\u6709content\u5b57\u6bb5\n\u7b2c16\u5c42  | import base64                                                   | \u5bfc\u5165base64\u6a21\u5757| \u7528\u4e8ebase64\u7f16\u7801\n\u7b2c17\u5c42  | content = delta&#91;'content']                                      | \u83b7\u53d6\u5185\u5bb9      | \u83b7\u53d6AI\u8fd4\u56de\u7684\u6587\u672c\u5185\u5bb9\n\u7b2c18\u5c42  | b64 = base64.b64encode(content.encode('utf-8')).decode('ascii') | base64\u7f16\u7801   | \u628a\u5185\u5bb9\u8f6c\u6210base64\u683c\u5f0f\n\u7b2c19\u5c42  | yield f\"data: {b64}\\n\\n\"                                        | \u8fd4\u56de\u6570\u636e      | \u4ee5\u7279\u5b9a\u683c\u5f0f\u8fd4\u56de\u7f16\u7801\u540e\u7684\u5185\u5bb9\n'''\n                    async for chunk in resp.content.iter_chunked(1024):\n                        if not chunk:\n                            break\n                        try:\n                            data = chunk.decode('utf-8')\n                            lines = data.split('\\n')\n                            for line in lines:\n                                line = line.strip()\n                                if line.startswith('data: '):\n                                    data_str = line&#91;6:]\n                                    if data_str == '&#91;DONE]':\n                                        return\n                                    try:\n                                        import json\n                                        data = json.loads(data_str)\n                                        if 'choices' in data and len(data&#91;'choices']) &gt; 0:\n                                            delta = data&#91;'choices']&#91;0].get('delta', {})\n                                            if 'content' in delta:\n                                                import base64\n                                                content = delta&#91;'content']\n                                                b64 = base64.b64encode(content.encode('utf-8')).decode('ascii')\n                                                yield f\"data: {b64}\\n\\n\"\n                                    #\u5f02\u5e38\u5904\u7406\n                                    except json.JSONDecodeError:\n                                        continue  #\u5982\u679cJSON\u89e3\u6790\u5931\u8d25\uff0c\u8df3\u8fc7\u8fd9\u884c\u7ee7\u7eed\n                        except UnicodeDecodeError:\n                            continue   #\u5982\u679c\u5b57\u7b26\u4e32\u89e3\u7801\u5931\u8d25\uff0c\u8df3\u8fc7\u8fd9\u4e2a\u6570\u636e\u5757\u7ee7\u7eed\n        #\u6574\u4f53\u5f02\u5e38\u5904\u7406                    \n        except Exception as e:   #\u5982\u679c\u4e0a\u9762\u6240\u6709\u4ee3\u7801\u51fa\u73b0\u4efb\u4f55\u9519\u8bef\n            logger.error(f\"\u6d41\u5f0f\u804a\u5929\u8c03\u7528\u5931\u8d25: {e}\")  #\u8bb0\u5f55\u9519\u8bef\u65e5\u5fd7\n            yield f\"data: \u6d41\u5f0f\u8c03\u7528\u51fa\u9519: {str(e)}\\n\\n\"  #\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\n\n# \u5168\u5c40LLM\u670d\u52a1\u5b9e\u4f8b\n_llm_service: Optional&#91;LLMService] = None\n\ndef get_llm_service() -&gt; LLMService:\n    \"\"\"\u83b7\u53d6\u5168\u5c40LLM\u670d\u52a1\u5b9e\u4f8b\"\"\"\n    global _llm_service\n    if _llm_service is None:\n        _llm_service = LLMService()\n    return _llm_service\n'''\n\u8fd9\u91cc\u7528\u4e86\u4e00\u4e2a\u8bbe\u8ba1\u6a21\u5f0f\u53eb\u201c\u5355\u4f8b\u6a21\u5f0f\u201d\uff1a\n\u6574\u4e2a\u7a0b\u5e8f\u53ea\u6709\u4e00\u4e2aLLMService\u5b9e\u4f8b\n\u5982\u679c\u8fd8\u6ca1\u6709\u521b\u5efa\uff0c\u5c31\u521b\u5efa\u4e00\u4e2a\n\u5982\u679c\u5df2\u7ecf\u521b\u5efa\u4e86\uff0c\u5c31\u76f4\u63a5\u7528\u90a3\u4e2a\n'''\n\n# ========Web API\u63a5\u53e3 ==========\n# \u521b\u5efa\u72ec\u7acb\u7684LLM\u670d\u52a1API\nllm_app = FastAPI(\n    title=\"LLM Service API\",\n    description=\"LLM\u670d\u52a1API\",\n    version=\"1.0.0\"\n)\n\n@llm_app.post(\"\/llm\/chat\")\nasync def llm_chat(request: Dict&#91;str, Any]):\n    \"\"\"LLM\u804a\u5929\u63a5\u53e3 - \u4e3a\u5176\u4ed6\u6a21\u5757\u63d0\u4f9bLLM\u8c03\u7528\u670d\u52a1\"\"\"\n    try:\n        prompt = request.get(\"prompt\", \"\")\n        temperature = request.get(\"temperature\", 0.7)\n        \n        if not prompt:\n            raise HTTPException(status_code=400, detail=\"prompt\u53c2\u6570\u4e0d\u80fd\u4e3a\u7a7a\")\n        \n        llm_service = get_llm_service()\n        response = await llm_service.get_response(prompt, temperature)\n        \n        return {\n            \"status\": \"success\",\n            \"response\": response,\n            \"temperature\": temperature\n        }\n        \n    except Exception as e:\n        logger.error(f\"LLM\u804a\u5929\u63a5\u53e3\u5f02\u5e38: {e}\")\n        raise HTTPException(status_code=500, detail=f\"LLM\u670d\u52a1\u5f02\u5e38: {str(e)}\")\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">start_server.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n\"\"\"\nNagaAgent \u670d\u52a1\u542f\u52a8\u811a\u672c\n\u670d\u52a1\u542f\u52a8\u811a\u672c\uff0c\u5c31\u50cf\u662f\u4e00\u4e2a\"\u603b\u5f00\u5173\"\uff0c\u8d1f\u8d23\u542f\u52a8\u6574\u4e2a\u7cfb\u7edf\u3002\n\u652f\u6301\u542f\u52a8API\u670d\u52a1\u5668\u548cLLM\u670d\u52a1\n\"\"\"\n\nimport asyncio\nimport sys\nimport os\nimport argparse  #\u547d\u4ee4\u884c\u53c2\u6570\u89e3\u6790\uff08\u8ba9\u7a0b\u5e8f\u53ef\u4ee5\u4ece\u547d\u4ee4\u884c\u63a5\u6536\u53c2\u6570\uff09\nfrom pathlib import Path\n\n# \u6dfb\u52a0\u9879\u76ee\u6839\u76ee\u5f55\u5230Python\u8def\u5f84\nproject_root = Path(__file__).parent.parent  #.parent.parent\uff1a\u7236\u76ee\u5f55\u7684\u7236\u76ee\u5f55\uff08\u9879\u76ee\u6839\u76ee\u5f55\uff09\nsys.path.insert(0, str(project_root)) #insert(0, ...)\uff1a\u63d2\u5165\u5230\u5217\u8868\u6700\u524d\u9762\uff08\u4f18\u5148\u7ea7\u6700\u9ad8\uff09\n\n#uvicorn\uff1a\u4e00\u4e2aWeb\u670d\u52a1\u5668\uff0c\u4e13\u95e8\u8fd0\u884cFastAPI\u5e94\u7528\uff0c\u5c31\u50cfApache\u6216Nginx\uff0c\u4f46\u662f\u4e13\u95e8\u4e3aPython\u5f02\u6b65\u5e94\u7528\u8bbe\u8ba1\u7684\nfrom nagaagent_core.api import uvicorn\n\nasync def start_api_server():\n    \"\"\"\u542f\u52a8API\u670d\u52a1\u5668\"\"\"\n    #\u4eceapiserver.api_server\u6a21\u5757\u5bfc\u5165app\u5bf9\u8c61\uff0c\u8fd9\u4e2aapp\u5e94\u8be5\u662f\u4e00\u4e2aFastAPI\u5e94\u7528\u5b9e\u4f8b\n    from apiserver.api_server import app\n    \n    # \u4ece\u73af\u5883\u53d8\u91cf\u83b7\u53d6\u914d\u7f6e\uff0c\u56de\u9000\u5230config\n    #os.getenv(\"\u53d8\u91cf\u540d\", \"\u9ed8\u8ba4\u503c\")\uff1a\u4ece\u73af\u5883\u53d8\u91cf\u83b7\u53d6\u503c\n    host = os.getenv(\"API_SERVER_HOST\", \"127.0.0.1\")#\u5982\u679c\u73af\u5883\u53d8\u91cfAPI_SERVER_HOST\u5b58\u5728\uff0c\u5c31\u7528\u5b83\u7684\u503c\n    try:\n        from system.config import get_server_port #\u5c1d\u8bd5\uff1a\u4ecesystem.config\u5bfc\u5165get_server_port\u51fd\u6570\n        default_port = get_server_port(\"api_server\") #\u5982\u679c\u5bfc\u5165\u6210\u529f\uff1a\u8c03\u7528get_server_port(\"api_server\")\u83b7\u53d6\u7aef\u53e3\n    except ImportError:  \n        default_port = 8000    #\u5982\u679c\u5bfc\u5165\u5931\u8d25\uff08except ImportError\uff09\uff1a\u7528\u9ed8\u8ba4\u7aef\u53e38000\n    #\u4ece\u73af\u5883\u53d8\u91cfAPI_SERVER_PORT\u83b7\u53d6\u7aef\u53e3\uff0c\u5982\u679c\u4e0d\u5b58\u5728\uff0c\u7528\u4e0a\u9762\u5f97\u5230\u7684default_port\uff0cint(...)\uff1a\u628a\u5b57\u7b26\u4e32\u8f6c\u6210\u6574\u6570\n    port = int(os.getenv(\"API_SERVER_PORT\", str(default_port))) \n    #\u83b7\u53d6\u73af\u5883\u53d8\u91cfAPI_SERVER_RELOAD\uff0c\u9ed8\u8ba4\u503c\u662f\u5b57\u7b26\u4e32\"False\"\uff0c.lower()\uff1a\u8f6c\u6210\u5c0f\u5199\uff08\u6bd4\u5982\"False\"\u2192\"false\"\uff09\uff0c== \"true\"\uff1a\u5224\u65ad\u662f\u5426\u7b49\u4e8e\"true\"\n    #\u7ed3\u679c\u662f\u5e03\u5c14\u503c\uff1aTrue\u6216False\n    reload = os.getenv(\"API_SERVER_RELOAD\", \"False\").lower() == \"true\"\n    \n    print(f\"\u542f\u52a8NagaAgent API\u670d\u52a1\u5668...\")\n    print(f\"\u5730\u5740: http:\/\/{host}:{port}\")\n    print(f\"\u6587\u6863: http:\/\/{host}:{port}\/docs\")\n    print(f\"\u81ea\u52a8\u91cd\u8f7d: {'\u5f00\u542f' if reload else '\u5173\u95ed'}\")\n    '''\n    \u8fd9\u91cc\u7528\u4e86f-string\u683c\u5f0f\u5316\uff1a\n      f\"\u5730\u5740: http:\/\/{host}:{port}\"\uff1a\u628ahost\u548cport\u53d8\u91cf\u7684\u503c\u63d2\u5165\u5230\u5b57\u7b26\u4e32\u4e2d\n      {'\u5f00\u542f' if reload else '\u5173\u95ed'}\uff1a\u4e09\u5143\u8868\u8fbe\u5f0f\n         \u5982\u679creload\u4e3aTrue\uff0c\u663e\u793a\"\u5f00\u542f\"\n         \u5982\u679creload\u4e3aFalse\uff0c\u663e\u793a\"\u5173\u95ed\"\n    '''\n    \n    # \u542f\u52a8\u670d\u52a1\u5668\n    uvicorn.run(\n        \"apiserver.api_server:app\",\n        host=host,\n        port=port,\n        reload=reload,   #\u662f\u5426\u5f00\u542f\u81ea\u52a8\u91cd\u8f7d\uff08\u4fee\u6539\u4ee3\u7801\u540e\u81ea\u52a8\u91cd\u542f\uff09\n        log_level=\"info\",\n        ws_ping_interval=None,\n        ws_ping_timeout=None\n    )\n\nasync def start_llm_service():\n    \"\"\"\u542f\u52a8LLM\u670d\u52a1\"\"\"\n    from apiserver.llm_service import llm_app\n    \n    # \u4ece\u73af\u5883\u53d8\u91cf\u83b7\u53d6\u914d\u7f6e\uff0c\u56de\u9000\u5230config\n    host = os.getenv(\"LLM_SERVICE_HOST\", \"127.0.0.1\")\n    try:\n        from system.config import get_server_port\n        #\u8fd9\u91cc\u4f20\u7684\u53c2\u6570\u662f\"agent_server\"\uff0c\u4e0d\u662f\"llm_service\",\u8fd9\u662f\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u547d\u540d\n        default_port = get_server_port(\"agent_server\")\n    except ImportError:\n        default_port = 8001\n    port = int(os.getenv(\"LLM_SERVICE_PORT\", str(default_port)))\n    reload = os.getenv(\"LLM_SERVICE_RELOAD\", \"False\").lower() == \"true\"\n    \n    print(f\"\u542f\u52a8LLM\u670d\u52a1...\")\n    print(f\"\u5730\u5740: http:\/\/{host}:{port}\")\n    print(f\"\u6587\u6863: http:\/\/{host}:{port}\/docs\")\n    print(f\"\u81ea\u52a8\u91cd\u8f7d: {'\u5f00\u542f' if reload else '\u5173\u95ed'}\")\n    \n    # \u542f\u52a8\u670d\u52a1\u5668\n    uvicorn.run(\n        \"apiserver.llm_service:llm_app\",\n        host=host,\n        port=port,\n        reload=reload,\n        log_level=\"info\",\n        ws_ping_interval=None,\n        ws_ping_timeout=None\n    )\n\nasync def main():\n    \"\"\"\u4e3b\u51fd\u6570\"\"\"\n    #\u521b\u5efa\u53c2\u6570\u89e3\u6790\u5668\n    parser = argparse.ArgumentParser(description=\"NagaAgent \u670d\u52a1\u542f\u52a8\u5668\")\n    parser.add_argument(\"service\", choices=&#91;\"api\", \"llm\", \"both\"], \n                       help=\"\u8981\u542f\u52a8\u7684\u670d\u52a1: api(API\u670d\u52a1\u5668), llm(LLM\u670d\u52a1), both(\u4e24\u4e2a\u90fd\u542f\u52a8)\")\n    \n    #\u89e3\u6790\u53c2\u6570\n    args = parser.parse_args()\n    \n    #\u6839\u636e\u53c2\u6570\u6267\u884c\u4e0d\u540c\u7684\u5206\u652f\n    #\u542f\u52a8API\u670d\u52a1\u5668\n    if args.service == \"api\":\n        await start_api_server()\n    #\u542f\u52a8LLM\u670d\u52a1\n    elif args.service == \"llm\":\n        await start_llm_service()\n    #\u542f\u52a8\u4e24\u4e2a\u670d\u52a1\n    elif args.service == \"both\":\n        print(\"\u542f\u52a8\u6240\u6709\u670d\u52a1...\")\n        print(\"\u6ce8\u610f: \u540c\u65f6\u542f\u52a8\u591a\u4e2a\u670d\u52a1\u9700\u8981\u4e0d\u540c\u7684\u7aef\u53e3\u914d\u7f6e\")\n        try:\n            from system.config import get_server_port\n            api_port = get_server_port(\"api_server\")\n            agent_port = get_server_port(\"agent_server\")\n            print(f\"API\u670d\u52a1\u5668: http:\/\/127.0.0.1:{api_port}\")\n            print(f\"LLM\u670d\u52a1: http:\/\/127.0.0.1:{agent_port}\")\n        except ImportError:\n            print(\"API\u670d\u52a1\u5668: http:\/\/127.0.0.1:8000\")\n            print(\"LLM\u670d\u52a1: http:\/\/127.0.0.1:8001\")\n        \n        # \u8fd9\u91cc\u53ef\u4ee5\u5b9e\u73b0\u540c\u65f6\u542f\u52a8\u591a\u4e2a\u670d\u52a1\u7684\u903b\u8f91\n        # \u76ee\u524d\u5148\u542f\u52a8API\u670d\u52a1\u5668\n        await start_api_server()\n\nif __name__ == \"__main__\":\n    try:\n        asyncio.run(main())\n    except KeyboardInterrupt: #\u6355\u83b7\u952e\u76d8\u4e2d\u65ad\uff08\u6bd4\u5982\u6309Ctrl+C\uff09\n        print(\"\\n\u6536\u5230\u505c\u6b62\u4fe1\u53f7\uff0c\u6b63\u5728\u5173\u95ed\u670d\u52a1...\")\n    except Exception as e:\n        print(f\"\u542f\u52a8\u5931\u8d25: {e}\")\n        sys.exit(1) \n        \n# ========\u6574\u4e2a\u6d41\u7a0b\u603b\u7ed3=======\n'''\n\u7528\u6237\u8fd0\u884c\u811a\u672c \u2192 \u89e3\u6790\u547d\u4ee4\u884c\u53c2\u6570 \u2192 \u6839\u636e\u53c2\u6570\u9009\u62e9\u542f\u52a8\u7684\u670d\u52a1\n       \u2193\n    api\u53c2\u6570 \u2192 \u542f\u52a8API\u670d\u52a1\u5668\n       \u2193\n    llm\u53c2\u6570 \u2192 \u542f\u52a8LLM\u670d\u52a1  \n       \u2193\n   both\u53c2\u6570 \u2192 \u663e\u793a\u4fe1\u606f\uff0c\u4f46\u53ea\u542f\u52a8API\u670d\u52a1\u5668\uff08\u6709bug\uff09\n'''\n\n# =======\u4e3a\u4ec0\u4e48\u5728\u51fd\u6570\u5185\u90e8\u5bfc\u5165\u6a21\u5757\uff1f=======\n#1. \u907f\u514d\u5faa\u73af\u5bfc\u5165\n'''\n\u60f3\u8c61\u4e00\u4e0b\u8fd9\u6837\u7684\u573a\u666f\uff1a\n \u6587\u4ef6A\u9700\u8981\u5bfc\u5165\u6587\u4ef6B\u7684\u67d0\u4e2a\u4e1c\u897f\n \u6587\u4ef6B\u4e5f\u9700\u8981\u5bfc\u5165\u6587\u4ef6A\u7684\u67d0\u4e2a\u4e1c\u897f\n \u8fd9\u6837\u5c31\u4f1a\u5f62\u6210\u4e00\u4e2a\"\u6b7b\u5faa\u73af\"\uff0cPython\u4e0d\u77e5\u9053\u5148\u52a0\u8f7d\u54ea\u4e2a\n \n\u4f8b\u5b50\uff1a\n# \u6587\u4ef6A.py\nimport B  # \u5bfc\u5165B\ndef func_a():\n    return \"A\"\n\n# \u6587\u4ef6B.py  \nimport A  # \u5bfc\u5165A\ndef func_b():\n    return \"B\"\n    \n\u8fd9\u6837\u4e24\u4e2a\u6587\u4ef6\u4e92\u76f8\u5bfc\u5165\uff0cPython\u4f1a\u62a5\u9519\u3002\n\n\u89e3\u51b3\u65b9\u6cd5\uff1a\u5728\u51fd\u6570\u5185\u90e8\u5bfc\u5165\n# \u6587\u4ef6B.py\ndef func_b():\n    from A import func_a  # \u5728\u51fd\u6570\u5185\u90e8\u5bfc\u5165\n    return \"B\"\n'''\n#2. \u5ef6\u8fdf\u52a0\u8f7d\uff0c\u63d0\u9ad8\u542f\u52a8\u901f\u5ea6\n'''\n\u5bf9\u6bd4\u4e00\u4e0b\u4e24\u79cd\u65b9\u5f0f\uff1a\n\u65b9\u5f0f\u4e00\uff1a\u5728\u9876\u90e8\u5168\u90e8\u5bfc\u5165\nimport heavy_module1  # \u8fd9\u4e2a\u6a21\u5757\u5f88\u5927\uff0c\u52a0\u8f7d\u89815\u79d2\nimport heavy_module2  # \u8fd9\u4e2a\u6a21\u5757\u4e5f\u5f88\u5927\uff0c\u52a0\u8f7d\u89815\u79d2\nimport heavy_module3  # \u8fd9\u4e2a\u6a21\u5757\u4e5f\u5f88\u5927\uff0c\u52a0\u8f7d\u89815\u79d2\n\ndef do_something():\n    # \u5b9e\u9645\u53ea\u7528\u4e86heavy_module1\n    return heavy_module1.func()\n    \n\u65b9\u5f0f\u4e8c\uff1a\u5728\u51fd\u6570\u5185\u90e8\u6309\u9700\u5bfc\u5165\ndef do_something():\n    import heavy_module1  # \u53ea\u6709\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u65f6\u624d\u52a0\u8f7d\n    return heavy_module1.func()\n    \n\u533a\u522b\uff1a\n\u65b9\u5f0f\u4e00\uff1a\u7a0b\u5e8f\u4e00\u542f\u52a8\u5c31\u8981\u52a0\u8f7d\u6240\u6709\u6a21\u5757\uff0815\u79d2\uff09\n\u65b9\u5f0f\u4e8c\uff1a\u53ea\u6709\u8c03\u7528\u51fd\u6570\u65f6\u624d\u52a0\u8f7d\u9700\u8981\u7684\u6a21\u5757\uff085\u79d2\uff09\n'''\n#3. \u6761\u4ef6\u5bfc\u5165\uff08\u6839\u636e\u73af\u5883\u9009\u62e9\u4e0d\u540c\u7684\u6a21\u5757\uff09\n'''\ndef process_image():\n    # \u6839\u636e\u64cd\u4f5c\u7cfb\u7edf\u9009\u62e9\u4e0d\u540c\u7684\u56fe\u50cf\u5904\u7406\u5e93\n    import platform\n    system = platform.system()\n    \n    if system == \"Windows\":\n        import windows_image_lib as image_lib\n    elif system == \"Linux\":\n        import linux_image_lib as image_lib\n    elif system == \"Darwin\":  # macOS\n        import mac_image_lib as image_lib\n    else:\n        raise Exception(\"\u4e0d\u652f\u6301\u7684\u64cd\u4f5c\u7cfb\u7edf\")\n    \n    return image_lib.process()\n'''\n#4. \u907f\u514d\u4e0d\u5fc5\u8981\u7684\u4f9d\u8d56\n'''\n\u5047\u8bbe\u4f60\u7684\u7a0b\u5e8f\u6709\u591a\u4e2a\u529f\u80fd\uff0c\u4f46\u4e0d\u662f\u6bcf\u4e2a\u7528\u6237\u90fd\u9700\u8981\u6240\u6709\u529f\u80fd\uff1a\ndef export_to_excel():\n    # \u53ea\u6709\u5f53\u7528\u6237\u9700\u8981\u5bfc\u51faExcel\u65f6\u624d\u5bfc\u5165pandas\n    import pandas as pd\n    # ... \u5bfc\u51fa\u4ee3\u7801\n\ndef export_to_pdf():\n    # \u53ea\u6709\u5f53\u7528\u6237\u9700\u8981\u5bfc\u51faPDF\u65f6\u624d\u5bfc\u5165reportlab\n    from reportlab.lib.pagesizes import letter\n    # ... \u5bfc\u51fa\u4ee3\u7801\n'''\n#\u5177\u4f53\u5230\u8fd9\u4e2a\u4ee3\u7801\u7684\u5206\u6790\n'''\n\u5728\u4ee3\u7801\u4e2d\uff1a\nasync def start_api_server():\n    \"\"\"\u542f\u52a8API\u670d\u52a1\u5668\"\"\"\n    from apiserver.api_server import app  # \u2190 \u5728\u8fd9\u91cc\u5bfc\u5165\n\u4e3a\u4ec0\u4e48\u8fd9\u4e48\u505a\uff1f\n  1.\u5982\u679cstart_api_server()\u4e0d\u88ab\u8c03\u7528\uff0capiserver.api_server\u6a21\u5757\u5c31\u4e0d\u4f1a\u88ab\u52a0\u8f7d\n     \u8282\u7701\u5185\u5b58\n     \u52a0\u5feb\u7a0b\u5e8f\u542f\u52a8\n  2.\u907f\u514d\u53ef\u80fd\u7684\u5faa\u73af\u5bfc\u5165\n     apiserver.api_server\u53ef\u80fd\u53c8\u5bfc\u5165\u4e86\u5f53\u524d\u6a21\u5757\u7684\u67d0\u4e9b\u4e1c\u897f\n     \u5ef6\u8fdf\u5bfc\u5165\u53ef\u4ee5\u6253\u7834\u5faa\u73af\n'''\n#\u518d\u770b\u53e6\u4e00\u4e2a\u4f8b\u5b50\uff1a\n'''\nasync def stream_chat_with_context(self, messages: List&#91;Dict], temperature: float = 0.7):\n    try:\n        import aiohttp  # \u2190 \u5728\u8fd9\u91cc\u5bfc\u5165\n        timeout = aiohttp.ClientTimeout(total=180, connect=60, sock_read=120)\n        \n        # \u540e\u9762\u8fd8\u6709\n        import json  # \u2190 \u5728try\u5757\u91cc\u9762\u5bfc\u5165\n        import base64  # \u2190 \u5728try\u5757\u91cc\u9762\u5bfc\u5165\n\n\u4e3a\u4ec0\u4e48\u8fd9\u91cc\u4e5f\u8fd9\u4e48\u505a\uff1f\n  1.aiohttp\u53ef\u80fd\u4e0d\u662f\u6240\u6709\u7528\u6237\u90fd\u9700\u8981\u7684\n       \u53ea\u6709\u4f7f\u7528\u6d41\u5f0f\u804a\u5929\u529f\u80fd\u65f6\u624d\u9700\u8981\n       \u5982\u679c\u7528\u6237\u4ece\u4e0d\u4f7f\u7528\u8fd9\u4e2a\u529f\u80fd\uff0c\u5c31\u4e0d\u4f1a\u5b89\u88c5aiohttp\uff0c\u7a0b\u5e8f\u4e5f\u80fd\u6b63\u5e38\u8fd0\u884c\n  2.\u5f02\u5e38\u5904\u7406\u4e2d\u5bfc\u5165json\u548cbase64\n  try:\n      import json\n      data = json.loads(data_str)\n  except json.JSONDecodeError:\n    continue\n   \u8fd9\u5176\u5b9e\u662f\u4e00\u4e2a\u5c0f\u95ee\u9898\uff1ajson\u662fPython\u6807\u51c6\u5e93\uff0c\u5e94\u8be5\u5728\u6700\u4e0a\u9762\u5bfc\u5165\n   \u8fd9\u91cc\u53ef\u80fd\u662f\u4e3a\u4e86\u4ee3\u7801\u7ed3\u6784\u6e05\u6670\uff0c\u628a\u76f8\u5173\u7684\u5bfc\u5165\u653e\u5728\u4e00\u8d77\n'''<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">streaming_tool_extractor.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\n\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\n\u8d1f\u8d23\u5c06LLM\u6d41\u5f0f\u8f93\u51fa\u6309\u53e5\u5207\u5272\u5e76\u53d1\u9001\u7ed9\u8bed\u97f3\u96c6\u6210\uff08TTS\uff09\u3002\u4e0d\u518d\u68c0\u6d4b\u6216\u5904\u7406\u5de5\u5177\u8c03\u7528\u3002\n\"\"\"\n\nimport re\nimport json\nimport logging\nimport asyncio\nimport sys\nimport os\nfrom typing import Callable, Optional, Dict, Any, Union, List #\u7c7b\u578b\u63d0\u793a\uff0c\u5e2e\u52a9IDE\u548c\u5f00\u53d1\u8005\u7406\u89e3\u4ee3\u7801\u7c7b\u578b\n\n# \u6dfb\u52a0\u9879\u76ee\u6839\u76ee\u5f55\u5230Python\u8def\u5f84\nsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n#os.path.abspath(__file__)\uff1a\u8f6c\u4e3a\u7edd\u5bf9\u8def\u5f84,os.path.dirname(...)\uff1a\u83b7\u53d6\u7236\u76ee\u5f55\uff08\u7528\u4e24\u6b21\u5f97\u5230\u9879\u76ee\u6839\u76ee\u5f55\uff09,sys.path.insert(0, ...)\uff1a\u63d2\u5165\u5230Python\u641c\u7d22\u8def\u5f84\u7684\u6700\u524d\u9762\n\ntry:\n    from system.config import config, AI_NAME  # \u5bfc\u5165\u914d\u7f6e\u7cfb\u7edf\nexcept ImportError:\n    # \u5982\u679c\u76f4\u63a5\u5bfc\u5165\u5931\u8d25\uff0c\u5c1d\u8bd5\u4ece\u7236\u76ee\u5f55\u5bfc\u5165\n    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n    from system.config import config, AI_NAME\n\n# \u5de5\u5177\u8c03\u7528\u89e3\u6790\/\u6267\u884c\u5df2\u4e0d\u518d\u9700\u8981\n\nlogger = logging.getLogger(\"StreamingToolCallExtractor\")\n\nclass CallbackManager:\n    \"\"\"\u56de\u8c03\u51fd\u6570\u7ba1\u7406\u5668 - \u7edf\u4e00\u5904\u7406\u540c\u6b65\/\u5f02\u6b65\u56de\u8c03\"\"\"\n    \n    def __init__(self):   \n        self.callbacks = {}   #self.callbacks\uff1a\u5b58\u50a8\u56de\u8c03\u51fd\u6570\n        #self.callback_types\uff1a\u5b58\u50a8\u56de\u8c03\u51fd\u6570\u7684\u7c7b\u578b\uff08\u662f\u540c\u6b65\u8fd8\u662f\u5f02\u6b65\uff09\n        self.callback_types = {}  # \u7f13\u5b58\u56de\u8c03\u51fd\u6570\u7c7b\u578b\n    \n    def register_callback(self, name: str, callback: Optional&#91;Callable]): #name: str\uff1a\u56de\u8c03\u51fd\u6570\u7684\u540d\u5b57\uff0ccallback: Optional&#91;Callable]\uff1a\u56de\u8c03\u51fd\u6570\u672c\u8eab\uff0c\u53ef\u4ee5\u662fNone\n        \"\"\"\u6ce8\u518c\u56de\u8c03\u51fd\u6570\"\"\"\n        self.callbacks&#91;name] = callback  #\u628a\u56de\u8c03\u51fd\u6570\u5b58\u5230\u5b57\u5178\u91cc\n        if callback: #\u5982\u679c\u56de\u8c03\u51fd\u6570\u4e0d\u662fNone\n            # \u7f13\u5b58\u51fd\u6570\u7c7b\u578b\uff0c\u907f\u514d\u91cd\u590d\u68c0\u67e5\n            self.callback_types&#91;name] = asyncio.iscoroutinefunction(callback) #\u5982\u679c\u56de\u8c03\u51fd\u6570\u4e0d\u662fNone\n        else:\n            self.callback_types&#91;name] = False\n    \n    async def call_callback(self, name: str, *args, **kwargs):\n        #*args\uff1a\u53ef\u53d8\u4f4d\u7f6e\u53c2\u6570\uff08\u53ef\u4ee5\u4f20\u4efb\u610f\u6570\u91cf\u7684\u4f4d\u7f6e\u53c2\u6570\uff09\n        #**kwargs\uff1a\u53ef\u53d8\u5173\u952e\u5b57\u53c2\u6570\uff08\u53ef\u4ee5\u4f20\u4efb\u610f\u6570\u91cf\u7684\u5173\u952e\u5b57\u53c2\u6570\uff09\n        \"\"\"\u7edf\u4e00\u8c03\u7528\u56de\u8c03\u51fd\u6570\"\"\"\n        callback = self.callbacks.get(name)\n        if not callback:\n            return None\n            \n        try:   #\u4ece\u7f13\u5b58\u4e2d\u83b7\u53d6\u8fd9\u4e2a\u51fd\u6570\u662f\u5426\u662f\u5f02\u6b65\u7684\uff0c\u5982\u679c\u662f\u5f02\u6b65\u7684\uff08\u8fd4\u56deTrue\uff09\uff0c\u5c31\u7528await\u8c03\u7528\uff0c\u5982\u679c\u662f\u540c\u6b65\u7684\uff08\u8fd4\u56deFalse\uff09\uff0c\u5c31\u76f4\u63a5\u8c03\u7528\n            if self.callback_types.get(name, False):\n                # \u5f02\u6b65\u56de\u8c03\n                return await callback(*args, **kwargs)\n            else:\n                # \u540c\u6b65\u56de\u8c03\n                return callback(*args, **kwargs)\n        except Exception as e:\n            logger.error(f\"\u56de\u8c03\u51fd\u6570 {name} \u6267\u884c\u9519\u8bef: {e}\")\n            return None\n        #\u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u533a\u5206\uff1f,\u5f02\u6b65\u51fd\u6570\u5fc5\u987b\u7528await\u8c03\u7528\uff0c\u5426\u5219\u4e0d\u4f1a\u6267\u884c,\u540c\u6b65\u51fd\u6570\u4e0d\u80fd\u7528await\u8c03\u7528\uff0c\u5426\u5219\u4f1a\u62a5\u9519,\u8fd9\u4e2a\u7ba1\u7406\u5668\u7edf\u4e00\u5904\u7406\u4e86\u8fd9\u4e24\u79cd\u60c5\u51b5\n\nclass StreamingToolCallExtractor:\n    \"\"\"\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668 - \u5b9e\u65f6\u6309\u53e5\u5207\u5272\u5e76\u53d1\u9001\u7ed9TTS\uff0c\u652f\u6301\u5de5\u5177\u8c03\u7528\u5904\u7406\"\"\"\n    \n    def __init__(self, mcp_manager=None):\n        self.mcp_manager = mcp_manager      #MCP\u7ba1\u7406\u5668\uff08\u662f\u5176\u4ed6\u6a21\u5757\u7684\u5f15\u7528\uff09\n        self.text_buffer = \"\"  # \u666e\u901a\u6587\u672c\u7f13\u51b2\u533a,\uff08\u4e34\u65f6\u5b58\u653e\u6b63\u5728\u5904\u7406\u7684\u6587\u672c\uff09\n        self.complete_text = \"\"  # \u5b8c\u6574\u6587\u672c\u5185\u5bb9,\uff08\u5b58\u653e\u6240\u6709\u5904\u7406\u8fc7\u7684\u6587\u672c\uff09\n        self.sentence_endings = r\"&#91;\u3002\uff1f\uff01\uff1b\\.\\?\\!\\;]\"  # \u65ad\u53e5\u6807\u70b9\n        \n        # \u4f7f\u7528\u56de\u8c03\u7ba1\u7406\u5668\n        self.callback_manager = CallbackManager() #\u521b\u5efa\u56de\u8c03\u7ba1\u7406\u5668\u5b9e\u4f8b\n        \n        # \u8bed\u97f3\u96c6\u6210\uff08\u53ef\u9009\uff09\uff08\u521d\u59cb\u4e3a\u7a7a\uff09\n        self.voice_integration = None  \n        \n        # \u5de5\u5177\u8c03\u7528\u529f\u80fd\u5df2\u79fb\u9664\n        self.tool_calls_queue = None\n    \n    #\u8bbe\u7f6e\u56de\u8c03\u51fd\u6570   \n    def set_callbacks(self, \n                     on_text_chunk: Optional&#91;Callable] = None,\n                     voice_integration=None):\n        \"\"\"\u8bbe\u7f6e\u56de\u8c03\u51fd\u6570\"\"\"\n        # \u6ce8\u518c\u56de\u8c03\u51fd\u6570\uff08\u4ec5\u6587\u672c\u5757\uff09\n        self.callback_manager.register_callback(\"text_chunk\", on_text_chunk) #\u6ce8\u518c\u4e00\u4e2a\u540d\u4e3a\"text_chunk\"\u7684\u56de\u8c03\u51fd\u6570\n        self.voice_integration = voice_integration #\u8bbe\u7f6e\u8bed\u97f3\u96c6\u6210\u63a5\u53e3\n    \n    async def process_text_chunk(self, text_chunk: str):\n        \"\"\"\n        \u5904\u7406\u6587\u672c\u5757\uff0c\u5b9e\u65f6\u6309\u53e5\u5207\u5272\u5e76\u53d1\u9001\u7ed9\u8bed\u97f3\u96c6\u6210\n        \n        \u5904\u7406\u6d41\u7a0b\uff1a\n        1. \u7d2f\u79ef\u5b8c\u6574\u6587\u672c\uff08\u7528\u4e8e\u6700\u7ec8\u4fdd\u5b58\uff09\n        2. \u9010\u5b57\u7b26\u68c0\u67e5\u53e5\u5b50\u7ed3\u675f\u7b26\n        3. \u9047\u5230\u7ed3\u675f\u7b26\u65f6\u7acb\u5373\u5207\u5272\u5e76\u53d1\u9001\u5b8c\u6574\u53e5\u5b50\u5230TTS\n        4. \u4fdd\u7559\u672a\u5b8c\u6210\u7684\u53e5\u5b50\u90e8\u5206\u7ee7\u7eed\u7d2f\u79ef\n        \"\"\"\n        if not text_chunk:\n            return None\n        \n        \n        # \u8c03\u7528\u6587\u672c\u5757\u56de\u8c03\uff0c\u5c06\u6587\u672c\u53d1\u9001\u5230\u524d\u7aef\n        results = &#91;]  #\u521b\u5efa\u4e00\u4e2a\u7a7a\u5217\u8868results\u5b58\u653e\u7ed3\u679c\n        #\u8c03\u7528\"text_chunk\"\u56de\u8c03\u51fd\u6570\uff0c\u4f20\u5165\u4e24\u4e2a\u53c2\u6570\uff1atext_chunk\u548c\u5b57\u7b26\u4e32\"chunk\"\n        result = await self.callback_manager.call_callback(\"text_chunk\", text_chunk, \"chunk\")  \n        if result: #\u5982\u679c\u6709\u8fd4\u56de\u503c\uff0c\u6dfb\u52a0\u5230results\u5217\u8868\n            results.append(result)\n\n        # \u7d2f\u79ef\u5b8c\u6574\u6587\u672c\uff08\u7528\u4e8e\u6700\u7ec8\u4fdd\u5b58\u5230\u6570\u636e\u5e93\uff09\n        self.complete_text += text_chunk\n        #\u628a\u6536\u5230\u7684\u6587\u672c\u5757\u6dfb\u52a0\u5230\u5b8c\u6574\u6587\u672c\u4e2d,\u5c31\u50cf\u628a\u6536\u5230\u7684\u4fe1\u4ef6\u653e\u5230\u6587\u4ef6\u5939\u91cc\u4fdd\u5b58\n     \n# =====\u8fd9\u662f\u6700\u590d\u6742\u7684\u90e8\u5206\uff0c\u6211\u4eec\u7528\u7b80\u5355\u7684\u65b9\u5f0f\u89e3\u91ca=====\n#\u903b\u8f91\u6d41\u7a0b\uff1a\n'''\n\u6536\u5230\u6587\u672c\u5757 \u2192 \u904d\u5386\u6bcf\u4e2a\u5b57\u7b26 \u2192 \u6dfb\u52a0\u5230\u7f13\u51b2\u533a \u2192 \u68c0\u67e5\u662f\u5426\u662f\u7ed3\u675f\u7b26\n        \u2193\n   \u5982\u679c\u662f\u7ed3\u675f\u7b26 \u2192 \u5207\u5272\u53e5\u5b50 \u2192 \u53d1\u9001\u5b8c\u6574\u53e5\u5b50\u7ed9TTS \u2192 \u4fdd\u7559\u5269\u4f59\u90e8\u5206\n        \u2193\n   \u8fd4\u56de\u5904\u7406\u7ed3\u679c\n   \n\u8be6\u7ec6\u5206\u89e3\uff1a\n  1.for char in text_chunk:\uff1a\u904d\u5386\u6587\u672c\u5757\u4e2d\u7684\u6bcf\u4e2a\u5b57\u7b26\n  2.self.text_buffer += char\uff1a\u628a\u5b57\u7b26\u6dfb\u52a0\u5230\u7f13\u51b2\u533a\n  3.if re.search(self.sentence_endings, char):\uff1a\u68c0\u67e5\u8fd9\u4e2a\u5b57\u7b26\u662f\u4e0d\u662f\u53e5\u5b50\u7ed3\u675f\u7b26\n       \u4f7f\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d\uff1a&#91;\u3002\uff1f\uff01\uff1b\\.\\?\\!\\;]\n       \u5305\u62ec\u4e2d\u6587\u548c\u82f1\u6587\u7684\u53e5\u53f7\u3001\u95ee\u53f7\u3001\u611f\u53f9\u53f7\u3001\u5206\u53f7\n  4.\u5982\u679c\u9047\u5230\u7ed3\u675f\u7b26\uff1asentences = re.split(self.sentence_endings, self.text_buffer)\n       \u7528\u7ed3\u675f\u7b26\u5206\u5272\u6574\u4e2a\u7f13\u51b2\u533a\n       \u6bd4\u5982\uff1a\"\u4f60\u597d\u3002\u4eca\u5929\u5929\u6c14\" \u2192 &#91;\"\u4f60\u597d\", \"\u4eca\u5929\u5929\u6c14\"]\n  5.if len(sentences) &gt; 1:\uff1a\u5982\u679c\u5206\u5272\u51fa\u591a\u4e2a\u90e8\u5206\n       complete_sentence = sentences&#91;0] + char\n       \u7b2c\u4e00\u4e2a\u90e8\u5206 + \u7ed3\u675f\u7b26 = \u5b8c\u6574\u53e5\u5b50\n       \"\u4f60\u597d\" + \"\u3002\" = \"\u4f60\u597d\u3002\"\n 6.if complete_sentence.strip():\uff1a\u5982\u679c\u53e5\u5b50\u4e0d\u662f\u7a7a\u7684   \n       self._send_to_voice_integration(complete_sentence)\n       \u4fdd\u7559\u7b2c\u4e00\u4e2a\u5b8c\u6574\u53e5\u5b50\u4e4b\u540e\u7684\u90e8\u5206\n       \u6bd4\u5982\uff1a\"\u4eca\u5929\u5929\u6c14\"\u7559\u5728\u7f13\u51b2\u533a\u7b49\u5f85\u66f4\u591a\u5b57\u7b26\n'''\n        # \u5b9e\u65f6\u6309\u53e5\u5207\u5272\u5e76\u53d1\u9001\u5230TTS\n        for char in text_chunk:\n            self.text_buffer += char\n            # \u68c0\u67e5\u662f\u5426\u9047\u5230\u53e5\u5b50\u7ed3\u675f\u7b26\uff08\u3002\uff1f\uff01\uff1b\u7b49\uff09\n            if re.search(self.sentence_endings, char):\n                # \u7acb\u5373\u5207\u5272\u5e76\u53d1\u9001\u5b8c\u6574\u53e5\u5b50\u5230TTS\n                sentences = re.split(self.sentence_endings, self.text_buffer)\n                if len(sentences) &gt; 1:\n                    complete_sentence = sentences&#91;0] + char\n                    if complete_sentence.strip():\n                        # \u7acb\u5373\u53d1\u9001\u5230\u8bed\u97f3\u96c6\u6210\u8fdb\u884cTTS\u5408\u6210\uff08\u4e0d\u963b\u585e\u6587\u672c\u6d41\uff09\n                        self._send_to_voice_integration(complete_sentence)\n                    # \u4fdd\u7559\u672a\u5b8c\u6210\u7684\u53e5\u5b50\u90e8\u5206\uff0c\u7ee7\u7eed\u7d2f\u79ef\n                    remaining_sentences = &#91;s for s in sentences&#91;1:] if s.strip()]\n                    self.text_buffer = \"\".join(remaining_sentences)\n        return results if results else None\n    \n    #\u5237\u65b0\u6587\u672c\u7f13\u51b2\u533a,\u5f53\u6d41\u5f0f\u4f20\u8f93\u7ed3\u675f\u65f6\uff0c\u53d1\u9001\u7f13\u51b2\u533a\u4e2d\u5269\u4f59\u7684\u6587\u672c\n    async def _flush_text_buffer(self):\n        \"\"\"\u5237\u65b0\u6587\u672c\u7f13\u51b2\u533a - \u5904\u7406\u6d41\u5f0f\u7ed3\u675f\u65f6\u7684\u5269\u4f59\u6587\u672c\"\"\"\n        if self.text_buffer:\n            # \u7acb\u5373\u53d1\u9001\u5269\u4f59\u7684\u672a\u5b8c\u6210\u53e5\u5b50\u5230\u8bed\u97f3\u96c6\u6210\uff08\u4e0d\u963b\u585e\uff09\n            self._send_to_voice_integration(self.text_buffer)\n            \n            self.text_buffer = \"\"\n            return None\n        return None\n    \n    #\u53d1\u9001\u5230\u8bed\u97f3\u96c6\u6210\n    def _send_to_voice_integration(self, text: str):\n        \"\"\"\u53d1\u9001\u6587\u672c\u5230\u8bed\u97f3\u96c6\u6210\uff08\u4e0d\u963b\u585e\u6587\u672c\u6d41\uff09\"\"\"\n        if self.voice_integration:\n            try:\n                # \u5728\u72ec\u7acb\u7ebf\u7a0b\u4e2d\u5904\u7406TTS\uff0c\u4e0d\u963b\u585e\u6587\u672c\u6d41\n                import threading  #\u5bfc\u5165\u7ebf\u7a0b\u6a21\u5757\n                threading.Thread(      #\u521b\u5efa\u5e76\u542f\u52a8\u4e00\u4e2a\u65b0\u7ebf\u7a0b\n                    target=self.voice_integration.receive_text_chunk,     #\u7ebf\u7a0b\u8981\u6267\u884c\u7684\u51fd\u6570\n                    args=(text,),       #\u4f20\u7ed9\u51fd\u6570\u7684\u53c2\u6570\n                    daemon=True         #\u8bbe\u7f6e\u4e3a\u5b88\u62a4\u7ebf\u7a0b\uff08\u4e3b\u7a0b\u5e8f\u9000\u51fa\u65f6\u81ea\u52a8\u7ed3\u675f\uff09\n                ).start()\n            except Exception as e:\n                logger.error(f\"\u53d1\u9001\u5230\u8bed\u97f3\u96c6\u6210\u5931\u8d25: {e}\")\n    #\u4e3a\u4ec0\u4e48\u7528\u7ebf\u7a0b\uff1fTTS\uff08\u6587\u672c\u8f6c\u8bed\u97f3\uff09\u53ef\u80fd\u9700\u8981\u8f83\u957f\u65f6\u95f4,\u5982\u679c\u7528\u4e3b\u7ebf\u7a0b\u6267\u884c\uff0c\u4f1a\u963b\u585e\u540e\u7eed\u6587\u672c\u7684\u5904\u7406,\u7528\u65b0\u7ebf\u7a0b\u6267\u884c\uff0c\u53ef\u4ee5\"\u8fb9\u8bf4\u8bdd\u8fb9\u63a5\u6536\u65b0\u6587\u672c\"\n    # \u5de5\u5177\u8c03\u7528\u76f8\u5173\u65b9\u6cd5\u5df2\u79fb\u9664\uff0c\u529f\u80fd\u5df2\u8fc1\u79fb\u5230background_analyzer\n    \n    #\u5b8c\u6210\u5904\u7406,\u7ed3\u675f\u5904\u7406\u6d41\u7a0b\uff0c\u6e05\u7406\u7f13\u51b2\u533a\n    async def finish_processing(self):\n        \"\"\"\u5b8c\u6210\u5904\u7406\uff0c\u6e05\u7406\u5269\u4f59\u5185\u5bb9\"\"\"\n        results = &#91;]\n        \n        # \u5904\u7406\u5269\u4f59\u7684\u6587\u672c\n        if self.text_buffer:\n            result = await self._flush_text_buffer()\n            if result:\n                results.append(result)\n        \n        return results if results else None\n    \n    def get_complete_text(self) -&gt; str:\n        \"\"\"\u83b7\u53d6\u5b8c\u6574\u6587\u672c\u5185\u5bb9\"\"\"\n        return self.complete_text\n    \n    def reset(self):\n        \"\"\"\u91cd\u7f6e\u63d0\u53d6\u5668\u72b6\u6001\"\"\"\n        self.text_buffer = \"\"\n        self.complete_text = \"\"\n    \n    async def process_streaming_response(self, llm_service, messages: List&#91;Dict], \n                                       temperature: float = 0.7, voice_integration=None):\n        '''\n        \u53c2\u65701\uff1allm_service - LLM\u670d\u52a1\u5b9e\u4f8b\n        \u53c2\u65702\uff1amessages - \u804a\u5929\u6d88\u606f\u5217\u8868\n        \u53c2\u65703\uff1atemperature - \u6e29\u5ea6\u53c2\u6570\uff08\u9ed8\u8ba40.7\uff09\n        \u53c2\u65704\uff1avoice_integration - \u8bed\u97f3\u96c6\u6210\u63a5\u53e3\n        '''\n        \"\"\"\u5904\u7406\u6d41\u5f0f\u54cd\u5e94\uff0c\u6574\u5408LLM\u8c03\u7528\u548cTTS\u5904\u7406,\uff08\u6838\u5fc3\u96c6\u6210\u65b9\u6cd5\uff09\"\"\"\n        if voice_integration:\n            self.voice_integration = voice_integration\n        \n        async for chunk in llm_service.stream_chat_with_context(messages, temperature):\n            if chunk.startswith(\"data: \"):\n                # \u89e3\u7801base64\u5185\u5bb9\n                try:\n                    import base64\n                    data_str = chunk&#91;6:].strip()  #\u53bb\u6389\u524d6\u4e2a\u5b57\u7b26\"data: \"\n                    if data_str == '&#91;DONE]':\n                        break   #\u5982\u679c\u662f\"&#91;DONE]\"\u8868\u793a\u6d41\u7ed3\u675f\n                    decoded = base64.b64decode(data_str).decode('utf-8')   #\u5426\u5219\u89e3\u7801base64\uff0c\u5904\u7406\u6587\u672c\n                    await self.process_text_chunk(decoded)\n                except Exception as e:\n                    logger.error(f\"\u5904\u7406\u6d41\u5f0f\u54cd\u5e94\u5757\u5931\u8d25: {e}\")\n                    continue\n            else:\n                # \u76f4\u63a5\u5904\u7406\u6587\u672c\u5185\u5bb9\n                await self.process_text_chunk(chunk)\n        \n        # \u5b8c\u6210\u5904\u7406\n        await self.finish_processing()\n        return self.get_complete_text()\n       '''\n       \u5f00\u59cb\u5904\u7406\u6d41\u5f0f\u54cd\u5e94\n            \u2193\n       \u904d\u5386\u6bcf\u4e2a\u6570\u636e\u5757\n            \u2193\n            \u2193---\u662fbase64\u683c\u5f0f---\u89e3\u7801---\u5904\u7406\u6587\u672c\n            \u2193\n            \u2193---\u662f\u666e\u901a\u6587\u672c---\u76f4\u63a5\u5904\u7406\u6587\u672c\n            \u2193\n       \u5207\u5272\u53e5\u5b50\uff0c\u53d1\u9001\u7ed9TTS\n            \u2193\n       \u7d2f\u79ef\u5230\u5b8c\u6574\u6587\u672c\n            \u2193\n       \u6d41\u7ed3\u675f\u2192\u6e05\u7406\u7f13\u51b2\u533a\u2192\u8fd4\u56de\u5b8c\u6574\u6587\u672c\n       '''\n# ======\u4e3a\u4ec0\u4e48\u6709\u5f02\u6b65\u51fd\u6570\u8fd8\u8981\u7528\u591a\u7ebf\u7a0b\uff1f=========\n#Python\u5e76\u53d1\u7f16\u7a0b\u4e2d\u7684\u4e00\u4e2a\u91cd\u8981\u8bdd\u9898\n#\u7b80\u5355\u56de\u7b54\uff1a\u5f02\u6b65\u548c\u591a\u7ebf\u7a0b\u89e3\u51b3\u4e0d\u540c\u7684\u95ee\u9898\uff0c\u6709\u65f6\u5019\u9700\u8981\u7ec4\u5408\u4f7f\u7528\u3002\n'''\n\u8be6\u7ec6\u5bf9\u6bd4\uff1a\n\u7279\u6027      |   \u5f02\u6b65 (asyncio)         | \u591a\u7ebf\u7a0b (threading)\n\u6838\u5fc3\u601d\u60f3   | \u5355\u7ebf\u7a0b\u5e76\u53d1\uff0c\u4efb\u52a1\u5207\u6362        | \u591a\u7ebf\u7a0b\u5e76\u884c\uff0c\u540c\u65f6\u8fd0\u884c\n\u9002\u5408\u573a\u666f   | I\/O\u5bc6\u96c6\u578b\u4efb\u52a1\uff08\u7f51\u7edc\u3001\u6587\u4ef6\uff09  | I\/O\u5bc6\u96c6\u578b\uff0c\u67d0\u4e9bCPU\u5bc6\u96c6\u578b\n\u8d44\u6e90\u6d88\u8017   | \u8f7b\u91cf\uff08\u4e00\u4e2a\u7ebf\u7a0b\uff09           | \u8f83\u91cd\uff08\u6bcf\u4e2a\u7ebf\u7a0b\u6709\u72ec\u7acb\u6808\uff09\n\u7f16\u7a0b\u96be\u5ea6   | \u4e2d\u7b49\uff08\u9700\u8981\u7406\u89e3async\/await\uff09| \u8f83\u9ad8\uff08\u9700\u8981\u5904\u7406\u7ebf\u7a0b\u5b89\u5168\uff09\nPython\u9650\u5236| \u53d7GIL\u5f71\u54cd\u8f83\u5c0f             | \u53d7GIL\u9650\u5236\uff08CPU\u5bc6\u96c6\u578b\u4e0d\u9ad8\u6548\uff09\n\n\u4e3a\u4ec0\u4e48\u5728\u8fd9\u4e2a\u4ee3\u7801\u4e2d\u8981\u540c\u65f6\u4f7f\u7528\uff1f\n\u770b\u8fd9\u4e2a\u4ee3\u7801\u7247\u6bb5\uff1a\ndef _send_to_voice_integration(self, text: str):\n    if self.voice_integration:\n        try:\n            # \u5728\u72ec\u7acb\u7ebf\u7a0b\u4e2d\u5904\u7406TTS\uff0c\u4e0d\u963b\u585e\u6587\u672c\u6d41\n            import threading\n            threading.Thread(\n                target=self.voice_integration.receive_text_chunk,\n                args=(text,),\n                daemon=True\n            ).start()\n        except Exception as e:\n            logger.error(f\"\u53d1\u9001\u5230\u8bed\u97f3\u96c6\u6210\u5931\u8d25: {e}\")\n \n\u53ef\u80fd\u7684\u539f\u56e0\uff1a   \n\u539f\u56e01\uff1aTTS\u5e93\u53ef\u80fd\u662f\u540c\u6b65\u7684,\uff08\u5f88\u591a\u8bed\u97f3\u5408\u6210\u5e93\u662f\u540c\u6b65\u7684\uff09  \n# \u5047\u8bbeTTS\u5e93\u662f\u8fd9\u6837\u7684\uff08\u4e0d\u652f\u6301\u5f02\u6b65\uff09\nclass \u540c\u6b65TTS\u5e93:\n    def receive_text_chunk(self, text):\n        # \u8fd9\u662f\u4e00\u4e2a\u540c\u6b65\u65b9\u6cd5\uff0c\u53ef\u80fd\u9700\u8981\u51e0\u79d2\u949f\n        time.sleep(3)  # \u6a21\u62df\u8017\u65f6\u64cd\u4f5c\n        print(f\"\u64ad\u653e: {text}\")  \n\u5982\u679c\u5728\u5f02\u6b65\u51fd\u6570\u4e2d\u76f4\u63a5\u8c03\u7528\u540c\u6b65\u7684TTS\uff1a    \nasync def process_text_chunk(self, text):\n    # \u5982\u679c\u76f4\u63a5\u8c03\u7528\u540c\u6b65TTS\n    self.voice_integration.receive_text_chunk(text)  # \u8fd9\u4f1a\u963b\u585e3\u79d2\uff01\n    # \u5728\u8fd93\u79d2\u5185\uff0c\u6574\u4e2a\u5f02\u6b65\u4e8b\u4ef6\u5faa\u73af\u90fd\u88ab\u963b\u585e\u4e86\n    \n\u539f\u56e02\uff1a\u907f\u514d\u963b\u585e\u4e8b\u4ef6\u5faa\u73af\n\u5f02\u6b65\u7f16\u7a0b\u6709\u4e00\u4e2a\u9ec4\u91d1\u6cd5\u5219\uff1a\u4e0d\u8981\u963b\u585e\u4e8b\u4ef6\u5faa\u73af    \n\\# \u4e0d\u597d\u7684\u505a\u6cd5\uff1a\u5728\u5f02\u6b65\u51fd\u6570\u4e2d\u8c03\u7528\u8017\u65f6\u540c\u6b65\u51fd\u6570\nasync def bad_example():\n    await \u5f02\u6b65\u64cd\u4f5c1()\n    \u8017\u65f6\u540c\u6b65\u51fd\u6570()  # \u8fd9\u4f1a\u963b\u585e\u6574\u4e2a\u4e8b\u4ef6\u5faa\u73af\uff01\n    await \u5f02\u6b65\u64cd\u4f5c2()  # \u8981\u7b49\u4e0a\u9762\u5b8c\u6210\u624d\u80fd\u6267\u884c\n\n\u539f\u56e03:TTS\u662fCPU\u5bc6\u96c6\u578b\uff08\u751f\u6210\u8bed\u97f3\u9700\u8981\u5927\u91cf\u8ba1\u7b97\uff09\n \n# \u597d\u7684\u505a\u6cd5\uff1a\u628a\u8017\u65f6\u540c\u6b65\u51fd\u6570\u653e\u5230\u7ebf\u7a0b\u4e2d\nasync def good_example():\n    await \u5f02\u6b65\u64cd\u4f5c1()\n    await asyncio.to_thread(\u8017\u65f6\u540c\u6b65\u51fd\u6570)  # \u5728\u540e\u53f0\u7ebf\u7a0b\u6267\u884c\n    await \u5f02\u6b65\u64cd\u4f5c2()  # \u53ef\u4ee5\u7acb\u5373\u6267\u884c\uff0c\u4e0d\u7528\u7b49\u5f85\n    \n\u5f02\u6b65\u548c\u591a\u7ebf\u7a0b\u7684\u914d\u5408\u5728\u8fd9\u4e2a\u5177\u4f53\u4ee3\u7801\u4e2d\u7684\u5e94\u7528\uff1a\nasync def process_streaming_response(self, ...):\n    # \u5f02\u6b65\u63a5\u6536AI\u7684\u6d41\u5f0f\u54cd\u5e94\n    async for chunk in llm_service.stream_chat_with_context(...):\n        # \u5f02\u6b65\u5904\u7406\u6587\u672c\n        await self.process_text_chunk(chunk)\n        # \u6587\u672c\u5904\u7406\u662f\u5f02\u6b65\u7684\uff0c\u4f46TTS\u662f\u540c\u6b65\u7684\n        # \u6240\u4ee5TTS\u653e\u5728\u7ebf\u7a0b\u4e2d\uff0c\u4e0d\u963b\u585e\u6587\u672c\u63a5\u6536\n'''\n# ========GIL\u662f\u4ec0\u4e48\uff1f\uff08\u5168\u5c40\u89e3\u91ca\u5668\u9501\uff09========\n'''\n\u7b80\u5355\u7406\u89e3\uff1a\n\u60f3\u8c61Python\u89e3\u91ca\u5668\u662f\u4e00\u4e2a\u53ea\u80fd\u4e00\u4e2a\u4eba\u8fdb\u53bb\u7684\u5395\u6240\u3002\n \u5395\u6240 = Python\u89e3\u91ca\u5668\n \u9501 = GIL\uff08\u95e8\u9501\uff09\n \u89c4\u5219\uff1a\u6bcf\u6b21\u53ea\u80fd\u6709\u4e00\u4e2a\u4eba\u8fdb\u53bb\u4e0a\u5395\u6240\uff08\u6267\u884cPython\u4ee3\u7801\uff09\n \n\u4e3a\u4ec0\u4e48\u8981\u6709\u8fd9\u4e2a\u9501\uff1f\n\u56e0\u4e3aPython\u8bbe\u8ba1\u5f97\u6bd4\u8f83\u65e9......6\n\n\u540e\u679c\u662f\u5373\u4f7f\u4f60\u6709\u591a\u4e2a\u7ebf\u7a0b,\u4f46\u56e0\u4e3a\u6709GIL,\u4e00\u6b21\u8fd8\u662f\u53ea\u80fd\u6709\u4e00\u884cPython\u4ee3\u7801\u3002\n\u5f53\u7136\u4e5f\u662f\u6709\u4f8b\u5916\u7684:\u5f53\u7ebf\u7a0b\u5728\u7b49\u5f85\u65f6\uff08\u6bd4\u5982\u7b49\u5f85\u7f51\u7edc\u6570\u636e\uff09\uff0c\u5b83\u4f1a\u6682\u65f6\u628a\u9501\u8ba9\u51fa\u6765\uff0c\u8ba9\u522b\u4eba\u8fdb\u53bb\u3002\n'''\n#\u591a\u7ebf\u7a0b\u53d7GIL\u9650\u5236,\u5f02\u6b65\u9700\u8981Python 3.5+\n#\u600e\u4e48\u7ed5\u8fc7GIL\uff1f\n'''\n\u7528\u591a\u8fdb\u7a0b\uff08Multiprocessing\uff09\n \u6bcf\u4e2a\u8fdb\u7a0b\u6709\u81ea\u5df1\u7684Python\u89e3\u91ca\u5668\n \u6bcf\u4e2a\u8fdb\u7a0b\u6709\u81ea\u5df1\u7684GIL\n \u53ef\u4ee5\u771f\u6b63\u5e76\u884c\n\u7528\u5f02\u6b65\uff08Asyncio\uff09\n \u4e00\u4e2a\u7ebf\u7a0b\u5185\u5207\u6362\u4efb\u52a1\n \u9002\u5408I\/O\u5bc6\u96c6\u578b\n\u7528\u5176\u4ed6\u8bed\u8a00\u5199\u7684\u6269\u5c55\n \u6bd4\u5982\u7528C\u5199\u7684numpy\uff0c\u5728\u6267\u884cC\u4ee3\u7801\u65f6\u91ca\u653eGIL\n'''\n# =========\u4ec0\u4e48\u662fI\/O\u5bc6\u96c6\u578b\u548cCPU\u5bc6\u96c6\u578b\uff1f==========\n'''\nI\/O\u5bc6\u96c6\u578b\uff08Input\/Output\uff09\uff1a\n\u5927\u90e8\u5206\u65f6\u95f4\u5728\u7b49\u5f85\uff0c\u6bd4\u5982\uff1a\n\u4ece\u7f51\u7edc\u4e0b\u8f7d\u6587\u4ef6\n\u4ece\u6570\u636e\u5e93\u8bfb\u53d6\u6570\u636e\n\u4ece\u786c\u76d8\u8bfb\u53d6\u6587\u4ef6\n\u7b49\u5f85\u7528\u6237\u8f93\u5165\n\u7279\u70b9\uff1aCPU\u5927\u90e8\u5206\u65f6\u95f4\u5728\u7b49\uff0c\u6ca1\u4e8b\u505a\n\nCPU\u5bc6\u96c6\u578b\uff1a\n\u5927\u90e8\u5206\u65f6\u95f4\u5728\u8ba1\u7b97\uff0c\u6bd4\u5982\uff1a\n\u89c6\u9891\u7f16\u7801\/\u89e3\u7801\n\u56fe\u50cf\u5904\u7406\n\u79d1\u5b66\u8ba1\u7b97\n\u52a0\u5bc6\u89e3\u5bc6\n\u7279\u70b9\uff1aCPU\u4e00\u76f4\u5f88\u5fd9\n'''\n# =====\u534f\u7a0b\uff08Coroutine\uff09======\n#\u4ece\u96f6\u5f00\u59cb\u89e3\u91ca\u4ec0\u4e48\u662f\u534f\u7a0b\uff1f\n#\u7b2c\u4e00\u6b65\uff1a\u5148\u7406\u89e3\u51fd\u6570\n#\u666e\u901a\u51fd\u6570\u5c31\u50cf\u4e00\u4e2a\u4e00\u6b21\u6027\u4efb\u52a1\u6e05\u5355\uff1a\n'''\ndef \u505a\u65e9\u996d():\n    1. \u714e\u86cb\n    2. \u70e4\u9762\u5305\n    3. \u5012\u725b\u5976\n    return \"\u65e9\u9910\u5b8c\u6210\"  # \u7ed3\u675f\u4e86\uff0c\u4e0d\u80fd\u4e2d\u9014\u6682\u505c\n'''\n#\u7279\u70b9\uff1a\u5f00\u59cb\u6267\u884c \u2192 \u4e00\u76f4\u6267\u884c\u5230\u7ed3\u675f \u2192 \u8fd4\u56de\u7ed3\u679c,\u4e0d\u80fd\u4e2d\u9014\u6682\u505c\uff0c\u4e0d\u80fd\u6062\u590d\n\n#\u7b2c\u4e8c\u6b65\uff1a\u7406\u89e3\u751f\u6210\u5668\uff08Generator\uff09\n#\u534f\u7a0b\u7684\u524d\u8eab\u662f\u751f\u6210\u5668\u3002\u751f\u6210\u5668\u5c31\u50cf\u4e00\u4e2a\u53ef\u6682\u505c\u7684\u4efb\u52a1\u6e05\u5355\uff1a\n'''\ndef \u505a\u590d\u6742\u7684\u65e9\u996d():\n    print(\"\u5f00\u59cb\u714e\u86cb\")\n    yield \"\u714e\u86cb\u5b8c\u6210\"  # \u6682\u505c\u5728\u8fd9\u91cc\uff0c\u8fd4\u56de\u7ed3\u679c\n    \n    print(\"\u5f00\u59cb\u70e4\u9762\u5305\")\n    yield \"\u70e4\u9762\u5305\u5b8c\u6210\"  # \u6682\u505c\u5728\u8fd9\u91cc\uff0c\u8fd4\u56de\u7ed3\u679c\n    \n    print(\"\u5f00\u59cb\u5012\u725b\u5976\")\n    yield \"\u65e9\u9910\u5b8c\u6210\"  # \u6700\u540e\u6682\u505c\n\n# \u4f7f\u7528\n\u65e9\u9910\u673a = \u505a\u590d\u6742\u7684\u65e9\u996d()\nprint(next(\u65e9\u9910\u673a))  # \u8f93\u51fa\uff1a\u5f00\u59cb\u714e\u86cb \\n \u714e\u86cb\u5b8c\u6210\nprint(next(\u65e9\u9910\u673a))  # \u8f93\u51fa\uff1a\u5f00\u59cb\u70e4\u9762\u5305 \\n \u70e4\u9762\u5305\u5b8c\u6210\nprint(next(\u65e9\u9910\u673a))  # \u8f93\u51fa\uff1a\u5f00\u59cb\u5012\u725b\u5976 \\n \u65e9\u9910\u5b8c\u6210\n'''\n#\u751f\u6210\u5668\u7684\u7279\u70b9\uff1a\u53ef\u4ee5\u6682\u505c\uff08yield\uff09,\u53ef\u4ee5\u6062\u590d\uff08next()\uff09,\u53ef\u4ee5\u4f20\u503c\u8fdb\u6765\uff08\u901a\u8fc7send()\uff09\n\n#\u7b2c\u4e09\u6b65\uff1a\u534f\u7a0b\u662f\u5347\u7ea7\u7248\u7684\u751f\u6210\u5668\n#\u534f\u7a0b\u5c31\u50cf\u4e00\u4e2a\u53ef\u4ee5\u53cc\u5411\u901a\u4fe1\u7684\u667a\u80fd\u4efb\u52a1\u6e05\u5355\uff1a\n'''\nasync def \u667a\u80fd\u505a\u65e9\u996d():\n    \u6750\u6599 = await \u83b7\u53d6\u6750\u6599()  # \u7b49\u5f85\u522b\u4eba\u9001\u6750\u6599\u6765\n    print(f\"\u7528{\u6750\u6599}\u714e\u86cb\")\n    \n    \u6e29\u5ea6 = await \u68c0\u67e5\u6e29\u5ea6()  # \u7b49\u5f85\u6e29\u5ea6\u8ba1\u8bfb\u6570\n    print(f\"\u5728{\u6e29\u5ea6}\u5ea6\u4e0b\u70e4\u9762\u5305\")\n    \n    return \"\u65e9\u9910\u5b8c\u6210\"\n'''\n#\u534f\u7a0b\u7684\u7279\u70b9\uff1a\u53ef\u4ee5\u6682\u505c\uff08await\uff09,\u53ef\u4ee5\u6062\u590d\uff08\u81ea\u52a8\uff09,\u53ef\u4ee5\u548c\u5176\u4ed6\u534f\u7a0b\u534f\u4f5c\uff08\u901a\u8fc7\u4e8b\u4ef6\u5faa\u73af\uff09\n\n# =======Python\u4e2d\u7684\u534f\u7a0b\u8fdb\u5316\u53f2=========\n'''\nPython 2.x: \u53ea\u6709\u751f\u6210\u5668\uff08yield\uff09      \u2190 \u53ef\u4ee5\u6682\u505c\uff0c\u4f46\u4e0d\u597d\u7528\nPython 3.3: yield from              \u2190 \u6539\u8fdb\u751f\u6210\u5668\nPython 3.4: @asyncio.coroutine      \u2190 \u6700\u65e9\u7684\u534f\u7a0b\u88c5\u9970\u5668\nPython 3.5: async\/await             \u2190 \u73b0\u5728\u7684\u65b9\u5f0f\uff08\u6700\u7b80\u5355\uff09\n'''\n#\u534f\u7a0b\u7684\u5177\u4f53\u5de5\u4f5c\u539f\u7406\n#\u534f\u7a0b\u7684\u4e09\u4e2a\u72b6\u6001\uff1a\u51c6\u5907\u4e2d\uff08CREATED\uff09\uff1a\u534f\u7a0b\u5bf9\u8c61\u521b\u5efa\u4e86\uff0c\u4f46\u8fd8\u6ca1\u5f00\u59cb,\u8fd0\u884c\u4e2d\uff08RUNNING\uff09\uff1a\u6b63\u5728\u6267\u884c,\u6682\u505c\u4e2d\uff08SUSPENDED\uff09\uff1a\u9047\u5230await\u6682\u505c\u4e86\n\n#\u534f\u7a0b\u7684\u751f\u547d\u5468\u671f\uff1a\n'''\n\u521b\u5efa\u534f\u7a0b \u2192 \u653e\u5165\u4e8b\u4ef6\u5faa\u73af \u2192 \u5f00\u59cb\u6267\u884c \u2192 \u9047\u5230await\u6682\u505c\n                                      \u2193\n                               \u4e8b\u4ef6\u5faa\u73af\u6267\u884c\u5176\u4ed6\u4efb\u52a1\n                                      \u2193\n                               await\u7684\u6761\u4ef6\u6ee1\u8db3\u4e86\n                                      \u2193\n                               \u6062\u590d\u6267\u884c \u2192 \u5b8c\u6210\/\u5f02\u5e38\n'''\n\n#\u534f\u7a0b\u7684\u6838\u5fc3\uff1a\u4e8b\u4ef6\u5faa\u73af\uff08Event Loop\uff09\n'''\n\u4e8b\u4ef6\u5faa\u73af\u5c31\u50cf\u4e00\u4e2a\u9910\u5385\u7ecf\u7406\uff1a\n  \u7ba1\u7406\u6240\u6709\u534f\u7a0b\uff08\u53a8\u5e08\uff09\n  \u54ea\u4e2a\u534f\u7a0b\u53ef\u4ee5\u6267\u884c\u4e86\uff08\u54ea\u4e2a\u9505\u53ef\u4ee5\u7092\u4e86\uff09\n  \u54ea\u4e2a\u534f\u7a0b\u9700\u8981\u7b49\u5f85\uff08\u54ea\u4e2a\u83dc\u8fd8\u5728\u5207\uff09\n'''\n#\u4e8b\u4ef6\u5faa\u73af\u7684\u5de5\u4f5c\u6d41\u7a0b\uff1a\n'''\n\u5f00\u59cb\n  \u2193\n\u68c0\u67e5\u534f\u7a0b\u961f\u5217\n  \u2193\n\u6709\u5c31\u7eea\u7684\u534f\u7a0b\u5417\uff1f \u2192 \u6709 \u2192 \u6267\u884c\u5b83\n  \u2193 \u6ca1\u6709\n\u7b49\u5f85\u4e8b\u4ef6\u53d1\u751f\uff08I\/O\u5b8c\u6210\u3001\u5b9a\u65f6\u5668\u5230\u70b9\uff09\n  \u2193\n\u4e8b\u4ef6\u53d1\u751f \u2192 \u5bf9\u5e94\u7684\u534f\u7a0b\u5c31\u7eea\n  \u2193\n\u7ee7\u7eed\u68c0\u67e5...\n'''\n# =======\u534f\u7a0b\u600e\u4e48\u90a3\u4e48\u50cf\u5f02\u6b65\u554a\uff1f=========\n#\u534f\u7a0b\u5c31\u662f\u5f02\u6b65\uff0c\u6216\u8005\u8bf4\u534f\u7a0b\u662f\u5b9e\u73b0\u5f02\u6b65\u7684\u4e00\u79cd\u5177\u4f53\u6280\u672f.......6\n#\u5f02\u6b65 \u662f\u4e00\u4e2a \u76ee\u6807\uff08\u60f3\u8981\u540c\u65f6\u505a\u591a\u4ef6\u4e8b\uff09,\u534f\u7a0b \u662f \u5b9e\u73b0\u8fd9\u4e2a\u76ee\u6807\u7684\u5de5\u5177\uff08\u5177\u4f53\u600e\u4e48\u505a\uff09\\\n#\u5c31\u50cf\uff1a\u6211\u8981\u4ece\u5317\u4eac\u5230\u4e0a\u6d77\uff08\u5f02\u6b65\uff1a\u60f3\u66f4\u5feb\u5230\u8fbe\uff09,\u6211\u53ef\u4ee5\u9009\u62e9\u5750\u9ad8\u94c1\u3001\u98de\u673a\u3001\u5f00\u8f66\uff08\u534f\u7a0b\uff1a\u5177\u4f53\u7684\u65b9\u6cd5\uff09\n#\u66f4\u51c6\u786e\u7684\u5c42\u6b21\u5173\u7cfb\uff1a\n'''\n\u7f16\u7a0b\u6a21\u5f0f\u5c42\u9762\uff1a\n   \u5f02\u6b65\u7f16\u7a0b\uff08Asynchronous Programming\uff09\n     \u2193\n\u5177\u4f53\u5b9e\u73b0\u5c42\u9762\uff1a\n   Python\uff1a\u534f\u7a0b\uff08Coroutine\uff09\u2190 \u8fd9\u662fPython\u5b9e\u73b0\u5f02\u6b65\u7684\u65b9\u5f0f\n   JavaScript\uff1aPromise\/async-await \u2190 \u8fd9\u662fJS\u5b9e\u73b0\u5f02\u6b65\u7684\u65b9\u5f0f  \n   Go\uff1aGoroutine \u2190 \u8fd9\u662fGo\u5b9e\u73b0\u5f02\u6b65\u7684\u65b9\u5f0f\n'''\n#\u4e3a\u4ec0\u4e48\u4f1a\u6709\u8fd9\u79cd\u6df7\u6dc6\uff1f\n#\u56e0\u4e3a\u4e0d\u540c\u8bed\u8a00\u7528\u4e0d\u540c\u7684\u8bcd\uff0c\u4f46\u8bf4\u7684\u662f\u4e00\u56de\u4e8b\uff1a\u7531\u7bc7\u5e45\u9650\u5236\uff0c\u8fd9\u91cc\u5c31\u4e0d\u518d\u8fc7\u591a\u8d58\u8ff0\u4e86\u3002\u4f46\u6838\u5fc3\u601d\u60f3\u90fd\u4e00\u6837\uff1a\u8ba9\u7a0b\u5e8f\u5728\u7b49\u5f85\u65f6\u53ef\u4ee5\u505a\u5176\u4ed6\u4e8b\u3002\n#\u6240\u4ee5\u5230\u8fd9\u9700\u8981\u5bf9\u524d\u9762\u7684\u89c2\u70b9\u8fdb\u884c\u4e00\u4e9b\u4fee\u590d\uff0c\u753b\u4e00\u4e2a\u66f4\u51c6\u786e\u7684\u5173\u7cfb\u56fe\uff1a\n'''\n\u5f02\u6b65\u7f16\u7a0b\uff08\u6982\u5ff5\uff09\n    \u2502\n    \u251c\u2500\u2500 \u5b9e\u73b0\u65b9\u5f0f1\uff1a\u591a\u7ebf\u7a0b\/\u591a\u8fdb\u7a0b\n    \u2502\n    \u251c\u2500\u2500 \u5b9e\u73b0\u65b9\u5f0f2\uff1a\u4e8b\u4ef6\u9a71\u52a8\n    \u2502\n    \u2514\u2500\u2500 \u5b9e\u73b0\u65b9\u5f0f3\uff1a\u534f\u7a0b\uff08Coroutine\uff09\u2190 Python\u7684\u9009\u62e9\n            \u2502\n            \u251c\u2500\u2500 \u5b9e\u73b0\u65b9\u5f0f\uff1aasync\/await\u8bed\u6cd5\n            \u251c\u2500\u2500 \u8fd0\u884c\u65f6\uff1aasyncio\u4e8b\u4ef6\u5faa\u73af  \n            \u2514\u2500\u2500 \u7279\u70b9\uff1a\u8f7b\u91cf\u7ea7\u3001\u5355\u7ebf\u7a0b\u5185\u5e76\u53d1\n'''\n#\u4e3a\u4ec0\u4e48Python\u9009\u62e9\u534f\u7a0b\uff1f\n'''\n\u5386\u53f2\u539f\u56e0\uff1a\n\u65e9\u671fPython\uff1a\u6709GIL\u9650\u5236\uff0c\u591a\u7ebf\u7a0b\u6548\u679c\u4e0d\u597d\nPython 3.4\uff1a\u5f15\u5165asyncio\u5e93\uff0c\u7528\u534f\u7a0b\u5b9e\u73b0\u5f02\u6b65\nPython 3.5\uff1a\u5f15\u5165async\/await\u8bed\u6cd5\uff0c\u8ba9\u534f\u7a0b\u66f4\u5bb9\u6613\u5199\n'''\n#\u6240\u4ee5\u6362\u4e00\u4e2a\u89d2\u5ea6\u7406\u89e3:\u5f02\u6b65 \u662f \"\u4ec0\u4e48\"\uff08What\uff09\uff1a\u6211\u60f3\u8981\u6211\u7684\u7a0b\u5e8f\u4e0d\u8981\u50bb\u7b49,\u6211\u60f3\u8981\u540c\u65f6\u5904\u7406\u591a\u4e2a\u8bf7\u6c42,\u6211\u60f3\u8981\u9ad8\u6548\u5229\u7528CPU\u65f6\u95f4\n#\u534f\u7a0b \u662f \"\u600e\u4e48\u5b9e\u73b0\"\uff08How\uff09\uff1aPython\u8bf4\uff1a\u6211\u4eec\u7528async\/await\u8bed\u6cd5,\u6211\u4eec\u5199\u534f\u7a0b\u51fd\u6570,\u6211\u4eec\u7528asyncio\u4e8b\u4ef6\u5faa\u73af\u6765\u8c03\u5ea6\n#\u5230\u65f6\u5019\u6211\u4eec\u8fdb\u884c\u6700\u540e\u4e00\u6b65\u6f84\u6e05:\u534f\u7a0b \u2260 \u5f02\u6b65,\u66f4\u51c6\u786e\u5730\u8bf4\uff1a\u534f\u7a0b\u662f\u5b9e\u73b0\u5f02\u6b65\u7684\u4e00\u79cd\u5177\u4f53\u6280\u672f\u624b\u6bb5\u3002\n#\u5c31\u50cf\uff1a\u98de\u673a \u2260 \u5feb\u901f\u51fa\u884c\uff08\u98de\u673a\u662f\u5b9e\u73b0\u5feb\u901f\u51fa\u884c\u7684\u4e00\u79cd\u65b9\u5f0f\uff09,\u534f\u7a0b \u2260 \u5f02\u6b65\u7f16\u7a0b\uff08\u534f\u7a0b\u662f\u5b9e\u73b0\u5f02\u6b65\u7f16\u7a0b\u7684\u4e00\u79cd\u65b9\u5f0f\uff09<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">message_manager.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n\"\"\"\n\u7edf\u4e00\u7684\u6d88\u606f\u7ba1\u7406\u6a21\u5757\n\u652f\u6301\u591a\u4f1a\u8bdd\u3001\u591aagent\u7684\u6d88\u606f\u5b58\u50a8\u548c\u62fc\u63a5\n\"\"\"\n\n# \u5f02\u6b65\u7f16\u7a0b\u5de5\u5177\uff08\u8ba9\u7a0b\u5e8f\u53ef\u4ee5\u540c\u65f6\u505a\u591a\u4ef6\u4e8b\u60c5\uff09\nimport asyncio\n\n# \u751f\u6210\u552f\u4e00ID\u7684\u5de5\u5177\uff08\u50cf\u8eab\u4efd\u8bc1\u53f7\u7801\u751f\u6210\u5668\uff09\nimport uuid\n\n# \u65e5\u5fd7\u8bb0\u5f55\u5de5\u5177\uff08\u50cf\u65e5\u8bb0\u672c\uff0c\u8bb0\u5f55\u7a0b\u5e8f\u505a\u4e86\u4ec0\u4e48\uff09\nimport logging\n\n# \u6b63\u5219\u8868\u8fbe\u5f0f\u5de5\u5177\uff08\u6587\u672c\u641c\u7d22\u548c\u5339\u914d\u5de5\u5177\uff09\nimport re\n\n# JSON\u6570\u636e\u5904\u7406\u5de5\u5177\uff08\u5904\u7406\u50cf{\"name\":\"\u5c0f\u660e\"}\u8fd9\u6837\u7684\u6570\u636e\u683c\u5f0f\uff09\nimport json\n\n# \u7cfb\u7edf\u5de5\u5177\uff08\u8bbf\u95ee\u547d\u4ee4\u884c\u53c2\u6570\u7b49\uff09\nimport sys\n\n# \u65f6\u95f4\u5de5\u5177\nimport time\n\n# \u7c7b\u578b\u63d0\u793a\uff08\u53ea\u662f\u7ed9\u7a0b\u5e8f\u5458\u770b\u7684\uff0c\u544a\u8bc9\u522b\u4eba\u53c2\u6570\u5e94\u8be5\u662f\u4ec0\u4e48\u7c7b\u578b\uff09\nfrom typing import Dict, List, Optional, Any\n\n# \u65e5\u671f\u65f6\u95f4\u5de5\u5177\nfrom datetime import datetime, timedelta\n\n# \u8def\u5f84\u5904\u7406\u5de5\u5177\uff08\u66f4\u65b9\u4fbf\u5730\u5904\u7406\u6587\u4ef6\u8def\u5f84\uff09\nfrom pathlib import Path\n\nlogger = logging.getLogger(__name__)\n\n\n# \u5de5\u5177\u51fd\u6570\ndef now():\n    \"\"\"\u83b7\u53d6\u5f53\u524d\u65f6\u95f4\u6233\"\"\"\n    return time.strftime('%H:%M:%S:') + str(int(time.time() * 1000) % 10000)\n\n\ndef setup_logging():\n    \"\"\"\u7edf\u4e00\u914d\u7f6e\u65e5\u5fd7\u7cfb\u7edf\"\"\"\n    try:\n        # \u5c1d\u8bd5\u4ece\u914d\u7f6e\u6587\u4ef6\u8bfb\u53d6\u8bbe\u7f6e\n        from system.config import config\n        log_level = getattr(logging, config.system.log_level.upper(), logging.INFO)\n        # \u914d\u7f6e\u65e5\u5fd7\u7684\u57fa\u672c\u8bbe\u7f6e        \n        logging.basicConfig(\n            level=log_level,  # \u65e5\u5fd7\u7ea7\u522b\n            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',  # \u65e5\u5fd7\u683c\u5f0f\n            handlers=&#91;logging.StreamHandler(sys.stderr)]  # \u8f93\u51fa\u5230\u9519\u8bef\u6d41\n        )\n\n        # \u8bbe\u7f6e\u7b2c\u4e09\u65b9\u5e93\u65e5\u5fd7\u7ea7\u522b\n        for logger_name in &#91;\"httpcore.connection\", \"httpcore.http11\", \"httpx\", \"openai._base_client\", \"asyncio\"]:\n            logging.getLogger(logger_name).setLevel(logging.WARNING)\n    except ImportError:\n        # \u5982\u679c\u65e0\u6cd5\u5bfc\u5165\u914d\u7f6e\uff0c\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e\n        logging.basicConfig(\n            level=logging.INFO,\n            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',\n            handlers=&#91;logging.StreamHandler(sys.stderr)]\n        )\n\n\nclass MessageManager:\n    \"\"\"\u7edf\u4e00\u7684\u6d88\u606f\u7ba1\u7406\u5668\"\"\"\n\n    def __init__(self):\n        self.sessions: Dict&#91;str, Dict] = {}\n        # \u5206\u6790\u72b6\u6001\u8ddf\u8e2a\uff0c\u9632\u6b62\u91cd\u590d\u6267\u884c\n        self.analysis_in_progress: Dict&#91;str, bool] = {}\n        # \u4ece\u914d\u7f6e\u6587\u4ef6\u8bfb\u53d6\u6700\u5927\u5386\u53f2\u8f6e\u6570\uff0c\u9ed8\u8ba4\u4e3a10\u8f6e\n        try:\n            from system.config import config\n            self.max_history_rounds = config.api.max_history_rounds  # \u6700\u5927\u5bf9\u8bdd\u8f6e\u6570\n            self.max_messages_per_session = self.max_history_rounds * 2  # \u6bcf\u8f6e\u5bf9\u8bdd\u5305\u542b\u7528\u6237\u548c\u52a9\u624b\u5404\u4e00\u6761\u6d88\u606f\n            self.persistent_context = config.api.persistent_context  # \u662f\u5426\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\n            self.context_load_days = config.api.context_load_days  # \u52a0\u8f7d\u591a\u5c11\u5929\u7684\u5386\u53f2\n            self.log_dir = config.system.log_dir  # \u65e5\u5fd7\u4fdd\u5b58\u76ee\u5f55\n            self.ai_name = config.system.ai_name  # AI\u7684\u540d\u5b57\n        except ImportError:\n            # \u5982\u679c\u627e\u4e0d\u5230\u914d\u7f6e\uff0c\u5c31\u7528\u9ed8\u8ba4\u503c\n            self.max_history_rounds = 10\n            self.max_messages_per_session = 20  # \u9ed8\u8ba420\u6761\u6d88\u606f\n            self.persistent_context = True\n            self.context_load_days = 3\n            self.log_dir = Path(\"logs\")\n            self.ai_name = \"\u5a1c\u8fe6\"\n            logger.warning(\"\u65e0\u6cd5\u5bfc\u5165\u914d\u7f6e\uff0c\u4f7f\u7528\u9ed8\u8ba4\u5386\u53f2\u8f6e\u6570\u8bbe\u7f6e\")\n\n    def generate_session_id(self) -&gt; str:\n        \"\"\"\u751f\u6210\u552f\u4e00\u7684\u4f1a\u8bddID\"\"\"\n        return str(uuid.uuid4())\n\n    def create_session(self, session_id: Optional&#91;str] = None) -&gt; str:\n        \"\"\"\u83b7\u53d6\u6216\u521b\u5efa\u4f1a\u8bdd\"\"\"\n        if not session_id:\n            session_id = self.generate_session_id()\n\n        # \u68c0\u67e5\u4f1a\u8bdd\u662f\u5426\u5df2\u5b58\u5728\n        if session_id in self.sessions:\n            logger.debug(f\"\u4f7f\u7528\u73b0\u6709\u4f1a\u8bdd: {session_id}\")\n            # \u66f4\u65b0\u6700\u540e\u6d3b\u52a8\u65f6\u95f4\n            self.sessions&#91;session_id]&#91;\"last_activity\"] = asyncio.get_event_loop().time()\n            return session_id\n\n        # \u521d\u59cb\u5316\u65b0\u4f1a\u8bdd\n        self.sessions&#91;session_id] = {\n            \"created_at\": asyncio.get_event_loop().time(),\n            \"messages\": &#91;],  # \u6d88\u606f\u5217\u8868\uff08\u7a7a\u7684\uff09\n            \"agent_type\": \"default\",  # \u53ef\u4ee5\u6269\u5c55\u652f\u6301\u4e0d\u540cagent\u7c7b\u578b\n            \"last_activity\": asyncio.get_event_loop().time()  # \u6700\u540e\u6d3b\u52a8\u65f6\u95f4\n        }\n        '''\n        \u903b\u8f91\u5224\u65ad\uff1a\n          \u5982\u679c \u6ca1\u6709\u63d0\u4f9bsession_id \u5c31 \u751f\u6210\u4e00\u4e2a\u65b0\u7684\n          \u5982\u679c session_id\u5df2\u7ecf\u5728sessions\u5b57\u5178\u91cc \u5c31 \u66f4\u65b0\u6700\u540e\u6d3b\u52a8\u65f6\u95f4\u5e76\u8fd4\u56de\n          \u5426\u5219 \u521b\u5efa\u65b0\u623f\u95f4\uff0c\u8bb0\u5f55\u521b\u5efa\u65f6\u95f4\u3001\u7a7a\u7684\u6d88\u606f\u5217\u8868\u7b49\n          \u5982\u679c persistent_context\u662fTrue \u5c31 \u5c1d\u8bd5\u52a0\u8f7d\u5386\u53f2\u5bf9\u8bdd\n        '''\n\n        # \u5982\u679c\u542f\u7528\u6301\u4e45\u5316\u4e0a\u4e0b\u6587\uff0c\u5c1d\u8bd5\u52a0\u8f7d\u5386\u53f2\u5bf9\u8bdd\n        if self.persistent_context:\n            self._load_persistent_context_for_session(session_id)\n\n        logger.info(f\"\u521b\u5efa\u65b0\u4f1a\u8bdd: {session_id}\")\n        return session_id\n\n    def _load_persistent_context_for_session(self, session_id: str):\n        \"\"\"\u4e3a\u6307\u5b9a\u4f1a\u8bdd\u52a0\u8f7d\u6301\u4e45\u5316\u4e0a\u4e0b\u6587\"\"\"\n        try:\n            # \u52a0\u8f7d\u5386\u53f2\u5bf9\u8bdd\n            recent_messages = self.load_recent_context(\n                days=self.context_load_days,\n                max_messages=self.max_messages_per_session\n            )\n\n            if recent_messages:\n                self.sessions&#91;session_id]&#91;\"messages\"] = recent_messages\n                logger.info(f\"\u4f1a\u8bdd {session_id} \u52a0\u8f7d\u4e86 {len(recent_messages)} \u6761\u5386\u53f2\u5bf9\u8bdd\")\n            else:\n                logger.debug(f\"\u4f1a\u8bdd {session_id} \u672a\u627e\u5230\u5386\u53f2\u5bf9\u8bdd\u8bb0\u5f55\")\n\n        except Exception as e:\n            logger.warning(f\"\u4e3a\u4f1a\u8bdd {session_id} \u52a0\u8f7d\u6301\u4e45\u5316\u4e0a\u4e0b\u6587\u5931\u8d25: {e}\")\n\n    def get_session(self, session_id: str) -&gt; Optional&#91;Dict]:\n        \"\"\"\u83b7\u53d6\u4f1a\u8bdd\u4fe1\u606f\"\"\"\n        return self.sessions.get(session_id)\n\n    def add_message(self, session_id: str, role: str, content: str) -&gt; bool:\n        \"\"\"\u5411\u4f1a\u8bdd\u6dfb\u52a0\u6d88\u606f\"\"\"\n        if session_id not in self.sessions:\n            logger.warning(f\"\u4f1a\u8bdd\u4e0d\u5b58\u5728: {session_id}\")\n            return False\n\n        session = self.sessions&#91;session_id]\n        session&#91;\"messages\"].append({\"role\": role, \"content\": content})  # \u6dfb\u52a0\u6d88\u606f\n        session&#91;\"last_activity\"] = asyncio.get_event_loop().time()  # \u66f4\u65b0\u6d3b\u52a8\u65f6\u95f4\n\n        # \u9650\u5236\u6d88\u606f\u6570\u91cf,\u5982\u679c\u6d88\u606f\u592a\u591a\u4e86\uff0c\u5c31\u5220\u9664\u6700\u65e9\u7684\u6d88\u606f\uff08\u53ea\u4fdd\u7559\u6700\u8fd1\u7684\uff09\n        if len(session&#91;\"messages\"]) &gt; self.max_messages_per_session:\n            session&#91;\"messages\"] = session&#91;\"messages\"]&#91;-self.max_messages_per_session:]\n\n        logger.debug(f\"\u4f1a\u8bdd {session_id} \u6dfb\u52a0\u6d88\u606f: {role} - {content&#91;:50]}...\")\n        return True\n\n    def get_messages(self, session_id: str) -&gt; List&#91;Dict]:\n        \"\"\"\u83b7\u53d6\u4f1a\u8bdd\u7684\u6240\u6709\u6d88\u606f\"\"\"\n        session = self.sessions.get(session_id)  # \uff1a\u5728\u6d88\u606f\u5b57\u5178\u91cc\u67e5\u627e\u8fd9\u4e2a\u6d88\u606f,\u5982\u679c\u627e\u5230\u6d88\u606f\uff1a\u8fd4\u56desession&#91;\"messages\"]\uff08\u8fd9\u4e2a\u5b57\u5178\u91cc\u7684\u6240\u6709\u5bf9\u8bdd\uff09\n        return session&#91;\"messages\"] if session else &#91;]  # \u5982\u679c\u6ca1\u627e\u5230,\u8fd4\u56de&#91;]\uff08\u7a7a\u5217\u8868\uff09\n\n    def get_recent_messages(self, session_id: str, count: Optional&#91;int] = None) -&gt; List&#91;Dict]:\n        \"\"\"\u83b7\u53d6\u4f1a\u8bdd\u7684\u6700\u8fd1\u6d88\u606f\"\"\"\n        if count is None:  # # \u5982\u679c\u6ca1\u6709\u6307\u5b9a\u8981\u591a\u5c11\u6761\n            count = self.max_messages_per_session  # \u5c31\u7528\u9ed8\u8ba4\u7684\u6700\u5927\u6d88\u606f\u6570\n        messages = self.get_messages(session_id)  # \u5148\u83b7\u53d6\u6240\u6709\u6d88\u606f\n        # session_id\uff1a\u623f\u95f4\u53f7,count\uff1a\u60f3\u8981\u591a\u5c11\u6761\u6700\u8fd1\u7684\u6d88\u606f\uff08\u53ef\u9009\uff0c\u4e0d\u586b\u5c31\u7528\u9ed8\u8ba4\u503c\uff09\n        return messages&#91;-count:] if messages else &#91;]\n\n    # \u8fd9\u662f\u6700\u91cd\u8981\u7684\u529f\u80fd\u4e4b\u4e00\n    def build_conversation_messages(self, session_id: str, system_prompt: str,\n                                    current_message: str, include_history: bool = True) -&gt; List&#91;Dict]:\n        \"\"\"\u6784\u5efa\u5b8c\u6574\u7684\u5bf9\u8bdd\u6d88\u606f\u5217\u8868\"\"\"\n        messages = &#91;]  # \u51c6\u5907\u4e00\u4e2a\u7a7a\u7684\u6d88\u606f\u5305\n\n        # \u6dfb\u52a0\u5f53\u524d\u65f6\u95f4\u4fe1\u606f\u5230\u7cfb\u7edf\u63d0\u793a\u8bcd\n        from datetime import datetime\n        current_time = datetime.now()  # \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\n        # \u5236\u4f5c\u65f6\u95f4\u4fe1\u606f\u5b57\u7b26\u4e32\n        time_info = f\"\\n\\n\u3010\u5f53\u524d\u65f6\u95f4\u4fe1\u606f\u3011\\n\u5f53\u524d\u65e5\u671f\uff1a{current_time.strftime('%Y\u5e74%m\u6708%d\u65e5')}\\n\u5f53\u524d\u65f6\u95f4\uff1a{current_time.strftime('%H:%M:%S')}\\n\u5f53\u524d\u661f\u671f\uff1a{current_time.strftime('%A')}\\n\"\n        enhanced_system_prompt = system_prompt + time_info  # \u628a\u65f6\u95f4\u4fe1\u606f\u52a0\u5230\u7cfb\u7edf\u63d0\u793a\u8bcd\u540e\u9762\n\n        # \u6dfb\u52a0\u7cfb\u7edf\u63d0\u793a\u8bcd\uff08\u8fd9\u662f\u7b2c\u4e00\u6761\u6d88\u606f\uff09\n        messages.append({\"role\": \"system\", \"content\": enhanced_system_prompt})\n\n        # \u6dfb\u52a0\u5386\u53f2\u5bf9\u8bdd (\u5982\u679c\u9700\u8981\u7684\u8bdd\uff09\n        if include_history:  # \u9ed8\u8ba4\u662fTrue\uff0c\u5305\u542b\u5386\u53f2\n            recent_messages = self.get_recent_messages(session_id)  # \u83b7\u53d6\u6700\u8fd1\u7684\u5386\u53f2\u5bf9\u8bdd\n            messages.extend(recent_messages)  # \u628a\u5386\u53f2\u5bf9\u8bdd\u52a0\u5230\u6d88\u606f\u5305\u91cc\n\n        # \u6dfb\u52a0\u5f53\u524d\u7528\u6237\u6d88\u606f \uff08\u8fd9\u662f\u6700\u540e\u4e00\u6761\u6d88\u606f\uff09\n        messages.append({\"role\": \"user\", \"content\": current_message})\n\n        return messages  # \u8fd4\u56de\u5b8c\u6574\u7684\u6d88\u606f\u5305\n\n    def build_conversation_messages_from_memory(self, memory_messages: List&#91;Dict], system_prompt: str,\n                                                current_message: str, max_history_rounds: int = None) -&gt; List&#91;Dict]:\n        \"\"\"\n        \u4ece\u5185\u5b58\u6d88\u606f\u5217\u8868\u6784\u5efa\u5bf9\u8bdd\u6d88\u606f\uff08\u7528\u4e8eUI\u754c\u9762\uff09\n\n        Args:\n            memory_messages: \u5185\u5b58\u4e2d\u7684\u6d88\u606f\u5217\u8868\n            system_prompt: \u7cfb\u7edf\u63d0\u793a\u8bcd\n            current_message: \u5f53\u524d\u7528\u6237\u6d88\u606f\n            max_history_rounds: \u6700\u5927\u5386\u53f2\u8f6e\u6570\uff0c\u9ed8\u8ba4\u4f7f\u7528\u914d\u7f6e\u503c\n\n        Returns:\n            List&#91;Dict]: \u5b8c\u6574\u7684\u5bf9\u8bdd\u6d88\u606f\u5217\u8868\n        \"\"\"\n        messages = &#91;]\n\n        # \u6dfb\u52a0\u5f53\u524d\u65f6\u95f4\u4fe1\u606f\u5230\u7cfb\u7edf\u63d0\u793a\u8bcd\n        from datetime import datetime\n        current_time = datetime.now()\n        time_info = f\"\\n\\n\u3010\u5f53\u524d\u65f6\u95f4\u4fe1\u606f\u3011\\n\u5f53\u524d\u65e5\u671f\uff1a{current_time.strftime('%Y\u5e74%m\u6708%d\u65e5')}\\n\u5f53\u524d\u65f6\u95f4\uff1a{current_time.strftime('%H:%M:%S')}\\n\u5f53\u524d\u661f\u671f\uff1a{current_time.strftime('%A')}\\n\"\n        enhanced_system_prompt = system_prompt + time_info\n\n        # \u6dfb\u52a0\u7cfb\u7edf\u63d0\u793a\u8bcd\n        messages.append({\"role\": \"system\", \"content\": enhanced_system_prompt})\n\n        # \u8ba1\u7b97\u6700\u5927\u6d88\u606f\u6570\u91cf\n        if max_history_rounds is None:\n            max_history_rounds = self.max_history_rounds\n\n        max_messages = max_history_rounds * 2  # \u6bcf\u8f6e\u5bf9\u8bdd\u5305\u542b\u7528\u6237\u548c\u52a9\u624b\u5404\u4e00\u6761\u6d88\u606f\n\n        # \u6dfb\u52a0\u5386\u53f2\u5bf9\u8bdd\uff08\u9650\u5236\u6570\u91cf\uff09\n        if memory_messages:\n            recent_messages = memory_messages&#91;-max_messages:]\n            messages.extend(recent_messages)\n\n        # \u6dfb\u52a0\u5f53\u524d\u7528\u6237\u6d88\u606f\n        messages.append({\"role\": \"user\", \"content\": current_message})\n\n        return messages\n\n    def get_session_info(self, session_id: str) -&gt; Optional&#91;Dict]:\n        \"\"\"\u83b7\u53d6\u4f1a\u8bdd\u8be6\u7ec6\u4fe1\u606f\"\"\"\n        session = self.sessions.get(session_id)\n        if not session:\n            return None\n\n        return {\n            \"session_id\": session_id,\n            \"created_at\": session&#91;\"created_at\"],\n            \"last_activity\": session&#91;\"last_activity\"],\n            \"message_count\": len(session&#91;\"messages\"]),\n            \"conversation_rounds\": len(session&#91;\"messages\"]) \/\/ 2,  # \u6709\u8da3\u7684\u8ba1\u7b97\uff1alen(session&#91;\"messages\"]) \/\/ 2\uff1a\u7528\u6574\u6570\u9664\u6cd5\u8ba1\u7b97\u8f6e\u6570\n            \"agent_type\": session&#91;\"agent_type\"],\n            \"max_history_rounds\": self.max_history_rounds,  # \u6dfb\u52a0\u6700\u5927\u5386\u53f2\u8f6e\u6570\u4fe1\u606f\n            \"last_message\": session&#91;\"messages\"]&#91;-1]&#91;\"content\"]&#91;:100] + \"...\" if session&#91;\"messages\"] else \"\u65e0\u5bf9\u8bdd\u5386\u53f2\"\n        }\n\n    def get_all_sessions_info(self) -&gt; Dict&#91;str, Dict]:\n        \"\"\"\u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\u4fe1\u606f\"\"\"\n        sessions_info = {}  # \u521b\u5efa\u4e00\u4e2a\u7a7a\u5b57\u5178\u6765\u5b58\u653e\u6240\u6709\u623f\u95f4\u4fe1\u606f\n        # \u904d\u5386self.sessions\u5b57\u5178\u4e2d\u7684\u6bcf\u4e2a\u623f\u95f4\n        for session_id, session in self.sessions.items():\n            # \u5bf9\u6bcf\u4e2a\u623f\u95f4\uff0c\u8c03\u7528get_session_info\u83b7\u53d6\u8be6\u7ec6\u4fe1\u606f\n            sessions_info&#91;session_id] = self.get_session_info(session_id)\n        return sessions_info  # \u8fd4\u56de\u5305\u542b\u6240\u6709\u623f\u95f4\u4fe1\u606f\u7684\u5b57\u5178\n\n    def delete_session(self, session_id: str) -&gt; bool:\n        \"\"\"\u5220\u9664\u6307\u5b9a\u4f1a\u8bdd\"\"\"\n        if session_id in self.sessions:  # \u5982\u679c\u623f\u95f4\u5b58\u5728\n            del self.sessions&#91;session_id]\n            \u5220\u9664\u8fd9\u4e2a\u623f\u95f4\n            logger.info(f\"\u5220\u9664\u4f1a\u8bdd: {session_id}\")\n            return True\n        return False\n\n    def clear_all_sessions(self) -&gt; int:\n        \"\"\"\u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd\"\"\"\n        count = len(self.sessions)  # \u5148\u7edf\u8ba1\u6709\u591a\u5c11\u4e2a\u623f\u95f4\n        self.sessions.clear()  # \u6e05\u7a7a\u6574\u4e2a\u5b57\u5178\n        logger.info(f\"\u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd\uff0c\u5171 {count} \u4e2a\")  # \u8bb0\u5f55\u6e05\u7a7a\u4e86\u591a\u5c11\u4e2a\n        return count  # \u8fd4\u56de\u6e05\u7a7a\u7684\u6570\u91cf\n\n    # \u8fd9\u662f\u975e\u5e38\u91cd\u8981\u7684\u529f\u80fd\uff0c\u9632\u6b62\u5185\u5b58\u88ab\u4e0d\u6d3b\u52a8\u7684\u623f\u95f4\u5360\u6ee1\uff1a\n    def cleanup_old_sessions(self, max_age_hours: int = 24) -&gt; int:\n        \"\"\"\u6e05\u7406\u8fc7\u671f\u4f1a\u8bdd\"\"\"\n        current_time = asyncio.get_event_loop().time()  # \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\n        expired_sessions = &#91;]  # \u521b\u5efa\u4e00\u4e2a\u5217\u8868\u6765\u5b58\u653e\u8fc7\u671f\u7684\u623f\u95f4\u53f7\n\n        # \u7b2c\u4e00\u904d\uff1a\u627e\u51fa\u6240\u6709\u8fc7\u671f\u7684\u623f\u95f4\n        for session_id, session in self.sessions.items():\n            # \u8ba1\u7b97\u623f\u95f4\u591a\u4e45\u6ca1\u6d3b\u52a8\u4e86\uff08\u5f53\u524d\u65f6\u95f4 - \u6700\u540e\u6d3b\u52a8\u65f6\u95f4\uff09\n            # \u5982\u679c\u8d85\u8fc7max_age_hours\u5c0f\u65f6\uff08\u9ed8\u8ba424\u5c0f\u65f6\uff09\uff0c\u5c31\u6807\u8bb0\u4e3a\u8fc7\u671f\n            if current_time - session&#91;\"last_activity\"] &gt; max_age_hours * 3600:\n                expired_sessions.append(session_id)  # \u6dfb\u52a0\u5230\u8fc7\u671f\u5217\u8868\n\n        # \u7b2c\u4e8c\u904d\uff1a\u5220\u9664\u6240\u6709\u8fc7\u671f\u7684\u623f\u95f4\n        for session_id in expired_sessions:\n            del self.sessions&#91;session_id]  # \u4ece\u5b57\u5178\u4e2d\u5220\u9664\n\n        # \u5982\u679c\u6709\u6e05\u7406\u8fc7\u671f\u7684\u623f\u95f4\uff0c\u5c31\u8bb0\u5f55\u65e5\u5fd7\n        if expired_sessions:\n            logger.info(f\"\u6e05\u7406\u4e86 {len(expired_sessions)} \u4e2a\u8fc7\u671f\u4f1a\u8bdd\")\n\n        return len(expired_sessions)  # \u8fd4\u56de\u6e05\u7406\u4e86\u591a\u5c11\u4e2a\n\n    def set_agent_type(self, session_id: str, agent_type: str) -&gt; bool:\n        \"\"\"\u8bbe\u7f6e\u4f1a\u8bdd\u7684agent\u7c7b\u578b\"\"\"\n        if session_id in self.sessions:  # \u5982\u679c\u623f\u95f4\u5b58\u5728\n            self.sessions&#91;session_id]&#91;\"agent_type\"] = agent_type  # \u8bbe\u7f6e\u7c7b\u578b\n            return True  # \u8bbe\u7f6e\u6210\u529f\n        return False  # \u623f\u95f4\u4e0d\u5b58\u5728\uff0c\u8bbe\u7f6e\u5931\u8d25\n\n    def get_agent_type(self, session_id: str) -&gt; Optional&#91;str]:\n        \"\"\"\u83b7\u53d6\u4f1a\u8bdd\u7684agent\u7c7b\u578b\"\"\"\n        session = self.sessions.get(session_id)  # \u5148\u627e\u5230\u623f\u95f4\n        return session&#91;\"agent_type\"] if session else None  # \u5982\u679c\u6709\u623f\u95f4\u5c31\u8fd4\u56de\u7c7b\u578b\uff0c\u5426\u5219\u8fd4\u56deNone\n\n    # ========== \u65e5\u5fd7\u89e3\u6790\u529f\u80fd ==========\n\n    def _parse_log_line(self, line: str) -&gt; Optional&#91;tuple]:\n        \"\"\"\n        \u89e3\u6790\u5355\u884c\u65e5\u5fd7\u5185\u5bb9\n\n        Args:\n            line: \u65e5\u5fd7\u884c\u5185\u5bb9\n\n        Returns:\n            tuple: (role, content) \u6216 None\n        \"\"\"\n        line = line.strip()  # 1. \u53bb\u6389\u9996\u5c3e\u7a7a\u767d\u5b57\u7b26\n        if not line:  # 2. \u5982\u679c\u662f\u7a7a\u884c\n            return None  # \u8fd4\u56deNone\n\n        # 3.\u5339\u914d\u683c\u5f0f\uff1a&#91;\u65f6\u95f4] \u7528\u6237: \u5185\u5bb9 \u6216 &#91;\u65f6\u95f4] AI\u540d\u79f0: \u5185\u5bb9\n        pattern = r'^\\&#91;(\\d{2}:\\d{2}:\\d{2})\\] (\u7528\u6237|' + re.escape(self.ai_name) + r'): (.+)$'\n        match = re.match(pattern, line)  # 4. \u5c1d\u8bd5\u5339\u914d\n\n        if match:  # 5. \u5982\u679c\u5339\u914d\u6210\u529f\n            time_str, speaker, content = match.groups()  # 6. \u63d0\u53d6\u4e09\u90e8\u5206\n            if speaker == \"\u7528\u6237\":  # 7. \u5224\u65ad\u8bf4\u8bdd\u8005\n                role = \"user\"  # \u7528\u6237\u8bf4\u7684\u8bdd\n            else:\n                role = \"assistant\"  # AI\u8bf4\u7684\u8bdd\n            return (role, content.strip())  # 8. \u8fd4\u56de\u89d2\u8272\u548c\u5185\u5bb9\n\n        return None  # 9. \u5339\u914d\u5931\u8d25\uff0c\u8fd4\u56deNone\n\n    def _is_message_start_line(self, line: str) -&gt; bool:\n        \"\"\"\n        \u5224\u65ad\u662f\u5426\u4e3a\u6d88\u606f\u5f00\u59cb\u884c\n\n        Args:\n            line: \u65e5\u5fd7\u884c\u5185\u5bb9\n\n        Returns:\n            bool: \u662f\u5426\u4e3a\u6d88\u606f\u5f00\u59cb\u884c\n        \"\"\"\n        line = line.strip()  # strip()\uff1a\u53bb\u6389\u5b57\u7b26\u4e32\u5f00\u5934\u548c\u7ed3\u5c3e\u7684\u7a7a\u767d\u5b57\u7b26\uff08\u7a7a\u683c\u3001\u5236\u8868\u7b26\u3001\u6362\u884c\u7b26\uff09\n        if not line:  # not line\uff1a\u5982\u679cline\u662f\u7a7a\u5b57\u7b26\u4e32\uff08\u957f\u5ea6\u4e3a0\uff09\n            return False  # \u7a7a\u884c\u5c31\u76f4\u63a5\u8fd4\u56deNone\uff0c\u4e0d\u5904\u7406\n\n        # \u5339\u914d\u683c\u5f0f\uff1a&#91;\u65f6\u95f4] \u7528\u6237: \u6216 &#91;\u65f6\u95f4] AI\u540d\u79f0:\n        pattern = r'^\\&#91;(\\d{2}:\\d{2}:\\d{2})\\] (\u7528\u6237|' + re.escape(self.ai_name) + r'):'\n        return bool(re.match(pattern, line))\n\n    def parse_log_file(self, log_file_path: str) -&gt; List&#91;Dict]:\n        \"\"\"\n        \u89e3\u6790\u5355\u4e2a\u65e5\u5fd7\u6587\u4ef6\uff0c\u63d0\u53d6\u5bf9\u8bdd\u5185\u5bb9\n        \u6309\u7167\u65e5\u5fd7\u8bb0\u5f55\u4ee3\u7801\u7684\u683c\u5f0f\uff1a\u6bcf\u8f6e\u5bf9\u8bdd\u5305\u542b\u7528\u6237\u6d88\u606f\u548cAI\u56de\u590d\uff0c\u752850\u4e2a-\u5206\u9694\n\n        Args:\n            log_file_path: \u65e5\u5fd7\u6587\u4ef6\u8def\u5f84\n\n        Returns:\n            List&#91;Dict]: \u5bf9\u8bdd\u6d88\u606f\u5217\u8868\uff0c\u683c\u5f0f\u4e3a&#91;{\"role\": \"user\/assistant\", \"content\": \"\u5185\u5bb9\"}]\n        \"\"\"\n        messages = &#91;]  # 1. \u51c6\u5907\u7a7a\u5217\u8868\u5b58\u653e\u7ed3\u679c\n\n        try:\n            # 2. \u6253\u5f00\u5e76\u8bfb\u53d6\u6587\u4ef6\n            with open(log_file_path, 'r', encoding='utf-8') as f:\n                content = f.read()\n\n            # \u4ee550\u4e2a-\u5206\u5272\u5bf9\u8bdd\u8f6e\u6b21\uff08\u6309\u7167\u65e5\u5fd7\u8bb0\u5f55\u4ee3\u7801\u7684\u683c\u5f0f\uff09\n            conversation_blocks = content.split('-' * 50)\n\n            for block in conversation_blocks:\n                block = block.strip()  # \u53bb\u6389\u7a7a\u767d\n                if not block:  # \u8df3\u8fc7\u7a7a\u5757\n                    continue\n\n                # \u89e3\u6790\u6bcf\u4e2a\u5bf9\u8bdd\u5757\u4e2d\u7684\u6d88\u606f\n                block_messages = self._parse_conversation_block(block)\n                messages.extend(block_messages)  # 6. \u6dfb\u52a0\u5230\u7ed3\u679c\u5217\u8868\n\n        except FileNotFoundError:\n            logger.debug(f\"\u65e5\u5fd7\u6587\u4ef6\u4e0d\u5b58\u5728: {log_file_path}\")\n        except Exception as e:\n            logger.error(f\"\u89e3\u6790\u65e5\u5fd7\u6587\u4ef6\u5931\u8d25 {log_file_path}: {e}\")\n\n        return messages  # 7. \u8fd4\u56de\u6240\u6709\u6d88\u606f\n\n    def _parse_conversation_block(self, block: str) -&gt; List&#91;Dict]:\n        \"\"\"\n        \u89e3\u6790\u5355\u4e2a\u5bf9\u8bdd\u5757\uff0c\u63d0\u53d6\u5176\u4e2d\u7684\u6240\u6709\u6d88\u606f\n        \u6bcf\u5757\u5305\u542b\u7528\u6237\u6d88\u606f\u548cAI\u56de\u590d\uff0c\u652f\u6301\u591a\u884c\u5185\u5bb9\n\n        Args:\n            block: \u5bf9\u8bdd\u5757\u5185\u5bb9\n\n        Returns:\n            List&#91;Dict]: \u6d88\u606f\u5217\u8868\n        \"\"\"\n        messages = &#91;]  # 1. \u5b58\u653e\u89e3\u6790\u51fa\u7684\u6d88\u606f\n        lines = block.split('\\n')  # 2. \u6309\u6362\u884c\u7b26\u5206\u5272\u6210\u591a\u884c\n        current_message = None  # 3. \u5f53\u524d\u6b63\u5728\u5904\u7406\u7684\u6d88\u606f\uff08None\u8868\u793a\u6ca1\u6709\uff09\n        current_content_lines = &#91;]  # 4. \u5f53\u524d\u6d88\u606f\u7684\u5185\u5bb9\u884c\u5217\u8868\n\n        # 5. \u9010\u884c\u5904\u7406\n        for line in lines:\n            line = line.rstrip('\\n\\r')  # 6.\u79fb\u9664\u884c\u5c3e\u6362\u884c\u7b26\uff0c\u4f46\u4fdd\u7559\u5185\u5bb9\u4e2d\u7684\u6362\u884c\n\n            # 7.\u68c0\u67e5\u662f\u5426\u4e3a\u6d88\u606f\u5f00\u59cb\u884c\n            if self._is_message_start_line(line):\n                # 8.\u4fdd\u5b58\u524d\u4e00\u4e2a\u6d88\u606f\n                if current_message is not None and current_content_lines:\n                    content = '\\n'.join(current_content_lines)  # \u5408\u5e76\u5185\u5bb9\u884c\n                    messages.append({\n                        \"role\": current_message&#91;\"role\"],\n                        \"content\": content\n                    })\n\n                # 9.\u5f00\u59cb\u65b0\u6d88\u606f\n                result = self._parse_log_line(line)  # \u89e3\u6790\u8fd9\u4e00\u884c\n                if result:  # \u5982\u679c\u89e3\u6790\u6210\u529f\n                    role, content = result\n                    current_message = {\"role\": role}  # \u8bb0\u5f55\u89d2\u8272\n                    current_content_lines = &#91;content] if content else &#91;]  # \u521d\u59cb\u5316\u5185\u5bb9\n                else:  # \u89e3\u6790\u5931\u8d25\n                    current_message = None\n                    current_content_lines = &#91;]\n\n            # 10.\u5982\u679c\u5f53\u524d\u6709\u6d3b\u8dc3\u6d88\u606f\uff0c\u4e14\u4e0d\u662f\u6d88\u606f\u5f00\u59cb\u884c\uff0c\u5219\u4f5c\u4e3a\u5185\u5bb9\u884c\u5904\u7406\n            elif current_message is not None:\n                # \u8df3\u8fc7\u5206\u9694\u7ebf\u548c\u7a7a\u884c\n                if line.strip() and not line.strip().startswith('---') and not line.strip().startswith('--'):\n                    current_content_lines.append(line  # \u6dfb\u52a0\u5230\u5f53\u524d\u6d88\u606f\u5185\u5bb9\n\n                    # 11.\u4fdd\u5b58\u6700\u540e\u4e00\u4e2a\u6d88\u606f\uff08\u5faa\u73af\u7ed3\u675f\u540e\uff09\n                    if current_message is not None and current_content_lines:\n                        content = '\\n'.join(current_content_lines)\n                    messages.append({\n                        \"role\": current_message&#91;\"role\"],\n                        \"content\": content\n                    })\n\n        return messages\n\n    def get_log_files_by_date(self, days: int = 3) -&gt; List&#91;str]:\n        \"\"\"\n        \u83b7\u53d6\u6700\u8fd1\u51e0\u5929\u7684\u65e5\u5fd7\u6587\u4ef6\u8def\u5f84\n\n        Args:\n            days: \u8981\u83b7\u53d6\u7684\u5929\u6570\n\n        Returns:\n            List&#91;str]: \u65e5\u5fd7\u6587\u4ef6\u8def\u5f84\u5217\u8868\uff0c\u6309\u65e5\u671f\u5012\u5e8f\u6392\u5217\n        \"\"\"\n        log_files = &#91;]\n        today = datetime.now()\n\n        for i in range(days):\n            date = today - timedelta(days=i)\n            date_str = date.strftime('%Y-%m-%d')\n            log_file = self.log_dir \/ f\"{date_str}.log\"\n\n            if log_file.exists():\n                log_files.append(str(log_file))\n\n        # \u6309\u65e5\u671f\u5012\u5e8f\u6392\u5217\uff08\u6700\u65b0\u7684\u5728\u524d\uff09\n        log_files.reverse()\n        return log_files\n\n    def load_recent_context(self, days: int = 3, max_messages: int = None) -&gt; List&#91;Dict]:\n        \"\"\"\n        \u52a0\u8f7d\u6700\u8fd1\u51e0\u5929\u7684\u5bf9\u8bdd\u4e0a\u4e0b\u6587\n\n        Args:\n            days: \u8981\u52a0\u8f7d\u7684\u5929\u6570\n            max_messages: \u6700\u5927\u6d88\u606f\u6570\u91cf\u9650\u5236\n\n        Returns:\n            List&#91;Dict]: \u5bf9\u8bdd\u6d88\u606f\u5217\u8868\n        \"\"\"\n        all_messages = &#91;]\n        log_files = self.get_log_files_by_date(days)\n\n        logger.info(f\"\u5f00\u59cb\u52a0\u8f7d\u6700\u8fd1 {days} \u5929\u7684\u65e5\u5fd7\u6587\u4ef6: {log_files}\")\n\n        for log_file in log_files:\n            messages = self.parse_log_file(log_file)\n            all_messages.extend(messages)\n            logger.debug(f\"\u4ece {log_file} \u52a0\u8f7d\u4e86 {len(messages)} \u6761\u6d88\u606f\")\n\n        # \u9650\u5236\u6d88\u606f\u6570\u91cf\n        if max_messages and len(all_messages) &gt; max_messages:\n            all_messages = all_messages&#91;-max_messages:]  # 7. \u53ea\u4fdd\u7559\u6700\u8fd1\u7684\u6d88\u606f\n            logger.info(f\"\u9650\u5236\u6d88\u606f\u6570\u91cf\u4e3a {max_messages} \u6761\")\n\n        logger.info(f\"\u603b\u5171\u52a0\u8f7d\u4e86 {len(all_messages)} \u6761\u5386\u53f2\u5bf9\u8bdd\")\n        return all_messages\n\n    def get_context_statistics(self, days: int = 7) -&gt; Dict:\n        \"\"\"\n        \u83b7\u53d6\u4e0a\u4e0b\u6587\u7edf\u8ba1\u4fe1\u606f\n\n        Args:\n            days: \u7edf\u8ba1\u5929\u6570\n\n        Returns:\n            Dict: \u7edf\u8ba1\u4fe1\u606f\n        \"\"\"\n        log_files = self.get_log_files_by_date(days)\n        total_messages = 0  # 2. \u521d\u59cb\u5316\u8ba1\u6570\u5668\n        user_messages = 0\n        assistant_messages = 0\n\n        # 3. \u904d\u5386\u6bcf\u4e2a\u6587\u4ef6\n        for log_file in log_files:\n            messages = self.parse_log_file(log_file)  # 4. \u89e3\u6790\u6587\u4ef6\n            total_messages += len(messages)  # 5. \u7d2f\u52a0\u603b\u6d88\u606f\u6570\n\n            # 6. \u7edf\u8ba1\u7528\u6237\u548cAI\u6d88\u606f\u6570\u91cf\n            for msg in messages:\n                if msg&#91;\"role\"] == \"user\":\n                    user_messages += 1\n                else:\n                    assistant_messages += 1\n\n        return {\n            \"total_files\": len(log_files),  # \u6587\u4ef6\u6570\u91cf\n            \"total_messages\": total_messages,  # \u603b\u6d88\u606f\u6570\n            \"user_messages\": user_messages,  # \u7528\u6237\u6d88\u606f\u6570\n            \"assistant_messages\": assistant_messages,  # AI\u6d88\u606f\u6570\n            \"days_covered\": days  # \u7edf\u8ba1\u5929\u6570\n        }\n\n    def save_conversation_log(self, user_message: str, assistant_message: str, dev_mode: bool = False):\n        \"\"\"\n        \u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\u5230\u6587\u4ef6\n\n        Args:\n            user_message: \u7528\u6237\u6d88\u606f\n            assistant_message: \u52a9\u624b\u56de\u590d\n            dev_mode: \u662f\u5426\u4e3a\u5f00\u53d1\u8005\u6a21\u5f0f\uff08\u5f00\u53d1\u8005\u6a21\u5f0f\u4e0d\u4fdd\u5b58\u65e5\u5fd7\uff09\n        \"\"\"\n        if dev_mode:\n            return  # \u5f00\u53d1\u8005\u6a21\u5f0f\u4e0d\u5199\u65e5\u5fd7\n\n        try:\n            from datetime import datetime\n            import os\n\n            # \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\n            now = datetime.now()\n            date_str = now.strftime('%Y-%m-%d')\n            time_str = now.strftime('%H:%M:%S')\n\n            # \u786e\u4fdd\u65e5\u5fd7\u76ee\u5f55\u5b58\u5728\n            log_dir = str(self.log_dir)\n            if not os.path.exists(log_dir):\n                os.makedirs(log_dir, exist_ok=True)  # \u521b\u5efa\u76ee\u5f55\uff08\u5982\u679c\u4e0d\u5b58\u5728\uff09\n                logger.info(f\"\u5df2\u521b\u5efa\u65e5\u5fd7\u76ee\u5f55: {log_dir}\")\n\n            # \u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\n            log_file = os.path.join(log_dir, f\"{date_str}.log\")\n            with open(log_file, 'a', encoding='utf-8') as f:\n                f.write(f\"&#91;{time_str}] \u7528\u6237: {user_message}\\n\")  # \u7528\u6237\u6d88\u606f\n                f.write(f\"&#91;{time_str}] {self.ai_name}: {assistant_message}\\n\")  # AI\u56de\u590d\n                f.write(\"-\" * 50 + \"\\n\")  # \u5206\u9694\u7ebf\n\n            logger.debug(f\"\u5df2\u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\u5230: {log_file}\")\n\n        except Exception as e:\n            logger.error(f\"\u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\u5931\u8d25: {e}\")\n\n    def save_conversation_and_logs(self, session_id: str, user_message: str, assistant_response: str):\n        \"\"\"\u7edf\u4e00\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\u4e0e\u65e5\u5fd7 - \u6574\u5408\u91cd\u590d\u903b\u8f91\"\"\"\n        try:\n            # \u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\u5230\u6d88\u606f\u7ba1\u7406\u5668\n            self.add_message(session_id, \"user\", user_message)\n            self.add_message(session_id, \"assistant\", assistant_response)\n\n            # \u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\u5230\u6587\u4ef6\n            self.save_conversation_log(\n                user_message,\n                assistant_response,\n                dev_mode=False  # \u5f00\u53d1\u8005\u6a21\u5f0f\u5df2\u7981\u7528\n            )\n        except Exception as e:\n            logger.error(f\"\u4fdd\u5b58\u5bf9\u8bdd\u4e0e\u65e5\u5fd7\u5931\u8d25: {e}\")\n\n    def trigger_background_analysis(self, session_id: str):\n        \"\"\"\u7edf\u4e00\u89e6\u53d1\u540e\u53f0\u610f\u56fe\u5206\u6790 - \u6574\u5408\u91cd\u590d\u903b\u8f91\"\"\"\n        try:\n            # \u68c0\u67e5\u662f\u5426\u5df2\u7ecf\u6709\u5206\u6790\u5728\u8fdb\u884c\u4e2d\n            # \u4f7f\u7528analysis_in_progress\u5b57\u5178\u9632\u6b62\u91cd\u590d\u5206\u6790\uff1a\n            if self.analysis_in_progress.get(session_id):  # \u68c0\u67e5\u662f\u5426\u5df2\u5728\u5206\u6790\u4e2d\n                logger.info(f\"&#91;\u535a\u5f08\u8bba] \u4f1a\u8bdd {session_id} \u5df2\u6709\u610f\u56fe\u5206\u6790\u5728\u8fdb\u884c\u4e2d\uff0c\u8df3\u8fc7\u91cd\u590d\u89e6\u53d1\")\n                return\n\n            # \u6807\u8bb0\u5206\u6790\u5f00\u59cb\n            self.analysis_in_progress&#91;session_id] = True\n\n            import asyncio\n            from system.background_analyzer import get_background_analyzer\n            from system.config import config\n            background_analyzer = get_background_analyzer()\n\n            # \u6839\u636e\u914d\u7f6e\u83b7\u53d6\u610f\u56fe\u5206\u6790\u8f6e\u6570\uff0c\u9ed8\u8ba43\u8f6e\n            intent_rounds = getattr(config.api, 'intent_analysis_rounds', 3)\n            max_messages = intent_rounds * 2  # \u6bcf\u8f6e\u5305\u542b\u7528\u6237\u548c\u52a9\u624b\u5404\u4e00\u6761\u6d88\u606f\n\n            recent_messages = self.get_recent_messages(session_id, count=max_messages)\n            logger.info(f\"&#91;\u535a\u5f08\u8bba] \u5206\u6790\u6700\u8fd1 {intent_rounds} \u8f6e\u5bf9\u8bdd\uff0c\u5171 {len(recent_messages)} \u6761\u6d88\u606f\")\n\n            # \u5f02\u6b65\u6267\u884c\u5206\u6790\u4efb\u52a1\n            async def _execute_analysis():\n                try:\n                    await background_analyzer.analyze_intent_async(recent_messages, session_id)\n                finally:\n                    # \u65e0\u8bba\u6210\u529f\u4e0e\u5426\uff0c\u90fd\u6e05\u9664\u5206\u6790\u72b6\u6001\n                    self.analysis_in_progress&#91;session_id] = False\n                    logger.info(f\"&#91;\u535a\u5f08\u8bba] \u4f1a\u8bdd {session_id} \u610f\u56fe\u5206\u6790\u5b8c\u6210\uff0c\u72b6\u6001\u5df2\u6e05\u9664\")\n\n            asyncio.create_task(_execute_analysis())\n        except Exception as e:\n            # \u53d1\u751f\u5f02\u5e38\u65f6\u4e5f\u8981\u6e05\u9664\u5206\u6790\u72b6\u6001\n            self.analysis_in_progress&#91;session_id] = False\n            logger.error(f\"\u540e\u53f0\u610f\u56fe\u5206\u6790\u89e6\u53d1\u5931\u8d25: {e}\")\n\n    def get_all_sessions_api(self):\n        \"\"\"\u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\u4fe1\u606f - API\u63a5\u53e3\"\"\"\n        try:\n            # \u6e05\u7406\u8fc7\u671f\u4f1a\u8bdd\n            self.cleanup_old_sessions()\n\n            # \u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\u4fe1\u606f\n            sessions_info = self.get_all_sessions_info()\n\n            return {\n                \"status\": \"success\",  # \u72b6\u6001\n                \"sessions\": sessions_info,  # \u4f1a\u8bdd\u4fe1\u606f\n                \"total_sessions\": len(sessions_info)  # \u4f1a\u8bdd\u603b\u6570\n            }\n        except Exception as e:\n            logger.error(f\"\u83b7\u53d6\u4f1a\u8bdd\u4fe1\u606f\u9519\u8bef: {e}\")\n            raise Exception(f\"\u83b7\u53d6\u4f1a\u8bdd\u4fe1\u606f\u5931\u8d25: {str(e)}\")\n\n    def get_session_detail_api(self, session_id: str):\n        \"\"\"\u83b7\u53d6\u6307\u5b9a\u4f1a\u8bdd\u7684\u8be6\u7ec6\u4fe1\u606f - API\u63a5\u53e3\"\"\"\n        try:\n            session_info = self.get_session_info(session_id)\n            if not session_info:\n                raise Exception(\"\u4f1a\u8bdd\u4e0d\u5b58\u5728\")\n\n            return {\n                \"status\": \"success\",\n                \"session_id\": session_id,\n                \"session_info\": session_info,\n                \"messages\": self.get_messages(session_id),\n                \"conversation_rounds\": session_info&#91;\"conversation_rounds\"]\n            }\n        except Exception as e:\n            logger.error(f\"\u83b7\u53d6\u4f1a\u8bdd\u8be6\u60c5\u9519\u8bef: {e}\")\n            raise Exception(f\"\u83b7\u53d6\u4f1a\u8bdd\u8be6\u60c5\u5931\u8d25: {str(e)}\")\n\n    def delete_session_api(self, session_id: str):\n        \"\"\"\u5220\u9664\u6307\u5b9a\u4f1a\u8bdd - API\u63a5\u53e3\"\"\"\n        try:\n            success = self.delete_session(session_id)\n            if success:\n                return {\n                    \"status\": \"success\",\n                    \"message\": f\"\u4f1a\u8bdd {session_id} \u5df2\u5220\u9664\"\n                }\n            else:\n                raise Exception(\"\u4f1a\u8bdd\u4e0d\u5b58\u5728\")\n        except Exception as e:\n            logger.error(f\"\u5220\u9664\u4f1a\u8bdd\u9519\u8bef: {e}\")\n            raise Exception(f\"\u5220\u9664\u4f1a\u8bdd\u5931\u8d25: {str(e)}\")\n\n    def clear_all_sessions_api(self):\n        \"\"\"\u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd - API\u63a5\u53e3\"\"\"\n        try:\n            count = self.clear_all_sessions()\n            return {\n                \"status\": \"success\",\n                \"message\": f\"\u5df2\u6e05\u7a7a {count} \u4e2a\u4f1a\u8bdd\"\n            }\n        except Exception as e:\n            logger.error(f\"\u6e05\u7a7a\u4f1a\u8bdd\u9519\u8bef: {e}\")\n            raise Exception(f\"\u6e05\u7a7a\u4f1a\u8bdd\u5931\u8d25: {str(e)}\")\n\n\n# \u5168\u5c40\u6d88\u606f\u7ba1\u7406\u5668\u5b9e\u4f8b\nmessage_manager = MessageManager()\n\n# =====MessageManager\u529f\u80fd\u5730\u56fe======\n'''\nMessageManager\n\u251c\u2500\u2500 \u521d\u59cb\u5316\u914d\u7f6e\n\u251c\u2500\u2500 \u4f1a\u8bdd\u7ba1\u7406\n\u2502   \u251c\u2500\u2500 create_session() - \u521b\u5efa\u4f1a\u8bdd\n\u2502   \u251c\u2500\u2500 get_session() - \u83b7\u53d6\u4f1a\u8bdd\n\u2502   \u251c\u2500\u2500 delete_session() - \u5220\u9664\u4f1a\u8bdd\n\u2502   \u251c\u2500\u2500 clear_all_sessions() - \u6e05\u7a7a\u6240\u6709\n\u2502   \u2514\u2500\u2500 cleanup_old_sessions() - \u6e05\u7406\u8fc7\u671f\n\u251c\u2500\u2500 \u6d88\u606f\u7ba1\u7406\n\u2502   \u251c\u2500\u2500 add_message() - \u6dfb\u52a0\u6d88\u606f\n\u2502   \u251c\u2500\u2500 get_messages() - \u83b7\u53d6\u6240\u6709\u6d88\u606f\n\u2502   \u251c\u2500\u2500 get_recent_messages() - \u83b7\u53d6\u6700\u8fd1\u6d88\u606f\n\u2502   \u251c\u2500\u2500 build_conversation_messages() - \u6784\u5efa\u5bf9\u8bdd\u5305\n\u2502   \u2514\u2500\u2500 build_conversation_messages_from_memory() - \u4ece\u5185\u5b58\u6784\u5efa\n\u251c\u2500\u2500 \u65e5\u5fd7\u7ba1\u7406\n\u2502   \u251c\u2500\u2500 parse_log_file() - \u89e3\u6790\u65e5\u5fd7\u6587\u4ef6\n\u2502   \u251c\u2500\u2500 load_recent_context() - \u52a0\u8f7d\u5386\u53f2\u4e0a\u4e0b\u6587\n\u2502   \u251c\u2500\u2500 save_conversation_log() - \u4fdd\u5b58\u65e5\u5fd7\n\u2502   \u2514\u2500\u2500 save_conversation_and_logs() - \u7edf\u4e00\u4fdd\u5b58\n\u251c\u2500\u2500 \u7edf\u8ba1\u5206\u6790\n\u2502   \u251c\u2500\u2500 get_session_info() - \u4f1a\u8bdd\u4fe1\u606f\n\u2502   \u251c\u2500\u2500 get_all_sessions_info() - \u6240\u6709\u4f1a\u8bdd\u4fe1\u606f\n\u2502   \u251c\u2500\u2500 get_context_statistics() - \u4e0a\u4e0b\u6587\u7edf\u8ba1\n\u2502   \u2514\u2500\u2500 get_agent_type()\/set_agent_type() - \u4ee3\u7406\u7c7b\u578b\n\u251c\u2500\u2500 \u540e\u53f0\u5904\u7406\n\u2502   \u2514\u2500\u2500 trigger_background_analysis() - \u89e6\u53d1\u540e\u53f0\u5206\u6790\n\u251c\u2500\u2500 API\u63a5\u53e3\n\u2502   \u251c\u2500\u2500 get_all_sessions_api() - \u6240\u6709\u4f1a\u8bddAPI\n\u2502   \u251c\u2500\u2500 get_session_detail_api() - \u4f1a\u8bdd\u8be6\u60c5API\n\u2502   \u251c\u2500\u2500 delete_session_api() - \u5220\u9664\u4f1a\u8bddAPI\n\u2502   \u2514\u2500\u2500 clear_all_sessions_api() - \u6e05\u7a7a\u6240\u6709API\n\u2514\u2500\u2500 \u8f85\u52a9\u65b9\u6cd5\uff08\u4ee5_\u5f00\u5934\uff09\n    \u251c\u2500\u2500 _parse_log_line() - \u89e3\u6790\u65e5\u5fd7\u884c\n    \u251c\u2500\u2500 _is_message_start_line() - \u5224\u65ad\u6d88\u606f\u5f00\u59cb\n    \u2514\u2500\u2500 _parse_conversation_block() - \u89e3\u6790\u5bf9\u8bdd\u5757\n'''\n\n# ========\u5e38\u89c1\u7684\u7f16\u7a0b\u8303\u5f0f\/\u6a21\u5f0f\u603b\u7ed3=========\n# 1. \u521d\u59cb\u5316-\u5904\u7406-\u6e05\u7406\u6a21\u5f0f\n# \u8fd9\u4e2a\u6a21\u5f0f\u5728\u4ee3\u7801\u4e2d\u53cd\u590d\u51fa\u73b0\uff1a\n'''\ndef \u67d0\u4e2a\u51fd\u6570():\n    # 1. \u521d\u59cb\u5316\u9636\u6bb5\n    \u7ed3\u679c\u5bb9\u5668 = &#91;]  # \u6216 {}\n    \u4e34\u65f6\u53d8\u91cf = None\n\n    # 2. \u5904\u7406\u9636\u6bb5\n    for \u6bcf\u4e2a\u9879\u76ee in \u6570\u636e\u6e90:\n        # \u5904\u7406\u903b\u8f91\n        if \u6761\u4ef6:\n            \u7ed3\u679c\u5bb9\u5668.append(\u5904\u7406\u7ed3\u679c)\n\n    # 3. \u6e05\u7406\/\u8fd4\u56de\u9636\u6bb5\n    return \u7ed3\u679c\u5bb9\u5668\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\n  parse_log_file()\uff1a\u521d\u59cb\u5316messages\u5217\u8868\uff0c\u9010\u5757\u5904\u7406\uff0c\u8fd4\u56de\u7ed3\u679c\n  load_recent_context()\uff1a\u521d\u59cb\u5316all_messages\uff0c\u9010\u4e2a\u6587\u4ef6\u5904\u7406\uff0c\u8fd4\u56de\u7ed3\u679c\n  _parse_conversation_block()\uff1a\u521d\u59cb\u5316\u5404\u79cd\u53d8\u91cf\uff0c\u9010\u884c\u5904\u7406\uff0c\u8fd4\u56de\u7ed3\u679c\n\n\u4e3a\u4ec0\u4e48\u8fd9\u6837\u8bbe\u8ba1\uff1f\n  \u6e05\u6670\uff1a\u4e09\u4e2a\u9636\u6bb5\u5206\u660e\n  \u53ef\u7ef4\u62a4\uff1a\u6bcf\u4e2a\u9636\u6bb5\u804c\u8d23\u660e\u786e\n  \u53ef\u6d4b\u8bd5\uff1a\u53ef\u4ee5\u5355\u72ec\u6d4b\u8bd5\u6bcf\u4e2a\u9636\u6bb5\n'''\n# 2. \u6807\u8bb0-\u5904\u7406-\u6e05\u9664\u6a21\u5f0f\uff08\u72b6\u6001\u7ba1\u7406\uff09\n'''\ndef \u6709\u72b6\u6001\u5904\u7406\u7684\u51fd\u6570():\n    # 1. \u6807\u8bb0\u5f00\u59cb\n    \u6807\u8bb0\u5b57\u5178&#91;\u952e] = True\n\n    try:\n        # 2. \u6838\u5fc3\u5904\u7406\n        \u590d\u6742\u64cd\u4f5c()\n    finally:\n        # 3. \u6e05\u9664\u6807\u8bb0\uff08\u65e0\u8bba\u5982\u4f55\u90fd\u6267\u884c\uff09\n        \u6807\u8bb0\u5b57\u5178&#91;\u952e] = False\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\ndef trigger_background_analysis(self, session_id: str):\n    # \u6807\u8bb0\u5f00\u59cb\n    if self.analysis_in_progress.get(session_id):\n        return  # \u9632\u6b62\u91cd\u590d\n    self.analysis_in_progress&#91;session_id] = True\n\n    try:\n        # \u6838\u5fc3\u5904\u7406\n        await background_analyzer.analyze_intent_async(...)\n    finally:\n        # \u6e05\u9664\u6807\u8bb0\n        self.analysis_in_progress&#91;session_id] = False\n\n\u4e3a\u4ec0\u4e48\u8fd9\u6837\u8bbe\u8ba1\uff1f\n  \u9632\u91cd\u5165\uff1a\u9632\u6b62\u540c\u4e00\u4efb\u52a1\u88ab\u91cd\u590d\u6267\u884c\n  \u8d44\u6e90\u5b89\u5168\uff1a\u786e\u4fdd\u6807\u8bb0\u88ab\u6b63\u786e\u6e05\u7406\n  \u5f02\u5e38\u5b89\u5168\uff1a\u5373\u4f7f\u51fa\u9519\u4e5f\u80fd\u6e05\u7406\u72b6\u6001\n'''\n# 3. \u914d\u7f6e-\u9ed8\u8ba4\u503c\u6a21\u5f0f\n'''\ndef \u67d0\u4e2a\u9700\u8981\u914d\u7f6e\u7684\u51fd\u6570():\n    try:\n        # 1. \u5c1d\u8bd5\u83b7\u53d6\u5916\u90e8\u914d\u7f6e\n        from \u914d\u7f6e\u6a21\u5757 import \u914d\u7f6e\n        \u53c2\u6570 = \u914d\u7f6e.\u67d0\u4e2a\u503c\n    except ImportError:\n        # 2. \u5931\u8d25\u65f6\u4f7f\u7528\u9ed8\u8ba4\u503c\n        \u53c2\u6570 = \u9ed8\u8ba4\u503c\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\ndef __init__(self):\n    try:\n        from system.config import config\n        self.max_history_rounds = config.api.max_history_rounds\n    except ImportError:\n        self.max_history_rounds = 10  # \u9ed8\u8ba4\u503c\n\n\u4e3a\u4ec0\u4e48\u8fd9\u6837\u8bbe\u8ba1\uff1f\n  \u7075\u6d3b\u6027\uff1a\u53ef\u4ee5\u901a\u8fc7\u914d\u7f6e\u6587\u4ef6\u8c03\u6574\u884c\u4e3a\n  \u9c81\u68d2\u6027\uff1a\u914d\u7f6e\u7f3a\u5931\u65f6\u7a0b\u5e8f\u4ecd\u80fd\u8fd0\u884c\n  \u53ef\u90e8\u7f72\u6027\uff1a\u4e0d\u540c\u73af\u5883\u53ef\u4ee5\u7528\u4e0d\u540c\u914d\u7f6e\n'''\n# 4. \u5305\u88c5\u5668\u6a21\u5f0f\uff08API\u5c01\u88c5\uff09\n'''\ndef \u539f\u59cb\u51fd\u6570(\u53c2\u6570):\n    # \u539f\u59cb\u903b\u8f91\n    return \u7ed3\u679c\n\ndef \u5305\u88c5\u540e\u7684API\u51fd\u6570(\u53c2\u6570):\n    try:\n        # \u8c03\u7528\u539f\u59cb\u51fd\u6570\n        \u7ed3\u679c = \u539f\u59cb\u51fd\u6570(\u53c2\u6570)\n\n        # \u5305\u88c5\u6210\u6807\u51c6\u683c\u5f0f\n        return {\n            \"status\": \"success\",\n            \"data\": \u7ed3\u679c\n        }\n    except Exception as e:\n        # \u7edf\u4e00\u9519\u8bef\u5904\u7406\n        logger.error(...)\n        return {\n            \"status\": \"error\",\n            \"message\": str(e)\n        }\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\ndef delete_session(self, session_id: str) -&gt; bool:\n    # \u539f\u59cb\u903b\u8f91\n    if session_id in self.sessions:\n        del self.sessions&#91;session_id]\n        return True\n    return False\n\ndef delete_session_api(self, session_id: str):\n    # \u5305\u88c5\u540e\u7684API\n    try:\n        success = self.delete_session(session_id)\n        if success:\n            return {\"status\": \"success\", \"message\": f\"\u4f1a\u8bdd\u5df2\u5220\u9664\"}\n        else:\n            raise Exception(\"\u4f1a\u8bdd\u4e0d\u5b58\u5728\")\n    except Exception as e:\n        logger.error(...)\n        raise Exception(...)\n\n\u4e3a\u4ec0\u4e48\u8fd9\u6837\u8bbe\u8ba1\uff1f\n  \u63a5\u53e3\u7edf\u4e00\uff1a\u6240\u6709API\u8fd4\u56de\u76f8\u540c\u7ed3\u6784\n  \u9519\u8bef\u5904\u7406\u96c6\u4e2d\uff1a\u7edf\u4e00\u8bb0\u5f55\u65e5\u5fd7\u548c\u9519\u8bef\u683c\u5f0f\n  \u4e1a\u52a1\u903b\u8f91\u5206\u79bb\uff1a\u6838\u5fc3\u903b\u8f91\u548c\u63a5\u53e3\u903b\u8f91\u5206\u79bb\n'''\n# 5. \u904d\u5386-\u8fc7\u6ee4-\u6536\u96c6\u6a21\u5f0f\n'''\ndef \u5904\u7406\u96c6\u5408(\u6570\u636e\u96c6\u5408):\n    \u7ed3\u679c = &#91;]\n\n    for \u9879\u76ee in \u6570\u636e\u96c6\u5408:\n        # \u8fc7\u6ee4\u6761\u4ef6\n        if not \u6ee1\u8db3\u6761\u4ef6(\u9879\u76ee):\n            continue  # \u8df3\u8fc7\n\n        # \u5904\u7406\u903b\u8f91\n        \u5904\u7406\u540e\u7684\u9879\u76ee = \u5904\u7406\u51fd\u6570(\u9879\u76ee)\n\n        # \u6536\u96c6\u7ed3\u679c\n        \u7ed3\u679c.append(\u5904\u7406\u540e\u7684\u9879\u76ee)\n\n    return \u7ed3\u679c\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\ndef cleanup_old_sessions(self, max_age_hours: int = 24):\n    expired_sessions = &#91;]  # \u6536\u96c6\u7ed3\u679c\n\n    for session_id, session in self.sessions.items():  # \u904d\u5386\n        # \u8fc7\u6ee4\u6761\u4ef6\n        if current_time - session&#91;\"last_activity\"] &gt; max_age_hours * 3600:\n            # \u6536\u96c6\u7b26\u5408\u6761\u4ef6\u7684\n            expired_sessions.append(session_id)\n\n    # \u540e\u7eed\u5904\u7406\u6536\u96c6\u5230\u7684\u7ed3\u679c\n    for session_id in expired_sessions:\n        del self.sessions&#91;session_id]\n\n    return len(expired_sessions)\n'''\n# 6. \u72b6\u6001\u673a\u6a21\u5f0f\n'''\ndef \u72b6\u6001\u673a\u5904\u7406\u51fd\u6570(\u8f93\u5165\u6570\u636e):\n    \u5f53\u524d\u72b6\u6001 = None\n    \u5f53\u524d\u6570\u636e = &#91;]\n\n    for \u884c in \u8f93\u5165\u6570\u636e:\n        if \u662f\u72b6\u6001\u5f00\u59cb\u6807\u8bb0(\u884c):\n            # \u4fdd\u5b58\u4e4b\u524d\u7684\u72b6\u6001\u6570\u636e\n            if \u5f53\u524d\u72b6\u6001 and \u5f53\u524d\u6570\u636e:\n                \u4fdd\u5b58\u72b6\u6001\u6570\u636e(\u5f53\u524d\u72b6\u6001, \u5f53\u524d\u6570\u636e)\n\n            # \u8fdb\u5165\u65b0\u72b6\u6001\n            \u5f53\u524d\u72b6\u6001 = \u89e3\u6790\u72b6\u6001(\u884c)\n            \u5f53\u524d\u6570\u636e = &#91;]\n        elif \u5f53\u524d\u72b6\u6001 is not None:\n            # \u5728\u5f53\u524d\u72b6\u6001\u4e0b\u6536\u96c6\u6570\u636e\n            \u5f53\u524d\u6570\u636e.append(\u884c)\n\n    # \u5904\u7406\u6700\u540e\u7684\u72b6\u6001\n    if \u5f53\u524d\u72b6\u6001 and \u5f53\u524d\u6570\u636e:\n        \u4fdd\u5b58\u72b6\u6001\u6570\u636e(\u5f53\u524d\u72b6\u6001, \u5f53\u524d\u6570\u636e)\n\n\u5728\u4ee3\u7801\u4e2d\u7684\u4f53\u73b0\uff1a\ndef _parse_conversation_block(self, block: str):\n    current_message = None  # \u5f53\u524d\u72b6\u6001\n    current_content_lines = &#91;]  # \u5f53\u524d\u6570\u636e\n\n    for line in lines:\n        if self._is_message_start_line(line):  # \u72b6\u6001\u5207\u6362\n            # \u4fdd\u5b58\u524d\u4e00\u4e2a\u72b6\u6001\n            if current_message is not None and current_content_lines:\n                \u4fdd\u5b58\u6d88\u606f()\n\n            # \u8fdb\u5165\u65b0\u72b6\u6001\n            current_message = {\"role\": role}\n            current_content_lines = &#91;]\n        elif current_message is not None:  # \u72b6\u6001\u5185\u5904\u7406\n            current_content_lines.append(line)\n\n    # \u5904\u7406\u6700\u540e\u4e00\u4e2a\u72b6\u6001\n    if current_message is not None and current_content_lines:\n        \u4fdd\u5b58\u6d88\u606f()\n\n\u4e3a\u4ec0\u4e48\u8fd9\u6837\u8bbe\u8ba1\uff1f\n  \u5904\u7406\u590d\u6742\u7ed3\u6784\uff1a\u9002\u5408\u5904\u7406\u6709\u5c42\u6b21\u3001\u6709\u72b6\u6001\u7684\u6570\u636e\n  \u5185\u5b58\u9ad8\u6548\uff1a\u4e00\u6b21\u904d\u5386\u5b8c\u6210\u5904\u7406\n  \u903b\u8f91\u6e05\u6670\uff1a\u72b6\u6001\u8f6c\u6362\u660e\u786e\n'''\n# ========\u8fd9\u4e9b\u6a21\u5f0f\u80cc\u540e\u7684\u7f16\u7a0b\u601d\u60f3=========\n'''\n1. \u5206\u79bb\u5173\u6ce8\u70b9\uff08Separation of Concerns\uff09\n  \u521d\u59cb\u5316\u3001\u5904\u7406\u3001\u6e05\u7406\u5404\u53f8\u5176\u804c\n  \u4e1a\u52a1\u903b\u8f91\u548c\u9519\u8bef\u5904\u7406\u5206\u79bb\n  \u6570\u636e\u83b7\u53d6\u548c\u6570\u636e\u4f7f\u7528\u5206\u79bb\n2. \u9632\u5fa1\u5f0f\u7f16\u7a0b\uff08Defensive Programming\uff09\n  \u603b\u662f\u68c0\u67e5\u8f93\u5165\u6709\u6548\u6027\n  \u603b\u662f\u5904\u7406\u5f02\u5e38\u60c5\u51b5\n  \u603b\u662f\u6e05\u7406\u8d44\u6e90\n3. \u4e00\u6b21\u505a\u597d\u4e00\u4ef6\u4e8b\uff08Do One Thing Well\uff09\n  \u6bcf\u4e2a\u51fd\u6570\u53ea\u8d1f\u8d23\u4e00\u4e2a\u4e3b\u8981\u4efb\u52a1\n  \u590d\u6742\u4efb\u52a1\u5206\u89e3\u4e3a\u7b80\u5355\u6b65\u9aa4\n  \u901a\u8fc7\u7ec4\u5408\u5c0f\u51fd\u6570\u5b8c\u6210\u5927\u529f\u80fd\n4. \u4e0d\u8981\u91cd\u590d\u81ea\u5df1\uff08DRY - Don't Repeat Yourself\uff09\n  \u76f8\u4f3c\u7684\u903b\u8f91\u62bd\u8c61\u6210\u51fd\u6570\n  \u901a\u7528\u7684\u6a21\u5f0f\u5f62\u6210\u89c4\u8303\n  \u914d\u7f6e\u96c6\u4e2d\u7ba1\u7406\n'''\n# \u5982\u4f55\u5728\u4ee3\u7801\u4e2d\u8bc6\u522b\u8fd9\u4e9b\u6a21\u5f0f\uff1f\n'''\n\u770b\u53d8\u91cf\u540d\uff1a\n  result = &#91;] \u2192 \u6536\u96c6\u6a21\u5f0f\n  current_xxx = None \u2192 \u72b6\u6001\u673a\u6a21\u5f0f\n  is_xxx_in_progress \u2192 \u6807\u8bb0\u6a21\u5f0f\n\u770b\u4ee3\u7801\u7ed3\u6784\uff1a\n  try-except\u5305\u88f9 \u2192 \u5f02\u5e38\u5b89\u5168\u6a21\u5f0f\n  \u51fd\u6570\u5f00\u5934\u6709\u914d\u7f6e\u8bfb\u53d6 \u2192 \u914d\u7f6e\u6a21\u5f0f\n  \u8fd4\u56de\u6807\u51c6\u5b57\u5178\u7ed3\u6784 \u2192 API\u5305\u88c5\u6a21\u5f0f\n\u770b\u6ce8\u91ca\uff1a\n  \u6ce8\u91ca\u4e2d\u63d0\u5230\u7684\"\u72b6\u6001\"\u3001\"\u6807\u8bb0\"\u3001\"\u6536\u96c6\"\u7b49\u5173\u952e\u8bcd\n'''\n# \u5728\u5176\u4ed6\u4ee3\u7801\u4e2d\u5bfb\u627e\u6a21\u5f0f\n'''\n# \u5199\u4e00\u4e2a\u7b80\u5355\u7684\u904d\u5386-\u8fc7\u6ee4-\u6536\u96c6\u6a21\u5f0f\ndef get_even_numbers(numbers):\n    \"\"\"\u83b7\u53d6\u6240\u6709\u5076\u6570\"\"\"\n    result = &#91;]  # \u521d\u59cb\u5316\n\n    for num in numbers:  # \u904d\u5386\n        if num % 2 == 0:  # \u8fc7\u6ee4\n            result.append(num)  # \u6536\u96c6\n\n    return result  # \u8fd4\u56de\n\n# \u5199\u4e00\u4e2a\u7b80\u5355\u7684\u914d\u7f6e-\u9ed8\u8ba4\u503c\u6a21\u5f0f\ndef get_timeout():\n    try:\n        import settings\n        return settings.TIMEOUT\n    except ImportError:\n        return 30  # \u9ed8\u8ba4\u503c\n'''<\/code><\/pre>\n\n\n\n<p>api_server.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n\"\"\"\nNagaAgent API\u670d\u52a1\u5668\n\u63d0\u4f9bRESTful API\u63a5\u53e3\u8bbf\u95eeNagaAgent\u529f\u80fd\n\"\"\"\n\nimport asyncio  # \u5f02\u6b65\u7f16\u7a0b\u5de5\u5177\uff08\u8ba9\u7a0b\u5e8f\u53ef\u4ee5\u540c\u65f6\u505a\u591a\u4ef6\u4e8b\uff09\nimport json    # JSON\u6570\u636e\u5904\u7406\uff08\u50cf\u7ffb\u8bd1\u5668\uff0c\u628a\u6570\u636e\u53d8\u6210\u8ba1\u7b97\u673a\u80fd\u61c2\u7684\u6837\u5b50\uff09\nimport sys     # \u7cfb\u7edf\u76f8\u5173\u529f\u80fd\nimport traceback  # \u9519\u8bef\u8ffd\u8e2a\uff08\u7a0b\u5e8f\u51fa\u9519\u65f6\u544a\u8bc9\u6211\u4eec\u662f\u54ea\u91cc\u9519\u4e86\uff09\nimport os      # \u64cd\u4f5c\u7cfb\u7edf\u529f\u80fd\uff08\u6587\u4ef6\u3001\u6587\u4ef6\u5939\u64cd\u4f5c\uff09\nimport logging  # \u65e5\u5fd7\u8bb0\u5f55\uff08\u5c31\u50cf\u5199\u65e5\u8bb0\uff0c\u8bb0\u5f55\u7a0b\u5e8f\u505a\u4e86\u4ec0\u4e48\uff09\nimport uuid    # \u751f\u6210\u552f\u4e00ID\uff08\u7ed9\u6bcf\u6837\u4e1c\u897f\u4e00\u4e2a\u552f\u4e00\u7684\u8eab\u4efd\u8bc1\u53f7\uff09\nimport time    # \u65f6\u95f4\u76f8\u5173\u529f\u80fd\nimport threading  # \u591a\u7ebf\u7a0b\uff08\u8ba9\u7a0b\u5e8f\u53ef\u4ee5\u5206\u8eab\u505a\u4e0d\u540c\u7684\u4e8b\uff09\nfrom contextlib import asynccontextmanager  # \u5f02\u6b65\u4e0a\u4e0b\u6587\u7ba1\u7406\uff08\u8d44\u6e90\u7ba1\u7406\u5de5\u5177\uff09\nfrom typing import Dict, List, Optional, AsyncGenerator, Any  # \u7c7b\u578b\u63d0\u793a\uff08\u544a\u8bc9\u8ba1\u7b97\u673a\u53d8\u91cf\u662f\u4ec0\u4e48\u7c7b\u578b\uff09\n\n# \u5728\u5bfc\u5165\u5176\u4ed6\u6a21\u5757\u524d\u5148\u8bbe\u7f6eHTTP\u5e93\u65e5\u5fd7\u7ea7\u522b,\uff08\u8ba9\u7a0b\u5e8f\u4fdd\u6301\u5b89\u9759\uff09\nlogging.getLogger(\"httpcore.http11\").setLevel(logging.WARNING)\nlogging.getLogger(\"httpx\").setLevel(logging.WARNING)\nlogging.getLogger(\"httpcore.connection\").setLevel(logging.WARNING)\n\n# \u521b\u5efalogger\u5b9e\u4f8b\nlogger = logging.getLogger(__name__)\n\n# \u4ecenagaagent_core\u5de5\u5177\u5305\u62ff\u5de5\u5177\nfrom nagaagent_core.api import uvicorn  # \u7f51\u9875\u670d\u52a1\u5668\u5f15\u64ce\nfrom nagaagent_core.api import FastAPI, HTTPException, Request, UploadFile, File, Form # \u521b\u5efa\u7f51\u7ad9API\u7684\u5de5\u5177\nfrom nagaagent_core.api import CORSMiddleware   # \u8de8\u57df\u8d44\u6e90\u5171\u4eab\uff08\u8ba9\u4e0d\u540c\u7f51\u7ad9\u80fd\u4e92\u76f8\u8bbf\u95ee\uff09\nfrom nagaagent_core.api import StreamingResponse    # \u6d41\u5f0f\u54cd\u5e94\uff08\u50cf\u6c34\u7ba1\u4e00\u6837\u6301\u7eed\u4f20\u8f93\u6570\u636e\uff09\nfrom nagaagent_core.api import StaticFiles      # \u9759\u6001\u6587\u4ef6\u670d\u52a1\uff08\u56fe\u7247\u3001CSS\u7b49\uff09\nfrom pydantic import BaseModel                # \u6570\u636e\u9a8c\u8bc1\u5de5\u5177\uff08\u68c0\u67e5\u6570\u636e\u662f\u5426\u7b26\u5408\u8981\u6c42\uff09\nfrom nagaagent_core.core import aiohttp      # \u5f02\u6b65HTTP\u5ba2\u6237\u7aef\nimport shutil                # \u6587\u4ef6\u64cd\u4f5c\u5de5\u5177\nfrom pathlib import Path     # \u8def\u5f84\u5904\u7406\u5de5\u5177\n\n# \u6dfb\u52a0\u9879\u76ee\u6839\u76ee\u5f55\u5230Python\u8def\u5f84\uff08\u544a\u8bc9\u7a0b\u5e8f\u53bb\u54ea\u91cc\u627e\u4e1c\u897f\uff09,\u5c31\u50cf\u5728\u624b\u673a\u4e0a\u6dfb\u52a0\u4e00\u4e2a\u65b0\u7684\u6536\u85cf\u4f4d\u7f6e\uff0c\u4ee5\u540e\u627e\u4e1c\u897f\u66f4\u65b9\u4fbf\u3002\nsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n\n# \u6d41\u5f0f\u6587\u672c\u5904\u7406\u6a21\u5757\uff08\u4ec5\u7528\u4e8eTTS\uff09\nfrom .message_manager import message_manager  # \u5bfc\u5165\u7edf\u4e00\u7684\u6d88\u606f\u7ba1\u7406\u5668\n\nfrom .llm_service import get_llm_service  # \u5bfc\u5165LLM\u670d\u52a1\n\n# \u5bfc\u5165\u914d\u7f6e\u7cfb\u7edf\ntry:\n    from system.config import config, AI_NAME  # \u4f7f\u7528\u65b0\u7684\u914d\u7f6e\u7cfb\u7edf\n    from system.config import get_prompt  # \u5bfc\u5165\u63d0\u793a\u8bcd\u4ed3\u5e93\nexcept ImportError:\n    # \u5982\u679c\u627e\u4e0d\u5230\uff0c\u518d\u8c03\u6574\u4e00\u6b21\u8def\u5f84\u7136\u540e\u5bfc\u5165\n    import sys\n    import os\n    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n    from system.config import config, AI_NAME  # \u4f7f\u7528\u65b0\u7684\u914d\u7f6e\u7cfb\u7edf\n    from system.config import get_prompt  # \u5bfc\u5165\u63d0\u793a\u8bcd\u4ed3\u5e93\nfrom ui.utils.response_util import extract_message  # \u5bfc\u5165\u6d88\u606f\u63d0\u53d6\u5de5\u5177\n\n# \u5bf9\u8bdd\u6838\u5fc3\u529f\u80fd\u5df2\u96c6\u6210\u5230apiserver\n\n#1. \u4e24\u4e2a\u201c\u8f6c\u53d1\u201d\u51fd\u6570\n# \u7edf\u4e00\u540e\u53f0\u610f\u56fe\u5206\u6790\u89e6\u53d1\u51fd\u6570 - \u5df2\u6574\u5408\u5230message_manager\ndef _trigger_background_analysis(session_id: str):\n    \"\"\"\u7edf\u4e00\u89e6\u53d1\u540e\u53f0\u610f\u56fe\u5206\u6790 - \u59d4\u6258\u7ed9message_manager\"\"\"\n    message_manager.trigger_background_analysis(session_id)\n\n# \u7edf\u4e00\u4fdd\u5b58\u5bf9\u8bdd\u4e0e\u65e5\u5fd7\u51fd\u6570 - \u5df2\u6574\u5408\u5230message_manager\ndef _save_conversation_and_logs(session_id: str, user_message: str, assistant_response: str):\n    \"\"\"\u7edf\u4e00\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\u4e0e\u65e5\u5fd7 - \u59d4\u6258\u7ed9message_manager\"\"\"\n    message_manager.save_conversation_and_logs(session_id, user_message, assistant_response)\n#\u8fd9\u4e24\u4e2a\u51fd\u6570\u81ea\u5df1\u4e0d\u5e72\u6d3b\uff0c\u53ea\u662f\u201c\u4f20\u8bdd\u5458\u201d\u3002\u5b83\u4eec\u628a\u5de5\u4f5c\u4ea4\u7ed9message_manager\u53bb\u505a\u3002\n# \u56de\u8c03\u5de5\u5382\u7c7b\u5df2\u79fb\u9664 - \u529f\u80fd\u5df2\u6574\u5408\u5230streaming_tool_extractor\n\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    \"\"\"\u5e94\u7528\u751f\u547d\u5468\u671f\u7ba1\u7406\"\"\"\n    try:\n        print(\"&#91;INFO] \u6b63\u5728\u521d\u59cb\u5316API\u670d\u52a1\u5668...\")\n        # \u7a0b\u5e8f\u542f\u52a8\u65f6\u8981\u505a\u7684\u4e8b\n        # \u5bf9\u8bdd\u6838\u5fc3\u529f\u80fd\u5df2\u96c6\u6210\u5230apiserver\n        print(\"&#91;SUCCESS] API\u670d\u52a1\u5668\u521d\u59cb\u5316\u5b8c\u6210\")\n        yield\n    except Exception as e:\n        print(f\"&#91;ERROR] API\u670d\u52a1\u5668\u521d\u59cb\u5316\u5931\u8d25: {e}\")\n        traceback.print_exc()\n        sys.exit(1)\n    finally:  #\u5173\u5e97\u6e05\u7406\uff08finally\u90e8\u5206\uff09\n        print(\"&#91;INFO] \u6b63\u5728\u6e05\u7406\u8d44\u6e90...\")\n        # MCP\u670d\u52a1\u73b0\u5728\u7531mcpserver\u72ec\u7acb\u7ba1\u7406\uff0c\u65e0\u9700\u6e05\u7406\n\n# \u521b\u5efaFastAPI\u5e94\u7528\napp = FastAPI(\n    title=\"NagaAgent API\",\n    description=\"\u667a\u80fd\u5bf9\u8bdd\u52a9\u624bAPI\u670d\u52a1\",\n    version=\"4.0.0\",\n    lifespan=lifespan   # \u4f7f\u7528\u4e0a\u9762\u5b9a\u4e49\u7684\u751f\u547d\u5468\u671f\u7ba1\u7406\n)\n\n# \u914d\u7f6eCORS\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=&#91;\"*\"],  # \u751f\u4ea7\u73af\u5883\u5efa\u8bae\u9650\u5236\u5177\u4f53\u57df\u540d\n    allow_credentials=True,    # \u5141\u8bb8\u643a\u5e26\u51ed\u8bc1\n    allow_methods=&#91;\"*\"],       # \u5141\u8bb8\u6240\u6709HTTP\u65b9\u6cd5\n    allow_headers=&#91;\"*\"],       # \u5141\u8bb8\u6240\u6709\u8bf7\u6c42\u5934\n)\n\n# \u6302\u8f7d\u9759\u6001\u6587\u4ef6\nstatic_dir = os.path.join(os.path.dirname(__file__), \"static\")\napp.mount(\"\/static\", StaticFiles(directory=static_dir), name=\"static\")\n\n# \u8bf7\u6c42\u6a21\u578b\nclass ChatRequest(BaseModel):\n    message: str                         # \u7528\u6237\u53d1\u9001\u7684\u6d88\u606f\n    stream: bool = False                 # \u662f\u5426\u4f7f\u7528\u6d41\u5f0f\u4f20\u8f93\uff08\u9ed8\u8ba4\u5426\uff09\n    session_id: Optional&#91;str] = None     # \u4f1a\u8bddID\uff08\u53ef\u9009\uff09\n    use_self_game: bool = False          # \u662f\u5426\u4f7f\u7528\u81ea\u535a\u5f08\uff08\u6e38\u620f\u76f8\u5173\uff09\n    disable_tts: bool = False  # V17: \u652f\u6301\u7981\u7528\u670d\u52a1\u5668\u7aefTTS\uff08\u8bed\u97f3\u5408\u6210\uff09\n    return_audio: bool = False  # V19: \u652f\u6301\u8fd4\u56de\u97f3\u9891URL\u4f9b\u5ba2\u6237\u7aef\u64ad\u653e\n    skip_intent_analysis: bool = False  # \u65b0\u589e\uff1a\u8df3\u8fc7\u610f\u56fe\u5206\u6790\n\nclass ChatResponse(BaseModel):\n    response: str\n    session_id: Optional&#91;str] = None\n    status: str = \"success\"\n\n\n\nclass SystemInfoResponse(BaseModel):   #\u7cfb\u7edf\u4fe1\u606f\n    version: str\n    status: str\n    available_services: List&#91;str]\n    api_key_configured: bool\n\nclass FileUploadResponse(BaseModel):  #\u6587\u4ef6\u4e0a\u4f20\u54cd\u5e94\n    filename: str\n    file_path: str\n    file_size: int\n    file_type: str\n    upload_time: str\n    status: str = \"success\"\n    message: str = \"\u6587\u4ef6\u4e0a\u4f20\u6210\u529f\"\n\nclass DocumentProcessRequest(BaseModel):  #\u6587\u6863\u5904\u7406\u8bf7\u6c42\n    file_path: str\n    action: str = \"read\"  # read, analyze, summarize\n    session_id: Optional&#91;str] = None\n\n\n# API\u8def\u7531\n@app.get(\"\/\", response_model=Dict&#91;str, str])  #\u8bbf\u95ee\u6839\u8def\u5f84\u65f6\u8fd4\u56de\u57fa\u672c\u4fe1\u606f\u3002\nasync def root():\n    \"\"\"API\u6839\u8def\u5f84\"\"\"\n    return {\n        \"name\": \"NagaAgent API\",\n        \"version\": \"4.0.0\",\n        \"status\": \"running\",\n        \"docs\": \"\/docs\",\n    }\n\n@app.get(\"\/health\")\nasync def health_check():\n    \"\"\"\u5065\u5eb7\u68c0\u67e5\"\"\"\n    return {\n        \"status\": \"healthy\",\n        \"agent_ready\": True,\n        \"timestamp\": str(asyncio.get_event_loop().time())\n    }\n\n@app.get(\"\/system\/info\", response_model=SystemInfoResponse)\nasync def get_system_info():\n    \"\"\"\u83b7\u53d6\u7cfb\u7edf\u4fe1\u606f\"\"\"\n    \n    return SystemInfoResponse(\n        version=\"4.0.0\",\n        status=\"running\",\n        available_services=&#91;],  # MCP\u670d\u52a1\u73b0\u5728\u7531mcpserver\u72ec\u7acb\u7ba1\u7406\n        api_key_configured=bool(config.api.api_key and config.api.api_key != \"sk-placeholder-key-not-set\")\n    )\n\n@app.post(\"\/chat\", response_model=ChatResponse)\nasync def chat(request: ChatRequest):\n    \"\"\"\u666e\u901a\u5bf9\u8bdd\u63a5\u53e3 - \u4ec5\u5904\u7406\u7eaf\u6587\u672c\u5bf9\u8bdd\"\"\"\n'''\n1. \u63a5\u53e3\u5b9a\u4e49 - \u5c31\u50cf\u5f00\u4e86\u4e00\u4e2a\u804a\u5929\u7a97\u53e3\napp.post(\"\/chat\")\uff1a\u521b\u5efa\u4e00\u4e2aPOST\u8bf7\u6c42\u7684\u63a5\u53e3\uff0c\u5730\u5740\u662f\/chat\n\u5c31\u50cf\u5728\u7f51\u7ad9\u4e0a\u5f00\u4e86\u4e00\u4e2a\u804a\u5929\u7a97\u53e3\uff0c\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u7a97\u53e3\u53d1\u9001\u6d88\u606f\nresponse_model=ChatResponse\uff1a\u544a\u8bc9\u7a0b\u5e8f\u8fd4\u56de\u7684\u6570\u636e\u8981\u6309\u7167ChatResponse\u7684\u683c\u5f0f\u6765\nasync def chat\uff1a\u8fd9\u662f\u4e00\u4e2a\u5f02\u6b65\u51fd\u6570\uff0c\u53ef\u4ee5\u540c\u65f6\u5904\u7406\u591a\u4e2a\u7528\u6237\u7684\u804a\u5929\n'''\n\n    #\u5b89\u5168\u68c0\u67e5 - \u68c0\u67e5\u7528\u6237\u6709\u6ca1\u6709\u53d1\u9001\u7a7a\u6d88\u606f\n    if not request.message.strip():   #request.message.strip()\uff1a\u83b7\u53d6\u7528\u6237\u53d1\u9001\u7684\u6d88\u606f\uff0c\u5e76\u53bb\u6389\u4e24\u8fb9\u7684\u7a7a\u683c\n        #raise HTTPException\uff1a\u5c31\u629b\u51fa\u4e00\u4e2a\u9519\u8bef\uff0c\u544a\u8bc9\u7528\u6237\"\u6d88\u606f\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a\"\n        raise HTTPException(status_code=400, detail=\"\u6d88\u606f\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a\")  #status_code=400\uff1a400\u662fHTTP\u72b6\u6001\u7801\uff0c\u8868\u793a\"\u9519\u8bef\u7684\u8bf7\u6c42\"\n    \n    try:\n        # \u5206\u652f: \u542f\u7528\u535a\u5f08\u8bba\u6d41\u7a0b\uff08\u975e\u6d41\u5f0f\uff0c\u8fd4\u56de\u805a\u5408\u6587\u672c\uff09\n        if request.use_self_game:  #if request.use_self_game:\uff1a\u68c0\u67e5\u7528\u6237\u662f\u5426\u60f3\u4f7f\u7528\"\u535a\u5f08\u8bba\"\u6a21\u5f0f\n            # \u914d\u7f6e\u9879\u63a7\u5236\uff1a\u5931\u8d25\u65f6\u53ef\u8df3\u8fc7\u56de\u9000\u5230\u666e\u901a\u5bf9\u8bdd\n            # #\u4ece\u914d\u7f6e\u4e2d\u8bfb\u53d6\u4e24\u4e2a\u8bbe\u7f6e\uff1a1.skip_on_error\uff1a\u535a\u5f08\u8bba\u5931\u8d25\u65f6\u662f\u5426\u8df3\u8fc7\uff08\u9ed8\u8ba4\u662f\uff092.enabled\uff1a\u662f\u5426\u542f\u7528\u535a\u5f08\u8bba\uff08\u9ed8\u8ba4\u5426\uff09\n            #getattr\u662fPython\u51fd\u6570\uff0c\u5b89\u5168\u5730\u83b7\u53d6\u5bf9\u8c61\u7684\u5c5e\u6027\uff0c\u5982\u679c\u5c5e\u6027\u4e0d\u5b58\u5728\u5c31\u8fd4\u56de\u9ed8\u8ba4\u503c\n            skip_on_error = getattr(getattr(config, 'game', None), 'skip_on_error', True)  # \u517c\u5bb9\u65e0\u914d\u7f6e\u60c5\u51b5 #\n            enabled = getattr(getattr(config, 'game', None), 'enabled', False)  # \u63a7\u5236\u603b\u5f00\u5173 #\n            if enabled:\n                try:\n                    # \u5ef6\u8fdf\u5bfc\u5165\u4ee5\u907f\u514d\u542f\u52a8\u65f6\u5faa\u73af\u4f9d\u8d56 #\n                    from game.naga_game_system import NagaGameSystem  # \u535a\u5f08\u7cfb\u7edf\u5165\u53e3 #\n                    from game.core.models.config import GameConfig  # \u535a\u5f08\u7cfb\u7edf\u914d\u7f6e #\n                    # \u521b\u5efa\u7cfb\u7edf\u5e76\u6267\u884c\u7528\u6237\u95ee\u9898\u5904\u7406 #\n                    system = NagaGameSystem(GameConfig())\n                    system_response = await system.process_user_question(\n                        user_question=request.message,\n                        user_id=request.session_id or \"api_user\"\n                    )\n                    return ChatResponse(\n                        response=system_response.content,\n                        session_id=request.session_id,\n                        status=\"success\"\n                    )\n                except Exception as e:\n                    print(f\"&#91;WARNING] \u535a\u5f08\u8bba\u6d41\u7a0b\u5931\u8d25\uff0c\u5c06{ '\u56de\u9000\u5230\u666e\u901a\u5bf9\u8bdd' if skip_on_error else '\u8fd4\u56de\u9519\u8bef' }: {e}\")  # \u8fd0\u884c\u65f6\u8b66\u544a #\n                    if not skip_on_error:\n                        raise HTTPException(status_code=500, detail=f\"\u535a\u5f08\u8bba\u6d41\u7a0b\u5931\u8d25: {str(e)}\")\n                    # \u5426\u5219\u7ee7\u7eed\u8d70\u666e\u901a\u5bf9\u8bdd\u6d41\u7a0b #\n            # \u82e5\u672a\u542f\u7528\u6216\u88ab\u914d\u7f6e\u8df3\u8fc7\uff0c\u5219\u76f4\u63a5\u56de\u9000\u5230\u666e\u901a\u5bf9\u8bdd\u5206\u652f #\n\n        # \u83b7\u53d6\u6216\u521b\u5efa\u4f1a\u8bddID\n        session_id = message_manager.create_session(request.session_id)\n        \n        # \u6784\u5efa\u7cfb\u7edf\u63d0\u793a\u8bcd\uff08\u53ea\u4f7f\u7528\u5bf9\u8bdd\u98ce\u683c\u63d0\u793a\u8bcd\uff09\n        #get_prompt(\"conversation_style_prompt\")\uff1a\u4ece\u63d0\u793a\u8bcd\u4ed3\u5e93\u83b7\u53d6\"\u5bf9\u8bdd\u98ce\u683c\u63d0\u793a\u8bcd\"\n        system_prompt = get_prompt(\"conversation_style_prompt\")\n        \n        # \u4f7f\u7528\u6d88\u606f\u7ba1\u7406\u5668\u6784\u5efa\u5b8c\u6574\u7684\u5bf9\u8bdd\u6d88\u606f\uff08\u7eaf\u804a\u5929\uff0c\u4e0d\u89e6\u53d1\u5de5\u5177\uff09\n        messages = message_manager.build_conversation_messages(\n            session_id=session_id,\n            system_prompt=system_prompt,\n            current_message=request.message\n        )\n        \n        # \u4f7f\u7528\u6574\u5408\u540e\u7684LLM\u670d\u52a1\n        llm_service = get_llm_service()\n        response_text = await llm_service.chat_with_context(messages, config.api.temperature)\n        \n        # \u5904\u7406\u5b8c\u6210\n        # \u7edf\u4e00\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\u4e0e\u65e5\u5fd7\n        _save_conversation_and_logs(session_id, request.message, response_text)\n        #\u8c03\u7528\u4e4b\u524d\u5b9a\u4e49\u7684_save_conversation_and_logs\u51fd\u6570\n        #\u4fdd\u5b58\u7528\u6237\u6d88\u606f\u548cAI\u56de\u590d\u5230\u5bf9\u8bdd\u5386\u53f2\u4e2d\n        #\u5c31\u50cf\u628a\u8fd9\u6b21\u804a\u5929\u8bb0\u5f55\u5230\u804a\u5929\u8bb0\u5f55\u672c\u91cc\n\n        # \u5728\u7528\u6237\u6d88\u606f\u4fdd\u5b58\u5230\u5386\u53f2\u540e\u89e6\u53d1\u540e\u53f0\u610f\u56fe\u5206\u6790\uff08\u9664\u975e\u660e\u786e\u8df3\u8fc7\uff09\n        #\u8fd9\u662f\u540e\u53f0\u6084\u6084\u8fdb\u884c\u7684\uff0c\u4e0d\u4f1a\u5f71\u54cd\u5f53\u524d\u56de\u590d\n        if not request.skip_intent_analysis:\n            _trigger_background_analysis(session_id=session_id)\n\n        return ChatResponse(   #\u8fd4\u56de\u54cd\u5e94\u7ed9\u7528\u6237\n            response=extract_message(response_text) if response_text else response_text,\n            session_id=session_id,\n            status=\"success\"\n        )\n        '''\n        \u7406\u89e3\uff1a\n        \u628aAI\u7684\u56de\u590d\u5305\u88c5\u6210ChatResponse\u683c\u5f0f\u8fd4\u56de\n        extract_message(response_text)\uff1a\u53ef\u80fd\u5bf9\u56de\u590d\u505a\u6700\u540e\u7684\u5904\u7406\uff08\u6bd4\u5982\u63d0\u53d6\u5173\u952e\u90e8\u5206\uff09\n        \u5305\u542b\u4f1a\u8bddID\uff08\u8fd9\u6837\u7528\u6237\u4e0b\u6b21\u53ef\u4ee5\u7ee7\u7eed\u8fd9\u4e2a\u5bf9\u8bdd\uff09\n        \u72b6\u6001\u8bbe\u7f6e\u4e3a\"success\"\uff08\u6210\u529f\uff09\n        '''\n    #\u9519\u8bef\u5904\u7406 - \u5982\u679c\u4e00\u5207\u51fa\u9519\u4e86\u600e\u4e48\u529e\n    except Exception as e:\n        print(f\"\u5bf9\u8bdd\u5904\u7406\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=f\"\u5904\u7406\u5931\u8d25: {str(e)}\")\n    '''\n    \u5982\u679c\u4e0a\u9762\u7684\u4ee3\u7801\u6709\u4efb\u4f55\u9519\u8bef\uff0c\u5c31\u6267\u884c\u8fd9\u91cc\n    print(f\"\u5bf9\u8bdd\u5904\u7406\u9519\u8bef: {e}\")\uff1a\u5728\u63a7\u5236\u53f0\u6253\u5370\u9519\u8bef\u4fe1\u606f\n    traceback.print_exc()\uff1a\u6253\u5370\u8be6\u7ec6\u7684\u9519\u8bef\u5806\u6808\uff08\u77e5\u9053\u662f\u54ea\u4e00\u884c\u51fa\u9519\u4e86\uff09\n    raise HTTPException\uff1a\u544a\u8bc9\u7528\u6237\"\u5904\u7406\u5931\u8d25\"\uff0c\u5e76\u663e\u793a\u5177\u4f53\u9519\u8bef\n    '''\n# =========\u6d41\u7a0b\u56fe\u603b\u7ed3\u8fd9\u4e2a\u51fd\u6570\u7684\u5de5\u4f5c\u6d41\u7a0b\uff1a============\n'''\n\u5f00\u59cb\n  \u2193\n\u68c0\u67e5\u6d88\u606f\u662f\u5426\u4e3a\u7a7a \u2192 \u5982\u679c\u662f \u2192 \u8fd4\u56de\u9519\u8bef\n  \u2193\n\u68c0\u67e5\u662f\u5426\u4f7f\u7528\u535a\u5f08\u8bba\u6a21\u5f0f \u2192 \u5982\u679c\u662f \u2192 \u5c1d\u8bd5\u535a\u5f08\u8bba\u5904\u7406\n  \u2193                                     \u2193\n  \u2193                     \u6210\u529f\uff1f \u2192 \u662f \u2192 \u8fd4\u56de\u535a\u5f08\u8bba\u7ed3\u679c\n  \u2193                                     \u2193\n  \u2193                     \u5426 \u2192 \u914d\u7f6e\u8df3\u8fc7\uff1f \u2192 \u5426 \u2192 \u8fd4\u56de\u9519\u8bef\n  \u2193                                     \u2193\n  \u2193                                    \u662f\n  \u2193                                     \u2193\n\u8fdb\u5165\u666e\u901a\u5bf9\u8bdd\u6a21\u5f0f\n  \u2193\n\u83b7\u53d6\/\u521b\u5efa\u4f1a\u8bddID\n  \u2193\n\u83b7\u53d6\u5bf9\u8bdd\u98ce\u683c\u63d0\u793a\u8bcd\n  \u2193\n\u6784\u5efa\u5b8c\u6574\u5bf9\u8bdd\u6d88\u606f\uff08\u5386\u53f2+\u65b0\u6d88\u606f\uff09\n  \u2193\n\u8c03\u7528AI\u6a21\u578b\u751f\u6210\u56de\u590d\n  \u2193\n\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\n  \u2193\n\uff08\u53ef\u9009\uff09\u89e6\u53d1\u540e\u53f0\u610f\u56fe\u5206\u6790\n  \u2193\n\u8fd4\u56de\u6210\u529f\u54cd\u5e94\n  \u2193\n\u5982\u679c\u6709\u4efb\u4f55\u9519\u8bef \u2192 \u6253\u5370\u9519\u8bef\u5e76\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\n'''\n\n# ======\u5173\u952e\u51fd\u6570\u603b\u7ed3\uff1a==========\n'''\n1.\u6d88\u606f\u7ba1\u7406\u5668\u76f8\u5173\uff1a\n    message_manager.create_session() - \u521b\u5efa\u4f1a\u8bdd\n    message_manager.build_conversation_messages() - \u6784\u5efa\u5bf9\u8bdd\u6d88\u606f\n2.\u914d\u7f6e\u76f8\u5173\uff1a\n   get_prompt() - \u83b7\u53d6\u63d0\u793a\u8bcd\n   config.api.temperature - \u83b7\u53d6\u6e29\u5ea6\u53c2\u6570\n3.AI\u670d\u52a1\u76f8\u5173\uff1a\n  get_llm_service() - \u83b7\u53d6AI\u670d\u52a1\n  llm_service.chat_with_context() - \u4e0eAI\u5bf9\u8bdd\n4.\u5de5\u5177\u51fd\u6570\uff1a\n  extract_message() - \u63d0\u53d6\u6d88\u606f\uff08\u53ef\u80fd\u6765\u81ea\u53e6\u4e00\u4e2a\u6a21\u5757\uff09\n  _save_conversation_and_logs() - \u4fdd\u5b58\u5bf9\u8bdd\uff08\u8c03\u7528\u6d88\u606f\u7ba1\u7406\u5668\uff09\n  _trigger_background_analysis() - \u89e6\u53d1\u610f\u56fe\u5206\u6790\uff08\u8c03\u7528\u6d88\u606f\u7ba1\u7406\u5668\uff09\n'''\n\n#\u6d41\u5f0f\u804a\u5929\u63a5\u53e3\uff08\/chat\/stream\uff09,\u8fd9\u6bb5\u4ee3\u7801\u6bd4\u4e4b\u524d\u7684\u66f4\u590d\u6742\u4e00\u4e9b\uff0c\u56e0\u4e3a\u5b83\u6d89\u53ca\u5230\u6d41\u5f0f\u4f20\u8f93\uff08\u50cf\u6c34\u7ba1\u4e00\u6837\u4e00\u70b9\u70b9\u8f93\u9001\u6570\u636e\uff09\u548c\u8bed\u97f3\u5904\u7406\u3002\n@app.post(\"\/chat\/stream\")\nasync def chat_stream(request: ChatRequest):\n    \"\"\"\u6d41\u5f0f\u5bf9\u8bdd\u63a5\u53e3 - \u6d41\u5f0f\u6587\u672c\u5904\u7406\u4ea4\u7ed9streaming_tool_extractor\u7528\u4e8eTTS\"\"\"\n'''\n\u7406\u89e3\uff1a\n  \u521b\u5efa\u4e00\u4e2a\u65b0\u7684POST\u63a5\u53e3\uff0c\u5730\u5740\u662f\/chat\/stream\n  \u4e13\u95e8\u5904\u7406\u6d41\u5f0f\u5bf9\u8bdd\uff08\u6587\u5b57\u4e00\u4e2a\u5b57\u4e00\u4e2a\u5b57\u5730\u663e\u793a\uff0c\u800c\u4e0d\u662f\u4e00\u6b21\u6027\u663e\u793a\u5b8c\u6574\u56de\u590d\uff09\n  \u8fd8\u4f1a\u5904\u7406\u8bed\u97f3\u5408\u6210\uff08TTS - Text To Speech\uff0c\u6587\u5b57\u8f6c\u8bed\u97f3\uff09\n\u6bd4\u55bb\uff1a\u8fd9\u5c31\u50cf\u4e24\u4e2a\u6c34\u7ba1\uff1a\n  \u666e\u901a\u804a\u5929\u63a5\u53e3\uff1a\u4e00\u6876\u6c34\u4e00\u6b21\u6027\u5012\u7ed9\u4f60\n  \u6d41\u5f0f\u804a\u5929\u63a5\u53e3\uff1a\u6c34\u7ba1\u4e00\u70b9\u70b9\u6d41\u6c34\u7ed9\u4f60\n'''\n\n    #2. \u68c0\u67e5\u7a7a\u6d88\u606f,\u548c\u4e4b\u524d\u4e00\u6837\uff0c\u5148\u68c0\u67e5\u7528\u6237\u662f\u4e0d\u662f\u53d1\u4e86\u7a7a\u6d88\u606f\u3002\n    if not request.message.strip():\n        raise HTTPException(status_code=400, detail=\"\u6d88\u606f\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a\")\n\n    #3. \u6838\u5fc3\uff1a\u521b\u5efa\u6d41\u5f0f\u54cd\u5e94\u751f\u6210\u5668\n    '''\n    \u91cd\u8981\u6982\u5ff5\uff1a\n       generate_response\u662f\u4e00\u4e2a\u751f\u6210\u5668\u51fd\u6570\uff08AsyncGenerator\uff09\n       \u5b83\u4e0d\u4f1a\u4e00\u6b21\u6027\u8fd4\u56de\u6240\u6709\u6570\u636e\uff0c\u800c\u662f\u7528yield\u4e00\u70b9\u70b9\u4ea7\u751f\u6570\u636e\n       complete_text\uff1a\u7528\u6765\u7d2f\u79efAI\u7684\u6240\u6709\u56de\u590d\u6587\u5b57\uff0c\u540e\u9762\u53ef\u80fd\u7528\u6765\u751f\u6210\u8bed\u97f3\n    '''\n    async def generate_response() -> AsyncGenerator&#91;str, None]:\n        complete_text = \"\"  # V19: \u7528\u4e8e\u7d2f\u79ef\u5b8c\u6574\u6587\u672c\u4ee5\u751f\u6210\u97f3\u9891\n        try:\n            # \u83b7\u53d6\u6216\u521b\u5efa\u4f1a\u8bddID,\u4e3b\u8981\u903b\u8f91\u5f00\u59cb\n            session_id = message_manager.create_session(request.session_id)\n            \n            # \u53d1\u9001\u4f1a\u8bddID\u4fe1\u606f\n            yield f\"data: session_id: {session_id}\\n\\n\"\n            \n            # \u6ce8\u610f\uff1a\u8fd9\u91cc\u4e0d\u89e6\u53d1\u540e\u53f0\u5206\u6790\uff0c\u5c06\u5728\u5bf9\u8bdd\u4fdd\u5b58\u540e\u89e6\u53d1\n            '''\n            \u7406\u89e3\uff1a\n              \u521b\u5efa\u4f1a\u8bddID\uff08\u548c\u4e4b\u524d\u4e00\u6837\uff09\n              yield f\"data: session_id: {session_id}\\n\\n\"\uff1a\u8fd9\u662f\u7b2c\u4e00\u6b21\u53d1\u9001\u6570\u636e\u7ed9\u5ba2\u6237\u7aef\n              \u683c\u5f0f\u662fdata: session_id: xxx\uff0c\u8fd9\u662f\u4e00\u79cd\u7279\u6b8a\u7684SSE\uff08Server-Sent Events\uff09\u683c\u5f0f\n            \u6bd4\u55bb\uff1a\u5c31\u50cf\u4f60\u5148\u544a\u8bc9\u7528\u6237\uff1a\"\u6211\u4eec\u7684\u804a\u5929\u5ba4\u7f16\u53f7\u662f123\uff0c\u7136\u540e\u6211\u4eec\u5f00\u59cb\u804a\u5929\"\n            '''\n\n            #\u6784\u5efa\u5bf9\u8bdd\u6d88\u606f,\u548c\u4e4b\u524d\u7684\u666e\u901a\u804a\u5929\u63a5\u53e3\u4e00\u6837\uff0c\u51c6\u5907\u5bf9\u8bdd\u5185\u5bb9\u3002\n            # \u6784\u5efa\u7cfb\u7edf\u63d0\u793a\u8bcd\uff08\u53ea\u4f7f\u7528\u5bf9\u8bdd\u98ce\u683c\u63d0\u793a\u8bcd\uff09\n            system_prompt = get_prompt(\"conversation_style_prompt\")\n            \n            # \u4f7f\u7528\u6d88\u606f\u7ba1\u7406\u5668\u6784\u5efa\u5b8c\u6574\u7684\u5bf9\u8bdd\u6d88\u606f\n            messages = message_manager.build_conversation_messages(\n                session_id=session_id,\n                system_prompt=system_prompt,\n                current_message=request.message\n            )\n\n            # \u8bed\u97f3\u96c6\u6210\u521d\u59cb\u5316\uff08\u91cd\u8981\u90e8\u5206\uff01\uff09,\u8fd9\u90e8\u5206\u6bd4\u8f83\u590d\u6742\uff0c\u56e0\u4e3a\u6709\u5f88\u591a\u6a21\u5f0f\u548c\u914d\u7f6e\uff1a\n            '''\n            \u7406\u89e34\u4e2a\u6761\u4ef6\uff08\u90fd\u8981\u6ee1\u8db3\u624d\u542f\u7528\u5b9e\u65f6TTS\uff09\uff1a\n               \u7cfb\u7edf\u914d\u7f6e\u542f\u7528\u4e86\u8bed\u97f3\u529f\u80fd\n               \u7528\u6237\u6ca1\u6709\u8981\u6c42\u8fd4\u56de\u97f3\u9891URL\uff08return_audio=False\uff09\n               \u8bed\u97f3\u6a21\u5f0f\u4e0d\u662f\"\u6df7\u5408\u6a21\u5f0f\"\n               \u7528\u6237\u6ca1\u6709\u660e\u786e\u7981\u7528TTS\n            '''\n            # \u521d\u59cb\u5316\u8bed\u97f3\u96c6\u6210\uff08\u6839\u636evoice_mode\u548creturn_audio\u51b3\u5b9a\uff09\n            # V19: \u5982\u679c\u5ba2\u6237\u7aef\u8bf7\u6c42\u8fd4\u56de\u97f3\u9891\uff0c\u5219\u5728\u670d\u52a1\u5668\u7aef\u751f\u6210\n            voice_integration = None\n\n            # V19: \u6df7\u5408\u6a21\u5f0f\u4e0b\uff0c\u5982\u679c\u8bf7\u6c42return_audio\uff0c\u5219\u5728\u670d\u52a1\u5668\u751f\u6210\u97f3\u9891\n            # \u4fee\u590d\u53cc\u97f3\u9891\u95ee\u9898\uff1areturn_audio\u65f6\u4e0d\u542f\u7528\u5b9e\u65f6TTS\uff0c\u53ea\u5728\u6700\u540e\u751f\u6210\u5b8c\u6574\u97f3\u9891\n            should_enable_tts = (\n                config.system.voice_enabled\n                and not request.return_audio  # \u4fee\u590d\uff1areturn_audio\u65f6\u4e0d\u542f\u7528\u5b9e\u65f6TTS\n                and config.voice_realtime.voice_mode != \"hybrid\"\n                and not request.disable_tts  # \u517c\u5bb9\u65e7\u7248\u672c\u7684disable_tts\n            )\n\n            if should_enable_tts:\n                try:\n                    from voice.output.voice_integration import get_voice_integration\n                    voice_integration = get_voice_integration()\n                    logger.info(f\"&#91;API Server] \u5b9e\u65f6\u8bed\u97f3\u96c6\u6210\u5df2\u542f\u7528 (return_audio={request.return_audio}, voice_mode={config.voice_realtime.voice_mode})\")\n                except Exception as e:\n                    print(f\"\u8bed\u97f3\u96c6\u6210\u521d\u59cb\u5316\u5931\u8d25: {e}\")\n            else:   #\u5982\u679c\u6761\u4ef6\u6ee1\u8db3\uff0c\u5c31\u521d\u59cb\u5316\u8bed\u97f3\u96c6\u6210\uff08\u8ba9AI\u8bf4\u8bdd\u7684\u529f\u80fd\uff09\n                if request.return_audio:\n                    logger.info(\"&#91;API Server] return_audio\u6a21\u5f0f\uff0c\u5c06\u5728\u6700\u540e\u751f\u6210\u5b8c\u6574\u97f3\u9891\")\n                elif config.voice_realtime.voice_mode == \"hybrid\" and not request.return_audio:\n                    logger.info(\"&#91;API Server] \u6df7\u5408\u6a21\u5f0f\u4e0b\u4e14\u672a\u8bf7\u6c42\u97f3\u9891\uff0c\u4e0d\u5904\u7406TTS\")\n                elif request.disable_tts:\n                    logger.info(\"&#91;API Server] \u5ba2\u6237\u7aef\u7981\u7528\u4e86TTS (disable_tts=True)\")\n                    '''\n                    \u7406\u89e3\u4e0d\u540c\u7684\u60c5\u51b5\uff1a\n                      return_audio=True\uff1a\u7528\u6237\u60f3\u8981\u97f3\u9891\u6587\u4ef6\uff0c\u6700\u540e\u751f\u6210\n                      \u6df7\u5408\u6a21\u5f0f\uff1a\u53ef\u80fd\u5ba2\u6237\u7aef\u81ea\u5df1\u5904\u7406\u8bed\u97f3\n                      disable_tts=True\uff1a\u7528\u6237\u660e\u786e\u4e0d\u8981\u8bed\u97f3\n                    '''\n\n            # \u521d\u59cb\u5316\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\uff08\u4ec5\u7528\u4e8eTTS\u5904\u7406\uff09\n            # \u59cb\u7ec8\u521b\u5efatool_extractor\u4ee5\u7d2f\u79ef\u6587\u672c\u5185\u5bb9\uff0c\u786e\u4fdd\u65e5\u5fd7\u4fdd\u5b58\n            tool_extractor = None\n            try:\n                from .streaming_tool_extractor import StreamingToolCallExtractor\n                tool_extractor = StreamingToolCallExtractor()\n                # \u53ea\u6709\u5728\u9700\u8981\u5b9e\u65f6TTS\u4e14\u4e0d\u662freturn_audio\u6a21\u5f0f\u65f6\uff0c\u624d\u8bbe\u7f6evoice_integration\n                if voice_integration and not request.return_audio:\n                    tool_extractor.set_callbacks(\n                        on_text_chunk=None,  # \u4e0d\u9700\u8981\u56de\u8c03\uff0c\u76f4\u63a5\u5904\u7406TTS\n                        voice_integration=voice_integration\n                    )\n            except Exception as e:\n                print(f\"\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\u521d\u59cb\u5316\u5931\u8d25: {e}\")\n                '''\n                \u7406\u89e3\uff1a\n                  tool_extractor\uff1a\u6587\u672c\u5207\u5272\u5668\uff0c\u628a\u8fde\u7eed\u7684\u6587\u672c\u5207\u6210\u5c0f\u5757\n                  \u5982\u679c\u9700\u8981\u5b9e\u65f6TTS\uff0c\u5c31\u628a\u8bed\u97f3\u96c6\u6210\u8bbe\u7f6e\u7ed9\u5207\u5272\u5668\n                  \u8fd9\u6837\u5207\u5272\u5668\u6536\u5230\u6587\u5b57\u65f6\uff0c\u53ef\u4ee5\u7acb\u5373\u8ba9\u8bed\u97f3\u96c6\u6210\u8bf4\u51fa\u6765\n                '''\n            \n            # \u4f7f\u7528\u6574\u5408\u540e\u7684\u6d41\u5f0f\u5904\u7406,\u6d41\u5f0f\u8c03\u7528AI\u6a21\u578b\uff08\u91cd\u70b9\uff01\uff09\n            llm_service = get_llm_service()\\\n            #llm_service.stream_chat_with_context\uff1a\u8fd9\u662f\u6d41\u5f0f\u8c03\u7528AI\u7684\u65b9\u6cd5\n            #async for chunk in ...\uff1a\u4e00\u70b9\u70b9\u83b7\u53d6AI\u7684\u56de\u590d\uff0c\u6bcf\u6b21\u4e00\u5c0f\u5757\uff08chunk\uff09\n            async for chunk in llm_service.stream_chat_with_context(messages, config.api.temperature):\n                # V19: \u5982\u679c\u9700\u8981\u8fd4\u56de\u97f3\u9891\uff0c\u7d2f\u79ef\u6587\u672c\n                if request.return_audio and chunk.startswith(\"data: \"):\n                    try:\n                        import base64\n                        data_str = chunk&#91;6:].strip()\n                        if data_str != '&#91;DONE]':\n                            decoded = base64.b64decode(data_str).decode('utf-8')\n                            complete_text += decoded\n                    except Exception:\n                        pass\n                    '''\n                    \u7406\u89e3\uff1a\n                       \u5982\u679c\u7528\u6237\u8981\u6c42\u8fd4\u56de\u97f3\u9891\uff0c\u5c31\u7d2f\u79ef\u5b8c\u6574\u7684\u6587\u672c\n                       chunk\u683c\u5f0f\u662fdata: BASE64\u7f16\u7801\u7684\u6587\u5b57\n                       \u9700\u8981\u89e3\u7801BASE64\uff0c\u7136\u540e\u62fc\u63a5\u5230complete_text\u4e2d\n                    '''\n                \n                # \u7acb\u5373\u53d1\u9001\u5230\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\u8fdb\u884cTTS\u5904\u7406\uff08\u4e0d\u963b\u585e\u6587\u672c\u6d41\uff09\n                if tool_extractor and chunk.startswith(\"data: \"):\n                    try:\n                        import base64\n                        data_str = chunk&#91;6:].strip()\n                        if data_str != '&#91;DONE]':\n                            decoded = base64.b64decode(data_str).decode('utf-8')\n                            # \u540c\u6b65\u5904\u7406\u6587\u672c\u7d2f\u79ef\uff0c\u4e0d\u963b\u585e\u6587\u672c\u6d41\n                            tool_extractor.complete_text += decoded\n                    except Exception as e:\n                        logger.error(f\"&#91;API Server] \u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\u5904\u7406\u9519\u8bef: {e}\")\n                        #\u540c\u65f6\uff0c\u628a\u6587\u5b57\u4e5f\u4f20\u7ed9\u6587\u672c\u5207\u5272\u5668\uff08\u7528\u4e8e\u5b9e\u65f6TTS\uff09,\u6ce8\u610f\uff1a\u8fd9\u662f\u5e76\u884c\u5904\u7406\u7684\uff0c\u4e0d\u5f71\u54cd\u6587\u5b57\u6d41\u7ed9\u7528\u6237\n                \n                yield chunk\n                #\u6700\u91cd\u8981\u7684\u90e8\u5206\uff1a\u7acb\u5373\u628a\u8fd9\u4e00\u5c0f\u5757\u6587\u5b57\u53d1\u9001\u7ed9\u7528\u6237\uff01,\u6bd4\u55bb\uff1aAI\u601d\u8003\u4e00\u4e2a\u5b57 \u2192 \u53d1\u9001\u7ed9\u7528\u6237\u663e\u793a \u2192 \u540c\u65f6\u4f20\u7ed9\u8bed\u97f3\u7cfb\u7edf\u51c6\u5907\u8bf4\u8bdd,\u5c31\u50cf\u4e00\u4e2a\u4eba\u4e00\u8fb9\u8bf4\u8bdd\uff08\u6587\u5b57\u663e\u793a\uff09\uff0c\u4e00\u8fb9\u53d1\u58f0\uff08\u8bed\u97f3\u5408\u6210\uff09\n            \n            # \u5904\u7406\u5b8c\u6210\n            #\u97f3\u9891\u751f\u6210\uff08\u5982\u679c\u7528\u6237\u8981\u6c42\u97f3\u9891\u6587\u4ef6\uff09\n            # V19: \u5982\u679c\u8bf7\u6c42\u8fd4\u56de\u97f3\u9891\uff0c\u5728\u8fd9\u91cc\u751f\u6210\u5e76\u8fd4\u56de\u97f3\u9891URL\n            if request.return_audio and complete_text:\n                try:\n                    logger.info(f\"&#91;API Server V19] \u751f\u6210\u97f3\u9891\uff0c\u6587\u672c\u957f\u5ea6: {len(complete_text)}\")\n\n                    # \u4f7f\u7528\u670d\u52a1\u5668\u7aef\u7684TTS\u751f\u6210\u97f3\u9891\n                    from voice.tts_wrapper import generate_speech_safe\n                    import tempfile\n                    import uuid\n\n                    # \u751f\u6210\u97f3\u9891\u6587\u4ef6\n                    tts_voice = config.voice_realtime.tts_voice or \"zh-CN-XiaoyiNeural\"\n                    audio_file = generate_speech_safe(\n                        text=complete_text,\n                        voice=tts_voice,\n                        response_format=\"mp3\",\n                        speed=1.0\n                    )\n                    '''\n                    \u7406\u89e3\uff1a\n                      \u6587\u5b57\u5168\u90e8\u63a5\u6536\u5b8c\u540e\uff0c\u7528TTS\u751f\u6210\u6574\u4e2a\u97f3\u9891\u6587\u4ef6\n                      generate_speech_safe\uff1a\u5b89\u5168\u751f\u6210\u8bed\u97f3\u7684\u51fd\u6570\n                      \u9009\u62e9\u8bed\u97f3\uff08\u9ed8\u8ba4\u662f\"\u6653\u6613\"\u4e2d\u6587\u8bed\u97f3\uff09\n                    '''\n\n                    # \u76f4\u63a5\u4f7f\u7528voice\/output\u64ad\u653e\u97f3\u9891\uff0c\u4e0d\u518d\u8fd4\u56de\u7ed9\u5ba2\u6237\u7aef\n                    try:\n                        from voice.output.voice_integration import get_voice_integration\n                        voice_integration = get_voice_integration()\n                        voice_integration.receive_audio_url(audio_file)\n                        logger.info(f\"&#91;API Server V19] \u97f3\u9891\u5df2\u76f4\u63a5\u64ad\u653e: {audio_file}\")\n                    except Exception as e:\n                        logger.error(f\"&#91;API Server V19] \u97f3\u9891\u64ad\u653e\u5931\u8d25: {e}\")\n                        # \u5982\u679c\u64ad\u653e\u5931\u8d25\uff0c\u4ecd\u7136\u8fd4\u56de\u7ed9\u5ba2\u6237\u7aef\u4f5c\u4e3a\u5907\u9009\n                        yield f\"data: audio_url: {audio_file}\\n\\n\"\n\n                except Exception as e:\n                    logger.error(f\"&#91;API Server V19] \u97f3\u9891\u751f\u6210\u5931\u8d25: {e}\")\n                    # traceback\u5df2\u7ecf\u5728\u6587\u4ef6\u9876\u90e8\u5bfc\u5165\uff0c\u76f4\u63a5\u4f7f\u7528\n                    print(f\"&#91;API Server V19] \u8be6\u7ec6\u9519\u8bef\u4fe1\u606f:\")\n                    traceback.print_exc()\n\n            #\u5b8c\u6210\u5904\u7406\n            # \u5b8c\u6210\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\u5904\u7406\uff08\u975ereturn_audio\u6a21\u5f0f\uff0c\u4e0d\u963b\u585e\uff09\n            if tool_extractor and not request.return_audio:\n                try:\n                    # \u540c\u6b65\u5904\u7406\u5b8c\u6210\uff0c\u4e0d\u963b\u585e\u6587\u672c\u6d41\u8fd4\u56de\n                    # tool_extractor.finish_processing() \u662f\u5f02\u6b65\u65b9\u6cd5\uff0c\u8fd9\u91cc\u4e0d\u9700\u8981\u8c03\u7528\n                    pass\n                except Exception as e:\n                    print(f\"\u6d41\u5f0f\u6587\u672c\u5207\u5272\u5668\u5b8c\u6210\u5904\u7406\u9519\u8bef: {e}\")\n            \n            # \u5b8c\u6210\u8bed\u97f3\u5904\u7406\n            if voice_integration and not request.return_audio:  # V19: return_audio\u6a21\u5f0f\u4e0d\u9700\u8981\u8fd9\u91cc\u7684\u5904\u7406\n                try:\n                    threading.Thread(\n                        target=voice_integration.finish_processing,\n                        daemon=True\n                    ).start()\n                except Exception as e:\n                    print(f\"\u8bed\u97f3\u96c6\u6210\u5b8c\u6210\u5904\u7406\u9519\u8bef: {e}\")\n                    #\u7406\u89e3\uff1a\u544a\u8bc9\u6587\u672c\u5207\u5272\u5668\u548c\u8bed\u97f3\u96c6\u6210\uff1a\"\u5904\u7406\u5b8c\u4e86\uff0c\u53ef\u4ee5\u505a\u6536\u5c3e\u5de5\u4f5c\u4e86\",threading.Thread(...).start()\uff1a\u5728\u65b0\u7ebf\u7a0b\u4e2d\u5904\u7406\uff0c\u4e0d\u963b\u585e\u4e3b\u7a0b\u5e8f\n\n            # \u6d41\u5f0f\u5904\u7406\u5b8c\u6210\u540e\uff0c\u83b7\u53d6\u5b8c\u6574\u6587\u672c\u7528\u4e8e\u4fdd\u5b58\n            complete_response = \"\"\n            if tool_extractor:\n                try:\n                    # \u83b7\u53d6\u5b8c\u6574\u6587\u672c\u5185\u5bb9\n                    complete_response = tool_extractor.get_complete_text()\n                except Exception as e:\n                    print(f\"\u83b7\u53d6\u5b8c\u6574\u54cd\u5e94\u6587\u672c\u5931\u8d25: {e}\")\n            elif request.return_audio:\n                # V19: \u5982\u679c\u662freturn_audio\u6a21\u5f0f\uff0c\u4f7f\u7528\u7d2f\u79ef\u7684\u6587\u672c\n                complete_response = complete_text\n            \n            # \u7edf\u4e00\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\u4e0e\u65e5\u5fd7\n            _save_conversation_and_logs(session_id, request.message, complete_response)\n\n            # \u5728\u7528\u6237\u6d88\u606f\u4fdd\u5b58\u5230\u5386\u53f2\u540e\u89e6\u53d1\u540e\u53f0\u610f\u56fe\u5206\u6790\uff08\u9664\u975e\u660e\u786e\u8df3\u8fc7\uff09\n            if not request.skip_intent_analysis:\n                _trigger_background_analysis(session_id)\n\n            yield \"data: &#91;DONE]\\n\\n\"\n            '''\n            \u7406\u89e3\uff1a\u83b7\u53d6\u5b8c\u6574\u7684AI\u56de\u590d\u6587\u5b57,\u4fdd\u5b58\u5230\u5bf9\u8bdd\u5386\u53f2,\u89e6\u53d1\u610f\u56fe\u5206\u6790,\u53d1\u9001\u7ed3\u675f\u6807\u8bb0&#91;DONE]\uff0c\u544a\u8bc9\u5ba2\u6237\u7aef\uff1a\"\u6211\u8bf4\u5b8c\u4e86\"\n            '''\n\n        # \u9519\u8bef\u5904\u7406\n        except Exception as e:\n            print(f\"\u6d41\u5f0f\u5bf9\u8bdd\u5904\u7406\u9519\u8bef: {e}\")\n            # \u4f7f\u7528\u9876\u90e8\u5bfc\u5165\u7684traceback\n            traceback.print_exc()\n            yield f\"data: \u9519\u8bef: {str(e)}\\n\\n\"\n\n    #\u8fd4\u56de\u6d41\u5f0f\u54cd\u5e94\n    return StreamingResponse(\n        generate_response(),\n        media_type=\"text\/event-stream\",  #\u8fd9\u662f\u670d\u52a1\u5668\u63a8\u9001\u4e8b\u4ef6\u7684\u683c\u5f0f\n        headers={\n            \"Cache-Control\": \"no-cache\",\n            \"Connection\": \"keep-alive\",\n            \"Content-Type\": \"text\/event-stream\",\n            \"Access-Control-Allow-Origin\": \"*\",\n            \"Access-Control-Allow-Headers\": \"*\",\n            \"X-Accel-Buffering\": \"no\"  # \u7981\u7528nginx\u7f13\u51b2,\u544a\u8bc9nginx\u4e0d\u8981\u7f13\u5b58\uff0c\u7acb\u5373\u4f20\u8f93\n        }\n    )\n# =========\u6d41\u7a0b\u56fe\u603b\u7ed3\uff1a=============\n'''\n\u5f00\u59cb\n  \u2193\n\u68c0\u67e5\u7a7a\u6d88\u606f\n  \u2193\n\u521b\u5efa\u4f1a\u8bddID \u2192 \u7acb\u5373\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef\n  \u2193\n\u5224\u65ad\u8bed\u97f3\u6a21\u5f0f\uff1a\n  - \u5b9e\u65f6TTS\u6a21\u5f0f\uff1f\n  - \u8fd4\u56de\u97f3\u9891\u6a21\u5f0f\uff1f\n  - \u6df7\u5408\u6a21\u5f0f\uff1f\n  - \u7981\u7528TTS\uff1f\n  \u2193\n\u521d\u59cb\u5316\u6587\u672c\u5207\u5272\u5668\n  \u2193\n\u5f00\u59cb\u6d41\u5f0f\u83b7\u53d6AI\u56de\u590d\uff1a\n  \u2193\nAI\u4ea7\u751f\u4e00\u4e2a\u5b57 \u2192 \u7acb\u5373\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef\u663e\u793a\n  \u2193              \u2193\n\u5982\u679c\u9700\u8981\u97f3\u9891 \u2192 \u7d2f\u79ef\u6587\u5b57     \u5982\u679c\u9700\u8981\u5b9e\u65f6TTS \u2192 \u4f20\u7ed9\u8bed\u97f3\u7cfb\u7edf\n  \u2193              \u2193\n\u7ee7\u7eed\u4e0b\u4e00\u4e2a\u5b57 \u2190---------------\n  \u2193\nAI\u56de\u590d\u5b8c\u6210\n  \u2193\n\u5982\u679c\u662f\u97f3\u9891\u6a21\u5f0f \u2192 \u751f\u6210\u97f3\u9891\u6587\u4ef6 \u2192 \u64ad\u653e\u6216\u8fd4\u56deURL\n  \u2193\n\u5b8c\u6210\u6587\u672c\u5207\u5272\u5668\u548c\u8bed\u97f3\u5904\u7406\n  \u2193\n\u4fdd\u5b58\u5bf9\u8bdd\u5386\u53f2\n  \u2193\n\u89e6\u53d1\u610f\u56fe\u5206\u6790\n  \u2193\n\u53d1\u9001\u7ed3\u675f\u6807\u8bb0\n  \u2193\n\u5982\u679c\u6709\u9519\u8bef \u2192 \u53d1\u9001\u9519\u8bef\u4fe1\u606f\n'''\n\n# ==========\u5173\u952e\u51fd\u6570\u548c\u8c03\u7528\uff1a=========\n'''\n1.\u6d88\u606f\u5904\u7406\uff1a\n  message_manager.create_session() - \u521b\u5efa\u4f1a\u8bdd\n  message_manager.build_conversation_messages() - \u6784\u5efa\u6d88\u606f\n2.AI\u670d\u52a1\uff1a\n  get_llm_service() - \u83b7\u53d6AI\u670d\u52a1\n  llm_service.stream_chat_with_context() - \u6d41\u5f0f\u804a\u5929\u6838\u5fc3\n3.\u8bed\u97f3\u5904\u7406\uff1a\n get_voice_integration() - \u83b7\u53d6\u8bed\u97f3\u96c6\u6210\n generate_speech_safe() - \u751f\u6210\u8bed\u97f3\u6587\u4ef6\n voice_integration.receive_audio_url() - \u64ad\u653e\u97f3\u9891\n4.\u6587\u672c\u5904\u7406\uff1a\n StreamingToolCallExtractor() - \u6587\u672c\u5207\u5272\u5668\n tool_extractor.set_callbacks() - \u8bbe\u7f6e\u56de\u8c03\n5.\u6570\u636e\u4fdd\u5b58\uff1a\n _save_conversation_and_logs() - \u4fdd\u5b58\u5bf9\u8bdd\n _trigger_background_analysis() - \u89e6\u53d1\u5206\u6790\n'''\n\n# \u83b7\u53d6\u8bb0\u5fc6\u7edf\u8ba1\u63a5\u53e3 (\/memory\/stats),@app.get(\"\/memory\/stats\")\uff1a\u521b\u5efa\u4e00\u4e2aGET\u8bf7\u6c42\u7684\u63a5\u53e3\uff0c\u5730\u5740\u662f\/memory\/stats,\u7528\u6765\u83b7\u53d6AI\u7684\"\u8bb0\u5fc6\u7cfb\u7edf\"\u7684\u7edf\u8ba1\u4fe1\u606f\n@app.get(\"\/memory\/stats\")\nasync def get_memory_stats():\n    \"\"\"\u83b7\u53d6\u8bb0\u5fc6\u7edf\u8ba1\u4fe1\u606f\"\"\"\n    \n    try:\n        # \u8bb0\u5fc6\u7cfb\u7edf\u73b0\u5728\u7531main.py\u76f4\u63a5\u7ba1\u7406\n        try:\n            #\u7b2c\u4e00\u5c42\uff1a\u5c1d\u8bd5\u5bfc\u5165\u8bb0\u5fc6\u7ba1\u7406\u5668\n            # \u5206\u5c42\u7406\u89e3\uff1a\u7b2c\u4e00\u5c42\uff1a\u5c1d\u8bd5\u5bfc\u5165\u8bb0\u5fc6\u7ba1\u7406\u5668:from summer_memory.memory_manager import memory_manager\n            # \u5c1d\u8bd5\u4ecesummer_memory\u6a21\u5757\u5bfc\u5165memory_manager,\u5982\u679c\u5bfc\u5165\u5931\u8d25\uff0c\u8bf4\u660e\u8bb0\u5fc6\u7cfb\u7edf\u6a21\u5757\u4e0d\u5b58\u5728\n            from summer_memory.memory_manager import memory_manager\n            #\u7b2c\u4e8c\u5c42\uff1a\u68c0\u67e5\u8bb0\u5fc6\u7cfb\u7edf\u662f\u5426\u542f\u7528\n            #\u5982\u679c\u8bb0\u5fc6\u7ba1\u7406\u5668\u5b58\u5728\u4e14\u542f\u7528\uff08enabled=True\uff09,\u8c03\u7528get_memory_stats()\u65b9\u6cd5\u83b7\u53d6\u7edf\u8ba1\u4fe1\u606f,\u8fd4\u56de\u6210\u529f\u72b6\u6001\u548c\u7edf\u8ba1\u4fe1\u606f\n            if memory_manager and memory_manager.enabled:\n                stats = memory_manager.get_memory_stats()\n                return {\n                    \"status\": \"success\",\n                    \"memory_stats\": stats\n                }\n            else:\n                return {\n                    \"status\": \"success\",\n                    \"memory_stats\": {\"enabled\": False, \"message\": \"\u8bb0\u5fc6\u7cfb\u7edf\u672a\u542f\u7528\"}\n                }\n        #\u7b2c\u4e09\u5c42\uff1a\u5982\u679c\u6a21\u5757\u4e0d\u5b58\u5728,\u5982\u679csummer_memory\u6a21\u5757\u4e0d\u5b58\u5728\uff08ImportError\uff09,\u8fd4\u56de\u6a21\u5757\u672a\u627e\u5230\u7684\u63d0\u793a\n        except ImportError:\n            return {\n                \"status\": \"success\",\n                \"memory_stats\": {\"enabled\": False, \"message\": \"\u8bb0\u5fc6\u7cfb\u7edf\u6a21\u5757\u672a\u627e\u5230\"}\n            }\n    #\u5904\u7406\u5176\u4ed6\u6240\u6709\u9519\u8bef\n    except Exception as e:\n        print(f\"\u83b7\u53d6\u8bb0\u5fc6\u7edf\u8ba1\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=f\"\u83b7\u53d6\u8bb0\u5fc6\u7edf\u8ba1\u5931\u8d25: {str(e)}\")\n    #\u8fd9\u4e2a\u63a5\u53e3\u5c31\u50cf\u95eeAI\uff1a\"\u4f60\u8fd8\u8bb0\u5f97\u591a\u5c11\u4e8b\u60c5\uff1f\",\u5982\u679cAI\u6709\u8bb0\u5fc6\u7cfb\u7edf\uff1a\u8fd4\u56de\u8bb0\u5fc6\u7edf\u8ba1,\u5982\u679c\u8bb0\u5fc6\u7cfb\u7edf\u6ca1\u5f00\uff1a\u544a\u8bc9\u7528\u6237\u6ca1\u5f00,\u5982\u679c\u8bb0\u5fc6\u7cfb\u7edf\u6839\u672c\u6ca1\u88c5\uff1a\u544a\u8bc9\u7528\u6237\u6ca1\u5b89\u88c5\n\n# \u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\u4fe1\u606f (\/sessions)\n'''\n\u7406\u89e3\uff1a\n  GET\u8bf7\u6c42\uff0c\u83b7\u53d6\u6240\u6709\u804a\u5929\u4f1a\u8bdd\u7684\u4fe1\u606f\n  \u5b8c\u5168\u59d4\u6258\u7ed9message_manager.get_all_sessions_api()\u5904\u7406\n  \u5982\u679c\u51fa\u9519\uff0c\u8fd4\u56de500\u9519\u8bef\n'''\n@app.get(\"\/sessions\")\nasync def get_sessions():\n    \"\"\"\u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\u4fe1\u606f - \u59d4\u6258\u7ed9message_manager\"\"\"\n    try:\n        return message_manager.get_all_sessions_api()\n    except Exception as e:\n        print(f\"\u83b7\u53d6\u4f1a\u8bdd\u4fe1\u606f\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=str(e))\n\n#{session_id}\uff1a\u8fd9\u662f\u8def\u5f84\u53c2\u6570\uff0c\u53ef\u4ee5\u4eceURL\u4e2d\u83b7\u53d6,\u4f8b\u5982\uff1a\u8bbf\u95ee\/sessions\/abc123\uff0csession_id\u5c31\u662f\"abc123\"\n@app.get(\"\/sessions\/{session_id}\")\nasync def get_session_detail(session_id: str):\n    \"\"\"\u83b7\u53d6\u6307\u5b9a\u4f1a\u8bdd\u7684\u8be6\u7ec6\u4fe1\u606f - \u59d4\u6258\u7ed9message_manager\"\"\"\n    try:\n        return message_manager.get_session_detail_api(session_id)\n    except Exception as e:\n        if \"\u4f1a\u8bdd\u4e0d\u5b58\u5728\" in str(e):   #\u68c0\u67e5\u9519\u8bef\u4fe1\u606f\u662f\u5426\u5305\u542b\"\u4f1a\u8bdd\u4e0d\u5b58\u5728\"\n            raise HTTPException(status_code=404, detail=str(e))\n        print(f\"\u83b7\u53d6\u4f1a\u8bdd\u8be6\u60c5\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=str(e))\n\n#@app.delete\uff1a\u521b\u5efa\u4e00\u4e2aDELETE\u8bf7\u6c42\u7684\u63a5\u53e3\n@app.delete(\"\/sessions\/{session_id}\")\nasync def delete_session(session_id: str):\n    \"\"\"\u5220\u9664\u6307\u5b9a\u4f1a\u8bdd - \u59d4\u6258\u7ed9message_manager\"\"\"\n    try:\n        return message_manager.delete_session_api(session_id)\n    except Exception as e:\n        if \"\u4f1a\u8bdd\u4e0d\u5b58\u5728\" in str(e):\n            raise HTTPException(status_code=404, detail=str(e))\n        print(f\"\u5220\u9664\u4f1a\u8bdd\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=str(e))\n\n#DELETE\u8bf7\u6c42\uff0c\u4f46\u6ca1\u6709\u8def\u5f84\u53c2\u6570,\u5220\u9664\u6240\u6709\u4f1a\u8bdd\uff08\u5371\u9669\u64cd\u4f5c\uff01\uff09,\u6ce8\u610f\uff1a\u8fd9\u4e2a\u63a5\u53e3\u6ca1\u6709404\u9519\u8bef\u7684\u5904\u7406\uff0c\u56e0\u4e3a\u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd\u4e0d\u4f1a\u51fa\u73b0\"\u4f1a\u8bdd\u4e0d\u5b58\u5728\"\u7684\u60c5\u51b5\u3002\n@app.delete(\"\/sessions\")\nasync def clear_all_sessions():\n    \"\"\"\u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd - \u59d4\u6258\u7ed9message_manager\"\"\"\n    try:\n        return message_manager.clear_all_sessions_api()\n    except Exception as e:\n        print(f\"\u6e05\u7a7a\u4f1a\u8bdd\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=str(e))\n\n# \u6587\u6863\u5904\u7406\u529f\u80fd\u5df2\u6574\u5408\u5230 ui\/controller\/tool_document.py\n\n# \u65b0\u589e\uff1a\u65e5\u5fd7\u89e3\u6790\u76f8\u5173API\u63a5\u53e3\n@app.get(\"\/logs\/context\/statistics\")\nasync def get_log_context_statistics(days: int = 7):\n    \"\"\"\u83b7\u53d6\u65e5\u5fd7\u4e0a\u4e0b\u6587\u7edf\u8ba1\u4fe1\u606f\"\"\"\n    try:\n        statistics = message_manager.get_context_statistics(days)\n        return {\n            \"status\": \"success\",\n            \"statistics\": statistics\n        }\n    except Exception as e:\n        print(f\"\u83b7\u53d6\u65e5\u5fd7\u4e0a\u4e0b\u6587\u7edf\u8ba1\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=f\"\u83b7\u53d6\u7edf\u8ba1\u4fe1\u606f\u5931\u8d25: {str(e)}\")\n\n\n@app.get(\"\/logs\/context\/load\")\nasync def load_log_context(days: int = 3, max_messages: int = None):\n    \"\"\"\u52a0\u8f7d\u65e5\u5fd7\u4e0a\u4e0b\u6587\"\"\"\n    try:\n        messages = message_manager.load_recent_context(days=days, max_messages=max_messages)\n        return {\n            \"status\": \"success\",\n            \"messages\": messages,\n            \"count\": len(messages),\n            \"days\": days\n        }\n    except Exception as e:\n        print(f\"\u52a0\u8f7d\u65e5\u5fd7\u4e0a\u4e0b\u6587\u9519\u8bef: {e}\")\n        traceback.print_exc()\n        raise HTTPException(status_code=500, detail=f\"\u52a0\u8f7d\u4e0a\u4e0b\u6587\u5931\u8d25: {str(e)}\")\n\n@app.post(\"\/tool_notification\")\nasync def tool_notification(payload: Dict&#91;str, Any]):\n    \"\"\"\u63a5\u6536\u5de5\u5177\u8c03\u7528\u72b6\u6001\u901a\u77e5\uff0c\u53ea\u663e\u793a\u5de5\u5177\u8c03\u7528\u72b6\u6001\uff0c\u4e0d\u663e\u793a\u7ed3\u679c\"\"\"\n    try:\n        session_id = payload.get(\"session_id\")\n        tool_calls = payload.get(\"tool_calls\", &#91;])\n        message = payload.get(\"message\", \"\")\n\n        if not session_id:\n            raise HTTPException(400, \"\u7f3a\u5c11session_id\")\n\n        # \u8bb0\u5f55\u5de5\u5177\u8c03\u7528\u72b6\u6001\uff08\u4e0d\u5904\u7406\u7ed3\u679c\uff0c\u7ed3\u679c\u7531tool_result_callback\u5904\u7406\uff09\n        for tool_call in tool_calls:\n            tool_name = tool_call.get(\"tool_name\", \"\u672a\u77e5\u5de5\u5177\")\n            service_name = tool_call.get(\"service_name\", \"\u672a\u77e5\u670d\u52a1\")\n            status = tool_call.get(\"status\", \"starting\")\n            logger.info(f\"\u5de5\u5177\u8c03\u7528\u72b6\u6001: {tool_name} ({service_name}) - {status}\")\n\n        # \u8fd9\u91cc\u53ef\u4ee5\u6dfb\u52a0WebSocket\u901a\u77e5UI\u7684\u903b\u8f91\uff0c\u8ba9UI\u663e\u793a\u5de5\u5177\u8c03\u7528\u72b6\u6001\n        # \u76ee\u524d\u5148\u8bb0\u5f55\u65e5\u5fd7\uff0cUI\u53ef\u4ee5\u901a\u8fc7\u5176\u4ed6\u65b9\u5f0f\u83b7\u53d6\u5de5\u5177\u8c03\u7528\u72b6\u6001\n\n        return {\n            \"success\": True,\n            \"message\": \"\u5de5\u5177\u8c03\u7528\u72b6\u6001\u901a\u77e5\u5df2\u63a5\u6536\",\n            \"tool_calls\": tool_calls,\n            \"display_message\": message\n        }\n\n    except Exception as e:\n        logger.error(f\"\u5de5\u5177\u8c03\u7528\u901a\u77e5\u5904\u7406\u5931\u8d25: {e}\")\n        raise HTTPException(500, f\"\u5904\u7406\u5931\u8d25: {str(e)}\")\n\n#\u975e\u5e38\u91cd\u8981\n@app.post(\"\/tool_result_callback\")\nasync def tool_result_callback(payload: Dict&#91;str, Any]):\n    \"\"\"\u63a5\u6536MCP\u5de5\u5177\u6267\u884c\u7ed3\u679c\u56de\u8c03\uff0c\u8ba9\u4e3bAI\u57fa\u4e8e\u539f\u59cb\u5bf9\u8bdd\u548c\u5de5\u5177\u7ed3\u679c\u91cd\u65b0\u751f\u6210\u56de\u590d\"\"\"\n    try:\n        session_id = payload.get(\"session_id\")\n        task_id = payload.get(\"task_id\")\n        result = payload.get(\"result\", {})\n        success = payload.get(\"success\", False)\n\n        if not session_id:\n            raise HTTPException(400, \"\u7f3a\u5c11session_id\")\n\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5f00\u59cb\u5904\u7406\u5de5\u5177\u56de\u8c03\uff0c\u4f1a\u8bdd: {session_id}, \u4efb\u52a1ID: {task_id}\")\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u56de\u8c03\u5185\u5bb9: {result}\")\n\n        # \u83b7\u53d6\u5de5\u5177\u6267\u884c\u7ed3\u679c\n        tool_result = result.get('result', '\u6267\u884c\u6210\u529f') if success else result.get('error', '\u672a\u77e5\u9519\u8bef')\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5de5\u5177\u6267\u884c\u7ed3\u679c: {tool_result}\")\n\n        # \u83b7\u53d6\u539f\u59cb\u5bf9\u8bdd\u7684\u6700\u540e\u4e00\u6761\u7528\u6237\u6d88\u606f\uff08\u89e6\u53d1\u5de5\u5177\u8c03\u7528\u7684\u6d88\u606f\uff09\n        session_messages = message_manager.get_messages(session_id)\n        original_user_message = \"\"\n        for msg in reversed(session_messages):\n            if msg.get('role') == 'user':\n                original_user_message = msg.get('content', '')\n                break\n\n        # \u6784\u5efa\u5305\u542b\u5de5\u5177\u7ed3\u679c\u7684\u7528\u6237\u6d88\u606f\n        enhanced_message = f\"{original_user_message}\\n\\n&#91;\u5de5\u5177\u6267\u884c\u7ed3\u679c]: {tool_result}\"\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u6784\u5efa\u589e\u5f3a\u6d88\u606f: {enhanced_message&#91;:200]}...\")\n\n        # \u6784\u5efa\u5bf9\u8bdd\u98ce\u683c\u63d0\u793a\u8bcd\u548c\u6d88\u606f\n        system_prompt = get_prompt(\"conversation_style_prompt\")\n        messages = message_manager.build_conversation_messages(\n            session_id=session_id,\n            system_prompt=system_prompt,\n            current_message=enhanced_message\n        )\n\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5f00\u59cb\u751f\u6210\u5de5\u5177\u540e\u56de\u590d...\")\n\n        # \u4f7f\u7528LLM\u670d\u52a1\u57fa\u4e8e\u539f\u59cb\u5bf9\u8bdd\u548c\u5de5\u5177\u7ed3\u679c\u91cd\u65b0\u751f\u6210\u56de\u590d\n        try:\n            llm_service = get_llm_service()\n            response_text = await llm_service.chat_with_context(messages, temperature=0.7)\n            logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5de5\u5177\u540e\u56de\u590d\u751f\u6210\u6210\u529f\uff0c\u5185\u5bb9: {response_text&#91;:200]}...\")\n        except Exception as e:\n            logger.error(f\"&#91;\u5de5\u5177\u56de\u8c03] \u8c03\u7528LLM\u670d\u52a1\u5931\u8d25: {e}\")\n            response_text = f\"\u5904\u7406\u5de5\u5177\u7ed3\u679c\u65f6\u51fa\u9519: {str(e)}\"\n\n        # \u53ea\u4fdd\u5b58AI\u56de\u590d\u5230\u5386\u53f2\u8bb0\u5f55\uff08\u7528\u6237\u6d88\u606f\u5df2\u5728\u6b63\u5e38\u5bf9\u8bdd\u6d41\u7a0b\u4e2d\u4fdd\u5b58\uff09\n        message_manager.add_message(session_id, \"assistant\", response_text)\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] AI\u56de\u590d\u5df2\u4fdd\u5b58\u5230\u5386\u53f2\")\n\n        # \u4fdd\u5b58\u5bf9\u8bdd\u65e5\u5fd7\u5230\u6587\u4ef6\n        message_manager.save_conversation_log(original_user_message, response_text, dev_mode=False)\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5bf9\u8bdd\u65e5\u5fd7\u5df2\u4fdd\u5b58\")\n\n        # \u901a\u8fc7UI\u901a\u77e5\u63a5\u53e3\u5c06AI\u56de\u590d\u53d1\u9001\u7ed9UI\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5f00\u59cb\u53d1\u9001AI\u56de\u590d\u5230UI...\")\n        await _notify_ui_refresh(session_id, response_text)\n\n        logger.info(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5de5\u5177\u7ed3\u679c\u5904\u7406\u5b8c\u6210\uff0c\u56de\u590d\u5df2\u53d1\u9001\u5230UI\")\n\n        return {\n            \"success\": True,\n            \"message\": \"\u5de5\u5177\u7ed3\u679c\u5df2\u901a\u8fc7\u4e3bAI\u5904\u7406\u5e76\u8fd4\u56de\u7ed9UI\",\n            \"response\": response_text,\n            \"task_id\": task_id,\n            \"session_id\": session_id\n        }\n\n    except Exception as e:\n        logger.error(f\"&#91;\u5de5\u5177\u56de\u8c03] \u5de5\u5177\u7ed3\u679c\u56de\u8c03\u5904\u7406\u5931\u8d25: {e}\")\n        raise HTTPException(500, f\"\u5904\u7406\u5931\u8d25: {str(e)}\")\n#\u5b8c\u6574\u6d41\u7a0b\u603b\u7ed3\uff1a\n'''\n\u7528\u6237\u63d0\u95ee \u2192 AI\u53d1\u73b0\u9700\u8981\u5de5\u5177 \u2192 \u8c03\u7528\u5de5\u5177 \u2192 \u5de5\u5177\u6267\u884c\n                                      \u2193\n\u5de5\u5177\u5b8c\u6210 \u2192 \u8c03\u7528\/tool_result_callback \u2192 AI\u91cd\u65b0\u751f\u6210\u56de\u590d \u2192 \u663e\u793a\u7ed9\u7528\u6237\n'''\n\n@app.post(\"\/tool_result\")\nasync def tool_result(payload: Dict&#91;str, Any]):\n    \"\"\"\u63a5\u6536\u5de5\u5177\u6267\u884c\u7ed3\u679c\u5e76\u663e\u793a\u5728UI\u4e0a\"\"\"\n    try:\n        session_id = payload.get(\"session_id\")\n        result = payload.get(\"result\", \"\")\n        notification_type = payload.get(\"type\", \"\")\n        ai_response = payload.get(\"ai_response\", \"\")\n\n        if not session_id:\n            raise HTTPException(400, \"\u7f3a\u5c11session_id\")\n\n        logger.info(f\"\u5de5\u5177\u6267\u884c\u7ed3\u679c: {result}\")\n\n        # \u5982\u679c\u662f\u5de5\u5177\u5b8c\u6210\u540e\u7684AI\u56de\u590d\uff0c\u901a\u8fc7\u4fe1\u53f7\u673a\u5236\u901a\u77e5UI\u7ebf\u7a0b\u663e\u793a\n        if notification_type == \"tool_completed_with_ai_response\" and ai_response:\n            try:\n                # \u4f7f\u7528Qt\u4fe1\u53f7\u673a\u5236\u5728\u4e3b\u7ebf\u7a0b\u4e2d\u5b89\u5168\u5730\u66f4\u65b0UI\n                from ui.controller.tool_chat import chat\n\n                # \u76f4\u63a5\u53d1\u5c04\u4fe1\u53f7\uff0c\u786e\u4fdd\u5728\u4e3b\u7ebf\u7a0b\u4e2d\u6267\u884c\n                chat.tool_ai_response_received.emit(ai_response)\n                logger.info(f\"&#91;UI] \u5df2\u901a\u8fc7\u4fe1\u53f7\u673a\u5236\u901a\u77e5UI\u663e\u793aAI\u56de\u590d\uff0c\u957f\u5ea6: {len(ai_response)}\")\n            except Exception as e:\n                logger.error(f\"&#91;UI] \u8c03\u7528UI\u63a7\u5236\u5668\u663e\u793aAI\u56de\u590d\u5931\u8d25: {e}\")\n'''\n\u91cd\u8981\u6982\u5ff5\uff1aQt\u4fe1\u53f7\u673a\u5236:\n  Qt\u662f\u4e00\u4e2a\u56fe\u5f62\u754c\u9762\u6846\u67b6\n  emit()\u662f\u53d1\u9001\u4fe1\u53f7\u7684\u51fd\u6570\n  \u8fd9\u662f\u5728\u591a\u7ebf\u7a0b\u73af\u5883\u4e0b\u5b89\u5168\u66f4\u65b0UI\u7684\u65b9\u5f0f\n  \n\u6bd4\u55bb\uff1a\u5c31\u50cf\u5728\u4e24\u4e2a\u623f\u95f4\u4e4b\u95f4\u7528\u5bf9\u8bb2\u673a\u901a\u8bdd\uff1a\n  \u540e\u53f0\u7ebf\u7a0b\uff1a\"\u6211\u8fd9\u91cc\u6709AI\u56de\u590d\u4e86\"\n  \u524d\u53f0UI\u7ebf\u7a0b\uff1a\"\u6536\u5230\uff0c\u6211\u9a6c\u4e0a\u663e\u793a\"\n'''\n\n        return {\n            \"success\": True,\n            \"message\": \"\u5de5\u5177\u7ed3\u679c\u5df2\u63a5\u6536\",\n            \"result\": result,\n            \"session_id\": session_id\n        }\n\n    except Exception as e:\n        logger.error(f\"\u5904\u7406\u5de5\u5177\u7ed3\u679c\u5931\u8d25: {e}\")\n        raise HTTPException(500, f\"\u5904\u7406\u5931\u8d25: {str(e)}\")\n\n\n@app.post(\"\/save_tool_conversation\")\nasync def save_tool_conversation(payload: Dict&#91;str, Any]):\n    \"\"\"\u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd\u5386\u53f2\"\"\"\n    try:\n        session_id = payload.get(\"session_id\")\n        user_message = payload.get(\"user_message\", \"\")\n        assistant_response = payload.get(\"assistant_response\", \"\")\n\n        if not session_id:\n            raise HTTPException(400, \"\u7f3a\u5c11session_id\")\n\n        logger.info(f\"&#91;\u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd] \u5f00\u59cb\u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd\u5386\u53f2\uff0c\u4f1a\u8bdd: {session_id}\")\n\n        # \u4fdd\u5b58\u7528\u6237\u6d88\u606f\uff08\u5de5\u5177\u6267\u884c\u7ed3\u679c\uff09\n        if user_message:\n            message_manager.add_message(session_id, \"user\", user_message)\n\n        # \u4fdd\u5b58AI\u56de\u590d\n        if assistant_response:\n            message_manager.add_message(session_id, \"assistant\", assistant_response)\n\n        logger.info(f\"&#91;\u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd] \u5de5\u5177\u5bf9\u8bdd\u5386\u53f2\u5df2\u4fdd\u5b58\uff0c\u4f1a\u8bdd: {session_id}\")\n\n        return {\n            \"success\": True,\n            \"message\": \"\u5de5\u5177\u5bf9\u8bdd\u5386\u53f2\u5df2\u4fdd\u5b58\",\n            \"session_id\": session_id\n        }\n\n    except Exception as e:\n        logger.error(f\"&#91;\u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd] \u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd\u5386\u53f2\u5931\u8d25: {e}\")\n        raise HTTPException(500, f\"\u4fdd\u5b58\u5931\u8d25: {str(e)}\")\n\n#\u8fd9\u662f\u4e00\u4e2a\u901a\u7528\u7684UI\u63a7\u5236\u63a5\u53e3\u3002\n@app.post(\"\/ui_notification\")\nasync def ui_notification(payload: Dict&#91;str, Any]):\n    \"\"\"UI\u901a\u77e5\u63a5\u53e3 - \u7528\u4e8e\u76f4\u63a5\u63a7\u5236UI\u663e\u793a\"\"\"\n    try:\n        session_id = payload.get(\"session_id\")\n        action = payload.get(\"action\", \"\")\n        ai_response = payload.get(\"ai_response\", \"\")\n\n        if not session_id:\n            raise HTTPException(400, \"\u7f3a\u5c11session_id\")\n\n        logger.info(f\"UI\u901a\u77e5: {action}, \u4f1a\u8bdd: {session_id}\")\n\n        # \u5904\u7406\u663e\u793a\u5de5\u5177AI\u56de\u590d\u7684\u52a8\u4f5c\n        if action == \"show_tool_ai_response\" and ai_response:\n            try:\n                from ui.controller.tool_chat import chat\n\n                # \u76f4\u63a5\u53d1\u5c04\u4fe1\u53f7\uff0c\u786e\u4fdd\u5728\u4e3b\u7ebf\u7a0b\u4e2d\u6267\u884c\n                chat.tool_ai_response_received.emit(ai_response)\n                logger.info(f\"&#91;UI\u901a\u77e5] \u5df2\u901a\u8fc7\u4fe1\u53f7\u673a\u5236\u663e\u793a\u5de5\u5177AI\u56de\u590d\uff0c\u957f\u5ea6: {len(ai_response)}\")\n                return {\n                    \"success\": True,\n                    \"message\": \"AI\u56de\u590d\u5df2\u663e\u793a\"\n                }\n            except Exception as e:\n                logger.error(f\"&#91;UI\u901a\u77e5] \u663e\u793a\u5de5\u5177AI\u56de\u590d\u5931\u8d25: {e}\")\n                raise HTTPException(500, f\"\u663e\u793aAI\u56de\u590d\u5931\u8d25: {str(e)}\")\n\n        return {\n            \"success\": True,\n            \"message\": \"UI\u901a\u77e5\u5df2\u5904\u7406\"\n        }\n\n    except Exception as e:\n        logger.error(f\"\u5904\u7406UI\u901a\u77e5\u5931\u8d25: {e}\")\n        raise HTTPException(500, f\"\u5904\u7406\u5931\u8d25: {str(e)}\")\n'''\n\u4e0e\/tool_result\u7684\u533a\u522b\uff1a\n  \/tool_result\uff1a\u7279\u5b9a\u7528\u4e8e\u5de5\u5177\u7ed3\u679c\n  \/ui_notification\uff1a\u901a\u7528\u7684UI\u63a7\u5236\uff0c\u53ef\u4ee5\u505a\u66f4\u591a\u4e8b\u60c5\n'''\n# ========\u5de5\u5177\u8c03\u7528\u6d41\u7a0b\u603b\u7ed3\uff1a=========\n#\u8fd9\u91cc\u6709\u4e24\u4e2a\u4e0d\u540c\u7684\u5de5\u5177\u8c03\u7528\u5904\u7406\u6d41\u7a0b\uff1a\n'''\n\u6d41\u7a0b\u4e00\uff1a\u5b8c\u6574\u56de\u8c03\u6d41\u7a0b\uff08\u63a8\u8350\uff09\n1. \u7528\u6237\u63d0\u95ee\n2. AI\u51b3\u5b9a\u8c03\u7528\u5de5\u5177\n3. \u8c03\u7528\u5de5\u5177 \u2192 \u5de5\u5177\u6267\u884c\n4. \u5de5\u5177\u5b8c\u6210 \u2192 \u8c03\u7528\/tool_result_callback\n5. AI\u91cd\u65b0\u751f\u6210\u5305\u542b\u7ed3\u679c\u7684\u56de\u590d\n6. \u8c03\u7528\/_notify_ui_refresh\uff08\u6216UI\u901a\u77e5\uff09\u663e\u793a\u56de\u590d\n\n\u6d41\u7a0b\u4e8c\uff1a\u7b80\u5355\u7ed3\u679c\u6d41\u7a0b\n1. \u7528\u6237\u63d0\u95ee\n2. AI\u51b3\u5b9a\u8c03\u7528\u5de5\u5177\n3. \u8c03\u7528\u5de5\u5177 \u2192 \u5de5\u5177\u6267\u884c\n4. \u5de5\u5177\u5b8c\u6210 \u2192 \u8c03\u7528\/tool_result\n5. \u76f4\u63a5\u663e\u793a\u7ed3\u679c\uff08\u4e0d\u7ecf\u8fc7AI\u91cd\u65b0\u7ec4\u7ec7\uff09\n'''\n# =======\u5173\u952e\u51fd\u6570\u548c\u65b9\u6cd5\uff1a=======\n'''\n\u65e5\u5fd7\u76f8\u5173\uff1a\n  message_manager.get_context_statistics() - \u83b7\u53d6\u7edf\u8ba1\n  message_manager.load_recent_context() - \u52a0\u8f7d\u5386\u53f2\n\u5de5\u5177\u8c03\u7528\u76f8\u5173\uff1a\n  message_manager.get_messages() - \u83b7\u53d6\u4f1a\u8bdd\u6d88\u606f\n  message_manager.add_message() - \u6dfb\u52a0\u6d88\u606f\u5230\u5386\u53f2\n  message_manager.save_conversation_log() - \u4fdd\u5b58\u65e5\u5fd7\nAI\u76f8\u5173\uff1a\n  get_llm_service() - \u83b7\u53d6AI\u670d\u52a1\n  llm_service.chat_with_context() - AI\u804a\u5929\nUI\u76f8\u5173\uff1a\n  chat.tool_ai_response_received.emit() - Qt\u4fe1\u53f7\u53d1\u9001\n'''\n# ==========\u9519\u8bef\u5904\u7406\u6a21\u5f0f\uff1a==========\n#\u6ce8\u610f\u8fd9\u4e9b\u63a5\u53e3\u90fd\u4f7f\u7528\u4e86\u76f8\u540c\u7684\u9519\u8bef\u5904\u7406\u6a21\u5f0f\uff1a\n'''\ntry:\n    # \u4e3b\u8981\u903b\u8f91\n    return {\"success\": True, ...}\nexcept Exception as e:\n    logger.error(f\"\u9519\u8bef\u4fe1\u606f: {e}\")\n    raise HTTPException(status_code=500, detail=str(e))\n'''\n#\u6574\u4f53\u67b6\u6784\u7406\u89e3\uff1a\n#\u8fd9\u90e8\u5206\u7684\u4ee3\u7801\u5c55\u793a\u4e86AI\u7cfb\u7edf\u7684\u6a21\u5757\u5316\u8bbe\u8ba1\uff1a\n'''\n\u7528\u6237\u754c\u9762 (UI)\n    \u2193\nAPI\u63a5\u53e3\u5c42 (\u8fd9\u4e9b\u63a5\u53e3)\n    \u2193\n\u4e1a\u52a1\u903b\u8f91\u5c42 (message_manager, llm_service)\n    \u2193\n\u5de5\u5177\u5c42 (\u5404\u79cd\u5de5\u5177\uff1a\u5929\u6c14\u3001\u641c\u7d22\u7b49)\n    \u2193\n\u6570\u636e\u5c42 (\u65e5\u5fd7\u3001\u5386\u53f2\u8bb0\u5f55)\n'''\n\n#\u8fd9\u6bb5\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e09\u4e2a\u5f02\u6b65\u51fd\u6570\uff0c\u5b83\u4eec\u90fd\u662f\u5185\u90e8\u4f7f\u7528\u7684\u5de5\u5177\u51fd\u6570\uff08\u4ee5_\u5f00\u5934\u8868\u793a\u79c1\u6709\uff09\u3002\u8fd9\u4e9b\u51fd\u6570\u7684\u4f5c\u7528\u662f\u628aAI\u7684\u56de\u590d\u53d1\u9001\u7ed9\u524d\u7aef\u7684\u7528\u6237\u754c\u9762\uff08UI\uff09\u3002\n\n#\u5185\u90e8\u8f85\u52a9\u51fd\u6570\uff08\u4e0eUI\u901a\u4fe1\uff09\nasync def _trigger_chat_stream_no_intent(session_id: str, response_text: str):\n    \"\"\"\u89e6\u53d1\u804a\u5929\u6d41\u5f0f\u54cd\u5e94\u4f46\u4e0d\u89e6\u53d1\u610f\u56fe\u5206\u6790 - \u53d1\u9001\u7eaf\u7cb9\u7684AI\u56de\u590d\u5230UI\"\"\"\n    try:\n        logger.info(f\"&#91;UI\u53d1\u9001] \u5f00\u59cb\u53d1\u9001AI\u56de\u590d\u5230UI\uff0c\u4f1a\u8bdd: {session_id}\")\n        logger.info(f\"&#91;UI\u53d1\u9001] \u53d1\u9001\u5185\u5bb9: {response_text&#91;:200]}...\")\n\n        # \u76f4\u63a5\u8c03\u7528\u73b0\u6709\u7684\u6d41\u5f0f\u5bf9\u8bdd\u63a5\u53e3\uff0c\u4f46\u8df3\u8fc7\u610f\u56fe\u5206\u6790\n        import httpx\n\n        # \u6784\u5efa\u8bf7\u6c42\u6570\u636e - \u4f7f\u7528\u7eaf\u7cb9\u7684AI\u56de\u590d\u5185\u5bb9\uff0c\u5e76\u8df3\u8fc7\u610f\u56fe\u5206\u6790\n        chat_request = {\n            \"message\": response_text,  # \u76f4\u63a5\u4f7f\u7528AI\u56de\u590d\u5185\u5bb9\uff0c\u4e0d\u52a0\u6807\u8bb0\n            \"stream\": True,\n            \"session_id\": session_id,\n            \"use_self_game\": False,\n            \"disable_tts\": False,\n            \"return_audio\": False,\n            \"skip_intent_analysis\": True  # \u5173\u952e\uff1a\u8df3\u8fc7\u610f\u56fe\u5206\u6790\n        }\n\n        # \u8c03\u7528\u73b0\u6709\u7684\u6d41\u5f0f\u5bf9\u8bdd\u63a5\u53e3\n        from system.config import get_server_port\n        api_url = f\"http:\/\/localhost:{get_server_port('api_server')}\/chat\/stream\"\n\n        async with httpx.AsyncClient() as client:\n            async with client.stream(\"POST\", api_url, json=chat_request) as response:   #json=chat_request\uff1a\u628a\u8bf7\u6c42\u6570\u636e\u8f6c\u4e3aJSON\u683c\u5f0f\n                if response.status_code == 200:\n                    # \u5904\u7406\u6d41\u5f0f\u54cd\u5e94\uff0c\u5305\u62ecTTS\u5207\u5272\n                    async for chunk in response.aiter_text():\n                        if chunk.strip():\n                            # \u8fd9\u91cc\u53ef\u4ee5\u8fdb\u4e00\u6b65\u5904\u7406\u6d41\u5f0f\u54cd\u5e94\n                            # \u6216\u8005\u76f4\u63a5\u8ba9UI\u5904\u7406\u6d41\u5f0f\u54cd\u5e94\n                            pass\n\n                    logger.info(f\"&#91;UI\u53d1\u9001] AI\u56de\u590d\u5df2\u6210\u529f\u53d1\u9001\u5230UI: {session_id}\")\n                    logger.info(f\"&#91;UI\u53d1\u9001] \u6210\u529f\u663e\u793a\u5230UI\")\n                else:\n                    logger.error(f\"&#91;UI\u53d1\u9001] \u8c03\u7528\u6d41\u5f0f\u5bf9\u8bdd\u63a5\u53e3\u5931\u8d25: {response.status_code}\")\n\n    except Exception as e:\n        logger.error(f\"&#91;UI\u53d1\u9001] \u89e6\u53d1\u804a\u5929\u6d41\u5f0f\u54cd\u5e94\u5931\u8d25: {e}\")\n\n#\u8fd9\u4e2a\u51fd\u6570\u6bd4\u7b2c\u4e00\u4e2a\u66f4\u76f4\u63a5\uff0c\u5b83\u76f4\u63a5\u8c03\u7528UI\u901a\u77e5\u63a5\u53e3\u3002\nasync def _notify_ui_refresh(session_id: str, response_text: str):\n    \"\"\"\u901a\u77e5UI\u5237\u65b0\u4f1a\u8bdd\u5386\u53f2\"\"\"\n    try:\n        import httpx\n\n        # \u901a\u8fc7UI\u901a\u77e5\u63a5\u53e3\u76f4\u63a5\u663e\u793aAI\u56de\u590d\n        ui_notification_payload = {\n            \"session_id\": session_id,\n            \"action\": \"show_tool_ai_response\",\n            \"ai_response\": response_text\n        }\n\n        from system.config import get_server_port\n        api_url = f\"http:\/\/localhost:{get_server_port('api_server')}\/ui_notification\"\n\n        async with httpx.AsyncClient(timeout=5.0) as client:\n            response = await client.post(api_url, json=ui_notification_payload)\n            if response.status_code == 200:\n                logger.info(f\"&#91;UI\u901a\u77e5] AI\u56de\u590d\u663e\u793a\u901a\u77e5\u53d1\u9001\u6210\u529f: {session_id}\")\n            else:\n                logger.error(f\"&#91;UI\u901a\u77e5] AI\u56de\u590d\u663e\u793a\u901a\u77e5\u5931\u8d25: {response.status_code}\")\n\n    except Exception as e:\n        logger.error(f\"&#91;UI\u901a\u77e5] \u901a\u77e5UI\u5237\u65b0\u5931\u8d25: {e}\")\n\n\n\n#\u8fd9\u662f\u7b2c\u4e09\u79cd\u65b9\u6cd5\uff0c\u901a\u8fc7\u975e\u6d41\u5f0f\u804a\u5929\u63a5\u53e3\u53d1\u9001\u3002\nasync def _send_ai_response_directly(session_id: str, response_text: str):\n    \"\"\"\u76f4\u63a5\u53d1\u9001AI\u56de\u590d\u5230UI\"\"\"\n    try:\n        import httpx\n\n        # \u4f7f\u7528\u975e\u6d41\u5f0f\u63a5\u53e3\u53d1\u9001AI\u56de\u590d\n        chat_request = {\n            \"message\": f\"&#91;\u5de5\u5177\u7ed3\u679c] {response_text}\",  # \u6dfb\u52a0\u6807\u8bb0\u8ba9UI\u77e5\u9053\u8fd9\u662f\u5de5\u5177\u7ed3\u679c\n            \"stream\": False,\n            \"session_id\": session_id,\n            \"use_self_game\": False,\n            \"disable_tts\": False,\n            \"return_audio\": False,\n            \"skip_intent_analysis\": True\n        }\n\n        from system.config import get_server_port\n        api_url = f\"http:\/\/localhost:{get_server_port('api_server')}\/chat\"\n\n        async with httpx.AsyncClient(timeout=10.0) as client:\n            response = await client.post(api_url, json=chat_request)\n            if response.status_code == 200:\n                logger.info(f\"&#91;\u76f4\u63a5\u53d1\u9001] AI\u56de\u590d\u5df2\u901a\u8fc7\u975e\u6d41\u5f0f\u63a5\u53e3\u53d1\u9001\u5230UI: {session_id}\")\n            else:\n                logger.error(f\"&#91;\u76f4\u63a5\u53d1\u9001] \u975e\u6d41\u5f0f\u63a5\u53e3\u53d1\u9001\u5931\u8d25: {response.status_code}\")\n\n    except Exception as e:\n        logger.error(f\"&#91;\u76f4\u63a5\u53d1\u9001] \u76f4\u63a5\u53d1\u9001AI\u56de\u590d\u5931\u8d25: {e}\")\n\n\n# \u5de5\u5177\u6267\u884c\u7ed3\u679c\u5df2\u901a\u8fc7LLM\u603b\u7ed3\u5e76\u4fdd\u5b58\u5230\u5bf9\u8bdd\u5386\u53f2\u4e2d\n# UI\u53ef\u4ee5\u901a\u8fc7\u67e5\u8be2\u5386\u53f2\u83b7\u53d6\u5de5\u5177\u6267\u884c\u7ed3\u679c\n\n# =======@\u7b26\u53f7\u9970\u5668\uff08Decorator\uff09==========\n#\u4ec0\u4e48\u662f\u88c5\u9970\u5668\uff1f\n#1. \u6700\u7b80\u5355\u7406\u89e3,\u88c5\u9970\u5668\u5c31\u50cf\u4e00\u4e2a\"\u5305\u88c5\u7eb8\"\uff0c\u5b83\u53ef\u4ee5\u628a\u4e00\u4e2a\u51fd\u6570\"\u5305\u88c5\"\u8d77\u6765\uff0c\u7ed9\u8fd9\u4e2a\u51fd\u6570\u589e\u52a0\u4e00\u4e9b\u989d\u5916\u7684\u529f\u80fd\uff0c\u4f46\u4e0d\u6539\u53d8\u51fd\u6570\u672c\u8eab\u7684\u6838\u5fc3\u903b\u8f91\u3002\n#\u751f\u6d3b\u6bd4\u55bb\uff1a\u5047\u8bbe\u4f60\u6709\u4e00\u4e2a\u666e\u901a\u7684\u793c\u7269\uff08\u51fd\u6570\uff09,\u7528\u6f02\u4eae\u7684\u5305\u88c5\u7eb8\u5305\u8d77\u6765\uff08\u88c5\u9970\u5668\uff09,\u793c\u7269\u672c\u8eab\u6ca1\u53d8\uff0c\u4f46\u73b0\u5728\u66f4\u597d\u770b\u4e86\uff08\u529f\u80fd\u66f4\u5f3a\u4e86\uff09\n\n#2. \u4ee3\u7801\u793a\u4f8b\u7406\u89e3\n'''\n\u6ca1\u6709\u88c5\u9970\u5668\u7684\u666e\u901a\u51fd\u6570\uff1a\ndef say_hello():\n    print(\"\u4f60\u597d\uff01\")\n\nsay_hello()  # \u8f93\u51fa\uff1a\u4f60\u597d\uff01\n\n\u4f7f\u7528\u88c5\u9970\u5668\u7684\u51fd\u6570\uff1a\ndef add_logging(func):  # \u88c5\u9970\u5668\u51fd\u6570\n    def wrapper():\n        print(\"\u5f00\u59cb\u8bb0\u5f55\u65e5\u5fd7...\")\n        func()\n        print(\"\u65e5\u5fd7\u8bb0\u5f55\u5b8c\u6210\u3002\")\n    return wrapper\n\n@add_logging  # \u4f7f\u7528\u88c5\u9970\u5668\ndef say_hello():\n    print(\"\u4f60\u597d\uff01\")\n\nsay_hello()\n# \u8f93\u51fa\uff1a\n# \u5f00\u59cb\u8bb0\u5f55\u65e5\u5fd7...\n# \u4f60\u597d\uff01\n# \u65e5\u5fd7\u8bb0\u5f55\u5b8c\u6210\u3002\n\nsay_hello\u51fd\u6570\u7684\u6838\u5fc3\u529f\u80fd\uff08\u6253\u5370\"\u4f60\u597d\uff01\"\uff09\u6ca1\u53d8\uff0c\u4f46\u901a\u8fc7@add_logging\u88c5\u9970\u5668\uff0c\u7ed9\u5b83\u589e\u52a0\u4e86\u8bb0\u5f55\u65e5\u5fd7\u7684\u529f\u80fd\u3002\n'''\n\n# =========FastAPI\u4e2d\u7684\u88c5\u9970\u5668============\n#\u5728FastAPI\u6846\u67b6\u4e2d\uff0c\u88c5\u9970\u5668\u6709\u7279\u5b9a\u7684\u7528\u9014\uff1a\u5b9a\u4e49API\u8def\u7531\u3002\n#1. \u57fa\u7840\u7528\u6cd5\n'''\n@app.get(\"\/\")  # \u88c5\u9970\u5668\uff1a\u628a\u4e0b\u9762\u7684\u51fd\u6570\u53d8\u6210\u4e00\u4e2a\u5904\u7406GET\u8bf7\u6c42\u7684API\nasync def root():\n    return {\"message\": \"Hello\"}\n    \n\u7406\u89e3\uff1a\n@app.get(\"\/\")\uff1a\u8fd9\u662f\u4e00\u4e2a\u88c5\u9970\u5668\n\u5b83\u544a\u8bc9FastAPI\uff1a\"\u5f53\u6709\u4eba\u8bbf\u95ee\u7f51\u7ad9\u7684\u6839\u8def\u5f84\uff08\/\uff09\u65f6\uff0c\u5c31\u6267\u884c\u4e0b\u9762\u7684root\u51fd\u6570\"\nroot\u51fd\u6570\u8fd4\u56de\u7684\u6570\u636e\u4f1a\u81ea\u52a8\u8f6c\u6362\u6210HTTP\u54cd\u5e94\n'''\n#2. \u5404\u79cdHTTP\u65b9\u6cd5\u7684\u88c5\u9970\u5668\n'''\n@app.get(\"\/users\")        # \u83b7\u53d6\u6570\u636e\n@app.post(\"\/users\")       # \u521b\u5efa\u6570\u636e\n@app.put(\"\/users\/{id}\")   # \u66f4\u65b0\u6570\u636e\n@app.delete(\"\/users\/{id}\") # \u5220\u9664\u6570\u636e\n\n\u8bb0\u5fc6\u65b9\u6cd5\uff1a\u5c31\u50cf\u6570\u636e\u5e93\u7684CRUD\u64cd\u4f5c\uff1a\nGET\uff1a\u8bfb\u53d6\uff08R\uff09\n\nPOST\uff1a\u521b\u5efa\uff08C\uff09\n\nPUT\uff1a\u66f4\u65b0\uff08U\uff09\n\nDELETE\uff1a\u5220\u9664\uff08D\uff09\n'''\n#\u8fd9\u4e2a\u4ee3\u7801\u4e2d\u51fa\u73b0\u7684\u6240\u6709\u88c5\u9970\u5668\u7c7b\u578b\n#\u8ba9\u6211\u4eec\u56de\u987e\u4e00\u4e0b\u4ee3\u7801\u4e2d\u51fa\u73b0\u7684\u5404\u79cd\u88c5\u9970\u5668\uff1a\n#1. \u8def\u7531\u88c5\u9970\u5668\uff08\u6700\u591a\uff09\n'''\n@app.get(\"\/\")                     # \u6839\u8def\u5f84\n@app.get(\"\/health\")               # \u5065\u5eb7\u68c0\u67e5\n@app.get(\"\/system\/info\")          # \u7cfb\u7edf\u4fe1\u606f\n@app.post(\"\/chat\")                # \u666e\u901a\u804a\u5929\n@app.post(\"\/chat\/stream\")         # \u6d41\u5f0f\u804a\u5929\n@app.get(\"\/memory\/stats\")         # \u8bb0\u5fc6\u7edf\u8ba1\n@app.get(\"\/sessions\")             # \u83b7\u53d6\u6240\u6709\u4f1a\u8bdd\n@app.get(\"\/sessions\/{session_id}\") # \u83b7\u53d6\u5355\u4e2a\u4f1a\u8bdd\n@app.delete(\"\/sessions\/{session_id}\") # \u5220\u9664\u4f1a\u8bdd\n@app.delete(\"\/sessions\")          # \u6e05\u7a7a\u6240\u6709\u4f1a\u8bdd\n@app.get(\"\/logs\/context\/statistics\") # \u65e5\u5fd7\u7edf\u8ba1\n@app.get(\"\/logs\/context\/load\")    # \u52a0\u8f7d\u65e5\u5fd7\n@app.post(\"\/tool_notification\")   # \u5de5\u5177\u901a\u77e5\n@app.post(\"\/tool_result_callback\") # \u5de5\u5177\u7ed3\u679c\u56de\u8c03\n@app.post(\"\/tool_result\")         # \u5de5\u5177\u7ed3\u679c\n@app.post(\"\/save_tool_conversation\") # \u4fdd\u5b58\u5de5\u5177\u5bf9\u8bdd\n@app.post(\"\/ui_notification\")     # UI\u901a\u77e5\n'''\n#2. \u7279\u6b8a\u7684\u751f\u547d\u5468\u671f\u88c5\u9970\u5668\n'''\n@asynccontextmanager  # \u8fd9\u662f\u4e00\u4e2a\u7279\u6b8a\u7684\u88c5\u9970\u5668\nasync def lifespan(app: FastAPI):\n    \"\"\"\u5e94\u7528\u751f\u547d\u5468\u671f\u7ba1\u7406\"\"\"\n    \n\u4f5c\u7528\uff1a\u8fd9\u4e2a\u88c5\u9970\u5668\u628a\u8fd9\u4e2a\u51fd\u6570\u53d8\u6210\u4e00\u4e2a\u5f02\u6b65\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\uff0c\u7528\u4e8e\u7ba1\u7406\u5e94\u7528\u7684\u542f\u52a8\u548c\u5173\u95ed\u3002    \n'''\n\n#\u88c5\u9970\u5668\u7684\u5de5\u4f5c\u539f\u7406\uff08\u66f4\u6df1\u5165\u4e00\u70b9\uff09\n#1. \u88c5\u9970\u5668\u5b9e\u9645\u4e0a\u5728\u505a\u4ec0\u4e48\uff1f\n'''\n\u5f53\u4f60\u5199\uff1a\n@app.get(\"\/hello\")\nasync def hello():\n    return \"World\"\n    \n\u5b9e\u9645\u4e0a\u76f8\u5f53\u4e8e\uff1a\ndef hello():\n    return \"World\"\n\nhello = app.get(\"\/hello\")(hello)  # \u88c5\u9970\u5668\u7684\u5e95\u5c42\u5b9e\u73b0\n'''\n\n# ======2. FastAPI\u88c5\u9970\u5668\u7684\u9b54\u6cd5 ===========\n'''\nFastAPI\u7684\u88c5\u9970\u5668\u505a\u4e86\u5f88\u591a\u4e8b\uff1a\n \u6ce8\u518c\u8def\u7531\uff1a\u628a\u8fd9\u4e2a\u51fd\u6570\u548cURL\u8def\u5f84\u5173\u8054\u8d77\u6765\n \u89e3\u6790\u53c2\u6570\uff1a\u81ea\u52a8\u89e3\u6790\u8bf7\u6c42\u53c2\u6570\u3001\u67e5\u8be2\u53c2\u6570\u3001\u8def\u5f84\u53c2\u6570\n \u9a8c\u8bc1\u6570\u636e\uff1a\u9a8c\u8bc1\u8bf7\u6c42\u6570\u636e\u7684\u683c\u5f0f\n \u751f\u6210\u6587\u6863\uff1a\u81ea\u52a8\u4e3a\u8fd9\u4e2a\u63a5\u53e3\u751f\u6210API\u6587\u6863\n \u5904\u7406\u54cd\u5e94\uff1a\u628a\u8fd4\u56de\u503c\u8f6c\u6362\u6210HTTP\u54cd\u5e94\n \n\u5bf9\u6bd4\uff08\u5982\u679c\u6ca1\u6709\u88c5\u9970\u5668\uff09\uff1a\n# \u6ca1\u6709\u88c5\u9970\u5668\u7684\u5199\u6cd5\uff08\u4f2a\u4ee3\u7801\uff09\ndef hello():\n    return \"World\"\n\n# \u9700\u8981\u624b\u52a8\u6ce8\u518c\u8def\u7531\napp.add_route(method=\"GET\", path=\"\/hello\", handler=hello)\n# \u9700\u8981\u624b\u52a8\u914d\u7f6e\u53c2\u6570\u89e3\u6790\n# \u9700\u8981\u624b\u52a8\u914d\u7f6e\u54cd\u5e94\u5904\u7406\n# ...\u5f88\u591a\u5176\u4ed6\u4ee3\u7801\n'''\n# ========\u88c5\u9970\u5668\u53c2\u6570\u7684\u89e3\u6790========\n'''\n1. \u8def\u5f84\u53c2\u6570\n@app.get(\"\/users\/{user_id}\")  # {user_id} \u662f\u8def\u5f84\u53c2\u6570\nasync def get_user(user_id: str):\n    return {\"user_id\": user_id}\n    \n2. \u67e5\u8be2\u53c2\u6570\n@app.get(\"\/items\")\nasync def read_items(skip: int = 0, limit: int = 10):\n    return {\"skip\": skip, \"limit\": limit}\n\u8bbf\u95ee\uff1a\/items?skip=0&amp;limit=10\n'''\n# \u5b9e\u9645\u6848\u4f8b\uff1a\u5206\u6790\u4ee3\u7801\u4e2d\u7684\u4e00\u4e2a\u88c5\u9970\u5668\n'''\n\u8ba9\u6211\u4eec\u8be6\u7ec6\u5206\u6790\u4ee3\u7801\u4e2d\u7684\u8fd9\u4e2a\u4f8b\u5b50\uff1a\n@app.post(\"\/chat\", response_model=ChatResponse)\nasync def chat(request: ChatRequest):\n    # ...\u51fd\u6570\u4f53...\n    \n\u8fd9\u4e2a\u88c5\u9970\u5668\u505a\u4e86\u4ee5\u4e0b\u4e8b\u60c5\uff1a\n  @app.post\uff1a\u8fd9\u662f\u4e00\u4e2aPOST\u8bf7\u6c42\u88c5\u9970\u5668\n  \"\/chat\"\uff1a\u8def\u5f84\u662f\/chat\n  response_model=ChatResponse\uff1a\n  \u6307\u5b9a\u54cd\u5e94\u6570\u636e\u7684\u683c\u5f0f\n  \u81ea\u52a8\u9a8c\u8bc1\u8fd4\u56de\u7684\u6570\u636e\u662f\u5426\u7b26\u5408ChatResponse\u7684\u683c\u5f0f\n  \u81ea\u52a8\u751f\u6210API\u6587\u6863\u4e2d\u7684\u54cd\u5e94\u793a\u4f8b\n'''\n#\u88c5\u9970\u5668\u7684\u6267\u884c\u987a\u5e8f\n'''\n\u5f53\u591a\u4e2a\u88c5\u9970\u5668\u88c5\u9970\u4e00\u4e2a\u51fd\u6570\u65f6\uff0c\u5b83\u4eec\u4ece\u4e0b\u5f80\u4e0a\u6267\u884c\uff1a\n@app.middleware(\"http\")  # \u7b2c\u4e8c\u4e2a\u6267\u884c\n@app.get(\"\/\")           # \u7b2c\u4e00\u4e2a\u6267\u884c\nasync def root():\n    return {\"message\": \"Hello\"}\n\u4f46\u5b9e\u9645\u4e0a\uff0c\u5728FastAPI\u4e2d\uff0c\u4f60\u5f88\u5c11\u4f1a\u770b\u5230\u591a\u4e2a\u88c5\u9970\u5668\u53e0\u52a0\u4f7f\u7528\u3002\n'''\n\n# \u603b\u7ed3\u88c5\u9970\u5668\u5728\u8fd9\u4e2a\u4ee3\u7801\u4e2d\u7684\u4f5c\u7528\uff1a\n'''\n\u88c5\u9970\u5668\t             |   \u4f5c\u7528\t         | \u7c7b\u6bd4\n@app.get(\"\/xxx\")\t | \u521b\u5efa\u4e00\u4e2aGET\u63a5\u53e3\t | \u5f00\u4e00\u4e2a\"\u53ea\u8bfb\"\u7a97\u53e3\n@app.delete(\"\/xxx\")\t | \u521b\u5efa\u4e00\u4e2aDELETE\u63a5\u53e3\t | \u5f00\u4e00\u4e2a\"\u5220\u9664\"\u7a97\u53e3\n@asynccontextmanager | \u521b\u5efa\u5f02\u6b65\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\t | \u8bbe\u7f6e\"\u5f00\u95e8\u5173\u95e8\"\u6d41\u7a0b\n'''\n#\u6574\u4f53\u6bd4\u55bb\uff1a\n'''\n\u8fd9\u4e2a\u7a0b\u5e8f\u5c31\u50cf\u4e00\u4e2a\u653f\u5e9c\u529e\u4e8b\u5927\u5385\n\u6bcf\u4e2a@app.get\/@app.post\u88c5\u9970\u5668\u5c31\u662f\u5f00\u4e00\u4e2a\u529e\u4e8b\u7a97\u53e3\n\u7a97\u53e3\u4e0a\u8d34\u7740\u6807\u7b7e\uff08\u8def\u5f84\uff09\uff1a\/chat\u3001\/health\u3001\/sessions\u7b49\n\u7a97\u53e3\u540e\u9762\u5750\u7740\u7684\u529e\u4e8b\u5458\u5c31\u662f\u88ab\u88c5\u9970\u7684\u51fd\u6570\n\u7fa4\u4f17\uff08\u5ba2\u6237\u7aef\uff09\u6765\u5230\u5bf9\u5e94\u7a97\u53e3\uff0c\u529e\u4e8b\u5458\u5c31\u5904\u7406\u4ed6\u4eec\u7684\u9700\u6c42\n'''\n#\u5e38\u89c1\u95ee\u9898\n'''\nQ\uff1a\u4e3a\u4ec0\u4e48\u6709\u4e9b\u88c5\u9970\u5668\u6709\u62ec\u53f7\uff0c\u6709\u4e9b\u6ca1\u6709\uff1f\nA\uff1a@app.get\u8fd9\u79cd\u6709\u62ec\u53f7\uff0c\u662f\u56e0\u4e3a\u5b83\u672c\u8eab\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u9700\u8981\u4f20\u9012\u53c2\u6570\uff08\u5982\u8def\u5f84\uff09\u3002@asynccontextmanager\u6ca1\u6709\u62ec\u53f7\u662f\u56e0\u4e3a\u5b83\u662f\u4e00\u4e2a\u88c5\u9970\u5668\u5de5\u5382\u3002\n\nQ\uff1a\u88c5\u9970\u5668\u4e00\u5b9a\u8981\u5199\u5728\u51fd\u6570\u4e0a\u9762\u5417\uff1f\nA\uff1a\u662f\u7684\uff0c\u88c5\u9970\u5668\u5fc5\u987b\u7d27\u6328\u7740\u51fd\u6570\u5b9a\u4e49\uff0c\u5199\u5728\u51fd\u6570\u5b9a\u4e49\u7684\u524d\u4e00\u884c\u3002\n\nQ\uff1a\u4e00\u4e2a\u51fd\u6570\u53ef\u4ee5\u6709\u591a\u4e2a\u88c5\u9970\u5668\u5417\uff1f\nA\uff1a\u53ef\u4ee5\uff0c\u4f46\u4e0d\u5e38\u89c1\u3002\u5982\u679c\u6709\uff0c\u6267\u884c\u987a\u5e8f\u662f\u4ece\u4e0b\u5f80\u4e0a\u3002\n'''\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">__init__.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\"\"\"\nNagaAgent API\u670d\u52a1\u5668\u6a21\u5757\n\"\"\"\n\nfrom .api_server import app\n\n__all__ = &#91;'app'] \n\n'''\n__init__.py \u6587\u4ef6\u867d\u7136\u4ee3\u7801\u77ed\uff0c\u4f46\u4f5c\u7528\u7279\u522b\u5173\u952e\uff0c\u662f Python \u5305\uff08package\uff09\u7684\u6838\u5fc3\u6807\u8bc6\u548c\u5bfc\u51fa\u63a7\u5236\u6587\n\n\u6838\u5fc3\u4f5c\u7528\u62c6\u89e3\n1.\u6807\u8bb0\u5305\u8eab\u4efd\n\u53ea\u8981\u76ee\u5f55\u91cc\u6709 __init__.py\uff0cPython \u5c31\u4f1a\u628a\u8fd9\u4e2a\u76ee\u5f55\u8bc6\u522b\u6210\u4e00\u4e2a\u53ef\u5bfc\u5165\u7684\u5305\uff0c\u800c\u4e0d\u662f\u666e\u901a\u6587\u4ef6\u5939\u3002\n\u6ca1\u6709\u5b83\u7684\u8bdd\uff0c\u4f60\u6ca1\u6cd5\u7528 import apiserver \u8fd9\u79cd\u65b9\u5f0f\u5bfc\u5165\u8fd9\u4e2a\u76ee\u5f55\u4e0b\u7684\u4ee3\u7801\u3002\nPython 3.3+ \u4e4b\u524d\uff0c\u76ee\u5f55\u5fc5\u987b\u6709 __init__.py \u624d\u88ab\u8ba4\u4e3a\u662f\u5305\u3002\u73b0\u5728\u867d\u7136\u53ef\u4ee5\u662f\u9690\u5f0f\u547d\u540d\u7a7a\u95f4\u5305\uff0c\u4f46\u663e\u5f0f\u521b\u5efa\u4ecd\u7136\u662f\u6700\u4f73\u5b9e\u8df5\u3002\n\n2.\u7b80\u5316\u5bfc\u5165\u903b\u8f91\n\u4ee3\u7801\u91cc from .api_server import app \u662f\u628a api_server.py \u91cc\u7684 app \u5bf9\u8c61\u5bfc\u5165\u5230\u5305\u7684\u201c\u6839\u5c42\u7ea7\u201d\u3002\n\u539f\u672c\u4f60\u8981\u5199 from apiserver.api_server import app\uff0c\u73b0\u5728\u53ef\u4ee5\u76f4\u63a5\u5199 from apiserver import app\uff0c\u66f4\u7b80\u6d01\u3002\n\u6ca1\u6709 __init__.py \u65f6\uff1a\n# \u7528\u6237\u9700\u8981\u77e5\u9053\u5185\u90e8\u7ed3\u6784\nfrom mypackage.module1 import ClassA\nfrom mypackage.module2 import function1\nfrom mypackage.subpackage.module3 import helper\n\u6709 __init__.py \u65f6\uff1a\n# mypackage\/__init__.py\nfrom .module1 import ClassA\nfrom .module2 import function1\nfrom .subpackage.module3 import helper\n_init_.py:# \u7528\u6237\u4f7f\u7528\u66f4\u7b80\u6d01\nfrom mypackage import ClassA, function1, helper\n\n3.\u63a7\u5236\u5bfc\u51fa\u8303\u56f4\uff08all\uff09\n__all__ = &#91;'app'] \u662f\u5b9a\u4e49\u8fd9\u4e2a\u5305\u88abfrom apiserver import * \u5bfc\u5165\u65f6\uff0c\u5bf9\u5916\u66b4\u9732\u7684\u5185\u5bb9\u53ea\u6709 app\u3002\n\u907f\u514d\u628a\u6a21\u5757\u91cc\u7684\u5176\u4ed6\u65e0\u5173\u53d8\u91cf\/\u51fd\u6570\u4e5f\u88ab\u6279\u91cf\u5bfc\u5165\uff0c\u89c4\u8303\u5305\u7684\u5bf9\u5916\u63a5\u53e3\n\u5f53\u7528\u6237\u4f7f\u7528 from apiserver import * \u65f6,\u53ea\u4f1a\u5bfc\u5165 __all__ \u4e2d\u6307\u5b9a\u7684\u5185\u5bb9\n\n4. \u66b4\u9732\u6838\u5fc3\u529f\u80fd\n\u5b9e\u9645\u6848\u4f8b\u6f14\u793a\uff1a\n\u9879\u76ee\u7ed3\u6784\uff1a\nmypackage\/\n    \u251c\u2500\u2500 __init__.py          # \u5305\u7684\u4e3b\u5165\u53e3\n    \u251c\u2500\u2500 utils.py            # \u5185\u90e8\u5de5\u5177\u51fd\u6570\n    \u251c\u2500\u2500 core.py             # \u6838\u5fc3\u7c7b\n    \u2514\u2500\u2500 submodule\/\n        \u251c\u2500\u2500 __init__.py     # \u5b50\u5305\u7684\u5165\u53e3\n        \u2514\u2500\u2500 helper.py\n \u5185\u5bb9\uff1a  \n # mypackage\/utils.py\ndef internal_helper():\n    return \"\u5185\u90e8\u4f7f\u7528\u7684\u5de5\u5177\u51fd\u6570\"\n\ndef user_helper():\n    return \"\u63d0\u4f9b\u7ed9\u7528\u6237\u7684\u5de5\u5177\u51fd\u6570\"\n =================== \n# mypackage\/core.py\nclass DataProcessor:\n    def process(self):\n        return \"\u5904\u7406\u6570\u636e\"\n    \nclass Analyzer:\n    def analyze(self):\n        return \"\u5206\u6790\u6570\u636e\"      \n ================       \n# mypackage\/submodule\/helper.py\nclass SpecialHelper:\n    def help(self):\n        return \"\u7279\u6b8a\u5e2e\u52a9\"\n        \n\u73b0\u5728\u914d\u7f6e __init__.py\uff1a \n# mypackage\/__init__.py\nfrom .core import DataProcessor, Analyzer\nfrom .utils import user_helper\n\n# \u7248\u672c\u4fe1\u606f\n__version__ = \"1.0.0\"\n__author__ = \"Your Name\"\n\n# \u63a7\u5236 from mypackage import * \u7684\u884c\u4e3a\n__all__ = &#91;'DataProcessor', 'Analyzer', 'user_helper']\n\n# \u53ef\u9009\uff1a\u521d\u59cb\u5316\u4ee3\u7801\nprint(f\"Initializing {__name__} version {__version__}\")\n===================\n# mypackage\/submodule\/__init__.py\nfrom .helper import SpecialHelper\n\n\u7528\u6237\u4f7f\u7528\u4f53\u9a8c\uff1a\n# \u7528\u6237\u4ee3\u7801 - \u6781\u5176\u7b80\u6d01\nfrom mypackage import DataProcessor, user_helper\nfrom mypackage.submodule import SpecialHelper\n\n# \u6216\u8005\u5168\u90e8\u4ece\u4e3b\u5305\u5bfc\u5165\nimport mypackage\n\ndp = mypackage.DataProcessor()\nresult = mypackage.user_helper()\n\n5. \u5176\u4ed6\u91cd\u8981\u529f\u80fd\n\u7248\u672c\u7ba1\u7406\n# __init__.py\n__version__ = \"2.1.0\"\n__version_info__ = (2, 1, 0)\n\n\u5305\u7ea7\u522b\u7684\u914d\u7f6e  \n# __init__.py\nimport logging\n\n# \u8bbe\u7f6e\u5305\u7ea7\u522b\u7684\u65e5\u5fd7\nlogger = logging.getLogger(__name__)\n\n# \u5305\u914d\u7f6e\nDEFAULT_CONFIG = {\n    'timeout': 30,\n    'retry': 3\n}   \n\n\u5ef6\u8fdf\u5bfc\u5165\uff08Lazy Import\uff09  \n# __init__.py\ndef __getattr__(name):\n    \"\"\"\u6309\u9700\u5bfc\u5165\uff0c\u51cf\u5c11\u542f\u52a8\u65f6\u95f4\"\"\"\n    if name == \"HeavyClass\":\n        from .heavy_module import HeavyClass\n        return HeavyClass\n    raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\") \n    \n6. \u5b9e\u9645\u8bbe\u8ba1\u6a21\u5f0f\n\u6a21\u5f0f\u4e00\uff1aAPI\u95e8\u9762\uff08Facade\uff09\n# __init__.py\n# \u5c06\u6240\u6709\u91cd\u8981\u7684\u7c7b\u3001\u51fd\u6570\u5bfc\u51fa\u5230\u5305\u7ea7\u522b\nfrom .module1 import APIClient, Connection\nfrom .module2 import process_data, validate_input\nfrom .module3 import Result, Error\n\n__all__ = &#91;\n    'APIClient', 'Connection',\n    'process_data', 'validate_input',\n    'Result', 'Error'\n]\n\u6a21\u5f0f\u4e8c\uff1a\u5b50\u5305\u91cd\u5bfc\u51fa\n# __init__.py\n# \u5c06\u5b50\u5305\u7684\u5185\u5bb9\u63d0\u5347\u5230\u4e3b\u5305\u7ea7\u522b\nfrom . import subpackage1\nfrom . import subpackage2\n\n# \u53ef\u4ee5\u76f4\u63a5\u5bfc\u5165\u5b50\u5305\u4e2d\u7684\u7279\u5b9a\u5185\u5bb9\nfrom .subpackage1.core import CoreClass\nfrom .subpackage2.helpers import helper_func    \n'''\n#\u7b80\u5355\u8bf4\uff0c\u5b83\u5c31\u50cf\u8fd9\u4e2a apiserver \u5305\u7684\u201c\u95e8\u9762\u201d\uff1a\u544a\u8bc9 Python \u8fd9\u662f\u4e2a\u5408\u6cd5\u5305\uff0c\u540c\u65f6\u628a\u6838\u5fc3\u7684 app \u66b4\u9732\u51fa\u6765\uff0c\u8ba9\u5916\u90e8\u7528\u8d77\u6765\u66f4\u65b9\u4fbf<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>llm_service.py start_server.py streaming_tool_extractor [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,55],"tags":[],"class_list":["post-1285","post","type-post","status-publish","format-standard","hentry","category-open-source-analysis","category-technology"],"_links":{"self":[{"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1285","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/comments?post=1285"}],"version-history":[{"count":5,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1285\/revisions"}],"predecessor-version":[{"id":1294,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1285\/revisions\/1294"}],"wp:attachment":[{"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/media?parent=1285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/categories?post=1285"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.preluna.xyz\/index.php\/wp-json\/wp\/v2\/tags?post=1285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}