Skip to content

Latest commit

 

History

History
420 lines (322 loc) · 11 KB

File metadata and controls

420 lines (322 loc) · 11 KB

错误处理改进文档

📋 概述

本次改进旨在将技术性错误信息转换为用户友好的提示,明确指出问题所在(数据源、大模型、配置等),并提供可操作的解决建议。

🎯 改进目标

改进前的问题

用户看到的错误信息类似:

分析失败:Error code: 401 - {'error': {'message': 'Incorrect API key provided.', 'type': 'invalid_request_error'}}

这种错误信息存在以下问题:

  1. 技术性太强:普通用户看不懂 "Error code: 401" 是什么意思
  2. 缺乏上下文:不知道是哪个组件出错(数据源?大模型?)
  3. 没有指导:不知道如何解决问题

改进后的效果

用户现在看到的错误信息:

❌ Google Gemini API Key 无效

Google Gemini 的 API Key 无效或未配置。

💡 请检查以下几点:
1. 在「系统设置 → 大模型配置」中检查 Google Gemini 的 API Key 是否正确
2. 确认 API Key 是否已激活且有效
3. 尝试重新生成 API Key 并更新配置
4. 或者切换到其他可用的大模型

改进后的优势:

  1. 清晰的标题:一眼看出是哪个组件的什么问题
  2. 简洁的描述:用通俗语言解释问题
  3. 可操作的建议:提供具体的解决步骤

🛠️ 技术实现

1. 错误分类器 (app/utils/error_formatter.py)

错误类别

class ErrorCategory(str, Enum):
    # 大模型相关
    LLM_API_KEY = "llm_api_key"          # API Key 错误
    LLM_NETWORK = "llm_network"          # 网络错误
    LLM_QUOTA = "llm_quota"              # 配额/限流错误
    LLM_OTHER = "llm_other"              # 其他错误
    
    # 数据源相关
    DATA_SOURCE_API_KEY = "data_source_api_key"      # API Key 错误
    DATA_SOURCE_NETWORK = "data_source_network"      # 网络错误
    DATA_SOURCE_NOT_FOUND = "data_source_not_found"  # 数据未找到
    DATA_SOURCE_OTHER = "data_source_other"          # 其他错误
    
    # 其他
    STOCK_CODE_INVALID = "stock_code_invalid"  # 股票代码无效
    NETWORK = "network"                        # 网络连接错误
    SYSTEM = "system"                          # 系统错误
    UNKNOWN = "unknown"                        # 未知错误

支持的厂商/数据源

大模型厂商

  • Google Gemini
  • 阿里百炼(通义千问)
  • 百度千帆
  • DeepSeek
  • OpenAI
  • OpenRouter
  • Anthropic Claude
  • 智谱AI
  • 月之暗面(Kimi)

数据源

  • Tushare
  • AKShare
  • BaoStock
  • Finnhub
  • MongoDB缓存

使用方法

from app.utils.error_formatter import ErrorFormatter

# 基本使用
formatted_error = ErrorFormatter.format_error(
    error_message="Error code: 401 - Invalid API key",
    context={"llm_provider": "google"}
)

# 返回结果
{
    "category": "大模型配置错误",
    "title": "❌ Google Gemini API Key 无效",
    "message": "Google Gemini 的 API Key 无效或未配置。",
    "suggestion": "请检查以下几点:\n1. ...\n2. ...",
    "technical_detail": "Error code: 401 - Invalid API key"
}

2. 后端集成

分析服务 (app/services/simple_analysis_service.py)

在异常处理中使用错误格式化器:

except Exception as e:
    logger.error(f"❌ 后台分析任务失败: {task_id} - {e}")

    # 格式化错误信息为用户友好的提示
    from ..utils.error_formatter import ErrorFormatter
    
    # 收集上下文信息
    error_context = {}
    if hasattr(request, 'parameters') and request.parameters:
        if hasattr(request.parameters, 'quick_model'):
            error_context['model'] = request.parameters.quick_model
    
    # 格式化错误
    formatted_error = ErrorFormatter.format_error(str(e), error_context)
    
    # 构建用户友好的错误消息
    user_friendly_error = (
        f"{formatted_error['title']}\n\n"
        f"{formatted_error['message']}\n\n"
        f"💡 {formatted_error['suggestion']}"
    )

    # 更新任务状态
    await self.memory_manager.update_task_status(
        task_id=task_id,
        status=TaskStatus.FAILED,
        error_message=user_friendly_error
    )

修改的文件:

  • app/services/simple_analysis_service.py (第 880-919 行, 737-765 行, 1614-1639 行)

3. 前端集成

单次分析页面 (frontend/src/views/Analysis/SingleAnalysis.vue)

错误消息显示

// 显示友好的错误提示(使用 dangerouslyUseHTMLString 支持换行)
ElMessage({
  type: 'error',
  message: errorMessage.replace(/\n/g, '<br>'),
  dangerouslyUseHTMLString: true,
  duration: 10000, // 显示10秒,让用户有时间阅读
  showClose: true
})

进度区域显示

<div 
  class="task-description" 
  style="white-space: pre-wrap; line-height: 1.6;"
>
  {{ progressInfo.message }}
</div>

修改的文件:

  • frontend/src/views/Analysis/SingleAnalysis.vue (第 1117-1141 行, 291-305 行)

任务中心页面 (frontend/src/views/Tasks/TaskCenter.vue)

添加"查看错误"按钮

<el-button 
  v-if="row.status==='failed'" 
  type="text" 
  size="small" 
  @click="showErrorDetail(row)"
>
  查看错误
</el-button>

错误详情弹窗

const showErrorDetail = async (row: any) => {
  const taskId = row.task_id || row.analysis_id || row.id
  const res = await analysisApi.getTaskStatus(taskId)
  const task = (res as any)?.data?.data || row
  const errorMessage = task.error_message || task.message || '未知错误'
  
  await ElMessageBox.alert(
    errorMessage,
    '错误详情',
    {
      confirmButtonText: '确定',
      type: 'error',
      dangerouslyUseHTMLString: true,
      message: errorMessage.replace(/\n/g, '<br>')
    }
  )
}

修改的文件:

  • frontend/src/views/Tasks/TaskCenter.vue (第 106-115 行, 372-411 行)

📊 错误类型示例

1. 大模型 API Key 错误

原始错误

Error code: 401 - {'error': {'message': 'Incorrect API key provided.'}}

格式化后

❌ Google Gemini API Key 无效

Google Gemini 的 API Key 无效或未配置。

💡 请检查以下几点:
1. 在「系统设置 → 大模型配置」中检查 Google Gemini 的 API Key 是否正确
2. 确认 API Key 是否已激活且有效
3. 尝试重新生成 API Key 并更新配置
4. 或者切换到其他可用的大模型

2. 大模型配额不足

原始错误

Error: Resource exhausted. Quota exceeded for model qwen-plus.

格式化后

⚠️ 阿里百炼(通义千问) 配额不足或限流

阿里百炼(通义千问) 的调用配额已用完或触发了限流。

💡 请尝试以下解决方案:
1. 检查 阿里百炼(通义千问) 账户余额和配额
2. 等待一段时间后重试(可能是限流)
3. 升级账户套餐以获取更多配额
4. 切换到其他可用的大模型

3. 数据源 Token 错误

原始错误

❌ [数据来源: Tushare失败] Token无效或未配置

格式化后

❌ Tushare Token/API Key 无效

Tushare 的 Token 或 API Key 无效或未配置。

💡 请检查以下几点:
1. 在「系统设置 → 数据源配置」中检查 Tushare 的配置
2. 确认 Token/API Key 是否正确且有效
3. 检查账户是否已激活
4. 系统会自动尝试使用备用数据源

4. 数据源未找到数据

原始错误

❌ [数据来源: AKShare失败] 未找到股票代码 999999 的数据

格式化后

📊 AKShare 未找到数据

从 AKShare 获取股票数据失败,可能是股票代码不存在或数据暂未更新。

💡 建议:
1. 检查股票代码是否正确
2. 确认该股票是否已上市
3. 系统会自动尝试使用其他数据源
4. 如果是新股,可能需要等待数据更新

5. 股票代码无效

原始错误

股票代码格式不正确: ABC123。A股代码应为6位数字。

格式化后

❌ 股票代码无效

输入的股票代码格式不正确或不存在。

💡 请检查:
1. A股代码格式:6位数字(如 000001、600000)
2. 港股代码格式:5位数字(如 00700)
3. 美股代码格式:股票代码(如 AAPL、TSLA)
4. 确认股票是否已上市

🧪 测试

运行测试脚本验证错误格式化功能:

.\.venv\Scripts\python scripts/test_error_formatter.py

测试覆盖:

  • ✅ Google Gemini API Key 错误
  • ✅ 阿里百炼配额不足
  • ✅ DeepSeek 网络错误
  • ✅ Tushare Token 错误
  • ✅ AKShare 数据未找到
  • ✅ 股票代码无效
  • ✅ 网络连接错误
  • ✅ 系统内部错误
  • ✅ 未知错误
  • ✅ 自动识别厂商(从错误信息中提取)

📝 使用指南

用户视角

  1. 分析失败时

    • 在单次分析页面,错误信息会自动显示在进度区域和弹窗中
    • 错误信息包含清晰的标题、描述和解决建议
    • 可以根据建议检查配置或切换服务
  2. 查看历史失败任务

    • 在任务中心页面,点击失败任务的"查看错误"按钮
    • 弹窗显示详细的错误信息和解决建议
    • 可以根据建议修复问题后重试

开发者视角

  1. 添加新的错误类型

    • ErrorCategory 枚举中添加新类别
    • _categorize_error 方法中添加识别逻辑
    • _generate_friendly_message 方法中添加友好提示
  2. 添加新的厂商/数据源

    • LLM_PROVIDERSDATA_SOURCES 字典中添加映射
    • 错误分类器会自动识别
  3. 在新的服务中使用

    from app.utils.error_formatter import ErrorFormatter
    
    try:
        # 业务逻辑
        pass
    except Exception as e:
        formatted = ErrorFormatter.format_error(str(e), context)
        user_message = f"{formatted['title']}\n\n{formatted['message']}\n\n💡 {formatted['suggestion']}"
        # 返回给用户

🔄 后续改进

  1. 国际化支持

    • 支持多语言错误提示
    • 根据用户语言设置显示对应语言
  2. 错误统计

    • 统计各类错误的发生频率
    • 帮助识别系统瓶颈
  3. 智能建议

    • 根据用户历史错误提供更精准的建议
    • 自动检测配置问题并提示修复
  4. 错误恢复

    • 某些错误可以自动恢复(如自动切换数据源)
    • 提供一键修复功能

📚 相关文件

新增文件

  • app/utils/error_formatter.py - 错误格式化器
  • scripts/test_error_formatter.py - 测试脚本
  • docs/error-handling-improvement.md - 本文档

修改文件

  • app/services/simple_analysis_service.py - 集成错误格式化
  • frontend/src/views/Analysis/SingleAnalysis.vue - 改进错误显示
  • frontend/src/views/Tasks/TaskCenter.vue - 添加错误详情查看

✅ 验收标准

  • 错误信息包含清晰的标题(指明组件和问题类型)
  • 错误信息包含简洁的描述(用通俗语言)
  • 错误信息包含可操作的建议(具体步骤)
  • 支持主流大模型厂商识别
  • 支持主流数据源识别
  • 前端正确显示多行错误信息
  • 任务中心可查看失败任务的错误详情
  • 测试脚本验证通过