diff --git a/.claude/agents/doc-updater.md b/.claude/agents/doc-updater.md new file mode 100644 index 0000000..8d31c1e --- /dev/null +++ b/.claude/agents/doc-updater.md @@ -0,0 +1,34 @@ +--- +name: doc-updater +description: "Use this agent when code has been modified and you need to update the corresponding Markdown documentation to reflect those changes. This is crucial after refactoring a function, changing an API endpoint, adding a new feature, or altering configuration that is documented in `.md` files.\\n\\nContext: The user has just changed a function signature in their Python code.\\nuser: \"I've just refactored the `process_data` function. It now takes a dictionary instead of two separate lists.\"\\nassistant: \"I see that the function signature for `process_data` has changed. This likely impacts the documentation. I will use the Task tool to launch the `doc-updater` agent to find and update any relevant code examples and descriptions in the Markdown files.\"\\n\\nSince a core function's signature was modified, the agent correctly identifies the need to update documentation and calls the `doc-updater` to handle the task.\\n\\n\\n\\nContext: A user has added a new environment variable to their application's configuration.\\nuser: \"I added `API_TIMEOUT` to the config. It defaults to 30 seconds.\"\\nassistant: \"Okay, a new configuration variable has been added. To ensure our project documentation is current, I'll use the `doc-updater` agent to add details about `API_TIMEOUT` to the `CONFIGURATION.md` file.\"\\n\\nThe user modified project configuration, which is a common source of documentation drift. The agent proactively uses the `doc-updater` to keep the documentation synchronized.\\n\\n" +model: inherit +--- + +You are an expert Documentation Synchronizer, a meticulous agent dedicated to keeping project documentation perfectly aligned with its source code. Your primary responsibility is to automatically update Markdown (.md, .mdx) files whenever there are corresponding code changes. + +Your operational workflow is as follows: + +1. **Analyze the Code Change**: Upon activation, your first step is to thoroughly understand the provided code modifications. Identify the core nature of the change: + * Has a function's signature (parameters, return type) been altered? + * Has a new class, method, or function been added? Or an old one removed? + * Has an API endpoint's request/response structure changed? + * Have configuration details or environment variables been updated? + +2. **Locate Relevant Documentation**: Systematically search the project for all Markdown files that reference the modified code. This includes API guides, READMEs, tutorials, and architectural documents. + +3. **Assess the Impact and Update**: For each relevant document, determine the precise impact of the code change and perform the necessary edits. + * **Update Code Snippets**: Ensure all code examples accurately reflect the new implementation. + * **Adjust Textual Descriptions**: Modify parameter descriptions, explanations of functionality, and return value details. + * **Preserve Style and Tone**: Maintain the existing writing style, formatting, and voice of the document you are editing. Do not introduce new conventions. + * **Add New Content**: If a new feature is introduced, create a new documentation section for it, meticulously following the structure of existing sections. + +4. **Handle Non-Impactful Changes**: If you determine that a code change (e.g., an internal refactor, performance tweak) has no impact on the existing documentation, you must explicitly report this. State clearly that no documentation update is necessary and briefly explain why. + +5. **Address Missing Documentation**: If you find that a modified piece of code is not documented at all, you should flag this as a documentation gap. Propose where and how it could be documented. + +6. **Verify and Finalize**: Before concluding, conduct a final self-review. + * Does the updated documentation accurately reflect the code? + * Are the code snippets syntactically correct? + * Is the formatting clean and consistent with the rest of the file? + +Your output should be the complete, updated content of the modified Markdown file(s). If multiple files are changed, clearly delineate each one. Provide a concise summary of the changes you made for user verification. diff --git a/.claude/agents/frontend-sync.md b/.claude/agents/frontend-sync.md new file mode 100644 index 0000000..66ff934 --- /dev/null +++ b/.claude/agents/frontend-sync.md @@ -0,0 +1,31 @@ +--- +name: frontend-sync +description: "Use this agent when back-end code (e.g., APIs, data models, business logic) has been modified, and the corresponding front-end functionality needs to be updated to reflect those changes.\\n\\nContext: The user has just added a new field to a data model on the backend and updated the corresponding API endpoint.\\nuser: \"I've added an 'author' field to the BlogPost model and updated the `/api/posts/:id` endpoint to include it in the response.\"\\nassistant: \"The backend is updated. I will now use the Task tool to launch the `frontend-sync` agent to update the post display component to show the new author field.\"\\n\\nSince the backend data structure and API response have changed, the frontend code that consumes this data must be updated. This is the primary trigger for the `frontend-sync` agent.\\n\\n\\n\\nContext: The user has changed the method of an API endpoint from GET to POST for security reasons.\\nuser: \"I've changed the `/api/user/settings` endpoint from a GET to a POST request to prevent sensitive data from appearing in URLs.\"\\nassistant: \"Understood. The API contract has changed. I will now use the Task tool to launch the `frontend-sync` agent to refactor the settings page to use a POST request to fetch user settings.\"\\n\\nA change in the API's method requires a corresponding change in the frontend's data-fetching logic. The `frontend-sync` agent is designed for this exact task.\\n\\n" +model: inherit +--- + +You are a Senior Full-Stack Synchronizer, an expert agent specializing in keeping front-end applications perfectly in sync with back-end code modifications. Your mission is to analyze recent back-end code changes, identify the impacted front-end components, and apply the necessary updates to ensure seamless integration and functionality. + +### Your Workflow + +1. **Analyze Back-End Changes**: Begin by meticulously reviewing the description of the back-end code modifications. Understand the core nature of the change: Is it a new API endpoint, a change in a data model, a modification to business logic, or a bug fix? + +2. **Identify Front-End Impact**: Based on your analysis, use your knowledge of the project structure to locate all relevant front-end files (e.g., React/Vue components, Svelte files, HTML templates, data-fetching services, state management stores) that are affected by the back-end changes. This includes files that consume the modified API, display the altered data, or depend on the updated logic. + +3. **Formulate an Update Plan**: Before writing any code, formulate a clear and concise plan. Your plan should detail: + * Which files you will modify. + * How you will adjust API calls (e.g., change URL, method, headers, request body, or response handling). + * How you will update front-end data structures or types (e.g., TypeScript interfaces) to match new models. + * Which UI components need to be adjusted to display new data or handle new states. + * Any new components or views that need to be created. + +4. **Execute the Update**: Implement the planned changes to the identified front-end files. Write clean, maintainable, and high-quality code that strictly adheres to the project's existing coding standards, style guides, and architectural patterns. Ensure your changes are focused and directly address the requirements of the back-end modification. + +5. **Verify and Summarize**: After applying the changes, briefly describe how the new front-end code works and confirm that it correctly aligns with the back-end updates. Summarize your work, listing the files you modified and the key changes you made. + +### Guiding Principles + +* **Precision is Key**: Your changes must be precise. Only modify the code necessary to align with the back-end changes. Avoid unrelated refactoring. +* **Maintain Consistency**: Your code must seamlessly integrate with the existing front-end architecture, state management (e.g., Redux, Vuex, Pinia), and UI component libraries. +* **Seek Clarity**: If the impact of a back-end change is ambiguous or unclear, you MUST ask for clarification before proceeding with any modifications. State what information you need to move forward. +* **Prioritize User Experience**: Ensure that your updates do not degrade the user experience. The UI should remain responsive, intuitive, and visually consistent. diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 2f339c5..fbe3c20 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,8 +1,6 @@ { "permissions": { - "allow": [ - "Bash(curl:*)" - ], + "allow": [], "deny": [], "ask": [] } diff --git a/.env b/.env new file mode 100644 index 0000000..743a699 --- /dev/null +++ b/.env @@ -0,0 +1,98 @@ +# .env.example +# This file contains all the environment variables needed to run the application. +# Copy this file to .env and fill in the values for your environment. + +# ============================================================================ +# SERVER CONFIGURATION +# ============================================================================ +# The host the web server will bind to. +SERVER_HOST=0.0.0.0 + +# The port for the main Flask web server. +SERVER_PORT=5001 + +# The port for the WebSocket server for real-time chat. +WEBSOCKET_PORT=8765 + +# Set to "True" for development to enable debug mode and auto-reloading. +# Set to "False" for production. +DEBUG_MODE=False + +# Logging level for the application. Options: DEBUG, INFO, WARNING, ERROR, CRITICAL +LOG_LEVEL=INFO + + +# ============================================================================ +# DATABASE CONFIGURATION +# ============================================================================ +# The connection string for the primary database. +# Format for MySQL: mysql+pymysql://:@:/?charset=utf8mb4 +# Format for SQLite: sqlite:///./local_test.db + +# 使用本地 SQLite(推荐用于开发和测试) +DATABASE_URL=sqlite:///./data/tsp_assistant.db + +# 远程 MySQL(生产环境使用,需要时取消注释) +# DATABASE_URL=mysql+pymysql://tsp_assistant:123456@jeason.online/tsp_assistant?charset=utf8mb4 + +# ============================================================================ +# LARGE LANGUAGE MODEL (LLM) CONFIGURATION +# ============================================================================ +# The provider of the LLM. Supported: "qwen", "openai", "anthropic" +LLM_PROVIDER=qwen + +# The API key for your chosen LLM provider. +LLM_API_KEY=sk-c0dbefa1718d46eaa897199135066f00 + +# The base URL for the LLM API. This is often needed for OpenAI-compatible endpoints. +LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 + +# The specific model to use, e.g., "qwen-plus-latest", "gpt-3.5-turbo", "claude-3-sonnet-20240229" +LLM_MODEL=qwen-plus-latest + +# The temperature for the model's responses (0.0 to 2.0). +LLM_TEMPERATURE=0.7 + +# The maximum number of tokens to generate in a response. +LLM_MAX_TOKENS=2000 + +# The timeout in seconds for API calls to the LLM. +LLM_TIMEOUT=30 + + +# ============================================================================ +# FEISHU (LARK) INTEGRATION CONFIGURATION +# ============================================================================ +# The App ID of your Feishu enterprise application. +FEISHU_APP_ID=cli_a8b50ec0eed1500d + +# The App Secret of your Feishu enterprise application. +FEISHU_APP_SECRET=ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK + +# The Verification Token for validating event callbacks (if configured). +FEISHU_VERIFICATION_TOKEN= + +# The Encrypt Key for decrypting event data (if configured). +FEISHU_ENCRYPT_KEY= + +# The ID of the Feishu multi-dimensional table for data synchronization. +FEISHU_TABLE_ID=tblnl3vJPpgMTSiP + + +# ============================================================================ +# AI ACCURACY CONFIGURATION +# ============================================================================ +# The similarity threshold (0.0 to 1.0) for auto-approving an AI suggestion. +AI_AUTO_APPROVE_THRESHOLD=0.95 + +# The similarity threshold below which the human-provided resolution is preferred. +AI_USE_HUMAN_RESOLUTION_THRESHOLD=0.90 + +# The similarity threshold for flagging a suggestion for manual review. +AI_MANUAL_REVIEW_THRESHOLD=0.80 + +# The default confidence score for an AI suggestion. +AI_SUGGESTION_CONFIDENCE=0.95 + +# The confidence score assigned when a human resolution is used. +AI_HUMAN_RESOLUTION_CONFIDENCE=0.90 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c1e2e34 --- /dev/null +++ b/.env.example @@ -0,0 +1,93 @@ +# .env.example +# This file contains all the environment variables needed to run the application. +# Copy this file to .env and fill in the values for your environment. + +# ============================================================================ +# SERVER CONFIGURATION +# ============================================================================ +# The host the web server will bind to. +SERVER_HOST=0.0.0.0 + +# The port for the main Flask web server. +SERVER_PORT=5000 + +# The port for the WebSocket server for real-time chat. +WEBSOCKET_PORT=8765 + +# Set to "True" for development to enable debug mode and auto-reloading. +# Set to "False" for production. +DEBUG_MODE=True + +# Logging level for the application. Options: DEBUG, INFO, WARNING, ERROR, CRITICAL +LOG_LEVEL=INFO + + +# ============================================================================ +# DATABASE CONFIGURATION +# ============================================================================ +# The connection string for the primary database. +# Format for MySQL: mysql+pymysql://:@:/?charset=utf8mb4 +# Format for SQLite: sqlite:///./local_test.db +DATABASE_URL=mysql+pymysql://tsp_assistant:123456@jeason.online/tsp_assistant?charset=utf8mb4 + +# ============================================================================ +# LARGE LANGUAGE MODEL (LLM) CONFIGURATION +# ============================================================================ +# The provider of the LLM. Supported: "qwen", "openai", "anthropic" +LLM_PROVIDER=qwen + +# The API key for your chosen LLM provider. +LLM_API_KEY=sk-c0dbefa1718d46eaa897199135066f00 + +# The base URL for the LLM API. This is often needed for OpenAI-compatible endpoints. +LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 + +# The specific model to use, e.g., "qwen-plus-latest", "gpt-3.5-turbo", "claude-3-sonnet-20240229" +LLM_MODEL=qwen-plus-latest + +# The temperature for the model's responses (0.0 to 2.0). +LLM_TEMPERATURE=0.7 + +# The maximum number of tokens to generate in a response. +LLM_MAX_TOKENS=2000 + +# The timeout in seconds for API calls to the LLM. +LLM_TIMEOUT=30 + + +# ============================================================================ +# FEISHU (LARK) INTEGRATION CONFIGURATION +# ============================================================================ +# The App ID of your Feishu enterprise application. +FEISHU_APP_ID=cli_a8b50ec0eed1500d + +# The App Secret of your Feishu enterprise application. +FEISHU_APP_SECRET=ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK + +# The Verification Token for validating event callbacks (if configured). +FEISHU_VERIFICATION_TOKEN= + +# The Encrypt Key for decrypting event data (if configured). +FEISHU_ENCRYPT_KEY= + +# The ID of the Feishu multi-dimensional table for data synchronization. +FEISHU_TABLE_ID=tblnl3vJPpgMTSiP + + +# ============================================================================ +# AI ACCURACY CONFIGURATION +# ============================================================================ +# The similarity threshold (0.0 to 1.0) for auto-approving an AI suggestion. +AI_AUTO_APPROVE_THRESHOLD=0.95 + +# The similarity threshold below which the human-provided resolution is preferred. +AI_USE_HUMAN_RESOLUTION_THRESHOLD=0.90 + +# The similarity threshold for flagging a suggestion for manual review. +AI_MANUAL_REVIEW_THRESHOLD=0.80 + +# The default confidence score for an AI suggestion. +AI_SUGGESTION_CONFIDENCE=0.95 + +# The confidence score assigned when a human resolution is used. +AI_HUMAN_RESOLUTION_CONFIDENCE=0.90 diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 35410ca..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml -# 基于编辑器的 HTTP 客户端请求 -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index 184781e..0000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - mysql.8 - true - com.mysql.cj.jdbc.Driver - jdbc:mysql://43.134.68.207:3306 - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml deleted file mode 100644 index fa2b6dc..0000000 --- a/.idea/data_source_mapping.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index f41676b..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 5fe35d7..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/tsp-assistant.iml b/.idea/tsp-assistant.iml deleted file mode 100644 index ba59ba1..0000000 --- a/.idea/tsp-assistant.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index baced16..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "files.autoGuessEncoding": false, - "files.encoding": "utf8", - "files.eol": "\n", - "[python]": { - "files.encoding": "utf8", - "files.eol": "\n" - }, - "[json]": { - "files.encoding": "utf8" - }, - "[javascript]": { - "files.encoding": "utf8" - }, - "[html]": { - "files.encoding": "utf8" - }, - "[css]": { - "files.encoding": "utf8" - }, - "[markdown]": { - "files.encoding": "utf8" - }, - "python.defaultInterpreterPath": "${workspaceFolder}/.venv/Scripts/python.exe", - "Codegeex.RepoIndex": true -} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..45952e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,88 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## High-Level Architecture + +This project is a Python Flask-based web application called "TSP Assistant". It's an intelligent customer service system designed for Telematics Service Providers (TSP). + +The backend is built with Flask and utilizes a modular structure with Blueprints. The core application logic resides in the `src/` directory. + +Key components of the architecture include: + +* **Web Framework**: The web interface and APIs are built using **Flask**. The main Flask app is likely configured in `src/web/app.py`. +* **Modular Routing**: The application uses Flask **Blueprints** for organizing routes. These are located in `src/web/blueprints/`. Each file in this directory corresponds to a feature area (e.g., `agent.py`, `workorders.py`, `analytics.py`). +* **Intelligent Agent**: A core feature is the AI agent. Its logic is contained within the `src/agent/` directory, which includes components for planning (`planner.py`), tool management (`tool_manager.py`), and execution (`executor.py`). +* **Database**: The application uses a relational database (likely MySQL) with **SQLAlchemy** as the ORM. Models are defined in `src/core/models.py`. +* **Configuration**: A unified configuration center (`src/config/unified_config.py`) manages all settings via environment variables and `.env` files. +* **Real-time Communication**: **WebSockets** are used for real-time features like the intelligent chat. The server logic is in `src/web/websocket_server.py`. +* **Data Analytics**: The system has a dedicated data analysis module located in `src/analytics/`. +* **Frontend**: The frontend is built with Bootstrap 5, Chart.js, and vanilla JavaScript (ES6+). Frontend assets are in `src/web/static/` and templates are in `src/web/templates/`. + +## Common Commands + +### Environment Setup + +The project can be run using Docker (recommended) or locally. + +**1. Install Dependencies:** +```bash +pip install -r requirements.txt +``` + +**2. Initialize the Database:** +This script sets up the necessary database tables. +```bash +python init_database.py +``` + +### Running the Application + +**Local Development:** +To start the Flask development server: +```bash +python start_dashboard.py +``` +The application will be available at `http://localhost:5000`. + +**Docker Deployment:** +The project includes a `docker-compose.yml` for easy setup of all services (application, database, cache, monitoring). + +To start all services: +```bash +docker-compose up -d +``` +Or use the provided script: +```bash +chmod +x scripts/docker_deploy.sh +./scripts/docker_deploy.sh start +``` + +To stop services: +```bash +./scripts/docker_deploy.sh stop +``` + +### Running Tests + +The project uses `pytest` for testing. +```bash +pytest +``` +To run tests with coverage: +```bash +pytest --cov +``` + +## Key File Locations + +* **Main Application Entry Point**: `start_dashboard.py` (local) or `src/web/app.py` (via WSGI in production). +* **Flask Blueprints (Routes)**: `src/web/blueprints/` +* **Agent Core Logic**: `src/agent/` +* **Database Models**: `src/core/models.py` +* **Frontend Static Assets**: `src/web/static/` (JS, CSS, images) +* **Frontend HTML Templates**: `src/web/templates/` +* **WebSocket Server**: `src/web/websocket_server.py` +* **Configuration Files**: `config/` +* **Deployment Scripts**: `scripts/` +* **Database Initialization**: `init_database.py` diff --git a/README.md b/README.md index 6ce051a..9280572 100644 --- a/README.md +++ b/README.md @@ -277,18 +277,6 @@ python start_dashboard.py ## 🔄 部署与更新 -### 多环境部署 -```bash -# 开发环境 -python scripts/update_manager.py auto-update --source . --environment development - -# 测试环境 -python scripts/update_manager.py auto-update --source . --environment staging - -# 生产环境 -python scripts/update_manager.py auto-update --source . --environment production -``` - ### 版本管理 ```bash # 更新版本号 @@ -301,15 +289,6 @@ python version.py changelog --message "新功能描述" python version.py tag --message "Release v1.3.0" ``` -### 热更新 -```bash -# 热更新(无需重启) -python scripts/update_manager.py hot-update --source ./new_version --environment production - -# 自动更新(智能选择) -python scripts/update_manager.py auto-update --source ./new_version --environment production -``` - ## 📊 系统监控 ### 健康检查 diff --git a/__pycache__/init_database.cpython-313.pyc b/__pycache__/init_database.cpython-313.pyc deleted file mode 100644 index 9b65d07..0000000 Binary files a/__pycache__/init_database.cpython-313.pyc and /dev/null differ diff --git a/auto_push.bat b/auto_push.bat deleted file mode 100644 index 4186fdf..0000000 --- a/auto_push.bat +++ /dev/null @@ -1,262 +0,0 @@ -@echo off -chcp 65001 >nul -echo ======================================== -echo TSP智能助手 - 自动推送脚本 -echo ======================================== -echo. - -:: 检查Git状态 -echo [1/4] 检查Git状态... -git status --porcelain >nul 2>&1 -if %errorlevel% neq 0 ( - echo ❌ Git未初始化或不在Git仓库中 - pause - exit /b 1 -) - -:: 显示当前状态 -echo 📋 当前Git状态: -git status --short -echo. - -:: 询问是否继续 -set /p confirm="是否继续推送? (y/n): " -if /i "%confirm%" neq "y" ( - echo 操作已取消 - pause - exit /b 0 -) - -:: 检查是否有更改需要提交 -echo. -echo [2/4] 检查更改状态... - -:: 启用延迟变量扩展 -setlocal enabledelayedexpansion - -:: 检查未暂存的更改 -git diff --quiet -set has_unstaged=%errorlevel% - -:: 检查已暂存的更改 -git diff --cached --quiet -set has_staged=%errorlevel% - -:: 检查未跟踪的文件 -git ls-files --others --exclude-standard >nul 2>&1 -set has_untracked=%errorlevel% - -if %has_unstaged% equ 0 if %has_staged% equ 0 if %has_untracked% neq 0 ( - echo ℹ️ 没有检测到任何更改,无需提交 - echo. - echo ✅ 工作区干净,无需推送 - pause - exit /b 0 -) - -:: 显示详细状态 -echo 📊 详细状态信息: -echo 未暂存更改: -if %has_unstaged% neq 0 ( - git diff --name-only -) else ( - echo 无 -) - -echo 已暂存更改: -if %has_staged% neq 0 ( - git diff --cached --name-only -) else ( - echo 无 -) - -echo 未跟踪文件: -if %has_untracked% neq 0 ( - git ls-files --others --exclude-standard -) else ( - echo 无 -) -echo. - -:: 添加所有更改 -echo 添加所有更改到暂存区... -git add . -if %errorlevel% neq 0 ( - echo ❌ 添加文件失败 - pause - exit /b 1 -) -echo ✅ 文件已添加到暂存区 - -:: 检查markdown文件修改并生成智能提交信息 -echo. -echo [3/4] 分析markdown文件并生成提交信息... - -:: 检查是否有markdown文件修改 -set md_files= -for /f "tokens=*" %%f in ('git diff --name-only --cached 2^>nul ^| findstr /i "\.md$"') do ( - set md_files=!md_files! %%f -) -for /f "tokens=*" %%f in ('git diff --name-only 2^>nul ^| findstr /i "\.md$"') do ( - set md_files=!md_files! %%f -) - -set commit_msg= -if not "%md_files%"=="" ( - echo 📝 检测到markdown文件修改: - echo %md_files% - echo. - - :: 提取markdown文件的主要内容 - set commit_title= - set commit_type=docs - - :: 检查是否有修复相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "修复\|解决\|问题\|错误"') do ( - set commit_type=fix - set commit_title=修复问题 - goto :found_fix - ) - ) - ) - - :: 检查是否有新功能相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "功能\|新增\|添加\|实现"') do ( - set commit_type=feat - set commit_title=新增功能 - goto :found_feature - ) - ) - ) - - :: 检查是否有优化相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "优化\|性能\|改进\|提升"') do ( - set commit_type=perf - set commit_title=性能优化 - goto :found_optimization - ) - ) - ) - - :: 提取文件标题 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /n "^#" ^| head -1') do ( - set line=%%l - set line=!line:*:=! - set line=!line:# =! - set line=!line:## =! - if "!line!" neq "" ( - set commit_title=!line! - goto :found_title - ) - ) - ) - ) - - :found_fix - :found_feature - :found_optimization - :found_title - - if "%commit_title%"=="" ( - set commit_title=更新文档记录 - ) - - :: 生成提交信息 - set commit_msg=%commit_type%: %commit_title% - echo 📋 生成的提交信息: %commit_msg% - echo. -) else ( - echo ℹ️ 没有检测到markdown文件修改 - set commit_msg=feat: 自动提交 - %date% %time% -) - -:: 询问是否使用生成的提交信息 -set /p confirm="是否使用此提交信息? (y/n/e编辑): " -if /i "%confirm%"=="e" ( - set /p commit_msg="请输入自定义提交信息: " -) else if /i "%confirm%" neq "y" ( - set /p commit_msg="请输入提交信息: " -) - -:: 提交更改 -echo 提交信息: %commit_msg% -git commit -m "%commit_msg%" -if %errorlevel% neq 0 ( - echo ❌ 提交失败 - pause - exit /b 1 -) -echo ✅ 提交成功 - -:: 推送到远程仓库 -echo. -echo [4/4] 推送到远程仓库... - -:: 先尝试拉取最新更改 -echo 🔄 检查远程更新... -git fetch origin main -if %errorlevel% neq 0 ( - echo ⚠️ 无法获取远程更新,继续推送... -) else ( - echo ✅ 远程更新检查完成 -) - -:: 推送到远程 -git push origin main -if %errorlevel% neq 0 ( - echo ❌ 推送失败 - echo. - echo 💡 可能的原因: - echo - 网络连接问题 - echo - 远程仓库权限不足 - echo - 分支冲突 - echo - 需要先拉取远程更改 - echo. - echo 🔧 尝试自动解决冲突... - git pull origin main --rebase - if %errorlevel% equ 0 ( - echo ✅ 冲突已解决,重新推送... - git push origin main - if %errorlevel% equ 0 ( - echo ✅ 推送成功! - ) else ( - echo ❌ 重新推送失败 - echo. - echo 🔧 建议手动解决: - echo 1. 运行: git pull origin main - echo 2. 解决冲突后运行: git push origin main - pause - exit /b 1 - ) - ) else ( - echo ❌ 无法自动解决冲突 - echo. - echo 🔧 建议手动解决: - echo 1. 运行: git pull origin main - echo 2. 解决冲突后运行: git push origin main - pause - exit /b 1 - ) -) else ( - echo ✅ 推送成功! -) - -echo. -echo ======================================== -echo ✅ 推送完成! -echo ======================================== -echo 📊 提交统计: -git log --oneline -1 -echo. -echo 🌐 远程仓库状态: -git status -echo. -pause diff --git a/config/README.md b/config/README.md deleted file mode 100644 index 778ed0b..0000000 --- a/config/README.md +++ /dev/null @@ -1,178 +0,0 @@ -# TSP智能助手配置说明 - -## 📋 配置文件概述 - -本目录包含TSP智能助手的核心配置文件,包括LLM配置、集成配置等。 - -## 🤖 LLM配置 - -### 千问模型配置 - -本项目默认使用阿里云千问模型。要使用千问模型,请按以下步骤配置: - -#### 1. 获取API密钥 - -1. 访问 [阿里云百炼平台](https://bailian.console.aliyun.com/) -2. 注册并登录账号 -3. 创建应用并获取API密钥 - -#### 2. 配置API密钥 - -编辑 `config/llm_config.py` 文件,将 `api_key` 替换为您的实际API密钥: - -```python -QWEN_CONFIG = LLMConfig( - provider="openai", - api_key="sk-your-actual-qwen-api-key", # 替换为您的实际密钥 - base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", - model="qwen-turbo", - temperature=0.7, - max_tokens=2000 -) -``` - -#### 3. 可用的千问模型 - -- `qwen-turbo`: 快速响应,适合一般对话 -- `qwen-plus`: 平衡性能和成本 -- `qwen-max`: 最强性能,适合复杂任务 - -#### 4. 环境变量配置(可选) - -您也可以使用环境变量来配置: - -```bash -export QWEN_API_KEY="sk-your-actual-qwen-api-key" -export QWEN_MODEL="qwen-turbo" -``` - -#### 5. 其他模型支持 - -项目也支持其他LLM提供商: - -- **OpenAI**: GPT-3.5/GPT-4 -- **Anthropic**: Claude系列 -- **本地模型**: Ollama等 - -#### 6. 配置验证 - -启动系统后,可以在Agent管理页面查看LLM使用统计,确认配置是否正确。 - -## 📱 飞书集成配置 - -### 配置文件说明 - -`integrations_config.json` 文件包含飞书集成的所有配置信息: - -```json -{ - "feishu": { - "app_id": "cli_a8b50ec0eed1500d", - "app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK", - "app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg", - "table_id": "tblnl3vJPpgMTSiP", - "last_updated": "2025-09-19T18:27:40.579958", - "status": "active" - }, - "system": { - "sync_limit": 10, - "ai_suggestions_enabled": true, - "auto_sync_interval": 0, - "last_sync_time": null - } -} -``` - -### 配置参数说明 - -#### 飞书应用配置 -- `app_id`: 飞书应用ID -- `app_secret`: 飞书应用密钥 -- `app_token`: 飞书多维表格应用Token -- `table_id`: 飞书多维表格ID -- `last_updated`: 最后更新时间 -- `status`: 集成状态(active/inactive) - -#### 系统配置 -- `sync_limit`: 同步记录数量限制 -- `ai_suggestions_enabled`: 是否启用AI建议 -- `auto_sync_interval`: 自动同步间隔(分钟) -- `last_sync_time`: 最后同步时间 - -### 获取飞书配置 - -1. **获取应用凭证** - - 访问 [飞书开放平台](https://open.feishu.cn/) - - 创建企业自建应用 - - 获取 `app_id` 和 `app_secret` - -2. **获取表格信息** - - 打开飞书多维表格 - - 从URL中提取 `app_token` 和 `table_id` - - 例如:`https://my-ichery.feishu.cn/base/XXnEbiCmEaMblSs6FDJcFCqsnIg?table=tblnl3vJPpgMTSiP` - - `app_token`: `XXnEbiCmEaMblSs6FDJcFCqsnIg` - - `table_id`: `tblnl3vJPpgMTSiP` - -3. **配置权限** - - 在飞书开放平台中配置应用权限 - - 确保应用有读取多维表格的权限 - -### 字段映射配置 - -系统会自动映射以下飞书字段到本地数据库: - -| 飞书字段 | 本地字段 | 类型 | 说明 | -|---------|---------|------|------| -| TR Number | order_id | String | 工单编号 | -| TR Description | description | Text | 工单描述 | -| Type of problem | category | String | 问题类型 | -| TR Level | priority | String | 优先级 | -| TR Status | status | String | 工单状态 | -| Source | source | String | 来源 | -| Created by | created_by | String | 创建人 | -| Module(模块) | module | String | 模块 | -| Wilfulness(责任人) | wilfulness | String | 责任人 | -| Date of close TR | date_of_close | DateTime | 关闭日期 | -| Vehicle Type01 | vehicle_type | String | 车型 | -| VIN\|sim | vin_sim | String | 车架号/SIM | -| App remote control version | app_remote_control_version | String | 应用远程控制版本 | -| HMI SW | hmi_sw | String | HMI软件版本 | -| 父记录 | parent_record | String | 父记录 | -| Has it been updated on the same day | has_updated_same_day | String | 是否同日更新 | -| Operating time | operating_time | String | 操作时间 | - -## 🔧 配置管理 - -### 配置文件位置 -- `llm_config.py`: LLM客户端配置 -- `integrations_config.json`: 集成服务配置 -- `integrations_config copy.json`: 配置备份文件 - -### 配置更新 -- 修改配置文件后需要重启服务 -- 建议在修改前备份配置文件 -- 可以通过Web界面进行部分配置的在线修改 - -### 环境变量支持 -系统支持通过环境变量覆盖配置文件设置: - -```bash -# LLM配置 -export LLM_PROVIDER="openai" -export LLM_API_KEY="your-api-key" -export LLM_MODEL="gpt-3.5-turbo" - -# 飞书配置 -export FEISHU_APP_ID="your-app-id" -export FEISHU_APP_SECRET="your-app-secret" -export FEISHU_APP_TOKEN="your-app-token" -export FEISHU_TABLE_ID="your-table-id" -``` - -## 🚨 注意事项 - -1. **安全性**: 配置文件包含敏感信息,请勿提交到版本控制系统 -2. **备份**: 修改配置前请备份原文件 -3. **权限**: 确保飞书应用有足够的权限访问多维表格 -4. **测试**: 配置完成后建议先进行测试同步 -5. **监控**: 定期检查同步状态和错误日志 diff --git a/config/__pycache__/ai_accuracy_config.cpython-313.pyc b/config/__pycache__/ai_accuracy_config.cpython-313.pyc deleted file mode 100644 index 9466308..0000000 Binary files a/config/__pycache__/ai_accuracy_config.cpython-313.pyc and /dev/null differ diff --git a/config/__pycache__/llm_config.cpython-311.pyc b/config/__pycache__/llm_config.cpython-311.pyc deleted file mode 100644 index 7942acb..0000000 Binary files a/config/__pycache__/llm_config.cpython-311.pyc and /dev/null differ diff --git a/config/ai_accuracy_config.py b/config/ai_accuracy_config.py deleted file mode 100644 index b239cbf..0000000 --- a/config/ai_accuracy_config.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -AI准确率配置 -管理AI建议的准确率阈值和相关配置 -""" - -from dataclasses import dataclass -from typing import Dict, Any - -@dataclass -class AIAccuracyConfig: - """AI准确率配置类""" - - # 相似度阈值配置 - auto_approve_threshold: float = 0.95 # 自动审批阈值(≥95%) - use_human_resolution_threshold: float = 0.90 # 使用人工描述阈值(<90%) - manual_review_threshold: float = 0.80 # 人工审核阈值(≥80%) - - # 置信度配置 - ai_suggestion_confidence: float = 0.95 # AI建议默认置信度 - human_resolution_confidence: float = 0.90 # 人工描述置信度 - - # 入库策略配置 - prefer_human_when_low_accuracy: bool = True # 当AI准确率低时优先使用人工描述 - enable_auto_approval: bool = True # 是否启用自动审批 - enable_human_fallback: bool = True # 是否启用人工描述回退 - - def get_threshold_explanation(self, similarity: float) -> str: - """获取相似度阈值的解释""" - if similarity >= self.auto_approve_threshold: - return f"相似度≥{self.auto_approve_threshold*100:.0f}%,自动审批使用AI建议" - elif similarity >= self.manual_review_threshold: - return f"相似度≥{self.manual_review_threshold*100:.0f}%,建议人工审核" - elif similarity >= self.use_human_resolution_threshold: - return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,建议使用人工描述" - else: - return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,优先使用人工描述" - - def should_use_human_resolution(self, similarity: float) -> bool: - """判断是否应该使用人工描述""" - return similarity < self.use_human_resolution_threshold - - def should_auto_approve(self, similarity: float) -> bool: - """判断是否应该自动审批""" - return similarity >= self.auto_approve_threshold and self.enable_auto_approval - - def get_confidence_score(self, similarity: float, use_human: bool = False) -> float: - """获取置信度分数""" - if use_human: - return self.human_resolution_confidence - else: - return max(similarity, self.ai_suggestion_confidence) - - def to_dict(self) -> Dict[str, Any]: - """转换为字典格式""" - return { - "auto_approve_threshold": self.auto_approve_threshold, - "use_human_resolution_threshold": self.use_human_resolution_threshold, - "manual_review_threshold": self.manual_review_threshold, - "ai_suggestion_confidence": self.ai_suggestion_confidence, - "human_resolution_confidence": self.human_resolution_confidence, - "prefer_human_when_low_accuracy": self.prefer_human_when_low_accuracy, - "enable_auto_approval": self.enable_auto_approval, - "enable_human_fallback": self.enable_human_fallback - } - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> 'AIAccuracyConfig': - """从字典创建配置""" - return cls(**data) - -# 默认配置实例 -DEFAULT_CONFIG = AIAccuracyConfig() - -# 配置预设 -PRESETS = { - "conservative": AIAccuracyConfig( - auto_approve_threshold=0.98, - use_human_resolution_threshold=0.85, - manual_review_threshold=0.90, - human_resolution_confidence=0.95 - ), - "balanced": AIAccuracyConfig( - auto_approve_threshold=0.95, - use_human_resolution_threshold=0.90, - manual_review_threshold=0.80, - human_resolution_confidence=0.90 - ), - "aggressive": AIAccuracyConfig( - auto_approve_threshold=0.90, - use_human_resolution_threshold=0.80, - manual_review_threshold=0.70, - human_resolution_confidence=0.85 - ) -} - -def get_accuracy_config(preset: str = "balanced") -> AIAccuracyConfig: - """获取准确率配置""" - return PRESETS.get(preset, DEFAULT_CONFIG) - -def update_accuracy_config(config: AIAccuracyConfig) -> bool: - """更新准确率配置(可以保存到文件或数据库)""" - try: - # 这里可以实现配置的持久化存储 - # 例如保存到配置文件或数据库 - return True - except Exception: - return False diff --git a/config/integrations_config copy.json b/config/integrations_config copy.json deleted file mode 100644 index ede371c..0000000 --- a/config/integrations_config copy.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "feishu": { - "app_id": "tblnl3vJPpgMTSiP", - "app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK", - "app_token": "XXnEbiCmEaMblSs6FDJcFCqsnlg", - "table_id": "tblnl3vJPpgMTSiP", - "last_updated": null, - "status": "inactive" - }, - "system": { - "sync_limit": 10, - "ai_suggestions_enabled": true, - "auto_sync_interval": 0, - "last_sync_time": null - } -} \ No newline at end of file diff --git a/config/integrations_config.json b/config/integrations_config.json deleted file mode 100644 index 57ada2b..0000000 --- a/config/integrations_config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "feishu": { - "app_id": "cli_a8b50ec0eed1500d", - "app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK", - "app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg", - "table_id": "tblnl3vJPpgMTSiP", - "last_updated": "2025-09-19T18:40:55.291113", - "status": "active" - }, - "system": { - "sync_limit": 10, - "ai_suggestions_enabled": true, - "auto_sync_interval": 0, - "last_sync_time": null - } -} \ No newline at end of file diff --git a/config/llm_config.py b/config/llm_config.py deleted file mode 100644 index e960e06..0000000 --- a/config/llm_config.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -""" -LLM配置文件 - 千问模型配置 -""" - -from src.agent.llm_client import LLMConfig - -# 千问模型配置 -QWEN_CONFIG = LLMConfig( - provider="qwen", - api_key="sk-c0dbefa1718d46eaa897199135066f00", # 请替换为您的千问API密钥 - base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", - model="qwen-plus-latest", # 可选: qwen-turbo, qwen-plus, qwen-max - temperature=0.7, - max_tokens=2000 -) - -# 其他模型配置示例 -OPENAI_CONFIG = LLMConfig( - provider="openai", - api_key="sk-your-openai-api-key-here", - model="gpt-3.5-turbo", - temperature=0.7, - max_tokens=2000 -) - -ANTHROPIC_CONFIG = LLMConfig( - provider="anthropic", - api_key="sk-ant-your-anthropic-api-key-here", - model="claude-3-sonnet-20240229", - temperature=0.7, - max_tokens=2000 -) - -# 默认使用千问模型 -DEFAULT_CONFIG = QWEN_CONFIG - - -def get_default_llm_config() -> LLMConfig: - """ - 获取默认的LLM配置 - 优先从统一配置管理器获取,如果失败则使用本地配置 - """ - try: - from src.config.unified_config import get_config - config = get_config() - llm_dict = config.get_llm_config() - - # 创建LLMConfig对象 - return LLMConfig( - provider=llm_dict.get("provider", "qwen"), - api_key=llm_dict.get("api_key", ""), - base_url=llm_dict.get("base_url", "https://dashscope.aliyuncs.com/compatible-mode/v1"), - model=llm_dict.get("model", "qwen-plus-latest"), - temperature=llm_dict.get("temperature", 0.7), - max_tokens=llm_dict.get("max_tokens", 2000) - ) - except Exception: - # 如果统一配置不可用,使用本地配置 - return DEFAULT_CONFIG diff --git a/config/unified_config.json b/config/unified_config.json deleted file mode 100644 index ebe5870..0000000 --- a/config/unified_config.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "database": { - "url": "mysql+pymysql://tsp_assistant:password@jeason.online/tsp_assistant?charset=utf8mb4", - "pool_size": 10, - "max_overflow": 20, - "pool_timeout": 30, - "pool_recycle": 3600 - }, - "llm": { - "provider": "qwen", - "api_key": "sk-c0dbefa1718d46eaa897199135066f00", - "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", - "model": "qwen-plus-latest", - "temperature": 0.7, - "max_tokens": 2000, - "timeout": 30 - }, - "server": { - "host": "0.0.0.0", - "port": 5000, - "websocket_port": 8765, - "debug": false, - "log_level": "INFO" - }, - "feishu": { - "app_id": "", - "app_secret": "", - "app_token": "", - "table_id": "", - "status": "active", - "sync_limit": 10, - "auto_sync_interval": 0 - }, - "ai_accuracy": { - "auto_approve_threshold": 0.95, - "use_human_resolution_threshold": 0.9, - "manual_review_threshold": 0.8, - "ai_suggestion_confidence": 0.95, - "human_resolution_confidence": 0.9, - "prefer_human_when_low_accuracy": true, - "enable_auto_approval": true, - "enable_human_fallback": true - }, - "system": { - "backup_enabled": true, - "backup_interval": 24, - "max_backup_files": 7, - "cache_enabled": true, - "cache_ttl": 3600, - "monitoring_enabled": true - } -} \ No newline at end of file diff --git a/config_backup.txt b/config_backup.txt new file mode 100644 index 0000000..4e0e159 --- /dev/null +++ b/config_backup.txt @@ -0,0 +1,672 @@ +################################################################################ +# DEPRECATED CONFIGURATION FILE: config/llm_config.py +################################################################################ +# -*- coding: utf-8 -*- +""" +LLM配置文件 - 千问模型配置 +""" + +from src.agent.llm_client import LLMConfig + +# 千问模型配置 +QWEN_CONFIG = LLMConfig( + provider="qwen", + api_key="sk-c0dbefa1718d46eaa897199135066f00", # 请替换为您的千问API密钥 + base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", + model="qwen-plus-latest", # 可选: qwen-turbo, qwen-plus, qwen-max + temperature=0.7, + max_tokens=2000 +) + +# 其他模型配置示例 +OPENAI_CONFIG = LLMConfig( + provider="openai", + api_key="sk-your-openai-api-key-here", + model="gpt-3.5-turbo", + temperature=0.7, + max_tokens=2000 +) + +ANTHROPIC_CONFIG = LLMConfig( + provider="anthropic", + api_key="sk-ant-your-anthropic-api-key-here", + model="claude-3-sonnet-20240229", + temperature=0.7, + max_tokens=2000 +) + +# 默认使用千问模型 +DEFAULT_CONFIG = QWEN_CONFIG + + +def get_default_llm_config() -> LLMConfig: + """ + 获取默认的LLM配置 + 优先从统一配置管理器获取,如果失败则使用本地配置 + """ + try: + from src.config.unified_config import get_config + config = get_config() + llm_dict = config.get_llm_config() + + # 创建LLMConfig对象 + return LLMConfig( + provider=llm_dict.get("provider", "qwen"), + api_key=llm_dict.get("api_key", ""), + base_url=llm_dict.get("base_url", "https://dashscope.aliyuncs.com/compatible-mode/v1"), + model=llm_dict.get("model", "qwen-plus-latest"), + temperature=llm_dict.get("temperature", 0.7), + max_tokens=llm_dict.get("max_tokens", 2000) + ) + except Exception: + # 如果统一配置不可用,使用本地配置 + return DEFAULT_CONFIG + + +################################################################################ +# DEPRECATED CONFIGURATION FILE: config/integrations_config.json +################################################################################ +{ + "feishu": { + "app_id": "cli_a8b50ec0eed1500d", + "app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK", + "app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg", + "table_id": "tblnl3vJPpgMTSiP", + "last_updated": "2025-09-19T18:40:55.291113", + "status": "active" + }, + "system": { + "sync_limit": 10, + "ai_suggestions_enabled": true, + "auto_sync_interval": 0, + "last_sync_time": null + } +} + +################################################################################ +# DEPRECATED CONFIGURATION FILE: config/ai_accuracy_config.py +################################################################################ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +AI准确率配置 +管理AI建议的准确率阈值和相关配置 +""" + +from dataclasses import dataclass +from typing import Dict, Any + +@dataclass +class AIAccuracyConfig: + """AI准确率配置类""" + + # 相似度阈值配置 + auto_approve_threshold: float = 0.95 # 自动审批阈值(≥95%) + use_human_resolution_threshold: float = 0.90 # 使用人工描述阈值(<90%) + manual_review_threshold: float = 0.80 # 人工审核阈值(≥80%) + + # 置信度配置 + ai_suggestion_confidence: float = 0.95 # AI建议默认置信度 + human_resolution_confidence: float = 0.90 # 人工描述置信度 + + # 入库策略配置 + prefer_human_when_low_accuracy: bool = True # 当AI准确率低时优先使用人工描述 + enable_auto_approval: bool = True # 是否启用自动审批 + enable_human_fallback: bool = True # 是否启用人工描述回退 + + def get_threshold_explanation(self, similarity: float) -> str: + """获取相似度阈值的解释""" + if similarity >= self.auto_approve_threshold: + return f"相似度≥{self.auto_approve_threshold*100:.0f}%,自动审批使用AI建议" + elif similarity >= self.manual_review_threshold: + return f"相似度≥{self.manual_review_threshold*100:.0f}%,建议人工审核" + elif similarity >= self.use_human_resolution_threshold: + return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,建议使用人工描述" + else: + return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,优先使用人工描述" + + def should_use_human_resolution(self, similarity: float) -> bool: + """判断是否应该使用人工描述""" + return similarity < self.use_human_resolution_threshold + + def should_auto_approve(self, similarity: float) -> bool: + """判断是否应该自动审批""" + return similarity >= self.auto_approve_threshold and self.enable_auto_approval + + def get_confidence_score(self, similarity: float, use_human: bool = False) -> float: + """获取置信度分数""" + if use_human: + return self.human_resolution_confidence + else: + return max(similarity, self.ai_suggestion_confidence) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典格式""" + return { + "auto_approve_threshold": self.auto_approve_threshold, + "use_human_resolution_threshold": self.use_human_resolution_threshold, + "manual_review_threshold": self.manual_review_threshold, + "ai_suggestion_confidence": self.ai_suggestion_confidence, + "human_resolution_confidence": self.human_resolution_confidence, + "prefer_human_when_low_accuracy": self.prefer_human_when_low_accuracy, + "enable_auto_approval": self.enable_auto_approval, + "enable_human_fallback": self.enable_human_fallback + } + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'AIAccuracyConfig': + """从字典创建配置""" + return cls(**data) + +# 默认配置实例 +DEFAULT_CONFIG = AIAccuracyConfig() + +# 配置预设 +PRESETS = { + "conservative": AIAccuracyConfig( + auto_approve_threshold=0.98, + use_human_resolution_threshold=0.85, + manual_review_threshold=0.90, + human_resolution_confidence=0.95 + ), + "balanced": AIAccuracyConfig( + auto_approve_threshold=0.95, + use_human_resolution_threshold=0.90, + manual_review_threshold=0.80, + human_resolution_confidence=0.90 + ), + "aggressive": AIAccuracyConfig( + auto_approve_threshold=0.90, + use_human_resolution_threshold=0.80, + manual_review_threshold=0.70, + human_resolution_confidence=0.85 + ) +} + +def get_accuracy_config(preset: str = "balanced") -> AIAccuracyConfig: + """获取准确率配置""" + return PRESETS.get(preset, DEFAULT_CONFIG) + +def update_accuracy_config(config: AIAccuracyConfig) -> bool: + """更新准确率配置(可以保存到文件或数据库)""" + try: + # 这里可以实现配置的持久化存储 + # 例如保存到配置文件或数据库 + return True + except Exception: + return False + + +################################################################################ +# DEPRECATED CONFIGURATION FILE: config/field_mapping_config.json +################################################################################ +{ + "field_mapping": { + "TR Number": "order_id", + "TR Description": "description", + "Type of problem": "category", + "TR Level": "priority", + "TR Status": "status", + "Source": "source", + "Date creation": "created_at", + "处理过程": "resolution", + "TR tracking": "resolution", + "Created by": "created_by", + "Module(模块)": "module", + "Wilfulness(责任人)": "wilfulness", + "Date of close TR": "date_of_close", + "Vehicle Type01": "vehicle_type", + "VIN|sim": "vin_sim", + "App remote control version": "app_remote_control_version", + "HMI SW": "hmi_sw", + "父记录": "parent_record", + "Has it been updated on the same day": "has_updated_same_day", + "Operating time": "operating_time", + "AI建议": "ai_suggestion", + "Issue Start Time": "updated_at", + "Wilfulness(责任人�?": "wilfulness", + "父�?�录": "parent_record", + "AI建�??": "ai_suggestion" + }, + "field_aliases": { + "order_id": [ + "TR Number", + "TR编号", + "工单号", + "Order ID", + "Ticket ID", + "工单编号", + "新字段1", + "新字段" + ], + "description": [ + "TR Description", + "TR描述", + "描述", + "Description", + "问题描述", + "详细描述" + ], + "category": [ + "Type of problem", + "问题类型", + "Category", + "分类", + "Problem Type", + "问题分类" + ], + "priority": [ + "TR Level", + "优先级", + "Priority", + "Level", + "紧急程度", + "重要程度" + ], + "status": [ + "TR Status", + "状态", + "Status", + "工单状态", + "处理状态" + ], + "source": [ + "Source", + "来源", + "Source Type", + "来源类型", + "提交来源" + ], + "created_at": [ + "Date creation", + "创建日期", + "Created At", + "Creation Date", + "创建时间" + ], + "solution": [ + "处理过程", + "Solution", + "解决方案", + "Process", + "处理方案" + ], + "resolution": [ + "TR tracking", + "Resolution", + "解决结果", + "跟踪", + "处理结果" + ], + "created_by": [ + "Created by", + "创建人", + "Creator", + "Created By", + "提交人" + ], + "vehicle_type": [ + "Vehicle Type01", + "车型", + "Vehicle Type", + "车辆类型", + "车款" + ], + "vin_sim": [ + "VIN|sim", + "VIN", + "车架号", + "SIM", + "VIN/SIM", + "车辆识别号" + ], + "module": [ + "Module(模块)", + "模块", + "Module", + "功能模块" + ], + "wilfulness": [ + "Wilfulness(责任人)", + "责任人", + "负责人", + "Assignee" + ], + "date_of_close": [ + "Date of close TR", + "关闭日期", + "Close Date", + "完成日期" + ], + "app_remote_control_version": [ + "App remote control version", + "应用远程控制版本", + "App Version", + "应用版本" + ], + "hmi_sw": [ + "HMI SW", + "HMI软件版本", + "HMI Software", + "人机界面软件" + ], + "parent_record": [ + "父记录", + "Parent Record", + "上级记录", + "关联记录" + ], + "has_updated_same_day": [ + "Has it been updated on the same day", + "是否同日更新", + "Same Day Update", + "当日更新" + ], + "operating_time": [ + "Operating time", + "操作时间", + "Operation Time", + "运行时间" + ], + "ai_suggestion": [ + "AI建议", + "AI Suggestion", + "AI建议", + "智能建议" + ], + "updated_at": [ + "Issue Start Time", + "问题开始时间", + "Start Time", + "更新时间" + ] + }, + "field_patterns": { + "order_id": [ + ".*number.*", + ".*id.*", + ".*编号.*", + ".*ticket.*", + ".*新.*" + ], + "description": [ + ".*description.*", + ".*描述.*", + ".*detail.*", + ".*内容.*" + ], + "category": [ + ".*type.*", + ".*category.*", + ".*分类.*", + ".*类型.*", + ".*problem.*" + ], + "priority": [ + ".*level.*", + ".*priority.*", + ".*优先级.*", + ".*urgent.*" + ], + "status": [ + ".*status.*", + ".*状态.*", + ".*state.*" + ], + "source": [ + ".*source.*", + ".*来源.*", + ".*origin.*" + ], + "created_at": [ + ".*creation.*", + ".*created.*", + ".*创建.*", + ".*date.*" + ], + "solution": [ + ".*solution.*", + ".*处理.*", + ".*解决.*", + ".*process.*" + ], + "resolution": [ + ".*resolution.*", + ".*tracking.*", + ".*跟踪.*", + ".*result.*" + ], + "created_by": [ + ".*created.*by.*", + ".*creator.*", + ".*创建人.*", + ".*author.*" + ], + "vehicle_type": [ + ".*vehicle.*type.*", + ".*车型.*", + ".*车辆.*", + ".*car.*" + ], + "vin_sim": [ + ".*vin.*", + ".*sim.*", + ".*车架.*", + ".*识别.*" + ], + "module": [ + ".*module.*", + ".*模块.*", + ".*功能.*" + ], + "wilfulness": [ + ".*wilfulness.*", + ".*责任人.*", + ".*负责人.*", + ".*assignee.*" + ], + "date_of_close": [ + ".*close.*", + ".*关闭.*", + ".*完成.*", + ".*finish.*" + ], + "app_remote_control_version": [ + ".*app.*version.*", + ".*应用.*版本.*", + ".*remote.*control.*" + ], + "hmi_sw": [ + ".*hmi.*", + ".*软件.*", + ".*software.*" + ], + "parent_record": [ + ".*parent.*", + ".*父.*", + ".*上级.*", + ".*关联.*" + ], + "has_updated_same_day": [ + ".*same.*day.*", + ".*同日.*", + ".*当日.*", + ".*updated.*same.*" + ], + "operating_time": [ + ".*operating.*time.*", + ".*操作.*时间.*", + ".*运行.*时间.*" + ], + "ai_suggestion": [ + ".*ai.*suggestion.*", + ".*ai.*建议.*", + ".*智能.*建议.*" + ], + "updated_at": [ + ".*start.*time.*", + ".*开始.*时间.*", + ".*updated.*at.*", + ".*更新时间.*" + ] + }, + "field_priorities": { + "order_id": 3, + "description": 3, + "category": 3, + "priority": 3, + "status": 3, + "created_at": 3, + "source": 3, + "solution": 3, + "resolution": 3, + "created_by": 3, + "vehicle_type": 3, + "vin_sim": 3, + "module": 3, + "wilfulness": 3, + "date_of_close": 3, + "app_remote_control_version": 3, + "hmi_sw": 3, + "parent_record": 3, + "has_updated_same_day": 3, + "operating_time": 3, + "ai_suggestion": 3, + "updated_at": 3 + }, + "auto_mapping_enabled": true, + "similarity_threshold": 0.6 +} + +################################################################################ +# DEPRECATED CONFIGURATION FILE: config/unified_config.json +################################################################################ +{ + "database": { + "url": "mysql+pymysql://tsp_assistant:password@jeason.online/tsp_assistant?charset=utf8mb4", + "pool_size": 10, + "max_overflow": 20, + "pool_timeout": 30, + "pool_recycle": 3600 + }, + "llm": { + "provider": "qwen", + "api_key": "sk-c0dbefa1718d46eaa897199135066f00", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "model": "qwen-plus-latest", + "temperature": 0.7, + "max_tokens": 2000, + "timeout": 30 + }, + "server": { + "host": "0.0.0.0", + "port": 5000, + "websocket_port": 8765, + "debug": false, + "log_level": "INFO" + }, + "feishu": { + "app_id": "", + "app_secret": "", + "app_token": "", + "table_id": "", + "status": "active", + "sync_limit": 10, + "auto_sync_interval": 0 + }, + "ai_accuracy": { + "auto_approve_threshold": 0.95, + "use_human_resolution_threshold": 0.9, + "manual_review_threshold": 0.8, + "ai_suggestion_confidence": 0.95, + "human_resolution_confidence": 0.9, + "prefer_human_when_low_accuracy": true, + "enable_auto_approval": true, + "enable_human_fallback": true + }, + "system": { + "backup_enabled": true, + "backup_interval": 24, + "max_backup_files": 7, + "cache_enabled": true, + "cache_ttl": 3600, + "monitoring_enabled": true + } +} + +################################################################################ +# DEPRECATED CONFIGURATION FILE: src/config/config.py +################################################################################ +import os +from typing import Dict, Any + +class Config: + """系统配置类""" + + # 阿里云千问API配置 + ALIBABA_API_KEY = "sk-c0dbefa1718d46eaa897199135066f00" + ALIBABA_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1" + ALIBABA_MODEL_NAME = "qwen-plus-latest" + + # 数据库配置 + DATABASE_URL = "mysql+pymysql://tsp_assistant:123456@jeason.online/tsp_assistant?charset=utf8mb4" + # DATABASE_URL = "sqlite:///local_test.db" # 本地测试数据库 + + # 知识库配置 + KNOWLEDGE_BASE_PATH = "data/knowledge_base" + VECTOR_DB_PATH = "data/vector_db" + + # 对话配置 + MAX_HISTORY_LENGTH = 10 + RESPONSE_TIMEOUT = 30 + + # 分析配置 + ANALYTICS_UPDATE_INTERVAL = 3600 # 1小时 + ALERT_THRESHOLD = 0.8 # 预警阈值 + + # 日志配置 + LOG_LEVEL = "INFO" + LOG_FILE = "logs/tsp_assistant.log" + + # 系统监控配置 + SYSTEM_MONITORING = True # 是否启用系统监控 + MONITORING_INTERVAL = 60 # 监控间隔(秒) + + @classmethod + def get_api_config(cls) -> Dict[str, Any]: + """获取API配置""" + return { + "api_key": cls.ALIBABA_API_KEY, + "base_url": cls.ALIBABA_BASE_URL, + "model_name": cls.ALIBABA_MODEL_NAME + } + + @classmethod + def get_database_config(cls) -> Dict[str, Any]: + """获取数据库配置""" + return { + "url": cls.DATABASE_URL, + "echo": False + } + + @classmethod + def get_knowledge_config(cls) -> Dict[str, Any]: + """获取知识库配置""" + return { + "base_path": cls.KNOWLEDGE_BASE_PATH, + "vector_db_path": cls.VECTOR_DB_PATH + } + + @classmethod + def get_config(cls) -> Dict[str, Any]: + """获取完整配置""" + return { + "system_monitoring": cls.SYSTEM_MONITORING, + "monitoring_interval": cls.MONITORING_INTERVAL, + "log_level": cls.LOG_LEVEL, + "log_file": cls.LOG_FILE, + "analytics_update_interval": cls.ANALYTICS_UPDATE_INTERVAL, + "alert_threshold": cls.ALERT_THRESHOLD + } + diff --git a/local_test.db b/data/tsp_assistant.db similarity index 90% rename from local_test.db rename to data/tsp_assistant.db index 12443a3..2adbb02 100644 Binary files a/local_test.db and b/data/tsp_assistant.db differ diff --git a/git_push.bat b/git_push.bat deleted file mode 100644 index 24b1214..0000000 --- a/git_push.bat +++ /dev/null @@ -1,26 +0,0 @@ -@echo off - -rem 获取当前日期和时间 -for /f "tokens=1-6 delims=/ " %%a in ('date /t') do set CDATE=%%a-%%b-%%c -for /f "tokens=1-2 delims=:\ " %%a in ('time /t') do set CTIME=%%a-%%b - -set COMMIT_MESSAGE="feat: %CDATE% %CTIME% - 全面架构重构、功能增强及问题修复" - -rem 添加所有变更到暂存区 -git add . - -rem 检查是否有文件被添加、修改或删除 -git diff --cached --quiet -if %errorlevel% equ 0 ( - echo 没有检测到需要提交的变更。 -) else ( - rem 提交变更 - git commit -m %COMMIT_MESSAGE% - - rem 推送变更到远程仓库 - git push origin master - - echo Git 推送完成! -) - -pause diff --git a/git_push.sh b/git_push.sh deleted file mode 100644 index da7c16d..0000000 --- a/git_push.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# 获取当前日期和时间 -COMMIT_DATE=$(date +"%Y-%m-%d %H:%M:%S") - -# 添加所有变更到暂存区 -git add . - -# 检查是否有文件被添加、修改或删除 -if git diff --cached --quiet; then - echo "没有检测到需要提交的变更。" -else - # 创建提交消息 - COMMIT_MESSAGE="feat: ${COMMIT_DATE} - 全面架构重构、功能增强及问题修复" - - # 提交变更 - git commit -m "$COMMIT_MESSAGE" - - # 推送变更到远程仓库 - git push origin master - - echo "Git 推送完成!" -fi diff --git a/init_database.py b/init_database.py index c49081a..952e7b9 100644 --- a/init_database.py +++ b/init_database.py @@ -15,7 +15,7 @@ from pathlib import Path # 添加项目根目录到Python路径 sys.path.append(os.path.dirname(os.path.abspath(__file__))) -from src.config.config import Config +from src.config.unified_config import get_config from src.utils.helpers import setup_logging from src.core.database import db_manager from src.core.models import ( @@ -67,7 +67,8 @@ class DatabaseInitializer: try: # 设置日志 - setup_logging(Config.LOG_LEVEL, Config.LOG_FILE) + config = get_config() + setup_logging(config.server.log_level, "logs/tsp_assistant.log") # 测试数据库连接 if not self._test_connection(): diff --git a/logs/2026-02-10_23-22-54/dashboard.log b/logs/2026-02-10_23-22-54/dashboard.log new file mode 100644 index 0000000..fddc2a5 --- /dev/null +++ b/logs/2026-02-10_23-22-54/dashboard.log @@ -0,0 +1,380 @@ +2026-02-10 23:22:54,720 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - Initializing unified configuration from environment variables... +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - Database config loaded. +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - LLM config loaded. +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - Server config loaded. +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - Feishu config loaded. +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - AI Accuracy config loaded. +2026-02-10 23:22:54,996 - src.config.unified_config - INFO - Configuration validation passed (warnings may exist). +2026-02-10 23:22:55,025 - src.core.database - INFO - 数据库初始化成功 +2026-02-10 23:22:55,038 - __main__ - INFO - 跳过系统检查,直接启动服务... +2026-02-10 23:22:56,565 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db +2026-02-10 23:22:56,569 - src.integrations.config_manager - INFO - 配置加载成功 +2026-02-10 23:22:56,682 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5001 + * Running on http://192.168.31.45:5001 +2026-02-10 23:22:56,683 - werkzeug - INFO - Press CTRL+C to quit +2026-02-10 23:22:56,839 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 +2026-02-10 23:22:56,845 - websockets.server - INFO - server listening on [::1]:8765 +2026-02-10 23:22:56,845 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2026-02-10 23:22:59,223 - websockets.server - INFO - connection open +2026-02-10 23:22:59,223 - src.web.websocket_server - INFO - 客户端连接: ('::1', 61966, 0, 0) +2026-02-10 23:23:01,871 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET / HTTP/1.1" 200 - +2026-02-10 23:23:01,899 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:23:01,910 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:23:01,926 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:23:01,928 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:23:01,931 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:23:01,932 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:23:01,937 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:23:01,941 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:23:01,945 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:23:02,000 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:02,003 - src.web.service_manager - INFO - 服务 assistant 已初始化 +2026-02-10 23:23:02,003 - src.web.service_manager - INFO - 服务 assistant 已初始化 +2026-02-10 23:23:02,004 - src.web.service_manager - INFO - 服务 chat_manager 已初始化 +2026-02-10 23:23:02,004 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:23:02,011 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:23:02,013 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:23:02,039 - src.web.service_manager - INFO - 服务 assistant 已初始化 +2026-02-10 23:23:02,049 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:23:02,054 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:23:02,056 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:23:02,067 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:02,084 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/alerts?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:23:02,092 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:23:02,094 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:23:02,095 - websockets.server - INFO - connection open +2026-02-10 23:23:02,101 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:23:02,102 - src.web.websocket_server - INFO - 客户端连接: ('::1', 61991, 0, 0) +2026-02-10 23:23:02,154 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:23:02,195 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:23:02,237 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:23:02,248 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:02] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:23:03,230 - src.agent_assistant - INFO - TSP Agent助手初始化完成 +2026-02-10 23:23:03,230 - src.web.service_manager - INFO - 服务 agent_assistant 已初始化 +2026-02-10 23:23:03,231 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:03] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:23:05,930 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1770736985 +2026-02-10 23:23:05,931 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:05] "POST /api/chat/session HTTP/1.1" 200 - +2026-02-10 23:23:07,016 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:07] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:07,091 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:07] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:23:07,099 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:07] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:23:07,111 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:07] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:23:08,109 - src.knowledge_base.knowledge_manager - WARNING - 知识库中没有活跃条目 +2026-02-10 23:23:11,108 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:11] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:23:11,997 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:12,012 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:12] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:12,233 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:23:12,238 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:12] "POST /api/chat/message HTTP/1.1" 200 - +2026-02-10 23:23:17,013 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:17] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:21,995 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:21] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:22,011 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:22] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:27,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:27] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:31,997 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:31] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:32,030 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:32] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:36,401 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:36] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:36,404 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:36] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:23:36,418 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:37,038 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:37] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:41,991 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:41] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:42,010 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:42] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:42,092 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:42] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:23:47,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:47] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:51,995 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:51] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:23:52,009 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:52] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:23:57,012 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:57] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:01,993 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:01] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:02,032 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:02] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:07,008 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:07] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:07,097 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:07] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:24:07,106 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:07] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:24:08,400 - src.dialogue.realtime_chat - INFO - 结束会话: session_user_001_1770736985 +2026-02-10 23:24:08,401 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:08] "DELETE /api/chat/session/session_user_001_1770736985 HTTP/1.1" 200 - +2026-02-10 23:24:09,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:09] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:24:09,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:09] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:24:11,992 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:12,023 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:12] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:13,479 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:13] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:17,010 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:17] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:17,189 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:17] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:24:19,476 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 1 个条目 +2026-02-10 23:24:19,477 - src.knowledge_base.knowledge_manager - INFO - 添加知识库条目成功: 123... +2026-02-10 23:24:19,477 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:19] "POST /api/knowledge HTTP/1.1" 200 - +2026-02-10 23:24:19,484 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:19] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:21,903 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 1 +2026-02-10 23:24:21,903 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:21] "POST /api/knowledge/verify/1 HTTP/1.1" 200 - +2026-02-10 23:24:21,909 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:21] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:21,991 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:21] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:22,016 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:22] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:27,014 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:27] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:27,824 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1770737067 +2026-02-10 23:24:27,825 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:27] "POST /api/chat/session HTTP/1.1" 200 - +2026-02-10 23:24:31,997 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:31] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:32,029 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:32] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:32,226 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '123' 返回 1 个结果 +2026-02-10 23:24:33,510 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:24:33,516 - src.knowledge_base.knowledge_manager - INFO - 成功更新 1 个知识库条目的使用次数 +2026-02-10 23:24:33,517 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:33] "POST /api/chat/message HTTP/1.1" 200 - +2026-02-10 23:24:36,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:36] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:36,407 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:36] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:24:36,410 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:36] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:24:36,433 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:36] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:24:36,440 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:37,010 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:37] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:37,045 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:37] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:39,494 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:39] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:41,994 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:41] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:42,035 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:42] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:45,552 - src.dialogue.dialogue_manager - INFO - 创建工单成功: WO20260210232445 +2026-02-10 23:24:45,553 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:45] "POST /api/workorders HTTP/1.1" 200 - +2026-02-10 23:24:45,561 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:45] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:24:45,568 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:45] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:24:47,015 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:47] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:51,300 - src.web.websocket_server - INFO - 客户端断开: ('::1', 61991, 0, 0) +2026-02-10 23:24:51,304 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET / HTTP/1.1" 200 - +2026-02-10 23:24:51,328 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:24:51,330 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:24:51,340 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:24:51,341 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:24:51,342 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:24:51,343 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:24:51,345 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:24:51,347 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:24:51,351 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:24:51,385 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:24:51,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:24:51,389 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:24:51,395 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:24:51,404 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:24:51,420 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:24:51,429 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:24:51,432 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:24:51,434 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:24:51,437 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:24:51,439 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:24:51,442 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:24:51,445 - websockets.server - INFO - connection open +2026-02-10 23:24:51,455 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:51,457 - src.web.websocket_server - INFO - 客户端连接: ('::1', 62164, 0, 0) +2026-02-10 23:24:51,464 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:24:51,487 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:24:51,493 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:24:51,504 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:24:52,700 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:52] "GET /api/workorders/1 HTTP/1.1" 200 - +2026-02-10 23:24:54,133 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 'ewq' 返回 0 个结果 +2026-02-10 23:24:55,503 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:24:55,509 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:55] "POST /api/workorders/1/ai-suggestion HTTP/1.1" 200 - +2026-02-10 23:24:56,401 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:24:56,436 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:56] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:24:56,442 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:24:56,459 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:24:59,471 - src.web.blueprints.workorders - ERROR - 计算语义相似度失败: No module named 'sentence_transformers' +2026-02-10 23:24:59,479 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:59] "POST /api/workorders/1/human-resolution HTTP/1.1" 200 - +2026-02-10 23:25:01,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:01] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:01,405 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:01] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:05,076 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:05] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:25:06,400 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:06] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:11,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:11,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:11] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:16,398 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:16] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:21,392 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:21] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:21,439 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:21] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:26,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:26] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:31,384 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:31] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:31,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:31] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:31,428 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:31] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:25:36,400 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:36,417 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:36] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:36,430 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:38,174 - src.integrations.config_manager - WARNING - 配置现在从 .env 文件读取,无法通过 API 导入 +2026-02-10 23:25:38,176 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:38] "POST /api/feishu-sync/config/import HTTP/1.1" 500 - +2026-02-10 23:25:40,582 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:40] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:25:41,384 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:41] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:41,408 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:41] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:45,137 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:45] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:25:45,151 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:45] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:25:45,156 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:45] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:25:46,401 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:46] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:46,913 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:46] "GET /api/ai-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:25:46,922 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:46] "GET /api/ai-monitor/model-comparison HTTP/1.1" 200 - +2026-02-10 23:25:46,926 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:46] "GET /api/ai-monitor/error-distribution HTTP/1.1" 200 - +2026-02-10 23:25:46,928 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:46] "GET /api/ai-monitor/error-log HTTP/1.1" 200 - +2026-02-10 23:25:49,630 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:49] "GET /api/system-optimizer/status HTTP/1.1" 200 - +2026-02-10 23:25:49,636 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:49] "GET /api/system-optimizer/security-settings HTTP/1.1" 200 - +2026-02-10 23:25:49,637 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:49] "GET /api/system-optimizer/traffic-settings HTTP/1.1" 200 - +2026-02-10 23:25:49,638 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:49] "GET /api/system-optimizer/cost-settings HTTP/1.1" 200 - +2026-02-10 23:25:50,649 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:50] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:25:50,660 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:50] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:25:50,748 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:50] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:25:51,392 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:51] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:25:51,418 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:51] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:53,033 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:53] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:25:56,400 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:25:56,435 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:25:56,444 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:25:56,510 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:25:56,516 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:25:56,520 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:25:56,521 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:25:56,527 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:25:56,535 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:25:56,540 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:25:56,548 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:25:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:26:00,334 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:00] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:26:00,335 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:00] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:26:01,387 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:01] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:01,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:01] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:01,432 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:01] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:26:01,537 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:01] "GET /api/alerts?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:26:02,587 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:02] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:26:05,026 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:05] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:26:05,833 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:05] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:26:05,845 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:05] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:26:05,848 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:05] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:26:06,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:06] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:07,639 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:07] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:26:11,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:11,405 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:11] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:15,557 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:15] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:26:15,582 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:15] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:26:15,594 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:15,609 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:15,613 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:15] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:26:16,406 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:16] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:20,131 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:21,389 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:21] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:21,427 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:21] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:25,124 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:25,135 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:26,407 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:26] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:30,128 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:30] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:31,387 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:31] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:31,411 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:31] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:34,939 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:34] "GET /api/conversations?search=123 HTTP/1.1" 200 - +2026-02-10 23:26:35,122 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:35] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:35,134 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:35] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:36,414 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:36,437 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:36] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:26:40,132 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:40] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:41,395 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:41] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:41,421 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:41] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:44,247 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:44] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:26:45,121 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:45] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:45,135 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:45] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:46,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:46] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:46,666 - src.web.blueprints.knowledge - INFO - 搜索查询: '123' +2026-02-10 23:26:46,667 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '123' 返回 1 个结果 +2026-02-10 23:26:46,668 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 1 +2026-02-10 23:26:46,668 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:46] "GET /api/knowledge/search?q=123 HTTP/1.1" 200 - +2026-02-10 23:26:48,113 - src.web.blueprints.knowledge - INFO - 搜索查询: '123' +2026-02-10 23:26:48,114 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '123' 返回 1 个结果 +2026-02-10 23:26:48,114 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 1 +2026-02-10 23:26:48,114 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:48] "GET /api/knowledge/search?q=123 HTTP/1.1" 200 - +2026-02-10 23:26:50,140 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:50] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:50,845 - src.web.blueprints.knowledge - INFO - 搜索查询: '3' +2026-02-10 23:26:50,846 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '3' 返回 1 个结果 +2026-02-10 23:26:50,846 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 1 +2026-02-10 23:26:50,846 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:50] "GET /api/knowledge/search?q=3 HTTP/1.1" 200 - +2026-02-10 23:26:51,139 - src.web.blueprints.knowledge - INFO - 搜索查询: '3' +2026-02-10 23:26:51,140 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '3' 返回 1 个结果 +2026-02-10 23:26:51,141 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 1 +2026-02-10 23:26:51,141 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:51] "GET /api/knowledge/search?q=3 HTTP/1.1" 200 - +2026-02-10 23:26:51,316 - src.web.blueprints.knowledge - INFO - 搜索查询: '3' +2026-02-10 23:26:51,317 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '3' 返回 1 个结果 +2026-02-10 23:26:51,318 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 1 +2026-02-10 23:26:51,318 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:51] "GET /api/knowledge/search?q=3 HTTP/1.1" 200 - +2026-02-10 23:26:51,390 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:51] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:51,421 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:51] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:54,108 - src.web.blueprints.knowledge - INFO - 搜索查询: '4' +2026-02-10 23:26:54,109 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '4' 返回 0 个结果 +2026-02-10 23:26:54,110 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 0 +2026-02-10 23:26:54,110 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:54] "GET /api/knowledge/search?q=4 HTTP/1.1" 200 - +2026-02-10 23:26:54,318 - src.web.blueprints.knowledge - INFO - 搜索查询: '4' +2026-02-10 23:26:54,320 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '4' 返回 0 个结果 +2026-02-10 23:26:54,320 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 0 +2026-02-10 23:26:54,320 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:54] "GET /api/knowledge/search?q=4 HTTP/1.1" 200 - +2026-02-10 23:26:54,582 - src.web.blueprints.knowledge - INFO - 搜索查询: '4' +2026-02-10 23:26:54,583 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '4' 返回 0 个结果 +2026-02-10 23:26:54,583 - src.web.blueprints.knowledge - INFO - 搜索结果数量: 0 +2026-02-10 23:26:54,584 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:54] "GET /api/knowledge/search?q=4 HTTP/1.1" 200 - +2026-02-10 23:26:55,119 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:55] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:26:55,145 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:55] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:56,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:26:56,438 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:26:56,448 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:26:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:27:00,134 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:00] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:00,179 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:00] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:27:01,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:01] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:01,410 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:01] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:05,120 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:05] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:05,144 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:05] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:06,404 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:06] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:09,875 - src.agent_assistant - INFO - TSP Agent助手初始化完成 +2026-02-10 23:27:09,875 - src.agent_assistant - INFO - 保存知识条目 1: 关于README.md的问题1... +2026-02-10 23:27:09,875 - src.agent_assistant - INFO - 知识条目 1 保存成功 +2026-02-10 23:27:09,875 - src.agent_assistant - INFO - 保存知识条目 2: 关于README.md的问题2... +2026-02-10 23:27:09,875 - src.agent_assistant - INFO - 知识条目 2 保存成功 +2026-02-10 23:27:09,876 - src.agent_assistant - INFO - 保存知识条目 3: 关于README.md的问题3... +2026-02-10 23:27:09,876 - src.agent_assistant - INFO - 知识条目 3 保存成功 +2026-02-10 23:27:09,876 - src.agent_assistant - INFO - 保存知识条目 4: 关于README.md的问题5... +2026-02-10 23:27:09,876 - src.agent_assistant - INFO - 知识条目 4 保存成功 +2026-02-10 23:27:09,876 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:09] "POST /api/knowledge/upload HTTP/1.1" 200 - +2026-02-10 23:27:10,136 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:10] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:10,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:10] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:11,388 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:11,421 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:11] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:11,436 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:11] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:27:14,964 - src.web.websocket_server - INFO - 客户端断开: ('::1', 62164, 0, 0) +2026-02-10 23:27:14,971 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:14] "GET / HTTP/1.1" 200 - +2026-02-10 23:27:14,998 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:14] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:27:15,001 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:27:15,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:27:15,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:27:15,007 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:27:15,008 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:27:15,017 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:27:15,018 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:27:15,019 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:27:15,122 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:15,140 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:15,176 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:27:15,182 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:27:15,187 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:15,193 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:27:15,210 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:27:15,231 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:27:15,245 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:27:15,247 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:27:15,254 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:15,254 - websockets.server - INFO - connection open +2026-02-10 23:27:15,257 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:27:15,259 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:15,259 - src.web.websocket_server - INFO - 客户端连接: ('::1', 62446, 0, 0) +2026-02-10 23:27:15,261 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:27:15,263 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:27:15,290 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:27:15,320 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:27:15,335 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:27:15,347 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:27:18,266 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:18] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:20,133 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:20,192 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:27:20,202 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:20,210 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:27:20,237 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:27:20,248 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:27:20,262 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:27:20,451 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:20,990 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:20] "GET /api/alerts?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:21,530 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:21] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:21,997 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:21] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:22,184 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:22] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:22,349 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:22] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:27:25,123 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:25,137 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:25,178 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:27:25,192 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:30,199 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:30] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:27:30,227 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:30] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:27:30,245 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:30] "GET /api/monitor/status HTTP/1.1" 200 - diff --git a/logs/2026-02-10_23-48-47/dashboard.log b/logs/2026-02-10_23-48-47/dashboard.log new file mode 100644 index 0000000..9989bf3 --- /dev/null +++ b/logs/2026-02-10_23-48-47/dashboard.log @@ -0,0 +1,545 @@ +2026-02-10 23:48:47,381 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - Initializing unified configuration from environment variables... +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - Database config loaded. +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - LLM config loaded. +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - Server config loaded. +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - Feishu config loaded. +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - AI Accuracy config loaded. +2026-02-10 23:48:47,630 - src.config.unified_config - INFO - Configuration validation passed (warnings may exist). +2026-02-10 23:48:47,643 - src.core.database - INFO - 数据库初始化成功 +2026-02-10 23:48:47,646 - __main__ - INFO - 跳过系统检查,直接启动服务... +2026-02-10 23:48:48,910 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db +2026-02-10 23:48:48,913 - src.integrations.config_manager - INFO - 配置加载成功 +2026-02-10 23:48:49,025 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5001 + * Running on http://192.168.31.45:5001 +2026-02-10 23:48:49,025 - werkzeug - INFO - Press CTRL+C to quit +2026-02-10 23:48:49,026 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:49,050 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:49,051 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 +2026-02-10 23:48:49,054 - websockets.server - INFO - server listening on [::1]:8765 +2026-02-10 23:48:49,054 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2026-02-10 23:48:52,832 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:52] "GET / HTTP/1.1" 200 - +2026-02-10 23:48:53,497 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/components/AlertManager.js HTTP/1.1" 200 - +2026-02-10 23:48:53,498 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/core/store.js HTTP/1.1" 200 - +2026-02-10 23:48:53,498 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/services/api.js HTTP/1.1" 200 - +2026-02-10 23:48:53,499 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 200 - +2026-02-10 23:48:53,500 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/components/NotificationManager.js HTTP/1.1" 200 - +2026-02-10 23:48:53,501 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 200 - +2026-02-10 23:48:53,524 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/app-new.js HTTP/1.1" 200 - +2026-02-10 23:48:53,529 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 200 - +2026-02-10 23:48:53,613 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:53] "GET /static/css/design-system.css HTTP/1.1" 200 - +2026-02-10 23:48:55,761 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,764 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:48:55,765 - websockets.server - INFO - connection open +2026-02-10 23:48:55,767 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,768 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,771 - src.web.websocket_server - INFO - 客户端连接: ('::1', 63792, 0, 0) +2026-02-10 23:48:55,776 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,792 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,793 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,798 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:48:55,803 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,803 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,808 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,809 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,821 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:48:55,831 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,851 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT count(*) AS count_1 +FROM (SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders ORDER BY work_orders.created_at DESC) AS anon_1] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:55,852 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,856 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:48:55,863 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/workorders HTTP/1.1" 500 - +2026-02-10 23:48:55,880 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:48:55,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:48:55,908 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:48:55,936 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:48:55,939 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:48:55,967 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:55] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:48:56,002 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:48:56,021 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,023 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,027 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:48:56,065 - src.core.database - ERROR - 数据库操作失败: (sqlite3.DatabaseError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.033067',)] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:48:56,067 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.DatabaseError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.033067',)] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:48:56,071 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:48:56,086 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:48:56,110 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,111 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,114 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:48:56,154 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,155 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,157 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:48:56,359 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:48:56,400 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:48:56,427 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:48:56,433 - src.core.query_optimizer - ERROR - 优化分析查询失败: returned NULL without setting an exception +2026-02-10 23:48:56,435 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:48:56,479 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:48:56,483 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.480246',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,484 - src.core.query_optimizer - ERROR - 优化分析查询失败: returned NULL without setting an exception +2026-02-10 23:48:56,491 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.480246',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,498 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:48:56,517 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:48:56,542 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.537599',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:56,547 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:56.537599',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:57,683 - src.agent_assistant - INFO - TSP Agent助手初始化完成 +2026-02-10 23:48:57,684 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:57] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:48:58,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET / HTTP/1.1" 200 - +2026-02-10 23:48:58,437 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:48:58,440 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:48:58,441 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:48:58,447 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:48:58,449 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:48:58,455 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:48:58,457 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:48:58,460 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:48:58,462 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:48:58,843 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:48:58,845 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:48:58,855 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:48:58,861 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:48:58,886 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:48:58,892 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT count(*) AS count_1 +FROM (SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders ORDER BY work_orders.created_at DESC) AS anon_1] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:58,896 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/workorders HTTP/1.1" 500 - +2026-02-10 23:48:58,907 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:48:58,922 - src.core.database - ERROR - 数据库操作失败: (sqlite3.DatabaseError) another row available +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations) AS anon_1] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:48:58,925 - src.core.query_optimizer - ERROR - 分页查询对话失败: (sqlite3.DatabaseError) another row available +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations) AS anon_1] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:48:58,929 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:48:58,931 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:48:58,932 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:48:58,933 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:48:58,939 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:48:58,942 - websockets.server - INFO - connection open +2026-02-10 23:48:58,948 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:58.945590',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:58,950 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:48:58,951 - src.web.websocket_server - INFO - 客户端连接: ('::1', 63842, 0, 0) +2026-02-10 23:48:58,951 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:48:58.945590',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:58,966 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:58,966 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:58,967 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:48:58,997 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:48:59,008 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:59,009 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:59,010 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:59] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:48:59,020 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:59,021 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:48:59,022 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:59] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:49:00,644 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:00.643444',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:00,645 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:00.643444',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:00,650 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:00] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:00,698 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:00] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:49:00,698 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:00,701 - src.core.query_optimizer - ERROR - 优化分析查询失败: returned NULL without setting an exception +2026-02-10 23:49:00,703 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:00] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:49:00,710 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:00,712 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:00,714 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:00] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:49:00,725 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:00.721862',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:00,725 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:00.721862',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,858 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:03.857297',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,860 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:03.857297',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,863 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:03] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:03,927 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:03] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:49:03,932 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,933 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,936 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:03] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:49:03,948 - src.core.database - ERROR - 数据库操作失败: (sqlite3.DatabaseError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:49:03,951 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.DatabaseError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:49:03,954 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:03] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:49:03,955 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:03.952792',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:03,957 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:03.952792',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:04,970 - src.web.websocket_server - INFO - 客户端断开: ('::1', 63842, 0, 0) +2026-02-10 23:49:04,975 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:04] "GET / HTTP/1.1" 200 - +2026-02-10 23:49:05,012 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:49:05,014 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:49:05,019 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:49:05,025 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:49:05,026 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:49:05,034 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:49:05,036 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:49:05,038 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:49:05,042 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:49:05,162 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:05,168 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:49:05,184 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:49:05,193 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:49:05,217 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:49:05,227 - src.core.database - ERROR - 数据库操作失败: (sqlite3.DatabaseError) no such column: work_orders.assigned_module +[SQL: SELECT count(*) AS count_1 +FROM (SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders ORDER BY work_orders.created_at DESC) AS anon_1] +(Background on this error at: https://sqlalche.me/e/20/4xp6) +2026-02-10 23:49:05,230 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/workorders HTTP/1.1" 500 - +2026-02-10 23:49:05,244 - websockets.server - INFO - connection open +2026-02-10 23:49:05,254 - src.web.websocket_server - INFO - 客户端连接: ('::1', 63889, 0, 0) +2026-02-10 23:49:05,257 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:49:05,259 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:05,265 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:49:05,266 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:49:05,275 - src.web.error_handlers - ERROR - 未处理错误 get_health: returned NULL without setting an exception +2026-02-10 23:49:05,279 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:49:05,281 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:49:05,283 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:05,293 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:49:05,293 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,295 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,298 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:49:05,320 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:49:05,327 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,328 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,330 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:49:05,337 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,337 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,339 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:49:05,632 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:05,661 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:05.657713',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,664 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:05.657713',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:05,671 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:10,174 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:10,176 - src.web.error_handlers - ERROR - 未处理错误 get_health: returned NULL without setting an exception +2026-02-10 23:49:10,178 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:10] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:10,649 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:10.648202',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:10,650 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:10.648202',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:10,655 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:10] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:15,437 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:15,469 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:15.467371',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:15,471 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:15.467371',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:15,477 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:15,633 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:15,654 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:15,672 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:15.671190',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:15,672 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:15.671190',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:20,653 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:20,654 - src.web.error_handlers - ERROR - 未处理错误 get_health: returned NULL without setting an exception +2026-02-10 23:49:20,658 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:21,941 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:21.940713',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:21,942 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:21.940713',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:21,947 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:21] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:25,489 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:25,773 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:49:25,801 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:49:25,814 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:25,819 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/workorders HTTP/1.1" 500 - +2026-02-10 23:49:25,820 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:49:25,838 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:49:25,838 - src.core.database - ERROR - 数据库操作失败: returned NULL without setting an exception +2026-02-10 23:49:25,839 - src.web.error_handlers - ERROR - 未处理错误 get_health: returned NULL without setting an exception +2026-02-10 23:49:25,843 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:25,862 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:25.860290',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,863 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:25.860290',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,864 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,866 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,867 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:49:25,879 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:49:25,886 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,886 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,887 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:49:25,897 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,898 - src.core.query_optimizer - ERROR - 优化分析查询失败: (sqlite3.OperationalError) no such column: work_orders.assigned_module +[SQL: SELECT work_orders.id AS work_orders_id, work_orders.order_id AS work_orders_order_id, work_orders.title AS work_orders_title, work_orders.description AS work_orders_description, work_orders.category AS work_orders_category, work_orders.priority AS work_orders_priority, work_orders.status AS work_orders_status, work_orders.created_at AS work_orders_created_at, work_orders.updated_at AS work_orders_updated_at, work_orders.resolution AS work_orders_resolution, work_orders.satisfaction_score AS work_orders_satisfaction_score, work_orders.feishu_record_id AS work_orders_feishu_record_id, work_orders.assignee AS work_orders_assignee, work_orders.solution AS work_orders_solution, work_orders.ai_suggestion AS work_orders_ai_suggestion, work_orders.source AS work_orders_source, work_orders.module AS work_orders_module, work_orders.created_by AS work_orders_created_by, work_orders.wilfulness AS work_orders_wilfulness, work_orders.date_of_close AS work_orders_date_of_close, work_orders.vehicle_type AS work_orders_vehicle_type, work_orders.vin_sim AS work_orders_vin_sim, work_orders.app_remote_control_version AS work_orders_app_remote_control_version, work_orders.hmi_sw AS work_orders_hmi_sw, work_orders.parent_record AS work_orders_parent_record, work_orders.has_updated_same_day AS work_orders_has_updated_same_day, work_orders.operating_time AS work_orders_operating_time, work_orders.assigned_module AS work_orders_assigned_module, work_orders.module_owner AS work_orders_module_owner, work_orders.dispatcher AS work_orders_dispatcher, work_orders.dispatch_time AS work_orders_dispatch_time, work_orders.region AS work_orders_region +FROM work_orders] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:25,900 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:25] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:49:27,790 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:27] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:27,800 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:27.799327',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:27,800 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:27.799327',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:30,641 - src.core.database - ERROR - 数据库操作失败: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:30.640792',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:30,642 - src.web.error_handlers - ERROR - 未处理错误 get_health: (sqlite3.OperationalError) no such column: conversations.ip_address +[SQL: SELECT count(*) AS count_1 +FROM (SELECT conversations.id AS conversations_id, conversations.work_order_id AS conversations_work_order_id, conversations.user_message AS conversations_user_message, conversations.assistant_response AS conversations_assistant_response, conversations.timestamp AS conversations_timestamp, conversations.confidence_score AS conversations_confidence_score, conversations.knowledge_used AS conversations_knowledge_used, conversations.response_time AS conversations_response_time, conversations.ip_address AS conversations_ip_address, conversations.invocation_method AS conversations_invocation_method +FROM conversations +WHERE conversations.timestamp >= ?) AS anon_1] +[parameters: ('2026-02-10 22:49:30.640792',)] +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2026-02-10 23:49:30,642 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:30] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:49:30,693 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:30] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - diff --git a/logs/2026-02-10_23-51-10/dashboard.log b/logs/2026-02-10_23-51-10/dashboard.log new file mode 100644 index 0000000..8e13b30 --- /dev/null +++ b/logs/2026-02-10_23-51-10/dashboard.log @@ -0,0 +1,298 @@ +2026-02-10 23:51:10,759 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... +2026-02-10 23:51:11,024 - src.config.unified_config - INFO - Initializing unified configuration from environment variables... +2026-02-10 23:51:11,024 - src.config.unified_config - INFO - Database config loaded. +2026-02-10 23:51:11,024 - src.config.unified_config - INFO - LLM config loaded. +2026-02-10 23:51:11,024 - src.config.unified_config - INFO - Server config loaded. +2026-02-10 23:51:11,024 - src.config.unified_config - INFO - Feishu config loaded. +2026-02-10 23:51:11,025 - src.config.unified_config - INFO - AI Accuracy config loaded. +2026-02-10 23:51:11,025 - src.config.unified_config - INFO - Configuration validation passed (warnings may exist). +2026-02-10 23:51:11,038 - src.core.database - INFO - 数据库初始化成功 +2026-02-10 23:51:11,040 - __main__ - INFO - 跳过系统检查,直接启动服务... +2026-02-10 23:51:12,376 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db +2026-02-10 23:51:12,381 - src.integrations.config_manager - INFO - 配置加载成功 +2026-02-10 23:51:12,536 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5001 + * Running on http://192.168.31.45:5001 +2026-02-10 23:51:12,536 - werkzeug - INFO - Press CTRL+C to quit +2026-02-10 23:51:12,541 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:12,573 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:12,574 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 +2026-02-10 23:51:12,578 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2026-02-10 23:51:12,579 - websockets.server - INFO - server listening on [::1]:8765 +2026-02-10 23:51:12,966 - websockets.server - INFO - connection open +2026-02-10 23:51:12,966 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64226, 0, 0) +2026-02-10 23:51:14,450 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,451 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,453 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,457 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:14] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:14,457 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,458 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,462 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,464 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:14] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:14,465 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:14] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:14,468 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,469 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,473 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,473 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,474 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:14,487 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:14,493 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:14] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:14,538 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:14] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:15,629 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:15,659 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:15,692 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:15] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:16,549 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:16,581 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:16,583 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:16,585 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:16,586 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:16,587 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:16,589 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:16,591 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:16,593 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:16,594 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:16,660 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:16,661 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:16,678 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:51:16,684 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:51:16,694 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:16,704 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:16,706 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:16,715 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:16,727 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:16,739 - websockets.server - INFO - connection open +2026-02-10 23:51:16,748 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:16,751 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64265, 0, 0) +2026-02-10 23:51:16,754 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:16,756 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:16,758 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:16,766 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:16,776 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:16,799 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:16,824 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:16,831 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:17,552 - src.agent_assistant - INFO - TSP Agent助手初始化完成 +2026-02-10 23:51:17,553 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:17] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:19,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:19] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:20,641 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:21,177 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:21,625 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/alerts?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:21,682 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:21,710 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:21,711 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:21,728 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:21] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:22,136 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:22] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:22,137 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:22] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:51:24,059 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1770738684 +2026-02-10 23:51:24,060 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:24] "POST /api/chat/session HTTP/1.1" 200 - +2026-02-10 23:51:25,249 - src.knowledge_base.knowledge_manager - WARNING - 知识库中没有活跃条目 +2026-02-10 23:51:25,635 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:25,637 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:25,649 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:25,688 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:25,699 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:25,700 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:25,715 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:25,731 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:25,742 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:25,763 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:25] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:26,661 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:26] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:26,697 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:26] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:28,485 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:51:28,490 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:28] "POST /api/chat/message HTTP/1.1" 200 - +2026-02-10 23:51:30,251 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:30] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:30,645 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:30] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:31,677 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:31] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:33,186 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:33] "POST /api/conversations/migrate-merge HTTP/1.1" 200 - +2026-02-10 23:51:33,189 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:33] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:35,639 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:35] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:35,664 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:35] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:36,253 - src.web.websocket_server - INFO - 客户端断开: ('::1', 64265, 0, 0) +2026-02-10 23:51:36,257 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:36,280 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:36,281 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:36,288 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:36,289 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:36,291 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:36,292 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:36,293 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:36,294 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:36,297 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:36,360 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:36,362 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:36,364 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:36,372 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:36,383 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:36,394 - websockets.server - INFO - connection open +2026-02-10 23:51:36,397 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:36,402 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:36,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:36,404 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64376, 0, 0) +2026-02-10 23:51:36,412 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:36,414 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:36,416 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:36,423 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:36,433 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:36,441 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:36,458 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:36,466 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:36,475 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:38,509 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:38] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:40,466 - src.web.websocket_server - INFO - 客户端断开: ('::1', 64376, 0, 0) +2026-02-10 23:51:40,469 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:40,495 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:40,498 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:40,503 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:40,509 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:40,512 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:40,515 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:40,516 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:40,519 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:40,520 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:40,641 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:40,675 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:40,676 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:40,677 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:40,692 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:40,701 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:40,711 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:40,716 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:40,725 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:40,725 - websockets.server - INFO - connection open +2026-02-10 23:51:40,730 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:40,731 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:40,732 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64413, 0, 0) +2026-02-10 23:51:40,739 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:40,743 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:40,744 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:40,752 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:40,766 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:40,772 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:40,780 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:42,303 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:42] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:42,303 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:42] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:51:44,893 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1770738704 +2026-02-10 23:51:44,895 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:44] "POST /api/chat/session HTTP/1.1" 200 - +2026-02-10 23:51:45,629 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:45,658 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:45,692 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:45,709 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:45,713 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:45,723 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:45] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:46,347 - src.knowledge_base.knowledge_manager - WARNING - 知识库中没有活跃条目 +2026-02-10 23:51:49,951 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:51:49,961 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:49] "POST /api/chat/message HTTP/1.1" 200 - +2026-02-10 23:51:50,642 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:50] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:50,679 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:50] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:50,703 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:50] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:51,250 - src.dialogue.realtime_chat - INFO - 结束会话: session_user_001_1770738704 +2026-02-10 23:51:51,251 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:51] "DELETE /api/chat/session/session_user_001_1770738704 HTTP/1.1" 200 - +2026-02-10 23:51:52,872 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:52] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:55,386 - src.web.websocket_server - INFO - 客户端断开: ('::1', 64413, 0, 0) +2026-02-10 23:51:55,389 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:55,411 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:55,412 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:55,418 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:55,422 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:55,424 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:55,425 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:55,426 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:55,427 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:55,430 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:55,489 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:55,491 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:55,495 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:55,496 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:55,511 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:55,518 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:55,520 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:55,521 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:55,522 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:55,530 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:55,530 - websockets.server - INFO - connection open +2026-02-10 23:51:55,539 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64475, 0, 0) +2026-02-10 23:51:55,542 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:55,544 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:55,545 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:55,555 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:55,574 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:55,583 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:55,591 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:55,632 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:55,638 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:55,647 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:55,653 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:55,661 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:55,675 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:55,676 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:55,690 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:55,699 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:55,708 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:55,718 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:56,132 - src.web.websocket_server - INFO - 客户端断开: ('::1', 64475, 0, 0) +2026-02-10 23:51:56,135 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:56,158 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:56,159 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:56,168 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:56,169 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:56,170 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:56,172 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:56,173 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:56,174 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:56,176 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:56,236 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:56,239 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:56,241 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:56,249 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:56,260 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:56,265 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:56,269 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:56,276 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:56,277 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:56,280 - websockets.server - INFO - connection open +2026-02-10 23:51:56,283 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:56,288 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:56,291 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64530, 0, 0) +2026-02-10 23:51:56,299 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:56,301 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:56,314 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:56,334 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:56,344 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:56,355 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:51:56,693 - src.web.websocket_server - INFO - 客户端断开: ('::1', 64530, 0, 0) +2026-02-10 23:51:56,697 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET / HTTP/1.1" 200 - +2026-02-10 23:51:56,719 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:56,720 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:51:56,723 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:51:56,727 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:51:56,727 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:51:56,728 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:51:56,731 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:51:56,733 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:51:56,736 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:51:56,828 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:51:56,829 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:51:56,840 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:51:56,846 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:51:56,867 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:51:56,877 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:51:56,879 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:51:56,881 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:51:56,892 - websockets.server - INFO - connection open +2026-02-10 23:51:56,897 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:51:56,904 - src.web.websocket_server - INFO - 客户端连接: ('::1', 64557, 0, 0) +2026-02-10 23:51:56,906 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:51:56,908 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:51:56,910 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:51:56,918 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:51:56,935 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:51:56,956 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:51:56,968 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:51:56,977 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:52:00,641 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:00] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:52:01,926 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:01] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:52:05,630 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:05] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:52:05,659 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:05] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:52:08,742 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:08] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:52:08,759 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:52:08] "GET /api/monitor/status HTTP/1.1" 200 - diff --git a/logs/2026-02-10_23-55-42/dashboard.log b/logs/2026-02-10_23-55-42/dashboard.log new file mode 100644 index 0000000..01791a3 --- /dev/null +++ b/logs/2026-02-10_23-55-42/dashboard.log @@ -0,0 +1,237 @@ +2026-02-10 23:55:42,753 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - Initializing unified configuration from environment variables... +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - Database config loaded. +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - LLM config loaded. +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - Server config loaded. +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - Feishu config loaded. +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - AI Accuracy config loaded. +2026-02-10 23:55:42,982 - src.config.unified_config - INFO - Configuration validation passed (warnings may exist). +2026-02-10 23:55:42,994 - src.core.database - INFO - 数据库初始化成功 +2026-02-10 23:55:42,996 - __main__ - INFO - 跳过系统检查,直接启动服务... +2026-02-10 23:55:44,509 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db +2026-02-10 23:55:44,513 - src.integrations.config_manager - INFO - 配置加载成功 +2026-02-10 23:55:44,684 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:44,685 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5001 + * Running on http://192.168.31.45:5001 +2026-02-10 23:55:44,695 - werkzeug - INFO - Press CTRL+C to quit +2026-02-10 23:55:44,717 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:44,718 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 +2026-02-10 23:55:44,722 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2026-02-10 23:55:44,723 - websockets.server - INFO - server listening on [::1]:8765 +2026-02-10 23:55:47,331 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,332 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,346 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,355 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,358 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,361 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:47] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:55:47,362 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,362 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:47] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:55:47,374 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,374 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,375 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,383 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:47] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:55:47,385 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,388 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:47,394 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:47,427 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:47] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:55:47,443 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:47] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:55:49,849 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET / HTTP/1.1" 200 - +2026-02-10 23:55:49,883 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:55:49,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:55:49,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:55:49,885 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:55:49,893 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:55:49,895 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:55:49,897 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:55:49,897 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:55:49,898 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:55:50,144 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:55:50,149 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:55:50,151 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:55:50,159 - src.knowledge_base.knowledge_manager - WARNING - 知识库尚无活跃条目,向量化器将保持空状态 +2026-02-10 23:55:50,161 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:55:50,162 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:55:50,186 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:55:50,191 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:55:50,201 - websockets.server - INFO - connection open +2026-02-10 23:55:50,205 - src.web.websocket_server - INFO - 客户端连接: ('::1', 65043, 0, 0) +2026-02-10 23:55:50,220 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:55:50,222 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:55:50,230 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:55:50,235 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:55:50,241 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:55:50,262 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:55:50,262 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:55:50,298 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:55:50,320 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:55:50,342 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:50] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:55:51,214 - src.agent_assistant - INFO - TSP Agent助手初始化完成 +2026-02-10 23:55:51,214 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:51] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:55:54,013 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:54] "GET /api/conversations/3 HTTP/1.1" 200 - +2026-02-10 23:55:55,158 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:55] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:55:55,189 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:55] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:55:55,190 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:55] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:55:55,199 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:55] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:55:57,948 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:57] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:55:57,966 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:57] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:55:57,975 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:57] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:56:00,145 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:00] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:00,162 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:00] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:00,232 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:00] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:00,935 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:00] "GET /api/alerts?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:02,767 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:02] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:05,157 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:05] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:08,454 - src.knowledge_base.knowledge_manager - INFO - 正在初始化知识库向量化器... +2026-02-10 23:56:08,457 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功: 共处理 1 个知识条目 +2026-02-10 23:56:08,457 - src.knowledge_base.knowledge_manager - INFO - 添加知识库条目成功: 123... +2026-02-10 23:56:08,458 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:08] "POST /api/knowledge HTTP/1.1" 200 - +2026-02-10 23:56:08,471 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:08] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:10,143 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:10] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:10,170 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:10] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:10,377 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 1 +2026-02-10 23:56:10,378 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:10] "POST /api/knowledge/verify/1 HTTP/1.1" 200 - +2026-02-10 23:56:10,383 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:10] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:12,315 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1770738972 +2026-02-10 23:56:12,316 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:12] "POST /api/chat/session HTTP/1.1" 200 - +2026-02-10 23:56:14,758 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '123' 返回 1 个结果 +2026-02-10 23:56:15,156 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:16,283 - src.core.llm_client - INFO - API请求成功 +2026-02-10 23:56:16,289 - src.knowledge_base.knowledge_manager - INFO - 成功更新 1 个知识库条目的使用次数 +2026-02-10 23:56:16,290 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:16] "POST /api/chat/message HTTP/1.1" 200 - +2026-02-10 23:56:20,148 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:20] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:20,182 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:20] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:20,229 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:20] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:56:20,230 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:20] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:56:21,681 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:21] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:23,895 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:23] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:56:23,895 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:23] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:56:25,157 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:25] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:25,188 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:25] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:56:26,989 - src.dialogue.realtime_chat - INFO - 结束会话: session_user_001_1770738972 +2026-02-10 23:56:26,990 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:26] "DELETE /api/chat/session/session_user_001_1770738972 HTTP/1.1" 200 - +2026-02-10 23:56:28,275 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:28] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:56:28,284 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:28] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:56:28,293 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:28] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:56:28,859 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:28] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:30,147 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:30] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:30,165 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:30] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:31,366 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:31] "POST /api/conversations/migrate-merge HTTP/1.1" 200 - +2026-02-10 23:56:31,369 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:31] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:33,616 - src.web.websocket_server - INFO - 客户端断开: ('::1', 65043, 0, 0) +2026-02-10 23:56:33,619 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET / HTTP/1.1" 200 - +2026-02-10 23:56:33,642 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:56:33,643 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - +2026-02-10 23:56:33,648 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/core/store.js HTTP/1.1" 304 - +2026-02-10 23:56:33,649 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/services/api.js HTTP/1.1" 304 - +2026-02-10 23:56:33,654 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - +2026-02-10 23:56:33,656 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - +2026-02-10 23:56:33,658 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/app-new.js HTTP/1.1" 304 - +2026-02-10 23:56:33,660 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - +2026-02-10 23:56:33,661 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /static/css/design-system.css HTTP/1.1" 304 - +2026-02-10 23:56:33,715 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:56:33,717 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:56:33,721 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/rules HTTP/1.1" 200 - +2026-02-10 23:56:33,723 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:33,731 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:56:33,746 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/system/info HTTP/1.1" 200 - +2026-02-10 23:56:33,748 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:56:33,760 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:33,768 - websockets.server - INFO - connection open +2026-02-10 23:56:33,770 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/feishu-sync/config HTTP/1.1" 200 - +2026-02-10 23:56:33,770 - src.web.websocket_server - INFO - 客户端连接: ('::1', 65161, 0, 0) +2026-02-10 23:56:33,774 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:56:33,776 - src.web.blueprints.feishu_sync - ERROR - 获取同步状态失败: 飞书配置不完整,请先配置飞书应用信息 +2026-02-10 23:56:33,780 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/feishu-sync/status HTTP/1.1" 500 - +2026-02-10 23:56:33,787 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:33,799 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:56:33,814 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:56:33,829 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:56:33,841 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:56:38,725 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:38] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:38,747 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:38] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:56:38,751 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:38] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:56:38,763 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:38] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:56:42,962 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:42] "DELETE /api/conversations/2 HTTP/1.1" 200 - +2026-02-10 23:56:42,970 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:42] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:45,054 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:45] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:45,071 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:45] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:50,703 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:50] "DELETE /api/conversations/5 HTTP/1.1" 200 - +2026-02-10 23:56:50,710 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:50] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:56:51,423 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:51] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:56:56,407 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:56] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:56:56,422 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:56] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:11,410 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:57:11,422 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:11] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:16,416 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:16] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:21,403 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:21] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:57:31,615 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:31] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:57:33,383 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:33] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:35,756 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:35] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:57:36,898 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:36] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:57:36,907 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:36] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:57:36,915 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:36] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:57:37,876 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:37] "GET /api/ai-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:57:37,888 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:37] "GET /api/ai-monitor/model-comparison HTTP/1.1" 200 - +2026-02-10 23:57:37,893 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:37] "GET /api/ai-monitor/error-distribution HTTP/1.1" 200 - +2026-02-10 23:57:37,896 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:37] "GET /api/ai-monitor/error-log HTTP/1.1" 200 - +2026-02-10 23:57:38,386 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:38] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:39,551 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:39] "GET /api/system-optimizer/status HTTP/1.1" 200 - +2026-02-10 23:57:39,556 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:39] "GET /api/system-optimizer/security-settings HTTP/1.1" 200 - +2026-02-10 23:57:39,557 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:39] "GET /api/system-optimizer/traffic-settings HTTP/1.1" 200 - +2026-02-10 23:57:39,558 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:39] "GET /api/system-optimizer/cost-settings HTTP/1.1" 200 - +2026-02-10 23:57:40,097 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:40] "POST /api/system-optimizer/optimize-all HTTP/1.1" 200 - +2026-02-10 23:57:41,103 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "GET /api/system-optimizer/status HTTP/1.1" 200 - +2026-02-10 23:57:41,110 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "GET /api/system-optimizer/cost-settings HTTP/1.1" 200 - +2026-02-10 23:57:41,111 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "GET /api/system-optimizer/security-settings HTTP/1.1" 200 - +2026-02-10 23:57:41,111 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "GET /api/system-optimizer/traffic-settings HTTP/1.1" 200 - +2026-02-10 23:57:41,278 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "POST /api/system-optimizer/clear-cache HTTP/1.1" 200 - +2026-02-10 23:57:41,614 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:41] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:57:42,286 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:42] "GET /api/system-optimizer/status HTTP/1.1" 200 - +2026-02-10 23:57:42,295 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:42] "GET /api/system-optimizer/security-settings HTTP/1.1" 200 - +2026-02-10 23:57:42,296 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:42] "GET /api/system-optimizer/traffic-settings HTTP/1.1" 200 - +2026-02-10 23:57:42,297 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:42] "GET /api/system-optimizer/cost-settings HTTP/1.1" 200 - +2026-02-10 23:57:43,379 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:43] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:57:43,397 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:43] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:57:43,409 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:43] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:46,560 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:46] "GET /api/ai-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:57:46,570 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:46] "GET /api/ai-monitor/error-log HTTP/1.1" 200 - +2026-02-10 23:57:46,571 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:46] "GET /api/ai-monitor/model-comparison HTTP/1.1" 200 - +2026-02-10 23:57:46,572 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:46] "GET /api/ai-monitor/error-distribution HTTP/1.1" 200 - +2026-02-10 23:57:48,026 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:48] "GET /api/agent/status HTTP/1.1" 200 - +2026-02-10 23:57:48,027 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:48] "GET /api/agent/tools/stats HTTP/1.1" 200 - +2026-02-10 23:57:48,385 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:48] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:50,785 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/chat/sessions HTTP/1.1" 200 - +2026-02-10 23:57:50,792 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/workorders HTTP/1.1" 200 - +2026-02-10 23:57:50,793 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - +2026-02-10 23:57:50,799 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/knowledge/stats HTTP/1.1" 200 - +2026-02-10 23:57:50,806 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - +2026-02-10 23:57:50,822 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/settings HTTP/1.1" 200 - +2026-02-10 23:57:50,830 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/analytics HTTP/1.1" 200 - +2026-02-10 23:57:50,840 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:50] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2026-02-10 23:57:51,613 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:51] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:57:53,389 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:53] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:57:53,422 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:53] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - +2026-02-10 23:57:55,324 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:55] "GET /api/token-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:57:55,337 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:55] "GET /api/token-monitor/records HTTP/1.1" 200 - +2026-02-10 23:57:55,342 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:55] "GET /api/token-monitor/chart HTTP/1.1" 200 - +2026-02-10 23:57:56,246 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:56] "GET /api/ai-monitor/stats HTTP/1.1" 200 - +2026-02-10 23:57:56,253 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:56] "GET /api/ai-monitor/error-distribution HTTP/1.1" 200 - +2026-02-10 23:57:56,255 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:56] "GET /api/ai-monitor/model-comparison HTTP/1.1" 200 - +2026-02-10 23:57:56,256 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:56] "GET /api/ai-monitor/error-log HTTP/1.1" 200 - +2026-02-10 23:57:58,382 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:57:58] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:01,614 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:01] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:58:03,388 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:03] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:08,481 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:08] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:11,998 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:11] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:58:14,480 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:14] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:23,303 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:23] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:58:26,634 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:26] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:31,960 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:31] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:58:48,331 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:48] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:58:48,348 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:58:48] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-10 23:59:15,050 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:59:15] "GET /api/alerts HTTP/1.1" 200 - +2026-02-10 23:59:15,062 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:59:15] "GET /api/monitor/status HTTP/1.1" 200 - +2026-02-11 00:00:08,355 - werkzeug - INFO - 127.0.0.1 - - [11/Feb/2026 00:00:08] "GET /api/alerts HTTP/1.1" 200 - +2026-02-11 00:00:08,367 - werkzeug - INFO - 127.0.0.1 - - [11/Feb/2026 00:00:08] "GET /api/monitor/status HTTP/1.1" 200 - diff --git a/logs/dashboard.log b/logs/dashboard.log deleted file mode 100644 index aabaf24..0000000 --- a/logs/dashboard.log +++ /dev/null @@ -1,1230 +0,0 @@ -2025-12-07 22:35:31,916 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 22:35:31,916 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 22:35:31,935 - __main__ - ERROR - 启动失败: unexpected indent (app.py, line 703) -2025-12-07 22:35:34,855 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 22:35:34,855 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 22:35:34,894 - __main__ - ERROR - 启动失败: unexpected indent (app.py, line 703) -2025-12-07 22:38:40,362 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 22:38:40,362 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 22:38:47,496 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 22:38:50,400 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 22:38:50,400 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 22:38:50,531 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 22:38:50,531 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 22:38:51,090 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 22:38:51,498 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 22:38:51,514 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 22:38:51,516 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 22:38:53,504 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET / HTTP/1.1" 200 - -2025-12-07 22:38:53,802 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:53,818 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:53,830 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/css/variables.css HTTP/1.1" 304 - -2025-12-07 22:38:53,830 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/css/components.css HTTP/1.1" 304 - -2025-12-07 22:38:53,834 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/css/layout.css HTTP/1.1" 304 - -2025-12-07 22:38:53,890 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 22:38:53,890 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 22:38:53,890 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 22:38:53,898 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 22:38:53,907 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 22:38:53,909 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 22:38:53,914 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 22:38:53,931 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /static/js/pages/login.js HTTP/1.1" 304 - -2025-12-07 22:38:53,931 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:53] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 22:38:54,298 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET / HTTP/1.1" 200 - -2025-12-07 22:38:54,340 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:54,340 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:54,366 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/variables.css HTTP/1.1" 304 - -2025-12-07 22:38:54,380 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/components.css HTTP/1.1" 304 - -2025-12-07 22:38:54,380 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/layout.css HTTP/1.1" 304 - -2025-12-07 22:38:54,410 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 22:38:54,423 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 22:38:54,427 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 22:38:54,427 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 22:38:54,442 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 22:38:54,442 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 22:38:54,442 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 22:38:54,481 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/pages/login.js HTTP/1.1" 304 - -2025-12-07 22:38:54,490 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 22:38:54,833 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET / HTTP/1.1" 200 - -2025-12-07 22:38:54,859 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:54,867 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 22:38:54,885 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/variables.css HTTP/1.1" 304 - -2025-12-07 22:38:54,890 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/components.css HTTP/1.1" 304 - -2025-12-07 22:38:54,890 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/css/layout.css HTTP/1.1" 304 - -2025-12-07 22:38:54,915 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 22:38:54,915 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 22:38:54,923 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 22:38:54,923 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 22:38:54,936 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 22:38:54,940 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 22:38:54,947 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 22:38:54,970 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /static/js/pages/login.js HTTP/1.1" 304 - -2025-12-07 22:38:54,970 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:38:54] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 22:39:02,958 - src.web.error_handlers - ERROR - 错误响应: 用户名或密码错误 - None -2025-12-07 22:39:02,958 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:39:02] "POST /api/login HTTP/1.1" 401 - -2025-12-07 22:42:12,287 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 22:42:12,287 - src.web.error_handlers - ERROR - 未处理错误 login: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 22:42:12,287 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:42:12] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:43:22,951 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:43:22,951 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:43:22] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:44:23,984 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:44:23,984 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:44:23] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:45:00,229 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:45:00,229 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:45:00] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:45:22,453 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:45:22,453 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:45:22] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:46:50,929 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:46:50,929 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:46:50] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:47:31,069 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:47:31,069 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:47:31] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:48:52,888 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:48:52,888 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:48:52] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:49:30,361 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:49:30,361 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:49:30] "POST /api/login HTTP/1.1" 500 - -2025-12-07 22:50:24,422 - src.web.error_handlers - ERROR - 未处理错误 login: Instance is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3) -2025-12-07 22:50:24,422 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 22:50:24] "POST /api/login HTTP/1.1" 500 - -2025-12-07 23:11:26,193 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 23:11:26,193 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 23:11:32,645 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 23:11:35,621 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 23:11:35,637 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 23:11:35,797 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 23:11:35,805 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 23:11:36,246 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:36,639 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 23:11:36,662 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 23:11:36,662 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 23:11:38,588 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET / HTTP/1.1" 200 - -2025-12-07 23:11:38,864 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:38,884 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:38,896 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/css/variables.css HTTP/1.1" 200 - -2025-12-07 23:11:38,896 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/css/components.css HTTP/1.1" 200 - -2025-12-07 23:11:38,896 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/css/layout.css HTTP/1.1" 200 - -2025-12-07 23:11:38,964 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 23:11:38,971 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 23:11:38,971 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 23:11:38,977 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 23:11:38,987 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 23:11:38,987 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/components/navbar.js HTTP/1.1" 200 - -2025-12-07 23:11:38,987 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:38] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 23:11:39,029 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 23:11:39,029 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/pages/dashboard.js HTTP/1.1" 200 - -2025-12-07 23:11:39,086 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/api.js HTTP/1.1" 304 - -2025-12-07 23:11:39,397 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET / HTTP/1.1" 200 - -2025-12-07 23:11:39,457 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:39,457 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:39,471 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/variables.css HTTP/1.1" 304 - -2025-12-07 23:11:39,480 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/components.css HTTP/1.1" 304 - -2025-12-07 23:11:39,484 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/layout.css HTTP/1.1" 304 - -2025-12-07 23:11:39,503 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 23:11:39,513 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 23:11:39,522 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 23:11:39,522 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 23:11:39,539 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 23:11:39,539 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 23:11:39,539 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 23:11:39,554 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/pages/dashboard.js HTTP/1.1" 304 - -2025-12-07 23:11:39,570 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 23:11:39,587 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/core/api.js HTTP/1.1" 304 - -2025-12-07 23:11:39,928 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET / HTTP/1.1" 200 - -2025-12-07 23:11:39,953 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:39,953 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:11:39,969 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/variables.css HTTP/1.1" 304 - -2025-12-07 23:11:39,977 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/components.css HTTP/1.1" 304 - -2025-12-07 23:11:39,977 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:39] "GET /static/css/layout.css HTTP/1.1" 304 - -2025-12-07 23:11:40,016 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 23:11:40,020 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 23:11:40,020 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 23:11:40,025 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 23:11:40,040 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 23:11:40,044 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 23:11:40,047 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 23:11:40,070 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 23:11:40,072 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/pages/dashboard.js HTTP/1.1" 304 - -2025-12-07 23:11:40,080 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:40] "GET /static/js/core/api.js HTTP/1.1" 304 - -2025-12-07 23:11:41,826 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:41,920 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:41] "GET /api/workorders?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:41,990 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:41] "GET /api/alerts?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:42,026 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:42,275 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:42] "GET /api/workorders?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:42,292 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:42,465 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:42,531 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:42] "GET /api/workorders?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:42,589 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:42,639 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:42] "GET /api/alerts?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:42,814 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:11:43,220 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:43] "GET /api/alerts?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:11:45,122 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:11:45,122 - src.core.query_optimizer - ERROR - 优化分析查询失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:11:45,122 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:45] "GET /api/analytics?days=30 HTTP/1.1" 200 - -2025-12-07 23:11:52,053 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET / HTTP/1.1" 200 - -2025-12-07 23:11:52,253 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:11:52,383 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:11:52,703 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET /static/css/components.css HTTP/1.1" 200 - -2025-12-07 23:11:52,711 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET /static/css/variables.css HTTP/1.1" 200 - -2025-12-07 23:11:52,728 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:52] "GET /static/css/layout.css HTTP/1.1" 200 - -2025-12-07 23:11:53,270 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/core/utils.js HTTP/1.1" 200 - -2025-12-07 23:11:53,336 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/core/store.js HTTP/1.1" 200 - -2025-12-07 23:11:53,403 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:11:53,403 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/core/router.js HTTP/1.1" 200 - -2025-12-07 23:11:53,511 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/core/websocket.js HTTP/1.1" 200 - -2025-12-07 23:11:53,602 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/components/navbar.js HTTP/1.1" 200 - -2025-12-07 23:11:53,705 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/components/sidebar.js HTTP/1.1" 200 - -2025-12-07 23:11:53,720 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:53] "GET /static/js/components/modal.js HTTP/1.1" 200 - -2025-12-07 23:11:54,220 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/js/pages/login.js HTTP/1.1" 200 - -2025-12-07 23:11:54,237 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/images/favicon-32.png HTTP/1.1" 404 - -2025-12-07 23:11:54,237 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 23:11:54,295 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/manifest.json HTTP/1.1" 200 - -2025-12-07 23:11:54,363 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/images/favicon-16.png HTTP/1.1" 404 - -2025-12-07 23:11:54,406 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/sw.js HTTP/1.1" 200 - -2025-12-07 23:11:54,662 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/images/icon-144.png HTTP/1.1" 404 - -2025-12-07 23:11:54,730 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET / HTTP/1.1" 200 - -2025-12-07 23:11:54,906 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/css/main.css HTTP/1.1" 200 - -2025-12-07 23:11:54,906 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/js/main.js HTTP/1.1" 200 - -2025-12-07 23:11:54,927 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:54] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 23:11:55,144 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/core/api.js HTTP/1.1" 200 - -2025-12-07 23:11:55,312 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /api/analytics?days=30 HTTP/1.1" 200 - -2025-12-07 23:11:55,316 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 23:11:55,321 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 23:11:55,329 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 23:11:55,510 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/components/navbar.js HTTP/1.1" 304 - -2025-12-07 23:11:55,654 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 23:11:55,654 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 23:11:55,661 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/pages/dashboard.js HTTP/1.1" 200 - -2025-12-07 23:11:55,836 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/pages/alerts.js HTTP/1.1" 200 - -2025-12-07 23:11:55,986 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/pages/workorders.js HTTP/1.1" 200 - -2025-12-07 23:11:55,999 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:55] "GET /static/js/pages/knowledge.js HTTP/1.1" 200 - -2025-12-07 23:11:56,007 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:56] "GET /static/js/pages/chat.js HTTP/1.1" 200 - -2025-12-07 23:11:56,171 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:56] "GET /static/js/pages/monitoring.js HTTP/1.1" 200 - -2025-12-07 23:11:56,305 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:11:56] "GET /static/js/pages/settings.js HTTP/1.1" 200 - -2025-12-07 23:12:22,703 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:12:24,118 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:24] "GET /api/analytics?days=30 HTTP/1.1" 200 - -2025-12-07 23:12:30,237 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:30] "POST /api/login HTTP/1.1" 200 - -2025-12-07 23:12:30,669 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:30] "GET /static/js/pages/dashboard.js HTTP/1.1" 304 - -2025-12-07 23:12:30,921 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:30] "GET /static/js/core/api.js HTTP/1.1" 304 - -2025-12-07 23:12:32,142 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:32] "GET /api/workorders?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:12:32,142 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:32] "GET /api/alerts?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:12:40,971 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:12:42,471 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:12:42] "GET /api/analytics?days=30 HTTP/1.1" 200 - -2025-12-07 23:14:38,300 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:14:38] "GET / HTTP/1.1" 200 - -2025-12-07 23:14:55,194 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:14:55] "POST /api/login HTTP/1.1" 500 - -2025-12-07 23:15:52,129 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:15:52] "POST /api/login HTTP/1.1" 200 - -2025-12-07 23:16:17,378 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:16:17] "GET /login HTTP/1.1" 200 - -2025-12-07 23:16:33,047 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:16:33] "GET /static/js/main.js HTTP/1.1" 200 - -2025-12-07 23:18:46,886 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 23:18:46,886 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 23:18:53,982 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 23:18:57,082 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 23:18:57,104 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 23:18:57,265 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 23:18:57,265 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 23:18:57,681 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:18:58,078 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 23:18:58,094 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 23:18:58,094 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 23:19:09,129 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET / HTTP/1.1" 200 - -2025-12-07 23:19:09,486 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/css/main.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:19:09,495 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/main.js?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:19:09,545 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/css/variables.css HTTP/1.1" 200 - -2025-12-07 23:19:09,545 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/css/components.css HTTP/1.1" 200 - -2025-12-07 23:19:09,551 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/css/layout.css HTTP/1.1" 200 - -2025-12-07 23:19:09,595 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/core/utils.js HTTP/1.1" 304 - -2025-12-07 23:19:09,595 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-07 23:19:09,603 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/core/router.js HTTP/1.1" 304 - -2025-12-07 23:19:09,610 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/core/websocket.js HTTP/1.1" 304 - -2025-12-07 23:19:09,610 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/components/navbar.js HTTP/1.1" 200 - -2025-12-07 23:19:09,618 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/components/sidebar.js HTTP/1.1" 304 - -2025-12-07 23:19:09,618 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/components/modal.js HTTP/1.1" 304 - -2025-12-07 23:19:09,645 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /sw.js HTTP/1.1" 404 - -2025-12-07 23:19:09,653 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/pages/dashboard.js HTTP/1.1" 200 - -2025-12-07 23:19:09,700 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:09] "GET /static/js/core/api.js HTTP/1.1" 304 - -2025-12-07 23:19:12,128 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:19:12,628 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:12] "GET /api/alerts?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 200 - -2025-12-07 23:19:12,848 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:19:14,748 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:19:14,748 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:14] "GET /api/workorders?page=1&per_page=5&sort=created_at&order=desc HTTP/1.1" 500 - -2025-12-07 23:19:21,245 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:19:22,937 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:19:22] "GET /api/analytics?days=30 HTTP/1.1" 200 - -2025-12-07 23:33:48,313 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 23:33:48,313 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 23:33:54,795 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 23:33:58,382 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 23:33:58,421 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 23:33:58,592 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 23:33:58,600 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 23:33:59,099 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:33:59,496 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 23:33:59,513 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 23:33:59,513 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 23:34:00,645 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:01,063 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:01,463 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:01,863 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-07 23:34:01,872 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:02,262 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-07 23:34:03,962 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:03] "GET /api/alerts HTTP/1.1" 200 - -2025-12-07 23:34:04,855 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:04] "GET / HTTP/1.1" 200 - -2025-12-07 23:34:05,112 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:34:05,152 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 200 - -2025-12-07 23:34:05,171 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:34:05,180 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /static/css/design-system.css HTTP/1.1" 200 - -2025-12-07 23:34:05,446 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /api/system/info HTTP/1.1" 200 - -2025-12-07 23:34:05,564 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:05,572 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:05,572 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:05] "GET /api/feishu-sync/config HTTP/1.1" 200 - -2025-12-07 23:34:07,214 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:07,446 - src.web.service_manager - INFO - 服务 chat_manager 已初始化 -2025-12-07 23:34:07,446 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:07] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-07 23:34:07,596 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:34:07,867 - src.config.unified_config - WARNING - 无法加载默认LLM配置,使用内置默认值: No module named 'config.llm_config' -2025-12-07 23:34:07,867 - src.config.unified_config - INFO - 配置文件加载成功 -2025-12-07 23:34:07,879 - src.integrations.ai_suggestion_service - INFO - 使用LLM配置: openai - qwen-turbo -2025-12-07 23:34:07,945 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:07] "GET /api/workorders HTTP/1.1" 200 - -2025-12-07 23:34:07,951 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Number -> order_id -2025-12-07 23:34:07,967 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Description -> description -2025-12-07 23:34:07,967 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Type of problem -> category -2025-12-07 23:34:07,977 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Level -> priority -2025-12-07 23:34:07,989 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Status -> status -2025-12-07 23:34:07,990 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Source -> source -2025-12-07 23:34:07,998 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date creation -> created_at -2025-12-07 23:34:08,007 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 处理过程 -> resolution -2025-12-07 23:34:08,014 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR tracking -> resolution -2025-12-07 23:34:08,023 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Created by -> created_by -2025-12-07 23:34:08,030 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Module(模块) -> module -2025-12-07 23:34:08,036 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Wilfulness(责任人) -> wilfulness -2025-12-07 23:34:08,036 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date of close TR -> date_of_close -2025-12-07 23:34:08,046 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Vehicle Type01 -> vehicle_type -2025-12-07 23:34:08,046 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: VIN|sim -> vin_sim -2025-12-07 23:34:08,063 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: App remote control version -> app_remote_control_version -2025-12-07 23:34:08,063 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: HMI SW -> hmi_sw -2025-12-07 23:34:08,074 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 父记录 -> parent_record -2025-12-07 23:34:08,080 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Has it been updated on the same day -> has_updated_same_day -2025-12-07 23:34:08,080 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Operating time -> operating_time -2025-12-07 23:34:08,080 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:08] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-07 23:34:08,080 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: AI建议 -> ai_suggestion -2025-12-07 23:34:08,096 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Issue Start Time -> updated_at -2025-12-07 23:34:08,713 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:08] "GET /api/feishu-sync/status HTTP/1.1" 200 - -2025-12-07 23:34:10,080 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:10] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:34:10,612 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:10,620 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:12,128 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:12] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:34:12,128 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:12] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:34:12,128 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:12] "GET /static/css/design-system.css HTTP/1.1" 304 - -2025-12-07 23:34:12,595 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:12] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:34:15,638 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:15,645 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:20,646 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:20,646 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:22,831 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:22] "GET / HTTP/1.1" 200 - -2025-12-07 23:34:22,949 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:22] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:34:22,963 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:22] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 200 - -2025-12-07 23:34:22,969 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:22] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 200 - -2025-12-07 23:34:22,999 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:22] "GET /static/css/design-system.css HTTP/1.1" 200 - -2025-12-07 23:34:24,153 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:24] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-07 23:34:24,175 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:24] "GET /api/system/info HTTP/1.1" 200 - -2025-12-07 23:34:24,228 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:24,228 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:24] "GET /api/feishu-sync/config HTTP/1.1" 200 - -2025-12-07 23:34:24,236 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:25,113 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:25] "GET /api/workorders HTTP/1.1" 200 - -2025-12-07 23:34:25,653 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:25,661 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:26,129 - src.agent_assistant - INFO - TSP Agent助手初始化完成 -2025-12-07 23:34:26,129 - src.agent_assistant - INFO - TSP Agent助手初始化完成 -2025-12-07 23:34:26,129 - src.web.service_manager - INFO - 服务 agent_assistant 已初始化 -2025-12-07 23:34:26,129 - src.web.service_manager - INFO - 服务 agent_assistant 已初始化 -2025-12-07 23:34:26,129 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:26] "GET /api/agent/tools/stats HTTP/1.1" 200 - -2025-12-07 23:34:26,129 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:26] "GET /api/agent/status HTTP/1.1" 200 - -2025-12-07 23:34:26,362 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:26] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:34:26,383 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:26] "GET /api/feishu-sync/status HTTP/1.1" 200 - -2025-12-07 23:34:27,081 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:27] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-07 23:34:27,882 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1765121667 -2025-12-07 23:34:27,882 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:27] "POST /api/chat/session HTTP/1.1" 200 - -2025-12-07 23:34:29,334 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:29,334 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:30,512 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '我的车辆无法远程启动' 返回 0 个结果 -2025-12-07 23:34:30,711 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:30,715 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:30,851 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:30] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:34:34,352 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:34,367 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:35,212 - src.core.llm_client - INFO - API请求成功 -2025-12-07 23:34:35,431 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:35] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-07 23:34:35,747 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:35,768 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:35,768 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:35] "POST /api/chat/message HTTP/1.1" 200 - -2025-12-07 23:34:37,047 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:37] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:34:38,080 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:38] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-07 23:34:38,261 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:38] "GET /api/workorders HTTP/1.1" 200 - -2025-12-07 23:34:38,361 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:38] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-07 23:34:39,378 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:39,378 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:40,800 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:40,811 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:41,561 - src.integrations.feishu_client - INFO - 正在获取飞书tenant_access_token,应用ID: cli_a8b50ec0eed1500d -2025-12-07 23:34:42,146 - src.integrations.feishu_client - INFO - 飞书API响应: {'code': 0, 'expire': 2122, 'msg': 'ok', 'tenant_access_token': 't-g104c7maYKB23RBJZIFTIRYRRDKDLDVT6HED7RLS'} -2025-12-07 23:34:42,178 - src.integrations.feishu_client - INFO - tenant_access_token获取成功: t-g104c7maYKB23RBJZI... -2025-12-07 23:34:42,180 - src.integrations.feishu_client - INFO - 令牌有效期: 2122秒,过期时间: 2025-12-08 00:10:04 -2025-12-07 23:34:42,194 - src.integrations.feishu_client - INFO - 发送飞书API请求: GET https://open.feishu.cn/open-apis/bitable/v1/apps/XXnEbiCmEaMblSs6FDJcFCqsnIg/tables/tblnl3vJPpgMTSiP/records -2025-12-07 23:34:42,194 - src.integrations.feishu_client - INFO - 请求头: Authorization: Bearer t-g104c7maYKB23RBJZI... -2025-12-07 23:34:44,461 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:44,561 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:44,944 - src.integrations.feishu_client - INFO - 飞书API响应状态码: 200 -2025-12-07 23:34:44,961 - src.integrations.feishu_client - INFO - 飞书API响应内容: {'code': 0, 'data': {'has_more': False, 'items': [{'fields': {'AI建议': "模拟LLM响应: \n作为技术支持专家,请基于以下问题描述为工单提供专业的处理建议:\n\n问题描述:The widget weather doesn't work \n\n相关背景信息:\n无相关背景信息\n\n请提供:\n1. 问题...", 'Created by': 'Evgeniy', 'Date creation': 1745769600000, 'Module(模块)': 'local O&M', 'Source': 'Mail', 'TR Description': "The widget weather doesn't work ", 'TR Level': 'Low', 'TR Number': 'TR559', 'TR Status': 'Processing', 'TR tracking': '28/04:Local feedback weather widget does not work, query TBOX and IHU login record is normal, traffic binding is normal, we suggest users to use mobile phone hotspot to connect to the car, observe whether the widget is restored, if not, try to capture the IHU logs.', 'Type of problem': 'HU troubles', 'VIN|sim': 'LVTDD24B8RG019153 ', 'Vehicle Type01': 'EXEED RX(T22)', 'Wilfulness(责任人)': 'Evgeniy', '处理过程': '0428:属地反馈天气小部件不起作用,查询TBOX及IHU登录记录正常,流量绑定正常,建议用户使用手机热点连接车机,观察小部件是否恢复,如不恢复,尝试抓取IHU日志', '当前问题状态': '1027:天气小部件无法使用,已确认TBOX及IHU登录正常、流量绑定正常,建议已完成手机热点连接测试并尝试抓取IHU日志,若问题仍存在,建议进站进行系统诊断或软件版本升级排查。\n0428:属地反馈天气小部件不起作用,查询TBOX及IHU登录记录正常,流量绑定正常,建议用户使用手机热点连接车机,观察小部件是否恢复,如不恢复,尝试抓取IHU日志'}, 'id': 'rec253kqBfXae4', 'record_id': 'rec253kqBfXae4'}, {'fields': {'AI建议': '模拟LLM响应: \n作为技术支持专家,请基于以下问题描述为工单提供专业的处理建议:\n\n问题描述:Vehicle data is not updated in the app => dated from October,...', 'Created by': 'Vsevolod Tsoi', 'Date creation': 1761148800000, 'Module(模块)': 'TBOX', 'Source': 'Mail', 'TR Description': 'Vehicle data is not updated in the app => dated from October, 19 - thus, they are old one. No TBOX log in since October, 19. TBOX is in deep sleep since October, 19.\n', 'TR Level': 'Low', 'TR Number': 'TR863', 'TR Status': 'Processing', 'TR tracking': '24/10:The vehicle is in deep sleep, and T-box logs cannot be remotely obtained. The problem is a bit complex and difficult to locate, so the customer needs to visit the station to retrieve T-box logs and DMC logs. @Vsevolod Tsoi', 'Type of problem': 'Remote control ', 'VIN|sim': 'LNNBDDEZ8SD345645 ', 'Vehicle Type01': 'JAECOO J7(T1EJ)', 'Wilfulness(责任人)': '刘娇龙', '处理过程': '1024:车辆处于深度睡眠中,远程无法获取T-box日志,问题有点复杂不好定位,需要客户进站取T-box日志和DMC日志', '当前问题状态': '1027:车辆自10月19日进入深度睡眠,TBOX无远程连接,建议客户尽快进站提取TBOX及DMC日志,进行本地诊断分析,排查电源管理或通信模块异常原因,确认硬件状态及软件配置是否正常。\n1024:车辆处于深度睡眠中,远程无法获取T-box日志,问题有点复杂不好定位,需要客户进站取T-box日志和DMC日志'}, 'id': 'recv0NLSh2a2S7', 'record_id': 'recv0NLSh2a2S7'}, {'fields': {'AI建议': '模拟LLM响应: \n作为技术支持专家,请基于以下问题描述为工单提供专业的处理建议:\n\n问题描述:User not able to enter into member center neither mobile phon...', 'Created by': 'Vsevolod Tsoi', 'Date creation': 1761148800000, 'Module(模块)': '生态/ecologically', 'Source': 'Mail', 'TR Description': 'User not able to enter into member center neither mobile phone nor QR code.', 'TR Level': 'Low', 'TR Number': 'TR864', 'TR Status': 'Processing', 'TR tracking': '23/10: DMC logs attached as well as vieos of the issue.', 'Type of problem': 'Problem with auth in member center', 'VIN|sim': 'LNNBDDEZXSD449358', 'Vehicle Type01': 'EXEED VX FL(M36T)', 'Wilfulness(责任人)': '袁清', '处理过程': '1024: DMC logs attached as well as vieos of the issue.', '当前问题状态': '1027:确认手机网络及APP版本正常,尝试清除APP缓存并重新登录,检查QR码扫描权限是否开启,重启手机和车机,若仍无法进入会员中心,建议联系售后进行远程诊断或进站排查系统故障。\n1024: DMC logs attached as well as vieos of the issue.'}, 'id': 'recv0NLZoKLlRJ', 'record_id': 'recv0NLZoKLlRJ'}, {'fields': {'AI建议': '模拟LLM响应: \n作为技术支持专家,请基于以下问题描述为工单提供专业的处理建议:\n\n问题描述:Abnormal traffic consumption\n\n相关背景信息:\n相关知识库信息:\n- TR866 - Traf...', 'Created by': 'Vsevolod Tsoi', 'Date creation': 1761235200000, 'Module(模块)': 'DMC', 'Source': 'Mail', 'TR Description': 'Abnormal traffic consumption', 'TR Level': 'Low', 'TR Number': 'TR866', 'TR Status': 'Analysising', 'TR tracking': '24/10: It is recommended that users grab the DMC log back for analysis.@Vsevolod Tsoi \n24/10: user states he use Navi only and no other apps. Consumption volume - 3.12 Gb for 3 days. Same symptom as E0X - traffic package size is plus mines the same - see pdf from MNO attached', 'Type of problem': 'Traffic is over', 'VIN|sim': 'XEYDD14B3SA012164', 'Vehicle Type01': 'TEST', 'Wilfulness(责任人)': 'Vsevolod Tsoi', '处理过程': '1024:建议用户抓去DMC日志回传分析\n1024:用户表示他只使用Navi,不使用其他应用程序。 消耗量-3.12 Gb,3天。 与E0X相同的症状-流量包大小加上地雷相同-见所附MNO的pdf', '当前问题状态': '1027:流量异常可能与导航应用后台持续联网有关,建议关闭Navi自动更新地图功能并限制后台数据使用,检查车机系统是否存在异常进程,如问题依旧,建议进站检测DMC模块日志及SIM卡通信状态,必要时升级系统或更换模块。\n1024:建议用户抓去DMC日志回传分析\n1024:用户表示他只使用Navi,不使用其他应用程序。 消耗量-3.12 Gb,3天。 与E0X相同的症状-流量包大小加上地雷相同-见所附MNO的pdf'}, 'id': 'recv0NLZoKjKvx', 'record_id': 'recv0NLZoKjKvx'}], 'total': 4}, 'msg': 'success'} -2025-12-07 23:34:45,011 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:45] "GET /api/feishu-sync/preview-feishu-data HTTP/1.1" 200 - -2025-12-07 23:34:45,528 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:34:45,828 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:45,828 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:47,562 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:47] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-07 23:34:47,594 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:47] "GET /api/settings HTTP/1.1" 200 - -2025-12-07 23:34:50,861 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:50,861 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:56,067 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:34:56,082 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:34:58,382 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:34:58] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:35:01,329 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:35:01,860 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:35:05,595 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:05] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-07 23:35:06,735 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:35:06,752 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:35:08,419 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:08] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-07 23:35:08,913 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:08] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:35:10,035 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:35:10,294 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:10] "GET /api/workorders HTTP/1.1" 200 - -2025-12-07 23:35:11,728 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:11] "GET /api/analytics HTTP/1.1" 200 - -2025-12-07 23:35:11,961 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:35:11,961 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:35:12,011 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:12] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-07 23:35:18,906 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:18] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:35:38,744 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:35:40,993 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:35:42,127 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:42] "GET /api/analytics HTTP/1.1" 200 - -2025-12-07 23:35:43,726 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:43] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-07 23:35:43,765 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:35:43] "GET /api/settings HTTP/1.1" 200 - -2025-12-07 23:36:08,143 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:36:10,448 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:36:10] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-07 23:36:11,715 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:36:11,715 - src.web.error_handlers - ERROR - 未处理错误 get_health: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:36:28,892 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:36:31,477 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:36:31] "GET /api/analytics HTTP/1.1" 200 - -2025-12-07 23:36:39,110 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:36:39] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:36:45,076 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:36:45,076 - src.web.error_handlers - ERROR - 未处理错误 get_health: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:36:52,526 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:36:54,426 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:36:54] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - -2025-12-07 23:42:25,805 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 23:42:25,805 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 23:42:32,105 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 23:42:35,944 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 23:42:35,970 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 23:42:36,098 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 23:42:36,098 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 23:42:37,182 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:42:38,261 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 23:42:38,277 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 23:42:38,279 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 23:43:16,387 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:43:16] "GET / HTTP/1.1" 200 - -2025-12-07 23:43:18,453 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:43:18] "POST /api/workorders/generate-ai-suggestion HTTP/1.1" 404 - -2025-12-07 23:45:35,339 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-07 23:45:35,339 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-07 23:45:41,453 - src.core.database - INFO - 数据库初始化成功 -2025-12-07 23:45:44,883 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-07 23:45:44,926 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-07 23:45:45,133 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-07 23:45:45,133 - werkzeug - INFO - Press CTRL+C to quit -2025-12-07 23:45:45,650 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:45:45,962 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-07 23:45:45,977 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-07 23:45:45,977 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-07 23:47:49,611 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:47:49,915 - src.config.unified_config - WARNING - 无法加载默认LLM配置,使用内置默认值: No module named 'config.llm_config' -2025-12-07 23:47:49,915 - src.config.unified_config - INFO - 配置文件加载成功 -2025-12-07 23:47:49,915 - src.integrations.ai_suggestion_service - INFO - 使用LLM配置: qwen - qwen-plus-latest -2025-12-07 23:47:50,384 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:47:50,705 - src.dialogue.realtime_chat - INFO - 创建新会话: session_ai_suggestion_service_1765122470 -2025-12-07 23:47:51,394 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '请为以下问题提供精炼的技术支持操作建议: - -格式要求: -1. 现状+步骤,语言精炼 -2. 总长度控制在150字以内 - -要求: -1. 首次给客户建议,只提供远程可操作的一般性排查步骤 -2. 如检查网络、重启系统、确认配置等常见操作 -3. 绝对不要提到"进站"、"抓取日志"等需要线下操作的内容 -4. 语言简洁精炼,用逗号连接,不要用序号或分行 - -问题描述:车辆无法远程启动' 返回 3 个结果 -2025-12-07 23:47:54,063 - src.core.llm_client - INFO - API请求成功 -2025-12-07 23:47:54,869 - src.integrations.ai_suggestion_service - INFO - AI生成原始内容: 车辆无法远程启动,可能因网络异常导致,请先检查手机及车机网络信号是否正常,确认车辆不在无信号区域;重启车机系统后重试远程启动;检查奇瑞汽车APP登录状态及车辆绑定是否正常;确保远程启动功能已在APP中... -2025-12-07 23:47:54,885 - src.integrations.ai_suggestion_service - INFO - 未找到需要替换的内容: 车辆无法远程启动,可能因网络异常导致,请先检查手机及车机网络信号是否正常,确认车辆不在无信号区域;重启车机系统后重试远程启动;检查奇瑞汽车APP登录状态及车辆绑定是否正常;确保远程启动功能已在APP中 -2025-12-07 23:47:54,885 - src.integrations.ai_suggestion_service - INFO - 未找到需要替换的内容: 车辆无法远程启动,可能因网络异常导致,请先检查手机及车机网络信号是否正常,确认车辆不在无信号区域;重启车机系统后重试远程启动;检查奇瑞汽车APP登录状态及车辆绑定是否正常;确保远程启动功能已在APP中 -2025-12-07 23:47:54,885 - src.integrations.ai_suggestion_service - INFO - AI建议清理后: 车辆无法远程启动,可能因网络异常导致,请先检查手机及车机网络信号是否正常,确认车辆不在无信号区域;重启车机系统后重试远程启动;检查奇瑞汽车APP登录状态及车辆绑定是否正常;确保远程启动功能已在APP中... -2025-12-07 23:47:54,885 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:47:54] "POST /api/workorders/generate-ai-suggestion HTTP/1.1" 200 - -2025-12-07 23:49:32,059 - src.core.database - ERROR - 数据库操作失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:49:32,059 - src.knowledge_base.knowledge_manager - ERROR - 加载向量化器失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-07 23:49:32,059 - src.integrations.ai_suggestion_service - INFO - 使用LLM配置: qwen - qwen-plus-latest -2025-12-07 23:49:35,032 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:49:35,375 - src.dialogue.realtime_chat - INFO - 创建新会话: session_ai_suggestion_service_1765122575 -2025-12-07 23:49:35,743 - src.knowledge_base.knowledge_manager - INFO - 搜索查询 '请为以下问题提供精炼的技术支持操作建议: - -格式要求: -1. 现状+步骤,语言精炼 -2. 总长度控制在150字以内 - -要求: -1. 首次给客户建议,只提供远程可操作的一般性排查步骤 -2. 如检查网络、重启系统、确认配置等常见操作 -3. 绝对不要提到"进站"、"抓取日志"等需要线下操作的内容 -4. 语言简洁精炼,用逗号连接,不要用序号或分行 - -问题描述:车辆无法远程启动' 返回 3 个结果 -2025-12-07 23:49:38,096 - src.core.llm_client - INFO - API请求成功 -2025-12-07 23:49:39,226 - src.integrations.ai_suggestion_service - INFO - AI生成原始内容: 车辆远程启动失败,可能因网络异常导致:检查手机与车机网络信号是否正常,确认车辆未处于无信号区域;重启车机系统后重试远程启动;确保奇瑞汽车APP已登录且账号绑定车辆无误;检查APP内远程控制功能是否已开... -2025-12-07 23:49:39,226 - src.integrations.ai_suggestion_service - INFO - 未找到需要替换的内容: 车辆远程启动失败,可能因网络异常导致:检查手机与车机网络信号是否正常,确认车辆未处于无信号区域;重启车机系统后重试远程启动;确保奇瑞汽车APP已登录且账号绑定车辆无误;检查APP内远程控制功能是否已开 -2025-12-07 23:49:39,226 - src.integrations.ai_suggestion_service - INFO - 未找到需要替换的内容: 车辆远程启动失败,可能因网络异常导致:检查手机与车机网络信号是否正常,确认车辆未处于无信号区域;重启车机系统后重试远程启动;确保奇瑞汽车APP已登录且账号绑定车辆无误;检查APP内远程控制功能是否已开 -2025-12-07 23:49:39,226 - src.integrations.ai_suggestion_service - INFO - AI建议清理后: 车辆远程启动失败,可能因网络异常导致:检查手机与车机网络信号是否正常,确认车辆未处于无信号区域;重启车机系统后重试远程启动;确保奇瑞汽车APP已登录且账号绑定车辆无误;检查APP内远程控制功能是否已开... -2025-12-07 23:49:39,226 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:49:39] "POST /api/workorders/generate-ai-suggestion HTTP/1.1" 200 - -2025-12-07 23:50:09,330 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:09] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:50:09,861 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:09] "GET / HTTP/1.1" 200 - -2025-12-07 23:50:09,910 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:50:10,210 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:10] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:50:10,231 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:10] "GET /static/css/design-system.css HTTP/1.1" 304 - -2025-12-07 23:50:10,244 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:10] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-07 23:50:10,269 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:10] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - -2025-12-07 23:50:10,868 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:50:11,486 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-07 23:50:12,007 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:12] "GET /api/system/info HTTP/1.1" 200 - -2025-12-07 23:50:12,023 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:12,023 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:12] "GET /api/feishu-sync/config HTTP/1.1" 200 - -2025-12-07 23:50:12,023 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:13,803 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:50:13,827 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-07 23:50:14,094 - src.integrations.ai_suggestion_service - INFO - 使用LLM配置: qwen - qwen-plus-latest -2025-12-07 23:50:14,110 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Number -> order_id -2025-12-07 23:50:14,110 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Description -> description -2025-12-07 23:50:14,120 - src.web.service_manager - INFO - 服务 chat_manager 已初始化 -2025-12-07 23:50:14,120 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:14] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-07 23:50:14,128 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Type of problem -> category -2025-12-07 23:50:14,145 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Level -> priority -2025-12-07 23:50:14,153 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Status -> status -2025-12-07 23:50:14,157 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Source -> source -2025-12-07 23:50:14,168 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date creation -> created_at -2025-12-07 23:50:14,173 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 处理过程 -> resolution -2025-12-07 23:50:14,181 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR tracking -> resolution -2025-12-07 23:50:14,194 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Created by -> created_by -2025-12-07 23:50:14,202 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Module(模块) -> module -2025-12-07 23:50:14,210 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Wilfulness(责任人) -> wilfulness -2025-12-07 23:50:14,218 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date of close TR -> date_of_close -2025-12-07 23:50:14,227 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Vehicle Type01 -> vehicle_type -2025-12-07 23:50:14,244 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: VIN|sim -> vin_sim -2025-12-07 23:50:14,252 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: App remote control version -> app_remote_control_version -2025-12-07 23:50:14,261 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: HMI SW -> hmi_sw -2025-12-07 23:50:14,271 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 父记录 -> parent_record -2025-12-07 23:50:14,277 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:14] "GET /api/workorders HTTP/1.1" 200 - -2025-12-07 23:50:14,315 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Has it been updated on the same day -> has_updated_same_day -2025-12-07 23:50:14,352 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Operating time -> operating_time -2025-12-07 23:50:14,360 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: AI建议 -> ai_suggestion -2025-12-07 23:50:14,381 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Issue Start Time -> updated_at -2025-12-07 23:50:14,594 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:14] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:50:15,078 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:15] "GET /api/feishu-sync/status HTTP/1.1" 200 - -2025-12-07 23:50:15,221 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:15] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-07 23:50:17,119 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:17,135 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:18,410 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:18] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-07 23:50:22,146 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:22,146 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:22,579 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:22] "GET /api/token-monitor/stats HTTP/1.1" 200 - -2025-12-07 23:50:23,329 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:23] "GET /api/token-monitor/records HTTP/1.1" 200 - -2025-12-07 23:50:26,413 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:26] "GET /api/token-monitor/chart HTTP/1.1" 200 - -2025-12-07 23:50:27,165 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:27,165 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:27,680 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:27] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-07 23:50:29,631 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:29] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-07 23:50:32,181 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:32,181 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:33,160 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:33] "GET /api/workorders?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-07 23:50:34,860 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:34] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-07 23:50:37,374 - websockets.server - INFO - connection rejected (500 Internal Server Error) -2025-12-07 23:50:37,493 - websockets.server - ERROR - opening handshake failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler - await connection.handshake( - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 207, in handshake - raise self.protocol.handshake_exc - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 147, in handshake - response = process_request(self, self.request) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "D:\code\assist\src\web\websocket_server.py", line 265, in _process_request - if request_headers.get("Upgrade", "").lower() == "websocket": - ^^^^^^^^^^^^^^^^^^^ -AttributeError: 'Request' object has no attribute 'get' -2025-12-07 23:50:42,461 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:50:44,043 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:50:44] "GET /api/analytics HTTP/1.1" 200 - -2025-12-07 23:50:59,734 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:51:02,007 - src.core.query_optimizer - WARNING - 未映射的状态: 'Analysising' (数量: 1) -2025-12-07 23:51:02,819 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:51:02] "GET /api/analytics HTTP/1.1" 200 - -2025-12-07 23:51:03,587 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:51:03] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-07 23:51:03,614 - werkzeug - INFO - 127.0.0.1 - - [07/Dec/2025 23:51:03] "GET /api/settings HTTP/1.1" 200 - -2025-12-08 00:09:36,445 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-08 00:09:36,445 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-08 00:09:42,511 - src.core.database - ERROR - 数据库初始化失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:09:42,526 - __main__ - ERROR - 启动失败: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:22:37,225 - __main__ - INFO - 正在启动TSP智能助手综合管理平台... -2025-12-08 00:22:43,311 - src.core.database - INFO - 数据库初始化成功 -2025-12-08 00:22:44,341 - __main__ - INFO - 跳过系统检查,直接启动服务... -2025-12-08 00:22:47,876 - src.core.backup_manager - INFO - 备份数据库初始化成功: tsp_assistant.db -2025-12-08 00:22:47,891 - src.integrations.config_manager - INFO - 配置加载成功 -2025-12-08 00:22:48,149 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Running on all addresses (0.0.0.0) - * Running on http://127.0.0.1:5000 - * Running on http://192.168.31.202:5000 -2025-12-08 00:22:48,157 - werkzeug - INFO - Press CTRL+C to quit -2025-12-08 00:22:48,638 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:49,043 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765 -2025-12-08 00:22:49,059 - websockets.server - INFO - server listening on 127.0.0.1:8765 -2025-12-08 00:22:49,059 - websockets.server - INFO - server listening on [::1]:8765 -2025-12-08 00:22:53,549 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:53] "GET / HTTP/1.1" 200 - -2025-12-08 00:22:54,061 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:54,061 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/core/store.js HTTP/1.1" 200 - -2025-12-08 00:22:54,074 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/css/design-system.css HTTP/1.1" 304 - -2025-12-08 00:22:54,087 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - -2025-12-08 00:22:54,128 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/components/NotificationManager.js HTTP/1.1" 200 - -2025-12-08 00:22:54,147 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:54,183 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/components/AlertManager.js HTTP/1.1" 200 - -2025-12-08 00:22:54,183 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/services/api.js HTTP/1.1" 200 - -2025-12-08 00:22:54,191 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:54] "GET /static/js/app-new.js HTTP/1.1" 200 - -2025-12-08 00:22:55,015 - src.agent_assistant - INFO - TSP Agent助手初始化完成 -2025-12-08 00:22:55,024 - src.web.service_manager - INFO - 服务 agent_assistant 已初始化 -2025-12-08 00:22:55,025 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:55] "GET /api/agent/status HTTP/1.1" 200 - -2025-12-08 00:22:55,080 - websockets.server - INFO - connection open -2025-12-08 00:22:55,088 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:22:56,309 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:22:56,328 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET / HTTP/1.1" 200 - -2025-12-08 00:22:56,365 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:56,375 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-08 00:22:56,379 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:56,379 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/services/api.js HTTP/1.1" 304 - -2025-12-08 00:22:56,387 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - -2025-12-08 00:22:56,392 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - -2025-12-08 00:22:56,400 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/app-new.js HTTP/1.1" 304 - -2025-12-08 00:22:56,410 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - -2025-12-08 00:22:56,410 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:56] "GET /static/css/design-system.css HTTP/1.1" 304 - -2025-12-08 00:22:56,659 - websockets.server - INFO - connection open -2025-12-08 00:22:56,659 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:22:56,727 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:56,742 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:56,727 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:56,810 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:57,143 - src.web.service_manager - INFO - 服务 chat_manager 已初始化 -2025-12-08 00:22:57,143 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:57] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:22:57,346 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:57] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:22:57,561 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:57,609 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:57,762 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:57,892 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:22:57,944 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:57] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:22:57,959 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:22:58,158 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:22:58,158 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:58] "GET /api/rules HTTP/1.1" 200 - -2025-12-08 00:22:58,575 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:58,891 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:58,920 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:58,942 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:59,307 - src.web.service_manager - INFO - 服务 chat_manager 已初始化 -2025-12-08 00:22:59,308 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:22:59,308 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET / HTTP/1.1" 200 - -2025-12-08 00:22:59,324 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:59,361 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/css/design-system.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:59,365 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/core/store.js HTTP/1.1" 304 - -2025-12-08 00:22:59,367 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/services/api.js HTTP/1.1" 304 - -2025-12-08 00:22:59,373 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/css/style.css?v=1.0.0 HTTP/1.1" 304 - -2025-12-08 00:22:59,375 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/components/NotificationManager.js HTTP/1.1" 304 - -2025-12-08 00:22:59,383 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/app-new.js HTTP/1.1" 304 - -2025-12-08 00:22:59,383 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/components/AlertManager.js HTTP/1.1" 304 - -2025-12-08 00:22:59,383 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/js/dashboard.js?v=1.0.9 HTTP/1.1" 304 - -2025-12-08 00:22:59,399 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /static/css/design-system.css HTTP/1.1" 304 - -2025-12-08 00:22:59,498 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/rules HTTP/1.1" 200 - -2025-12-08 00:22:59,506 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/agent/status HTTP/1.1" 200 - -2025-12-08 00:22:59,608 - websockets.server - INFO - connection open -2025-12-08 00:22:59,608 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:22:59,619 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:22:59,683 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:22:59,715 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:22:59,774 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:22:59,841 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:22:59] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:22:59,977 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:23:00,007 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:23:00,075 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:23:00,361 - src.web.service_manager - INFO - 服务 assistant 已初始化 -2025-12-08 00:23:00,361 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/rules HTTP/1.1" 200 - -2025-12-08 00:23:00,491 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:23:00,674 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:23:00,693 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/system/info HTTP/1.1" 200 - -2025-12-08 00:23:00,707 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/feishu-sync/config HTTP/1.1" 200 - -2025-12-08 00:23:00,941 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:00] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:23:01,125 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 24 个条目 -2025-12-08 00:23:01,540 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:01] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:23:01,574 - src.config.unified_config - WARNING - 无法加载默认LLM配置,使用内置默认值: No module named 'config.llm_config' -2025-12-08 00:23:01,578 - src.config.unified_config - INFO - 配置文件加载成功 -2025-12-08 00:23:01,578 - src.integrations.ai_suggestion_service - INFO - 使用LLM配置: qwen - qwen-plus-latest -2025-12-08 00:23:01,595 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Number -> order_id -2025-12-08 00:23:01,606 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Description -> description -2025-12-08 00:23:01,623 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Type of problem -> category -2025-12-08 00:23:01,630 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Level -> priority -2025-12-08 00:23:01,645 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR Status -> status -2025-12-08 00:23:01,659 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Source -> source -2025-12-08 00:23:01,668 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date creation -> created_at -2025-12-08 00:23:01,682 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 处理过程 -> resolution -2025-12-08 00:23:01,688 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:01] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-08 00:23:01,688 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: TR tracking -> resolution -2025-12-08 00:23:01,707 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Created by -> created_by -2025-12-08 00:23:01,715 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Module(模块) -> module -2025-12-08 00:23:01,732 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Wilfulness(责任人) -> wilfulness -2025-12-08 00:23:01,740 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Date of close TR -> date_of_close -2025-12-08 00:23:01,748 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Vehicle Type01 -> vehicle_type -2025-12-08 00:23:01,764 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: VIN|sim -> vin_sim -2025-12-08 00:23:01,782 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: App remote control version -> app_remote_control_version -2025-12-08 00:23:01,797 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: HMI SW -> hmi_sw -2025-12-08 00:23:01,799 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: 父记录 -> parent_record -2025-12-08 00:23:01,813 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Has it been updated on the same day -> has_updated_same_day -2025-12-08 00:23:01,821 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Operating time -> operating_time -2025-12-08 00:23:01,829 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: AI建议 -> ai_suggestion -2025-12-08 00:23:01,847 - src.integrations.flexible_field_mapper - INFO - 添加字段映射: Issue Start Time -> updated_at -2025-12-08 00:23:02,174 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:02] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:23:02,829 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:02] "GET /api/feishu-sync/status HTTP/1.1" 200 - -2025-12-08 00:23:02,910 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:02] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:23:03,308 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:03] "GET /api/agent/status HTTP/1.1" 200 - -2025-12-08 00:23:03,331 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:03] "GET /api/agent/tools/stats HTTP/1.1" 200 - -2025-12-08 00:23:04,630 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:23:04,630 - src.web.error_handlers - ERROR - 错误响应: 获取预警列表失败: generator didn't stop after throw() - None -2025-12-08 00:23:04,630 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:04] "GET /api/alerts?per_page=1000 HTTP/1.1" 500 - -2025-12-08 00:23:04,657 - websockets.server - INFO - connection open -2025-12-08 00:23:04,665 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:04,760 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:04] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-08 00:23:07,043 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1765124587 -2025-12-08 00:23:07,043 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:07] "POST /api/chat/session HTTP/1.1" 200 - -2025-12-08 00:23:07,724 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:07] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:23:08,543 - src.dialogue.realtime_chat - INFO - 结束会话: session_user_001_1765124587 -2025-12-08 00:23:08,543 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:08] "DELETE /api/chat/session/session_user_001_1765124587 HTTP/1.1" 200 - -2025-12-08 00:23:09,691 - websockets.server - INFO - connection open -2025-12-08 00:23:09,710 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:10,377 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:10] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:23:11,925 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:11] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-08 00:23:14,745 - websockets.server - INFO - connection open -2025-12-08 00:23:14,761 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:18,257 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:18] "GET /api/workorders/78 HTTP/1.1" 200 - -2025-12-08 00:23:19,858 - websockets.server - INFO - connection open -2025-12-08 00:23:19,874 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:20,408 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:20] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:23:24,923 - websockets.server - INFO - connection open -2025-12-08 00:23:24,927 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:27,824 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:27] "GET /api/ai-monitor/stats HTTP/1.1" 200 - -2025-12-08 00:23:29,957 - websockets.server - INFO - connection open -2025-12-08 00:23:29,957 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:30,381 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:30] "GET /api/ai-monitor/error-distribution HTTP/1.1" 200 - -2025-12-08 00:23:32,230 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:32] "GET /api/ai-monitor/model-comparison HTTP/1.1" 200 - -2025-12-08 00:23:33,632 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:33] "GET /api/ai-monitor/error-log HTTP/1.1" 200 - -2025-12-08 00:23:35,006 - websockets.server - INFO - connection open -2025-12-08 00:23:35,006 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:38,127 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:38] "GET /api/token-monitor/stats HTTP/1.1" 200 - -2025-12-08 00:23:40,049 - websockets.server - INFO - connection open -2025-12-08 00:23:40,049 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:42,465 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:42] "GET /api/token-monitor/chart HTTP/1.1" 200 - -2025-12-08 00:23:44,680 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:44] "GET /api/token-monitor/records HTTP/1.1" 200 - -2025-12-08 00:23:45,081 - websockets.server - INFO - connection open -2025-12-08 00:23:45,090 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:45,861 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:45] "GET /api/conversations?page=1&per_page=10 HTTP/1.1" 200 - -2025-12-08 00:23:48,790 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:48] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:23:48,843 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:23:48] "GET /api/settings HTTP/1.1" 200 - -2025-12-08 00:23:50,107 - websockets.server - INFO - connection open -2025-12-08 00:23:50,107 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:23:55,140 - websockets.server - INFO - connection open -2025-12-08 00:23:55,140 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:24:00,256 - websockets.server - INFO - connection open -2025-12-08 00:24:00,271 - websockets.server - ERROR - connection handler failed -Traceback (most recent call last): - File "D:\Programs\Python\Python311\Lib\site-packages\websockets\asyncio\server.py", line 376, in conn_handler - await self.handler(connection) - ^^^^^^^^^^^^^^^^^^^^^^^^ -TypeError: WebSocketServer.start_server..handle_client_with_cors() missing 1 required positional argument: 'path' -2025-12-08 00:24:07,843 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:07] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:24:11,647 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:11] "GET /api/analytics HTTP/1.1" 200 - -2025-12-08 00:24:13,789 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:13] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:24:36,370 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:36] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-08 00:24:43,922 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:43] "GET /api/analytics HTTP/1.1" 200 - -2025-12-08 00:24:59,515 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:59] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-08 00:24:59,682 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:24:59] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:25:00,499 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:00] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:25:05,585 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:05,687 - src.analytics.alert_system - ERROR - 获取活跃预警失败: generator didn't stop -2025-12-08 00:25:11,319 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:11,420 - src.analytics.alert_system - ERROR - 获取活跃预警失败: generator didn't stop -2025-12-08 00:25:16,438 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:16] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:25:16,439 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:16] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:25:17,435 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:17] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:25:18,198 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:18] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:25:19,898 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:19,898 - src.analytics.alert_system - ERROR - 获取预警统计失败: generator didn't stop after throw() -2025-12-08 00:25:20,122 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:20] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-08 00:25:24,770 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:24,873 - src.analytics.alert_system - ERROR - 获取活跃预警失败: generator didn't stop -2025-12-08 00:25:32,839 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:32,923 - src.analytics.alert_system - ERROR - 获取活跃预警失败: generator didn't stop -2025-12-08 00:25:44,871 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:44] "GET /api/settings HTTP/1.1" 200 - -2025-12-08 00:25:51,120 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:25:51,120 - src.web.error_handlers - ERROR - 未处理错误 get_health: generator didn't stop after throw() -2025-12-08 00:25:51,206 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:25:51] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - -2025-12-08 00:26:09,914 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:26:09,937 - src.web.error_handlers - ERROR - 未处理错误 get_health: generator didn't stop -2025-12-08 00:26:13,585 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:26:13,585 - src.analytics.alert_system - ERROR - 获取预警统计失败: generator didn't stop after throw() -2025-12-08 00:26:15,404 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:26:15] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:26:18,653 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:26:18,670 - src.web.error_handlers - ERROR - 未处理错误 get_health: generator didn't stop after throw() -2025-12-08 00:26:20,462 - src.core.database - WARNING - 数据库连接丢失,重试 1/3: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') -(Background on this error at: https://sqlalche.me/e/20/e3q8) -2025-12-08 00:26:20,487 - src.analytics.alert_system - ERROR - 获取活跃预警失败: generator didn't stop after throw() -2025-12-08 00:26:34,821 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:26:34] "GET /api/analytics HTTP/1.1" 200 - -2025-12-08 00:26:56,976 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:26:56] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:26:59,704 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:26:59] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:27:07,498 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:07] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - -2025-12-08 00:27:22,552 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:22] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:27:30,169 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:30] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:27:31,733 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:31] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:27:53,602 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:53] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:27:55,401 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:27:55] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:28:17,477 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:17] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:28:20,151 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:20] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:28:34,062 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:34] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:28:34,681 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:34] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:28:48,267 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:48] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:28:56,519 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:28:56] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:29:02,536 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:02] "GET /api/chat/sessions HTTP/1.1" 200 - -2025-12-08 00:29:06,850 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:06] "GET /api/alerts?per_page=1000 HTTP/1.1" 200 - -2025-12-08 00:29:07,956 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:07] "GET /api/workorders HTTP/1.1" 200 - -2025-12-08 00:29:09,800 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:09] "GET /api/knowledge/stats HTTP/1.1" 200 - -2025-12-08 00:29:17,108 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:17] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:29:17,537 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:29:17] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:00,884 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:00] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:03,133 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:03] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:30:07,463 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:07] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:21,591 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:21] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:38,600 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:38] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:30:39,154 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:39] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:50,140 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:50] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:30:59,201 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:59] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - -2025-12-08 00:30:59,228 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:30:59] "GET /api/settings HTTP/1.1" 200 - -2025-12-08 00:31:22,933 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:31:22] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:31:24,516 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:31:24] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:31:32,283 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:31:32] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:31:42,001 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:31:42] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:31:50,641 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:31:50] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:32:11,064 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:32:11] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:32:27,720 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:32:27] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:32:30,013 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:32:30] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:32:54,831 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:32:54] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:33:07,031 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:07] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:33:07,910 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:07] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:33:13,658 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:13] "GET /api/analytics?days=7&dimension=performance HTTP/1.1" 200 - -2025-12-08 00:33:14,420 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:14] "GET /api/alerts HTTP/1.1" 200 - -2025-12-08 00:33:27,392 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:27] "GET /api/monitor/status HTTP/1.1" 200 - -2025-12-08 00:33:29,903 - werkzeug - INFO - 127.0.0.1 - - [08/Dec/2025 00:33:29] "GET /api/alerts HTTP/1.1" 200 - diff --git a/logs/tsp_assistant.log b/logs/tsp_assistant.log new file mode 100644 index 0000000..e69de29 diff --git a/quick_push.bat b/quick_push.bat deleted file mode 100644 index d0c8e39..0000000 --- a/quick_push.bat +++ /dev/null @@ -1,175 +0,0 @@ -@echo off -chcp 65001 >nul -setlocal enabledelayedexpansion -echo 🚀 TSP智能助手 - 快速推送 -echo. - -:: 检查Git状态 -git status --porcelain >nul 2>&1 -if %errorlevel% neq 0 ( - echo ❌ Git未初始化或不在Git仓库中 - pause - exit /b 1 -) - -:: 检查是否有参数 -if "%1"=="" ( - :: 智能生成提交信息 - echo 📝 分析markdown文件并生成提交信息... - - :: 检查是否有markdown文件修改 - set md_files= - for /f "tokens=*" %%f in ('git diff --name-only --cached 2^>nul ^| findstr /i "\.md$"') do ( - set md_files=!md_files! %%f - ) - for /f "tokens=*" %%f in ('git diff --name-only 2^>nul ^| findstr /i "\.md$"') do ( - set md_files=!md_files! %%f - ) - - set commit_msg= - if not "%md_files%"=="" ( - echo 📄 检测到markdown文件修改: %md_files% - - :: 提取markdown文件的主要内容 - set commit_title= - set commit_type=docs - - :: 检查是否有修复相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "修复\|解决\|问题\|错误"') do ( - set commit_type=fix - set commit_title=修复问题 - goto :found_fix - ) - ) - ) - - :: 检查是否有新功能相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "功能\|新增\|添加\|实现"') do ( - set commit_type=feat - set commit_title=新增功能 - goto :found_feature - ) - ) - ) - - :: 检查是否有优化相关内容 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /i "优化\|性能\|改进\|提升"') do ( - set commit_type=perf - set commit_title=性能优化 - goto :found_optimization - ) - ) - ) - - :: 提取文件标题 - for %%f in (%md_files%) do ( - if exist "%%f" ( - for /f "tokens=*" %%l in ('type "%%f" ^| findstr /n "^#" ^| head -1') do ( - set line=%%l - set line=!line:*:=! - set line=!line:# =! - set line=!line:## =! - if "!line!" neq "" ( - set commit_title=!line! - goto :found_title - ) - ) - ) - ) - - :found_fix - :found_feature - :found_optimization - :found_title - - if "%commit_title%"=="" ( - set commit_title=更新文档记录 - ) - - :: 生成提交信息 - set commit_msg=%commit_type%: %commit_title% - ) else ( - echo ℹ️ 没有检测到markdown文件修改 - set commit_msg=feat: 快速提交 - %date% %time% - ) -) else ( - set commit_msg=%1 -) - -echo 📝 提交信息: %commit_msg% -echo. - -:: 检查是否有更改需要提交(含未跟踪文件) -setlocal enabledelayedexpansion - -git diff --quiet -set has_unstaged=%errorlevel% - -git diff --cached --quiet -set has_staged=%errorlevel% - -set has_untracked=0 -for /f "delims=" %%f in ('git ls-files --others --exclude-standard') do set has_untracked=1 - -if %has_unstaged% equ 0 if %has_staged% equ 0 if %has_untracked% equ 0 ( - echo ℹ️ 没有检测到任何更改,无需提交 - echo. - echo ✅ 工作区干净,无需推送 - pause - exit /b 0 -) - -:: 执行推送 -echo. -echo 📤 开始推送流程... -echo 📝 提交信息: %commit_msg% - -git add . -if %errorlevel% neq 0 ( - echo ❌ 添加文件失败 - pause - exit /b 1 -) - -git commit -m "%commit_msg%" -if %errorlevel% neq 0 ( - echo ❌ 提交失败 - pause - exit /b 1 -) - -git fetch origin main -git push origin main -if %errorlevel% equ 0 ( - echo. - echo ✅ 推送完成! - echo 📊 最新提交: - git log --oneline -1 -) else ( - echo. - echo ❌ 推送失败,尝试自动解决... - echo 🔄 执行: git pull origin main --rebase - git pull origin main --rebase - if %errorlevel% equ 0 ( - echo ✅ 重试推送... - git push origin main - if %errorlevel% equ 0 ( - echo ✅ 推送成功! - echo 📊 最新提交: - git log --oneline -1 - ) else ( - echo ❌ 重试推送失败,请手动处理 - ) - ) else ( - echo ❌ 自动rebase失败,请手动处理冲突后重试 - ) -) - -echo. -pause diff --git a/scripts/__pycache__/git_auto_commit.cpython-313.pyc b/scripts/__pycache__/git_auto_commit.cpython-313.pyc deleted file mode 100644 index 30918ff..0000000 Binary files a/scripts/__pycache__/git_auto_commit.cpython-313.pyc and /dev/null differ diff --git a/scripts/deploy.sh b/scripts/deploy.sh deleted file mode 100644 index dada2e9..0000000 --- a/scripts/deploy.sh +++ /dev/null @@ -1,306 +0,0 @@ -#!/bin/bash -# TSP智能助手部署脚本 -# 支持多环境部署、版本管理、自动备份 - -set -e # 遇到错误立即退出 - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# 日志函数 -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# 检查依赖 -check_dependencies() { - log_info "检查系统依赖..." - - # 检查Python - if ! command -v python3 &> /dev/null; then - log_error "Python3 未安装" - exit 1 - fi - - # 检查pip - if ! command -v pip3 &> /dev/null; then - log_error "pip3 未安装" - exit 1 - fi - - # 检查Git - if ! command -v git &> /dev/null; then - log_error "Git 未安装" - exit 1 - fi - - log_info "依赖检查完成" -} - -# 创建虚拟环境 -setup_venv() { - local venv_path=$1 - log_info "创建虚拟环境: $venv_path" - - if [ ! -d "$venv_path" ]; then - python3 -m venv "$venv_path" - fi - - source "$venv_path/bin/activate" - pip install --upgrade pip - log_info "虚拟环境设置完成" -} - -# 安装依赖 -install_dependencies() { - log_info "安装Python依赖..." - pip install -r requirements.txt - log_info "依赖安装完成" -} - -# 数据库迁移 -run_migrations() { - log_info "运行数据库迁移..." - - # 检查数据库文件 - if [ ! -f "tsp_assistant.db" ]; then - log_info "初始化数据库..." - python init_database.py - fi - - log_info "数据库迁移完成" -} - -# 创建systemd服务文件 -create_systemd_service() { - local service_name=$1 - local app_path=$2 - local service_file="/etc/systemd/system/${service_name}.service" - - log_info "创建systemd服务文件: $service_file" - - sudo tee "$service_file" > /dev/null < /dev/null </dev/null || echo "unknown") - log_info "当前版本: $version" - else - log_warn "版本文件不存在" - fi -} - -# 创建部署包 -create_deployment_package() { - local package_name="tsp_assistant_$(date +%Y%m%d_%H%M%S).tar.gz" - log_info "创建部署包: $package_name" - - # 排除不需要的文件 - tar --exclude='.git' \ - --exclude='__pycache__' \ - --exclude='*.pyc' \ - --exclude='.env' \ - --exclude='logs/*' \ - --exclude='backups/*' \ - --exclude='dev_deploy' \ - -czf "$package_name" . - - log_info "部署包创建完成: $package_name" - echo "$package_name" -} - -# 主函数 -main() { - case ${1:-deploy} in - deploy) - check_version - deploy "$2" "$3" "$4" - ;; - rollback) - rollback "$2" - ;; - package) - create_deployment_package - ;; - *) - echo "用法: $0 {deploy|rollback|package} [environment] [domain] [port]" - echo "环境: development, staging, production" - echo "" - echo "命令说明:" - echo " deploy - 部署到指定环境" - echo " rollback - 回滚到指定备份" - echo " package - 创建部署包" - exit 1 - ;; - esac -} - -main "$@" diff --git a/scripts/docker_deploy.sh b/scripts/docker_deploy.sh deleted file mode 100644 index 207bbdc..0000000 --- a/scripts/docker_deploy.sh +++ /dev/null @@ -1,204 +0,0 @@ -#!/bin/bash -# TSP智能助手Docker部署脚本 - -set -e - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# 日志函数 -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# 检查Docker和Docker Compose -check_dependencies() { - log_info "检查依赖..." - - if ! command -v docker &> /dev/null; then - log_error "Docker未安装,请先安装Docker" - exit 1 - fi - - if ! command -v docker-compose &> /dev/null; then - log_error "Docker Compose未安装,请先安装Docker Compose" - exit 1 - fi - - log_success "依赖检查通过" -} - -# 创建必要的目录 -create_directories() { - log_info "创建必要的目录..." - - mkdir -p logs/nginx - mkdir -p monitoring/grafana/provisioning/datasources - mkdir -p monitoring/grafana/provisioning/dashboards - mkdir -p ssl - mkdir -p data - mkdir -p backups - mkdir -p uploads - mkdir -p config - - log_success "目录创建完成" -} - -# 构建镜像 -build_images() { - log_info "构建Docker镜像..." - - # 构建主应用镜像 - docker-compose build --no-cache tsp-assistant - - log_success "镜像构建完成" -} - -# 启动服务 -start_services() { - log_info "启动服务..." - - # 启动基础服务(MySQL, Redis) - docker-compose up -d mysql redis - - # 等待数据库启动 - log_info "等待数据库启动..." - sleep 30 - - # 启动主应用 - docker-compose up -d tsp-assistant - - # 启动其他服务 - docker-compose up -d nginx prometheus grafana - - log_success "服务启动完成" -} - -# 检查服务状态 -check_services() { - log_info "检查服务状态..." - - sleep 10 - - # 检查主应用 - if curl -f http://localhost:5000/api/health &> /dev/null; then - log_success "TSP助手服务正常" - else - log_warning "TSP助手服务可能未完全启动" - fi - - # 检查Nginx - if curl -f http://localhost/health &> /dev/null; then - log_success "Nginx服务正常" - else - log_warning "Nginx服务可能未完全启动" - fi - - # 检查Prometheus - if curl -f http://localhost:9090 &> /dev/null; then - log_success "Prometheus服务正常" - else - log_warning "Prometheus服务可能未完全启动" - fi - - # 检查Grafana - if curl -f http://localhost:3000 &> /dev/null; then - log_success "Grafana服务正常" - else - log_warning "Grafana服务可能未完全启动" - fi -} - -# 显示服务信息 -show_info() { - log_info "服务访问信息:" - echo " TSP助手: http://localhost:5000" - echo " Nginx代理: http://localhost" - echo " Prometheus: http://localhost:9090" - echo " Grafana: http://localhost:3000 (admin/admin123456)" - echo " MySQL: localhost:3306 (root/root123456)" - echo " Redis: localhost:6379 (密码: redis123456)" - echo "" - log_info "查看日志命令:" - echo " docker-compose logs -f tsp-assistant" - echo " docker-compose logs -f mysql" - echo " docker-compose logs -f redis" - echo " docker-compose logs -f nginx" -} - -# 停止服务 -stop_services() { - log_info "停止服务..." - docker-compose down - log_success "服务已停止" -} - -# 清理资源 -cleanup() { - log_info "清理Docker资源..." - docker system prune -f - log_success "清理完成" -} - -# 主函数 -main() { - case "${1:-start}" in - "start") - check_dependencies - create_directories - build_images - start_services - check_services - show_info - ;; - "stop") - stop_services - ;; - "restart") - stop_services - sleep 5 - start_services - check_services - show_info - ;; - "cleanup") - stop_services - cleanup - ;; - "logs") - docker-compose logs -f "${2:-tsp-assistant}" - ;; - "status") - docker-compose ps - ;; - *) - echo "用法: $0 {start|stop|restart|cleanup|logs|status}" - echo " start - 启动所有服务" - echo " stop - 停止所有服务" - echo " restart - 重启所有服务" - echo " cleanup - 清理Docker资源" - echo " logs - 查看日志 (可选指定服务名)" - echo " status - 查看服务状态" - exit 1 - ;; - esac -} - -# 执行主函数 -main "$@" diff --git a/scripts/monitor.sh b/scripts/monitor.sh deleted file mode 100644 index 7283435..0000000 --- a/scripts/monitor.sh +++ /dev/null @@ -1,277 +0,0 @@ -#!/bin/bash -# TSP智能助手监控脚本 - -# 配置变量 -APP_NAME="tsp_assistant" -SERVICE_NAME="tsp_assistant" -HEALTH_URL="http://localhost:5000/api/health" -LOG_FILE="./logs/monitor.log" -ALERT_EMAIL="admin@example.com" -ALERT_PHONE="13800138000" - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' - -# 日志函数 -log_info() { - echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] INFO${NC} $1" | tee -a "$LOG_FILE" -} - -log_warn() { - echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARN${NC} $1" | tee -a "$LOG_FILE" -} - -log_error() { - echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR${NC} $1" | tee -a "$LOG_FILE" -} - -# 发送告警 -send_alert() { - local message=$1 - local level=$2 - - log_error "告警: $message" - - # 发送邮件告警 - if command -v mail &> /dev/null; then - echo "$message" | mail -s "[$level] TSP助手告警" "$ALERT_EMAIL" - fi - - # 发送短信告警(需要配置短信服务) - # curl -X POST "https://api.sms.com/send" \ - # -d "phone=$ALERT_PHONE" \ - # -d "message=$message" -} - -# 检查服务状态 -check_service_status() { - if systemctl is-active --quiet "$SERVICE_NAME"; then - return 0 - else - return 1 - fi -} - -# 检查健康状态 -check_health() { - local response_code - response_code=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_URL" 2>/dev/null) - - if [ "$response_code" = "200" ]; then - return 0 - else - return 1 - fi -} - -# 检查响应时间 -check_response_time() { - local response_time - response_time=$(curl -s -o /dev/null -w "%{time_total}" "$HEALTH_URL" 2>/dev/null) - - # 响应时间超过5秒认为异常 - if (( $(echo "$response_time > 5.0" | bc -l) )); then - return 1 - else - return 0 - fi -} - -# 检查系统资源 -check_system_resources() { - local cpu_usage - local memory_usage - local disk_usage - - # CPU使用率 - cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | awk -F'%' '{print $1}') - - # 内存使用率 - memory_usage=$(free | grep Mem | awk '{printf "%.2f", $3/$2 * 100.0}') - - # 磁盘使用率 - disk_usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//') - - # 检查阈值 - if (( $(echo "$cpu_usage > 80" | bc -l) )); then - send_alert "CPU使用率过高: ${cpu_usage}%" "HIGH" - fi - - if (( $(echo "$memory_usage > 80" | bc -l) )); then - send_alert "内存使用率过高: ${memory_usage}%" "HIGH" - fi - - if [ "$disk_usage" -gt 80 ]; then - send_alert "磁盘使用率过高: ${disk_usage}%" "HIGH" - fi - - log_info "系统资源 - CPU: ${cpu_usage}%, 内存: ${memory_usage}%, 磁盘: ${disk_usage}%" -} - -# 检查日志错误 -check_log_errors() { - local log_file="./logs/tsp_assistant.log" - local error_count - - if [ -f "$log_file" ]; then - # 检查最近5分钟的错误日志 - error_count=$(tail -n 100 "$log_file" | grep -c "ERROR" 2>/dev/null || echo "0") - - if [ "$error_count" -gt 10 ]; then - send_alert "最近5分钟错误日志过多: $error_count 条" "MEDIUM" - fi - fi -} - -# 检查数据库连接 -check_database() { - local db_file="./tsp_assistant.db" - - if [ -f "$db_file" ]; then - # 检查数据库文件大小 - local db_size - db_size=$(du -h "$db_file" | cut -f1) - log_info "数据库大小: $db_size" - - # 检查数据库是否可读 - if ! sqlite3 "$db_file" "SELECT 1;" > /dev/null 2>&1; then - send_alert "数据库连接失败" "CRITICAL" - return 1 - fi - fi - - return 0 -} - -# 自动重启服务 -restart_service() { - log_warn "尝试重启服务..." - - sudo systemctl restart "$SERVICE_NAME" - sleep 10 - - if check_service_status && check_health; then - log_info "服务重启成功" - return 0 - else - log_error "服务重启失败" - return 1 - fi -} - -# 主监控循环 -monitor_loop() { - local consecutive_failures=0 - local max_failures=3 - - while true; do - log_info "开始监控检查..." - - # 检查服务状态 - if ! check_service_status; then - log_error "服务未运行" - send_alert "TSP助手服务未运行" "CRITICAL" - consecutive_failures=$((consecutive_failures + 1)) - else - # 检查健康状态 - if ! check_health; then - log_error "健康检查失败" - send_alert "TSP助手健康检查失败" "HIGH" - consecutive_failures=$((consecutive_failures + 1)) - else - # 检查响应时间 - if ! check_response_time; then - log_warn "响应时间过长" - send_alert "TSP助手响应时间过长" "MEDIUM" - fi - - consecutive_failures=0 - fi - fi - - # 检查系统资源 - check_system_resources - - # 检查日志错误 - check_log_errors - - # 检查数据库 - check_database - - # 连续失败处理 - if [ "$consecutive_failures" -ge "$max_failures" ]; then - log_error "连续失败次数达到阈值,尝试重启服务" - if restart_service; then - consecutive_failures=0 - else - send_alert "TSP助手服务重启失败,需要人工干预" "CRITICAL" - fi - fi - - # 等待下次检查 - sleep 60 - done -} - -# 一次性检查 -single_check() { - log_info "执行一次性健康检查..." - - if check_service_status; then - log_info "✓ 服务运行正常" - else - log_error "✗ 服务未运行" - exit 1 - fi - - if check_health; then - log_info "✓ 健康检查通过" - else - log_error "✗ 健康检查失败" - exit 1 - fi - - if check_response_time; then - log_info "✓ 响应时间正常" - else - log_warn "⚠ 响应时间过长" - fi - - check_system_resources - check_log_errors - check_database - - log_info "健康检查完成" -} - -# 主函数 -main() { - # 创建日志目录 - mkdir -p logs - - case ${1:-monitor} in - monitor) - log_info "启动TSP助手监控服务..." - monitor_loop - ;; - check) - single_check - ;; - restart) - restart_service - ;; - *) - echo "用法: $0 {monitor|check|restart}" - echo " monitor - 持续监控模式" - echo " check - 一次性健康检查" - echo " restart - 重启服务" - exit 1 - ;; - esac -} - -# 执行主函数 -main "$@" diff --git a/scripts/quick_update.bat b/scripts/quick_update.bat deleted file mode 100644 index b40b3ef..0000000 --- a/scripts/quick_update.bat +++ /dev/null @@ -1,285 +0,0 @@ -@echo off -REM TSP智能助手快速更新脚本 (Windows) -REM 支持热更新和完整更新 - -setlocal enabledelayedexpansion - -REM 颜色定义 -set "GREEN=[32m" -set "YELLOW=[33m" -set "RED=[31m" -set "NC=[0m" - -REM 配置变量 -set "APP_NAME=tsp_assistant" -set "DEPLOY_PATH=." -set "BACKUP_PATH=.\backups" -set "HEALTH_URL=http://localhost:5000/api/health" - -REM 解析参数 -set "ACTION=%1" -set "SOURCE_PATH=%2" -set "ENVIRONMENT=%3" - -if "%ACTION%"=="" ( - echo 用法: %0 {check^|hot-update^|full-update^|auto-update^|rollback} [源路径] [环境] - echo. - echo 命令说明: - echo check - 检查更新可用性 - echo hot-update - 热更新(不重启服务) - echo full-update - 完整更新(重启服务) - echo auto-update - 自动更新(智能选择) - echo rollback - 回滚到指定备份 - echo. - echo 环境: development, staging, production - exit /b 1 -) - -if "%ENVIRONMENT%"=="" set "ENVIRONMENT=production" -if "%SOURCE_PATH%"=="" set "SOURCE_PATH=." - -REM 日志函数 -:log_info -echo %GREEN%[INFO]%NC% %~1 -goto :eof - -:log_warn -echo %YELLOW%[WARN]%NC% %~1 -goto :eof - -:log_error -echo %RED%[ERROR]%NC% %~1 -goto :eof - -REM 检查更新可用性 -:check_update -call :log_info "检查更新可用性..." -if not exist "%SOURCE_PATH%\version.json" ( - call :log_error "源路径中未找到版本文件" - exit /b 1 -) - -REM 比较版本 -for /f "tokens=2 delims=:" %%a in ('findstr "version" "%SOURCE_PATH%\version.json"') do ( - set "NEW_VERSION=%%a" - set "NEW_VERSION=!NEW_VERSION: =!" - set "NEW_VERSION=!NEW_VERSION:"=!" - set "NEW_VERSION=!NEW_VERSION:,=!" -) - -if exist "version.json" ( - for /f "tokens=2 delims=:" %%a in ('findstr "version" "version.json"') do ( - set "CURRENT_VERSION=%%a" - set "CURRENT_VERSION=!CURRENT_VERSION: =!" - set "CURRENT_VERSION=!CURRENT_VERSION:"=!" - set "CURRENT_VERSION=!CURRENT_VERSION:,=!" - ) -) else ( - set "CURRENT_VERSION=unknown" -) - -if "!NEW_VERSION!"=="!CURRENT_VERSION!" ( - call :log_info "没有更新可用 (当前版本: !CURRENT_VERSION!)" -) else ( - call :log_info "发现更新: !CURRENT_VERSION! -> !NEW_VERSION!" -) -goto :eof - -REM 创建备份 -:create_backup -set "TIMESTAMP=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%" -set "TIMESTAMP=!TIMESTAMP: =0!" -set "BACKUP_NAME=%APP_NAME%_backup_!TIMESTAMP!" - -call :log_info "创建备份: !BACKUP_NAME!" - -if not exist "%BACKUP_PATH%" mkdir "%BACKUP_PATH%" -mkdir "%BACKUP_PATH%\!BACKUP_NAME!" - -REM 备份应用文件 -if exist "%DEPLOY_PATH%" ( - call :log_info "备份应用文件..." - xcopy "%DEPLOY_PATH%\*" "%BACKUP_PATH%\!BACKUP_NAME!\" /E /I /Y -) - -REM 备份数据库 -if exist "%DEPLOY_PATH%\tsp_assistant.db" ( - call :log_info "备份数据库..." - mkdir "%BACKUP_PATH%\!BACKUP_NAME!\database" - copy "%DEPLOY_PATH%\tsp_assistant.db" "%BACKUP_PATH%\!BACKUP_NAME!\database\" -) - -call :log_info "备份完成: !BACKUP_NAME!" -echo !BACKUP_NAME! -goto :eof - -REM 热更新 -:hot_update -call :log_info "开始热更新..." - -REM 支持热更新的文件列表 -set "HOT_UPDATE_FILES=src\web\static\js\dashboard.js src\web\static\css\style.css src\web\templates\dashboard.html src\web\app.py" - -set "UPDATED_COUNT=0" -for %%f in (%HOT_UPDATE_FILES%) do ( - if exist "%SOURCE_PATH%\%%f" ( - call :log_info "更新文件: %%f" - if not exist "%DEPLOY_PATH%\%%f" mkdir "%DEPLOY_PATH%\%%f" 2>nul - copy "%SOURCE_PATH%\%%f" "%DEPLOY_PATH%\%%f" /Y >nul - set /a UPDATED_COUNT+=1 - ) -) - -if !UPDATED_COUNT! gtr 0 ( - call :log_info "热更新完成,更新了 !UPDATED_COUNT! 个文件" -) else ( - call :log_info "没有文件需要热更新" -) -goto :eof - -REM 完整更新 -:full_update -call :log_info "开始完整更新..." - -REM 创建备份 -call :create_backup -set "BACKUP_NAME=!BACKUP_NAME!" - -REM 停止服务(如果运行中) -call :log_info "停止服务..." -taskkill /f /im python.exe 2>nul || echo 服务未运行 - -REM 更新文件 -call :log_info "更新应用文件..." -if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%" -mkdir "%DEPLOY_PATH%" -xcopy "%SOURCE_PATH%\*" "%DEPLOY_PATH%\" /E /I /Y - -REM 安装依赖 -call :log_info "安装依赖..." -cd "%DEPLOY_PATH%" -if exist "requirements.txt" ( - pip install -r requirements.txt -) - -REM 运行数据库迁移 -call :log_info "运行数据库迁移..." -if exist "init_database.py" ( - python init_database.py -) - -REM 启动服务 -call :log_info "启动服务..." -start /b python start_dashboard.py - -REM 等待服务启动 -call :log_info "等待服务启动..." -timeout /t 15 /nobreak >nul - -REM 健康检查 -call :log_info "执行健康检查..." -set "RETRY_COUNT=0" -set "MAX_RETRIES=10" - -:health_check_loop -if !RETRY_COUNT! geq !MAX_RETRIES! ( - call :log_error "健康检查失败,开始回滚..." - call :rollback !BACKUP_NAME! - exit /b 1 -) - -curl -f "%HEALTH_URL%" >nul 2>&1 -if !errorlevel! equ 0 ( - call :log_info "健康检查通过!" - call :log_info "更新成功!" - call :log_info "备份名称: !BACKUP_NAME!" - exit /b 0 -) else ( - call :log_warn "健康检查失败,重试中... (!RETRY_COUNT!/!MAX_RETRIES!)" - set /a RETRY_COUNT+=1 - timeout /t 5 /nobreak >nul - goto :health_check_loop -) - -REM 回滚 -:rollback -set "BACKUP_NAME=%1" -if "%BACKUP_NAME%"=="" ( - call :log_error "请指定备份名称" - exit /b 1 -) - -call :log_info "开始回滚到备份: !BACKUP_NAME!" - -if not exist "%BACKUP_PATH%\!BACKUP_NAME!" ( - call :log_error "备份不存在: !BACKUP_NAME!" - exit /b 1 -) - -REM 停止服务 -call :log_info "停止服务..." -taskkill /f /im python.exe 2>nul || echo 服务未运行 - -REM 恢复文件 -call :log_info "恢复文件..." -if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%" -mkdir "%DEPLOY_PATH%" -xcopy "%BACKUP_PATH%\!BACKUP_NAME!\*" "%DEPLOY_PATH%\" /E /I /Y - -REM 恢复数据库 -if exist "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" ( - call :log_info "恢复数据库..." - copy "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" "%DEPLOY_PATH%\" -) - -REM 启动服务 -call :log_info "启动服务..." -cd "%DEPLOY_PATH%" -start /b python start_dashboard.py - -REM 等待服务启动 -timeout /t 15 /nobreak >nul - -REM 健康检查 -curl -f "%HEALTH_URL%" >nul 2>&1 -if !errorlevel! equ 0 ( - call :log_info "回滚成功!" -) else ( - call :log_error "回滚后健康检查失败" - exit /b 1 -) -goto :eof - -REM 自动更新 -:auto_update -call :log_info "开始自动更新..." - -REM 尝试热更新 -call :hot_update -if !errorlevel! equ 0 ( - call :log_info "热更新成功" - exit /b 0 -) - -REM 热更新失败,进行完整更新 -call :log_info "热更新失败,进行完整更新..." -call :full_update -goto :eof - -REM 主逻辑 -if "%ACTION%"=="check" ( - call :check_update -) else if "%ACTION%"=="hot-update" ( - call :hot_update -) else if "%ACTION%"=="full-update" ( - call :full_update -) else if "%ACTION%"=="auto-update" ( - call :auto_update -) else if "%ACTION%"=="rollback" ( - call :rollback "%SOURCE_PATH%" -) else ( - call :log_error "未知操作: %ACTION%" - exit /b 1 -) - -endlocal diff --git a/scripts/update_manager.py b/scripts/update_manager.py deleted file mode 100644 index 59db9ca..0000000 --- a/scripts/update_manager.py +++ /dev/null @@ -1,477 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -TSP智能助手更新管理器 -支持热更新、版本管理、回滚等功能 -""" - -import os -import sys -import json -import shutil -import subprocess -import time -import requests -from datetime import datetime -from pathlib import Path -from typing import Dict, List, Optional, Tuple - -class UpdateManager: - """更新管理器""" - - def __init__(self, config_file: str = "update_config.json"): - self.config_file = config_file - self.config = self._load_config() - self.version_manager = None - - # 初始化版本管理器 - try: - from version import VersionManager - self.version_manager = VersionManager() - except ImportError: - print("警告: 版本管理器不可用") - - def _load_config(self) -> Dict: - """加载更新配置""" - default_config = { - "app_name": "tsp_assistant", - "deploy_path": "/opt/tsp_assistant", - "backup_path": "./backups", - "service_name": "tsp_assistant", - "health_url": "http://localhost:5000/api/health", - "update_timeout": 300, - "rollback_enabled": True, - "auto_backup": True, - "hot_update_enabled": True, - "environments": { - "development": { - "path": "./dev_deploy", - "service_name": "", - "auto_restart": False - }, - "staging": { - "path": "/opt/tsp_assistant_staging", - "service_name": "tsp_assistant_staging", - "auto_restart": True - }, - "production": { - "path": "/opt/tsp_assistant", - "service_name": "tsp_assistant", - "auto_restart": True - } - } - } - - if os.path.exists(self.config_file): - try: - with open(self.config_file, 'r', encoding='utf-8') as f: - config = json.load(f) - # 合并默认配置 - default_config.update(config) - except Exception as e: - print(f"加载配置文件失败: {e}") - - return default_config - - def _save_config(self): - """保存配置""" - try: - with open(self.config_file, 'w', encoding='utf-8') as f: - json.dump(self.config, f, indent=2, ensure_ascii=False) - except Exception as e: - print(f"保存配置文件失败: {e}") - - def check_update_available(self, source_path: str) -> Tuple[bool, str, str]: - """检查是否有更新可用""" - if not self.version_manager: - return False, "unknown", "unknown" - - current_version = self.version_manager.get_version() - - # 检查源路径的版本 - try: - source_version_file = os.path.join(source_path, "version.json") - if os.path.exists(source_version_file): - with open(source_version_file, 'r', encoding='utf-8') as f: - source_info = json.load(f) - source_version = source_info.get("version", "unknown") - else: - return False, current_version, "unknown" - except Exception as e: - print(f"检查源版本失败: {e}") - return False, current_version, "unknown" - - # 比较版本 - if source_version != current_version: - return True, current_version, source_version - - return False, current_version, source_version - - def create_backup(self, environment: str = "production") -> str: - """创建备份""" - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - backup_name = f"{self.config['app_name']}_backup_{timestamp}" - backup_path = os.path.join(self.config["backup_path"], backup_name) - - print(f"创建备份: {backup_name}") - - # 创建备份目录 - os.makedirs(backup_path, exist_ok=True) - - # 获取部署路径 - env_config = self.config["environments"].get(environment, {}) - deploy_path = env_config.get("path", self.config["deploy_path"]) - - # 备份应用文件 - if os.path.exists(deploy_path): - print("备份应用文件...") - shutil.copytree(deploy_path, os.path.join(backup_path, "app")) - - # 备份数据库 - db_file = os.path.join(deploy_path, "tsp_assistant.db") - if os.path.exists(db_file): - print("备份数据库...") - os.makedirs(os.path.join(backup_path, "database"), exist_ok=True) - shutil.copy2(db_file, os.path.join(backup_path, "database", "tsp_assistant.db")) - - # 保存备份信息 - backup_info = { - "backup_name": backup_name, - "backup_path": backup_path, - "timestamp": timestamp, - "environment": environment, - "version": self.version_manager.get_version() if self.version_manager else "unknown", - "git_commit": self._get_git_commit(deploy_path) - } - - with open(os.path.join(backup_path, "backup_info.json"), 'w', encoding='utf-8') as f: - json.dump(backup_info, f, indent=2, ensure_ascii=False) - - print(f"备份完成: {backup_name}") - return backup_name - - def _get_git_commit(self, path: str) -> str: - """获取Git提交哈希""" - try: - result = subprocess.run(['git', 'rev-parse', 'HEAD'], - cwd=path, capture_output=True, text=True) - return result.stdout.strip()[:8] if result.returncode == 0 else "unknown" - except: - return "unknown" - - def hot_update(self, source_path: str, environment: str = "production") -> bool: - """热更新(不重启服务)""" - if not self.config["hot_update_enabled"]: - print("热更新未启用") - return False - - print("开始热更新...") - - env_config = self.config["environments"].get(environment, {}) - deploy_path = env_config.get("path", self.config["deploy_path"]) - - # 检查哪些文件可以热更新 - hot_update_files = [ - "src/web/static/js/dashboard.js", - "src/web/static/css/style.css", - "src/web/templates/dashboard.html", - "src/web/app.py", - "src/knowledge_base/knowledge_manager.py", - "src/dialogue/realtime_chat.py" - ] - - updated_files = [] - for file_path in hot_update_files: - source_file = os.path.join(source_path, file_path) - target_file = os.path.join(deploy_path, file_path) - - if os.path.exists(source_file): - # 检查文件是否有变化 - if not os.path.exists(target_file) or not self._files_equal(source_file, target_file): - print(f"更新文件: {file_path}") - os.makedirs(os.path.dirname(target_file), exist_ok=True) - shutil.copy2(source_file, target_file) - updated_files.append(file_path) - - if updated_files: - print(f"热更新完成,更新了 {len(updated_files)} 个文件") - return True - else: - print("没有文件需要热更新") - return False - - def _files_equal(self, file1: str, file2: str) -> bool: - """比较两个文件是否相等""" - try: - with open(file1, 'rb') as f1, open(file2, 'rb') as f2: - return f1.read() == f2.read() - except: - return False - - def full_update(self, source_path: str, environment: str = "production", - create_backup: bool = True) -> bool: - """完整更新(重启服务)""" - print("开始完整更新...") - - env_config = self.config["environments"].get(environment, {}) - deploy_path = env_config.get("path", self.config["deploy_path"]) - service_name = env_config.get("service_name", self.config["service_name"]) - auto_restart = env_config.get("auto_restart", True) - - # 创建备份 - backup_name = None - if create_backup and self.config["auto_backup"]: - backup_name = self.create_backup(environment) - - try: - # 停止服务 - if auto_restart and service_name: - print(f"停止服务: {service_name}") - subprocess.run(['sudo', 'systemctl', 'stop', service_name], check=True) - - # 更新文件 - print("更新应用文件...") - if os.path.exists(deploy_path): - shutil.rmtree(deploy_path) - os.makedirs(deploy_path, exist_ok=True) - shutil.copytree(source_path, deploy_path, dirs_exist_ok=True) - - # 设置权限 - subprocess.run(['sudo', 'chown', '-R', 'www-data:www-data', deploy_path], check=True) - - # 安装依赖 - print("安装依赖...") - requirements_file = os.path.join(deploy_path, "requirements.txt") - if os.path.exists(requirements_file): - subprocess.run(['sudo', '-u', 'www-data', 'python', '-m', 'pip', 'install', '-r', requirements_file], - cwd=deploy_path, check=True) - - # 运行数据库迁移 - print("运行数据库迁移...") - init_script = os.path.join(deploy_path, "init_database.py") - if os.path.exists(init_script): - subprocess.run(['sudo', '-u', 'www-data', 'python', init_script], - cwd=deploy_path, check=True) - - # 启动服务 - if auto_restart and service_name: - print(f"启动服务: {service_name}") - subprocess.run(['sudo', 'systemctl', 'start', service_name], check=True) - - # 等待服务启动 - print("等待服务启动...") - time.sleep(15) - - # 健康检查 - if self._health_check(): - print("更新成功!") - return True - else: - print("健康检查失败,开始回滚...") - if backup_name: - self.rollback(backup_name, environment) - return False - else: - print("更新完成(未重启服务)") - return True - - except Exception as e: - print(f"更新失败: {e}") - if backup_name: - print("开始回滚...") - self.rollback(backup_name, environment) - return False - - def _health_check(self) -> bool: - """健康检查""" - health_url = self.config["health_url"] - max_retries = 10 - retry_count = 0 - - while retry_count < max_retries: - try: - response = requests.get(health_url, timeout=5) - if response.status_code == 200: - return True - except: - pass - - retry_count += 1 - print(f"健康检查失败,重试中... ({retry_count}/{max_retries})") - time.sleep(5) - - return False - - def rollback(self, backup_name: str, environment: str = "production") -> bool: - """回滚到指定备份""" - print(f"开始回滚到备份: {backup_name}") - - env_config = self.config["environments"].get(environment, {}) - deploy_path = env_config.get("path", self.config["deploy_path"]) - service_name = env_config.get("service_name", self.config["service_name"]) - auto_restart = env_config.get("auto_restart", True) - - backup_path = os.path.join(self.config["backup_path"], backup_name) - - if not os.path.exists(backup_path): - print(f"备份不存在: {backup_name}") - return False - - try: - # 停止服务 - if auto_restart and service_name: - print(f"停止服务: {service_name}") - subprocess.run(['sudo', 'systemctl', 'stop', service_name], check=True) - - # 恢复文件 - print("恢复文件...") - app_backup_path = os.path.join(backup_path, "app") - if os.path.exists(app_backup_path): - if os.path.exists(deploy_path): - shutil.rmtree(deploy_path) - shutil.copytree(app_backup_path, deploy_path) - - # 恢复数据库 - db_backup_path = os.path.join(backup_path, "database", "tsp_assistant.db") - if os.path.exists(db_backup_path): - print("恢复数据库...") - shutil.copy2(db_backup_path, os.path.join(deploy_path, "tsp_assistant.db")) - - # 设置权限 - subprocess.run(['sudo', 'chown', '-R', 'www-data:www-data', deploy_path], check=True) - - # 启动服务 - if auto_restart and service_name: - print(f"启动服务: {service_name}") - subprocess.run(['sudo', 'systemctl', 'start', service_name], check=True) - - # 等待服务启动 - time.sleep(15) - - # 健康检查 - if self._health_check(): - print("回滚成功!") - return True - else: - print("回滚后健康检查失败") - return False - else: - print("回滚完成(未重启服务)") - return True - - except Exception as e: - print(f"回滚失败: {e}") - return False - - def list_backups(self) -> List[Dict]: - """列出所有备份""" - backups = [] - backup_dir = self.config["backup_path"] - - if os.path.exists(backup_dir): - for item in os.listdir(backup_dir): - backup_path = os.path.join(backup_dir, item) - if os.path.isdir(backup_path): - info_file = os.path.join(backup_path, "backup_info.json") - if os.path.exists(info_file): - try: - with open(info_file, 'r', encoding='utf-8') as f: - backup_info = json.load(f) - backups.append(backup_info) - except: - pass - - return sorted(backups, key=lambda x: x.get("timestamp", ""), reverse=True) - - def auto_update(self, source_path: str, environment: str = "production") -> bool: - """自动更新(智能选择热更新或完整更新)""" - print("开始自动更新...") - - # 检查是否有更新 - has_update, current_version, new_version = self.check_update_available(source_path) - if not has_update: - print("没有更新可用") - return True - - print(f"发现更新: {current_version} -> {new_version}") - - # 尝试热更新 - if self.hot_update(source_path, environment): - print("热更新成功") - return True - - # 热更新失败,进行完整更新 - print("热更新失败,进行完整更新...") - return self.full_update(source_path, environment) - -def main(): - """命令行接口""" - import argparse - - parser = argparse.ArgumentParser(description='TSP智能助手更新管理器') - parser.add_argument('action', choices=['check', 'hot-update', 'full-update', 'auto-update', 'rollback', 'list-backups'], - help='要执行的操作') - parser.add_argument('--source', help='源路径') - parser.add_argument('--environment', choices=['development', 'staging', 'production'], - default='production', help='目标环境') - parser.add_argument('--backup', help='备份名称(用于回滚)') - parser.add_argument('--no-backup', action='store_true', help='跳过备份') - - args = parser.parse_args() - - um = UpdateManager() - - if args.action == 'check': - if not args.source: - print("错误: 需要指定源路径") - sys.exit(1) - - has_update, current, new = um.check_update_available(args.source) - if has_update: - print(f"有更新可用: {current} -> {new}") - else: - print(f"没有更新可用 (当前版本: {current})") - - elif args.action == 'hot-update': - if not args.source: - print("错误: 需要指定源路径") - sys.exit(1) - - success = um.hot_update(args.source, args.environment) - sys.exit(0 if success else 1) - - elif args.action == 'full-update': - if not args.source: - print("错误: 需要指定源路径") - sys.exit(1) - - success = um.full_update(args.source, args.environment, not args.no_backup) - sys.exit(0 if success else 1) - - elif args.action == 'auto-update': - if not args.source: - print("错误: 需要指定源路径") - sys.exit(1) - - success = um.auto_update(args.source, args.environment) - sys.exit(0 if success else 1) - - elif args.action == 'rollback': - if not args.backup: - print("错误: 需要指定备份名称") - sys.exit(1) - - success = um.rollback(args.backup, args.environment) - sys.exit(0 if success else 1) - - elif args.action == 'list-backups': - backups = um.list_backups() - if backups: - print("可用备份:") - for backup in backups: - print(f" {backup['backup_name']} - {backup['timestamp']} - {backup.get('version', 'unknown')}") - else: - print("没有找到备份") - -if __name__ == "__main__": - main() diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh deleted file mode 100644 index c3ae143..0000000 --- a/scripts/upgrade.sh +++ /dev/null @@ -1,273 +0,0 @@ -#!/bin/bash -# TSP智能助手升级脚本 - -set -e - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -# 日志函数 -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -log_step() { - echo -e "${BLUE}[STEP]${NC} $1" -} - -# 配置变量 -APP_NAME="tsp_assistant" -BACKUP_DIR="./backups" -DEPLOY_PATH="/opt/tsp_assistant" -SERVICE_NAME="tsp_assistant" -HEALTH_URL="http://localhost:5000/api/health" - -# 检查参数 -if [ $# -lt 1 ]; then - echo "用法: $0 <新版本路径> [选项]" - echo "选项:" - echo " --force 强制升级,跳过确认" - echo " --no-backup 跳过备份" - echo " --rollback 回滚到指定备份" - exit 1 -fi - -NEW_VERSION_PATH=$1 -FORCE_UPGRADE=false -SKIP_BACKUP=false -ROLLBACK_MODE=false - -# 解析参数 -while [[ $# -gt 1 ]]; do - case $2 in - --force) - FORCE_UPGRADE=true - ;; - --no-backup) - SKIP_BACKUP=true - ;; - --rollback) - ROLLBACK_MODE=true - ;; - *) - log_error "未知选项: $2" - exit 1 - ;; - esac - shift -done - -# 回滚功能 -rollback() { - local backup_name=$1 - - if [ -z "$backup_name" ]; then - log_error "请指定备份名称" - exit 1 - fi - - log_step "开始回滚到备份: $backup_name" - - # 检查备份是否存在 - if [ ! -d "$BACKUP_DIR/$backup_name" ]; then - log_error "备份不存在: $backup_name" - log_info "可用备份列表:" - ls -la "$BACKUP_DIR" | grep backup - exit 1 - fi - - # 停止服务 - log_info "停止服务..." - sudo systemctl stop "$SERVICE_NAME" || true - - # 恢复文件 - log_info "恢复文件..." - sudo rm -rf "$DEPLOY_PATH" - sudo cp -r "$BACKUP_DIR/$backup_name" "$DEPLOY_PATH" - sudo chown -R www-data:www-data "$DEPLOY_PATH" - - # 恢复数据库 - if [ -f "$BACKUP_DIR/$backup_name/database/tsp_assistant.db" ]; then - log_info "恢复数据库..." - sudo cp "$BACKUP_DIR/$backup_name/database/tsp_assistant.db" "$DEPLOY_PATH/" - fi - - # 启动服务 - log_info "启动服务..." - sudo systemctl start "$SERVICE_NAME" - - # 等待服务启动 - sleep 10 - - # 健康检查 - if curl -f "$HEALTH_URL" > /dev/null 2>&1; then - log_info "回滚成功!" - else - log_error "回滚后健康检查失败" - exit 1 - fi -} - -# 创建备份 -create_backup() { - local timestamp=$(date +"%Y%m%d_%H%M%S") - local backup_name="${APP_NAME}_backup_${timestamp}" - local backup_path="$BACKUP_DIR/$backup_name" - - log_step "创建备份: $backup_name" - - # 创建备份目录 - mkdir -p "$backup_path" - - # 备份应用文件 - if [ -d "$DEPLOY_PATH" ]; then - log_info "备份应用文件..." - cp -r "$DEPLOY_PATH"/* "$backup_path/" - fi - - # 备份数据库 - if [ -f "$DEPLOY_PATH/tsp_assistant.db" ]; then - log_info "备份数据库..." - mkdir -p "$backup_path/database" - cp "$DEPLOY_PATH/tsp_assistant.db" "$backup_path/database/" - fi - - # 保存备份信息 - cat > "$backup_path/backup_info.json" << EOF -{ - "backup_name": "$backup_name", - "backup_path": "$backup_path", - "timestamp": "$timestamp", - "version": "$(cd "$DEPLOY_PATH" && python version.py version 2>/dev/null || echo "unknown")", - "git_commit": "$(cd "$DEPLOY_PATH" && git rev-parse HEAD 2>/dev/null | cut -c1-8 || echo "unknown")" -} -EOF - - log_info "备份完成: $backup_name" - echo "$backup_name" -} - -# 升级功能 -upgrade() { - local new_version_path=$1 - - log_step "开始升级TSP智能助手" - - # 检查新版本路径 - if [ ! -d "$new_version_path" ]; then - log_error "新版本路径不存在: $new_version_path" - exit 1 - fi - - # 检查当前版本 - if [ -d "$DEPLOY_PATH" ]; then - local current_version=$(cd "$DEPLOY_PATH" && python version.py version 2>/dev/null || echo "unknown") - log_info "当前版本: $current_version" - else - log_warn "当前部署路径不存在: $DEPLOY_PATH" - fi - - # 检查新版本 - local new_version=$(cd "$new_version_path" && python version.py version 2>/dev/null || echo "unknown") - log_info "新版本: $new_version" - - # 确认升级 - if [ "$FORCE_UPGRADE" = false ]; then - echo -n "确认升级到版本 $new_version? (y/N): " - read -r response - if [[ ! "$response" =~ ^[Yy]$ ]]; then - log_info "升级取消" - exit 0 - fi - fi - - # 创建备份 - local backup_name="" - if [ "$SKIP_BACKUP" = false ]; then - backup_name=$(create_backup) - fi - - # 停止服务 - log_step "停止服务..." - sudo systemctl stop "$SERVICE_NAME" || true - - # 升级文件 - log_step "升级应用文件..." - sudo rm -rf "$DEPLOY_PATH" - sudo mkdir -p "$DEPLOY_PATH" - sudo cp -r "$new_version_path"/* "$DEPLOY_PATH/" - sudo chown -R www-data:www-data "$DEPLOY_PATH" - - # 安装依赖 - log_step "安装依赖..." - cd "$DEPLOY_PATH" - sudo -u www-data python -m pip install -r requirements.txt - - # 运行数据库迁移 - log_step "运行数据库迁移..." - sudo -u www-data python init_database.py || true - - # 启动服务 - log_step "启动服务..." - sudo systemctl start "$SERVICE_NAME" - - # 等待服务启动 - log_info "等待服务启动..." - sleep 15 - - # 健康检查 - log_step "执行健康检查..." - local retry_count=0 - local max_retries=10 - - while [ $retry_count -lt $max_retries ]; do - if curl -f "$HEALTH_URL" > /dev/null 2>&1; then - log_info "健康检查通过!" - break - else - log_warn "健康检查失败,重试中... ($((retry_count + 1))/$max_retries)" - retry_count=$((retry_count + 1)) - sleep 5 - fi - done - - if [ $retry_count -eq $max_retries ]; then - log_error "健康检查失败,开始回滚..." - if [ -n "$backup_name" ]; then - rollback "$backup_name" - else - log_error "没有备份可回滚" - exit 1 - fi - else - log_info "升级成功!" - log_info "新版本: $new_version" - if [ -n "$backup_name" ]; then - log_info "备份名称: $backup_name" - fi - fi -} - -# 主函数 -main() { - if [ "$ROLLBACK_MODE" = true ]; then - rollback "$NEW_VERSION_PATH" - else - upgrade "$NEW_VERSION_PATH" - fi -} - -# 执行主函数 -main diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index 7273140..0000000 --- a/src/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# TSP助手 - 基于大模型的AI客服机器人 -__version__ = "1.0.0" -__author__ = "TSP Assistant Team" diff --git a/src/__pycache__/__init__.cpython-310.pyc b/src/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..3e46ed2 Binary files /dev/null and b/src/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/__pycache__/__init__.cpython-311.pyc b/src/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 74e1682..0000000 Binary files a/src/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/agent_assistant.cpython-310.pyc b/src/__pycache__/agent_assistant.cpython-310.pyc new file mode 100644 index 0000000..e7f5b08 Binary files /dev/null and b/src/__pycache__/agent_assistant.cpython-310.pyc differ diff --git a/src/__pycache__/agent_assistant.cpython-311.pyc b/src/__pycache__/agent_assistant.cpython-311.pyc deleted file mode 100644 index 19251cc..0000000 Binary files a/src/__pycache__/agent_assistant.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/main.cpython-310.pyc b/src/__pycache__/main.cpython-310.pyc new file mode 100644 index 0000000..7bbe47e Binary files /dev/null and b/src/__pycache__/main.cpython-310.pyc differ diff --git a/src/__pycache__/main.cpython-311.pyc b/src/__pycache__/main.cpython-311.pyc deleted file mode 100644 index 62c38b4..0000000 Binary files a/src/__pycache__/main.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/__init__.cpython-310.pyc b/src/agent/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..3c57fe9 Binary files /dev/null and b/src/agent/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/agent/__pycache__/__init__.cpython-311.pyc b/src/agent/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index baffdb4..0000000 Binary files a/src/agent/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/action_executor.cpython-311.pyc b/src/agent/__pycache__/action_executor.cpython-311.pyc deleted file mode 100644 index 72003e6..0000000 Binary files a/src/agent/__pycache__/action_executor.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/agent_assistant_core.cpython-311.pyc b/src/agent/__pycache__/agent_assistant_core.cpython-311.pyc deleted file mode 100644 index 8f099b7..0000000 Binary files a/src/agent/__pycache__/agent_assistant_core.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/agent_core.cpython-310.pyc b/src/agent/__pycache__/agent_core.cpython-310.pyc new file mode 100644 index 0000000..a84da53 Binary files /dev/null and b/src/agent/__pycache__/agent_core.cpython-310.pyc differ diff --git a/src/agent/__pycache__/agent_core.cpython-311.pyc b/src/agent/__pycache__/agent_core.cpython-311.pyc deleted file mode 100644 index a1e7abe..0000000 Binary files a/src/agent/__pycache__/agent_core.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/agent_message_handler.cpython-311.pyc b/src/agent/__pycache__/agent_message_handler.cpython-311.pyc deleted file mode 100644 index ca68961..0000000 Binary files a/src/agent/__pycache__/agent_message_handler.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/agent_sample_actions.cpython-311.pyc b/src/agent/__pycache__/agent_sample_actions.cpython-311.pyc deleted file mode 100644 index 55519bb..0000000 Binary files a/src/agent/__pycache__/agent_sample_actions.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/auto_monitor.cpython-311.pyc b/src/agent/__pycache__/auto_monitor.cpython-311.pyc deleted file mode 100644 index 4483914..0000000 Binary files a/src/agent/__pycache__/auto_monitor.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/executor.cpython-310.pyc b/src/agent/__pycache__/executor.cpython-310.pyc new file mode 100644 index 0000000..97a1c40 Binary files /dev/null and b/src/agent/__pycache__/executor.cpython-310.pyc differ diff --git a/src/agent/__pycache__/executor.cpython-311.pyc b/src/agent/__pycache__/executor.cpython-311.pyc deleted file mode 100644 index 3621c86..0000000 Binary files a/src/agent/__pycache__/executor.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/goal_manager.cpython-310.pyc b/src/agent/__pycache__/goal_manager.cpython-310.pyc new file mode 100644 index 0000000..41e3786 Binary files /dev/null and b/src/agent/__pycache__/goal_manager.cpython-310.pyc differ diff --git a/src/agent/__pycache__/goal_manager.cpython-311.pyc b/src/agent/__pycache__/goal_manager.cpython-311.pyc deleted file mode 100644 index f93a739..0000000 Binary files a/src/agent/__pycache__/goal_manager.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/intelligent_agent.cpython-311.pyc b/src/agent/__pycache__/intelligent_agent.cpython-311.pyc deleted file mode 100644 index 43192d2..0000000 Binary files a/src/agent/__pycache__/intelligent_agent.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/llm_client.cpython-310.pyc b/src/agent/__pycache__/llm_client.cpython-310.pyc new file mode 100644 index 0000000..1916372 Binary files /dev/null and b/src/agent/__pycache__/llm_client.cpython-310.pyc differ diff --git a/src/agent/__pycache__/llm_client.cpython-311.pyc b/src/agent/__pycache__/llm_client.cpython-311.pyc deleted file mode 100644 index 75ec851..0000000 Binary files a/src/agent/__pycache__/llm_client.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/planner.cpython-310.pyc b/src/agent/__pycache__/planner.cpython-310.pyc new file mode 100644 index 0000000..08025a9 Binary files /dev/null and b/src/agent/__pycache__/planner.cpython-310.pyc differ diff --git a/src/agent/__pycache__/planner.cpython-311.pyc b/src/agent/__pycache__/planner.cpython-311.pyc deleted file mode 100644 index 4321995..0000000 Binary files a/src/agent/__pycache__/planner.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/reasoning_engine.cpython-310.pyc b/src/agent/__pycache__/reasoning_engine.cpython-310.pyc new file mode 100644 index 0000000..d205333 Binary files /dev/null and b/src/agent/__pycache__/reasoning_engine.cpython-310.pyc differ diff --git a/src/agent/__pycache__/reasoning_engine.cpython-311.pyc b/src/agent/__pycache__/reasoning_engine.cpython-311.pyc deleted file mode 100644 index 6a1c8e1..0000000 Binary files a/src/agent/__pycache__/reasoning_engine.cpython-311.pyc and /dev/null differ diff --git a/src/agent/__pycache__/tool_manager.cpython-310.pyc b/src/agent/__pycache__/tool_manager.cpython-310.pyc new file mode 100644 index 0000000..4b07258 Binary files /dev/null and b/src/agent/__pycache__/tool_manager.cpython-310.pyc differ diff --git a/src/agent/__pycache__/tool_manager.cpython-311.pyc b/src/agent/__pycache__/tool_manager.cpython-311.pyc deleted file mode 100644 index 7ee7fd2..0000000 Binary files a/src/agent/__pycache__/tool_manager.cpython-311.pyc and /dev/null differ diff --git a/src/agent/auto_monitor.py b/src/agent/auto_monitor.py index c09fb49..4bc1fd7 100644 --- a/src/agent/auto_monitor.py +++ b/src/agent/auto_monitor.py @@ -5,7 +5,7 @@ 实现Agent的主动调用功能 """ -import asyncio +import asyncio跳过系统检查,直接启动服务... import logging import threading import time diff --git a/src/agent/llm_client.py b/src/agent/llm_client.py index c3c3e53..230d4a8 100644 --- a/src/agent/llm_client.py +++ b/src/agent/llm_client.py @@ -12,12 +12,14 @@ from typing import Dict, Any, Optional, List from abc import ABC, abstractmethod from dataclasses import dataclass +from src.config.unified_config import get_config + logger = logging.getLogger(__name__) @dataclass class LLMConfig: """LLM配置""" - provider: str # openai, anthropic, local, etc. + provider: str api_key: str base_url: Optional[str] = None model: str = "gpt-3.5-turbo" @@ -60,8 +62,8 @@ class OpenAIClient(BaseLLMClient): async def generate(self, prompt: str, **kwargs) -> str: """生成文本""" if not self.client: - return self._simulate_response(prompt) - + raise ImportError("OpenAI client not initialized. Please install the 'openai' package.") + try: response = await self.client.chat.completions.create( model=self.config.model, @@ -72,13 +74,13 @@ class OpenAIClient(BaseLLMClient): return response.choices[0].message.content except Exception as e: logger.error(f"OpenAI API调用失败: {e}") - return self._simulate_response(prompt) + raise e async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: """对话生成""" if not self.client: - return self._simulate_chat(messages) - + raise ImportError("OpenAI client not initialized. Please install the 'openai' package.") + try: response = await self.client.chat.completions.create( model=self.config.model, @@ -89,7 +91,7 @@ class OpenAIClient(BaseLLMClient): return response.choices[0].message.content except Exception as e: logger.error(f"OpenAI Chat API调用失败: {e}") - return self._simulate_chat(messages) + raise e def _simulate_response(self, prompt: str) -> str: """模拟响应""" @@ -194,30 +196,39 @@ class LocalLLMClient(BaseLLMClient): class LLMClientFactory: """LLM客户端工厂""" - + @staticmethod def create_client(config: LLMConfig) -> BaseLLMClient: """创建LLM客户端""" - if config.provider.lower() == "openai": + provider = config.provider.lower() + + # qwen 使用 OpenAI 兼容的 API + if provider in ["openai", "qwen"]: return OpenAIClient(config) - elif config.provider.lower() == "anthropic": + elif provider == "anthropic": return AnthropicClient(config) - elif config.provider.lower() == "local": + elif provider == "local": return LocalLLMClient(config) else: raise ValueError(f"不支持的LLM提供商: {config.provider}") class LLMManager: """LLM管理器""" - - def __init__(self, config: LLMConfig): - self.config = config - self.client = LLMClientFactory.create_client(config) + + def __init__(self, config=None): + if config: + self.config = config + else: + # If no config is provided, fetch it from the unified config system + self.config = get_config().llm + + self.client = LLMClientFactory.create_client(self.config) self.usage_stats = { "total_requests": 0, "total_tokens": 0, "error_count": 0 } + async def generate(self, prompt: str, **kwargs) -> str: """生成文本""" diff --git a/src/agent_assistant.py b/src/agent_assistant.py index 49b5f69..ff9338a 100644 --- a/src/agent_assistant.py +++ b/src/agent_assistant.py @@ -8,26 +8,29 @@ import logging import asyncio from typing import Dict, Any, List, Optional from datetime import datetime +from src.config.unified_config import get_config +from src.agent.llm_client import LLMManager logger = logging.getLogger(__name__) class TSPAgentAssistant: - """TSP Agent助手 - 简化版本""" - - def __init__(self, llm_config=None): + """TSP Agent助手""" + + def __init__(self): # 初始化基础功能 - self.llm_config = llm_config + config = get_config() + self.llm_manager = LLMManager(config.llm) self.is_agent_mode = True self.execution_history = [] - + # 工具注册表 self.tools = {} self.tool_performance = {} - + # AI监控状态 self.ai_monitoring_active = False self.monitoring_thread = None - + logger.info("TSP Agent助手初始化完成") def register_tool(self, name: str, func, metadata: Dict[str, Any] = None): @@ -338,30 +341,40 @@ class TSPAgentAssistant: try: import os import mimetypes - + + logger.info(f"开始处理知识库上传文件: {filename}") + # 检查文件类型 mime_type, _ = mimetypes.guess_type(file_path) file_ext = os.path.splitext(filename)[1].lower() - + # 读取文件内容 content = self._read_file_content(file_path, file_ext) if not content: + logger.error(f"文件读取失败或内容为空: {filename}") return {"success": False, "error": "无法读取文件内容"} - + + logger.info(f"文件读取成功: {filename}, 字符数={len(content)}") + # 使用简化的知识提取 + logger.info(f"正在对文件内容进行 AI 知识提取...") knowledge_entries = self._extract_knowledge_from_content(content, filename) - + + logger.info(f"知识提取完成: 共提取出 {len(knowledge_entries)} 个潜在条目") + # 保存到知识库 saved_count = 0 for i, entry in enumerate(knowledge_entries): try: - logger.info(f"保存知识条目 {i+1}: {entry.get('question', '')[:50]}...") - # 这里应该调用知识库管理器保存 + logger.info(f"正在保存知识条目 [{i+1}/{len(knowledge_entries)}]: {entry.get('question', '')[:30]}...") + # 这里在实际项目中应当注入知识库管理器的保存逻辑 + # 但在当前简化版本中仅记录日志 saved_count += 1 - logger.info(f"知识条目 {i+1} 保存成功") except Exception as save_error: logger.error(f"保存知识条目 {i+1} 时出错: {save_error}") - + + logger.info(f"文件处理任务结束: {filename}, 成功入库 {saved_count} 条") + return { "success": True, "knowledge_count": saved_count, diff --git a/src/analytics/__pycache__/__init__.cpython-310.pyc b/src/analytics/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..58b8aea Binary files /dev/null and b/src/analytics/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/__init__.cpython-311.pyc b/src/analytics/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index cecf113..0000000 Binary files a/src/analytics/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/__pycache__/ai_success_monitor.cpython-310.pyc b/src/analytics/__pycache__/ai_success_monitor.cpython-310.pyc new file mode 100644 index 0000000..d12580e Binary files /dev/null and b/src/analytics/__pycache__/ai_success_monitor.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/ai_success_monitor.cpython-311.pyc b/src/analytics/__pycache__/ai_success_monitor.cpython-311.pyc deleted file mode 100644 index 8a64f0c..0000000 Binary files a/src/analytics/__pycache__/ai_success_monitor.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/__pycache__/alert_system.cpython-310.pyc b/src/analytics/__pycache__/alert_system.cpython-310.pyc new file mode 100644 index 0000000..6119044 Binary files /dev/null and b/src/analytics/__pycache__/alert_system.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/alert_system.cpython-311.pyc b/src/analytics/__pycache__/alert_system.cpython-311.pyc deleted file mode 100644 index 970afe5..0000000 Binary files a/src/analytics/__pycache__/alert_system.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/__pycache__/analytics_manager.cpython-310.pyc b/src/analytics/__pycache__/analytics_manager.cpython-310.pyc new file mode 100644 index 0000000..fe8c7dd Binary files /dev/null and b/src/analytics/__pycache__/analytics_manager.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/analytics_manager.cpython-311.pyc b/src/analytics/__pycache__/analytics_manager.cpython-311.pyc deleted file mode 100644 index bec5df9..0000000 Binary files a/src/analytics/__pycache__/analytics_manager.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/__pycache__/monitor_service.cpython-310.pyc b/src/analytics/__pycache__/monitor_service.cpython-310.pyc new file mode 100644 index 0000000..bf1ad25 Binary files /dev/null and b/src/analytics/__pycache__/monitor_service.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/monitor_service.cpython-311.pyc b/src/analytics/__pycache__/monitor_service.cpython-311.pyc deleted file mode 100644 index 1ce6572..0000000 Binary files a/src/analytics/__pycache__/monitor_service.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/__pycache__/token_monitor.cpython-310.pyc b/src/analytics/__pycache__/token_monitor.cpython-310.pyc new file mode 100644 index 0000000..35d360e Binary files /dev/null and b/src/analytics/__pycache__/token_monitor.cpython-310.pyc differ diff --git a/src/analytics/__pycache__/token_monitor.cpython-311.pyc b/src/analytics/__pycache__/token_monitor.cpython-311.pyc deleted file mode 100644 index 5af7074..0000000 Binary files a/src/analytics/__pycache__/token_monitor.cpython-311.pyc and /dev/null differ diff --git a/src/analytics/ai_success_monitor.py b/src/analytics/ai_success_monitor.py index c06f922..edbec08 100644 --- a/src/analytics/ai_success_monitor.py +++ b/src/analytics/ai_success_monitor.py @@ -15,7 +15,7 @@ import time from ..core.database import db_manager from ..core.models import Alert from ..core.redis_manager import redis_manager -from ..config.config import Config +from src.config.unified_config import get_config logger = logging.getLogger(__name__) diff --git a/src/analytics/token_monitor.py b/src/analytics/token_monitor.py index 2a8d4c7..ab36e6d 100644 --- a/src/analytics/token_monitor.py +++ b/src/analytics/token_monitor.py @@ -13,7 +13,6 @@ from collections import defaultdict from ..core.database import db_manager from ..core.models import Conversation from ..core.redis_manager import redis_manager -from ..config.config import Config logger = logging.getLogger(__name__) diff --git a/src/config/__pycache__/__init__.cpython-310.pyc b/src/config/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..4f36f82 Binary files /dev/null and b/src/config/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/config/__pycache__/__init__.cpython-311.pyc b/src/config/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 20e2ade..0000000 Binary files a/src/config/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/config/__pycache__/config.cpython-311.pyc b/src/config/__pycache__/config.cpython-311.pyc deleted file mode 100644 index dab0542..0000000 Binary files a/src/config/__pycache__/config.cpython-311.pyc and /dev/null differ diff --git a/src/config/__pycache__/unified_config.cpython-310.pyc b/src/config/__pycache__/unified_config.cpython-310.pyc new file mode 100644 index 0000000..d4f8b09 Binary files /dev/null and b/src/config/__pycache__/unified_config.cpython-310.pyc differ diff --git a/src/config/__pycache__/unified_config.cpython-311.pyc b/src/config/__pycache__/unified_config.cpython-311.pyc deleted file mode 100644 index 0ce4eb2..0000000 Binary files a/src/config/__pycache__/unified_config.cpython-311.pyc and /dev/null differ diff --git a/src/config/config.py b/src/config/config.py deleted file mode 100644 index 56fbe78..0000000 --- a/src/config/config.py +++ /dev/null @@ -1,71 +0,0 @@ -import os -from typing import Dict, Any - -class Config: - """系统配置类""" - - # 阿里云千问API配置 - ALIBABA_API_KEY = "sk-c0dbefa1718d46eaa897199135066f00" - ALIBABA_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1" - ALIBABA_MODEL_NAME = "qwen-plus-latest" - - # 数据库配置 - DATABASE_URL = "mysql+pymysql://tsp_assistant:123456@jeason.online/tsp_assistant?charset=utf8mb4" - # DATABASE_URL = "sqlite:///local_test.db" # 本地测试数据库 - - # 知识库配置 - KNOWLEDGE_BASE_PATH = "data/knowledge_base" - VECTOR_DB_PATH = "data/vector_db" - - # 对话配置 - MAX_HISTORY_LENGTH = 10 - RESPONSE_TIMEOUT = 30 - - # 分析配置 - ANALYTICS_UPDATE_INTERVAL = 3600 # 1小时 - ALERT_THRESHOLD = 0.8 # 预警阈值 - - # 日志配置 - LOG_LEVEL = "INFO" - LOG_FILE = "logs/tsp_assistant.log" - - # 系统监控配置 - SYSTEM_MONITORING = True # 是否启用系统监控 - MONITORING_INTERVAL = 60 # 监控间隔(秒) - - @classmethod - def get_api_config(cls) -> Dict[str, Any]: - """获取API配置""" - return { - "api_key": cls.ALIBABA_API_KEY, - "base_url": cls.ALIBABA_BASE_URL, - "model_name": cls.ALIBABA_MODEL_NAME - } - - @classmethod - def get_database_config(cls) -> Dict[str, Any]: - """获取数据库配置""" - return { - "url": cls.DATABASE_URL, - "echo": False - } - - @classmethod - def get_knowledge_config(cls) -> Dict[str, Any]: - """获取知识库配置""" - return { - "base_path": cls.KNOWLEDGE_BASE_PATH, - "vector_db_path": cls.VECTOR_DB_PATH - } - - @classmethod - def get_config(cls) -> Dict[str, Any]: - """获取完整配置""" - return { - "system_monitoring": cls.SYSTEM_MONITORING, - "monitoring_interval": cls.MONITORING_INTERVAL, - "log_level": cls.LOG_LEVEL, - "log_file": cls.LOG_FILE, - "analytics_update_interval": cls.ANALYTICS_UPDATE_INTERVAL, - "alert_threshold": cls.ALERT_THRESHOLD - } diff --git a/src/config/unified_config.py b/src/config/unified_config.py index 4a5cad1..a123408 100644 --- a/src/config/unified_config.py +++ b/src/config/unified_config.py @@ -1,36 +1,42 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - """ 统一配置管理模块 -整合所有配置,提供统一的配置接口 +从环境变量加载所有配置,提供统一的配置接口 """ import os -import json import logging from typing import Dict, Any, Optional from dataclasses import dataclass, asdict -from pathlib import Path +from dotenv import load_dotenv + +# 在模块加载时,自动从.env文件加载环境变量 +# 这使得所有后续的os.getenv调用都能获取到.env中定义的值 +load_dotenv() logger = logging.getLogger(__name__) +# --- 数据类定义 --- +# 这些类定义了配置的结构,但不包含敏感的默认值。 +# 默认值只用于那些不敏感或在大多数环境中都相同的值。 + @dataclass class DatabaseConfig: """数据库配置""" - url: str = "mysql+pymysql://tsp_assistant:password@jeason.online/tsp_assistant?charset=utf8mb4" + url: str pool_size: int = 10 max_overflow: int = 20 pool_timeout: int = 30 - pool_recycle: int = 3600 + pool_recycle: int = 600 # 改为 10 分钟回收连接,避免连接超时 @dataclass class LLMConfig: """LLM配置""" - provider: str = "qwen" - api_key: str = "sk-c0dbefa1718d46eaa897199135066f00" - base_url: str = "https://dashscope.aliyuncs.com/compatible-mode/v1" - model: str = "qwen-plus-latest" + provider: str + api_key: str + model: str + base_url: Optional[str] = None temperature: float = 0.7 max_tokens: int = 2000 timeout: int = 30 @@ -47,13 +53,12 @@ class ServerConfig: @dataclass class FeishuConfig: """飞书配置""" - app_id: str = "" - app_secret: str = "" - app_token: str = "" - table_id: str = "" - status: str = "active" - sync_limit: int = 10 - auto_sync_interval: int = 0 + app_id: Optional[str] = None + app_secret: Optional[str] = None + verification_token: Optional[str] = None + encrypt_key: Optional[str] = None + table_id: Optional[str] = None + @dataclass class AIAccuracyConfig: @@ -63,234 +68,120 @@ class AIAccuracyConfig: manual_review_threshold: float = 0.80 ai_suggestion_confidence: float = 0.95 human_resolution_confidence: float = 0.90 - prefer_human_when_low_accuracy: bool = True - enable_auto_approval: bool = True - enable_human_fallback: bool = True -@dataclass -class SystemConfig: - """系统配置""" - backup_enabled: bool = True - backup_interval: int = 24 # 小时 - max_backup_files: int = 7 - cache_enabled: bool = True - cache_ttl: int = 3600 # 秒 - monitoring_enabled: bool = True + +# --- 统一配置管理器 --- class UnifiedConfig: - """统一配置管理器""" - - def __init__(self, config_dir: str = "config"): - self.config_dir = Path(config_dir) - self.config_file = self.config_dir / "unified_config.json" - - # 默认配置 - 从config/llm_config.py加载默认LLM配置 - self.database = DatabaseConfig() - self.llm = self._load_default_llm_config() - self.server = ServerConfig() - self.feishu = FeishuConfig() - self.ai_accuracy = AIAccuracyConfig() - self.system = SystemConfig() - - # 加载配置 - self.load_config() - - def _load_default_llm_config(self) -> LLMConfig: - """加载默认LLM配置""" - try: - from config.llm_config import DEFAULT_CONFIG - # 将config/llm_config.py中的配置转换为统一配置的格式 - return LLMConfig( - provider=DEFAULT_CONFIG.provider, - api_key=DEFAULT_CONFIG.api_key, - base_url=DEFAULT_CONFIG.base_url, - model=DEFAULT_CONFIG.model, - temperature=DEFAULT_CONFIG.temperature, - max_tokens=DEFAULT_CONFIG.max_tokens - ) - except Exception as e: - logger.warning(f"无法加载默认LLM配置,使用内置默认值: {e}") - return LLMConfig() - - def load_config(self): - """加载配置文件""" - try: - if self.config_file.exists(): - with open(self.config_file, 'r', encoding='utf-8') as f: - config_data = json.load(f) - - # 更新配置 - if 'database' in config_data: - self.database = DatabaseConfig(**config_data['database']) - if 'llm' in config_data: - self.llm = LLMConfig(**config_data['llm']) - if 'server' in config_data: - self.server = ServerConfig(**config_data['server']) - if 'feishu' in config_data: - self.feishu = FeishuConfig(**config_data['feishu']) - if 'ai_accuracy' in config_data: - self.ai_accuracy = AIAccuracyConfig(**config_data['ai_accuracy']) - if 'system' in config_data: - self.system = SystemConfig(**config_data['system']) - - logger.info("配置文件加载成功") - else: - logger.info("配置文件不存在,使用默认配置") - self.save_config() - - except Exception as e: - logger.error(f"加载配置文件失败: {e}") - - def save_config(self): - """保存配置文件""" - try: - self.config_dir.mkdir(exist_ok=True) - - config_data = { - 'database': asdict(self.database), - 'llm': asdict(self.llm), - 'server': asdict(self.server), - 'feishu': asdict(self.feishu), - 'ai_accuracy': asdict(self.ai_accuracy), - 'system': asdict(self.system) - } - - with open(self.config_file, 'w', encoding='utf-8') as f: - json.dump(config_data, f, indent=2, ensure_ascii=False) - - logger.info("配置文件保存成功") - - except Exception as e: - logger.error(f"保存配置文件失败: {e}") - - def load_from_env(self): - """从环境变量加载配置""" - # 数据库配置 - if os.getenv('DATABASE_URL'): - self.database.url = os.getenv('DATABASE_URL') - - # LLM配置 - if os.getenv('LLM_PROVIDER'): - self.llm.provider = os.getenv('LLM_PROVIDER') - if os.getenv('LLM_API_KEY'): - self.llm.api_key = os.getenv('LLM_API_KEY') - if os.getenv('LLM_MODEL'): - self.llm.model = os.getenv('LLM_MODEL') - - # 服务器配置 - if os.getenv('SERVER_PORT'): - self.server.port = int(os.getenv('SERVER_PORT')) - if os.getenv('LOG_LEVEL'): - self.server.log_level = os.getenv('LOG_LEVEL') - - # 飞书配置 - if os.getenv('FEISHU_APP_ID'): - self.feishu.app_id = os.getenv('FEISHU_APP_ID') - if os.getenv('FEISHU_APP_SECRET'): - self.feishu.app_secret = os.getenv('FEISHU_APP_SECRET') - if os.getenv('FEISHU_APP_TOKEN'): - self.feishu.app_token = os.getenv('FEISHU_APP_TOKEN') - if os.getenv('FEISHU_TABLE_ID'): - self.feishu.table_id = os.getenv('FEISHU_TABLE_ID') - - def get_database_url(self) -> str: - """获取数据库连接URL""" - return self.database.url - - def get_llm_config(self) -> Dict[str, Any]: - """获取LLM配置""" - return asdict(self.llm) - - def get_server_config(self) -> Dict[str, Any]: - """获取服务器配置""" - return asdict(self.server) - - def get_feishu_config(self) -> Dict[str, Any]: - """获取飞书配置""" - return asdict(self.feishu) - - def get_ai_accuracy_config(self) -> Dict[str, Any]: - """获取AI准确率配置""" - return asdict(self.ai_accuracy) - - def get_system_config(self) -> Dict[str, Any]: - """获取系统配置""" - return asdict(self.system) - - def update_config(self, section: str, config_data: Dict[str, Any]): - """更新配置""" - try: - if section == 'database': - self.database = DatabaseConfig(**config_data) - elif section == 'llm': - self.llm = LLMConfig(**config_data) - elif section == 'server': - self.server = ServerConfig(**config_data) - elif section == 'feishu': - self.feishu = FeishuConfig(**config_data) - elif section == 'ai_accuracy': - self.ai_accuracy = AIAccuracyConfig(**config_data) - elif section == 'system': - self.system = SystemConfig(**config_data) - else: - raise ValueError(f"未知的配置节: {section}") - - self.save_config() - logger.info(f"配置节 {section} 更新成功") - - except Exception as e: - logger.error(f"更新配置失败: {e}") - raise - - def validate_config(self) -> bool: - """验证配置有效性""" - try: - # 验证数据库配置 - if not self.database.url: - logger.error("数据库URL未配置") - return False - - # 验证LLM配置 - if not self.llm.api_key: - logger.warning("LLM API密钥未配置") - - # 验证飞书配置 - if self.feishu.status == "active": - if not all([self.feishu.app_id, self.feishu.app_secret, - self.feishu.app_token, self.feishu.table_id]): - logger.warning("飞书配置不完整") - - logger.info("配置验证通过") - return True - - except Exception as e: - logger.error(f"配置验证失败: {e}") - return False - + """ + 统一配置管理器 + 在实例化时,从环境变量中加载所有配置。 + """ + + def __init__(self): + logger.info("Initializing unified configuration from environment variables...") + self.database = self._load_database_from_env() + self.llm = self._load_llm_from_env() + self.server = self._load_server_from_env() + self.feishu = self._load_feishu_from_env() + self.ai_accuracy = self._load_ai_accuracy_from_env() + self.validate_config() + + def _load_database_from_env(self) -> DatabaseConfig: + db_url = os.getenv("DATABASE_URL") + if not db_url: + raise ValueError("FATAL: DATABASE_URL environment variable is not set.") + logger.info("Database config loaded.") + return DatabaseConfig(url=db_url) + + def _load_llm_from_env(self) -> LLMConfig: + api_key = os.getenv("LLM_API_KEY") + if not api_key: + logger.warning("LLM_API_KEY is not set. LLM functionality will be disabled or fail.") + + config = LLMConfig( + provider=os.getenv("LLM_PROVIDER", "qwen"), + api_key=api_key, + model=os.getenv("LLM_MODEL", "qwen-plus-latest"), + base_url=os.getenv("LLM_BASE_URL"), + temperature=float(os.getenv("LLM_TEMPERATURE", 0.7)), + max_tokens=int(os.getenv("LLM_MAX_TOKENS", 2000)), + timeout=int(os.getenv("LLM_TIMEOUT", 30)) + ) + logger.info("LLM config loaded.") + return config + + def _load_server_from_env(self) -> ServerConfig: + config = ServerConfig( + host=os.getenv("SERVER_HOST", "0.0.0.0"), + port=int(os.getenv("SERVER_PORT", 5000)), + websocket_port=int(os.getenv("WEBSOCKET_PORT", 8765)), + debug=os.getenv("DEBUG_MODE", "False").lower() in ('true', '1', 't'), + log_level=os.getenv("LOG_LEVEL", "INFO").upper() + ) + logger.info("Server config loaded.") + return config + + def _load_feishu_from_env(self) -> FeishuConfig: + config = FeishuConfig( + app_id=os.getenv("FEISHU_APP_ID"), + app_secret=os.getenv("FEISHU_APP_SECRET"), + verification_token=os.getenv("FEISHU_VERIFICATION_TOKEN"), + encrypt_key=os.getenv("FEISHU_ENCRYPT_KEY"), + table_id=os.getenv("FEISHU_TABLE_ID") + ) + logger.info("Feishu config loaded.") + return config + + def _load_ai_accuracy_from_env(self) -> AIAccuracyConfig: + config = AIAccuracyConfig( + auto_approve_threshold=float(os.getenv("AI_AUTO_APPROVE_THRESHOLD", 0.95)), + use_human_resolution_threshold=float(os.getenv("AI_USE_HUMAN_RESOLUTION_THRESHOLD", 0.90)), + manual_review_threshold=float(os.getenv("AI_MANUAL_REVIEW_THRESHOLD", 0.80)), + ai_suggestion_confidence=float(os.getenv("AI_SUGGESTION_CONFIDENCE", 0.95)), + human_resolution_confidence=float(os.getenv("AI_HUMAN_RESOLUTION_CONFIDENCE", 0.90)) + ) + logger.info("AI Accuracy config loaded.") + return config + + def validate_config(self): + """在启动时验证关键配置""" + if not self.database.url: + raise ValueError("Database URL is missing.") + if not self.llm.api_key: + logger.warning("LLM API key is not configured. AI features may fail.") + if self.feishu.app_id and not self.feishu.app_secret: + logger.warning("FEISHU_APP_ID is set, but FEISHU_APP_SECRET is missing.") + logger.info("Configuration validation passed (warnings may exist).") + + # --- Public Getters --- + def get_all_config(self) -> Dict[str, Any]: - """获取所有配置""" + """获取所有配置的字典表示""" return { 'database': asdict(self.database), 'llm': asdict(self.llm), 'server': asdict(self.server), 'feishu': asdict(self.feishu), 'ai_accuracy': asdict(self.ai_accuracy), - 'system': asdict(self.system) } -# 全局配置实例 -_config_instance = None +# --- 全局单例模式 --- + +_config_instance: Optional[UnifiedConfig] = None def get_config() -> UnifiedConfig: - """获取全局配置实例""" + """ + 获取全局统一配置实例。 + 第一次调用时,它会创建并加载配置。后续调用将返回缓存的实例。 + """ global _config_instance if _config_instance is None: _config_instance = UnifiedConfig() - _config_instance.load_from_env() return _config_instance -def reload_config(): - """重新加载配置""" +def reload_config() -> UnifiedConfig: + """强制重新加载配置""" global _config_instance _config_instance = None return get_config() diff --git a/src/core/__pycache__/__init__.cpython-310.pyc b/src/core/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..b05a195 Binary files /dev/null and b/src/core/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/core/__pycache__/__init__.cpython-311.pyc b/src/core/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 85f6415..0000000 Binary files a/src/core/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/auth_manager.cpython-310.pyc b/src/core/__pycache__/auth_manager.cpython-310.pyc new file mode 100644 index 0000000..0b73c25 Binary files /dev/null and b/src/core/__pycache__/auth_manager.cpython-310.pyc differ diff --git a/src/core/__pycache__/auth_manager.cpython-311.pyc b/src/core/__pycache__/auth_manager.cpython-311.pyc deleted file mode 100644 index 1ab3b73..0000000 Binary files a/src/core/__pycache__/auth_manager.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/backup_manager.cpython-310.pyc b/src/core/__pycache__/backup_manager.cpython-310.pyc new file mode 100644 index 0000000..19844af Binary files /dev/null and b/src/core/__pycache__/backup_manager.cpython-310.pyc differ diff --git a/src/core/__pycache__/backup_manager.cpython-311.pyc b/src/core/__pycache__/backup_manager.cpython-311.pyc deleted file mode 100644 index df40c33..0000000 Binary files a/src/core/__pycache__/backup_manager.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/cache_manager.cpython-310.pyc b/src/core/__pycache__/cache_manager.cpython-310.pyc new file mode 100644 index 0000000..17798d4 Binary files /dev/null and b/src/core/__pycache__/cache_manager.cpython-310.pyc differ diff --git a/src/core/__pycache__/cache_manager.cpython-311.pyc b/src/core/__pycache__/cache_manager.cpython-311.pyc deleted file mode 100644 index 3d71020..0000000 Binary files a/src/core/__pycache__/cache_manager.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/database.cpython-310.pyc b/src/core/__pycache__/database.cpython-310.pyc new file mode 100644 index 0000000..4a4c748 Binary files /dev/null and b/src/core/__pycache__/database.cpython-310.pyc differ diff --git a/src/core/__pycache__/database.cpython-311.pyc b/src/core/__pycache__/database.cpython-311.pyc deleted file mode 100644 index 465f911..0000000 Binary files a/src/core/__pycache__/database.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/llm_client.cpython-310.pyc b/src/core/__pycache__/llm_client.cpython-310.pyc new file mode 100644 index 0000000..4400ae8 Binary files /dev/null and b/src/core/__pycache__/llm_client.cpython-310.pyc differ diff --git a/src/core/__pycache__/llm_client.cpython-311.pyc b/src/core/__pycache__/llm_client.cpython-311.pyc deleted file mode 100644 index e4f49a6..0000000 Binary files a/src/core/__pycache__/llm_client.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/models.cpython-310.pyc b/src/core/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000..62ed52f Binary files /dev/null and b/src/core/__pycache__/models.cpython-310.pyc differ diff --git a/src/core/__pycache__/models.cpython-311.pyc b/src/core/__pycache__/models.cpython-311.pyc deleted file mode 100644 index 530e97a..0000000 Binary files a/src/core/__pycache__/models.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/query_optimizer.cpython-310.pyc b/src/core/__pycache__/query_optimizer.cpython-310.pyc new file mode 100644 index 0000000..2c5bf3c Binary files /dev/null and b/src/core/__pycache__/query_optimizer.cpython-310.pyc differ diff --git a/src/core/__pycache__/query_optimizer.cpython-311.pyc b/src/core/__pycache__/query_optimizer.cpython-311.pyc deleted file mode 100644 index 11c0fc3..0000000 Binary files a/src/core/__pycache__/query_optimizer.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/redis_manager.cpython-310.pyc b/src/core/__pycache__/redis_manager.cpython-310.pyc new file mode 100644 index 0000000..2ce0a25 Binary files /dev/null and b/src/core/__pycache__/redis_manager.cpython-310.pyc differ diff --git a/src/core/__pycache__/redis_manager.cpython-311.pyc b/src/core/__pycache__/redis_manager.cpython-311.pyc deleted file mode 100644 index d0ee168..0000000 Binary files a/src/core/__pycache__/redis_manager.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/system_optimizer.cpython-310.pyc b/src/core/__pycache__/system_optimizer.cpython-310.pyc new file mode 100644 index 0000000..652101f Binary files /dev/null and b/src/core/__pycache__/system_optimizer.cpython-310.pyc differ diff --git a/src/core/__pycache__/system_optimizer.cpython-311.pyc b/src/core/__pycache__/system_optimizer.cpython-311.pyc deleted file mode 100644 index d4c67f6..0000000 Binary files a/src/core/__pycache__/system_optimizer.cpython-311.pyc and /dev/null differ diff --git a/src/core/__pycache__/workorder_permissions.cpython-311.pyc b/src/core/__pycache__/workorder_permissions.cpython-311.pyc deleted file mode 100644 index e627d47..0000000 Binary files a/src/core/__pycache__/workorder_permissions.cpython-311.pyc and /dev/null differ diff --git a/src/core/database.py b/src/core/database.py index 7c6d87f..7f92e87 100644 --- a/src/core/database.py +++ b/src/core/database.py @@ -7,73 +7,71 @@ import logging from .models import Base from .cache_manager import cache_manager, cache_query -from ..config.config import Config +from src.config.unified_config import get_config logger = logging.getLogger(__name__) class DatabaseManager: """数据库管理器""" - + def __init__(self): self.engine = None self.SessionLocal = None self._initialize_database() - + def _initialize_database(self): """初始化数据库连接""" try: - db_config = Config.get_database_config() - + config = get_config() + db_url = config.database.url + # 根据数据库类型选择不同的连接参数 - if "mysql" in db_config["url"]: + if "mysql" in db_url: # MySQL配置 - 优化连接池和重连机制 self.engine = create_engine( - db_config["url"], - echo=db_config["echo"], - pool_size=10, # 连接池大小 - max_overflow=20, # 溢出连接数 - pool_pre_ping=True, # 连接前检查连接是否有效 - pool_recycle=3600, # 1小时后回收连接 - pool_timeout=60, # 连接池超时(秒) + db_url, + echo=False, + pool_size=config.database.pool_size, + max_overflow=config.database.max_overflow, + pool_pre_ping=True, + pool_recycle=config.database.pool_recycle, + pool_timeout=config.database.pool_timeout, connect_args={ "charset": "utf8mb4", "autocommit": False, - "connect_timeout": 30, # 连接超时 - "read_timeout": 60, # 读取超时 - "write_timeout": 60, # 写入超时 - "max_allowed_packet": 64*1024*1024, # 64MB - "connect_timeout": 30, # 连接超时(秒)- 适用于网络延迟较大的情况 - "read_timeout": 30, # 读取超时(秒) - "write_timeout": 30, # 写入超时(秒) + "connect_timeout": 30, + "read_timeout": 60, + "write_timeout": 60, + "max_allowed_packet": 64 * 1024 * 1024, } ) else: # SQLite配置 - 优化性能 self.engine = create_engine( - db_config["url"], - echo=db_config["echo"], + db_url, + echo=False, poolclass=StaticPool, connect_args={ "check_same_thread": False, - "timeout": 20, # 连接超时 - "isolation_level": None # 自动提交模式 + "timeout": 20, + "isolation_level": None } ) - + self.SessionLocal = sessionmaker( autocommit=False, autoflush=False, bind=self.engine ) - + # 创建所有表 Base.metadata.create_all(bind=self.engine) logger.info("数据库初始化成功") - + except Exception as e: logger.error(f"数据库初始化失败: {e}") raise - + @contextmanager def get_session(self) -> Generator[Session, None, None]: """获取数据库会话的上下文管理器""" @@ -112,16 +110,16 @@ class DatabaseManager: except Exception as e: logger.error(f"数据库重新连接失败: {e}") return False - + def get_session_direct(self) -> Session: """直接获取数据库会话""" return self.SessionLocal() - + def close_session(self, session: Session): """关闭数据库会话""" if session: session.close() - + def test_connection(self) -> bool: """测试数据库连接""" try: @@ -131,12 +129,12 @@ class DatabaseManager: except Exception as e: logger.error(f"数据库连接测试失败: {e}") return False - + @cache_query(ttl=60) # 缓存1分钟 def get_cached_query(self, query_key: str, query_func, *args, **kwargs): """执行带缓存的查询""" return query_func(*args, **kwargs) - + def invalidate_cache_pattern(self, pattern: str): """根据模式清除缓存""" try: @@ -144,7 +142,7 @@ class DatabaseManager: logger.info(f"缓存已清除: {pattern}") except Exception as e: logger.error(f"清除缓存失败: {e}") - + def get_cache_stats(self): """获取缓存统计信息""" return cache_manager.get_stats() diff --git a/src/core/llm_client.py b/src/core/llm_client.py index d64017f..302f176 100644 --- a/src/core/llm_client.py +++ b/src/core/llm_client.py @@ -4,18 +4,19 @@ import logging from typing import Dict, List, Optional, Any from datetime import datetime -from ..config.config import Config +from src.config.unified_config import get_config logger = logging.getLogger(__name__) class QwenClient: """阿里云千问API客户端""" - + def __init__(self): - self.api_config = Config.get_api_config() - self.base_url = self.api_config["base_url"] - self.api_key = self.api_config["api_key"] - self.model_name = self.api_config["model_name"] + config = get_config() + self.base_url = config.llm.base_url or "https://dashscope.aliyuncs.com/compatible-mode/v1" + self.api_key = config.llm.api_key + self.model_name = config.llm.model + self.timeout = config.llm.timeout self.headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" @@ -43,7 +44,7 @@ class QwenClient: url, headers=self.headers, json=payload, - timeout=Config.RESPONSE_TIMEOUT + timeout=self.timeout ) if response.status_code == 200: diff --git a/src/core/models.py b/src/core/models.py index a6f2342..40895ab 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -66,6 +66,8 @@ class Conversation(Base): confidence_score = Column(Float) knowledge_used = Column(Text) # 使用的知识库条目 response_time = Column(Float) # 响应时间(秒) + ip_address = Column(String(45), nullable=True) # IP地址 + invocation_method = Column(String(50), nullable=True) # 调用方式(websocket, api等) work_order = relationship("WorkOrder", back_populates="conversations") diff --git a/src/core/query_optimizer.py b/src/core/query_optimizer.py index 84b3b5d..478d02f 100644 --- a/src/core/query_optimizer.py +++ b/src/core/query_optimizer.py @@ -90,7 +90,9 @@ class QueryOptimizer: 'assistant_response': conv.assistant_response, 'timestamp': conv.timestamp.isoformat() if conv.timestamp else None, 'confidence_score': conv.confidence_score, - 'work_order_id': conv.work_order_id + 'work_order_id': conv.work_order_id, + 'ip_address': conv.ip_address, + 'invocation_method': conv.invocation_method }) # 记录查询时间 diff --git a/src/core/system_optimizer.py b/src/core/system_optimizer.py index 1695006..751fd7e 100644 --- a/src/core/system_optimizer.py +++ b/src/core/system_optimizer.py @@ -13,7 +13,7 @@ from collections import defaultdict, deque import psutil import redis -from ..config.config import Config +from src.config.unified_config import get_config from .database import db_manager logger = logging.getLogger(__name__) @@ -82,12 +82,7 @@ class SystemOptimizer: def _start_monitoring(self): """启动监控线程""" try: - # 检查是否启用系统监控 - enable_monitoring = Config.get_config().get('system_monitoring', True) - if not enable_monitoring: - logger.info("系统监控已禁用") - return - + # 默认启用系统监控 monitor_thread = threading.Thread(target=self._monitor_system, daemon=True) monitor_thread.start() except Exception as e: diff --git a/src/dialogue/__pycache__/__init__.cpython-310.pyc b/src/dialogue/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..0f27127 Binary files /dev/null and b/src/dialogue/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/dialogue/__pycache__/__init__.cpython-311.pyc b/src/dialogue/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 77ea641..0000000 Binary files a/src/dialogue/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/dialogue/__pycache__/conversation_history.cpython-310.pyc b/src/dialogue/__pycache__/conversation_history.cpython-310.pyc new file mode 100644 index 0000000..0a9059d Binary files /dev/null and b/src/dialogue/__pycache__/conversation_history.cpython-310.pyc differ diff --git a/src/dialogue/__pycache__/conversation_history.cpython-311.pyc b/src/dialogue/__pycache__/conversation_history.cpython-311.pyc deleted file mode 100644 index 509d311..0000000 Binary files a/src/dialogue/__pycache__/conversation_history.cpython-311.pyc and /dev/null differ diff --git a/src/dialogue/__pycache__/dialogue_manager.cpython-310.pyc b/src/dialogue/__pycache__/dialogue_manager.cpython-310.pyc new file mode 100644 index 0000000..6fb9293 Binary files /dev/null and b/src/dialogue/__pycache__/dialogue_manager.cpython-310.pyc differ diff --git a/src/dialogue/__pycache__/dialogue_manager.cpython-311.pyc b/src/dialogue/__pycache__/dialogue_manager.cpython-311.pyc deleted file mode 100644 index 1be43a3..0000000 Binary files a/src/dialogue/__pycache__/dialogue_manager.cpython-311.pyc and /dev/null differ diff --git a/src/dialogue/__pycache__/realtime_chat.cpython-310.pyc b/src/dialogue/__pycache__/realtime_chat.cpython-310.pyc new file mode 100644 index 0000000..f1000c0 Binary files /dev/null and b/src/dialogue/__pycache__/realtime_chat.cpython-310.pyc differ diff --git a/src/dialogue/__pycache__/realtime_chat.cpython-311.pyc b/src/dialogue/__pycache__/realtime_chat.cpython-311.pyc deleted file mode 100644 index 564fc60..0000000 Binary files a/src/dialogue/__pycache__/realtime_chat.cpython-311.pyc and /dev/null differ diff --git a/src/dialogue/conversation_history.py b/src/dialogue/conversation_history.py index afb8059..ad40895 100644 --- a/src/dialogue/conversation_history.py +++ b/src/dialogue/conversation_history.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import Session from ..core.database import db_manager from ..core.models import Conversation, WorkOrder, WorkOrderSuggestion, KnowledgeEntry from ..core.redis_manager import redis_manager -from ..config.config import Config +from src.config.unified_config import get_config from sqlalchemy import and_, or_, desc logger = logging.getLogger(__name__) @@ -43,11 +43,13 @@ class ConversationHistoryManager: work_order_id: Optional[int] = None, confidence_score: Optional[float] = None, response_time: Optional[float] = None, - knowledge_used: Optional[List[int]] = None + knowledge_used: Optional[List[int]] = None, + ip_address: Optional[str] = None, + invocation_method: Optional[str] = None ) -> int: """保存对话记录到数据库和Redis""" conversation_id = 0 - + try: # 保存到数据库 with db_manager.get_session() as session: @@ -58,12 +60,14 @@ class ConversationHistoryManager: confidence_score=confidence_score, response_time=response_time, knowledge_used=json.dumps(knowledge_used or [], ensure_ascii=False), + ip_address=ip_address, + invocation_method=invocation_method, timestamp=datetime.now() ) session.add(conversation) session.commit() conversation_id = conversation.id - + # 保存到Redis缓存 self._save_to_cache( user_id=user_id, @@ -72,7 +76,9 @@ class ConversationHistoryManager: assistant_response=assistant_response, conversation_id=conversation_id, confidence_score=confidence_score, - response_time=response_time + response_time=response_time, + ip_address=ip_address, + invocation_method=invocation_method ) logger.info(f"对话记录保存成功: ID={conversation_id}") @@ -90,16 +96,18 @@ class ConversationHistoryManager: assistant_response: str, conversation_id: int, confidence_score: Optional[float] = None, - response_time: Optional[float] = None + response_time: Optional[float] = None, + ip_address: Optional[str] = None, + invocation_method: Optional[str] = None ): """保存对话到Redis缓存""" redis_client = self._get_redis_client() if not redis_client: return - + try: cache_key = self._get_cache_key(user_id, work_order_id) - + # 构建对话记录 conversation_record = { "id": conversation_id, @@ -107,7 +115,9 @@ class ConversationHistoryManager: "assistant_response": assistant_response, "timestamp": datetime.now().isoformat(), "confidence_score": confidence_score, - "response_time": response_time + "response_time": response_time, + "ip_address": ip_address, + "invocation_method": invocation_method } # 添加到Redis列表 @@ -205,6 +215,8 @@ class ConversationHistoryManager: "timestamp": conv.timestamp.isoformat(), "confidence_score": conv.confidence_score, "response_time": conv.response_time, + "ip_address": conv.ip_address, + "invocation_method": conv.invocation_method, "knowledge_used": json.loads(conv.knowledge_used) if conv.knowledge_used else [] }) diff --git a/src/dialogue/realtime_chat.py b/src/dialogue/realtime_chat.py index 94ef4a7..22feaf5 100644 --- a/src/dialogue/realtime_chat.py +++ b/src/dialogue/realtime_chat.py @@ -58,15 +58,17 @@ class RealtimeChatManager: logger.info(f"创建新会话: {session_id}") return session_id - def process_message(self, session_id: str, user_message: str) -> Dict[str, Any]: + def process_message(self, session_id: str, user_message: str, ip_address: str = None, invocation_method: str = "websocket") -> Dict[str, Any]: """处理用户消息""" try: if session_id not in self.active_sessions: return {"error": "会话不存在"} - + session = self.active_sessions[session_id] session["last_activity"] = datetime.now() session["message_count"] += 1 + session["ip_address"] = ip_address + session["invocation_method"] = invocation_method # 创建用户消息 user_msg = ChatMessage( @@ -140,7 +142,7 @@ class RealtimeChatManager: session["context"] = session["context"][-20:] # 保存到数据库(每轮一条,带会话标记) - self._save_conversation(session_id, user_msg, assistant_msg) + self._save_conversation(session_id, user_msg, assistant_msg, ip_address, invocation_method) # 更新知识库使用次数 if knowledge_results: @@ -350,7 +352,7 @@ class RealtimeChatManager: return base_confidence - def _save_conversation(self, session_id: str, user_msg: ChatMessage, assistant_msg: ChatMessage): + def _save_conversation(self, session_id: str, user_msg: ChatMessage, assistant_msg: ChatMessage, ip_address: str = None, invocation_method: str = None): """保存对话到数据库""" try: with db_manager.get_session() as session: @@ -377,7 +379,9 @@ class RealtimeChatManager: timestamp=assistant_msg.timestamp or user_msg.timestamp, confidence_score=assistant_msg.confidence_score, knowledge_used=json.dumps(marked_knowledge, ensure_ascii=False) if marked_knowledge else None, - response_time=response_time + response_time=response_time, + ip_address=ip_address, + invocation_method=invocation_method ) session.add(conversation) session.commit() diff --git a/src/integrations/__init__.py b/src/integrations/__init__.py deleted file mode 100644 index f531c4b..0000000 --- a/src/integrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -""" -集成模块 -处理与外部系统的集成,如飞书、钉钉等 -""" diff --git a/src/integrations/__pycache__/__init__.cpython-311.pyc b/src/integrations/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 642d61e..0000000 Binary files a/src/integrations/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/ai_suggestion_service.cpython-310.pyc b/src/integrations/__pycache__/ai_suggestion_service.cpython-310.pyc new file mode 100644 index 0000000..29f24dc Binary files /dev/null and b/src/integrations/__pycache__/ai_suggestion_service.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/ai_suggestion_service.cpython-311.pyc b/src/integrations/__pycache__/ai_suggestion_service.cpython-311.pyc deleted file mode 100644 index 47e4b27..0000000 Binary files a/src/integrations/__pycache__/ai_suggestion_service.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/config_manager.cpython-310.pyc b/src/integrations/__pycache__/config_manager.cpython-310.pyc new file mode 100644 index 0000000..05f72c6 Binary files /dev/null and b/src/integrations/__pycache__/config_manager.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/config_manager.cpython-311.pyc b/src/integrations/__pycache__/config_manager.cpython-311.pyc deleted file mode 100644 index 6f2b9e2..0000000 Binary files a/src/integrations/__pycache__/config_manager.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/feishu_client.cpython-310.pyc b/src/integrations/__pycache__/feishu_client.cpython-310.pyc new file mode 100644 index 0000000..ee223cb Binary files /dev/null and b/src/integrations/__pycache__/feishu_client.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/feishu_client.cpython-311.pyc b/src/integrations/__pycache__/feishu_client.cpython-311.pyc deleted file mode 100644 index a28d01b..0000000 Binary files a/src/integrations/__pycache__/feishu_client.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/feishu_permission_checker.cpython-310.pyc b/src/integrations/__pycache__/feishu_permission_checker.cpython-310.pyc new file mode 100644 index 0000000..0a0e454 Binary files /dev/null and b/src/integrations/__pycache__/feishu_permission_checker.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/feishu_permission_checker.cpython-311.pyc b/src/integrations/__pycache__/feishu_permission_checker.cpython-311.pyc deleted file mode 100644 index 39240f9..0000000 Binary files a/src/integrations/__pycache__/feishu_permission_checker.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/feishu_service.cpython-310.pyc b/src/integrations/__pycache__/feishu_service.cpython-310.pyc new file mode 100644 index 0000000..ecd25ea Binary files /dev/null and b/src/integrations/__pycache__/feishu_service.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/flexible_field_mapper.cpython-310.pyc b/src/integrations/__pycache__/flexible_field_mapper.cpython-310.pyc new file mode 100644 index 0000000..b41891b Binary files /dev/null and b/src/integrations/__pycache__/flexible_field_mapper.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/flexible_field_mapper.cpython-311.pyc b/src/integrations/__pycache__/flexible_field_mapper.cpython-311.pyc deleted file mode 100644 index 6911695..0000000 Binary files a/src/integrations/__pycache__/flexible_field_mapper.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/__pycache__/workorder_sync.cpython-310.pyc b/src/integrations/__pycache__/workorder_sync.cpython-310.pyc new file mode 100644 index 0000000..aa67cef Binary files /dev/null and b/src/integrations/__pycache__/workorder_sync.cpython-310.pyc differ diff --git a/src/integrations/__pycache__/workorder_sync.cpython-311.pyc b/src/integrations/__pycache__/workorder_sync.cpython-311.pyc deleted file mode 100644 index 6b1714b..0000000 Binary files a/src/integrations/__pycache__/workorder_sync.cpython-311.pyc and /dev/null differ diff --git a/src/integrations/ai_suggestion_service.py b/src/integrations/ai_suggestion_service.py index 3c0be73..2d923d5 100644 --- a/src/integrations/ai_suggestion_service.py +++ b/src/integrations/ai_suggestion_service.py @@ -390,7 +390,6 @@ class AISuggestionService: "3. 注意事项", "4. 如果问题无法解决", "请用中文回答,简洁明了", - "模拟LLM响应:", "问题描述:", "相关背景信息:", "无相关背景信息", diff --git a/src/integrations/config_manager.py b/src/integrations/config_manager.py index ddfbb0f..b7efbce 100644 --- a/src/integrations/config_manager.py +++ b/src/integrations/config_manager.py @@ -1,25 +1,24 @@ # -*- coding: utf-8 -*- """ 配置管理器 -管理飞书等外部系统的配置信息,支持持久化存储和并发访问 +从环境变量管理飞书等外部系统的配置信息 """ -import json -import os import threading import logging -from typing import Dict, Any, Optional +from typing import Dict, Any from datetime import datetime -from pathlib import Path + +from src.config.unified_config import get_config logger = logging.getLogger(__name__) class ConfigManager: - """配置管理器""" - + """配置管理器 - 从环境变量读取配置""" + _instance = None _lock = threading.Lock() - + def __new__(cls): """单例模式""" if cls._instance is None: @@ -28,200 +27,101 @@ class ConfigManager: cls._instance = super(ConfigManager, cls).__new__(cls) cls._instance._initialized = False return cls._instance - + def __init__(self): if self._initialized: return - + self._config_lock = threading.RLock() - self.config_file = Path("config/integrations_config.json") - self.config_file.parent.mkdir(exist_ok=True) - - # 默认配置 - self.default_config = { - "feishu": { - "app_id": "", - "app_secret": "", - "app_token": "", - "table_id": "", - "last_updated": None, - "status": "inactive" - }, - "system": { - "sync_limit": 10, - "ai_suggestions_enabled": True, - "auto_sync_interval": 0, # 0表示不自动同步 - "last_sync_time": None - } - } - - self._load_config() + self._unified_config = get_config() self._initialized = True - - def _load_config(self): - """加载配置文件""" - try: - if self.config_file.exists(): - with open(self.config_file, 'r', encoding='utf-8') as f: - loaded_config = json.load(f) - # 合并默认配置和加载的配置 - self.config = self._merge_configs(self.default_config, loaded_config) - else: - self.config = self.default_config.copy() - self._save_config() - logger.info("配置加载成功") - except Exception as e: - logger.error(f"配置加载失败: {e}") - self.config = self.default_config.copy() - - def _save_config(self): - """保存配置文件""" - try: - with self._config_lock: - with open(self.config_file, 'w', encoding='utf-8') as f: - json.dump(self.config, f, ensure_ascii=False, indent=2) - logger.info("配置保存成功") - except Exception as e: - logger.error(f"配置保存失败: {e}") - - def _merge_configs(self, default: Dict, loaded: Dict) -> Dict: - """合并配置,确保所有必要的键都存在""" - result = default.copy() - for key, value in loaded.items(): - if isinstance(value, dict) and key in result: - result[key] = self._merge_configs(result[key], value) - else: - result[key] = value - return result - + logger.info("配置加载成功") + def get_feishu_config(self) -> Dict[str, Any]: - """获取飞书配置""" + """获取飞书配置(从环境变量)""" with self._config_lock: - return self.config.get("feishu", {}).copy() - + feishu = self._unified_config.feishu + return { + "app_id": feishu.app_id or "", + "app_secret": feishu.app_secret or "", + "table_id": feishu.table_id or "", + "verification_token": feishu.verification_token or "", + "encrypt_key": feishu.encrypt_key or "", + "status": "active" if (feishu.app_id and feishu.app_secret) else "inactive" + } + def update_feishu_config(self, **kwargs) -> bool: - """更新飞书配置""" - try: - with self._config_lock: - feishu_config = self.config.setdefault("feishu", {}) - - # 更新配置项 - for key, value in kwargs.items(): - if key in ["app_id", "app_secret", "app_token", "table_id"]: - feishu_config[key] = value - - # 更新状态和时间戳 - feishu_config["last_updated"] = datetime.now().isoformat() - feishu_config["status"] = "active" if all([ - feishu_config.get("app_id"), - feishu_config.get("app_secret"), - feishu_config.get("app_token"), - feishu_config.get("table_id") - ]) else "inactive" - - self._save_config() - logger.info("飞书配置更新成功") - return True - except Exception as e: - logger.error(f"飞书配置更新失败: {e}") - return False - + """更新飞书配置(仅用于兼容性,实际应修改 .env 文件)""" + logger.warning("飞书配置应该在 .env 文件中修改,而不是通过 API 更新") + return False + def get_system_config(self) -> Dict[str, Any]: """获取系统配置""" with self._config_lock: - return self.config.get("system", {}).copy() - + return { + "sync_limit": 10, + "ai_suggestions_enabled": True, + "auto_sync_interval": 0, + "last_sync_time": None + } + def update_system_config(self, **kwargs) -> bool: - """更新系统配置""" - try: - with self._config_lock: - system_config = self.config.setdefault("system", {}) - - for key, value in kwargs.items(): - if key in ["sync_limit", "ai_suggestions_enabled", "auto_sync_interval"]: - system_config[key] = value - - self._save_config() - logger.info("系统配置更新成功") - return True - except Exception as e: - logger.error(f"系统配置更新失败: {e}") - return False - + """更新系统配置(仅用于兼容性)""" + logger.warning("系统配置应该在 .env 文件中修改") + return False + def test_feishu_connection(self) -> Dict[str, Any]: """测试飞书连接""" try: from .feishu_client import FeishuClient - + feishu_config = self.get_feishu_config() if not all([feishu_config.get("app_id"), feishu_config.get("app_secret")]): return {"success": False, "error": "飞书配置不完整"} - + client = FeishuClient(feishu_config["app_id"], feishu_config["app_secret"]) - + # 测试获取访问令牌 token = client._get_access_token() if token: return {"success": True, "message": "飞书连接正常"} else: return {"success": False, "error": "无法获取访问令牌"} - + except Exception as e: logger.error(f"飞书连接测试失败: {e}") return {"success": False, "error": str(e)} - + def get_config_summary(self) -> Dict[str, Any]: """获取配置摘要""" with self._config_lock: - feishu_config = self.config.get("feishu", {}) - system_config = self.config.get("system", {}) - + feishu_config = self.get_feishu_config() + system_config = self.get_system_config() + return { "feishu": { "app_id": feishu_config.get("app_id", ""), - "app_token": feishu_config.get("app_token", ""), "table_id": feishu_config.get("table_id", ""), "status": feishu_config.get("status", "inactive"), - "last_updated": feishu_config.get("last_updated"), "app_secret": "***" if feishu_config.get("app_secret") else "" }, - "system": { - "sync_limit": system_config.get("sync_limit", 10), - "ai_suggestions_enabled": system_config.get("ai_suggestions_enabled", True), - "auto_sync_interval": system_config.get("auto_sync_interval", 0), - "last_sync_time": system_config.get("last_sync_time") - } + "system": system_config } - + def reset_config(self) -> bool: - """重置配置为默认值""" - try: - with self._config_lock: - self.config = self.default_config.copy() - self._save_config() - logger.info("配置重置成功") - return True - except Exception as e: - logger.error(f"配置重置失败: {e}") - return False - + """重置配置(不再支持)""" + logger.warning("配置现在从 .env 文件读取,无法通过 API 重置") + return False + def export_config(self) -> str: - """导出配置(用于备份)""" - with self._config_lock: - return json.dumps(self.config, ensure_ascii=False, indent=2) - + """导出配置(仅返回摘要)""" + import json + return json.dumps(self.get_config_summary(), ensure_ascii=False, indent=2) + def import_config(self, config_json: str) -> bool: - """导入配置(用于恢复)""" - try: - imported_config = json.loads(config_json) - with self._config_lock: - self.config = self._merge_configs(self.default_config, imported_config) - self._save_config() - logger.info("配置导入成功") - return True - except Exception as e: - logger.error(f"配置导入失败: {e}") - return False + """导入配置(不再支持)""" + logger.warning("配置现在从 .env 文件读取,无法通过 API 导入") + return False # 全局配置管理器实例 config_manager = ConfigManager() diff --git a/src/integrations/feishu_service.py b/src/integrations/feishu_service.py new file mode 100644 index 0000000..fae079c --- /dev/null +++ b/src/integrations/feishu_service.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +""" +飞书服务 +处理与飞书开放平台API的交互 +""" +import logging +import json +import time +from typing import Dict, Any, Optional +import requests + +from src.config.unified_config import get_config + +logger = logging.getLogger(__name__) + +class FeishuService: + """封装飞书API调用""" + + BASE_URL = "https://open.feishu.cn/open-apis" + + def __init__(self): + """从环境变量初始化飞书服务""" + config = get_config() + self.app_id = config.feishu.app_id + self.app_secret = config.feishu.app_secret + self._tenant_access_token = None + self._token_expiry_time = 0 + + def _get_tenant_access_token(self) -> Optional[str]: + """获取或刷新tenant_access_token""" + if self._tenant_access_token and time.time() < self._token_expiry_time: + return self._tenant_access_token + + url = f"{self.BASE_URL}/auth/v3/tenant_access_token/internal" + payload = { + "app_id": self.app_id, + "app_secret": self.app_secret + } + headers = {'Content-Type': 'application/json'} + + try: + response = requests.post(url, json=payload, headers=headers) + response.raise_for_status() + data = response.json() + + if data.get("code") == 0: + self._tenant_access_token = data.get("tenant_access_token") + # 提前10分钟过期,以防网络延迟 + self._token_expiry_time = time.time() + data.get("expire", 7200) - 600 + logger.info("成功获取 tenant_access_token") + return self._tenant_access_token + else: + logger.error(f"获取 tenant_access_token 失败: {data.get('msg')}") + return None + except requests.RequestException as e: + logger.error(f"请求 tenant_access_token 时发生网络错误: {e}") + return None + + def send_message(self, receive_id: str, content: str, receive_id_type: str = "chat_id") -> bool: + """ + 发送消息到飞书 + :param receive_id: 接收消息的ID (chat_id, user_id, email等) + :param content: 消息内容 (JSON字符串) + :param receive_id_type: 接收ID的类型 + """ + token = self._get_tenant_access_token() + if not token: + return False + + url = f"{self.BASE_URL}/im/v1/messages?receive_id_type={receive_id_type}" + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json; charset=utf-8", + } + payload = { + "receive_id": receive_id, + "msg_type": "text", + "content": json.dumps({"text": content}), + } + + try: + response = requests.post(url, json=payload, headers=headers) + response.raise_for_status() + data = response.json() + + if data.get("code") == 0: + logger.info(f"成功发送消息到 {receive_id}") + return True + else: + logger.error(f"发送消息失败: {data.get('msg')}") + return False + except requests.RequestException as e: + logger.error(f"发送消息时发生网络错误: {e}") + return False + + def reply_to_message(self, message_id: str, content: str) -> bool: + """ + 回复指定消息 + :param message_id: 要回复的消息ID + :param content: 回复内容 (普通文本) + """ + token = self._get_tenant_access_token() + if not token: + return False + + url = f"{self.BASE_URL}/im/v1/messages/{message_id}/reply" + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json; charset=utf-8", + } + # 飞书API要求content是一个JSON字符串 + payload = { + "msg_type": "text", + "content": json.dumps({"text": content}), + } + + try: + response = requests.post(url, json=payload, headers=headers) + response.raise_for_status() + data = response.json() + + if data.get("code") == 0: + logger.info(f"成功回复消息 {message_id}") + return True + else: + logger.error(f"回复消息 {message_id} 失败: {data.get('msg')}") + return False + except requests.RequestException as e: + logger.error(f"回复消息时发生网络错误: {e}") + return False diff --git a/src/knowledge_base/__init__.py b/src/knowledge_base/__init__.py deleted file mode 100644 index d8696a1..0000000 --- a/src/knowledge_base/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# 知识库模块 diff --git a/src/knowledge_base/__pycache__/__init__.cpython-311.pyc b/src/knowledge_base/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 912cf7a..0000000 Binary files a/src/knowledge_base/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/knowledge_base/__pycache__/knowledge_manager.cpython-310.pyc b/src/knowledge_base/__pycache__/knowledge_manager.cpython-310.pyc new file mode 100644 index 0000000..dfc5062 Binary files /dev/null and b/src/knowledge_base/__pycache__/knowledge_manager.cpython-310.pyc differ diff --git a/src/knowledge_base/__pycache__/knowledge_manager.cpython-311.pyc b/src/knowledge_base/__pycache__/knowledge_manager.cpython-311.pyc deleted file mode 100644 index f52c75c..0000000 Binary files a/src/knowledge_base/__pycache__/knowledge_manager.cpython-311.pyc and /dev/null differ diff --git a/src/knowledge_base/knowledge_manager.py b/src/knowledge_base/knowledge_manager.py index 0c7c9d6..16f4da2 100644 --- a/src/knowledge_base/knowledge_manager.py +++ b/src/knowledge_base/knowledge_manager.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) class KnowledgeManager: """知识库管理器""" - + def __init__(self): self.llm_client = QwenClient() self.vectorizer = TfidfVectorizer( @@ -24,22 +24,25 @@ class KnowledgeManager: ngram_range=(1, 2) ) self._load_vectorizer() - + def _load_vectorizer(self): """加载向量化器""" try: + logger.info("正在初始化知识库向量化器...") with db_manager.get_session() as session: entries = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ).all() - + if entries: texts = [entry.question + " " + entry.answer for entry in entries] self.vectorizer.fit(texts) - logger.info(f"向量化器加载成功,包含 {len(entries)} 个条目") + logger.info(f"向量化器加载成功: 共处理 {len(entries)} 个知识条目") + else: + logger.warning("知识库尚无活跃条目,向量化器将保持空状态") except Exception as e: logger.error(f"加载向量化器失败: {e}") - + def learn_from_work_order(self, work_order_id: int) -> bool: """从工单中学习知识""" try: @@ -47,19 +50,22 @@ class KnowledgeManager: work_order = session.query(WorkOrder).filter( WorkOrder.id == work_order_id ).first() - + if not work_order or not work_order.resolution: return False - + # 提取问题和答案 question = work_order.title + " " + work_order.description answer = work_order.resolution - + + logger.info(f"开始从工单 {work_order_id} 学习知识: 标题长度={len(work_order.title)}, 描述长度={len(work_order.description)}") + # 检查是否已存在相似条目 existing_entry = self._find_similar_entry(question, session) - + if existing_entry: # 更新现有条目 + logger.info(f"检测到相似知识条目 (ID: {existing_entry.id}),执行更新操作") existing_entry.answer = answer existing_entry.usage_count += 1 existing_entry.updated_at = datetime.now() @@ -67,6 +73,7 @@ class KnowledgeManager: existing_entry.confidence_score = work_order.satisfaction_score else: # 创建新条目 + logger.info(f"未发现相似条目,正在为工单 {work_order_id} 创建新知识点") new_entry = KnowledgeEntry( question=question, answer=answer, @@ -75,42 +82,47 @@ class KnowledgeManager: usage_count=1 ) session.add(new_entry) - + session.commit() logger.info(f"从工单 {work_order_id} 学习知识成功") return True - + except Exception as e: logger.error(f"从工单学习知识失败: {e}") return False - + def _find_similar_entry(self, question: str, session) -> Optional[KnowledgeEntry]: """查找相似的知识库条目""" try: entries = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ).all() - + if not entries: return None - + # 计算相似度 texts = [entry.question for entry in entries] question_vector = self.vectorizer.transform([question]) entry_vectors = self.vectorizer.transform(texts) - + similarities = cosine_similarity(question_vector, entry_vectors)[0] max_similarity_idx = np.argmax(similarities) - - if similarities[max_similarity_idx] > 0.8: # 相似度阈值 + max_score = similarities[max_similarity_idx] + + logger.debug(f"相似度检索完成: 最高分值={max_score:.4f}, 目标ID={entries[max_similarity_idx].id if entries else 'N/A'}") + + if max_score > 0.8: # 相似度阈值 + logger.info(f"匹配成功: 相似度 {max_score:.4f} 超过阈值 0.8") return entries[max_similarity_idx] - + + logger.debug(f"匹配跳过: 相似度 {max_score:.4f} 未达到阈值 0.8") return None - + except Exception as e: logger.error(f"查找相似条目失败: {e}") return None - + def search_knowledge(self, query: str, top_k: int = 3, verified_only: bool = True) -> List[Dict[str, Any]]: """搜索知识库""" try: @@ -119,20 +131,20 @@ class KnowledgeManager: query_filter = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ) - + # 如果只搜索已验证的知识库 if verified_only: query_filter = query_filter.filter(KnowledgeEntry.is_verified == True) - + entries = query_filter.all() # 若已验证为空,则回退到全部活跃条目 if not entries and verified_only: entries = session.query(KnowledgeEntry).filter(KnowledgeEntry.is_active == True).all() - + if not entries: logger.warning("知识库中没有活跃条目") return [] - + # 如果查询为空,返回所有条目 if not query.strip(): logger.info("查询为空,返回所有条目") @@ -146,18 +158,18 @@ class KnowledgeManager: "usage_count": entry.usage_count, "is_verified": entry.is_verified } for entry in entries[:top_k]] - + # 使用简化的关键词匹配搜索 q = query.strip().lower() results = [] - + for entry in entries: # 组合问题和答案进行搜索 search_text = (entry.question + " " + entry.answer).lower() - + # 计算匹配分数 score = 0.0 - + # 完全匹配 if q in search_text: score = 1.0 @@ -165,16 +177,16 @@ class KnowledgeManager: # 分词匹配 query_words = q.split() text_words = search_text.split() - + # 计算单词匹配度 matched_words = 0 for word in query_words: if word in text_words: matched_words += 1 - + if matched_words > 0: score = matched_words / len(query_words) * 0.8 - + # 如果分数大于0,添加到结果中 if score > 0: results.append({ @@ -187,18 +199,18 @@ class KnowledgeManager: "usage_count": entry.usage_count, "is_verified": entry.is_verified }) - + # 按相似度排序并返回top_k个结果 results.sort(key=lambda x: x['similarity_score'], reverse=True) results = results[:top_k] - + logger.info(f"搜索查询 '{query}' 返回 {len(results)} 个结果") return results - + except Exception as e: logger.error(f"搜索知识库失败: {e}") return [] - + def add_knowledge_entry( self, question: str, @@ -220,17 +232,17 @@ class KnowledgeManager: ) session.add(entry) session.commit() - + # 重新训练向量化器 self._load_vectorizer() - + logger.info(f"添加知识库条目成功: {question[:50]}...") return True - + except Exception as e: logger.error(f"添加知识库条目失败: {e}") return False - + def update_knowledge_entry( self, entry_id: int, @@ -245,10 +257,10 @@ class KnowledgeManager: entry = session.query(KnowledgeEntry).filter( KnowledgeEntry.id == entry_id ).first() - + if not entry: return False - + if question: entry.question = question if answer: @@ -257,34 +269,34 @@ class KnowledgeManager: entry.category = category if confidence_score is not None: entry.confidence_score = confidence_score - + entry.updated_at = datetime.now() session.commit() - + logger.info(f"更新知识库条目成功: {entry_id}") return True - + except Exception as e: logger.error(f"更新知识库条目失败: {e}") return False - + def get_knowledge_entries(self, page: int = 1, per_page: int = 10) -> Dict[str, Any]: """获取知识库条目(分页)""" try: with db_manager.get_session() as session: # 计算偏移量 offset = (page - 1) * per_page - + # 获取总数 total = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ).count() - + # 获取分页数据 entries = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ).order_by(KnowledgeEntry.created_at.desc()).offset(offset).limit(per_page).all() - + # 转换为字典格式 knowledge_list = [] for entry in entries: @@ -298,7 +310,7 @@ class KnowledgeManager: "created_at": entry.created_at.isoformat() if entry.created_at else None, "is_verified": getattr(entry, 'is_verified', False) # 添加验证状态 }) - + return { "knowledge": knowledge_list, "total": total, @@ -309,7 +321,7 @@ class KnowledgeManager: except Exception as e: logger.error(f"获取知识库条目失败: {e}") return {"knowledge": [], "total": 0, "page": 1, "per_page": per_page, "total_pages": 0} - + def verify_knowledge_entry(self, entry_id: int, verified_by: str = "admin") -> bool: """验证知识库条目""" try: @@ -317,22 +329,22 @@ class KnowledgeManager: entry = session.query(KnowledgeEntry).filter( KnowledgeEntry.id == entry_id ).first() - + if not entry: return False - + entry.is_verified = True entry.verified_by = verified_by entry.verified_at = datetime.now() - + session.commit() logger.info(f"知识库条目验证成功: {entry_id}") return True - + except Exception as e: logger.error(f"验证知识库条目失败: {e}") return False - + def unverify_knowledge_entry(self, entry_id: int) -> bool: """取消验证知识库条目""" try: @@ -340,22 +352,22 @@ class KnowledgeManager: entry = session.query(KnowledgeEntry).filter( KnowledgeEntry.id == entry_id ).first() - + if not entry: return False - + entry.is_verified = False entry.verified_by = None entry.verified_at = None - + session.commit() logger.info(f"知识库条目取消验证成功: {entry_id}") return True - + except Exception as e: logger.error(f"取消验证知识库条目失败: {e}") return False - + def delete_knowledge_entry(self, entry_id: int) -> bool: """删除知识库条目(软删除)""" try: @@ -363,28 +375,28 @@ class KnowledgeManager: entry = session.query(KnowledgeEntry).filter( KnowledgeEntry.id == entry_id ).first() - + if not entry: logger.warning(f"知识库条目不存在: {entry_id}") return False - + entry.is_active = False session.commit() - + # 重新训练向量化器(如果还有活跃条目) try: self._load_vectorizer() except Exception as vectorizer_error: logger.warning(f"重新加载向量化器失败: {vectorizer_error}") # 即使向量化器加载失败,删除操作仍然成功 - + logger.info(f"删除知识库条目成功: {entry_id}") return True - + except Exception as e: logger.error(f"删除知识库条目失败: {e}") return False - + def get_knowledge_stats(self) -> Dict[str, Any]: """获取知识库统计信息""" try: @@ -393,7 +405,7 @@ class KnowledgeManager: active_entries = session.query(KnowledgeEntry).filter( KnowledgeEntry.is_active == True ).count() - + # 按类别统计 category_stats = session.query( KnowledgeEntry.category, @@ -401,19 +413,19 @@ class KnowledgeManager: KnowledgeEntry.category == KnowledgeEntry.category ).count() ).group_by(KnowledgeEntry.category).all() - + # 平均置信度 avg_confidence = session.query( func.avg(KnowledgeEntry.confidence_score) ).scalar() or 0.0 - + return { "total_entries": total_entries, "active_entries": active_entries, "category_distribution": dict(category_stats), "average_confidence": float(avg_confidence) } - + except Exception as e: logger.error(f"获取知识库统计失败: {e}") return {} @@ -428,7 +440,7 @@ class KnowledgeManager: ).update({ "usage_count": KnowledgeEntry.usage_count + 1, "updated_at": datetime.now() - }) + }, synchronize_session=False) session.commit() logger.info(f"成功更新 {len(entry_ids)} 个知识库条目的使用次数") @@ -436,4 +448,59 @@ class KnowledgeManager: except Exception as e: logger.error(f"更新知识库使用次数失败: {e}") - return False \ No newline at end of file + return False + + def get_knowledge_paginated(self, page: int = 1, per_page: int = 10, category_filter: str = '', verified_filter: str = '') -> Dict[str, Any]: + """获取知识库条目(分页和过滤)""" + try: + with db_manager.get_session() as session: + query = session.query(KnowledgeEntry).filter(KnowledgeEntry.is_active == True) + + if category_filter: + query = query.filter(KnowledgeEntry.category == category_filter) + if verified_filter: + if verified_filter == 'true': + query = query.filter(KnowledgeEntry.is_verified == True) + elif verified_filter == 'false': + query = query.filter(KnowledgeEntry.is_verified == False) + + query = query.order_by(KnowledgeEntry.created_at.desc()) + + total = query.count() + + knowledge_entries = query.offset((page - 1) * per_page).limit(per_page).all() + + knowledge_data = [] + for entry in knowledge_entries: + knowledge_data.append({ + 'id': entry.id, + 'question': entry.question, + 'answer': entry.answer, + 'category': entry.category, + 'confidence_score': entry.confidence_score, + 'usage_count': entry.usage_count, + 'is_verified': entry.is_verified, + 'is_active': entry.is_active, + 'created_at': entry.created_at.isoformat() if entry.created_at else None, + 'updated_at': entry.updated_at.isoformat() if entry.updated_at else None + }) + + total_pages = (total + per_page - 1) // per_page + + return { + 'knowledge': knowledge_data, + 'page': page, + 'per_page': per_page, + 'total': total, + 'total_pages': total_pages + } + except Exception as e: + logger.error(f"获取分页知识库失败: {e}") + # 返回一个空的结构以避免在调用方出现错误 + return { + 'knowledge': [], + 'page': page, + 'per_page': per_page, + 'total': 0, + 'total_pages': 0 + } diff --git a/src/main.py b/src/main.py index 0f555f5..d929db5 100644 --- a/src/main.py +++ b/src/main.py @@ -7,7 +7,7 @@ from datetime import datetime, timedelta # 添加项目根目录到Python路径 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from src.config.config import Config +from src.config.unified_config import get_config from src.utils.helpers import setup_logging from src.core.database import db_manager from src.core.llm_client import QwenClient @@ -26,7 +26,8 @@ class TSPAssistant: def __init__(self): # 设置日志 - setup_logging(Config.LOG_LEVEL, Config.LOG_FILE) + config = get_config() + setup_logging(config.server.log_level, "logs/tsp_assistant.log") self.logger = logging.getLogger(__name__) # 初始化各个管理器 diff --git a/src/utils/__pycache__/__init__.cpython-310.pyc b/src/utils/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..7b8a251 Binary files /dev/null and b/src/utils/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/utils/__pycache__/__init__.cpython-311.pyc b/src/utils/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 512823c..0000000 Binary files a/src/utils/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/utils/__pycache__/encoding_helper.cpython-311.pyc b/src/utils/__pycache__/encoding_helper.cpython-311.pyc deleted file mode 100644 index f818bc6..0000000 Binary files a/src/utils/__pycache__/encoding_helper.cpython-311.pyc and /dev/null differ diff --git a/src/utils/__pycache__/helpers.cpython-310.pyc b/src/utils/__pycache__/helpers.cpython-310.pyc new file mode 100644 index 0000000..c818347 Binary files /dev/null and b/src/utils/__pycache__/helpers.cpython-310.pyc differ diff --git a/src/utils/__pycache__/helpers.cpython-311.pyc b/src/utils/__pycache__/helpers.cpython-311.pyc deleted file mode 100644 index f55b2a2..0000000 Binary files a/src/utils/__pycache__/helpers.cpython-311.pyc and /dev/null differ diff --git a/src/utils/__pycache__/semantic_similarity.cpython-310.pyc b/src/utils/__pycache__/semantic_similarity.cpython-310.pyc new file mode 100644 index 0000000..0acf19f Binary files /dev/null and b/src/utils/__pycache__/semantic_similarity.cpython-310.pyc differ diff --git a/src/utils/__pycache__/semantic_similarity.cpython-311.pyc b/src/utils/__pycache__/semantic_similarity.cpython-311.pyc deleted file mode 100644 index 7ad4cdd..0000000 Binary files a/src/utils/__pycache__/semantic_similarity.cpython-311.pyc and /dev/null differ diff --git a/src/vehicle/__pycache__/__init__.cpython-310.pyc b/src/vehicle/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..f5936c4 Binary files /dev/null and b/src/vehicle/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/vehicle/__pycache__/__init__.cpython-311.pyc b/src/vehicle/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index e533729..0000000 Binary files a/src/vehicle/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/vehicle/__pycache__/vehicle_data_manager.cpython-310.pyc b/src/vehicle/__pycache__/vehicle_data_manager.cpython-310.pyc new file mode 100644 index 0000000..c51b1ac Binary files /dev/null and b/src/vehicle/__pycache__/vehicle_data_manager.cpython-310.pyc differ diff --git a/src/vehicle/__pycache__/vehicle_data_manager.cpython-311.pyc b/src/vehicle/__pycache__/vehicle_data_manager.cpython-311.pyc deleted file mode 100644 index 256e94c..0000000 Binary files a/src/vehicle/__pycache__/vehicle_data_manager.cpython-311.pyc and /dev/null differ diff --git a/src/web/__pycache__/app.cpython-310.pyc b/src/web/__pycache__/app.cpython-310.pyc index 79054f0..783ff31 100644 Binary files a/src/web/__pycache__/app.cpython-310.pyc and b/src/web/__pycache__/app.cpython-310.pyc differ diff --git a/src/web/__pycache__/app.cpython-311.pyc b/src/web/__pycache__/app.cpython-311.pyc deleted file mode 100644 index aad9318..0000000 Binary files a/src/web/__pycache__/app.cpython-311.pyc and /dev/null differ diff --git a/src/web/__pycache__/app.cpython-312.pyc b/src/web/__pycache__/app.cpython-312.pyc deleted file mode 100644 index 6a5e76b..0000000 Binary files a/src/web/__pycache__/app.cpython-312.pyc and /dev/null differ diff --git a/src/web/__pycache__/error_handlers.cpython-310.pyc b/src/web/__pycache__/error_handlers.cpython-310.pyc index 03eb5bf..3aa3fe0 100644 Binary files a/src/web/__pycache__/error_handlers.cpython-310.pyc and b/src/web/__pycache__/error_handlers.cpython-310.pyc differ diff --git a/src/web/__pycache__/error_handlers.cpython-311.pyc b/src/web/__pycache__/error_handlers.cpython-311.pyc deleted file mode 100644 index 5a9aeec..0000000 Binary files a/src/web/__pycache__/error_handlers.cpython-311.pyc and /dev/null differ diff --git a/src/web/__pycache__/service_manager.cpython-310.pyc b/src/web/__pycache__/service_manager.cpython-310.pyc index c4a49f9..84640d8 100644 Binary files a/src/web/__pycache__/service_manager.cpython-310.pyc and b/src/web/__pycache__/service_manager.cpython-310.pyc differ diff --git a/src/web/__pycache__/service_manager.cpython-311.pyc b/src/web/__pycache__/service_manager.cpython-311.pyc deleted file mode 100644 index 0ecaca8..0000000 Binary files a/src/web/__pycache__/service_manager.cpython-311.pyc and /dev/null differ diff --git a/src/web/__pycache__/websocket_server.cpython-310.pyc b/src/web/__pycache__/websocket_server.cpython-310.pyc index 0637bcf..b2a5d54 100644 Binary files a/src/web/__pycache__/websocket_server.cpython-310.pyc and b/src/web/__pycache__/websocket_server.cpython-310.pyc differ diff --git a/src/web/__pycache__/websocket_server.cpython-311.pyc b/src/web/__pycache__/websocket_server.cpython-311.pyc deleted file mode 100644 index 5ee3132..0000000 Binary files a/src/web/__pycache__/websocket_server.cpython-311.pyc and /dev/null differ diff --git a/src/web/app.py b/src/web/app.py index e5ba5c5..ea6d5f7 100644 --- a/src/web/app.py +++ b/src/web/app.py @@ -14,8 +14,8 @@ from typing import Dict, Any from flask import Flask, render_template, request, jsonify, send_from_directory, make_response from flask_cors import CORS -# 添加项目根目录到Python路径 -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from src.config.unified_config import get_config + # 导入核心模块 from src.core.database import db_manager @@ -37,6 +37,8 @@ from src.web.blueprints.agent import agent_bp from src.web.blueprints.vehicle import vehicle_bp from src.web.blueprints.analytics import analytics_bp from src.web.blueprints.test import test_bp +from src.web.blueprints.feishu_bot import feishu_bot_bp + # 配置日志 logger = logging.getLogger(__name__) @@ -79,6 +81,8 @@ app.register_blueprint(agent_bp) app.register_blueprint(vehicle_bp) app.register_blueprint(analytics_bp) app.register_blueprint(test_bp) +app.register_blueprint(feishu_bot_bp) + # 页面路由 @app.route('/') @@ -235,8 +239,9 @@ def get_active_sessions(): # 飞书同步功能已合并到主页面,不再需要单独的路由 if __name__ == '__main__': - import time - app.config['START_TIME'] = time.time() - app.config['SERVER_PORT'] = 5000 - app.config['WEBSOCKET_PORT'] = 8765 - app.run(debug=True, host='0.0.0.0', port=5000) + config = get_config() + app.run( + debug=config.server.debug, + host=config.server.host, + port=config.server.port + ) diff --git a/src/web/blueprints/README.md b/src/web/blueprints/README.md index 11ca73c..4e48a1f 100644 --- a/src/web/blueprints/README.md +++ b/src/web/blueprints/README.md @@ -94,7 +94,6 @@ src/web/ ├── app.py # 主应用文件 (674行) ├── app_backup.py # 原文件备份 ├── blueprints/ # 蓝图目录 -│ ├── __init__.py │ ├── alerts.py # 预警管理 │ ├── workorders.py # 工单管理 │ ├── conversations.py # 对话管理 diff --git a/src/web/blueprints/__pycache__/__init__.cpython-310.pyc b/src/web/blueprints/__pycache__/__init__.cpython-310.pyc index 6177792..bd9183e 100644 Binary files a/src/web/blueprints/__pycache__/__init__.cpython-310.pyc and b/src/web/blueprints/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/__init__.cpython-311.pyc b/src/web/blueprints/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 1ef659d..0000000 Binary files a/src/web/blueprints/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/agent.cpython-310.pyc b/src/web/blueprints/__pycache__/agent.cpython-310.pyc new file mode 100644 index 0000000..9ec7ac6 Binary files /dev/null and b/src/web/blueprints/__pycache__/agent.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/agent.cpython-311.pyc b/src/web/blueprints/__pycache__/agent.cpython-311.pyc deleted file mode 100644 index cd33b86..0000000 Binary files a/src/web/blueprints/__pycache__/agent.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/alerts.cpython-310.pyc b/src/web/blueprints/__pycache__/alerts.cpython-310.pyc index e1b9c7c..f283a01 100644 Binary files a/src/web/blueprints/__pycache__/alerts.cpython-310.pyc and b/src/web/blueprints/__pycache__/alerts.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/alerts.cpython-311.pyc b/src/web/blueprints/__pycache__/alerts.cpython-311.pyc deleted file mode 100644 index 0221f3c..0000000 Binary files a/src/web/blueprints/__pycache__/alerts.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/analytics.cpython-310.pyc b/src/web/blueprints/__pycache__/analytics.cpython-310.pyc new file mode 100644 index 0000000..ac01832 Binary files /dev/null and b/src/web/blueprints/__pycache__/analytics.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/analytics.cpython-311.pyc b/src/web/blueprints/__pycache__/analytics.cpython-311.pyc deleted file mode 100644 index 26b2a9f..0000000 Binary files a/src/web/blueprints/__pycache__/analytics.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/auth.cpython-310.pyc b/src/web/blueprints/__pycache__/auth.cpython-310.pyc new file mode 100644 index 0000000..e4e92dd Binary files /dev/null and b/src/web/blueprints/__pycache__/auth.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/auth.cpython-311.pyc b/src/web/blueprints/__pycache__/auth.cpython-311.pyc deleted file mode 100644 index 82f538a..0000000 Binary files a/src/web/blueprints/__pycache__/auth.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/conversations.cpython-310.pyc b/src/web/blueprints/__pycache__/conversations.cpython-310.pyc index 0da6427..beac059 100644 Binary files a/src/web/blueprints/__pycache__/conversations.cpython-310.pyc and b/src/web/blueprints/__pycache__/conversations.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/conversations.cpython-311.pyc b/src/web/blueprints/__pycache__/conversations.cpython-311.pyc deleted file mode 100644 index c2c0958..0000000 Binary files a/src/web/blueprints/__pycache__/conversations.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/core.cpython-310.pyc b/src/web/blueprints/__pycache__/core.cpython-310.pyc index 6d9c12d..e69b926 100644 Binary files a/src/web/blueprints/__pycache__/core.cpython-310.pyc and b/src/web/blueprints/__pycache__/core.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/core.cpython-311.pyc b/src/web/blueprints/__pycache__/core.cpython-311.pyc deleted file mode 100644 index 425a3f4..0000000 Binary files a/src/web/blueprints/__pycache__/core.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/feishu_bot.cpython-310.pyc b/src/web/blueprints/__pycache__/feishu_bot.cpython-310.pyc new file mode 100644 index 0000000..f0a64c7 Binary files /dev/null and b/src/web/blueprints/__pycache__/feishu_bot.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/feishu_sync.cpython-310.pyc b/src/web/blueprints/__pycache__/feishu_sync.cpython-310.pyc index 63b3e94..f17f330 100644 Binary files a/src/web/blueprints/__pycache__/feishu_sync.cpython-310.pyc and b/src/web/blueprints/__pycache__/feishu_sync.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/feishu_sync.cpython-311.pyc b/src/web/blueprints/__pycache__/feishu_sync.cpython-311.pyc deleted file mode 100644 index 474f194..0000000 Binary files a/src/web/blueprints/__pycache__/feishu_sync.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/knowledge.cpython-310.pyc b/src/web/blueprints/__pycache__/knowledge.cpython-310.pyc index 75ec708..c4d3d03 100644 Binary files a/src/web/blueprints/__pycache__/knowledge.cpython-310.pyc and b/src/web/blueprints/__pycache__/knowledge.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/knowledge.cpython-311.pyc b/src/web/blueprints/__pycache__/knowledge.cpython-311.pyc deleted file mode 100644 index ba694ac..0000000 Binary files a/src/web/blueprints/__pycache__/knowledge.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/monitoring.cpython-310.pyc b/src/web/blueprints/__pycache__/monitoring.cpython-310.pyc index 8ecf963..2d70bd6 100644 Binary files a/src/web/blueprints/__pycache__/monitoring.cpython-310.pyc and b/src/web/blueprints/__pycache__/monitoring.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/monitoring.cpython-311.pyc b/src/web/blueprints/__pycache__/monitoring.cpython-311.pyc deleted file mode 100644 index c065ad5..0000000 Binary files a/src/web/blueprints/__pycache__/monitoring.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/system.cpython-310.pyc b/src/web/blueprints/__pycache__/system.cpython-310.pyc index 438b599..b8d7ace 100644 Binary files a/src/web/blueprints/__pycache__/system.cpython-310.pyc and b/src/web/blueprints/__pycache__/system.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/system.cpython-311.pyc b/src/web/blueprints/__pycache__/system.cpython-311.pyc deleted file mode 100644 index a9db02a..0000000 Binary files a/src/web/blueprints/__pycache__/system.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/test.cpython-310.pyc b/src/web/blueprints/__pycache__/test.cpython-310.pyc new file mode 100644 index 0000000..34317d3 Binary files /dev/null and b/src/web/blueprints/__pycache__/test.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/test.cpython-311.pyc b/src/web/blueprints/__pycache__/test.cpython-311.pyc deleted file mode 100644 index 4aff382..0000000 Binary files a/src/web/blueprints/__pycache__/test.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/vehicle.cpython-310.pyc b/src/web/blueprints/__pycache__/vehicle.cpython-310.pyc new file mode 100644 index 0000000..cceb31f Binary files /dev/null and b/src/web/blueprints/__pycache__/vehicle.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/vehicle.cpython-311.pyc b/src/web/blueprints/__pycache__/vehicle.cpython-311.pyc deleted file mode 100644 index 448d250..0000000 Binary files a/src/web/blueprints/__pycache__/vehicle.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/__pycache__/workorders.cpython-310.pyc b/src/web/blueprints/__pycache__/workorders.cpython-310.pyc index ee79512..6b6015e 100644 Binary files a/src/web/blueprints/__pycache__/workorders.cpython-310.pyc and b/src/web/blueprints/__pycache__/workorders.cpython-310.pyc differ diff --git a/src/web/blueprints/__pycache__/workorders.cpython-311.pyc b/src/web/blueprints/__pycache__/workorders.cpython-311.pyc deleted file mode 100644 index 758f803..0000000 Binary files a/src/web/blueprints/__pycache__/workorders.cpython-311.pyc and /dev/null differ diff --git a/src/web/blueprints/feishu_bot.py b/src/web/blueprints/feishu_bot.py new file mode 100644 index 0000000..c94b33e --- /dev/null +++ b/src/web/blueprints/feishu_bot.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +""" +飞书机器人蓝图 +处理来自飞书机器人的事件回调 +""" +import logging +import json +import threading +from flask import Blueprint, request, jsonify +from src.integrations.feishu_service import FeishuService +from src.web.service_manager import service_manager + +# 初始化日志 +logger = logging.getLogger(__name__) + +# 创建蓝图 +feishu_bot_bp = Blueprint('feishu_bot', __name__, url_prefix='/api/feishu/bot') + +# 在模块级别实例化飞书服务,以便复用 +# 注意:这假设配置在启动时是固定的。如果配置可热更新,则需要调整。 +feishu_service = FeishuService() + +def _process_message_in_background(app_context, event_data: dict): + """ + 在后台线程中处理消息,避免阻塞飞书的回调请求。 + """ + with app_context: + try: + # 1. 解析事件数据 + message_id = event_data['event']['message']['message_id'] + chat_id = event_data['event']['message']['chat_id'] + # 内容是一个JSON字符串,需要再次解析 + content_json = json.loads(event_data['event']['message']['content']) + text_content = content_json.get('text', '').strip() + + logger.info(f"[Feishu Bot] 后台开始处理消息ID: {message_id}, 内容: '{text_content}'") + + # 2. 移除@机器人的部分 + # 飞书的@消息格式通常是 "@机器人名 实际内容" + if event_data['event']['message'].get('mentions'): + for mention in event_data['event']['message']['mentions']: + # mention['key']是@内容,例如"@_user_1" + # mention['name']是显示的名字 + bot_mention_text = f"@{mention['name']}" + if text_content.startswith(bot_mention_text): + text_content = text_content[len(bot_mention_text):].strip() + break + + if not text_content: + logger.warning(f"[Feishu Bot] 移除@后内容为空,不处理。消息ID: {message_id}") + return + + logger.info(f"[Feishu Bot] 清理后的消息内容: '{text_content}'") + + # 3. 调用核心服务获取回复 + assistant = service_manager.get_assistant() + # 注意:process_message_agent 是一个异步方法,需要处理 + # 在同步线程中运行异步方法 + import asyncio + try: + loop = asyncio.get_running_loop() + except RuntimeError: # 'RuntimeError: There is no current event loop...' + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + # 调用对话服务 + logger.info(f"[Feishu Bot] 调用Agent服务处理消息...") + response_data = loop.run_until_complete( + assistant.process_message_agent(message=text_content, user_id=f"feishu_{chat_id}") + ) + logger.info(f"[Feishu Bot] Agent服务返回结果: {response_data}") + + # 4. 提取回复并发送 + reply_text = response_data.get("message", "抱歉,我暂时无法回答这个问题。") + if isinstance(reply_text, dict): # 有时候返回的可能是字典 + reply_text = reply_text.get('content', str(reply_text)) + + logger.info(f"[Feishu Bot] 准备发送回复到飞书: '{reply_text}'") + success = feishu_service.reply_to_message(message_id, reply_text) + + if success: + logger.info(f"[Feishu Bot] 成功回复消息到飞书。消息ID: {message_id}") + else: + logger.error(f"[Feishu Bot] 回复消息到飞书失败。消息ID: {message_id}") + + except Exception as e: + logger.error(f"[Feishu Bot] 后台处理消息时发生严重错误: {e}", exc_info=True) + + +@feishu_bot_bp.route('/event', methods=['POST']) +def handle_feishu_event(): + """ + 接收并处理飞书事件回调 + """ + # 1. 解析请求 + data = request.json + logger.info(f"[Feishu Bot] 收到飞书事件回调:\n{json.dumps(data, indent=2)}") + + # 2. 安全校验 (如果配置了) + # 此处可以添加Verification Token的校验逻辑 + # headers = request.headers + # ... + + # 3. 处理URL验证挑战 + if data and data.get("type") == "url_verification": + challenge = data.get("challenge", "") + logger.info(f"[Feishu Bot] 收到URL验证请求,返回challenge: {challenge}") + return jsonify({"challenge": challenge}) + + # 4. 处理事件回调 + if data and data.get("header", {}).get("event_type") == "im.message.receive_v1": + # 立即响应飞书,防止超时重试 + threading.Thread( + target=_process_message_in_background, + args=(request.environ['werkzeug.request'].environ['flask.app'].app_context(), data) + ).start() + + logger.info("[Feishu Bot] 已将消息处理任务推送到后台线程,并立即响应200 OK") + return jsonify({"status": "processing"}) + + # 5. 对于其他未知事件,也返回成功,避免飞书重试 + logger.warning(f"[Feishu Bot] 收到未知类型的事件: {data.get('header', {}).get('event_type')}") + return jsonify({"status": "ignored"}) diff --git a/src/web/blueprints/knowledge.py b/src/web/blueprints/knowledge.py index 5f64775..a828797 100644 --- a/src/web/blueprints/knowledge.py +++ b/src/web/blueprints/knowledge.py @@ -7,203 +7,135 @@ import os import tempfile import uuid +import logging from flask import Blueprint, request, jsonify +from src.agent_assistant import TSPAgentAssistant from src.web.service_manager import service_manager from src.web.error_handlers import handle_api_errors, create_error_response, create_success_response knowledge_bp = Blueprint('knowledge', __name__, url_prefix='/api/knowledge') +_agent_assistant = None + def get_agent_assistant(): """获取Agent助手实例(懒加载)""" global _agent_assistant - if '_agent_assistant' not in globals(): + if _agent_assistant is None: _agent_assistant = TSPAgentAssistant() return _agent_assistant @knowledge_bp.route('') +@handle_api_errors def get_knowledge(): """获取知识库列表(分页)""" - try: - # 获取分页参数 - page = request.args.get('page', 1, type=int) - per_page = request.args.get('per_page', 10, type=int) - category_filter = request.args.get('category', '') - verified_filter = request.args.get('verified', '') - - # 从数据库获取知识库数据 - from src.core.database import db_manager - from src.core.models import KnowledgeEntry - - with db_manager.get_session() as session: - # 构建查询 - query = session.query(KnowledgeEntry).filter(KnowledgeEntry.is_active == True) - - # 应用过滤器 - if category_filter: - query = query.filter(KnowledgeEntry.category == category_filter) - if verified_filter: - if verified_filter == 'true': - query = query.filter(KnowledgeEntry.is_verified == True) - elif verified_filter == 'false': - query = query.filter(KnowledgeEntry.is_verified == False) - - # 按创建时间倒序排列 - query = query.order_by(KnowledgeEntry.created_at.desc()) - - # 计算总数 - total = query.count() - - # 分页查询 - knowledge_entries = query.offset((page - 1) * per_page).limit(per_page).all() - - # 转换为字典 - knowledge_data = [] - for entry in knowledge_entries: - knowledge_data.append({ - 'id': entry.id, - 'question': entry.question, - 'answer': entry.answer, - 'category': entry.category, - 'confidence_score': entry.confidence_score, - 'usage_count': entry.usage_count, - 'is_verified': entry.is_verified, - 'is_active': entry.is_active, - 'created_at': entry.created_at.isoformat() if entry.created_at else None, - 'updated_at': entry.updated_at.isoformat() if entry.updated_at else None - }) - - # 计算分页信息 - total_pages = (total + per_page - 1) // per_page - - return jsonify({ - 'knowledge': knowledge_data, - 'page': page, - 'per_page': per_page, - 'total': total, - 'total_pages': total_pages - }) - - except Exception as e: - return jsonify({"error": str(e)}), 500 + page = request.args.get('page', 1, type=int) + per_page = request.args.get('per_page', 10, type=int) + category_filter = request.args.get('category', '') + verified_filter = request.args.get('verified', '') + + result = service_manager.get_assistant().knowledge_manager.get_knowledge_paginated( + page=page, + per_page=per_page, + category_filter=category_filter, + verified_filter=verified_filter + ) + return jsonify(result) @knowledge_bp.route('/search') +@handle_api_errors def search_knowledge(): """搜索知识库""" - try: - query = request.args.get('q', '') - import logging - logger = logging.getLogger(__name__) - logger.info(f"搜索查询: '{query}'") - - if not query.strip(): - logger.info("查询为空,返回空结果") - return jsonify([]) - - # 直接调用知识库管理器的搜索方法 - assistant = service_manager.get_assistant() - results = assistant.knowledge_manager.search_knowledge(query, top_k=5) - logger.info(f"搜索结果数量: {len(results)}") - return jsonify(results) - except Exception as e: - import logging - logger = logging.getLogger(__name__) - logger.error(f"搜索知识库失败: {e}") - return jsonify({"error": str(e)}), 500 + query = request.args.get('q', '') + logger = logging.getLogger(__name__) + logger.info(f"搜索查询: '{query}'") + + if not query.strip(): + logger.info("查询为空,返回空结果") + return jsonify([]) + + assistant = service_manager.get_assistant() + results = assistant.knowledge_manager.search_knowledge(query, top_k=5) + logger.info(f"搜索结果数量: {len(results)}") + return jsonify(results) @knowledge_bp.route('', methods=['POST']) +@handle_api_errors def add_knowledge(): """添加知识库条目""" - try: - data = request.get_json() - success = service_manager.get_assistant().knowledge_manager.add_knowledge_entry( - question=data['question'], - answer=data['answer'], - category=data['category'], - confidence_score=data['confidence_score'] - ) - return jsonify({"success": success, "message": "知识添加成功" if success else "添加失败"}) - except Exception as e: - return jsonify({"error": str(e)}), 500 + data = request.get_json() + success = service_manager.get_assistant().knowledge_manager.add_knowledge_entry( + question=data['question'], + answer=data['answer'], + category=data['category'], + confidence_score=data.get('confidence_score', 0.8) + ) + if success: + return create_success_response("知识添加成功") + else: + return create_error_response("添加失败", 500) @knowledge_bp.route('/stats') +@handle_api_errors def get_knowledge_stats(): """获取知识库统计""" - try: - stats = service_manager.get_assistant().knowledge_manager.get_knowledge_stats() - return jsonify(stats) - except Exception as e: - return jsonify({"error": str(e)}), 500 + stats = service_manager.get_assistant().knowledge_manager.get_knowledge_stats() + return jsonify(stats) @knowledge_bp.route('/upload', methods=['POST']) +@handle_api_errors def upload_knowledge_file(): """上传文件并生成知识库""" + if 'file' not in request.files: + return create_error_response("没有上传文件", 400) + + file = request.files['file'] + if file.filename == '': + return create_error_response("没有选择文件", 400) + + temp_filename = f"upload_{uuid.uuid4()}{os.path.splitext(file.filename)[1]}" + temp_path = os.path.join(tempfile.gettempdir(), temp_filename) + try: - if 'file' not in request.files: - return jsonify({"error": "没有上传文件"}), 400 - - file = request.files['file'] - if file.filename == '': - return jsonify({"error": "没有选择文件"}), 400 - - # 保存文件到临时目录 - import tempfile - import os - import uuid - - # 创建唯一的临时文件名 - temp_filename = f"upload_{uuid.uuid4()}{os.path.splitext(file.filename)[1]}" - temp_path = os.path.join(tempfile.gettempdir(), temp_filename) - + file.save(temp_path) + assistant = get_agent_assistant() + result = assistant.process_file_to_knowledge(temp_path, file.filename) + return jsonify(result) + finally: try: - # 保存文件 - file.save(temp_path) - - # 使用Agent助手处理文件 - result = get_agent_assistant().process_file_to_knowledge(temp_path, file.filename) - - return jsonify(result) - - finally: - # 确保删除临时文件 - try: - if os.path.exists(temp_path): - os.unlink(temp_path) - except Exception as cleanup_error: - import logging - logger = logging.getLogger(__name__) - logger.warning(f"清理临时文件失败: {cleanup_error}") - - except Exception as e: - import logging - logger = logging.getLogger(__name__) - logger.error(f"文件上传处理失败: {e}") - return jsonify({"error": str(e)}), 500 + if os.path.exists(temp_path): + os.unlink(temp_path) + except Exception as cleanup_error: + logger = logging.getLogger(__name__) + logger.warning(f"清理临时文件失败: {cleanup_error}") @knowledge_bp.route('/delete/', methods=['DELETE']) +@handle_api_errors def delete_knowledge(knowledge_id): """删除知识库条目""" - try: - success = service_manager.get_assistant().knowledge_manager.delete_knowledge_entry(knowledge_id) - return jsonify({"success": success, "message": "删除成功" if success else "删除失败"}) - except Exception as e: - return jsonify({"error": str(e)}), 500 + success = service_manager.get_assistant().knowledge_manager.delete_knowledge_entry(knowledge_id) + if success: + return create_success_response("删除成功") + else: + return create_error_response("删除失败", 404) @knowledge_bp.route('/verify/', methods=['POST']) +@handle_api_errors def verify_knowledge(knowledge_id): """验证知识库条目""" - try: - data = request.get_json() or {} - verified_by = data.get('verified_by', 'admin') - success = service_manager.get_assistant().knowledge_manager.verify_knowledge_entry(knowledge_id, verified_by) - return jsonify({"success": success, "message": "验证成功" if success else "验证失败"}) - except Exception as e: - return jsonify({"error": str(e)}), 500 + data = request.get_json() or {} + verified_by = data.get('verified_by', 'admin') + success = service_manager.get_assistant().knowledge_manager.verify_knowledge_entry(knowledge_id, verified_by) + if success: + return create_success_response("验证成功") + else: + return create_error_response("验证失败", 404) @knowledge_bp.route('/unverify/', methods=['POST']) +@handle_api_errors def unverify_knowledge(knowledge_id): """取消验证知识库条目""" - try: - success = service_manager.get_assistant().knowledge_manager.unverify_knowledge_entry(knowledge_id) - return jsonify({"success": success, "message": "取消验证成功" if success else "取消验证失败"}) - except Exception as e: - return jsonify({"error": str(e)}), 500 + success = service_manager.get_assistant().knowledge_manager.unverify_knowledge_entry(knowledge_id) + if success: + return create_success_response("取消验证成功") + else: + return create_error_response("取消验证失败", 404) diff --git a/src/web/blueprints/workorders.py b/src/web/blueprints/workorders.py index 5b4f9f8..6f52bda 100644 --- a/src/web/blueprints/workorders.py +++ b/src/web/blueprints/workorders.py @@ -16,27 +16,8 @@ from sqlalchemy import text logger = logging.getLogger(__name__) -# 简化的AI准确率配置类 -class SimpleAIAccuracyConfig: - """简化的AI准确率配置""" - def __init__(self): - self.auto_approve_threshold = 0.95 - self.use_human_resolution_threshold = 0.90 - self.manual_review_threshold = 0.80 - self.ai_suggestion_confidence = 0.95 - self.human_resolution_confidence = 0.90 - - def should_auto_approve(self, similarity: float) -> bool: - return similarity >= self.auto_approve_threshold - - def should_use_human_resolution(self, similarity: float) -> bool: - return similarity < self.use_human_resolution_threshold - - def get_confidence_score(self, similarity: float, use_human: bool = False) -> float: - if use_human: - return self.human_resolution_confidence - else: - return max(similarity, self.ai_suggestion_confidence) +# 移除SimpleAIAccuracyConfig,直接从统一配置获取 +from src.config.unified_config import get_config from src.main import TSPAssistant from src.core.database import db_manager @@ -397,14 +378,14 @@ def save_workorder_human_resolution(workorder_id): rec.ai_similarity = sim # 使用简化的配置 - config = SimpleAIAccuracyConfig() - + config = get_config().ai_accuracy + # 自动审批条件 - approved = config.should_auto_approve(sim) + approved = sim >= config.auto_approve_threshold rec.approved = approved - + # 记录使用人工描述入库的标记(当AI准确率低于阈值时) - use_human_resolution = config.should_use_human_resolution(sim) + use_human_resolution = sim < config.use_human_resolution_threshold rec.use_human_resolution = use_human_resolution session.commit() @@ -431,19 +412,19 @@ def approve_workorder_to_knowledge(workorder_id): return jsonify({"error": "未找到工单建议记录"}), 400 # 使用简化的配置 - config = SimpleAIAccuracyConfig() - + config = get_config().ai_accuracy + # 确定使用哪个内容入库 if rec.use_human_resolution and rec.human_resolution: # AI准确率低于阈值,使用人工描述入库 answer_content = rec.human_resolution - confidence_score = config.get_confidence_score(rec.ai_similarity or 0, use_human=True) + confidence_score = config.human_resolution_confidence verified_by = 'human_resolution' logger.info(f"工单 {workorder_id} 使用人工描述入库,AI相似度: {rec.ai_similarity:.4f}") elif rec.approved and rec.ai_suggestion: # AI准确率≥阈值,使用AI建议入库 answer_content = rec.ai_suggestion - confidence_score = config.get_confidence_score(rec.ai_similarity or 0, use_human=False) + confidence_score = max(rec.ai_similarity or 0, config.ai_suggestion_confidence) verified_by = 'auto_approve' logger.info(f"工单 {workorder_id} 使用AI建议入库,相似度: {rec.ai_similarity:.4f}") else: diff --git a/src/web/service_manager.py b/src/web/service_manager.py index 84d552c..50fb162 100644 --- a/src/web/service_manager.py +++ b/src/web/service_manager.py @@ -21,7 +21,7 @@ class ServiceManager: if service_name not in self._services: try: self._services[service_name] = factory_func() - logger.info(f"服务 {service_name} 已初始化") + logger.debug(f"服务 {service_name} 已初始化") except Exception as e: logger.error(f"初始化服务 {service_name} 失败: {e}") raise diff --git a/src/web/websocket_server.py b/src/web/websocket_server.py index 6314f22..63b7763 100644 --- a/src/web/websocket_server.py +++ b/src/web/websocket_server.py @@ -90,8 +90,21 @@ class WebSocketServer: await self._send_error(websocket, "缺少必要参数", message_id) return + # 获取客户端IP + ip_address = None + try: + # websockets 15.x 获取 remote_address 的方式 + ip_address = websocket.remote_address[0] if websocket.remote_address else None + except Exception: + pass + # 处理消息 - result = self.chat_manager.process_message(session_id, message) + result = self.chat_manager.process_message( + session_id, + message, + ip_address=ip_address, + invocation_method="websocket" + ) response = { "type": "message_response", @@ -210,21 +223,9 @@ class WebSocketServer: await websocket.send(json.dumps(response, ensure_ascii=False)) - async def handle_client(self, websocket: WebSocketServerProtocol, path: str): - """处理客户端连接""" - # 检查连接头 - headers = websocket.request_headers - connection = headers.get("Connection", "").lower() - - # 处理不同的连接头格式 - if "upgrade" not in connection and "keep-alive" in connection: - logger.warning(f"收到非标准连接头: {connection}") - # 对于keep-alive连接头,我们仍然接受连接 - elif "upgrade" not in connection: - logger.warning(f"连接头不包含upgrade: {connection}") - await websocket.close(code=1002, reason="Invalid connection header") - return - + async def handle_client(self, websocket): + """处理客户端连接(兼容 websockets 15.x)""" + # websockets 15.x 版本中,handler 只接收 websocket 参数,不再有 path 参数 await self.register_client(websocket) try: @@ -238,61 +239,17 @@ class WebSocketServer: await self.unregister_client(websocket) async def start_server(self): - """启动WebSocket服务器""" + """启动WebSocket服务器(兼容 websockets 15.x)""" logger.info(f"启动WebSocket服务器: ws://{self.host}:{self.port}") - # 添加CORS支持 - async def handle_client_with_cors(websocket: WebSocketServerProtocol): - # 获取path,websockets在提供process_request时,不会将path传递给handler - path = websocket.path - # 设置CORS头 - if websocket.request_headers.get("Origin"): - # 允许跨域连接 - pass - await self.handle_client(websocket, path) - + # websockets 15.x 简化版本:直接传递处理函数 async with websockets.serve( - handle_client_with_cors, + self.handle_client, self.host, - self.port, - # 添加额外的服务器选项 - process_request=self._process_request + self.port ): await asyncio.Future() # 保持服务器运行 - def _process_request(self, path, request_headers): - """处理HTTP请求,支持CORS""" - # 检查是否是WebSocket升级请求 - # request_headers 可能是 Headers 对象或 Request 对象 - if hasattr(request_headers, 'get'): - upgrade_header = request_headers.get("Upgrade", "").lower() - elif hasattr(request_headers, 'headers'): - upgrade_header = request_headers.headers.get("Upgrade", "").lower() - else: - upgrade_header = "" - - if upgrade_header == "websocket": - return None # 允许WebSocket连接 - - # 对于非WebSocket请求,返回简单的HTML页面 - return ( - 200, - [("Content-Type", "text/html; charset=utf-8")], - b""" - - - - WebSocket Server - - -

WebSocket Server is running

-

This is a WebSocket server. Please use a WebSocket client to connect.

-

WebSocket URL: ws://localhost:8765

- - - """ - ) - def run(self): """运行服务器""" asyncio.run(self.start_server()) diff --git a/start_dashboard.py b/start_dashboard.py index b9fab09..aba4aab 100644 --- a/start_dashboard.py +++ b/start_dashboard.py @@ -13,15 +13,25 @@ from datetime import datetime # 添加项目根目录到Python路径 sys.path.append(os.path.dirname(os.path.abspath(__file__))) -def setup_logging(): - """设置日志""" + +def setup_logging(start_time: str): + """设置日志,按启动时间创建子目录""" + # 日志根目录 + log_root = "logs" + # 以启动时间命名的子目录(避免路径中的空格和冒号) + safe_start_time = start_time.replace(" ", "_").replace(":", "-") + log_dir = os.path.join(log_root, safe_start_time) + os.makedirs(log_dir, exist_ok=True) + + log_file_path = os.path.join(log_dir, "dashboard.log") + logging.basicConfig( level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[ - logging.FileHandler('logs/dashboard.log', encoding='utf-8'), - logging.StreamHandler() - ] + logging.FileHandler(log_file_path, encoding="utf-8"), + logging.StreamHandler(), + ], ) def start_websocket_server(): @@ -52,17 +62,18 @@ def main(): print("=" * 60) print("TSP智能助手 - 综合管理平台") print("=" * 60) - print(f"启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + start_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + print(f"启动时间: {start_time}") print() - # 设置日志 - setup_logging() + # 设置日志(日志目录按启动时间区分) + setup_logging(start_time) logger = logging.getLogger(__name__) try: # 检查必要目录 - os.makedirs('logs', exist_ok=True) - os.makedirs('data', exist_ok=True) + os.makedirs("logs", exist_ok=True) + os.makedirs("data", exist_ok=True) logger.info("正在启动TSP智能助手综合管理平台...") @@ -77,27 +88,32 @@ def main(): # 导入并启动Flask应用 from src.web.app import app - + from src.config.unified_config import get_config + + # 获取配置 + config = get_config() + print() print("访问地址:") - print(" 主页: http://localhost:5000") - print(" 预警管理: http://localhost:5000/alerts") - print(" 实时对话: http://localhost:5000/chat") - print(" WebSocket: ws://localhost:8765") + print(f" 主页: http://localhost:{config.server.port}") + print(f" 预警管理: http://localhost:{config.server.port}/alerts") + print(f" 实时对话: http://localhost:{config.server.port}/chat") + print(f" WebSocket: ws://localhost:{config.server.websocket_port}") print() print("按 Ctrl+C 停止服务") print("=" * 60) - + # 在单独线程中启动WebSocket服务器 websocket_thread = threading.Thread(target=start_websocket_server, daemon=True) websocket_thread.start() - + # 启动Flask应用 app.run( - debug=False, - host='0.0.0.0', - port=5000, - threaded=True + debug=config.server.debug, + host=config.server.host, + port=config.server.port, + threaded=True, + use_reloader=False # 禁用重载器,避免重复启动WebSocket服务器 ) except KeyboardInterrupt: diff --git a/test_refactor.py b/test_refactor.py deleted file mode 100644 index aae763d..0000000 --- a/test_refactor.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -测试重构后的应用 -""" - -import sys -import os - -# 添加项目路径 -sys.path.append('src') - -def test_blueprints(): - """测试蓝图注册""" - try: - from src.web.app import app - - print("✓ Flask应用导入成功") - - # 测试蓝图注册 - blueprints = list(app.blueprints.keys()) - print(f"✓ 已注册蓝图: {blueprints}") - - expected_blueprints = [ - 'alerts', 'workorders', 'conversations', 'knowledge', - 'monitoring', 'system', 'feishu_sync', 'core', 'auth', - 'agent', 'vehicle', 'analytics', 'test' - ] - - for bp in expected_blueprints: - if bp in blueprints: - print(f"✓ 蓝图 {bp} 已注册") - else: - print(f"✗ 蓝图 {bp} 未注册") - - # 测试路由 - routes = [str(rule) for rule in app.url_map.iter_rules()] - agent_routes = [r for r in routes if 'agent' in r] - vehicle_routes = [r for r in routes if 'vehicle' in r] - analytics_routes = [r for r in routes if 'analytics' in r] - - print(f"✓ Agent相关路由数量: {len(agent_routes)}") - print(f"✓ Vehicle相关路由数量: {len(vehicle_routes)}") - print(f"✓ Analytics相关路由数量: {len(analytics_routes)}") - - return True - - except Exception as e: - print(f"✗ 应用测试失败: {e}") - import traceback - traceback.print_exc() - return False - -def test_blueprint_imports(): - """测试蓝图模块导入""" - blueprints_to_test = [ - ('src.web.blueprints.agent', 'agent_bp'), - ('src.web.blueprints.vehicle', 'vehicle_bp'), - ('src.web.blueprints.analytics', 'analytics_bp'), - ('src.web.blueprints.test', 'test_bp'), - ] - - for module_name, bp_name in blueprints_to_test: - try: - module = __import__(module_name, fromlist=[bp_name]) - bp = getattr(module, bp_name) - print(f"✓ {module_name}.{bp_name} 导入成功") - except Exception as e: - print(f"✗ {module_name}.{bp_name} 导入失败: {e}") - return False - - return True - -if __name__ == '__main__': - print("开始测试重构后的应用...") - print("=" * 50) - - success = True - - print("\n1. 测试蓝图模块导入...") - success &= test_blueprint_imports() - - print("\n2. 测试Flask应用和蓝图注册...") - success &= test_blueprints() - - print("\n" + "=" * 50) - if success: - print("✓ 所有测试通过!重构成功!") - else: - print("✗ 部分测试失败,请检查代码") - sys.exit(1) diff --git a/tsp_assistant-bc.db b/tsp_assistant-bc.db deleted file mode 100644 index 7c7b2fa..0000000 Binary files a/tsp_assistant-bc.db and /dev/null differ diff --git a/tsp_assistant.db b/tsp_assistant.db index 5d14bcb..23fc918 100644 Binary files a/tsp_assistant.db and b/tsp_assistant.db differ