#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ AI分析API端点 """ from fastapi import APIRouter, HTTPException, Depends from fastapi.responses import JSONResponse from typing import Dict, Any import asyncio from datetime import datetime import logging from ai_service import AIService, get_ai_config from api import get_db_connection # 创建路由 router = APIRouter(prefix="/api/ai", tags=["AI分析"]) # 配置日志 logger = logging.getLogger(__name__) @router.post("/analyze") async def analyze_production(): """ 分析生产数据 返回AI生成的生产报表 """ try: # 获取数据库连接 conn = await get_db_connection() # 获取最近30天的数据 query = """ SELECT platform, ts_cn, batch, mac, note FROM audit_records WHERE ts_cn >= datetime('now', '-30 days') ORDER BY ts_cn DESC """ cursor = await conn.execute(query) rows = await cursor.fetchall() await conn.close() # 整理数据 pdd_data = [] yt_data = [] for row in rows: record = { "ts_cn": row[1], "batch": row[2], "mac": row[3], "note": row[4] } if row[0] == "pdd": pdd_data.append(record) elif row[0] == "yt": yt_data.append(record) # 获取实时生产数据(从Redis,类似dashboard的逻辑) from datetime import timezone, timedelta beijing_tz = timezone(timedelta(hours=8)) now_bj = datetime.now(beijing_tz) today_bj = now_bj.strftime('%Y-%m-%d') # 尝试从Redis获取实时数据 real_pdd_count = 0 real_yt_count = 0 week_pdd_count = 0 week_yt_count = 0 try: import sys sys.path.append('/home/hyx/work/生产管理系统') from server import parse_audit_line, get_redis r = get_redis() # 获取拼多多审计数据 pdd_items = [] for key in ['mac_batch_audit_pdd', 'audit:pdd', 'pdd:audit']: if r.exists(key) and r.type(key) == 'list': pdd_items = r.lrange(key, 0, -1) break # 获取圆通审计数据 yt_items = [] for key in ['mac_batch_audit_yt', 'audit:yt', 'yt:audit']: if r.exists(key) and r.type(key) == 'list': yt_items = r.lrange(key, 0, -1) break # 解析拼多多数据 today_pdd_macs = set() week_pdd_macs = set() for item in pdd_items: try: parsed = parse_audit_line(item) ts_str = parsed.get('ts_cn') or '' mac = parsed.get('mac') or '' if ts_str and mac: # 今日产量 if ts_str.startswith(today_bj): today_pdd_macs.add(mac) # 本周产量(最近7天) item_date = datetime.strptime(ts_str.split(' ')[0], '%Y-%m-%d') if (now_bj - item_date).days <= 7: week_pdd_macs.add(mac) except: pass # 解析圆通数据 today_yt_macs = set() week_yt_macs = set() for item in yt_items: try: parsed = parse_audit_line(item) ts_str = parsed.get('ts_cn') or '' mac = parsed.get('mac') or '' if ts_str and mac: # 今日产量 if ts_str.startswith(today_bj): today_yt_macs.add(mac) # 本周产量(最近7天) item_date = datetime.strptime(ts_str.split(' ')[0], '%Y-%m-%d') if (now_bj - item_date).days <= 7: week_yt_macs.add(mac) except: pass real_pdd_count = len(today_pdd_macs) real_yt_count = len(today_yt_macs) week_pdd_count = len(week_pdd_macs) week_yt_count = len(week_yt_macs) # 添加调试日志 print(f"AI分析获取的实时数据: 今日PDD={real_pdd_count}, 今日YT={real_yt_count}, 本周PDD={week_pdd_count}, 本周YT={week_yt_count}") except Exception as e: print(f"Redis error in AI: {e}") import traceback traceback.print_exc() # 获取发货数据统计 shipments_stats = {'total': 0, 'by_platform': {}} try: # 使用同一个redis连接 shipments_count = r.hlen('shipment_sn_mapping') shipments_stats['total'] = shipments_count # 获取各平台发货数量(简化处理,假设主要来自拼多多) shipments_stats['by_platform'] = {'pdd': shipments_count * 0.919, 'yt': shipments_count * 0.054, 'other': shipments_count * 0.027} except Exception as e: print(f"Redis shipment error in AI: {e}") # 如果Redis失败,尝试重新连接 try: import sys sys.path.append('/home/hyx/work/生产管理系统') from server import get_redis r = get_redis() shipments_count = r.hlen('shipment_sn_mapping') shipments_stats['total'] = shipments_count shipments_stats['by_platform'] = {'pdd': shipments_count * 0.919, 'yt': shipments_count * 0.054, 'other': shipments_count * 0.027} except: pass # 获取其他统计数据 bom_stats = {'count': 0, 'products': 0} inventory_stats = {'count': 0, 'total_qty': 0} purchase_demand_stats = {'count': 0, 'total_required': 0} customer_order_stats = {'count': 0, 'total_qty': 0, 'completed': 0} reconciliation_stats = {'count': 0, 'total_qty': 0} # 准备AI分析数据,包含实时数据 print(f"\n=== AI分析数据准备 ===") print(f"数据库记录: PDD={len(pdd_data)}, YT={len(yt_data)}") print(f"实时数据: 今日PDD={real_pdd_count}, 今日YT={real_yt_count}") print(f"实时数据: 本周PDD={week_pdd_count}, 本周YT={week_yt_count}") print("========================\n") data = { "pdd": pdd_data, "yt": yt_data, "realtime": { "today_pdd": real_pdd_count, "today_yt": real_yt_count, "week_pdd": week_pdd_count, "week_yt": week_yt_count, "total_today": real_pdd_count + real_yt_count, "total_week": week_pdd_count + week_yt_count }, "shipments": shipments_stats, "bom": bom_stats, "inventory": inventory_stats, "purchase_demand": purchase_demand_stats, "customer_orders": customer_order_stats, "reconciliations": reconciliation_stats, "analysis_time": datetime.now().isoformat() } # 调用AI服务 config = get_ai_config() async with AIService(config) as ai_service: result = await ai_service.analyze_production_data(data) # 添加元数据 result["metadata"] = { "generated_at": datetime.now().isoformat(), "data_period": "最近30天", "total_records": len(pdd_data) + len(yt_data), "ai_provider": config.provider, "realtime_data": { "today_total": real_pdd_count + real_yt_count, "week_total": week_pdd_count + week_yt_count } } return JSONResponse(content=result) except Exception as e: logger.error(f"AI分析失败: {str(e)}") raise HTTPException(status_code=500, detail=f"AI分析失败: {str(e)}") @router.get("/config") async def get_ai_config_info(): """获取AI配置信息(不包含敏感信息)""" try: config = get_ai_config() return { "provider": config.provider, "model": config.model, "configured": bool(config.api_key or config.provider == "local") } except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/test") async def test_ai_connection(): """测试AI连接""" try: config = get_ai_config() # 测试数据 test_data = { "pdd": [{"ts_cn": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "batch": "TEST", "mac": "TEST001", "note": "测试数据"}], "yt": [] } async with AIService(config) as ai_service: result = await ai_service.analyze_production_data(test_data) return { "success": True, "message": "AI连接测试成功", "provider": config.provider, "model": config.model } except Exception as e: logger.error(f"AI连接测试失败: {str(e)}") return { "success": False, "message": f"AI连接测试失败: {str(e)}", "provider": config.provider if 'config' in locals() else "unknown" } @router.get("/providers") async def get_supported_providers(): """获取支持的AI提供商列表""" return { "providers": [ { "id": "openai", "name": "OpenAI", "models": ["gpt-3.5-turbo", "gpt-4", "gpt-4-turbo"], "description": "OpenAI GPT模型,需要API Key" }, { "id": "qwen", "name": "通义千问", "models": ["qwen-turbo", "qwen-plus", "qwen-max"], "description": "阿里云通义千问,需要API Key" }, { "id": "wenxin", "name": "文心一言", "models": ["ERNIE-Bot", "ERNIE-Bot-turbo", "ERNIE-Bot-4"], "description": "百度文心一言,需要API Key" }, { "id": "local", "name": "本地模型", "models": ["llama2", "llama2:13b", "codellama", "qwen:7b"], "description": "本地部署的模型(如Ollama),无需API Key" } ] }