Compare commits
10 Commits
UAT
...
f5acb05e61
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5acb05e61 | ||
|
|
0bee1c86fc | ||
|
|
e4b76def44 | ||
|
|
bdef0f72e8 | ||
|
|
71e47b2636 | ||
|
|
18bbbe0f46 | ||
|
|
57e12facf7 | ||
|
|
6bae875b4b | ||
|
|
c3560b43fd | ||
| 2026007045 |
34
.claude/agents/doc-updater.md
Normal file
34
.claude/agents/doc-updater.md
Normal file
@@ -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<example>\\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<commentary>\\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</commentary>\\n</example>\\n<example>\\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<commentary>\\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</commentary>\\n</example>"
|
||||||
|
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.
|
||||||
31
.claude/agents/frontend-sync.md
Normal file
31
.claude/agents/frontend-sync.md
Normal file
@@ -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<example>\\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<commentary>\\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</commentary>\\n</example>\\n<example>\\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<commentary>\\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</commentary>\\n</example>"
|
||||||
|
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.
|
||||||
12
.claude/settings.local.json
Normal file
12
.claude/settings.local.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)",
|
||||||
|
"Bash(git push:*)",
|
||||||
|
"Bash(git config:*)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
92
.claude/skills/ai-metrics-report/SKILL.md
Normal file
92
.claude/skills/ai-metrics-report/SKILL.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
Name: ai-metrics-report
|
||||||
|
Description: 基于现有监控与分析模块,生成一份最近一段时间的 AI 成功率、错误率与 Token 成本的综合报告,用于评估 TSP 智能助手的整体表现。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「AI 指标报告助手」,技能名为 **ai-metrics-report**。
|
||||||
|
|
||||||
|
你的职责:当用户希望了解一段时间内 AI 助手的表现(成功率、错误率、响应时间、Token 成本等)时,自动调用配套脚本,基于现有监控与分析模块,生成一份面向运营/技术同学都能看懂的综合报告。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候使用 ai-metrics-report)
|
||||||
|
|
||||||
|
当用户有类似需求时,应激活本 Skill,例如:
|
||||||
|
|
||||||
|
- 「帮我出一份最近 7 天 AI 调用表现的报告」
|
||||||
|
- 「看一下最近 AI 的成功率和错误率」
|
||||||
|
- 「近一周 Token 消耗和成本情况如何」
|
||||||
|
- 「AI 现在效果怎么样,有没有明显波动」
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
1. 从项目根目录执行脚本 `scripts/ai_metrics_report.py`;
|
||||||
|
2. 读取脚本输出的结构化指标数据(JSON 或结构化文本);
|
||||||
|
3. 将关键指标用自然语言转述,并做简要分析(例如是否达标、是否有波动);
|
||||||
|
4. 如发现明显异常(高错误率 / 成本突增 / 成功率显著下降),给出 1~3 条排查或优化建议。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、脚本调用规范
|
||||||
|
|
||||||
|
从项目根目录执行命令(可传入天数参数,默认 7 天):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python .claude/skills/ai-metrics-report/scripts/ai_metrics_report.py --days 7
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本行为约定:
|
||||||
|
|
||||||
|
- 尝试复用现有模块:
|
||||||
|
- `src.analytics.ai_success_monitor.AISuccessMonitor`(如提供聚合接口则优先使用);
|
||||||
|
- `src.analytics.token_monitor.TokenMonitor.get_system_token_stats(days=...)`。
|
||||||
|
- 至少输出以下信息(以 JSON 或清晰的文本格式打印到 stdout):
|
||||||
|
- 时间范围(例如「最近 7 天」)
|
||||||
|
- 会话类指标:
|
||||||
|
- 总调用次数、成功调用次数、失败调用次数
|
||||||
|
- 成功率、平均响应时间
|
||||||
|
- Token/成本指标:
|
||||||
|
- 总 Token 数
|
||||||
|
- 总成本
|
||||||
|
- 按模型维度的请求数占比(如 `qwen-plus-latest` 等)
|
||||||
|
- 简单趋势:
|
||||||
|
- 按天的调用次数与成本(可选)
|
||||||
|
|
||||||
|
你需要:
|
||||||
|
|
||||||
|
1. 运行脚本并捕获输出;
|
||||||
|
2. 解析其中关键字段;
|
||||||
|
3. 用 5~10 句中文自然语言,对用户生成一份「运营视角」的口头报告。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、对用户的输出规范
|
||||||
|
|
||||||
|
当成功执行 `ai-metrics-report` 时,应返回如下结构的信息:
|
||||||
|
|
||||||
|
1. **时间范围与总体结论**
|
||||||
|
- 例如:「最近 7 天,AI 总调用 1234 次,成功率约 96%,整体表现稳定。」
|
||||||
|
2. **关键指标分项**
|
||||||
|
- 成功率 / 错误率、平均响应时间;
|
||||||
|
- 总 Token 使用量与总成本;
|
||||||
|
- 主力模型(如 `qwen-plus-latest`)的占比;
|
||||||
|
3. **趋势与风险提醒**
|
||||||
|
- 若发现某几天错误率或成本异常升高,应指出并提醒。
|
||||||
|
4. **建议(可选)**
|
||||||
|
- 如「可以考虑优化 prompt 降低平均 Token」「错误集中在某业务接口,建议重点排查」等。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 直接把原始 JSON 或 Python repr 整段贴给用户;
|
||||||
|
- 输出过多技术细节,优先用业务/运营语言阐述。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、反模式与边界
|
||||||
|
|
||||||
|
- 如脚本运行失败,应告诉用户「ai-metrics-report 脚本运行失败」,简要给出错误原因;
|
||||||
|
- 不要直接访问数据库执行复杂 SQL,优先复用已有封装好的监控/统计接口;
|
||||||
|
- 不要修改任何生产配置或监控阈值,仅进行只读分析和报告。
|
||||||
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
AI 指标报告脚本
|
||||||
|
|
||||||
|
聚合最近一段时间的 AI 使用与成本指标,供 ai-metrics-report Skill 调用。
|
||||||
|
当前版本主要复用 TokenMonitor 的系统统计能力。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def add_project_root_to_path():
|
||||||
|
# 假定脚本位于 .claude/skills/ai-metrics-report/scripts/ 下
|
||||||
|
script_path = Path(__file__).resolve()
|
||||||
|
project_root = script_path.parents[4]
|
||||||
|
if str(project_root) not in sys.path:
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Generate AI metrics report.")
|
||||||
|
parser.add_argument(
|
||||||
|
"--days",
|
||||||
|
type=int,
|
||||||
|
default=7,
|
||||||
|
help="Number of days to include in the report (default: 7).",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
add_project_root_to_path()
|
||||||
|
|
||||||
|
from src.analytics.token_monitor import TokenMonitor
|
||||||
|
|
||||||
|
monitor = TokenMonitor()
|
||||||
|
stats = monitor.get_system_token_stats(days=args.days) or {}
|
||||||
|
|
||||||
|
print(f"=== AI 指标报告(最近 {args.days} 天) ===\n")
|
||||||
|
|
||||||
|
total_tokens = stats.get("total_tokens", 0)
|
||||||
|
total_cost = stats.get("total_cost", 0.0)
|
||||||
|
total_requests = stats.get("total_requests", 0)
|
||||||
|
successful_requests = stats.get("successful_requests", 0)
|
||||||
|
failed_requests = stats.get("failed_requests", 0)
|
||||||
|
success_rate = stats.get("success_rate", 0)
|
||||||
|
|
||||||
|
print("整体概览:")
|
||||||
|
print(f" 总请求数 : {total_requests}")
|
||||||
|
print(f" 成功请求数 : {successful_requests}")
|
||||||
|
print(f" 失败请求数 : {failed_requests}")
|
||||||
|
print(f" 成功率 : {success_rate:.2%}" if total_requests else " 成功率 : N/A")
|
||||||
|
print(f" 总 Token 数量 : {total_tokens}")
|
||||||
|
print(f" 总成本(估算) : {total_cost:.4f} 元")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 模型使用分布
|
||||||
|
model_usage = stats.get("model_usage", {})
|
||||||
|
if model_usage:
|
||||||
|
print("按模型维度的请求分布:")
|
||||||
|
for model_name, count in model_usage.items():
|
||||||
|
pct = (count / total_requests) * 100 if total_requests else 0
|
||||||
|
print(f" - {model_name}: {count} 次 ({pct:.1f}%)")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 按日期的成本趋势(如有)
|
||||||
|
daily_usage = stats.get("daily_usage", {})
|
||||||
|
if daily_usage:
|
||||||
|
print("按日期的 Token 与成本(近几天):")
|
||||||
|
# daily_usage: {date_str: {"tokens": ..., "cost": ...}}
|
||||||
|
for date_str in sorted(daily_usage.keys()):
|
||||||
|
day_data = daily_usage[date_str]
|
||||||
|
tokens = day_data.get("tokens", 0)
|
||||||
|
cost = day_data.get("cost", 0.0)
|
||||||
|
print(f" {date_str}: tokens={tokens}, cost={cost:.4f} 元")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("提示:")
|
||||||
|
print(" - 成本与成功率仅基于 TokenMonitor 收集的调用记录进行估算;")
|
||||||
|
print(" - 如需更细粒度的会话质量指标,可结合 analytics 模块或自定义报表。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
82
.claude/skills/config-audit/SKILL.md
Normal file
82
.claude/skills/config-audit/SKILL.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
Name: config-audit
|
||||||
|
Description: 检查 TSP 智能助手当前环境配置是否完整可用,包括数据库、LLM、服务端口等关键配置,并输出人类可读的健康检查报告。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「配置健康检查助手」,技能名为 **config-audit**。
|
||||||
|
|
||||||
|
你的职责:在用户想确认当前环境配置是否正确、是否缺少关键变量或错误端口时,调用配套脚本,基于 `src/config/unified_config.py` 与 `.env`/环境变量,输出清晰的配置健康检查报告。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候使用 config-audit)
|
||||||
|
|
||||||
|
当用户有类似需求时,应激活本 Skill,例如:
|
||||||
|
|
||||||
|
- 「帮我检查一下配置有没有问题」
|
||||||
|
- 「现在这个环境的数据库/LLM 配置正常吗」
|
||||||
|
- 「我改了 .env,帮我看下有没有缺的」
|
||||||
|
- 「启动报配置错误,帮我检查 config」
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
1. 从项目根目录执行脚本 `scripts/config_audit.py`。
|
||||||
|
2. 读取并理解输出的检查结果(包括成功与警告/错误)。
|
||||||
|
3. 将关键结论用自然语言总结给用户,并提出简单修复建议。
|
||||||
|
4. 避免泄露敏感值(如完整 URL、API Key),仅报告是否存在与格式是否看起来合理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、脚本调用规范
|
||||||
|
|
||||||
|
从项目根目录执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python .claude/skills/config-audit/scripts/config_audit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本行为约定:
|
||||||
|
|
||||||
|
- 尝试导入 `src.config.unified_config.get_config`。
|
||||||
|
- 调用 `get_config()`:
|
||||||
|
- 若成功,说明必需的配置大体齐全;
|
||||||
|
- 若抛出异常(如缺少 `DATABASE_URL`),捕获异常并报告。
|
||||||
|
- 对关键配置字段进行检查(不打印敏感具体值):
|
||||||
|
- 数据库:是否配置 `DATABASE_URL`,能否看起来是有效的 URL。
|
||||||
|
- LLM:`LLM_API_KEY` 是否存在,`LLM_PROVIDER` / `LLM_MODEL` 是否有值。
|
||||||
|
- 服务:`SERVER_PORT`、`WEBSOCKET_PORT` 是否在合理范围(例如 1–65535),是否冲突。
|
||||||
|
- 飞书与 AI 准确率配置:如有配置则检查字段完整性,如未配置则给出提示。
|
||||||
|
- 最终打印一份「健康检查报告」,按模块(database / llm / server / feishu / ai_accuracy)分段展示。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、对用户的输出规范
|
||||||
|
|
||||||
|
当成功执行 `config-audit` 时,你应该向用户返回类似结构的信息:
|
||||||
|
|
||||||
|
1. **总体结论**(一句话)
|
||||||
|
- 例如:「当前环境配置基本健康,仅存在 LLM API Key 未配置的警告。」
|
||||||
|
2. **按模块总结**
|
||||||
|
- 数据库配置:是否存在、看起来是否合理(不展示完整 URL)。
|
||||||
|
- LLM 配置:是否配置了 provider/model/key,未配置时的影响。
|
||||||
|
- 服务端口:当前 HTTP/WebSocket 端口及是否在合理范围。
|
||||||
|
- 其他模块(飞书、AI 准确率):若有明显问题则简要说明。
|
||||||
|
3. **建议**
|
||||||
|
- 对每个有问题的模块,给出 1~2 条修改 `.env` 或环境变量的建议。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 直接打印完整的敏感信息(如 `DATABASE_URL`、`LLM_API_KEY` 值);
|
||||||
|
- 输出过多的 Python Traceback,优先用自然语言解释。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、反模式与边界
|
||||||
|
|
||||||
|
- 如导入 `src.config.unified_config` 失败,或脚本无法运行:
|
||||||
|
- 明确告诉用户「config-audit 脚本运行失败」,并简述原因。
|
||||||
|
- 不要修改 `.env` 或环境变量,仅进行只读检查和报告。
|
||||||
|
- 避免主观猜测真实密码/API Key 内容,只报告「存在 / 缺失 / 格式异常」。
|
||||||
|
|
||||||
127
.claude/skills/config-audit/scripts/config_audit.py
Normal file
127
.claude/skills/config-audit/scripts/config_audit.py
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
配置健康检查脚本
|
||||||
|
|
||||||
|
基于 src.config.unified_config 对当前环境配置进行简单体检,
|
||||||
|
输出人类可读的检查结果,供 config-audit Skill 调用。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def add_project_root_to_path():
|
||||||
|
# 假定脚本位于 .claude/skills/config-audit/scripts/ 下
|
||||||
|
script_path = Path(__file__).resolve()
|
||||||
|
project_root = script_path.parents[4] # 回到项目根目录
|
||||||
|
if str(project_root) not in sys.path:
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
add_project_root_to_path()
|
||||||
|
|
||||||
|
print("=== TSP Assistant 配置健康检查 ===\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
from src.config.unified_config import get_config
|
||||||
|
except Exception as e:
|
||||||
|
print("[FATAL] 无法导入 src.config.unified_config.get_config:")
|
||||||
|
print(f" 错误:{e}")
|
||||||
|
print("\n请检查 Python 路径与项目结构。")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
cfg = get_config()
|
||||||
|
except Exception as e:
|
||||||
|
print("[FATAL] get_config() 调用失败,可能缺少关键环境变量:")
|
||||||
|
print(f" 错误:{e}")
|
||||||
|
print("\n请检查 .env / 环境变量是否包含 DATABASE_URL 等必需项。")
|
||||||
|
return
|
||||||
|
|
||||||
|
problems = []
|
||||||
|
|
||||||
|
# Database
|
||||||
|
print("---- 数据库配置 (database) ----")
|
||||||
|
db_url = os.getenv("DATABASE_URL", "")
|
||||||
|
if not db_url:
|
||||||
|
print(" [ERROR] 未设置 DATABASE_URL,无法连接数据库。")
|
||||||
|
problems.append("缺少 DATABASE_URL")
|
||||||
|
else:
|
||||||
|
# 不打印完整 URL,只提示前缀
|
||||||
|
prefix = db_url.split("://")[0] if "://" in db_url else "未知协议"
|
||||||
|
print(f" [OK] 已配置 DATABASE_URL(协议前缀:{prefix}://...)")
|
||||||
|
|
||||||
|
# LLM
|
||||||
|
print("\n---- LLM 配置 (llm) ----")
|
||||||
|
llm_api_key = os.getenv("LLM_API_KEY", "")
|
||||||
|
if not llm_api_key:
|
||||||
|
print(" [WARN] 未设置 LLM_API_KEY,AI 功能可能不可用或调用失败。")
|
||||||
|
problems.append("缺少 LLM_API_KEY")
|
||||||
|
else:
|
||||||
|
print(" [OK] 已配置 LLM_API_KEY(具体值已隐藏)。")
|
||||||
|
|
||||||
|
provider = os.getenv("LLM_PROVIDER", cfg.llm.provider if hasattr(cfg, "llm") else "")
|
||||||
|
model = os.getenv("LLM_MODEL", cfg.llm.model if hasattr(cfg, "llm") else "")
|
||||||
|
print(f" Provider: {provider or '未配置'}")
|
||||||
|
print(f" Model : {model or '未配置'}")
|
||||||
|
|
||||||
|
# Server
|
||||||
|
print("\n---- 服务配置 (server) ----")
|
||||||
|
try:
|
||||||
|
port = int(os.getenv("SERVER_PORT", cfg.server.port))
|
||||||
|
ws_port = int(os.getenv("WEBSOCKET_PORT", cfg.server.websocket_port))
|
||||||
|
except Exception:
|
||||||
|
port = cfg.server.port
|
||||||
|
ws_port = cfg.server.websocket_port
|
||||||
|
|
||||||
|
def _check_port(p: int, name: str):
|
||||||
|
if not (1 <= p <= 65535):
|
||||||
|
problems.append(f"{name} 端口不在 1-65535 范围内")
|
||||||
|
return f"[ERROR] {name} 端口 {p} 非法(应在 1-65535 范围内)。"
|
||||||
|
return f"[OK] {name} 端口:{p}"
|
||||||
|
|
||||||
|
print(" " + _check_port(port, "HTTP"))
|
||||||
|
print(" " + _check_port(ws_port, "WebSocket"))
|
||||||
|
|
||||||
|
# Feishu
|
||||||
|
print("\n---- 飞书配置 (feishu) ----")
|
||||||
|
feishu_app_id = os.getenv("FEISHU_APP_ID", "")
|
||||||
|
feishu_app_secret = os.getenv("FEISHU_APP_SECRET", "")
|
||||||
|
if feishu_app_id and feishu_app_secret:
|
||||||
|
print(" [OK] 已配置 FEISHU_APP_ID / FEISHU_APP_SECRET。")
|
||||||
|
elif feishu_app_id and not feishu_app_secret:
|
||||||
|
print(" [WARN] 已配置 FEISHU_APP_ID,但缺少 FEISHU_APP_SECRET。")
|
||||||
|
problems.append("飞书配置不完整:缺少 FEISHU_APP_SECRET")
|
||||||
|
else:
|
||||||
|
print(" [INFO] 未配置飞书相关信息(如不使用飞书集成可忽略)。")
|
||||||
|
|
||||||
|
# AI Accuracy
|
||||||
|
print("\n---- AI 准确率配置 (ai_accuracy) ----")
|
||||||
|
# 使用 cfg.ai_accuracy 中的默认或 env 覆盖值
|
||||||
|
try:
|
||||||
|
aa = cfg.ai_accuracy
|
||||||
|
print(
|
||||||
|
f" auto_approve_threshold: {aa.auto_approve_threshold}, "
|
||||||
|
f"manual_review_threshold: {aa.manual_review_threshold}"
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
print(" [INFO] 无法读取 AI 准确率配置,使用默认值。")
|
||||||
|
|
||||||
|
# 总结
|
||||||
|
print("\n=== 检查总结 ===")
|
||||||
|
if not problems:
|
||||||
|
print(" [OK] 当前配置整体健康,未发现明显问题。")
|
||||||
|
else:
|
||||||
|
print(" 以下问题需要关注:")
|
||||||
|
for p in problems:
|
||||||
|
print(f" - {p}")
|
||||||
|
|
||||||
|
print("\n 建议:根据提示检查 .env 或部署环境变量,并重新运行 config-audit 以确认问题是否已解决。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
241
.claude/skills/gitupdate/SKILL.md
Normal file
241
.claude/skills/gitupdate/SKILL.md
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
---
|
||||||
|
Name: gitupdate
|
||||||
|
Description: 在对代码仓库进行较大范围修改后,自动检测变更范围,执行 git add / commit / push,并向用户汇报本次提交的摘要和推送结果。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「自动 Git 提交与推送助手」,技能名为 **gitupdate**。
|
||||||
|
|
||||||
|
你的职责:在对项目进行 **较大范围代码变更** 后,**自动** 将变更提交到 Git 仓库并推送远程,减少人工操作,同时保证安全、可追踪。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候激活 gitupdate)
|
||||||
|
|
||||||
|
当本次会话中,你对代码做了满足以下任一条件的修改时,应自动考虑激活本 Skill:
|
||||||
|
|
||||||
|
- 修改的文件数 **≥ 3**,或
|
||||||
|
- 单个文件改动行数 **≥ 50 行**,或
|
||||||
|
- 用户在对话中明确表达「这次改动比较大」「重构」「重写某个模块」「请帮我一起提交」「记得帮我提交 git」等需求。
|
||||||
|
|
||||||
|
如果改动很小(例如只改一两个小 bug、几行配置),可以不自动提交,除非用户明确要求你提交。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
激活 `gitupdate` 后,严格按以下顺序执行:
|
||||||
|
|
||||||
|
1. 确认当前目录为 Git 仓库
|
||||||
|
2. 查看并总结本次变更内容
|
||||||
|
3. 可选:运行测试(如果存在测试命令)
|
||||||
|
4. 将变更加入暂存区(git add)
|
||||||
|
5. 自动生成规范化的 commit message
|
||||||
|
6. 执行 git commit
|
||||||
|
7. 检测并执行 git push
|
||||||
|
8. 向用户汇报结果(简短、清晰)
|
||||||
|
|
||||||
|
每一步都需要有清晰的异常处理与用户反馈。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、详细步骤与命令规范
|
||||||
|
|
||||||
|
### 1. 确认当前目录为 Git 仓库
|
||||||
|
|
||||||
|
- 执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git rev-parse --is-inside-work-tree
|
||||||
|
```
|
||||||
|
|
||||||
|
- 若返回非 0,或输出不是 `true`:
|
||||||
|
- 向用户说明:「当前目录不是 Git 仓库,gitupdate 自动提交流程已跳过」。
|
||||||
|
- 立即终止本 Skill 后续步骤。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. 查看并总结变更
|
||||||
|
|
||||||
|
- 执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status
|
||||||
|
git diff
|
||||||
|
git diff --cached || true
|
||||||
|
```
|
||||||
|
|
||||||
|
- 阅读差异内容,尝试用 **1~3 句话** 总结本次变更,例如:
|
||||||
|
- 「重构了配置模块,迁移到 unified_config」
|
||||||
|
- 「新增 AI 调用监控(ai_success_monitor / token_monitor)」
|
||||||
|
- 「修复对话历史中的 Redis 缓存逻辑」
|
||||||
|
|
||||||
|
- 该总结将用于后续生成 commit message。
|
||||||
|
|
||||||
|
如果 `git status` 显示没有任何变更(工作区干净),则:
|
||||||
|
|
||||||
|
- 告诉用户「当前没有可提交的变更」,
|
||||||
|
- 不再进行后续步骤。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. 可选:运行测试(若存在)
|
||||||
|
|
||||||
|
按以下优先级尝试检测和运行测试命令(存在就执行,不存在就跳过):
|
||||||
|
|
||||||
|
1. `pytest`
|
||||||
|
2. `python -m pytest`
|
||||||
|
3. `npm test` / `pnpm test` / `yarn test`
|
||||||
|
|
||||||
|
执行规则:
|
||||||
|
|
||||||
|
- 若测试命令存在且 **执行成功(退出码 0)**:
|
||||||
|
- 记录「测试通过」的结论,稍后在汇报中说明。
|
||||||
|
- 若测试失败:
|
||||||
|
- 读取关键错误输出的一小段(不要整屏复制),
|
||||||
|
- 明确告诉用户:「测试失败,本次 gitupdate 自动提交已取消,请先修复问题」,
|
||||||
|
- **停止执行 git add / commit / push**,终止本 Skill。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. 将修改加入暂存区
|
||||||
|
|
||||||
|
默认策略:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A
|
||||||
|
```
|
||||||
|
|
||||||
|
例外情况:
|
||||||
|
|
||||||
|
- 如果用户在会话中明确说「不要提交某些文件 / 目录」,则:
|
||||||
|
- 改用精确路径,例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add src/ config/ README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
- 确保不将用户明确排除的文件加入暂存区。
|
||||||
|
|
||||||
|
如 `git add` 报错(权限或路径问题),向用户说明并终止本 Skill。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. 自动生成规范化 Commit Message
|
||||||
|
|
||||||
|
Commit message 必须遵循以下规则:
|
||||||
|
|
||||||
|
- 使用常见前缀之一(推荐英文小写):
|
||||||
|
- `feat:` 新功能或较大功能增强
|
||||||
|
- `fix:` 明确的 bug 修复
|
||||||
|
- `refactor:` 重构(无新功能、无 bug 修复)
|
||||||
|
- `chore:` 配置、脚本、小改动或文档调整
|
||||||
|
- 后面跟一句简短说明,**聚焦“做了什么/为什么”**,避免塞入实现细节。
|
||||||
|
- 尽量使用英文,必要时可使用中英混合,但保持清晰。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
- `feat: add ai success monitoring dashboards`
|
||||||
|
- `refactor: migrate legacy Config to unified_config`
|
||||||
|
- `fix: handle missing redis connection in system optimizer`
|
||||||
|
- `chore: update logging to per-startup folders`
|
||||||
|
|
||||||
|
生成逻辑建议:
|
||||||
|
|
||||||
|
1. 先根据变更总结判断改动类型(新增功能 / 重构 / 修 bug / 配置调整)。
|
||||||
|
2. 再提取 1~2 个关键模块或文件名,概括在短语中。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. 执行 Commit
|
||||||
|
|
||||||
|
- 执行命令示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git commit -m "<自动生成的 commit message>"
|
||||||
|
```
|
||||||
|
|
||||||
|
- 如果 commit 失败:
|
||||||
|
- 若提示「nothing to commit, working tree clean」:
|
||||||
|
- 说明当前没有实际变更,不再继续 push。
|
||||||
|
- 向用户简单说明「没有可提交的变更」。
|
||||||
|
- 若因 hook 失败:
|
||||||
|
- 将 hook 的关键错误信息简要反馈给用户,
|
||||||
|
- 不要反复重试或绕过 hook(除非用户明确要求)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. 推送到远程仓库
|
||||||
|
|
||||||
|
1. 检查当前分支及是否有 upstream:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status -sb
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 若当前分支 **尚无 upstream**(初次推送):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push -u origin HEAD
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 若已存在 upstream:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 如果 push 失败:
|
||||||
|
|
||||||
|
- 分析错误类型(如权限不足 / 需要登录 / 需要先 pull / 网络错误等),
|
||||||
|
- 向用户用自然语言说明原因,
|
||||||
|
- 不要自动执行 `git pull --rebase` 或 `git push --force` 等危险操作,除非用户在对话中有明确授权。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、安全与边界条件
|
||||||
|
|
||||||
|
在任何情况下,必须遵守以下规则:
|
||||||
|
|
||||||
|
- **禁止** 使用以下命令,除非用户显式、清晰地要求(并且复述确认):
|
||||||
|
- `git push --force`
|
||||||
|
- `git push --force-with-lease`
|
||||||
|
- 任何会重写公共历史的操作(如 `git rebase -i`)。
|
||||||
|
- 不要修改全局 Git 配置,例如:
|
||||||
|
- `git config --global ...`
|
||||||
|
- 避免提交明显敏感文件:
|
||||||
|
- 如 `.env`、包含 `secret` / `password` / `token` 等关键词的配置文件。
|
||||||
|
- 若用户坚持要求提交敏感文件,应先发出风险提示再执行。
|
||||||
|
- 如 `git status` 显示仓库干净,**不要创建空 commit**,简单提示「无变更,不需要提交」。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、对用户的输出格式要求
|
||||||
|
|
||||||
|
每次成功执行 `gitupdate` 后,向用户返回一个简洁的小节,包含:
|
||||||
|
|
||||||
|
1. **提交概览**(一句话):
|
||||||
|
- 例如:「已提交并推送本次大改:重构配置系统并新增 AI 监控模块。」
|
||||||
|
2. **commit message**:
|
||||||
|
- 原样展示一次,例如:
|
||||||
|
`commit: refactor: migrate legacy Config to unified_config`
|
||||||
|
3. **分支与远程信息**:
|
||||||
|
- 例如:「当前分支:\`main\`,已推送到 \`origin/main\`。」
|
||||||
|
4. **测试情况(若有执行)**:
|
||||||
|
- 例如:「pytest 已通过」或「未检测到测试命令,未执行自动测试」。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 粘贴大段 diff 或完整日志;
|
||||||
|
- 输出过多与用户无关的 Git 内部细节。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、反模式(应避免的做法)
|
||||||
|
|
||||||
|
- 为了“干净”而强制 push 覆盖远程历史。
|
||||||
|
- 未经用户允许自动创建新分支或修改远程分支结构。
|
||||||
|
- 在测试失败或仓库状态异常时仍然继续执行 commit / push。
|
||||||
|
- 提交前后不向用户交代任何信息,让用户不知道发生了什么。
|
||||||
|
|
||||||
|
严格遵守以上规范,以确保 `gitupdate` 自动提交既省心又安全。
|
||||||
|
|
||||||
85
.claude/skills/http-error-analyzer/SKILL.md
Normal file
85
.claude/skills/http-error-analyzer/SKILL.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
Name: http-error-analyzer
|
||||||
|
Description: 当日志中出现 4xx/5xx HTTP 错误(如 404、500)时,自动提取相关日志上下文,并分析可能的原因与影响范围,给出排查建议。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「HTTP 报错分析助手」,技能名为 **http-error-analyzer**。
|
||||||
|
|
||||||
|
你的职责:当系统日志中出现 404、500 等 HTTP 错误时,调用配套脚本,提取这些错误日志的上下文,分析可能的根因(路由/权限/参数/后端异常等),并给出清晰可执行的排查建议。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候使用 http-error-analyzer)
|
||||||
|
|
||||||
|
在以下场景中,应考虑激活本 Skill:
|
||||||
|
|
||||||
|
- 用户直接给出日志片段,包含 `404` / `500` / `502` / `503` 等状态码,并询问「为什么」;
|
||||||
|
- 用户提到「某个页面/接口 404/500」并附带或引用了日志文件;
|
||||||
|
- 你通过其他 Skill(例如 `log-summary`)发现最近 4xx/5xx 错误明显增多,需要进一步排查。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
1. 从项目根目录执行脚本 `scripts/analyze_http_errors.py`;
|
||||||
|
2. 读取脚本输出的错误汇总与示例上下文;
|
||||||
|
3. 结合项目结构与路由、后端模块划分,推断每类错误的可能成因;
|
||||||
|
4. 向用户输出简明的「错误分类 → 可能原因 → 建议排查路径」列表。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、脚本调用规范
|
||||||
|
|
||||||
|
从项目根目录执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python .claude/skills/http-error-analyzer/scripts/analyze_http_errors.py
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本行为约定:
|
||||||
|
|
||||||
|
- 扫描 `logs/` 目录下最近若干个 `dashboard.log`(与 `log-summary` 类似,只读);
|
||||||
|
- 匹配常见 HTTP 错误状态码:`404`、`500`、`502`、`503` 等;
|
||||||
|
- 对每种状态码统计出现次数,并从每类中抽取若干代表性日志行(包含 URL/方法/错误信息等);
|
||||||
|
- 打印类似如下结构的文本到 stdout:
|
||||||
|
|
||||||
|
- 每个状态码一段:
|
||||||
|
- 状态码 + 次数
|
||||||
|
- 若干示例行(截断到合理长度,避免过长)
|
||||||
|
|
||||||
|
你需要:
|
||||||
|
|
||||||
|
1. 运行脚本并捕获输出;
|
||||||
|
2. 判断 4xx 与 5xx 错误主要集中在哪些 URL / 接口;
|
||||||
|
3. 根据日志中的路径、报错栈信息等,推理可能的成因。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、对用户的输出规范
|
||||||
|
|
||||||
|
当成功执行 `http-error-analyzer` 时,你应该向用户返回包括以下内容的简要报告:
|
||||||
|
|
||||||
|
1. **错误分布概览**
|
||||||
|
- 例如:「最近 5 个日志文件中,404 共 32 次,500 共 5 次。」
|
||||||
|
2. **按错误类型的分析**
|
||||||
|
- 对每种状态码(如 404、500),用 1~3 句话说明:
|
||||||
|
- 主要集中在哪些 URL 或模块(如 `/knowledge/...`、`/api/workorders/...`);
|
||||||
|
- 可能原因(如路由未配置、静态资源路径错误、模板缺失、后端异常、数据库错误等)。
|
||||||
|
3. **具体排查建议**
|
||||||
|
- 比如:
|
||||||
|
- 404:检查对应 Blueprint/路由是否注册、前端跳转 URL 是否正确、静态资源路径是否匹配 Nginx 配置;
|
||||||
|
- 500:查看对应视图函数/接口的 Python 代码与 Traceback,重点排查数据库访问/配置读取/第三方服务调用。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 一股脑贴出整段日志,只需引用少量代表性行做说明;
|
||||||
|
- 在没有足够信息的情况下,过度肯定某个具体根因;应以「可能是」「优先排查方向」来表述。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、反模式与边界
|
||||||
|
|
||||||
|
- 本 Skill 只做分析与建议,不修改任何代码或配置;如需改动,应由用户确认后再进行;
|
||||||
|
- 若日志中没有任何 4xx/5xx 错误,应明确告知用户「未发现相关 HTTP 错误」,而不是强行分析;
|
||||||
|
- 如脚本运行失败(路径不对/权限问题等),应提示用户修复后再重试。
|
||||||
|
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
HTTP 错误日志分析脚本
|
||||||
|
|
||||||
|
扫描 logs/*/dashboard.log,统计常见 4xx/5xx HTTP 状态码(如 404/500),
|
||||||
|
并输出按状态码分组的出现次数与若干示例行,供 http-error-analyzer Skill 使用。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
LOG_ROOT = Path("logs")
|
||||||
|
LOG_FILENAME = "dashboard.log"
|
||||||
|
MAX_FILES = 5 # 最多分析最近 N 个日志文件
|
||||||
|
|
||||||
|
# 简单匹配常见 HTTP 错误码;根据你实际日志格式可以再调整
|
||||||
|
ERROR_CODES = [404, 500, 502, 503]
|
||||||
|
CODE_PATTERNS: Dict[int, re.Pattern] = {
|
||||||
|
code: re.compile(rf"\b{code}\b") for code in ERROR_CODES
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def find_log_files() -> List[Path]:
|
||||||
|
if not LOG_ROOT.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
candidates: List[Tuple[float, Path]] = []
|
||||||
|
for root, dirs, files in os.walk(LOG_ROOT):
|
||||||
|
if LOG_FILENAME in files:
|
||||||
|
p = Path(root) / LOG_FILENAME
|
||||||
|
try:
|
||||||
|
mtime = p.stat().st_mtime
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
candidates.append((mtime, p))
|
||||||
|
|
||||||
|
candidates.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
return [p for _, p in candidates[:MAX_FILES]]
|
||||||
|
|
||||||
|
|
||||||
|
def analyze_file(path: Path):
|
||||||
|
"""
|
||||||
|
返回:
|
||||||
|
counts: {status_code: 次数}
|
||||||
|
samples: {status_code: [示例行1, 示例行2, ...]}
|
||||||
|
"""
|
||||||
|
counts: Dict[int, int] = {code: 0 for code in ERROR_CODES}
|
||||||
|
samples: Dict[int, List[str]] = {code: [] for code in ERROR_CODES}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with path.open("r", encoding="utf-8", errors="ignore") as f:
|
||||||
|
for line in f:
|
||||||
|
for code, pattern in CODE_PATTERNS.items():
|
||||||
|
if pattern.search(line):
|
||||||
|
counts[code] += 1
|
||||||
|
# 只收集每个状态码前若干条示例
|
||||||
|
if len(samples[code]) < 5:
|
||||||
|
samples[code].append(line.strip()[:300])
|
||||||
|
break
|
||||||
|
except OSError as e:
|
||||||
|
print(f"[!] 读取日志失败 {path}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return counts, samples
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
log_files = find_log_files()
|
||||||
|
if not log_files:
|
||||||
|
print("未找到任何日志文件(logs/*/dashboard.log)。")
|
||||||
|
return
|
||||||
|
|
||||||
|
overall_counts: Dict[int, int] = {code: 0 for code in ERROR_CODES}
|
||||||
|
overall_samples: Dict[int, List[str]] = {code: [] for code in ERROR_CODES}
|
||||||
|
|
||||||
|
print(f"=== HTTP 错误日志分析(最近最多 {MAX_FILES} 个日志文件)===\n")
|
||||||
|
|
||||||
|
for idx, path in enumerate(log_files, start=1):
|
||||||
|
print(f"[{idx}] 日志文件: {path}")
|
||||||
|
result = analyze_file(path)
|
||||||
|
if result is None:
|
||||||
|
print(" 无法读取该日志文件。\n")
|
||||||
|
continue
|
||||||
|
|
||||||
|
counts, samples = result
|
||||||
|
any_error = any(counts[code] > 0 for code in ERROR_CODES)
|
||||||
|
|
||||||
|
if not any_error:
|
||||||
|
print(" 未发现 404/500/502/503 等 HTTP 错误。")
|
||||||
|
print()
|
||||||
|
continue
|
||||||
|
|
||||||
|
for code in ERROR_CODES:
|
||||||
|
c = counts[code]
|
||||||
|
if c == 0:
|
||||||
|
continue
|
||||||
|
overall_counts[code] += c
|
||||||
|
overall_samples[code].extend(samples[code])
|
||||||
|
print(f" 状态码 {code}: {c} 次")
|
||||||
|
if samples[code]:
|
||||||
|
print(" 示例:")
|
||||||
|
for line in samples[code]:
|
||||||
|
print(f" {line}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("=== 汇总统计 ===")
|
||||||
|
any_overall = any(overall_counts[code] > 0 for code in ERROR_CODES)
|
||||||
|
if not any_overall:
|
||||||
|
print(" 未在最近的日志文件中发现任何配置的 HTTP 错误状态码。")
|
||||||
|
return
|
||||||
|
|
||||||
|
for code in ERROR_CODES:
|
||||||
|
c = overall_counts[code]
|
||||||
|
if c == 0:
|
||||||
|
continue
|
||||||
|
print(f" 状态码 {code}: {c} 次")
|
||||||
|
|
||||||
|
print("\n提示:以上为按状态码汇总的次数与部分示例行,")
|
||||||
|
print("你可以结合 URL 路径、接口名称、堆栈片段来推断可能的路由配置问题、权限问题或后端异常。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
84
.claude/skills/kb-audit/SKILL.md
Normal file
84
.claude/skills/kb-audit/SKILL.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
Name: kb-audit
|
||||||
|
Description: 对知识库条目进行体检,找出命中率低、置信度低或长期未更新的知识点,并给出优化建议,帮助持续提升 TSP 智能助手的知识质量。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「知识库健康检查与优化助手」,技能名为 **kb-audit**。
|
||||||
|
|
||||||
|
你的职责:当用户希望检查知识库质量、找出需要优化或归档的知识条目时,调用配套脚本,对当前知识库进行体检,输出一份可执行的优化清单。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候使用 kb-audit)
|
||||||
|
|
||||||
|
当用户有类似需求时,应激活本 Skill,例如:
|
||||||
|
|
||||||
|
- 「帮我看看知识库有没有陈旧/低质量内容」
|
||||||
|
- 「哪些知识点命中率低需要优化」
|
||||||
|
- 「清理一下长期不用的知识条目」
|
||||||
|
- 「做一次知识库体检,看看哪里要改」
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
1. 从项目根目录执行脚本 `scripts/kb_audit.py`;
|
||||||
|
2. 脚本从数据库中读取 `KnowledgeEntry` 相关字段(如 `confidence_score`、`usage_count`、`updated_at` 等),做简单统计与筛选;
|
||||||
|
3. 你读取脚本输出,提炼出「高风险/待优化」的知识条目特征和数量;
|
||||||
|
4. 为用户形成简明的优化建议与优先级排序。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、脚本调用规范
|
||||||
|
|
||||||
|
从项目根目录执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python .claude/skills/kb-audit/scripts/kb_audit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本行为约定:
|
||||||
|
|
||||||
|
- 通过 `db_manager.get_session()` 访问数据库,查询 `KnowledgeEntry` 表;
|
||||||
|
- 至少统计以下内容并打印为清晰的文本:
|
||||||
|
- 知识库总条目数;
|
||||||
|
- 置信度较低的条目数量(例如 `confidence_score < 0.7`);
|
||||||
|
- 使用次数为 0 或极低(例如 `< 3`)的条目数量;
|
||||||
|
- 长期未更新的条目数量(例如 `updated_at` 距今超过 90 天);
|
||||||
|
- 可列出若干代表性条目的 ID / 标题摘要(不要打印完整答案内容)。
|
||||||
|
- 脚本不做任何写操作,只读。
|
||||||
|
|
||||||
|
你需要:
|
||||||
|
|
||||||
|
1. 运行脚本并捕获输出;
|
||||||
|
2. 根据统计结果,概括知识库当前健康状况(良好 / 一般 / 需要重点治理);
|
||||||
|
3. 给出 3~5 条具体的优化建议,如「优先补充高频问题的答案」「合并重复知识点」等。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、对用户的输出规范
|
||||||
|
|
||||||
|
当成功执行 `kb-audit` 时,应向用户返回包括以下内容的简要报告:
|
||||||
|
|
||||||
|
1. **总体健康度**(一句话)
|
||||||
|
- 例如:「当前知识库共 500 条,其中约 15% 条目置信度偏低,10% 长期未更新。」
|
||||||
|
2. **问题概览**
|
||||||
|
- 低置信度条目大致数量与比例;
|
||||||
|
- 使用次数很少的条目数量与可能的原因;
|
||||||
|
- 长期未更新条目的数量。
|
||||||
|
3. **优化建议**
|
||||||
|
- 分点列出建议(如按优先级:先处理高频但低置信度的条目)。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 直接打印或暴露完整的知识答案内容(可能包含敏感信息);
|
||||||
|
- 输出过长的 SQL 或技术细节,优先用运营视角解释。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、反模式与边界
|
||||||
|
|
||||||
|
- 脚本仅做只读操作,**禁止** 修改或删除知识库条目;
|
||||||
|
- 如数据库连接失败,应提示用户先确认数据库配置与网络,再重试;
|
||||||
|
- 不要根据少量样本过度推断整体质量,尽量使用统计结果支撑你的结论。
|
||||||
|
|
||||||
89
.claude/skills/kb-audit/scripts/kb_audit.py
Normal file
89
.claude/skills/kb-audit/scripts/kb_audit.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
知识库体检脚本
|
||||||
|
|
||||||
|
对 KnowledgeEntry 做简单统计,供 kb-audit Skill 调用。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def add_project_root_to_path():
|
||||||
|
# 假定脚本位于 .claude/skills/kb-audit/scripts/ 下
|
||||||
|
script_path = Path(__file__).resolve()
|
||||||
|
project_root = script_path.parents[4]
|
||||||
|
if str(project_root) not in sys.path:
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
add_project_root_to_path()
|
||||||
|
|
||||||
|
from src.core.database import db_manager
|
||||||
|
from src.core.models import KnowledgeEntry
|
||||||
|
|
||||||
|
print("=== 知识库健康检查 ===\n")
|
||||||
|
|
||||||
|
with db_manager.get_session() as session:
|
||||||
|
total = session.query(KnowledgeEntry).count()
|
||||||
|
print(f"知识条目总数: {total}")
|
||||||
|
|
||||||
|
# 低置信度(<0.7)
|
||||||
|
low_conf = (
|
||||||
|
session.query(KnowledgeEntry)
|
||||||
|
.filter(KnowledgeEntry.confidence_score.isnot(None))
|
||||||
|
.filter(KnowledgeEntry.confidence_score < 0.7)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
print(f"低置信度条目数 (confidence_score < 0.7): {low_conf}")
|
||||||
|
|
||||||
|
# 使用次数极低(usage_count < 3 或为 NULL)
|
||||||
|
low_usage = (
|
||||||
|
session.query(KnowledgeEntry)
|
||||||
|
.filter(
|
||||||
|
(KnowledgeEntry.usage_count.is_(None))
|
||||||
|
| (KnowledgeEntry.usage_count < 3)
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
print(f"使用次数极低条目数 (usage_count < 3 或空): {low_usage}")
|
||||||
|
|
||||||
|
# 长期未更新(> 90 天)
|
||||||
|
cutoff = datetime.now() - timedelta(days=90)
|
||||||
|
old_entries = (
|
||||||
|
session.query(KnowledgeEntry)
|
||||||
|
.filter(
|
||||||
|
(KnowledgeEntry.updated_at.isnot(None))
|
||||||
|
& (KnowledgeEntry.updated_at < cutoff)
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
print(f"长期未更新条目数 (updated_at > 90 天未更新): {old_entries}")
|
||||||
|
|
||||||
|
print("\n示例问题条目(不含完整答案,仅展示前若干个):")
|
||||||
|
sample_entries = (
|
||||||
|
session.query(KnowledgeEntry)
|
||||||
|
.order_by(KnowledgeEntry.created_at.desc())
|
||||||
|
.limit(5)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
for e in sample_entries:
|
||||||
|
q_preview = (e.question or "")[:40]
|
||||||
|
print(
|
||||||
|
f" ID={e.id}, category={e.category}, "
|
||||||
|
f"confidence={e.confidence_score}, usage={e.usage_count}, "
|
||||||
|
f"Q='{q_preview}...'"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\n提示:")
|
||||||
|
print(" - 建议优先审查低置信度且 usage_count 较高的条目;")
|
||||||
|
print(" - 对长期未更新且 usage_count 较高的条目,可考虑人工复查内容是否过时;")
|
||||||
|
print(" - 对 usage_count 极低且从未触发的条目,可考虑合并或归档。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
86
.claude/skills/log-summary/SKILL.md
Normal file
86
.claude/skills/log-summary/SKILL.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
Name: log-summary
|
||||||
|
Description: 汇总并分析 TSP 智能助手日志中的 ERROR 与 WARNING,输出最近一次启动以来的错误概览和统计,帮助快速诊断问题。
|
||||||
|
---
|
||||||
|
|
||||||
|
你是一个「日志错误汇总与分析助手」,技能名为 **log-summary**。
|
||||||
|
|
||||||
|
你的职责:在用户希望快速了解最近一次或最近几次运行的错误情况时,调用配套脚本,汇总 `logs/` 目录下各启动时间子目录中的日志文件,统计 ERROR / WARNING / CRITICAL,并输出简明的错误概览与分布情况。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、触发条件(什么时候使用 log-summary)
|
||||||
|
|
||||||
|
当用户有类似需求时,应激活本 Skill,例如:
|
||||||
|
|
||||||
|
- 「帮我看看最近运行有没有错误」
|
||||||
|
- 「总结一下最近日志里的报错」
|
||||||
|
- 「分析 logs 下面的错误情况」
|
||||||
|
- 「最近系统老出问题,帮我看看日志」
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、总体流程
|
||||||
|
|
||||||
|
1. 调用脚本 `scripts/log_summary.py`,从项目根目录执行。
|
||||||
|
2. 读取输出并用自然语言向用户转述关键发现。
|
||||||
|
3. 对明显频繁的错误类型,给出简单的排查建议。
|
||||||
|
4. 输出时保持简洁,避免粘贴大段原始日志。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、脚本调用规范
|
||||||
|
|
||||||
|
从项目根目录(包含 `start_dashboard.py` 的目录)执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python .claude/skills/log-summary/scripts/log_summary.py
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本行为约定:
|
||||||
|
|
||||||
|
- 自动遍历 `logs/` 目录下所有子目录(例如 `logs/2026-02-10_23-51-10/dashboard.log`)。
|
||||||
|
- 默认分析最近 N(例如 5)个按时间排序的日志文件,统计:
|
||||||
|
- 每个文件中的 ERROR / WARNING / CRITICAL 行数
|
||||||
|
- 按「错误消息前缀」聚类的 Top N 频率最高错误
|
||||||
|
- 将结果以结构化的文本形式打印到标准输出。
|
||||||
|
|
||||||
|
你需要:
|
||||||
|
|
||||||
|
1. 运行脚本并捕获输出;
|
||||||
|
2. 读懂其中的统计数据与 Top 错误信息;
|
||||||
|
3. 用 3~8 句中文自然语言,对用户进行总结说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、对用户的输出规范
|
||||||
|
|
||||||
|
当成功执行 `log-summary` 时,你应该向用户返回类似结构的信息:
|
||||||
|
|
||||||
|
1. **总体健康度**(一句话)
|
||||||
|
- 例如:「最近 3 次启动中共记录 2 条 ERROR、5 条 WARNING,整体较为稳定。」
|
||||||
|
2. **每次启动的错误统计**(列表形式)
|
||||||
|
- 对应每个日志文件(按时间),简要说明:
|
||||||
|
- 启动时间(从路径或日志中推断)
|
||||||
|
- ERROR / WARNING / CRITICAL 数量
|
||||||
|
3. **Top 错误类型**
|
||||||
|
- 例如:「最频繁的错误是 `No module named 'src.config.config'`,共出现 4 次。」
|
||||||
|
4. **简单建议(可选)**
|
||||||
|
- 对明显重复的错误给出 1~3 条排查/优化建议。
|
||||||
|
|
||||||
|
避免:
|
||||||
|
|
||||||
|
- 直接原样复制整段日志;
|
||||||
|
- 输出过长的技术细节堆栈,优先摘要。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、反模式与边界
|
||||||
|
|
||||||
|
- 如果 `logs/` 目录不存在或没有任何日志文件:
|
||||||
|
- 明确告诉用户当前没有可分析的日志,而不是编造结果。
|
||||||
|
- 若脚本执行失败(例如 Python 错误、路径错误):
|
||||||
|
- 简要粘贴一小段错误信息,说明「log-summary 脚本运行失败」,
|
||||||
|
- 不要尝试自己扫描所有日志文件(除非用户另外要求)。
|
||||||
|
- 不要擅自删除或修改日志文件。
|
||||||
|
|
||||||
115
.claude/skills/log-summary/scripts/log_summary.py
Normal file
115
.claude/skills/log-summary/scripts/log_summary.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
简单日志汇总脚本
|
||||||
|
|
||||||
|
遍历 logs/ 目录下最近的若干个 dashboard.log 文件,统计 ERROR / WARNING / CRITICAL,
|
||||||
|
并输出简要汇总信息,供 log-summary Skill 调用。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
LOG_ROOT = Path("logs")
|
||||||
|
LOG_FILENAME = "dashboard.log"
|
||||||
|
MAX_FILES = 5 # 最多分析最近 N 个日志文件
|
||||||
|
|
||||||
|
|
||||||
|
LEVEL_PATTERNS = {
|
||||||
|
"ERROR": re.compile(r"\bERROR\b"),
|
||||||
|
"WARNING": re.compile(r"\bWARNING\b"),
|
||||||
|
"CRITICAL": re.compile(r"\bCRITICAL\b"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def find_log_files() -> List[Path]:
|
||||||
|
if not LOG_ROOT.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
candidates: List[Tuple[float, Path]] = []
|
||||||
|
for root, dirs, files in os.walk(LOG_ROOT):
|
||||||
|
if LOG_FILENAME in files:
|
||||||
|
p = Path(root) / LOG_FILENAME
|
||||||
|
try:
|
||||||
|
mtime = p.stat().st_mtime
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
candidates.append((mtime, p))
|
||||||
|
|
||||||
|
# 按修改时间从新到旧排序
|
||||||
|
candidates.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
return [p for _, p in candidates[:MAX_FILES]]
|
||||||
|
|
||||||
|
|
||||||
|
def summarize_file(path: Path):
|
||||||
|
counts = {level: 0 for level in LEVEL_PATTERNS.keys()}
|
||||||
|
top_messages = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with path.open("r", encoding="utf-8", errors="ignore") as f:
|
||||||
|
for line in f:
|
||||||
|
for level, pattern in LEVEL_PATTERNS.items():
|
||||||
|
if pattern.search(line):
|
||||||
|
counts[level] += 1
|
||||||
|
# 取日志消息部分做前缀(粗略)
|
||||||
|
msg = line.strip()
|
||||||
|
# 截断以防过长
|
||||||
|
msg = msg[:200]
|
||||||
|
top_messages[msg] = top_messages.get(msg, 0) + 1
|
||||||
|
break
|
||||||
|
except OSError as e:
|
||||||
|
print(f"[!] 读取日志失败 {path}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 取 Top 5
|
||||||
|
top_list = sorted(top_messages.items(), key=lambda x: x[1], reverse=True)[:5]
|
||||||
|
return counts, top_list
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
log_files = find_log_files()
|
||||||
|
if not log_files:
|
||||||
|
print("未找到任何日志文件(logs/*/dashboard.log)。")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"共找到 {len(log_files)} 个最近的日志文件(最多 {MAX_FILES} 个):\n")
|
||||||
|
|
||||||
|
overall = {level: 0 for level in LEVEL_PATTERNS.keys()}
|
||||||
|
|
||||||
|
for idx, path in enumerate(log_files, start=1):
|
||||||
|
print(f"[{idx}] 日志文件: {path}")
|
||||||
|
result = summarize_file(path)
|
||||||
|
if result is None:
|
||||||
|
print(" 无法读取该日志文件。\n")
|
||||||
|
continue
|
||||||
|
|
||||||
|
counts, top_list = result
|
||||||
|
for level, c in counts.items():
|
||||||
|
overall[level] += c
|
||||||
|
print(
|
||||||
|
" 级别统计: "
|
||||||
|
+ ", ".join(f"{lvl}={counts[lvl]}" for lvl in LEVEL_PATTERNS.keys())
|
||||||
|
)
|
||||||
|
|
||||||
|
if top_list:
|
||||||
|
print(" Top 错误/警告消息:")
|
||||||
|
for msg, n in top_list:
|
||||||
|
print(f" [{n}次] {msg}")
|
||||||
|
else:
|
||||||
|
print(" 未发现 ERROR/WARNING/CRITICAL 级别日志。")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("总体统计:")
|
||||||
|
print(
|
||||||
|
" "
|
||||||
|
+ ", ".join(f"{lvl}={overall[lvl]}" for lvl in LEVEL_PATTERNS.keys())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
98
.env
Normal file
98
.env
Normal file
@@ -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://<user>:<password>@<host>:<port>/<dbname>?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
|
||||||
93
.env.example
Normal file
93
.env.example
Normal file
@@ -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://<user>:<password>@<host>:<port>/<dbname>?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
|
||||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
# 默认忽略的文件
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# 基于编辑器的 HTTP 客户端请求
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
12
.idea/dataSources.xml
generated
12
.idea/dataSources.xml
generated
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
|
||||||
<data-source source="LOCAL" name="@43.134.68.207" uuid="715b070d-f258-43df-a066-49e825a9b04f">
|
|
||||||
<driver-ref>mysql.8</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:mysql://43.134.68.207:3306</jdbc-url>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
</data-source>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/data_source_mapping.xml
generated
6
.idea/data_source_mapping.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourcePerFileMappings">
|
|
||||||
<file url="file://$APPLICATION_CONFIG_DIR$/consoles/db/715b070d-f258-43df-a066-49e825a9b04f/console.sql" value="715b070d-f258-43df-a066-49e825a9b04f" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<settings>
|
|
||||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
|
||||||
<version value="1.0" />
|
|
||||||
</settings>
|
|
||||||
</component>
|
|
||||||
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="Black">
|
|
||||||
<option name="sdkName" value="Python 3.11 (tsp-assistant)" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (tsp-assistant)" project-jdk-type="Python SDK" />
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/tsp-assistant.iml" filepath="$PROJECT_DIR$/.idea/tsp-assistant.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
14
.idea/tsp-assistant.iml
generated
14
.idea/tsp-assistant.iml
generated
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="PYTHON_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Python 3.11 (tsp-assistant)" jdkType="Python SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
<component name="PyDocumentationSettings">
|
|
||||||
<option name="format" value="PLAIN" />
|
|
||||||
<option name="myDocStringFormat" value="Plain" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
26
.vscode/settings.json
vendored
26
.vscode/settings.json
vendored
@@ -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
|
|
||||||
}
|
|
||||||
88
CLAUDE.md
Normal file
88
CLAUDE.md
Normal file
@@ -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`
|
||||||
144
LLM配置统一说明.md
144
LLM配置统一说明.md
@@ -1,144 +0,0 @@
|
|||||||
# LLM配置统一管理说明
|
|
||||||
|
|
||||||
## ? 概述
|
|
||||||
|
|
||||||
本项目已将LLM配置统一管理,确保整个项目只在一个地方配置千问模型,所有地方都从统一配置获取。
|
|
||||||
|
|
||||||
## ?? 配置架构
|
|
||||||
|
|
||||||
### 1. 核心配置文件:`config/llm_config.py`
|
|
||||||
|
|
||||||
这是**唯一的**LLM配置源,定义了千问模型的所有配置:
|
|
||||||
|
|
||||||
```python
|
|
||||||
QWEN_CONFIG = LLMConfig(
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
# 默认使用千问模型
|
|
||||||
DEFAULT_CONFIG = QWEN_CONFIG
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 统一配置管理器:`src/config/unified_config.py`
|
|
||||||
|
|
||||||
统一配置管理器在初始化时自动从 `config/llm_config.py` 加载配置:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def _load_default_llm_config(self) -> LLMConfig:
|
|
||||||
"""加载默认LLM配置"""
|
|
||||||
try:
|
|
||||||
from config.llm_config import DEFAULT_CONFIG
|
|
||||||
# 转换配置格式
|
|
||||||
return LLMConfig(...)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"无法加载默认LLM配置,使用内置默认值: {e}")
|
|
||||||
return LLMConfig()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 全局配置实例
|
|
||||||
|
|
||||||
通过 `get_config()` 函数获取全局配置实例:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.config.unified_config import get_config
|
|
||||||
|
|
||||||
config = get_config()
|
|
||||||
llm_config = config.llm # 获取LLM配置
|
|
||||||
```
|
|
||||||
|
|
||||||
## ? 如何使用
|
|
||||||
|
|
||||||
### 在任何需要使用LLM的地方:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.config.unified_config import get_config
|
|
||||||
|
|
||||||
# 获取LLM配置
|
|
||||||
llm_config = get_config().llm
|
|
||||||
|
|
||||||
# 使用配置
|
|
||||||
print(f"Provider: {llm_config.provider}")
|
|
||||||
print(f"Model: {llm_config.model}")
|
|
||||||
print(f"API Key: {llm_config.api_key}")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 示例:AI建议服务
|
|
||||||
|
|
||||||
```python
|
|
||||||
class AISuggestionService:
|
|
||||||
def __init__(self):
|
|
||||||
# 从统一配置管理器获取LLM配置
|
|
||||||
self.llm_config = get_config().llm
|
|
||||||
logger.info(f"使用LLM配置: {self.llm_config.provider} - {self.llm_config.model}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## ? 配置优先级
|
|
||||||
|
|
||||||
1. **第一优先级**:统一配置管理器中的配置(可通过配置文件或环境变量设置)
|
|
||||||
2. **第二优先级**:`config/llm_config.py` 中的 `DEFAULT_CONFIG`
|
|
||||||
3. **最后备选**:内置的默认值
|
|
||||||
|
|
||||||
## ? 修改配置
|
|
||||||
|
|
||||||
### 方法1:修改配置文件(推荐)
|
|
||||||
|
|
||||||
直接编辑 `config/llm_config.py`,修改API密钥或模型:
|
|
||||||
|
|
||||||
```python
|
|
||||||
QWEN_CONFIG = LLMConfig(
|
|
||||||
provider="qwen",
|
|
||||||
api_key="你的新API密钥", # 修改这里
|
|
||||||
model="qwen-max", # 或修改模型
|
|
||||||
...
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方法2:通过统一配置文件
|
|
||||||
|
|
||||||
编辑 `config/unified_config.json`(如果存在):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"llm": {
|
|
||||||
"provider": "qwen",
|
|
||||||
"api_key": "你的新API密钥",
|
|
||||||
"model": "qwen-plus-latest",
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方法3:环境变量(可选)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export LLM_API_KEY="你的API密钥"
|
|
||||||
export LLM_MODEL="qwen-plus-latest"
|
|
||||||
```
|
|
||||||
|
|
||||||
## ? 优势
|
|
||||||
|
|
||||||
1. **单一配置源**:只需要在 `config/llm_config.py` 配置一次
|
|
||||||
2. **统一管理**:所有模块都通过统一配置管理器获取
|
|
||||||
3. **易于维护**:修改配置不需要修改多处代码
|
|
||||||
4. **自动同步**:修改配置后,所有使用该配置的地方自动更新
|
|
||||||
5. **向后兼容**:保留fallback机制,确保系统稳定运行
|
|
||||||
|
|
||||||
## ? 已更新的文件
|
|
||||||
|
|
||||||
- ? `config/llm_config.py` - 添加了 `get_default_llm_config()` 函数
|
|
||||||
- ? `src/config/unified_config.py` - 从 `config/llm_config.py` 加载默认配置
|
|
||||||
- ? `src/integrations/ai_suggestion_service.py` - 使用统一配置
|
|
||||||
- ? `src/agent/agent_assistant_core.py` - 使用统一配置
|
|
||||||
|
|
||||||
## ? 注意事项
|
|
||||||
|
|
||||||
- **不要**在代码中硬编码OpenAI或其他模型的配置
|
|
||||||
- **不要**直接从 `config/llm_config.py` 导入(除非作为fallback)
|
|
||||||
- **总是**通过 `get_config().llm` 获取配置
|
|
||||||
- 修改配置后,请重启应用使配置生效
|
|
||||||
|
|
||||||
55
README.md
55
README.md
@@ -1,6 +1,6 @@
|
|||||||
# TSP智能助手 (TSP Assistant)
|
# TSP智能助手 (TSP Assistant)
|
||||||
|
|
||||||
[](version.json)
|
[](version.json)
|
||||||
[](requirements.txt)
|
[](requirements.txt)
|
||||||
[](Dockerfile)
|
[](Dockerfile)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
@@ -15,19 +15,22 @@
|
|||||||
- **智能规划**: 基于目标驱动的任务规划和执行
|
- **智能规划**: 基于目标驱动的任务规划和执行
|
||||||
- **自主学习**: 从用户反馈中持续优化响应质量
|
- **自主学习**: 从用户反馈中持续优化响应质量
|
||||||
- **实时监控**: 主动监控系统状态和异常情况
|
- **实时监控**: 主动监控系统状态和异常情况
|
||||||
- **模块化重构**: 代码优化,降低运行风险,提升维护性
|
- **模块化重构**: 后端服务(Agent, 车辆数据, 分析, 测试)蓝图化,提高可维护性和扩展性
|
||||||
|
- **前端模块化**: 引入ES6模块化架构,优化UI组件、状态管理和API服务
|
||||||
|
|
||||||
### 💬 智能对话系统
|
### 💬 智能对话系统
|
||||||
- **实时通信**: WebSocket支持,毫秒级响应
|
- **实时通信**: WebSocket支持,毫秒级响应,已修复连接稳定性问题
|
||||||
- **上下文理解**: 多轮对话记忆和上下文关联
|
- **上下文理解**: 多轮对话记忆和上下文关联
|
||||||
- **VIN识别**: 自动识别车辆VIN码并获取实时数据
|
- **VIN识别**: 自动识别车辆VIN码并获取实时数据
|
||||||
- **知识库集成**: 基于TF-IDF和余弦相似度的智能检索
|
- **知识库集成**: 基于TF-IDF和余弦相似度的智能检索
|
||||||
|
- **自定义提示词**: 支持飞书同步和实时对话不同场景的LLM提示词
|
||||||
|
|
||||||
### 📊 数据驱动分析
|
### 📊 数据驱动分析
|
||||||
- **真实数据**: 基于数据库的真实性能趋势分析
|
- **真实数据**: 基于数据库的真实性能趋势分析
|
||||||
- **多维度统计**: 工单、预警、满意度、性能指标
|
- **多维度统计**: 工单、预警、满意度、性能指标
|
||||||
- **可视化展示**: Chart.js图表,直观的数据呈现
|
- **可视化展示**: Chart.js图表,直观的数据呈现
|
||||||
- **系统监控**: 实时CPU、内存、健康状态监控
|
- **系统监控**: 实时CPU、内存、健康状态监控
|
||||||
|
- **专属蓝图**: 独立的数据分析API模块,提供专业数据报告导出
|
||||||
|
|
||||||
### 🔧 企业级管理
|
### 🔧 企业级管理
|
||||||
- **多环境部署**: 开发、测试、生产环境隔离
|
- **多环境部署**: 开发、测试、生产环境隔离
|
||||||
@@ -35,6 +38,7 @@
|
|||||||
- **热更新**: 支持前端文件热更新,无需重启服务
|
- **热更新**: 支持前端文件热更新,无需重启服务
|
||||||
- **自动备份**: 更新前自动备份,支持一键回滚
|
- **自动备份**: 更新前自动备份,支持一键回滚
|
||||||
- **飞书集成**: 支持飞书多维表格数据同步和管理
|
- **飞书集成**: 支持飞书多维表格数据同步和管理
|
||||||
|
- **统一错误处理**: 后端API统一异常处理,提高系统健壮性
|
||||||
|
|
||||||
## 🏗️ 系统架构
|
## 🏗️ 系统架构
|
||||||
|
|
||||||
@@ -66,18 +70,21 @@
|
|||||||
- **VIN识别**: 自动识别车辆VIN并获取实时数据
|
- **VIN识别**: 自动识别车辆VIN并获取实时数据
|
||||||
- **知识库检索**: 智能匹配相关技术文档和解决方案
|
- **知识库检索**: 智能匹配相关技术文档和解决方案
|
||||||
- **工单创建**: 对话中直接创建和关联工单
|
- **工单创建**: 对话中直接创建和关联工单
|
||||||
|
- **错误修复**: 解决了WebSocket连接TypeError问题
|
||||||
|
|
||||||
### 2. Agent管理 🤖
|
### 2. Agent管理 🤖
|
||||||
- **工具管理**: 10+内置工具,支持自定义工具注册
|
- **工具管理**: 10+内置工具,支持自定义工具注册
|
||||||
- **执行监控**: 实时监控Agent任务执行状态
|
- **执行监控**: 实时监控Agent任务执行状态
|
||||||
- **性能统计**: 工具使用频率和成功率分析
|
- **性能统计**: 工具使用频率和成功率分析
|
||||||
- **智能规划**: 基于目标的任务分解和执行
|
- **智能规划**: 基于目标的任务分解和执行
|
||||||
|
- **专用蓝图**: Agent相关API已独立为蓝图管理
|
||||||
|
|
||||||
### 3. 工单系统 📋
|
### 3. 工单系统 📋
|
||||||
- **AI建议**: 基于知识库生成工单处理建议
|
- **AI建议**: 基于知识库生成工单处理建议
|
||||||
- **人工审核**: 支持人工输入和AI建议对比
|
- **人工审核**: 支持人工输入和AI建议对比
|
||||||
- **相似度评估**: 自动计算AI与人工建议的相似度
|
- **相似度评估**: 自动计算AI与人工建议的相似度
|
||||||
- **知识库更新**: 高相似度建议自动入库
|
- **知识库更新**: 高相似度建议自动入库
|
||||||
|
- **飞书AI提示词**: 针对飞书同步场景提供更详细的AI建议提示词
|
||||||
|
|
||||||
### 4. 知识库管理 📚
|
### 4. 知识库管理 📚
|
||||||
- **多格式支持**: TXT、PDF、DOC、DOCX、MD文件
|
- **多格式支持**: TXT、PDF、DOC、DOCX、MD文件
|
||||||
@@ -90,12 +97,14 @@
|
|||||||
- **多维度统计**: 工单、预警、满意度等关键指标
|
- **多维度统计**: 工单、预警、满意度等关键指标
|
||||||
- **系统健康**: CPU、内存、响应时间监控
|
- **系统健康**: CPU、内存、响应时间监控
|
||||||
- **可视化展示**: 丰富的图表和仪表板
|
- **可视化展示**: 丰富的图表和仪表板
|
||||||
|
- **专用蓝图**: 数据分析API已独立为蓝图管理,并支持Excel报告导出
|
||||||
|
|
||||||
### 6. 系统设置 ⚙️
|
### 6. 系统设置 ⚙️
|
||||||
- **API管理**: 支持多种LLM提供商配置
|
- **API管理**: 支持多种LLM提供商配置
|
||||||
- **模型参数**: 温度、最大令牌数等参数调节
|
- **模型参数**: 温度、最大令牌数等参数调节
|
||||||
- **端口配置**: Web服务和WebSocket端口管理
|
- **端口配置**: Web服务和WebSocket端口管理
|
||||||
- **日志级别**: 灵活的日志级别控制
|
- **日志级别**: 灵活的日志级别控制
|
||||||
|
- **数据库健壮性**: 优化了数据库连接配置和错误处理
|
||||||
|
|
||||||
### 7. 飞书集成 📱
|
### 7. 飞书集成 📱
|
||||||
- **多维表格同步**: 自动同步飞书多维表格数据
|
- **多维表格同步**: 自动同步飞书多维表格数据
|
||||||
@@ -268,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
|
```bash
|
||||||
# 更新版本号
|
# 更新版本号
|
||||||
@@ -292,15 +289,6 @@ python version.py changelog --message "新功能描述"
|
|||||||
python version.py tag --message "Release v1.3.0"
|
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 系统监控
|
## 📊 系统监控
|
||||||
|
|
||||||
### 健康检查
|
### 健康检查
|
||||||
@@ -377,6 +365,25 @@ TZ=Asia/Shanghai
|
|||||||
|
|
||||||
## 📝 更新日志
|
## 📝 更新日志
|
||||||
|
|
||||||
|
### v2.1.0 (2025-12-08) - 全面架构优化与问题修复
|
||||||
|
- ⚙️ **后端架构重构**:
|
||||||
|
- 将Agent、车辆数据、数据分析、API测试相关路由拆分为独立蓝图。
|
||||||
|
- 精简 `app.py` 主应用文件,提升模块化和可维护性。
|
||||||
|
- 引入统一错误处理装饰器和依赖注入机制。
|
||||||
|
- 🎨 **前端架构优化**:
|
||||||
|
- 实现了JavaScript模块化架构,划分 `core`, `services`, `components` 目录。
|
||||||
|
- 引入了统一状态管理 (`store.js`) 和API服务 (`api.js`)。
|
||||||
|
- 优化了通知管理和预警显示组件。
|
||||||
|
- 🛠️ **关键问题修复**:
|
||||||
|
- 修复了WebSocket连接中 `TypeError: missing 1 required positional argument: 'path'` 错误。
|
||||||
|
- 改进了数据库连接的健壮性,优化MySQL连接池配置,并增强了异常处理和重连机制。
|
||||||
|
- 解决了 `generator didn't stop` 错误,确保数据库会话的正确关闭。
|
||||||
|
- 增强了预警系统异常处理,并在规则检查失败时生成系统预警。
|
||||||
|
- 优化了API错误响应,包含更详细的错误信息。
|
||||||
|
- ✨ **新功能增强**:
|
||||||
|
- 为飞书同步和实时对话场景引入了不同的LLM提示词,提升AI建议的针对性。
|
||||||
|
- 增加了对`Analysising`工单状态的映射处理。
|
||||||
|
|
||||||
### v2.0.0 (2025-09-22) - Docker环境全面升级
|
### v2.0.0 (2025-09-22) - Docker环境全面升级
|
||||||
- 🐳 **Docker环境重构**: 升级到Python 3.11,优化镜像构建
|
- 🐳 **Docker环境重构**: 升级到Python 3.11,优化镜像构建
|
||||||
- 🐳 **多服务编排**: MySQL 8.0 + Redis 7 + Nginx + Prometheus + Grafana
|
- 🐳 **多服务编排**: MySQL 8.0 + Redis 7 + Nginx + Prometheus + Grafana
|
||||||
|
|||||||
524
TSP智能助手完整文档.md
524
TSP智能助手完整文档.md
@@ -1,524 +0,0 @@
|
|||||||
# TSP智能助手完整文档
|
|
||||||
|
|
||||||
## 📋 目录
|
|
||||||
- [项目概述](#项目概述)
|
|
||||||
- [系统架构](#系统架构)
|
|
||||||
- [核心功能](#核心功能)
|
|
||||||
- [技术栈](#技术栈)
|
|
||||||
- [安装部署](#安装部署)
|
|
||||||
- [配置说明](#配置说明)
|
|
||||||
- [使用指南](#使用指南)
|
|
||||||
- [API接口](#api接口)
|
|
||||||
- [数据库设计](#数据库设计)
|
|
||||||
- [开发指南](#开发指南)
|
|
||||||
- [故障排除](#故障排除)
|
|
||||||
- [更新日志](#更新日志)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 项目概述
|
|
||||||
|
|
||||||
TSP智能助手是一个基于大语言模型的智能客服系统,专为TSP(Telematics Service Provider)车辆服务提供商设计。系统集成了智能对话、工单管理、知识库、数据分析、飞书集成等核心功能。
|
|
||||||
|
|
||||||
### 核心特性
|
|
||||||
- **智能Agent架构**: 多工具集成,智能规划,自主学习
|
|
||||||
- **实时对话系统**: WebSocket支持,上下文理解,VIN识别
|
|
||||||
- **数据驱动分析**: 真实数据统计,可视化展示,系统监控
|
|
||||||
- **企业级管理**: 多环境部署,版本控制,热更新,自动备份
|
|
||||||
- **飞书集成**: 支持飞书多维表格数据同步和管理
|
|
||||||
- **AI准确率优化**: 智能判断AI建议质量,优先使用高质量内容入库
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ 系统架构
|
|
||||||
|
|
||||||
### 整体架构
|
|
||||||
```
|
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ 前端界面 │ │ 后端服务 │ │ 数据存储 │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ • 仪表板 │◄──►│ • Flask API │◄──►│ • MySQL DB │
|
|
||||||
│ • 智能对话 │ │ • WebSocket │ │ • 知识库 │
|
|
||||||
│ • Agent管理 │ │ • Agent核心 │ │ • 工单系统 │
|
|
||||||
│ • 数据分析 │ │ • LLM集成 │ │ • 车辆数据 │
|
|
||||||
│ • 飞书同步 │ │ • 备份系统 │ │ • SQLite备份 │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 模块化设计
|
|
||||||
- **Web层**: Flask蓝图架构,模块化API设计
|
|
||||||
- **业务层**: Agent核心、对话管理、工单处理
|
|
||||||
- **数据层**: MySQL主库 + SQLite备份,ORM映射
|
|
||||||
- **集成层**: 飞书API、LLM服务、监控系统
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 核心功能
|
|
||||||
|
|
||||||
### 1. 智能对话系统 💬
|
|
||||||
- **多轮对话**: 支持上下文关联的连续对话
|
|
||||||
- **VIN识别**: 自动识别车辆VIN并获取实时数据
|
|
||||||
- **知识库检索**: 基于TF-IDF和余弦相似度的智能检索
|
|
||||||
- **工单创建**: 对话中直接创建和关联工单
|
|
||||||
|
|
||||||
### 2. Agent管理系统 🤖
|
|
||||||
- **工具管理**: 10+内置工具,支持自定义工具注册
|
|
||||||
- **执行监控**: 实时监控Agent任务执行状态
|
|
||||||
- **性能统计**: 工具使用频率和成功率分析
|
|
||||||
- **智能规划**: 基于目标的任务分解和执行
|
|
||||||
|
|
||||||
### 3. 工单管理系统 📋
|
|
||||||
- **AI建议生成**: 基于知识库生成工单处理建议
|
|
||||||
- **人工审核**: 支持人工输入和AI建议对比
|
|
||||||
- **语义相似度**: 使用sentence-transformers进行准确度评估
|
|
||||||
- **智能入库**: AI准确率<90%时优先使用人工描述入库
|
|
||||||
- **知识库更新**: 高相似度建议自动入库
|
|
||||||
|
|
||||||
### 4. 知识库管理 📚
|
|
||||||
- **多格式支持**: TXT、PDF、DOC、DOCX、MD文件
|
|
||||||
- **智能提取**: 自动从文档中提取Q&A对
|
|
||||||
- **向量化检索**: TF-IDF + 余弦相似度搜索
|
|
||||||
- **质量验证**: 支持知识条目验证和置信度设置
|
|
||||||
|
|
||||||
### 5. 数据分析系统 📊
|
|
||||||
- **实时趋势**: 基于真实数据的性能趋势分析
|
|
||||||
- **多维度统计**: 工单、预警、满意度等关键指标
|
|
||||||
- **系统健康**: CPU、内存、响应时间监控
|
|
||||||
- **可视化展示**: 丰富的图表和仪表板
|
|
||||||
|
|
||||||
### 6. 飞书集成系统 📱
|
|
||||||
- **多维表格同步**: 自动同步飞书多维表格数据
|
|
||||||
- **字段映射**: 智能映射飞书字段到本地数据库
|
|
||||||
- **实时更新**: 支持增量同步和全量同步
|
|
||||||
- **数据预览**: 同步前预览数据,确保准确性
|
|
||||||
|
|
||||||
### 7. 系统设置管理 ⚙️
|
|
||||||
- **API管理**: 支持多种LLM提供商配置
|
|
||||||
- **模型参数**: 温度、最大令牌数等参数调节
|
|
||||||
- **端口配置**: Web服务和WebSocket端口管理
|
|
||||||
- **日志级别**: 灵活的日志级别控制
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ 技术栈
|
|
||||||
|
|
||||||
### 后端技术
|
|
||||||
- **Python 3.8+**: 核心开发语言
|
|
||||||
- **Flask**: Web框架和API服务
|
|
||||||
- **SQLAlchemy**: ORM数据库操作
|
|
||||||
- **WebSocket**: 实时通信支持
|
|
||||||
- **psutil**: 系统资源监控
|
|
||||||
|
|
||||||
### 前端技术
|
|
||||||
- **Bootstrap 5**: UI框架
|
|
||||||
- **Chart.js**: 数据可视化
|
|
||||||
- **JavaScript ES6+**: 前端逻辑
|
|
||||||
- **WebSocket**: 实时通信客户端
|
|
||||||
|
|
||||||
### AI/ML技术
|
|
||||||
- **大语言模型**: 支持OpenAI、通义千问等
|
|
||||||
- **sentence-transformers**: 语义相似度计算
|
|
||||||
- **TF-IDF**: 文本向量化
|
|
||||||
- **余弦相似度**: 语义相似度计算
|
|
||||||
- **Agent框架**: 智能任务规划
|
|
||||||
|
|
||||||
### 部署运维
|
|
||||||
- **Docker**: 容器化部署
|
|
||||||
- **Nginx**: 反向代理和静态文件服务
|
|
||||||
- **Systemd**: 服务管理
|
|
||||||
- **Git**: 版本控制
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 安装部署
|
|
||||||
|
|
||||||
### 环境要求
|
|
||||||
- Python 3.8+
|
|
||||||
- Node.js 16+ (可选,用于前端构建)
|
|
||||||
- Git
|
|
||||||
- MySQL 8.0+
|
|
||||||
|
|
||||||
### 安装步骤
|
|
||||||
|
|
||||||
1. **克隆项目**
|
|
||||||
```bash
|
|
||||||
git clone http://jeason.online:3000/zhaojie/assist.git
|
|
||||||
cd assist
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **安装依赖**
|
|
||||||
```bash
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **配置数据库**
|
|
||||||
```bash
|
|
||||||
# 创建MySQL数据库
|
|
||||||
mysql -u root -p
|
|
||||||
CREATE DATABASE tsp_assistant CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **初始化数据库**
|
|
||||||
```bash
|
|
||||||
python init_database.py
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **启动服务**
|
|
||||||
```bash
|
|
||||||
python start_dashboard.py
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **访问系统**
|
|
||||||
- 打开浏览器访问: `http://localhost:5000`
|
|
||||||
- 默认端口: 5000 (可在系统设置中修改)
|
|
||||||
|
|
||||||
### Windows快速启动
|
|
||||||
```cmd
|
|
||||||
# 双击运行
|
|
||||||
快速启动.bat
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ 配置说明
|
|
||||||
|
|
||||||
### 环境变量
|
|
||||||
```bash
|
|
||||||
# 数据库配置
|
|
||||||
DATABASE_URL=mysql+pymysql://user:password@host:port/database
|
|
||||||
|
|
||||||
# LLM配置
|
|
||||||
LLM_PROVIDER=openai
|
|
||||||
LLM_API_KEY=your_api_key
|
|
||||||
LLM_MODEL=gpt-3.5-turbo
|
|
||||||
|
|
||||||
# 服务配置
|
|
||||||
SERVER_PORT=5000
|
|
||||||
WEBSOCKET_PORT=8765
|
|
||||||
LOG_LEVEL=INFO
|
|
||||||
```
|
|
||||||
|
|
||||||
### 配置文件结构
|
|
||||||
```
|
|
||||||
config/
|
|
||||||
├── llm_config.py # LLM客户端配置
|
|
||||||
├── integrations_config.json # 飞书集成配置
|
|
||||||
├── ai_accuracy_config.py # AI准确率配置
|
|
||||||
└── README.md # 配置说明文档
|
|
||||||
```
|
|
||||||
|
|
||||||
### 飞书集成配置
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"feishu": {
|
|
||||||
"app_id": "cli_a8b50ec0eed1500d",
|
|
||||||
"app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK",
|
|
||||||
"app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg",
|
|
||||||
"table_id": "tblnl3vJPpgMTSiP",
|
|
||||||
"status": "active"
|
|
||||||
},
|
|
||||||
"system": {
|
|
||||||
"sync_limit": 10,
|
|
||||||
"ai_suggestions_enabled": true,
|
|
||||||
"auto_sync_interval": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### AI准确率配置
|
|
||||||
```python
|
|
||||||
# 默认配置
|
|
||||||
auto_approve_threshold = 0.95 # 自动审批阈值
|
|
||||||
use_human_resolution_threshold = 0.90 # 使用人工描述阈值
|
|
||||||
manual_review_threshold = 0.80 # 人工审核阈值
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📖 使用指南
|
|
||||||
|
|
||||||
### 基础操作
|
|
||||||
|
|
||||||
#### 1. 智能对话
|
|
||||||
1. 在"智能对话"页面输入问题
|
|
||||||
2. 系统自动检索知识库并生成回答
|
|
||||||
3. 支持VIN码识别和车辆数据查询
|
|
||||||
|
|
||||||
#### 2. 工单管理
|
|
||||||
1. 创建工单并获取AI建议
|
|
||||||
2. 输入人工处理描述
|
|
||||||
3. 系统自动计算语义相似度
|
|
||||||
4. 根据相似度决定入库策略
|
|
||||||
|
|
||||||
#### 3. 知识库维护
|
|
||||||
1. 手动添加Q&A对
|
|
||||||
2. 上传文档自动提取知识
|
|
||||||
3. 设置置信度和验证状态
|
|
||||||
|
|
||||||
#### 4. 飞书数据同步
|
|
||||||
1. 配置飞书应用凭证
|
|
||||||
2. 在主仪表板"飞书同步"标签页
|
|
||||||
3. 测试连接并执行数据同步
|
|
||||||
|
|
||||||
### 高级功能
|
|
||||||
|
|
||||||
#### 1. Agent工具管理
|
|
||||||
- 查看工具使用统计
|
|
||||||
- 注册自定义工具
|
|
||||||
- 监控执行历史
|
|
||||||
|
|
||||||
#### 2. 数据分析
|
|
||||||
- 多维度数据统计
|
|
||||||
- 自定义时间范围
|
|
||||||
- 导出分析报告
|
|
||||||
|
|
||||||
#### 3. 系统配置
|
|
||||||
- API和模型参数配置
|
|
||||||
- 端口和日志级别设置
|
|
||||||
- 环境变量管理
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔌 API接口
|
|
||||||
|
|
||||||
### 工单管理API
|
|
||||||
```http
|
|
||||||
POST /api/workorders/{id}/ai-suggestion
|
|
||||||
POST /api/workorders/{id}/human-resolution
|
|
||||||
POST /api/workorders/{id}/approve-to-knowledge
|
|
||||||
GET /api/workorders
|
|
||||||
POST /api/workorders
|
|
||||||
PUT /api/workorders/{id}
|
|
||||||
DELETE /api/workorders/{id}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 知识库API
|
|
||||||
```http
|
|
||||||
GET /api/knowledge
|
|
||||||
POST /api/knowledge
|
|
||||||
PUT /api/knowledge/{id}
|
|
||||||
DELETE /api/knowledge/{id}
|
|
||||||
POST /api/knowledge/search
|
|
||||||
POST /api/knowledge/upload
|
|
||||||
```
|
|
||||||
|
|
||||||
### 对话API
|
|
||||||
```http
|
|
||||||
POST /api/chat/session
|
|
||||||
GET /api/chat/session/{id}
|
|
||||||
DELETE /api/chat/session/{id}
|
|
||||||
POST /api/chat/message
|
|
||||||
```
|
|
||||||
|
|
||||||
### Agent管理API
|
|
||||||
```http
|
|
||||||
GET /api/agent/status
|
|
||||||
POST /api/agent/tools/execute
|
|
||||||
POST /api/agent/tools/register
|
|
||||||
GET /api/agent/tools/stats
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗄️ 数据库设计
|
|
||||||
|
|
||||||
### 核心表结构
|
|
||||||
|
|
||||||
#### work_orders (工单表)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE work_orders (
|
|
||||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
order_id VARCHAR(50) UNIQUE NOT NULL,
|
|
||||||
title VARCHAR(200) NOT NULL,
|
|
||||||
description TEXT NOT NULL,
|
|
||||||
category VARCHAR(100) NOT NULL,
|
|
||||||
priority VARCHAR(20) NOT NULL,
|
|
||||||
status VARCHAR(20) NOT NULL,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
resolution TEXT,
|
|
||||||
satisfaction_score FLOAT,
|
|
||||||
|
|
||||||
-- 飞书集成字段
|
|
||||||
feishu_record_id VARCHAR(100),
|
|
||||||
source VARCHAR(50),
|
|
||||||
module VARCHAR(100),
|
|
||||||
created_by VARCHAR(100),
|
|
||||||
wilfulness VARCHAR(100),
|
|
||||||
date_of_close DATETIME,
|
|
||||||
vehicle_type VARCHAR(100),
|
|
||||||
vin_sim VARCHAR(50),
|
|
||||||
app_remote_control_version VARCHAR(100),
|
|
||||||
hmi_sw VARCHAR(100),
|
|
||||||
parent_record VARCHAR(100),
|
|
||||||
has_updated_same_day VARCHAR(50),
|
|
||||||
operating_time VARCHAR(100)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### work_order_suggestions (工单建议表)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE work_order_suggestions (
|
|
||||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
work_order_id INT NOT NULL,
|
|
||||||
ai_suggestion TEXT,
|
|
||||||
human_resolution TEXT,
|
|
||||||
ai_similarity FLOAT,
|
|
||||||
approved BOOLEAN DEFAULT FALSE,
|
|
||||||
use_human_resolution BOOLEAN DEFAULT FALSE,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### knowledge_entries (知识库表)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE knowledge_entries (
|
|
||||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
question TEXT NOT NULL,
|
|
||||||
answer TEXT NOT NULL,
|
|
||||||
category VARCHAR(100),
|
|
||||||
confidence_score FLOAT DEFAULT 0.5,
|
|
||||||
usage_count INT DEFAULT 0,
|
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
|
||||||
is_verified BOOLEAN DEFAULT FALSE,
|
|
||||||
verified_by VARCHAR(100),
|
|
||||||
verified_at DATETIME,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 👨💻 开发指南
|
|
||||||
|
|
||||||
### 项目结构
|
|
||||||
```
|
|
||||||
tsp-assistant/
|
|
||||||
├── src/ # 源代码
|
|
||||||
│ ├── agent/ # Agent核心模块
|
|
||||||
│ ├── analytics/ # 数据分析模块
|
|
||||||
│ ├── config/ # 配置模块
|
|
||||||
│ ├── core/ # 核心模块
|
|
||||||
│ ├── dialogue/ # 对话模块
|
|
||||||
│ ├── integrations/ # 集成模块
|
|
||||||
│ ├── knowledge_base/ # 知识库模块
|
|
||||||
│ ├── utils/ # 工具模块
|
|
||||||
│ ├── vehicle/ # 车辆数据模块
|
|
||||||
│ └── web/ # Web应用模块
|
|
||||||
├── config/ # 配置文件
|
|
||||||
├── scripts/ # 脚本文件
|
|
||||||
├── uploads/ # 上传文件
|
|
||||||
├── requirements.txt # 依赖文件
|
|
||||||
├── init_database.py # 数据库初始化
|
|
||||||
└── start_dashboard.py # 启动脚本
|
|
||||||
```
|
|
||||||
|
|
||||||
### 代码规范
|
|
||||||
- **Python**: 遵循PEP 8规范
|
|
||||||
- **JavaScript**: 使用ES6+语法
|
|
||||||
- **提交信息**: 使用约定式提交格式
|
|
||||||
- **文档**: 新功能需要添加相应的文档
|
|
||||||
|
|
||||||
### 开发流程
|
|
||||||
1. Fork项目到个人仓库
|
|
||||||
2. 创建功能分支: `git checkout -b feature/new-feature`
|
|
||||||
3. 提交更改: `git commit -m "Add new feature"`
|
|
||||||
4. 推送分支: `git push origin feature/new-feature`
|
|
||||||
5. 创建Pull Request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 故障排除
|
|
||||||
|
|
||||||
### 常见问题
|
|
||||||
|
|
||||||
#### 1. 数据库连接失败
|
|
||||||
```bash
|
|
||||||
# 检查数据库服务状态
|
|
||||||
systemctl status mysql
|
|
||||||
|
|
||||||
# 检查连接配置
|
|
||||||
python -c "from src.core.database import db_manager; print(db_manager.test_connection())"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 飞书集成问题
|
|
||||||
- 检查飞书应用权限配置
|
|
||||||
- 验证app_token和table_id是否正确
|
|
||||||
- 确认网络连接和API访问权限
|
|
||||||
|
|
||||||
#### 3. AI建议生成失败
|
|
||||||
- 检查LLM API配置
|
|
||||||
- 验证知识库数据完整性
|
|
||||||
- 查看应用日志
|
|
||||||
|
|
||||||
#### 4. 数据库字段缺失
|
|
||||||
```bash
|
|
||||||
# 运行数据库迁移
|
|
||||||
python init_database.py
|
|
||||||
|
|
||||||
# 手动添加字段
|
|
||||||
mysql -u root -p tsp_assistant
|
|
||||||
ALTER TABLE work_order_suggestions ADD COLUMN use_human_resolution BOOLEAN DEFAULT FALSE;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 日志位置
|
|
||||||
- **应用日志**: `logs/tsp_assistant.log`
|
|
||||||
- **访问日志**: Nginx访问日志
|
|
||||||
- **错误追踪**: 详细的错误堆栈信息
|
|
||||||
|
|
||||||
### 性能优化
|
|
||||||
- **数据库索引**: 为常用查询字段添加索引
|
|
||||||
- **缓存策略**: 使用Redis缓存热点数据
|
|
||||||
- **异步处理**: 耗时操作使用异步处理
|
|
||||||
- **连接池**: 配置数据库连接池
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 更新日志
|
|
||||||
|
|
||||||
### v1.4.0 (2025-09-19)
|
|
||||||
- ✅ 飞书集成功能:支持飞书多维表格数据同步
|
|
||||||
- ✅ 页面功能合并:飞书同步页面合并到主仪表板
|
|
||||||
- ✅ 数据库架构优化:扩展工单表字段,支持飞书数据
|
|
||||||
- ✅ 代码重构优化:大文件拆分,降低运行风险
|
|
||||||
- ✅ 字段映射完善:智能映射飞书字段到本地数据库
|
|
||||||
- ✅ 数据库初始化改进:集成字段迁移到初始化流程
|
|
||||||
- ✅ AI准确率优化:AI准确率<90%时优先使用人工描述入库
|
|
||||||
- ✅ 语义相似度计算:使用sentence-transformers提升准确度
|
|
||||||
|
|
||||||
### v1.3.0 (2025-09-17)
|
|
||||||
- ✅ 数据库架构优化:MySQL主数据库+SQLite备份系统
|
|
||||||
- ✅ 工单详情API修复:解决数据库会话管理问题
|
|
||||||
- ✅ 备份管理系统:自动备份MySQL数据到SQLite
|
|
||||||
- ✅ 数据库状态监控:实时监控MySQL和SQLite状态
|
|
||||||
- ✅ 备份管理API:支持数据备份和恢复操作
|
|
||||||
|
|
||||||
### v1.2.0 (2025-09-16)
|
|
||||||
- ✅ 系统设置扩展:API管理、模型参数配置、端口管理
|
|
||||||
- ✅ 真实数据分析:修复性能趋势图表显示问题
|
|
||||||
- ✅ 工单AI建议功能:智能生成处理建议
|
|
||||||
- ✅ 知识库搜索优化:提升检索准确率
|
|
||||||
- ✅ Agent管理改进:工具使用统计和自定义工具
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 许可证
|
|
||||||
|
|
||||||
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
|
|
||||||
|
|
||||||
## 📞 支持与联系
|
|
||||||
|
|
||||||
- **项目地址**: http://jeason.online:3000/zhaojie/assist
|
|
||||||
- **问题反馈**: 请在Issues中提交问题
|
|
||||||
- **功能建议**: 欢迎提交Feature Request
|
|
||||||
|
|
||||||
## 🙏 致谢
|
|
||||||
|
|
||||||
感谢所有为项目做出贡献的开发者和用户!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**TSP智能助手** - 让车辆服务更智能,让客户体验更美好! 🚗✨
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# UTF-8 编码规范
|
|
||||||
|
|
||||||
## 项目编码标准
|
|
||||||
|
|
||||||
本项目所有文件必须使用 **UTF-8** 编码格式,以确保中文和特殊字符的正确显示和处理。
|
|
||||||
|
|
||||||
## 文件编码要求
|
|
||||||
|
|
||||||
### 1. Python 文件
|
|
||||||
- **必须** 在文件开头添加编码声明:
|
|
||||||
```python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
```
|
|
||||||
或
|
|
||||||
```python
|
|
||||||
# coding: utf-8
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 文件保存
|
|
||||||
- 所有文件保存时使用 **UTF-8** 编码(无BOM)
|
|
||||||
- 禁止使用 GBK、GB2312 等其他编码格式
|
|
||||||
|
|
||||||
### 3. 文件读取/写入
|
|
||||||
- 所有文件操作必须明确指定 `encoding='utf-8'`:
|
|
||||||
```python
|
|
||||||
with open('file.txt', 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
with open('file.txt', 'w', encoding='utf-8') as f:
|
|
||||||
f.write(content)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cursor/VS Code 配置
|
|
||||||
|
|
||||||
项目已配置 `.vscode/settings.json`,确保:
|
|
||||||
- 默认文件编码:UTF-8
|
|
||||||
- 自动检测编码:禁用(避免误判)
|
|
||||||
- 文件行尾:LF(Unix风格)
|
|
||||||
|
|
||||||
## 控制台输出
|
|
||||||
|
|
||||||
### Windows 系统
|
|
||||||
在 Python 脚本中,需要设置标准输出编码:
|
|
||||||
```python
|
|
||||||
import sys
|
|
||||||
import io
|
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
|
||||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
|
||||||
```
|
|
||||||
|
|
||||||
## 检查脚本
|
|
||||||
|
|
||||||
使用 `check_encoding.py` 脚本检查所有文件的编码格式:
|
|
||||||
```bash
|
|
||||||
python check_encoding.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### 1. 控制台输出乱码
|
|
||||||
- 确保文件以 UTF-8 保存
|
|
||||||
- 在脚本开头设置标准输出编码
|
|
||||||
- Windows 系统运行 `chcp 65001` 设置控制台代码页
|
|
||||||
|
|
||||||
### 2. 文件读取乱码
|
|
||||||
- 检查文件实际编码(可用 `check_encoding.py`)
|
|
||||||
- 确保使用 `encoding='utf-8'` 参数
|
|
||||||
|
|
||||||
### 3. 文件保存乱码
|
|
||||||
- 检查编辑器编码设置
|
|
||||||
- 确保 Cursor/VS Code 设置为 UTF-8
|
|
||||||
|
|
||||||
## 验证清单
|
|
||||||
|
|
||||||
创建新文件时,请确认:
|
|
||||||
- [ ] 文件以 UTF-8 编码保存
|
|
||||||
- [ ] Python 文件包含编码声明
|
|
||||||
- [ ] 文件读写操作指定 `encoding='utf-8'`
|
|
||||||
- [ ] 控制台输出脚本设置了 UTF-8 编码
|
|
||||||
- [ ] 测试输出中文显示正常
|
|
||||||
|
|
||||||
Binary file not shown.
302
auto_push.bat
302
auto_push.bat
@@ -1,302 +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] 推送到远程仓库...
|
|
||||||
|
|
||||||
:: 获取当前分支名称(在延迟变量扩展内)
|
|
||||||
set current_branch=
|
|
||||||
for /f "tokens=*" %%b in ('git branch --show-current 2^>nul') do set current_branch=%%b
|
|
||||||
|
|
||||||
if "!current_branch!"=="" (
|
|
||||||
echo ❌ 无法获取当前分支名称
|
|
||||||
echo 尝试使用默认分支 main...
|
|
||||||
set current_branch=main
|
|
||||||
) else (
|
|
||||||
echo 📍 当前分支: !current_branch!
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 先尝试拉取最新更改
|
|
||||||
echo 🔄 检查远程更新...
|
|
||||||
git fetch origin !current_branch! >nul 2>&1
|
|
||||||
set fetch_result=!errorlevel!
|
|
||||||
if !fetch_result! neq 0 (
|
|
||||||
echo ⚠️ 无法获取远程更新,尝试获取所有分支...
|
|
||||||
git fetch origin >nul 2>&1
|
|
||||||
set fetch_all_result=!errorlevel!
|
|
||||||
if !fetch_all_result! neq 0 (
|
|
||||||
echo ⚠️ 无法获取远程更新,继续推送...
|
|
||||||
) else (
|
|
||||||
echo ✅ 远程更新检查完成
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
echo ✅ 远程更新检查完成
|
|
||||||
)
|
|
||||||
|
|
||||||
:: 检查远程分支是否存在,如果不存在则设置上游
|
|
||||||
echo 🔍 检查远程分支状态...
|
|
||||||
git ls-remote --heads origin !current_branch! >nul 2>&1
|
|
||||||
set remote_exists=!errorlevel!
|
|
||||||
set push_result=0
|
|
||||||
|
|
||||||
if !remote_exists! equ 0 (
|
|
||||||
echo 远程分支 !current_branch! 已存在
|
|
||||||
:: 推送到远程(分支已存在)
|
|
||||||
git push origin !current_branch!
|
|
||||||
set push_result=!errorlevel!
|
|
||||||
) else (
|
|
||||||
echo 远程分支 !current_branch! 不存在,将创建并设置上游
|
|
||||||
:: 推送到远程并设置上游(分支不存在)
|
|
||||||
git push -u origin !current_branch!
|
|
||||||
set push_result=!errorlevel!
|
|
||||||
)
|
|
||||||
|
|
||||||
if !push_result! neq 0 (
|
|
||||||
echo ❌ 推送失败
|
|
||||||
echo.
|
|
||||||
echo 💡 可能的原因:
|
|
||||||
echo - 网络连接问题
|
|
||||||
echo - 远程仓库权限不足
|
|
||||||
echo - 分支冲突
|
|
||||||
echo - 需要先拉取远程更改
|
|
||||||
echo.
|
|
||||||
echo 🔧 尝试自动解决冲突...
|
|
||||||
git pull origin !current_branch! --rebase
|
|
||||||
set pull_result=!errorlevel!
|
|
||||||
if !pull_result! equ 0 (
|
|
||||||
echo ✅ 冲突已解决,重新推送...
|
|
||||||
git push origin !current_branch!
|
|
||||||
set final_push_result=!errorlevel!
|
|
||||||
if !final_push_result! equ 0 (
|
|
||||||
echo ✅ 推送成功!
|
|
||||||
) else (
|
|
||||||
echo ❌ 重新推送失败
|
|
||||||
echo.
|
|
||||||
echo 🔧 建议手动解决:
|
|
||||||
echo 1. 运行: git pull origin !current_branch!
|
|
||||||
echo 2. 解决冲突后运行: git push origin !current_branch!
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
echo ❌ 无法自动解决冲突
|
|
||||||
echo.
|
|
||||||
echo 🔧 建议手动解决:
|
|
||||||
echo 1. 运行: git pull origin !current_branch!
|
|
||||||
echo 2. 解决冲突后运行: git push origin !current_branch!
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
echo ✅ 推送成功!
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo ✅ 推送完成!
|
|
||||||
echo ========================================
|
|
||||||
echo 📊 提交统计:
|
|
||||||
git log --oneline -1
|
|
||||||
echo.
|
|
||||||
echo 🌐 远程仓库状态:
|
|
||||||
git status
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
268
auto_push.ps1
268
auto_push.ps1
@@ -1,268 +0,0 @@
|
|||||||
# TSP智能助手 - 自动推送脚本 (PowerShell版本)
|
|
||||||
# 使用方法: .\auto_push.ps1 [提交信息]
|
|
||||||
|
|
||||||
param(
|
|
||||||
[string]$CommitMessage = "",
|
|
||||||
[switch]$Force = $false,
|
|
||||||
[switch]$NoConfirm = $false
|
|
||||||
)
|
|
||||||
|
|
||||||
# 设置控制台编码
|
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
||||||
|
|
||||||
# 颜色输出函数
|
|
||||||
function Write-ColorOutput {
|
|
||||||
param(
|
|
||||||
[string]$Message,
|
|
||||||
[string]$Color = "White"
|
|
||||||
)
|
|
||||||
Write-Host $Message -ForegroundColor $Color
|
|
||||||
}
|
|
||||||
|
|
||||||
function Write-Step {
|
|
||||||
param(
|
|
||||||
[int]$Step,
|
|
||||||
[int]$Total,
|
|
||||||
[string]$Message
|
|
||||||
)
|
|
||||||
Write-ColorOutput "[$Step/$Total] $Message" "Cyan"
|
|
||||||
}
|
|
||||||
|
|
||||||
function Show-GitStatus {
|
|
||||||
Write-ColorOutput "`n📋 当前Git状态:" "Yellow"
|
|
||||||
$status = git status --porcelain
|
|
||||||
if ($status) {
|
|
||||||
$status | ForEach-Object {
|
|
||||||
$line = $_
|
|
||||||
if ($line.StartsWith("??")) {
|
|
||||||
Write-ColorOutput " + $($line.Substring(3))" "Green"
|
|
||||||
} elseif ($line.StartsWith(" M")) {
|
|
||||||
Write-ColorOutput " ~ $($line.Substring(3))" "Yellow"
|
|
||||||
} elseif ($line.StartsWith(" D")) {
|
|
||||||
Write-ColorOutput " - $($line.Substring(3))" "Red"
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput " $line" "White"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput " 工作区干净,无更改" "Green"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-CommitMessage {
|
|
||||||
if ($CommitMessage) {
|
|
||||||
return $CommitMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
# 尝试从最近提交生成智能消息
|
|
||||||
$lastCommit = git log --oneline -1 2>$null
|
|
||||||
if ($lastCommit) {
|
|
||||||
$suggested = "feat: 自动提交更新 - $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
|
|
||||||
} else {
|
|
||||||
$suggested = "feat: 初始提交 - $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-ColorOutput "`n💡 建议的提交信息: $suggested" "Cyan"
|
|
||||||
$custom = Read-Host "请输入自定义提交信息 (直接回车使用建议)"
|
|
||||||
|
|
||||||
if ($custom) {
|
|
||||||
return $custom
|
|
||||||
} else {
|
|
||||||
return $suggested
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Test-GitRepository {
|
|
||||||
try {
|
|
||||||
git status --porcelain >$null 2>&1
|
|
||||||
return $LASTEXITCODE -eq 0
|
|
||||||
} catch {
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Show-CommitStats {
|
|
||||||
Write-ColorOutput "`n📊 提交统计:" "Yellow"
|
|
||||||
$commitHash = git log --oneline -1 | Select-String -Pattern "^\w+" | ForEach-Object { $_.Matches[0].Value }
|
|
||||||
$filesChanged = git diff --cached --numstat | Measure-Object | Select-Object -ExpandProperty Count
|
|
||||||
$insertions = git diff --cached --numstat | ForEach-Object {
|
|
||||||
$parts = $_ -split '\s+'
|
|
||||||
if ($parts[0] -match '^\d+$') { [int]$parts[0] } else { 0 }
|
|
||||||
} | Measure-Object -Sum | Select-Object -ExpandProperty Sum
|
|
||||||
$deletions = git diff --cached --numstat | ForEach-Object {
|
|
||||||
$parts = $_ -split '\s+'
|
|
||||||
if ($parts[1] -match '^\d+$') { [int]$parts[1] } else { 0 }
|
|
||||||
} | Measure-Object -Sum | Select-Object -ExpandProperty Sum
|
|
||||||
|
|
||||||
Write-ColorOutput " 提交哈希: $commitHash" "White"
|
|
||||||
Write-ColorOutput " 文件变更: $filesChanged 个文件" "White"
|
|
||||||
Write-ColorOutput " 新增行数: $insertions 行" "Green"
|
|
||||||
Write-ColorOutput " 删除行数: $deletions 行" "Red"
|
|
||||||
Write-ColorOutput " 净增加: $($insertions - $deletions) 行" "Cyan"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主程序开始
|
|
||||||
Write-ColorOutput "========================================" "Magenta"
|
|
||||||
Write-ColorOutput "TSP智能助手 - 自动推送脚本 v2.0" "Magenta"
|
|
||||||
Write-ColorOutput "========================================" "Magenta"
|
|
||||||
|
|
||||||
# 检查Git仓库
|
|
||||||
Write-Step 1 4 "检查Git仓库状态"
|
|
||||||
if (-not (Test-GitRepository)) {
|
|
||||||
Write-ColorOutput "❌ Git未初始化或不在Git仓库中" "Red"
|
|
||||||
Write-ColorOutput "请确保在正确的Git仓库目录中运行此脚本" "Yellow"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Write-ColorOutput "✅ Git仓库状态正常" "Green"
|
|
||||||
|
|
||||||
# 显示状态
|
|
||||||
Show-GitStatus
|
|
||||||
|
|
||||||
# 检查是否有更改
|
|
||||||
$hasChanges = git status --porcelain | Measure-Object | Select-Object -ExpandProperty Count
|
|
||||||
if ($hasChanges -eq 0) {
|
|
||||||
Write-ColorOutput "`n✅ 工作区干净,无需提交" "Green"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 显示详细状态
|
|
||||||
Write-ColorOutput "`n📊 详细状态信息:" "Yellow"
|
|
||||||
|
|
||||||
# 检查未暂存的更改
|
|
||||||
$unstaged = git diff --name-only 2>$null
|
|
||||||
if ($unstaged) {
|
|
||||||
Write-ColorOutput " 未暂存更改: $($unstaged.Count) 个文件" "Yellow"
|
|
||||||
$unstaged | ForEach-Object { Write-ColorOutput " ~ $_" "Yellow" }
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput " 未暂存更改: 无" "Green"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查已暂存的更改
|
|
||||||
$staged = git diff --cached --name-only 2>$null
|
|
||||||
if ($staged) {
|
|
||||||
Write-ColorOutput " 已暂存更改: $($staged.Count) 个文件" "Green"
|
|
||||||
$staged | ForEach-Object { Write-ColorOutput " + $_" "Green" }
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput " 已暂存更改: 无" "Green"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查未跟踪的文件
|
|
||||||
$untracked = git ls-files --others --exclude-standard 2>$null
|
|
||||||
if ($untracked) {
|
|
||||||
Write-ColorOutput " 未跟踪文件: $($untracked.Count) 个文件" "Cyan"
|
|
||||||
$untracked | ForEach-Object { Write-ColorOutput " + $_" "Cyan" }
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput " 未跟踪文件: 无" "Green"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 确认操作
|
|
||||||
if (-not $NoConfirm) {
|
|
||||||
Write-ColorOutput "`n❓ 是否继续推送?" "Yellow"
|
|
||||||
$confirm = Read-Host "输入 'y' 继续,其他键取消"
|
|
||||||
if ($confirm -ne 'y') {
|
|
||||||
Write-ColorOutput "操作已取消" "Yellow"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 添加文件
|
|
||||||
Write-Step 2 4 "添加所有更改到暂存区"
|
|
||||||
try {
|
|
||||||
git add .
|
|
||||||
Write-ColorOutput "✅ 文件已添加到暂存区" "Green"
|
|
||||||
} catch {
|
|
||||||
Write-ColorOutput "❌ 添加文件失败: $($_.Exception.Message)" "Red"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成提交信息
|
|
||||||
Write-Step 3 4 "生成提交信息"
|
|
||||||
$finalCommitMessage = Get-CommitMessage
|
|
||||||
Write-ColorOutput "提交信息: $finalCommitMessage" "Cyan"
|
|
||||||
|
|
||||||
# 提交更改
|
|
||||||
try {
|
|
||||||
git commit -m $finalCommitMessage
|
|
||||||
Write-ColorOutput "✅ 提交成功" "Green"
|
|
||||||
} catch {
|
|
||||||
Write-ColorOutput "❌ 提交失败: $($_.Exception.Message)" "Red"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 推送到远程
|
|
||||||
Write-Step 4 4 "推送到远程仓库"
|
|
||||||
|
|
||||||
# 先尝试拉取最新更改
|
|
||||||
Write-ColorOutput "🔄 检查远程更新..." "Cyan"
|
|
||||||
try {
|
|
||||||
git fetch origin main
|
|
||||||
Write-ColorOutput "✅ 远程更新检查完成" "Green"
|
|
||||||
} catch {
|
|
||||||
Write-ColorOutput "⚠️ 无法获取远程更新,继续推送..." "Yellow"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 推送到远程
|
|
||||||
try {
|
|
||||||
git push origin main
|
|
||||||
Write-ColorOutput "✅ 推送成功" "Green"
|
|
||||||
} catch {
|
|
||||||
Write-ColorOutput "❌ 推送失败: $($_.Exception.Message)" "Red"
|
|
||||||
Write-ColorOutput "`n💡 可能的原因:" "Yellow"
|
|
||||||
Write-ColorOutput " - 网络连接问题" "White"
|
|
||||||
Write-ColorOutput " - 远程仓库权限不足" "White"
|
|
||||||
Write-ColorOutput " - 分支冲突" "White"
|
|
||||||
Write-ColorOutput " - 需要先拉取远程更改" "White"
|
|
||||||
|
|
||||||
Write-ColorOutput "`n🔧 尝试自动解决冲突..." "Cyan"
|
|
||||||
try {
|
|
||||||
git pull origin main --rebase
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
|
||||||
Write-ColorOutput "✅ 冲突已解决,重新推送..." "Green"
|
|
||||||
git push origin main
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
|
||||||
Write-ColorOutput "✅ 推送成功!" "Green"
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput "❌ 重新推送失败" "Red"
|
|
||||||
Write-ColorOutput "`n🔧 建议手动解决:" "Yellow"
|
|
||||||
Write-ColorOutput " 1. 运行: git pull origin main" "White"
|
|
||||||
Write-ColorOutput " 2. 解决冲突后运行: git push origin main" "White"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-ColorOutput "❌ 无法自动解决冲突" "Red"
|
|
||||||
Write-ColorOutput "`n🔧 建议手动解决:" "Yellow"
|
|
||||||
Write-ColorOutput " 1. 运行: git pull origin main" "White"
|
|
||||||
Write-ColorOutput " 2. 解决冲突后运行: git push origin main" "White"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Write-ColorOutput "❌ 自动解决冲突失败: $($_.Exception.Message)" "Red"
|
|
||||||
Write-ColorOutput "`n🔧 建议手动解决:" "Yellow"
|
|
||||||
Write-ColorOutput " 1. 运行: git pull origin main" "White"
|
|
||||||
Write-ColorOutput " 2. 解决冲突后运行: git push origin main" "White"
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 显示结果
|
|
||||||
Write-ColorOutput "`n========================================" "Magenta"
|
|
||||||
Write-ColorOutput "✅ 推送完成!" "Green"
|
|
||||||
Write-ColorOutput "========================================" "Magenta"
|
|
||||||
|
|
||||||
Show-CommitStats
|
|
||||||
|
|
||||||
Write-ColorOutput "`n🌐 远程仓库状态:" "Yellow"
|
|
||||||
git status --short
|
|
||||||
|
|
||||||
Write-ColorOutput "`n🎉 所有操作完成!" "Green"
|
|
||||||
if (-not $NoConfirm) {
|
|
||||||
Read-Host "按任意键退出"
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
from src.core.database import db_manager
|
|
||||||
from sqlalchemy import text, inspect
|
|
||||||
|
|
||||||
print("Checking users table structure...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
with db_manager.get_session() as session:
|
|
||||||
inspector = inspect(db_manager.engine)
|
|
||||||
cols = inspector.get_columns('users')
|
|
||||||
|
|
||||||
print("\nUsers table columns:")
|
|
||||||
required_fields = {}
|
|
||||||
optional_fields = {}
|
|
||||||
|
|
||||||
for col in cols:
|
|
||||||
name = col['name']
|
|
||||||
nullable = col.get('nullable', True)
|
|
||||||
default = col.get('default', None)
|
|
||||||
|
|
||||||
if nullable or default is not None:
|
|
||||||
optional_fields[name] = col
|
|
||||||
print(f" {name}: {col['type']} (nullable: {nullable}, default: {default})")
|
|
||||||
else:
|
|
||||||
required_fields[name] = col
|
|
||||||
print(f" {name}: {col['type']} (REQUIRED, nullable: {nullable})")
|
|
||||||
|
|
||||||
print(f"\nRequired fields: {list(required_fields.keys())}")
|
|
||||||
print(f"Optional fields: {list(optional_fields.keys())}")
|
|
||||||
|
|
||||||
# Check for existing admin user
|
|
||||||
result = session.execute(text("SELECT * FROM users WHERE username = 'admin' LIMIT 1"))
|
|
||||||
admin_row = result.fetchone()
|
|
||||||
|
|
||||||
if admin_row:
|
|
||||||
print("\nAdmin user found in database")
|
|
||||||
# Update password
|
|
||||||
from werkzeug.security import generate_password_hash
|
|
||||||
password_hash = generate_password_hash('admin123')
|
|
||||||
session.execute(text("""
|
|
||||||
UPDATE users
|
|
||||||
SET password_hash = :password_hash,
|
|
||||||
is_active = 1,
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE username = 'admin'
|
|
||||||
"""), {'password_hash': password_hash})
|
|
||||||
session.commit()
|
|
||||||
print("Admin password updated successfully")
|
|
||||||
else:
|
|
||||||
print("\nAdmin user not found, creating...")
|
|
||||||
from werkzeug.security import generate_password_hash
|
|
||||||
password_hash = generate_password_hash('admin123')
|
|
||||||
|
|
||||||
# Build INSERT with all required fields
|
|
||||||
insert_fields = ['username', 'email', 'password_hash', 'role']
|
|
||||||
insert_values = {
|
|
||||||
'username': 'admin',
|
|
||||||
'email': 'admin@tsp.com',
|
|
||||||
'password_hash': password_hash,
|
|
||||||
'role': 'admin'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add optional fields that exist in table
|
|
||||||
if 'is_active' in optional_fields or 'is_active' not in required_fields:
|
|
||||||
insert_fields.append('is_active')
|
|
||||||
insert_values['is_active'] = True
|
|
||||||
|
|
||||||
if 'region' in optional_fields or 'region' not in required_fields:
|
|
||||||
insert_fields.append('region')
|
|
||||||
insert_values['region'] = None
|
|
||||||
|
|
||||||
# Handle full_name if it exists
|
|
||||||
if 'full_name' in required_fields:
|
|
||||||
insert_fields.append('full_name')
|
|
||||||
insert_values['full_name'] = 'Administrator'
|
|
||||||
elif 'full_name' in optional_fields:
|
|
||||||
insert_fields.append('full_name')
|
|
||||||
insert_values['full_name'] = 'Administrator'
|
|
||||||
|
|
||||||
# Handle other required fields with defaults
|
|
||||||
for field_name in required_fields:
|
|
||||||
if field_name not in insert_fields:
|
|
||||||
if field_name in ['created_at', 'updated_at']:
|
|
||||||
insert_fields.append(field_name)
|
|
||||||
insert_values[field_name] = 'NOW()'
|
|
||||||
else:
|
|
||||||
# Use empty string or default value
|
|
||||||
insert_fields.append(field_name)
|
|
||||||
insert_values[field_name] = ''
|
|
||||||
|
|
||||||
fields_str = ', '.join(insert_fields)
|
|
||||||
values_str = ', '.join([f':{f}' for f in insert_fields])
|
|
||||||
|
|
||||||
sql = f"""
|
|
||||||
INSERT INTO users ({fields_str})
|
|
||||||
VALUES ({values_str})
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Fix NOW() placeholders
|
|
||||||
final_values = {}
|
|
||||||
for k, v in insert_values.items():
|
|
||||||
if v == 'NOW()':
|
|
||||||
# Will use SQL NOW()
|
|
||||||
continue
|
|
||||||
final_values[k] = v
|
|
||||||
|
|
||||||
# Use raw SQL with NOW()
|
|
||||||
sql_final = f"""
|
|
||||||
INSERT INTO users ({fields_str.replace(':created_at', 'created_at').replace(':updated_at', 'updated_at')})
|
|
||||||
VALUES ({values_str.replace(':created_at', 'NOW()').replace(':updated_at', 'NOW()')})
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Clean up the SQL
|
|
||||||
for k in ['created_at', 'updated_at']:
|
|
||||||
if f':{k}' in values_str:
|
|
||||||
values_str = values_str.replace(f':{k}', 'NOW()')
|
|
||||||
if k in final_values:
|
|
||||||
del final_values[k]
|
|
||||||
|
|
||||||
# Final SQL construction
|
|
||||||
final_sql = f"INSERT INTO users ({', '.join([f if f not in ['created_at', 'updated_at'] else f for f in insert_fields])}) VALUES ({', '.join([f':{f}' if f not in ['created_at', 'updated_at'] else 'NOW()' for f in insert_fields])})"
|
|
||||||
|
|
||||||
print(f"Executing SQL with fields: {insert_fields}")
|
|
||||||
session.execute(text(final_sql), final_values)
|
|
||||||
session.commit()
|
|
||||||
print("Admin user created successfully")
|
|
||||||
|
|
||||||
# Verify
|
|
||||||
result = session.execute(text("SELECT username, email, role, is_active FROM users WHERE username = 'admin'"))
|
|
||||||
admin_data = result.fetchone()
|
|
||||||
if admin_data:
|
|
||||||
print(f"\nVerification:")
|
|
||||||
print(f" Username: {admin_data[0]}")
|
|
||||||
print(f" Email: {admin_data[1]}")
|
|
||||||
print(f" Role: {admin_data[2]}")
|
|
||||||
print(f" Is Active: {admin_data[3]}")
|
|
||||||
print("\nAdmin user ready for login!")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
文件编码检查工具
|
|
||||||
检查项目中所有文件是否使用UTF-8编码
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import chardet
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def check_file_encoding(file_path: Path) -> dict:
|
|
||||||
"""检查文件编码"""
|
|
||||||
try:
|
|
||||||
with open(file_path, 'rb') as f:
|
|
||||||
raw_data = f.read()
|
|
||||||
result = chardet.detect(raw_data)
|
|
||||||
encoding = result.get('encoding', 'unknown')
|
|
||||||
confidence = result.get('confidence', 0)
|
|
||||||
|
|
||||||
# 检查文件是否有BOM
|
|
||||||
has_bom = False
|
|
||||||
if raw_data.startswith(b'\xef\xbb\xbf'):
|
|
||||||
has_bom = True
|
|
||||||
encoding = 'utf-8-sig'
|
|
||||||
|
|
||||||
return {
|
|
||||||
'file': str(file_path),
|
|
||||||
'encoding': encoding,
|
|
||||||
'confidence': confidence,
|
|
||||||
'has_bom': has_bom,
|
|
||||||
'is_utf8': encoding.lower() in ['utf-8', 'utf-8-sig', 'ascii'],
|
|
||||||
'size': len(raw_data)
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
return {
|
|
||||||
'file': str(file_path),
|
|
||||||
'error': str(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
def check_python_file_header(file_path: Path) -> bool:
|
|
||||||
"""检查Python文件是否有编码声明"""
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r', encoding='utf-8') as f:
|
|
||||||
first_lines = [f.readline() for _ in range(3)]
|
|
||||||
for line in first_lines:
|
|
||||||
if 'coding' in line.lower() or 'encoding' in line.lower():
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""主函数"""
|
|
||||||
project_root = Path(__file__).parent
|
|
||||||
|
|
||||||
# 需要检查的文件扩展名
|
|
||||||
check_extensions = {'.py', '.json', '.md', '.txt', '.html', '.css', '.js', '.sql', '.bat', '.sh'}
|
|
||||||
|
|
||||||
# 排除的目录
|
|
||||||
exclude_dirs = {'.git', '.venv', '__pycache__', 'node_modules', '.idea', 'logs', 'data', 'dist', 'build'}
|
|
||||||
|
|
||||||
results = []
|
|
||||||
python_files_without_encoding = []
|
|
||||||
|
|
||||||
print("=" * 80)
|
|
||||||
print("文件编码检查工具")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 遍历所有文件
|
|
||||||
for root, dirs, files in os.walk(project_root):
|
|
||||||
# 排除指定目录
|
|
||||||
dirs[:] = [d for d in dirs if d not in exclude_dirs]
|
|
||||||
|
|
||||||
for file in files:
|
|
||||||
file_path = Path(root) / file
|
|
||||||
|
|
||||||
# 只检查指定扩展名的文件
|
|
||||||
if file_path.suffix.lower() not in check_extensions:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 检查编码
|
|
||||||
result = check_file_encoding(file_path)
|
|
||||||
results.append(result)
|
|
||||||
|
|
||||||
# 检查Python文件的编码声明
|
|
||||||
if file_path.suffix == '.py':
|
|
||||||
if not check_python_file_header(file_path):
|
|
||||||
python_files_without_encoding.append(file_path)
|
|
||||||
|
|
||||||
# 统计结果
|
|
||||||
total_files = len(results)
|
|
||||||
utf8_files = sum(1 for r in results if r.get('is_utf8', False))
|
|
||||||
non_utf8_files = total_files - utf8_files
|
|
||||||
|
|
||||||
print(f"总计检查文件: {total_files}")
|
|
||||||
print(f"UTF-8 编码文件: {utf8_files}")
|
|
||||||
print(f"非 UTF-8 编码文件: {non_utf8_files}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 显示非UTF-8文件
|
|
||||||
if non_utf8_files > 0:
|
|
||||||
print("=" * 80)
|
|
||||||
print("⚠️ 非 UTF-8 编码文件:")
|
|
||||||
print("=" * 80)
|
|
||||||
for result in results:
|
|
||||||
if not result.get('is_utf8', False) and 'error' not in result:
|
|
||||||
print(f" {result['file']}")
|
|
||||||
print(f" 编码: {result['encoding']} (置信度: {result['confidence']:.2%})")
|
|
||||||
if result.get('has_bom'):
|
|
||||||
print(f" ⚠️ 包含 BOM")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 显示缺少编码声明的Python文件
|
|
||||||
if python_files_without_encoding:
|
|
||||||
print("=" * 80)
|
|
||||||
print("⚠️ Python 文件缺少编码声明:")
|
|
||||||
print("=" * 80)
|
|
||||||
for file_path in python_files_without_encoding:
|
|
||||||
print(f" {file_path}")
|
|
||||||
print()
|
|
||||||
print("建议在这些文件开头添加: # -*- coding: utf-8 -*-")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 显示错误
|
|
||||||
errors = [r for r in results if 'error' in r]
|
|
||||||
if errors:
|
|
||||||
print("=" * 80)
|
|
||||||
print("❌ 检查出错的文件:")
|
|
||||||
print("=" * 80)
|
|
||||||
for result in errors:
|
|
||||||
print(f" {result['file']}: {result['error']}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 总结
|
|
||||||
print("=" * 80)
|
|
||||||
if non_utf8_files == 0 and not python_files_without_encoding:
|
|
||||||
print("✅ 所有文件编码检查通过!")
|
|
||||||
else:
|
|
||||||
print("⚠️ 发现编码问题,请根据上述信息修复")
|
|
||||||
print("=" * 80)
|
|
||||||
|
|
||||||
return non_utf8_files == 0 and not python_files_without_encoding
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
try:
|
|
||||||
import chardet
|
|
||||||
except ImportError:
|
|
||||||
print("错误: 需要安装 chardet 库")
|
|
||||||
print("运行: pip install chardet")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
success = main()
|
|
||||||
sys.exit(0 if success else 1)
|
|
||||||
|
|
||||||
178
config/README.md
178
config/README.md
@@ -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. **监控**: 定期检查同步状态和错误日志
|
|
||||||
Binary file not shown.
@@ -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
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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": "openai",
|
|
||||||
"api_key": "",
|
|
||||||
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
||||||
"model": "qwen-turbo",
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
672
config_backup.txt
Normal file
672
config_backup.txt
Normal file
@@ -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(责任人<E4BBBB>?": "wilfulness",
|
||||||
|
"父<>?<3F>录": "parent_record",
|
||||||
|
"AI建<49>??": "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
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
chcp 65001 >nul 2>&1
|
|
||||||
echo ========================================
|
|
||||||
echo 代码文件编码批量转换工具
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 设置要扫描的文件扩展名
|
|
||||||
set "extensions=*.py *.java *.js *.ts *.html *.css *.xml *.json *.md *.txt *.bat *.cmd *.ps1 *.sh *.yml *.yaml *.ini *.cfg *.conf *.properties"
|
|
||||||
|
|
||||||
:: 设置目标目录(默认为当前目录)
|
|
||||||
set "target_dir=%cd%"
|
|
||||||
if not "%~1"=="" set "target_dir=%~1"
|
|
||||||
|
|
||||||
echo 目标目录: %target_dir%
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 检查目录是否存在
|
|
||||||
if not exist "%target_dir%" (
|
|
||||||
echo 错误:指定的目录不存在
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
:: 创建临时目录
|
|
||||||
set "temp_dir=%temp%\encoding_convert_%random%"
|
|
||||||
mkdir "%temp_dir%"
|
|
||||||
|
|
||||||
:: 统计变量
|
|
||||||
set "total_files=0"
|
|
||||||
set "converted_files=0"
|
|
||||||
set "skipped_files=0"
|
|
||||||
|
|
||||||
echo 开始扫描文件...
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 遍历所有指定扩展名的文件
|
|
||||||
for %%e in (%extensions%) do (
|
|
||||||
for /r "%target_dir%" %%f in (%%e) do (
|
|
||||||
set /a total_files+=1
|
|
||||||
call :process_file "%%f"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 转换完成
|
|
||||||
echo ========================================
|
|
||||||
echo 总文件数: %total_files%
|
|
||||||
echo 已转换: %converted_files%
|
|
||||||
echo 已跳过: %skipped_files%
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 清理临时目录
|
|
||||||
rd /s /q "%temp_dir%" 2>nul
|
|
||||||
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
|
|
||||||
:process_file
|
|
||||||
set "file=%~1"
|
|
||||||
set "is_utf8=0"
|
|
||||||
|
|
||||||
:: 检查文件是否已经是UTF-8编码
|
|
||||||
powershell -Command "try { $content = [System.IO.File]::ReadAllText('%file%', [System.Text.Encoding]::UTF8); $content | Out-Null; exit 0 } catch { exit 1 }" >nul 2>&1
|
|
||||||
if %errorlevel% equ 0 set "is_utf8=1"
|
|
||||||
|
|
||||||
if %is_utf8% equ 1 (
|
|
||||||
echo [跳过] %file% (已经是UTF-8)
|
|
||||||
set /a skipped_files+=1
|
|
||||||
) else (
|
|
||||||
echo [转换] %file%
|
|
||||||
|
|
||||||
:: 尝试检测并转换编码
|
|
||||||
powershell -Command ^
|
|
||||||
"$path = '%file%'; ^
|
|
||||||
try { ^
|
|
||||||
$bytes = [System.IO.File]::ReadAllBytes($path); ^
|
|
||||||
$encoding = [System.Text.Encoding]::GetEncoding('GB2312'); ^
|
|
||||||
$content = $encoding.GetString($bytes); ^
|
|
||||||
[System.IO.File]::WriteAllText($path, $content, [System.Text.Encoding]::UTF8); ^
|
|
||||||
exit 0 ^
|
|
||||||
} catch { ^
|
|
||||||
exit 1 ^
|
|
||||||
}"
|
|
||||||
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
set /a converted_files+=1
|
|
||||||
) else (
|
|
||||||
echo [警告] 无法转换 %file%
|
|
||||||
)
|
|
||||||
)
|
|
||||||
goto :eof
|
|
||||||
@@ -9,7 +9,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
from src.core.database import db_manager
|
from src.core.database import db_manager
|
||||||
from src.core.models import User
|
from src.core.models import User
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
# from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
from sqlalchemy import text, inspect
|
from sqlalchemy import text, inspect
|
||||||
|
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
@@ -37,12 +37,12 @@ try:
|
|||||||
print(f" 激活状态: {admin_user.is_active}")
|
print(f" 激活状态: {admin_user.is_active}")
|
||||||
|
|
||||||
# 验证密码
|
# 验证密码
|
||||||
password_ok = check_password_hash(admin_user.password_hash, 'admin123')
|
password_ok = admin_user.check_password('admin123')
|
||||||
print(f" 密码验证: {'正确' if password_ok else '错误'}")
|
print(f" 密码验证: {'正确' if password_ok else '错误'}")
|
||||||
|
|
||||||
if not password_ok:
|
if not password_ok:
|
||||||
print("\n密码不匹配,正在更新密码...")
|
print("\n密码不匹配,正在更新密码...")
|
||||||
admin_user.password_hash = generate_password_hash('admin123')
|
admin_user.set_password('admin123')
|
||||||
admin_user.is_active = True
|
admin_user.is_active = True
|
||||||
if hasattr(admin_user, 'region'):
|
if hasattr(admin_user, 'region'):
|
||||||
admin_user.region = None
|
admin_user.region = None
|
||||||
@@ -56,7 +56,7 @@ try:
|
|||||||
print("用户已激活")
|
print("用户已激活")
|
||||||
|
|
||||||
# 最终验证
|
# 最终验证
|
||||||
test_password = check_password_hash(admin_user.password_hash, 'admin123')
|
test_password = admin_user.check_password('admin123')
|
||||||
if test_password and admin_user.is_active:
|
if test_password and admin_user.is_active:
|
||||||
print("\n管理员用户已就绪!")
|
print("\n管理员用户已就绪!")
|
||||||
print(" 用户名: admin")
|
print(" 用户名: admin")
|
||||||
@@ -69,8 +69,10 @@ try:
|
|||||||
else:
|
else:
|
||||||
print("\n未找到admin用户,正在创建...")
|
print("\n未找到admin用户,正在创建...")
|
||||||
|
|
||||||
# 准备密码哈希
|
# 创建用户对象来生成密码哈希
|
||||||
password_hash = generate_password_hash('admin123')
|
temp_user = User()
|
||||||
|
temp_user.set_password('admin123')
|
||||||
|
password_hash = temp_user.password_hash
|
||||||
|
|
||||||
# 检查表结构,使用SQL直接插入避免字段不匹配
|
# 检查表结构,使用SQL直接插入避免字段不匹配
|
||||||
try:
|
try:
|
||||||
@@ -78,6 +80,7 @@ try:
|
|||||||
new_admin = User(
|
new_admin = User(
|
||||||
username='admin',
|
username='admin',
|
||||||
email='admin@tsp.com',
|
email='admin@tsp.com',
|
||||||
|
name='系统管理员',
|
||||||
password_hash=password_hash,
|
password_hash=password_hash,
|
||||||
role='admin',
|
role='admin',
|
||||||
is_active=True
|
is_active=True
|
||||||
@@ -93,10 +96,11 @@ try:
|
|||||||
session.rollback()
|
session.rollback()
|
||||||
|
|
||||||
# 使用SQL直接插入
|
# 使用SQL直接插入
|
||||||
insert_fields = ['username', 'email', 'password_hash', 'role']
|
insert_fields = ['username', 'email', 'name', 'password_hash', 'role']
|
||||||
insert_values = {
|
insert_values = {
|
||||||
'username': 'admin',
|
'username': 'admin',
|
||||||
'email': 'admin@tsp.com',
|
'email': 'admin@tsp.com',
|
||||||
|
'name': '系统管理员',
|
||||||
'password_hash': password_hash,
|
'password_hash': password_hash,
|
||||||
'role': 'admin'
|
'role': 'admin'
|
||||||
}
|
}
|
||||||
@@ -124,7 +128,7 @@ try:
|
|||||||
# 验证创建结果
|
# 验证创建结果
|
||||||
verify_user = session.query(User).filter(User.username == 'admin').first()
|
verify_user = session.query(User).filter(User.username == 'admin').first()
|
||||||
if verify_user:
|
if verify_user:
|
||||||
test_password = check_password_hash(verify_user.password_hash, 'admin123')
|
test_password = verify_user.check_password('admin123')
|
||||||
print(f"\n验证结果:")
|
print(f"\n验证结果:")
|
||||||
print(f" 用户ID: {verify_user.id}")
|
print(f" 用户ID: {verify_user.id}")
|
||||||
print(f" 密码正确: {test_password}")
|
print(f" 密码正确: {test_password}")
|
||||||
@@ -138,9 +142,9 @@ try:
|
|||||||
print("\n警告: 用户创建成功但状态异常")
|
print("\n警告: 用户创建成功但状态异常")
|
||||||
|
|
||||||
# 创建其他示例用户
|
# 创建其他示例用户
|
||||||
for username, email, password, role, region in [
|
for username, name, email, password, role, region in [
|
||||||
('overseas_ops', 'overseas@tsp.com', 'ops123', 'overseas_ops', 'overseas'),
|
('overseas_ops', '海外运维', 'overseas@tsp.com', 'ops123', 'overseas_ops', 'overseas'),
|
||||||
('domestic_ops', 'domestic@tsp.com', 'ops123', 'domestic_ops', 'domestic')
|
('domestic_ops', '国内运维', 'domestic@tsp.com', 'ops123', 'domestic_ops', 'domestic')
|
||||||
]:
|
]:
|
||||||
ops_user = session.query(User).filter(User.username == username).first()
|
ops_user = session.query(User).filter(User.username == username).first()
|
||||||
if not ops_user:
|
if not ops_user:
|
||||||
@@ -148,11 +152,12 @@ try:
|
|||||||
try:
|
try:
|
||||||
new_user = User(
|
new_user = User(
|
||||||
username=username,
|
username=username,
|
||||||
|
name=name,
|
||||||
email=email,
|
email=email,
|
||||||
password_hash=generate_password_hash(password),
|
|
||||||
role=role,
|
role=role,
|
||||||
is_active=True
|
is_active=True
|
||||||
)
|
)
|
||||||
|
new_user.set_password(password)
|
||||||
if 'region' in existing_columns:
|
if 'region' in existing_columns:
|
||||||
new_user.region = region
|
new_user.region = region
|
||||||
session.add(new_user)
|
session.add(new_user)
|
||||||
|
|||||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"init_time": "2025-10-31T12:46:01.637890",
|
|
||||||
"database_version": "MySQL 8.4.6",
|
|
||||||
"database_url": "mysql+pymysql://tsp_assistant:***@43.134.68.207/tsp_assistant?charset=utf8mb4",
|
|
||||||
"migrations_applied": 0,
|
|
||||||
"tables_created": 16,
|
|
||||||
"initial_data_inserted": true,
|
|
||||||
"verification_passed": true
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
# 数据库迁移说明
|
|
||||||
|
|
||||||
## 工单处理过程记录系统迁移
|
|
||||||
|
|
||||||
### 新增表:`work_order_process_history`
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE IF NOT EXISTS work_order_process_history (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
work_order_id INTEGER NOT NULL,
|
|
||||||
processor_name VARCHAR(100) NOT NULL,
|
|
||||||
processor_role VARCHAR(50),
|
|
||||||
processor_region VARCHAR(50),
|
|
||||||
process_content TEXT NOT NULL,
|
|
||||||
action_type VARCHAR(50) NOT NULL,
|
|
||||||
previous_status VARCHAR(50),
|
|
||||||
new_status VARCHAR(50),
|
|
||||||
assigned_module VARCHAR(50),
|
|
||||||
process_time DATETIME NOT NULL,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_process_history_workorder ON work_order_process_history(work_order_id);
|
|
||||||
CREATE INDEX idx_process_history_time ON work_order_process_history(process_time);
|
|
||||||
```
|
|
||||||
|
|
||||||
### WorkOrder表新增字段
|
|
||||||
|
|
||||||
如果使用SQLite,可以使用以下SQL添加字段:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 注意:SQLite不支持直接ALTER TABLE添加多个列,需要逐个添加
|
|
||||||
|
|
||||||
ALTER TABLE work_orders ADD COLUMN assigned_module VARCHAR(50);
|
|
||||||
ALTER TABLE work_orders ADD COLUMN module_owner VARCHAR(100);
|
|
||||||
ALTER TABLE work_orders ADD COLUMN dispatcher VARCHAR(100);
|
|
||||||
ALTER TABLE work_orders ADD COLUMN dispatch_time DATETIME;
|
|
||||||
ALTER TABLE work_orders ADD COLUMN region VARCHAR(50);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用Python脚本迁移(推荐)
|
|
||||||
|
|
||||||
创建迁移脚本 `migrate_process_history.py`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
数据库迁移脚本:添加工单处理过程记录表和相关字段
|
|
||||||
"""
|
|
||||||
from src.core.database import db_manager
|
|
||||||
from src.core.models import Base, WorkOrderProcessHistory
|
|
||||||
from sqlalchemy import text
|
|
||||||
|
|
||||||
def migrate_database():
|
|
||||||
"""执行数据库迁移"""
|
|
||||||
try:
|
|
||||||
with db_manager.get_session() as session:
|
|
||||||
# 创建新表
|
|
||||||
WorkOrderProcessHistory.__table__.create(db_manager.engine, checkfirst=True)
|
|
||||||
|
|
||||||
# 检查并添加新字段(SQLite需要特殊处理)
|
|
||||||
try:
|
|
||||||
# 尝试添加字段(如果已存在会报错,可以忽略)
|
|
||||||
session.execute(text("ALTER TABLE work_orders ADD COLUMN assigned_module VARCHAR(50)"))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"字段 assigned_module 可能已存在: {e}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
session.execute(text("ALTER TABLE work_orders ADD COLUMN module_owner VARCHAR(100)"))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"字段 module_owner 可能已存在: {e}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
session.execute(text("ALTER TABLE work_orders ADD COLUMN dispatcher VARCHAR(100)"))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"字段 dispatcher 可能已存在: {e}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
session.execute(text("ALTER TABLE work_orders ADD COLUMN dispatch_time DATETIME"))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"字段 dispatch_time 可能已存在: {e}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
session.execute(text("ALTER TABLE work_orders ADD COLUMN region VARCHAR(50)"))
|
|
||||||
except Exception as e:
|
|
||||||
print(f"字段 region 可能已存在: {e}")
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
print("数据库迁移完成!")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"数据库迁移失败: {e}")
|
|
||||||
raise
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
migrate_database()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 执行迁移
|
|
||||||
|
|
||||||
运行迁移脚本:
|
|
||||||
```bash
|
|
||||||
python migrate_process_history.py
|
|
||||||
```
|
|
||||||
|
|
||||||
或者直接在Python交互式环境中执行:
|
|
||||||
```python
|
|
||||||
from migrate_process_history import migrate_database
|
|
||||||
migrate_database()
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **备份数据库**:在执行迁移前,请务必备份现有数据库
|
|
||||||
2. **SQLite限制**:如果使用SQLite,ALTER TABLE添加列的操作在某些情况下可能失败,如果字段已存在会报错
|
|
||||||
3. **数据迁移**:现有工单的处理过程历史记录(存储在`resolution`字段中的)不会自动迁移到新表,需要手动处理
|
|
||||||
4. **索引优化**:新表已包含必要的索引,如果数据量大可以考虑添加更多索引
|
|
||||||
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
修复管理员用户
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
from src.core.database import db_manager
|
|
||||||
from sqlalchemy import text
|
|
||||||
from werkzeug.security import generate_password_hash
|
|
||||||
|
|
||||||
print("Fixing admin user...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
with db_manager.get_session() as session:
|
|
||||||
# Check if admin user exists
|
|
||||||
result = session.execute(text("SELECT id FROM users WHERE username = 'admin'"))
|
|
||||||
admin_row = result.fetchone()
|
|
||||||
|
|
||||||
password_hash = generate_password_hash('admin123')
|
|
||||||
|
|
||||||
if admin_row:
|
|
||||||
print("Admin user exists, updating password...")
|
|
||||||
session.execute(text("""
|
|
||||||
UPDATE users
|
|
||||||
SET password_hash = :password_hash,
|
|
||||||
is_active = 1,
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE username = 'admin'
|
|
||||||
"""), {'password_hash': password_hash})
|
|
||||||
session.commit()
|
|
||||||
print("Admin password updated successfully")
|
|
||||||
else:
|
|
||||||
print("Admin user not found, creating...")
|
|
||||||
session.execute(text("""
|
|
||||||
INSERT INTO users (
|
|
||||||
username, email, password_hash, role, full_name,
|
|
||||||
is_active, region, created_at, updated_at
|
|
||||||
) VALUES (
|
|
||||||
'admin', 'admin@tsp.com', :password_hash, 'admin', 'Administrator',
|
|
||||||
1, NULL, NOW(), NOW()
|
|
||||||
)
|
|
||||||
"""), {'password_hash': password_hash})
|
|
||||||
session.commit()
|
|
||||||
print("Admin user created successfully")
|
|
||||||
|
|
||||||
# Verify
|
|
||||||
result = session.execute(text("""
|
|
||||||
SELECT username, email, role, is_active, full_name
|
|
||||||
FROM users
|
|
||||||
WHERE username = 'admin'
|
|
||||||
"""))
|
|
||||||
admin_data = result.fetchone()
|
|
||||||
|
|
||||||
if admin_data:
|
|
||||||
print("\nVerification:")
|
|
||||||
print(f" Username: {admin_data[0]}")
|
|
||||||
print(f" Email: {admin_data[1]}")
|
|
||||||
print(f" Role: {admin_data[2]}")
|
|
||||||
print(f" Is Active: {admin_data[3]}")
|
|
||||||
print(f" Full Name: {admin_data[4]}")
|
|
||||||
|
|
||||||
# Test password verification
|
|
||||||
result = session.execute(text("SELECT password_hash FROM users WHERE username = 'admin'"))
|
|
||||||
stored_hash = result.fetchone()[0]
|
|
||||||
from werkzeug.security import check_password_hash
|
|
||||||
password_ok = check_password_hash(stored_hash, 'admin123')
|
|
||||||
print(f" Password Check: {'PASS' if password_ok else 'FAIL'}")
|
|
||||||
|
|
||||||
if password_ok and admin_data[3]:
|
|
||||||
print("\n[SUCCESS] Admin user is ready for login!")
|
|
||||||
print(" Username: admin")
|
|
||||||
print(" Password: admin123")
|
|
||||||
else:
|
|
||||||
print("\n[WARNING] User exists but password or status issue")
|
|
||||||
else:
|
|
||||||
print("\n[ERROR] User not found after creation")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
161
fix_git_push.bat
161
fix_git_push.bat
@@ -1,161 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
chcp 65001 >nul 2>&1
|
|
||||||
echo ========================================
|
|
||||||
echo Git推送问题诊断和修复工具
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 1. 检查Git状态
|
|
||||||
echo [1] 检查Git状态...
|
|
||||||
git status >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ? Git未初始化或不可用
|
|
||||||
echo 请确保:
|
|
||||||
echo 1. 已安装Git
|
|
||||||
echo 2. 当前目录是Git仓库
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo ? Git状态正常
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 2. 检查远程仓库配置
|
|
||||||
echo [2] 检查远程仓库配置...
|
|
||||||
git remote -v >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ? 未配置远程仓库
|
|
||||||
echo 请先运行: git remote add origin ^<仓库地址^>
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo ? 远程仓库配置正常
|
|
||||||
git remote -v
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 3. 检查当前分支
|
|
||||||
echo [3] 检查当前分支...
|
|
||||||
for /f "tokens=*" %%b in ('git branch --show-current 2^>nul') do set current_branch=%%b
|
|
||||||
if "!current_branch!"=="" (
|
|
||||||
echo ? 无法获取当前分支信息
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo 当前分支: !current_branch!
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 4. 检查是否有未提交的更改
|
|
||||||
echo [4] 检查未提交的更改...
|
|
||||||
git status --porcelain >nul 2>&1
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
git status --porcelain | findstr /r "." >nul
|
|
||||||
if !errorlevel! equ 0 (
|
|
||||||
echo ?? 有未提交的更改
|
|
||||||
set /p commit="是否先提交更改? (y/n): "
|
|
||||||
if /i "!commit!"=="y" (
|
|
||||||
git add .
|
|
||||||
set /p msg="请输入提交信息: "
|
|
||||||
if "!msg!"=="" set msg=自动提交
|
|
||||||
git commit -m "!msg!"
|
|
||||||
if !errorlevel! neq 0 (
|
|
||||||
echo ? 提交失败
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
echo ? 暂存区状态正常
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 5. 尝试获取远程分支信息
|
|
||||||
echo [5] 获取远程分支信息...
|
|
||||||
git fetch origin >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ? 无法连接到远程仓库
|
|
||||||
echo.
|
|
||||||
echo 可能的原因:
|
|
||||||
echo 1. 网络连接问题
|
|
||||||
echo 2. 远程仓库地址错误
|
|
||||||
echo 3. 需要认证(请检查是否已配置SSH密钥或Token)
|
|
||||||
echo.
|
|
||||||
echo 远程仓库地址:
|
|
||||||
git config --get remote.origin.url
|
|
||||||
echo.
|
|
||||||
echo 解决建议:
|
|
||||||
echo 1. 检查网络连接
|
|
||||||
echo 2. 验证远程仓库地址
|
|
||||||
echo 3. 配置SSH密钥或访问令牌
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo ? 远程仓库连接成功
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 6. 检查分支跟踪关系
|
|
||||||
echo [6] 检查分支跟踪关系...
|
|
||||||
git branch -vv
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 7. 尝试推送到远程
|
|
||||||
echo [7] 尝试推送...
|
|
||||||
echo 当前分支: !current_branch!
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 检查远程是否存在该分支
|
|
||||||
git ls-remote --heads origin !current_branch! >nul 2>&1
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo 远程分支 !current_branch! 已存在
|
|
||||||
echo.
|
|
||||||
echo 尝试使用当前分支名称推送...
|
|
||||||
git push origin !current_branch!
|
|
||||||
if !errorlevel! neq 0 (
|
|
||||||
echo.
|
|
||||||
echo ? 推送失败,尝试拉取最新更改...
|
|
||||||
git pull origin !current_branch! --rebase
|
|
||||||
if !errorlevel! equ 0 (
|
|
||||||
echo ? 重新尝试推送...
|
|
||||||
git push origin !current_branch!
|
|
||||||
) else (
|
|
||||||
echo ? 拉取失败,请检查冲突
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
echo 远程分支 !current_branch! 不存在
|
|
||||||
echo.
|
|
||||||
echo 尝试设置上游并推送...
|
|
||||||
git push -u origin !current_branch!
|
|
||||||
)
|
|
||||||
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo.
|
|
||||||
echo ? 推送成功!
|
|
||||||
) else (
|
|
||||||
echo.
|
|
||||||
echo ? 推送失败
|
|
||||||
echo.
|
|
||||||
echo ? 常见问题和解决方案:
|
|
||||||
echo.
|
|
||||||
echo 1. 如果是认证问题:
|
|
||||||
echo - 检查SSH密钥: ssh -T git@github.com (GitHub) 或 ssh -T git@gitee.com (Gitee)
|
|
||||||
echo - 或使用HTTPS + Token方式
|
|
||||||
echo.
|
|
||||||
echo 2. 如果是分支冲突:
|
|
||||||
echo - 运行: git pull origin !current_branch! --rebase
|
|
||||||
echo - 解决冲突后: git push origin !current_branch!
|
|
||||||
echo.
|
|
||||||
echo 3. 如果远程分支名称不同:
|
|
||||||
echo - 检查远程分支: git branch -r
|
|
||||||
echo - 可能需要推送主分支: git push origin main 或 git push origin master
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo ? 诊断完成!
|
|
||||||
echo ========================================
|
|
||||||
pause
|
|
||||||
211
init.sql
211
init.sql
@@ -1,211 +0,0 @@
|
|||||||
-- TSP智能助手数据库初始化脚本
|
|
||||||
|
|
||||||
-- 创建数据库(如果不存在)
|
|
||||||
CREATE DATABASE IF NOT EXISTS tsp_assistant CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- 使用数据库
|
|
||||||
USE tsp_assistant;
|
|
||||||
|
|
||||||
-- 创建用户表
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
username VARCHAR(50) UNIQUE NOT NULL,
|
|
||||||
email VARCHAR(100) UNIQUE NOT NULL,
|
|
||||||
password_hash VARCHAR(255) NOT NULL,
|
|
||||||
role ENUM('admin', 'user', 'operator') DEFAULT 'user',
|
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建工单表
|
|
||||||
CREATE TABLE IF NOT EXISTS work_orders (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
order_id VARCHAR(50) UNIQUE NOT NULL,
|
|
||||||
title VARCHAR(200) NOT NULL,
|
|
||||||
description TEXT NOT NULL,
|
|
||||||
category VARCHAR(100) NOT NULL,
|
|
||||||
priority VARCHAR(20) NOT NULL DEFAULT 'medium',
|
|
||||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
resolution TEXT,
|
|
||||||
satisfaction_score FLOAT,
|
|
||||||
|
|
||||||
-- 飞书集成字段
|
|
||||||
feishu_record_id VARCHAR(100) UNIQUE,
|
|
||||||
assignee VARCHAR(100),
|
|
||||||
solution TEXT,
|
|
||||||
ai_suggestion TEXT,
|
|
||||||
|
|
||||||
-- 扩展飞书字段
|
|
||||||
source VARCHAR(50),
|
|
||||||
module VARCHAR(100),
|
|
||||||
created_by VARCHAR(100),
|
|
||||||
wilfulness VARCHAR(100),
|
|
||||||
date_of_close TIMESTAMP NULL,
|
|
||||||
vehicle_type VARCHAR(100),
|
|
||||||
vin_sim VARCHAR(50),
|
|
||||||
app_remote_control_version VARCHAR(100),
|
|
||||||
hmi_sw VARCHAR(100),
|
|
||||||
parent_record VARCHAR(100),
|
|
||||||
has_updated_same_day VARCHAR(50),
|
|
||||||
operating_time VARCHAR(100),
|
|
||||||
|
|
||||||
-- 工单分发和权限管理字段
|
|
||||||
assigned_module VARCHAR(50),
|
|
||||||
module_owner VARCHAR(100),
|
|
||||||
dispatcher VARCHAR(100),
|
|
||||||
dispatch_time TIMESTAMP NULL,
|
|
||||||
region VARCHAR(50),
|
|
||||||
|
|
||||||
INDEX idx_order_id (order_id),
|
|
||||||
INDEX idx_status (status),
|
|
||||||
INDEX idx_priority (priority),
|
|
||||||
INDEX idx_created_at (created_at),
|
|
||||||
INDEX idx_assigned_module (assigned_module),
|
|
||||||
INDEX idx_region (region),
|
|
||||||
INDEX idx_feishu_record_id (feishu_record_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建预警表
|
|
||||||
CREATE TABLE IF NOT EXISTS alerts (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
rule_name VARCHAR(100) NOT NULL,
|
|
||||||
alert_type VARCHAR(50) NOT NULL,
|
|
||||||
level VARCHAR(20) NOT NULL DEFAULT 'info',
|
|
||||||
severity VARCHAR(20) NOT NULL DEFAULT 'medium',
|
|
||||||
message TEXT NOT NULL,
|
|
||||||
data TEXT,
|
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
resolved_at TIMESTAMP NULL,
|
|
||||||
INDEX idx_level (level),
|
|
||||||
INDEX idx_alert_type (alert_type),
|
|
||||||
INDEX idx_severity (severity),
|
|
||||||
INDEX idx_is_active (is_active),
|
|
||||||
INDEX idx_created_at (created_at)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建对话表
|
|
||||||
CREATE TABLE IF NOT EXISTS conversations (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
work_order_id INT,
|
|
||||||
user_message TEXT NOT NULL,
|
|
||||||
assistant_response TEXT NOT NULL,
|
|
||||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
confidence_score FLOAT,
|
|
||||||
knowledge_used TEXT,
|
|
||||||
response_time FLOAT,
|
|
||||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id) ON DELETE CASCADE,
|
|
||||||
INDEX idx_work_order_id (work_order_id),
|
|
||||||
INDEX idx_timestamp (timestamp)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建知识库表
|
|
||||||
CREATE TABLE IF NOT EXISTS knowledge_entries (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
question TEXT NOT NULL,
|
|
||||||
answer TEXT NOT NULL,
|
|
||||||
category VARCHAR(100) NOT NULL,
|
|
||||||
confidence_score FLOAT DEFAULT 0.0,
|
|
||||||
usage_count INT DEFAULT 0,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
|
||||||
is_verified BOOLEAN DEFAULT FALSE,
|
|
||||||
verified_by VARCHAR(100),
|
|
||||||
verified_at TIMESTAMP NULL,
|
|
||||||
vector_embedding TEXT,
|
|
||||||
INDEX idx_category (category),
|
|
||||||
INDEX idx_is_active (is_active),
|
|
||||||
INDEX idx_is_verified (is_verified)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建工单建议表
|
|
||||||
CREATE TABLE IF NOT EXISTS work_order_suggestions (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
work_order_id INT NOT NULL,
|
|
||||||
ai_suggestion TEXT,
|
|
||||||
human_resolution TEXT,
|
|
||||||
ai_similarity FLOAT,
|
|
||||||
approved BOOLEAN DEFAULT FALSE,
|
|
||||||
use_human_resolution BOOLEAN DEFAULT FALSE,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id) ON DELETE CASCADE,
|
|
||||||
INDEX idx_work_order_id (work_order_id),
|
|
||||||
INDEX idx_approved (approved)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建工单处理过程记录表
|
|
||||||
CREATE TABLE IF NOT EXISTS work_order_process_history (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
work_order_id INT NOT NULL,
|
|
||||||
processor_name VARCHAR(100) NOT NULL,
|
|
||||||
processor_role VARCHAR(50),
|
|
||||||
processor_region VARCHAR(50),
|
|
||||||
process_content TEXT NOT NULL,
|
|
||||||
action_type VARCHAR(50) NOT NULL,
|
|
||||||
previous_status VARCHAR(50),
|
|
||||||
new_status VARCHAR(50),
|
|
||||||
assigned_module VARCHAR(50),
|
|
||||||
process_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id) ON DELETE CASCADE,
|
|
||||||
INDEX idx_work_order_id (work_order_id),
|
|
||||||
INDEX idx_process_time (process_time),
|
|
||||||
INDEX idx_action_type (action_type),
|
|
||||||
INDEX idx_processor_name (processor_name)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建系统配置表
|
|
||||||
CREATE TABLE IF NOT EXISTS system_settings (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
key_name VARCHAR(100) UNIQUE NOT NULL,
|
|
||||||
value TEXT,
|
|
||||||
description TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 插入默认管理员用户
|
|
||||||
INSERT IGNORE INTO users (username, email, password_hash, role) VALUES
|
|
||||||
('admin', 'admin@tsp.com', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8K8K8K8', 'admin');
|
|
||||||
|
|
||||||
-- 插入默认系统配置
|
|
||||||
INSERT IGNORE INTO system_settings (key_name, value, description) VALUES
|
|
||||||
('system_name', 'TSP智能助手', '系统名称'),
|
|
||||||
('version', '2.0.0', '系统版本'),
|
|
||||||
('maintenance_mode', 'false', '维护模式'),
|
|
||||||
('max_concurrent_users', '100', '最大并发用户数'),
|
|
||||||
('session_timeout', '3600', '会话超时时间(秒)');
|
|
||||||
|
|
||||||
-- 创建分析统计表
|
|
||||||
CREATE TABLE IF NOT EXISTS analytics (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
date TIMESTAMP NOT NULL,
|
|
||||||
total_orders INT DEFAULT 0,
|
|
||||||
resolved_orders INT DEFAULT 0,
|
|
||||||
avg_resolution_time FLOAT DEFAULT 0.0,
|
|
||||||
satisfaction_avg FLOAT DEFAULT 0.0,
|
|
||||||
knowledge_hit_rate FLOAT DEFAULT 0.0,
|
|
||||||
category_distribution TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
INDEX idx_date (date)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 创建车辆实时数据表(如果不存在)
|
|
||||||
CREATE TABLE IF NOT EXISTS vehicle_data (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
vehicle_id VARCHAR(50) NOT NULL,
|
|
||||||
vehicle_vin VARCHAR(17),
|
|
||||||
data_type VARCHAR(50) NOT NULL,
|
|
||||||
data_value TEXT NOT NULL,
|
|
||||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
|
||||||
INDEX idx_vehicle_id (vehicle_id),
|
|
||||||
INDEX idx_vehicle_vin (vehicle_vin),
|
|
||||||
INDEX idx_data_type (data_type),
|
|
||||||
INDEX idx_timestamp (timestamp)
|
|
||||||
);
|
|
||||||
@@ -15,12 +15,12 @@ from pathlib import Path
|
|||||||
# 添加项目根目录到Python路径
|
# 添加项目根目录到Python路径
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
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.utils.helpers import setup_logging
|
||||||
from src.core.database import db_manager
|
from src.core.database import db_manager
|
||||||
from src.core.models import (
|
from src.core.models import (
|
||||||
Base, WorkOrder, KnowledgeEntry, Conversation, Analytics, Alert, VehicleData,
|
Base, WorkOrder, KnowledgeEntry, Conversation, Analytics, Alert, VehicleData,
|
||||||
WorkOrderSuggestion, WorkOrderProcessHistory
|
WorkOrderSuggestion, WorkOrderProcessHistory, User
|
||||||
)
|
)
|
||||||
|
|
||||||
class DatabaseInitializer:
|
class DatabaseInitializer:
|
||||||
@@ -67,7 +67,8 @@ class DatabaseInitializer:
|
|||||||
|
|
||||||
try:
|
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():
|
if not self._test_connection():
|
||||||
@@ -168,6 +169,7 @@ class DatabaseInitializer:
|
|||||||
print("\n执行数据库迁移...")
|
print("\n执行数据库迁移...")
|
||||||
|
|
||||||
migrations = [
|
migrations = [
|
||||||
|
self._migrate_user_table_structure,
|
||||||
self._migrate_knowledge_verification_fields,
|
self._migrate_knowledge_verification_fields,
|
||||||
self._migrate_alert_severity_field,
|
self._migrate_alert_severity_field,
|
||||||
self._migrate_vehicle_data_table,
|
self._migrate_vehicle_data_table,
|
||||||
@@ -192,6 +194,51 @@ class DatabaseInitializer:
|
|||||||
print(f"完成 {success_count}/{len(migrations)} 个迁移")
|
print(f"完成 {success_count}/{len(migrations)} 个迁移")
|
||||||
return success_count > 0
|
return success_count > 0
|
||||||
|
|
||||||
|
def _migrate_user_table_structure(self) -> bool:
|
||||||
|
"""迁移用户表结构"""
|
||||||
|
print(" 检查用户表结构...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with db_manager.get_session() as session:
|
||||||
|
# 检查users表是否存在
|
||||||
|
inspector = inspect(db_manager.engine)
|
||||||
|
if 'users' not in inspector.get_table_names():
|
||||||
|
print(" 创建users表...")
|
||||||
|
# 创建User模型的表
|
||||||
|
User.__table__.create(session.bind, checkfirst=True)
|
||||||
|
print(" users表创建成功")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 检查users表的列
|
||||||
|
existing_columns = [col['name'] for col in inspector.get_columns('users')]
|
||||||
|
print(f" users表现有字段: {existing_columns}")
|
||||||
|
|
||||||
|
# 检查必需的字段
|
||||||
|
required_fields = {
|
||||||
|
'name': 'VARCHAR(100)',
|
||||||
|
'email': 'VARCHAR(120)',
|
||||||
|
'role': 'VARCHAR(20) DEFAULT \'user\'',
|
||||||
|
'is_active': 'BOOLEAN DEFAULT TRUE',
|
||||||
|
'created_at': 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP',
|
||||||
|
'last_login': 'TIMESTAMP NULL'
|
||||||
|
}
|
||||||
|
|
||||||
|
fields_to_add = []
|
||||||
|
for field_name, field_type in required_fields.items():
|
||||||
|
if field_name not in existing_columns:
|
||||||
|
fields_to_add.append((field_name, field_type))
|
||||||
|
|
||||||
|
if fields_to_add:
|
||||||
|
print(f" 需要添加字段: {[f[0] for f in fields_to_add]}")
|
||||||
|
return self._add_table_columns('users', fields_to_add)
|
||||||
|
else:
|
||||||
|
print(" users表结构完整")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" 用户表结构迁移失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def _migrate_knowledge_verification_fields(self) -> bool:
|
def _migrate_knowledge_verification_fields(self) -> bool:
|
||||||
"""迁移知识库验证字段"""
|
"""迁移知识库验证字段"""
|
||||||
print(" 检查知识库验证字段...")
|
print(" 检查知识库验证字段...")
|
||||||
@@ -454,7 +501,18 @@ class DatabaseInitializer:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with db_manager.get_session() as session:
|
with db_manager.get_session() as session:
|
||||||
# 检查是否已有数据
|
# 检查是否已有用户数据
|
||||||
|
existing_users = session.query(User).count()
|
||||||
|
if existing_users == 0:
|
||||||
|
# 创建默认管理员用户
|
||||||
|
from src.core.auth_manager import auth_manager
|
||||||
|
admin_user = auth_manager.create_default_admin()
|
||||||
|
if admin_user:
|
||||||
|
print(" 默认管理员用户已创建: admin/admin123")
|
||||||
|
else:
|
||||||
|
print(" 创建默认管理员用户失败")
|
||||||
|
|
||||||
|
# 检查是否已有知识库数据
|
||||||
existing_count = session.query(KnowledgeEntry).count()
|
existing_count = session.query(KnowledgeEntry).count()
|
||||||
if existing_count > 0:
|
if existing_count > 0:
|
||||||
print(f" 数据库中已有 {existing_count} 条知识库条目,跳过初始数据插入")
|
print(f" 数据库中已有 {existing_count} 条知识库条目,跳过初始数据插入")
|
||||||
@@ -653,6 +711,7 @@ class DatabaseInitializer:
|
|||||||
with db_manager.get_session() as session:
|
with db_manager.get_session() as session:
|
||||||
# 检查各表的记录数
|
# 检查各表的记录数
|
||||||
tables_info = {
|
tables_info = {
|
||||||
|
'users': User,
|
||||||
'work_orders': WorkOrder,
|
'work_orders': WorkOrder,
|
||||||
'conversations': Conversation,
|
'conversations': Conversation,
|
||||||
'knowledge_entries': KnowledgeEntry,
|
'knowledge_entries': KnowledgeEntry,
|
||||||
|
|||||||
380
logs/2026-02-10_23-22-54/dashboard.log
Normal file
380
logs/2026-02-10_23-22-54/dashboard.log
Normal file
@@ -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 - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* 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 - [33mPress CTRL+C to quit[0m
|
||||||
|
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] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,910 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,926 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,928 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,931 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,932 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,937 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,941 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:23:01,945 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:23:01] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,330 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,340 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,341 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,342 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,343 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,345 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,347 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:24:51,351 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:24:51] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[35m[1mPOST /api/feishu-sync/config/import HTTP/1.1[0m" 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] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,001 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,006 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,007 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,008 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,017 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,018 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:27:15,019 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:27:15] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 -
|
||||||
545
logs/2026-02-10_23-48-47/dashboard.log
Normal file
545
logs/2026-02-10_23-48-47/dashboard.log
Normal file
@@ -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 - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* 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 - [33mPress CTRL+C to quit[0m
|
||||||
|
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] "[35m[1mGET /api/workorders HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> returned NULL without setting an exception
|
||||||
|
2026-02-10 23:48:56,433 - src.core.query_optimizer - ERROR - 优化分析查询失败: <sqlite3.Connection object at 0x1065fd840> 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> 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 - 优化分析查询失败: <sqlite3.Connection object at 0x1065fd840> 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] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,440 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,441 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,447 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,449 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,455 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,457 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,460 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:48:58,462 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:48:58] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/workorders HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> returned NULL without setting an exception
|
||||||
|
2026-02-10 23:49:00,701 - src.core.query_optimizer - ERROR - 优化分析查询失败: <sqlite3.Connection object at 0x1065fd840> 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,014 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,019 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,025 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,026 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,034 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,036 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,038 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:49:05,042 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:49:05] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 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] "[35m[1mGET /api/workorders HTTP/1.1[0m" 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> 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: <sqlite3.Connection object at 0x1065fd840> 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> returned NULL without setting an exception
|
||||||
|
2026-02-10 23:49:10,176 - src.web.error_handlers - ERROR - 未处理错误 get_health: <sqlite3.Connection object at 0x1065fd840> 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> returned NULL without setting an exception
|
||||||
|
2026-02-10 23:49:20,654 - src.web.error_handlers - ERROR - 未处理错误 get_health: <sqlite3.Connection object at 0x1065fd840> 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> 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] "[35m[1mGET /api/workorders HTTP/1.1[0m" 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 - 数据库操作失败: <sqlite3.Connection object at 0x1065fd840> returned NULL without setting an exception
|
||||||
|
2026-02-10 23:49:25,839 - src.web.error_handlers - ERROR - 未处理错误 get_health: <sqlite3.Connection object at 0x1065fd840> 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 -
|
||||||
298
logs/2026-02-10_23-51-10/dashboard.log
Normal file
298
logs/2026-02-10_23-51-10/dashboard.log
Normal file
@@ -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 - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* 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 - [33mPress CTRL+C to quit[0m
|
||||||
|
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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,583 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,585 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,586 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,587 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,589 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,591 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,593 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:16,594 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:16] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,281 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,288 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,289 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,291 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,292 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,293 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,294 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:36,297 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:36] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,498 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,503 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,509 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,512 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,515 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,516 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,519 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:40,520 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:40] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,412 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,418 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,422 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,424 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,425 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,426 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,427 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:55,430 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:55] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,159 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,168 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,169 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,170 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,172 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,173 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,174 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,176 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,720 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,723 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,727 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,727 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,728 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,731 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,733 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:51:56,736 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:51:56] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 -
|
||||||
237
logs/2026-02-10_23-55-42/dashboard.log
Normal file
237
logs/2026-02-10_23-55-42/dashboard.log
Normal file
@@ -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 - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* 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 - [33mPress CTRL+C to quit[0m
|
||||||
|
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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,884 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,885 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,893 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,895 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,897 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,897 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:55:49,898 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:55:49] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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] "[36mGET /static/css/design-system.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,643 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/css/style.css?v=1.0.0 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,648 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/core/store.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,649 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/services/api.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,654 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/components/NotificationManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,656 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/components/AlertManager.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,658 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/app-new.js HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,660 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/js/dashboard.js?v=1.0.9 HTTP/1.1[0m" 304 -
|
||||||
|
2026-02-10 23:56:33,661 - werkzeug - INFO - 127.0.0.1 - - [10/Feb/2026 23:56:33] "[36mGET /static/css/design-system.css HTTP/1.1[0m" 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] "[35m[1mGET /api/feishu-sync/status HTTP/1.1[0m" 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 -
|
||||||
15432
logs/dashboard.log
15432
logs/dashboard.log
File diff suppressed because one or more lines are too long
@@ -1,70 +0,0 @@
|
|||||||
2025-09-19 18:26:27,748 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - location
|
|
||||||
2025-09-19 18:26:27,752 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - status
|
|
||||||
2025-09-19 18:26:27,756 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - battery
|
|
||||||
2025-09-19 18:26:27,759 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - engine
|
|
||||||
2025-09-19 18:26:27,764 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - location
|
|
||||||
2025-09-19 18:26:27,768 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - status
|
|
||||||
2025-09-19 18:26:27,772 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - fault
|
|
||||||
2025-09-19 18:26:27,773 - src.vehicle.vehicle_data_manager - INFO - 示例车辆数据添加成功
|
|
||||||
2025-09-19 18:53:30,187 - sqlalchemy.pool.impl.QueuePool - ERROR - Exception during reset or similar
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\pool\base.py", line 985, in _finalize_fairy
|
|
||||||
fairy._reset(
|
|
||||||
~~~~~~~~~~~~^
|
|
||||||
pool,
|
|
||||||
^^^^^
|
|
||||||
...<2 lines>...
|
|
||||||
asyncio_safe=can_manipulate_connection,
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
)
|
|
||||||
^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\pool\base.py", line 1433, in _reset
|
|
||||||
pool._dialect.do_rollback(self)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\engine\default.py", line 711, in do_rollback
|
|
||||||
dbapi_connection.rollback()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 505, in rollback
|
|
||||||
self._read_ok_packet()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 465, in _read_ok_packet
|
|
||||||
pkt = self._read_packet()
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 751, in _read_packet
|
|
||||||
packet_header = self._read_bytes(4)
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 789, in _read_bytes
|
|
||||||
data = self._rfile.read(num_bytes)
|
|
||||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.2032.0_x64__qbz5n2kfra8p0\Lib\socket.py", line 719, in readinto
|
|
||||||
return self._sock.recv_into(b)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~^^^
|
|
||||||
KeyboardInterrupt
|
|
||||||
2025-09-19 18:54:31,332 - sqlalchemy.pool.impl.QueuePool - ERROR - Exception during reset or similar
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\pool\base.py", line 985, in _finalize_fairy
|
|
||||||
fairy._reset(
|
|
||||||
~~~~~~~~~~~~^
|
|
||||||
pool,
|
|
||||||
^^^^^
|
|
||||||
...<2 lines>...
|
|
||||||
asyncio_safe=can_manipulate_connection,
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
)
|
|
||||||
^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\pool\base.py", line 1433, in _reset
|
|
||||||
pool._dialect.do_rollback(self)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\sqlalchemy\engine\default.py", line 711, in do_rollback
|
|
||||||
dbapi_connection.rollback()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 505, in rollback
|
|
||||||
self._read_ok_packet()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~^^
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 465, in _read_ok_packet
|
|
||||||
pkt = self._read_packet()
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 751, in _read_packet
|
|
||||||
packet_header = self._read_bytes(4)
|
|
||||||
File "C:\Users\Administrator.CHERY-NOT-8217.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pymysql\connections.py", line 789, in _read_bytes
|
|
||||||
data = self._rfile.read(num_bytes)
|
|
||||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.2032.0_x64__qbz5n2kfra8p0\Lib\socket.py", line 719, in readinto
|
|
||||||
return self._sock.recv_into(b)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~^^^
|
|
||||||
KeyboardInterrupt
|
|
||||||
|
|||||||
175
quick_push.bat
175
quick_push.bat
@@ -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
|
|
||||||
Binary file not shown.
@@ -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 <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=TSP智能助手服务
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=www-data
|
|
||||||
Group=www-data
|
|
||||||
WorkingDirectory=$app_path
|
|
||||||
Environment=PATH=$app_path/venv/bin
|
|
||||||
ExecStart=$app_path/venv/bin/python start_dashboard.py
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable "$service_name"
|
|
||||||
log_info "systemd服务创建完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 创建nginx配置
|
|
||||||
create_nginx_config() {
|
|
||||||
local domain=$1
|
|
||||||
local app_port=$2
|
|
||||||
local config_file="/etc/nginx/sites-available/tsp_assistant"
|
|
||||||
|
|
||||||
log_info "创建nginx配置: $config_file"
|
|
||||||
|
|
||||||
sudo tee "$config_file" > /dev/null <<EOF
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name $domain;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://127.0.0.1:$app_port;
|
|
||||||
proxy_set_header Host \$host;
|
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /static {
|
|
||||||
alias $app_path/src/web/static;
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 启用站点
|
|
||||||
sudo ln -sf "$config_file" /etc/nginx/sites-enabled/
|
|
||||||
sudo nginx -t
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
log_info "nginx配置完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主部署函数
|
|
||||||
deploy() {
|
|
||||||
local environment=${1:-production}
|
|
||||||
local domain=${2:-localhost}
|
|
||||||
local app_port=${3:-5000}
|
|
||||||
|
|
||||||
log_info "开始部署TSP智能助手到 $environment 环境"
|
|
||||||
|
|
||||||
# 设置部署路径
|
|
||||||
case $environment in
|
|
||||||
development)
|
|
||||||
DEPLOY_PATH="./dev_deploy"
|
|
||||||
SERVICE_NAME=""
|
|
||||||
;;
|
|
||||||
staging)
|
|
||||||
DEPLOY_PATH="/opt/tsp_assistant_staging"
|
|
||||||
SERVICE_NAME="tsp_assistant_staging"
|
|
||||||
;;
|
|
||||||
production)
|
|
||||||
DEPLOY_PATH="/opt/tsp_assistant"
|
|
||||||
SERVICE_NAME="tsp_assistant"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_error "未知环境: $environment"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# 检查依赖
|
|
||||||
check_dependencies
|
|
||||||
|
|
||||||
# 创建部署目录
|
|
||||||
log_info "创建部署目录: $DEPLOY_PATH"
|
|
||||||
sudo mkdir -p "$DEPLOY_PATH"
|
|
||||||
sudo chown $USER:$USER "$DEPLOY_PATH"
|
|
||||||
|
|
||||||
# 复制文件
|
|
||||||
log_info "复制应用文件..."
|
|
||||||
cp -r . "$DEPLOY_PATH/"
|
|
||||||
cd "$DEPLOY_PATH"
|
|
||||||
|
|
||||||
# 设置虚拟环境
|
|
||||||
setup_venv "venv"
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
install_dependencies
|
|
||||||
|
|
||||||
# 运行迁移
|
|
||||||
run_migrations
|
|
||||||
|
|
||||||
# 创建服务文件(非开发环境)
|
|
||||||
if [ "$environment" != "development" ] && [ -n "$SERVICE_NAME" ]; then
|
|
||||||
create_systemd_service "$SERVICE_NAME" "$DEPLOY_PATH"
|
|
||||||
create_nginx_config "$domain" "$app_port"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "部署完成!"
|
|
||||||
|
|
||||||
if [ "$environment" != "development" ]; then
|
|
||||||
log_info "启动服务..."
|
|
||||||
sudo systemctl start "$SERVICE_NAME"
|
|
||||||
sudo systemctl status "$SERVICE_NAME"
|
|
||||||
else
|
|
||||||
log_info "开发环境部署完成,使用以下命令启动:"
|
|
||||||
log_info "cd $DEPLOY_PATH && source venv/bin/activate && python start_dashboard.py"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 回滚函数
|
|
||||||
rollback() {
|
|
||||||
local backup_name=$1
|
|
||||||
|
|
||||||
if [ -z "$backup_name" ]; then
|
|
||||||
log_error "请指定备份名称"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "回滚到备份: $backup_name"
|
|
||||||
|
|
||||||
# 停止服务
|
|
||||||
sudo systemctl stop tsp_assistant
|
|
||||||
|
|
||||||
# 恢复备份
|
|
||||||
if [ -d "backups/$backup_name" ]; then
|
|
||||||
sudo rm -rf /opt/tsp_assistant
|
|
||||||
sudo cp -r "backups/$backup_name" /opt/tsp_assistant
|
|
||||||
sudo chown -R www-data:www-data /opt/tsp_assistant
|
|
||||||
|
|
||||||
# 重启服务
|
|
||||||
sudo systemctl start tsp_assistant
|
|
||||||
log_info "回滚完成"
|
|
||||||
else
|
|
||||||
log_error "备份不存在: $backup_name"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 版本检查
|
|
||||||
check_version() {
|
|
||||||
log_info "检查版本信息..."
|
|
||||||
if [ -f "version.json" ]; then
|
|
||||||
local version=$(python3 -c "import json; print(json.load(open('version.json'))['version'])" 2>/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 "$@"
|
|
||||||
@@ -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 "$@"
|
|
||||||
@@ -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 "$@"
|
|
||||||
@@ -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
|
|
||||||
@@ -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()
|
|
||||||
@@ -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
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
@echo off
|
|
||||||
chcp 65001 >nul
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
|
|
||||||
echo ========================================
|
|
||||||
echo 简单Git推送工具
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 1. 显示Git状态
|
|
||||||
echo [1] Git状态:
|
|
||||||
git status --short
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 2. 显示远程仓库
|
|
||||||
echo [2] 远程仓库:
|
|
||||||
git remote -v
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo 错误: 未配置远程仓库
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 3. 显示当前分支
|
|
||||||
echo [3] 当前分支:
|
|
||||||
for /f "tokens=*" %%b in ('git branch --show-current 2^>nul') do set branch=%%b
|
|
||||||
if "!branch!"=="" (
|
|
||||||
echo 警告: 无法获取分支名称,尝试使用main
|
|
||||||
set branch=main
|
|
||||||
)
|
|
||||||
echo 分支: !branch!
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 4. 检查是否有未提交的更改
|
|
||||||
echo [4] 检查未提交的更改...
|
|
||||||
git diff --quiet
|
|
||||||
set has_uncommitted=%errorlevel%
|
|
||||||
git diff --cached --quiet
|
|
||||||
set has_staged=%errorlevel%
|
|
||||||
|
|
||||||
if %has_uncommitted% neq 0 (
|
|
||||||
echo 有未暂存的更改
|
|
||||||
)
|
|
||||||
if %has_staged% neq 0 (
|
|
||||||
echo 有已暂存的更改
|
|
||||||
)
|
|
||||||
if %has_uncommitted% equ 0 if %has_staged% equ 0 (
|
|
||||||
echo 所有更改已提交
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: 5. 尝试推送
|
|
||||||
echo [5] 开始推送...
|
|
||||||
echo 命令: git push origin !branch!
|
|
||||||
echo.
|
|
||||||
|
|
||||||
git push origin !branch! 2>&1 | findstr /v "^$"
|
|
||||||
set push_error=!errorlevel!
|
|
||||||
|
|
||||||
if !push_error! equ 0 (
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 推送成功!
|
|
||||||
echo ========================================
|
|
||||||
) else (
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 推送失败!错误码: !push_error!
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
echo 尝试设置上游并推送...
|
|
||||||
git push -u origin !branch! 2>&1 | findstr /v "^$"
|
|
||||||
set push_u_error=!errorlevel!
|
|
||||||
|
|
||||||
if !push_u_error! equ 0 (
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 推送成功(已设置上游)!
|
|
||||||
echo ========================================
|
|
||||||
) else (
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 推送仍然失败
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
echo 常见问题和解决方案:
|
|
||||||
echo.
|
|
||||||
echo 1. 认证问题:
|
|
||||||
echo - 检查SSH密钥: ssh -T git@github.com (GitHub)
|
|
||||||
echo - 检查SSH密钥: ssh -T git@gitee.com (Gitee)
|
|
||||||
echo - 或使用HTTPS + Personal Access Token
|
|
||||||
echo.
|
|
||||||
echo 2. 远程仓库地址:
|
|
||||||
git config --get remote.origin.url
|
|
||||||
echo.
|
|
||||||
echo 3. 分支冲突:
|
|
||||||
echo - 先拉取: git pull origin !branch! --rebase
|
|
||||||
echo - 解决冲突后推送: git push origin !branch!
|
|
||||||
echo.
|
|
||||||
echo 4. 检查网络连接和远程仓库权限
|
|
||||||
echo.
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# TSP助手 - 基于大模型的AI客服机器人
|
|
||||||
__version__ = "1.0.0"
|
|
||||||
__author__ = "TSP Assistant Team"
|
|
||||||
BIN
src/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/__pycache__/agent_assistant.cpython-310.pyc
Normal file
BIN
src/__pycache__/agent_assistant.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/__pycache__/main.cpython-310.pyc
Normal file
BIN
src/__pycache__/main.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/agent_core.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/agent_core.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/executor.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/executor.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/goal_manager.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/goal_manager.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/llm_client.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/llm_client.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/planner.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/planner.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/reasoning_engine.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/reasoning_engine.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/agent/__pycache__/tool_manager.cpython-310.pyc
Normal file
BIN
src/agent/__pycache__/tool_manager.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
实现Agent的主动调用功能
|
实现Agent的主动调用功能
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio跳过系统检查,直接启动服务...
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ from typing import Dict, Any, Optional, List
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from src.config.unified_config import get_config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LLMConfig:
|
class LLMConfig:
|
||||||
"""LLM配置"""
|
"""LLM配置"""
|
||||||
provider: str # openai, anthropic, local, etc.
|
provider: str
|
||||||
api_key: str
|
api_key: str
|
||||||
base_url: Optional[str] = None
|
base_url: Optional[str] = None
|
||||||
model: str = "gpt-3.5-turbo"
|
model: str = "gpt-3.5-turbo"
|
||||||
@@ -60,7 +62,7 @@ class OpenAIClient(BaseLLMClient):
|
|||||||
async def generate(self, prompt: str, **kwargs) -> str:
|
async def generate(self, prompt: str, **kwargs) -> str:
|
||||||
"""生成文本"""
|
"""生成文本"""
|
||||||
if not self.client:
|
if not self.client:
|
||||||
return self._simulate_response(prompt)
|
raise ImportError("OpenAI client not initialized. Please install the 'openai' package.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await self.client.chat.completions.create(
|
response = await self.client.chat.completions.create(
|
||||||
@@ -72,12 +74,12 @@ class OpenAIClient(BaseLLMClient):
|
|||||||
return response.choices[0].message.content
|
return response.choices[0].message.content
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"OpenAI API调用失败: {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:
|
async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str:
|
||||||
"""对话生成"""
|
"""对话生成"""
|
||||||
if not self.client:
|
if not self.client:
|
||||||
return self._simulate_chat(messages)
|
raise ImportError("OpenAI client not initialized. Please install the 'openai' package.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await self.client.chat.completions.create(
|
response = await self.client.chat.completions.create(
|
||||||
@@ -89,7 +91,7 @@ class OpenAIClient(BaseLLMClient):
|
|||||||
return response.choices[0].message.content
|
return response.choices[0].message.content
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"OpenAI Chat API调用失败: {e}")
|
logger.error(f"OpenAI Chat API调用失败: {e}")
|
||||||
return self._simulate_chat(messages)
|
raise e
|
||||||
|
|
||||||
def _simulate_response(self, prompt: str) -> str:
|
def _simulate_response(self, prompt: str) -> str:
|
||||||
"""模拟响应"""
|
"""模拟响应"""
|
||||||
@@ -198,11 +200,14 @@ class LLMClientFactory:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create_client(config: LLMConfig) -> BaseLLMClient:
|
def create_client(config: LLMConfig) -> BaseLLMClient:
|
||||||
"""创建LLM客户端"""
|
"""创建LLM客户端"""
|
||||||
if config.provider.lower() == "openai":
|
provider = config.provider.lower()
|
||||||
|
|
||||||
|
# qwen 使用 OpenAI 兼容的 API
|
||||||
|
if provider in ["openai", "qwen"]:
|
||||||
return OpenAIClient(config)
|
return OpenAIClient(config)
|
||||||
elif config.provider.lower() == "anthropic":
|
elif provider == "anthropic":
|
||||||
return AnthropicClient(config)
|
return AnthropicClient(config)
|
||||||
elif config.provider.lower() == "local":
|
elif provider == "local":
|
||||||
return LocalLLMClient(config)
|
return LocalLLMClient(config)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"不支持的LLM提供商: {config.provider}")
|
raise ValueError(f"不支持的LLM提供商: {config.provider}")
|
||||||
@@ -210,15 +215,21 @@ class LLMClientFactory:
|
|||||||
class LLMManager:
|
class LLMManager:
|
||||||
"""LLM管理器"""
|
"""LLM管理器"""
|
||||||
|
|
||||||
def __init__(self, config: LLMConfig):
|
def __init__(self, config=None):
|
||||||
|
if config:
|
||||||
self.config = config
|
self.config = config
|
||||||
self.client = LLMClientFactory.create_client(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 = {
|
self.usage_stats = {
|
||||||
"total_requests": 0,
|
"total_requests": 0,
|
||||||
"total_tokens": 0,
|
"total_tokens": 0,
|
||||||
"error_count": 0
|
"error_count": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def generate(self, prompt: str, **kwargs) -> str:
|
async def generate(self, prompt: str, **kwargs) -> str:
|
||||||
"""生成文本"""
|
"""生成文本"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ import logging
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from src.config.unified_config import get_config
|
||||||
|
from src.agent.llm_client import LLMManager
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class TSPAgentAssistant:
|
class TSPAgentAssistant:
|
||||||
"""TSP Agent助手 - 简化版本"""
|
"""TSP Agent助手"""
|
||||||
|
|
||||||
def __init__(self, llm_config=None):
|
def __init__(self):
|
||||||
# 初始化基础功能
|
# 初始化基础功能
|
||||||
self.llm_config = llm_config
|
config = get_config()
|
||||||
|
self.llm_manager = LLMManager(config.llm)
|
||||||
self.is_agent_mode = True
|
self.is_agent_mode = True
|
||||||
self.execution_history = []
|
self.execution_history = []
|
||||||
|
|
||||||
@@ -339,6 +342,8 @@ class TSPAgentAssistant:
|
|||||||
import os
|
import os
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
|
||||||
|
logger.info(f"开始处理知识库上传文件: {filename}")
|
||||||
|
|
||||||
# 检查文件类型
|
# 检查文件类型
|
||||||
mime_type, _ = mimetypes.guess_type(file_path)
|
mime_type, _ = mimetypes.guess_type(file_path)
|
||||||
file_ext = os.path.splitext(filename)[1].lower()
|
file_ext = os.path.splitext(filename)[1].lower()
|
||||||
@@ -346,22 +351,30 @@ class TSPAgentAssistant:
|
|||||||
# 读取文件内容
|
# 读取文件内容
|
||||||
content = self._read_file_content(file_path, file_ext)
|
content = self._read_file_content(file_path, file_ext)
|
||||||
if not content:
|
if not content:
|
||||||
|
logger.error(f"文件读取失败或内容为空: {filename}")
|
||||||
return {"success": False, "error": "无法读取文件内容"}
|
return {"success": False, "error": "无法读取文件内容"}
|
||||||
|
|
||||||
|
logger.info(f"文件读取成功: {filename}, 字符数={len(content)}")
|
||||||
|
|
||||||
# 使用简化的知识提取
|
# 使用简化的知识提取
|
||||||
|
logger.info(f"正在对文件内容进行 AI 知识提取...")
|
||||||
knowledge_entries = self._extract_knowledge_from_content(content, filename)
|
knowledge_entries = self._extract_knowledge_from_content(content, filename)
|
||||||
|
|
||||||
|
logger.info(f"知识提取完成: 共提取出 {len(knowledge_entries)} 个潜在条目")
|
||||||
|
|
||||||
# 保存到知识库
|
# 保存到知识库
|
||||||
saved_count = 0
|
saved_count = 0
|
||||||
for i, entry in enumerate(knowledge_entries):
|
for i, entry in enumerate(knowledge_entries):
|
||||||
try:
|
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
|
saved_count += 1
|
||||||
logger.info(f"知识条目 {i+1} 保存成功")
|
|
||||||
except Exception as save_error:
|
except Exception as save_error:
|
||||||
logger.error(f"保存知识条目 {i+1} 时出错: {save_error}")
|
logger.error(f"保存知识条目 {i+1} 时出错: {save_error}")
|
||||||
|
|
||||||
|
logger.info(f"文件处理任务结束: {filename}, 成功入库 {saved_count} 条")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"success": True,
|
"success": True,
|
||||||
"knowledge_count": saved_count,
|
"knowledge_count": saved_count,
|
||||||
|
|||||||
BIN
src/analytics/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/analytics/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user