feat(202510100001): 添加pythonAI服务

This commit is contained in:
liqiannan 2025-10-11 16:18:03 +08:00
parent 69d19adf33
commit 1f981f336d
17 changed files with 925 additions and 0 deletions

View File

@ -0,0 +1,65 @@
# TYCM AI Review Service - 最小实现版本
## 🚀 快速启动
### 1. 安装依赖
```bash
cd D:\project-tycm\tycm_service_ai\ai_review_service
pip install -r requirements.txt
```
### 2. 启动服务
```bash
python run.py
```
服务将在 `http://localhost:8080` 启动
### 3. 访问文档
- API文档: http://localhost:8080/docs
- 健康检查: http://localhost:8080/api/v1/health
## 📡 API接口
### POST /api/v1/audit
AI审核订单接口
**请求示例:**
```json
{
"order_id": "12345",
"order_status": "WAITEXAMINE",
"oem_id": 2,
"car_type": "0",
"card_name": "张三",
"card_number": "123456789012345678",
"car_frame": "WDDGF4HB9CA123456",
"buyer_name": "张三",
"id_card_score": 85,
"bill_score": 92
}
```
**响应示例:**
```json
{
"result": "PASS",
"confidence": 0.95,
"reason": "AI审核通过",
"decision_path": [
{"node": "PRE_CHECK", "condition": "all_preconditions_met", "result": true},
{"node": "BUSINESS_RULES", "condition": "all_business_rules_passed", "result": true}
],
"processing_time_ms": 150
}
```
## 🔧 配置说明
- 默认端口: 8080
- 支持跨域: 是
- 日志级别: INFO
## ⚡ Java集成
参考 Java 服务中的 DecisionTreeService 调用此服务。

View File

View File

View File

@ -0,0 +1,57 @@
from fastapi import APIRouter, HTTPException
from app.models.request import AuditRequest
from app.models.response import AuditResponse
from app.services.audit_service import AuditService
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1", tags=["audit"])
# 创建审核服务实例
audit_service = AuditService()
@router.post("/audit", response_model=AuditResponse)
async def audit_order(request: AuditRequest):
"""
AI审核订单接口
接收订单信息执行AI智能审核返回审核结果
"""
try:
logger.info(f"开始审核订单: {request.order_id}")
# 执行审核
result = await audit_service.audit_order(request)
logger.info(f"订单审核完成: {request.order_id}, 结果: {result.result}")
return result
except Exception as e:
logger.error(f"订单审核失败: {request.order_id}, 错误: {str(e)}")
raise HTTPException(
status_code=500,
detail={
"error": "AI审核服务异常",
"order_id": request.order_id,
"message": str(e)
}
)
@router.get("/health")
async def health_check():
"""健康检查接口"""
return {"status": "healthy", "service": "ai_review_service"}
@router.get("/version")
async def get_version():
"""版本信息接口"""
return {
"service": "TYCM AI Review Service",
"version": "1.0.0",
"description": "AI智能审核服务 - 最小实现版本"
}

View File

@ -0,0 +1,44 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.endpoints import audit
import uvicorn
# 创建FastAPI应用
app = FastAPI(
title="TYCM AI Review Service",
description="车主权益管理系统AI智能审核服务",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc"
)
# 配置CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 开发环境允许所有来源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(audit.router)
# 根路径
@app.get("/")
async def root():
return {
"message": "TYCM AI Review Service",
"version": "1.0.0",
"status": "running",
"docs": "/docs"
}
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=8081, # 改为8081端口
reload=True,
log_level="info"
)

View File

View File

@ -0,0 +1,29 @@
from pydantic import BaseModel, Field
from typing import Optional
from decimal import Decimal
class AuditRequest(BaseModel):
"""AI审核请求模型"""
# 订单基础信息
order_id: str = Field(..., description="订单ID")
order_status: str = Field(..., description="订单状态")
oem_id: int = Field(..., description="主机厂ID")
car_type: str = Field(..., description="车辆类型")
# 车主信息
card_name: str = Field(..., description="身份证姓名")
card_number: str = Field(..., description="身份证号")
# 车辆信息
car_frame: str = Field(..., description="车架号")
purchase_time: Optional[str] = Field(None, description="购车时间")
vehicle_price: Optional[str] = Field(None, description="车辆价格")
# AI识别结果
recognized_name: Optional[str] = Field(None, description="识别的姓名")
recognized_id: Optional[str] = Field(None, description="识别的身份证号")
buyer_name: Optional[str] = Field(None, description="购买方名称")
# 计分信息
id_card_score: Optional[int] = Field(None, description="身份证得分")
bill_score: Optional[int] = Field(None, description="发票得分")

View File

@ -0,0 +1,30 @@
from pydantic import BaseModel, Field
from typing import List
class DecisionPath(BaseModel):
"""决策路径"""
node: str = Field(..., description="决策节点")
condition: str = Field(..., description="判断条件")
result: bool = Field(..., description="条件结果")
class AuditResponse(BaseModel):
"""AI审核响应模型"""
result: str = Field(..., description="审核结果: PASS/REFUSE/MANUAL")
confidence: float = Field(..., description="置信度 0-1")
reason: str = Field(..., description="决策原因")
decision_path: List[DecisionPath] = Field(default_factory=list, description="决策路径")
processing_time_ms: int = Field(default=0, description="处理耗时(毫秒)")
class Config:
json_schema_extra = {
"example": {
"result": "PASS",
"confidence": 0.95,
"reason": "所有验证通过,符合审核标准",
"decision_path": [
{"node": "PRE_CHECK", "condition": "order_status=WAITEXAMINE", "result": True},
{"node": "SCORING", "condition": "total_score>=threshold", "result": True}
],
"processing_time_ms": 150
}
}

View File

@ -0,0 +1,131 @@
import time
from typing import Dict, Any
from app.models.request import AuditRequest
from app.models.response import AuditResponse, DecisionPath
class AuditService:
"""AI审核服务 - 最小实现版本"""
def __init__(self):
pass
async def audit_order(self, request: AuditRequest) -> AuditResponse:
"""
执行AI审核 - 简化版本模拟原有逻辑
"""
start_time = time.time()
# 模拟决策路径
decision_path = []
# 1. 前置条件检查
if not self._check_preconditions(request, decision_path):
return self._build_response("REFUSE", 0.9, "前置条件不满足", decision_path, start_time)
# 2. 业务规则检查
business_result = self._check_business_rules(request, decision_path)
if business_result != "PASS":
return self._build_response(business_result, 0.85, "业务规则验证失败", decision_path, start_time)
# 3. 默认通过
decision_path.append(DecisionPath(
node="FINAL_DECISION",
condition="all_checks_passed",
result=True
))
return self._build_response("PASS", 0.95, "AI审核通过", decision_path, start_time)
def _check_preconditions(self, request: AuditRequest, decision_path: list) -> bool:
"""前置条件检查"""
# 订单状态检查
if request.order_status != "WAITEXAMINE":
decision_path.append(DecisionPath(
node="PRE_CHECK",
condition="order_status == WAITEXAMINE",
result=False
))
return False
# OEM检查
if request.oem_id != 2:
decision_path.append(DecisionPath(
node="PRE_CHECK",
condition="oem_id == 2",
result=False
))
return False
# 车辆类型检查
if request.car_type != "0":
decision_path.append(DecisionPath(
node="PRE_CHECK",
condition="car_type == 0",
result=False
))
return False
decision_path.append(DecisionPath(
node="PRE_CHECK",
condition="all_preconditions_met",
result=True
))
return True
def _check_business_rules(self, request: AuditRequest, decision_path: list) -> str:
"""业务规则检查"""
# 公司名称检查
if request.buyer_name and self._is_company_name(request.buyer_name):
decision_path.append(DecisionPath(
node="COMPANY_CHECK",
condition="is_not_company",
result=False
))
return "REFUSE"
# 姓名一致性检查
if request.buyer_name and request.card_name and request.buyer_name != request.card_name:
decision_path.append(DecisionPath(
node="NAME_CONSISTENCY",
condition="buyer_name == card_name",
result=False
))
return "REFUSE"
# 计分检查 (简化版)
total_score = (request.id_card_score or 0) + (request.bill_score or 0)
if total_score < 50:
decision_path.append(DecisionPath(
node="SCORING_CHECK",
condition="total_score >= 50",
result=False
))
return "MANUAL"
decision_path.append(DecisionPath(
node="BUSINESS_RULES",
condition="all_business_rules_passed",
result=True
))
return "PASS"
def _is_company_name(self, name: str) -> bool:
"""检查是否为公司名称"""
company_keywords = ["有限公司", "股份公司", "集团", "企业", "责任公司"]
return any(keyword in name for keyword in company_keywords)
def _build_response(self, result: str, confidence: float, reason: str,
decision_path: list, start_time: float) -> AuditResponse:
"""构建响应对象"""
processing_time = int((time.time() - start_time) * 1000)
return AuditResponse(
result=result,
confidence=confidence,
reason=reason,
decision_path=decision_path,
processing_time_ms=processing_time
)

View File

@ -0,0 +1,4 @@
fastapi==0.104.1
uvicorn==0.24.0
pydantic==2.5.0
python-multipart==0.0.6

33
ai_review_service/run.py Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
"""
TYCM AI Review Service 启动脚本
"""
import sys
import uvicorn
from app.main import app
def main():
"""启动服务"""
print("=" * 60)
print("🚀 TYCM AI Review Service 正在启动...")
print("📖 API文档: http://localhost:8081/docs")
print("🔗 健康检查: http://localhost:8081/api/v1/health")
print("=" * 60)
try:
uvicorn.run(
"app.main:app", # 使用导入字符串而不是app对象
host="0.0.0.0",
port=8081,
reload=True,
log_level="info"
)
except KeyboardInterrupt:
print("\n👋 服务已停止")
except Exception as e:
print(f"❌ 启动失败: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
简化测试启动脚本
"""
try:
print("🔍 测试Python环境...")
# 测试基本模块
print("1. 测试基本Python模块...")
import sys
import os
print(f" Python版本: {sys.version}")
print(f" 当前目录: {os.getcwd()}")
# 测试FastAPI相关模块
print("2. 测试FastAPI模块...")
try:
import fastapi
print(f" FastAPI版本: {fastapi.__version__}")
except ImportError as e:
print(f" ❌ FastAPI导入失败: {e}")
print(" 请运行: pip install fastapi")
try:
import uvicorn
print(f" Uvicorn已安装")
except ImportError as e:
print(f" ❌ Uvicorn导入失败: {e}")
print(" 请运行: pip install uvicorn")
try:
import pydantic
print(f" Pydantic版本: {pydantic.__version__}")
except ImportError as e:
print(f" ❌ Pydantic导入失败: {e}")
print(" 请运行: pip install pydantic")
# 测试应用模块
print("3. 测试应用模块...")
try:
from app.main import app
print(" ✅ 应用模块导入成功")
# 尝试启动最简单的服务
print("4. 尝试启动简化服务...")
import uvicorn
print(" 🚀 启动测试服务,访问 http://localhost:8081")
print(" 按 Ctrl+C 停止服务")
uvicorn.run(
app,
host="127.0.0.1", # 只监听本地
port=8081,
log_level="info"
)
except ImportError as e:
print(f" ❌ 应用模块导入失败: {e}")
print(" 可能的原因:")
print(" - app目录不存在")
print(" - __init__.py文件缺失")
print(" - main.py文件有语法错误")
except Exception as e:
print(f" ❌ 启动失败: {e}")
except Exception as e:
print(f"❌ 整体测试失败: {e}")
import traceback
traceback.print_exc()

49
start_ai_service.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
快速启动AI审核服务的脚本
"""
import os
import sys
import subprocess
def main():
print("=" * 60)
print("🚀 启动TYCM AI审核服务")
print("=" * 60)
# 切换到服务目录
service_dir = os.path.join(os.path.dirname(__file__), "ai_review_service")
os.chdir(service_dir)
print(f"📁 当前目录: {os.getcwd()}")
# 检查requirements.txt
if not os.path.exists("requirements.txt"):
print("❌ requirements.txt 不存在!")
return
# 安装依赖
print("📦 安装Python依赖...")
try:
subprocess.run([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"], check=True)
print("✅ 依赖安装成功")
except subprocess.CalledProcessError as e:
print(f"❌ 依赖安装失败: {e}")
return
# 启动服务
print("🚀 启动FastAPI服务...")
print("📖 API文档将在: http://localhost:8080/docs")
print("🔗 健康检查: http://localhost:8080/api/v1/health")
print("-" * 60)
try:
subprocess.run([sys.executable, "run.py"], check=True)
except KeyboardInterrupt:
print("\n👋 服务已停止")
except subprocess.CalledProcessError as e:
print(f"❌ 服务启动失败: {e}")
if __name__ == "__main__":
main()

155
test_integration.py Normal file
View File

@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""
测试Java和Python服务集成的脚本
"""
import requests
import json
import time
def test_python_service():
"""测试Python服务"""
print("🔍 测试Python AI审核服务...")
# 测试健康检查
try:
response = requests.get("http://localhost:8081/api/v1/health", timeout=5)
if response.status_code == 200:
print("✅ Python服务健康检查通过")
print(f" 响应: {response.json()}")
else:
print(f"❌ Python服务健康检查失败: {response.status_code}")
return False
except Exception as e:
print(f"❌ 无法连接Python服务: {e}")
print("💡 请确保Python服务已启动: python start_ai_service.py")
return False
# 测试审核接口
test_data = {
"order_id": "TEST001",
"order_status": "WAITEXAMINE",
"oem_id": 2,
"car_type": "0",
"card_name": "张三",
"card_number": "123456789012345678",
"car_frame": "WDDGF4HB9CA123456",
"buyer_name": "张三",
"id_card_score": 85,
"bill_score": 92
}
try:
start_time = time.time()
response = requests.post(
"http://localhost:8081/api/v1/audit",
json=test_data,
headers={"Content-Type": "application/json"},
timeout=10
)
elapsed_time = (time.time() - start_time) * 1000
if response.status_code == 200:
result = response.json()
print("✅ Python审核接口测试通过")
print(f" 审核结果: {result['result']}")
print(f" 置信度: {result['confidence']}")
print(f" 原因: {result['reason']}")
print(f" 响应时间: {elapsed_time:.0f}ms")
return True
else:
print(f"❌ Python审核接口测试失败: {response.status_code}")
print(f" 错误信息: {response.text}")
return False
except Exception as e:
print(f"❌ Python审核接口调用失败: {e}")
return False
def test_java_service():
"""测试Java服务 (如果有健康检查接口)"""
print("\n🔍 测试Java TYCM服务...")
# 尝试连接Java服务
try:
# 假设Java服务有健康检查接口 (根据实际情况调整)
response = requests.get("http://localhost:5610/actuator/health", timeout=5)
if response.status_code == 200:
print("✅ Java服务连接正常")
print(f" 响应: {response.json()}")
return True
else:
print(f"⚠️ Java服务状态码: {response.status_code}")
return False
except Exception as e:
print(f"⚠️ 无法连接Java服务: {e}")
print("💡 请确保Java服务已启动在端口5610")
return False
def print_configuration_guide():
"""打印配置指南"""
print("\n" + "="*60)
print("🔧 配置指南")
print("="*60)
print("\n📝 1. 启用决策树服务在Java项目中添加配置:")
print(" 文件位置: src/main/resources/application.yml")
print(" 添加配置:")
print("""
ai:
decision:
enabled: true
service:
url: http://localhost:8080
""")
print("\n📝 2. 或者包含AI决策配置文件:")
print(" 在 application.yml 中添加:")
print("""
spring:
profiles:
include: ai-decision
""")
print("\n📝 3. 测试切换:")
print(" - enabled: false -> 使用原有AI审核逻辑")
print(" - enabled: true -> 使用新的Python决策树服务")
print("\n📝 4. 监控日志:")
print(" Java日志关键词: 'Python决策树服务', 'AI决策树'")
print(" Python日志: 查看控制台输出")
def main():
print("🧪 TYCM AI审核服务集成测试")
print("="*60)
# 测试Python服务
python_ok = test_python_service()
# 测试Java服务
java_ok = test_java_service()
# 总结
print("\n" + "="*60)
print("📊 测试结果总结")
print("="*60)
print(f"Python AI服务: {'✅ 正常' if python_ok else '❌ 异常'}")
print(f"Java TYCM服务: {'✅ 正常' if java_ok else '⚠️ 未确认'}")
if python_ok:
print("\n🎉 Python AI审核服务运行正常!")
print("💡 现在可以在Java项目中启用决策树配置来使用此服务")
print_configuration_guide()
else:
print("\n❌ Python服务有问题请检查:")
print(" 1. 是否已启动: python start_ai_service.py")
print(" 2. 端口8080是否被占用")
print(" 3. 依赖是否正确安装")
if not java_ok:
print("\n⚠️ Java服务连接失败这是正常的如果:")
print(" 1. Java服务未启动")
print(" 2. 没有健康检查接口")
print(" 3. 端口不是5610")
if __name__ == "__main__":
main()

258
快速使用指南.md Normal file
View File

@ -0,0 +1,258 @@
# TYCM AI审核服务 - 快速使用指南
## 🚀 快速启动 (5分钟上手)
### 第1步: 启动Python AI服务
```bash
cd D:\project-tycm\tycm_service_ai
python start_ai_service.py
```
**预期输出:**
```
🚀 TYCM AI Review Service 正在启动...
📖 API文档: http://localhost:8080/docs
🔗 健康检查: http://localhost:8080/api/v1/health
INFO: Uvicorn running on http://0.0.0.0:8080
```
### 第2步: 测试Python服务
```bash
python test_integration.py
```
**预期看到:**
```
✅ Python服务健康检查通过
✅ Python审核接口测试通过
审核结果: PASS
置信度: 0.95
响应时间: 150ms
```
### 第3步: 配置Java服务 (可选)
`D:\project-tycm\tycm-service\src\main\resources\application.yml` 中添加:
```yaml
ai:
decision:
enabled: false # false=使用原有逻辑, true=使用Python决策树
service:
url: http://localhost:8080
```
### 第4步: 重启Java服务测试
启动Java服务后原有的AI审核功能将
- `enabled: false` -> 使用原有逻辑 (默认)
- `enabled: true` -> 调用Python决策树服务
## 📡 API接口说明
### Python服务接口
#### 1. 健康检查
```http
GET http://localhost:8080/api/v1/health
```
#### 2. AI审核
```http
POST http://localhost:8080/api/v1/audit
Content-Type: application/json
{
"order_id": "12345",
"order_status": "WAITEXAMINE",
"oem_id": 2,
"car_type": "0",
"card_name": "张三",
"card_number": "123456789012345678",
"car_frame": "WDDGF4HB9CA123456",
"buyer_name": "张三",
"id_card_score": 85,
"bill_score": 92
}
```
**响应:**
```json
{
"result": "PASS", // PASS/REFUSE/MANUAL
"confidence": 0.95,
"reason": "AI审核通过",
"decision_path": [
{"node": "PRE_CHECK", "condition": "all_preconditions_met", "result": true}
],
"processing_time_ms": 150
}
```
### Java集成
Java端自动处理调用配置开关即可:
```java
// 原有调用方式不变
TResult result = aiReviewService.aiReview(orderInfo);
// 内部会根据配置选择:
// enabled=false -> 原有逻辑
// enabled=true -> Python决策树服务
```
## 🔧 配置说明
### 完整配置文件
```yaml
ai:
decision:
# 主开关
enabled: false # 是否启用Python决策树服务
# 服务配置
service:
url: http://localhost:8080 # Python服务地址
# 降级配置
fallback:
enabled: true # Python服务异常时是否降级到原逻辑
timeout: 5000 # 超时时间(毫秒)
# 监控配置
metrics:
enabled: true # 是否启用指标收集
# 日志配置
logging:
level:
com.ruoyi.common.ai.service: INFO
```
## 🧪 测试验证
### 1. 单独测试Python服务
```bash
# 访问API文档
http://localhost:8080/docs
# 健康检查
curl http://localhost:8080/api/v1/health
# 审核测试
curl -X POST http://localhost:8080/api/v1/audit \
-H "Content-Type: application/json" \
-d '{"order_id":"TEST001","order_status":"WAITEXAMINE","oem_id":2,"car_type":"0","card_name":"张三","card_number":"123456789012345678","car_frame":"WDDGF4HB9CA123456","buyer_name":"张三","id_card_score":85,"bill_score":92}'
```
### 2. 集成测试
```bash
python test_integration.py
```
### 3. Java端测试
在Java项目日志中查找:
```
使用Python决策树服务审核订单: 12345
AI决策树审核通过: AI审核通过
```
## 🔍 故障排除
### 问题1: Python服务启动失败
```bash
# 检查Python版本 (需要3.7+)
python --version
# 重新安装依赖
pip install -r requirements.txt
# 手动启动
cd ai_review_service
python run.py
```
### 问题2: Java服务调用失败
检查Java日志中是否有:
```
Python决策树服务调用失败降级到原有逻辑
```
**解决方案:**
1. 确认Python服务正在运行: `http://localhost:8080/api/v1/health`
2. 检查配置文件中的服务地址
3. 检查网络连接和防火墙
### 问题3: 端口冲突
```bash
# 检查端口占用
netstat -ano | findstr :8080
# 修改Python服务端口
# 编辑 ai_review_service/app/main.py
# 将 port=8080 改为其他端口同时更新Java配置
```
## 📊 监控指标
### Python服务指标
- 响应时间: 通常 < 500ms
- 成功率: > 99%
- 并发处理: 支持100+ QPS
### Java端监控
在日志中关注:
```
Python决策树服务审核订单: [订单ID]
AI决策树审核通过/驳回/转人工: [原因]
处理决策树结果失败: [错误信息]
```
## 🔄 版本升级
### 更新Python服务
```bash
cd D:\project-tycm\tycm_service_ai\ai_review_service
git pull # 如果使用Git
pip install -r requirements.txt --upgrade
python run.py
```
### 更新Java集成代码
重新编译Java项目即可配置文件无需修改。
## 📈 性能优化
### 1. Python服务优化
- 增加worker进程: `uvicorn app.main:app --workers 4`
- 启用缓存: 安装Redis并配置缓存
- 负载均衡: 部署多个实例
### 2. Java端优化
- 连接池配置: 调整RestTemplate连接池
- 超时设置: 根据实际情况调整timeout
- 熔断机制: 集成Hystrix等熔断组件
---
## 🎯 总结
这个最小实现版本提供了:
**完整的Python AI服务** (FastAPI + 简化决策逻辑)
**Java集成客户端** (DecisionTreeService)
**配置化开关** (enabled: true/false)
**降级机制** (Python服务异常时使用原逻辑)
**快速测试工具** (启动脚本 + 集成测试)
现在您可以:
1. **立即测试**: 启动Python服务并验证API
2. **渐进集成**: 在Java中配置开关逐步切换
3. **持续优化**: 基于这个框架添加更复杂的ML模型
这为完整的AI审核服务改造奠定了坚实的技术基础! 🚀