first commit
This commit is contained in:
1
src/core/__init__.py
Normal file
1
src/core/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# 核心模块
|
||||
BIN
src/core/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
src/core/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/core/__pycache__/database.cpython-311.pyc
Normal file
BIN
src/core/__pycache__/database.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/core/__pycache__/llm_client.cpython-311.pyc
Normal file
BIN
src/core/__pycache__/llm_client.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/core/__pycache__/models.cpython-311.pyc
Normal file
BIN
src/core/__pycache__/models.cpython-311.pyc
Normal file
Binary file not shown.
94
src/core/database.py
Normal file
94
src/core/database.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from contextlib import contextmanager
|
||||
from typing import Generator
|
||||
import logging
|
||||
|
||||
from .models import Base
|
||||
from ..config.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class DatabaseManager:
|
||||
"""数据库管理器"""
|
||||
|
||||
def __init__(self):
|
||||
self.engine = None
|
||||
self.SessionLocal = None
|
||||
self._initialize_database()
|
||||
|
||||
def _initialize_database(self):
|
||||
"""初始化数据库连接"""
|
||||
try:
|
||||
db_config = Config.get_database_config()
|
||||
|
||||
# 根据数据库类型选择不同的连接参数
|
||||
if "mysql" in db_config["url"]:
|
||||
# MySQL配置
|
||||
self.engine = create_engine(
|
||||
db_config["url"],
|
||||
echo=db_config["echo"],
|
||||
pool_size=10,
|
||||
max_overflow=20,
|
||||
pool_pre_ping=True,
|
||||
pool_recycle=3600
|
||||
)
|
||||
else:
|
||||
# SQLite配置
|
||||
self.engine = create_engine(
|
||||
db_config["url"],
|
||||
echo=db_config["echo"],
|
||||
poolclass=StaticPool,
|
||||
connect_args={"check_same_thread": False}
|
||||
)
|
||||
|
||||
self.SessionLocal = sessionmaker(
|
||||
autocommit=False,
|
||||
autoflush=False,
|
||||
bind=self.engine
|
||||
)
|
||||
|
||||
# 创建所有表
|
||||
Base.metadata.create_all(bind=self.engine)
|
||||
logger.info("数据库初始化成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"数据库初始化失败: {e}")
|
||||
raise
|
||||
|
||||
@contextmanager
|
||||
def get_session(self) -> Generator[Session, None, None]:
|
||||
"""获取数据库会话的上下文管理器"""
|
||||
session = self.SessionLocal()
|
||||
try:
|
||||
yield session
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
logger.error(f"数据库操作失败: {e}")
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_session_direct(self) -> Session:
|
||||
"""直接获取数据库会话"""
|
||||
return self.SessionLocal()
|
||||
|
||||
def close_session(self, session: Session):
|
||||
"""关闭数据库会话"""
|
||||
if session:
|
||||
session.close()
|
||||
|
||||
def test_connection(self) -> bool:
|
||||
"""测试数据库连接"""
|
||||
try:
|
||||
with self.get_session() as session:
|
||||
session.execute(text("SELECT 1"))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"数据库连接测试失败: {e}")
|
||||
return False
|
||||
|
||||
# 全局数据库管理器实例
|
||||
db_manager = DatabaseManager()
|
||||
149
src/core/llm_client.py
Normal file
149
src/core/llm_client.py
Normal file
@@ -0,0 +1,149 @@
|
||||
import requests
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Any
|
||||
from datetime import datetime
|
||||
|
||||
from ..config.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class QwenClient:
|
||||
"""阿里云千问API客户端"""
|
||||
|
||||
def __init__(self):
|
||||
self.api_config = Config.get_api_config()
|
||||
self.base_url = self.api_config["base_url"]
|
||||
self.api_key = self.api_config["api_key"]
|
||||
self.model_name = self.api_config["model_name"]
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def chat_completion(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
temperature: float = 0.7,
|
||||
max_tokens: int = 1000,
|
||||
stream: bool = False
|
||||
) -> Dict[str, Any]:
|
||||
"""发送聊天请求"""
|
||||
try:
|
||||
url = f"{self.base_url}/chat/completions"
|
||||
payload = {
|
||||
"model": self.model_name,
|
||||
"messages": messages,
|
||||
"temperature": temperature,
|
||||
"max_tokens": max_tokens,
|
||||
"stream": stream
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
url,
|
||||
headers=self.headers,
|
||||
json=payload,
|
||||
timeout=Config.RESPONSE_TIMEOUT
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
logger.info("API请求成功")
|
||||
return result
|
||||
else:
|
||||
logger.error(f"API请求失败: {response.status_code} - {response.text}")
|
||||
return {"error": f"API请求失败: {response.status_code}"}
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.error("API请求超时")
|
||||
return {"error": "请求超时"}
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"API请求异常: {e}")
|
||||
return {"error": f"请求异常: {str(e)}"}
|
||||
except Exception as e:
|
||||
logger.error(f"未知错误: {e}")
|
||||
return {"error": f"未知错误: {str(e)}"}
|
||||
|
||||
def generate_response(
|
||||
self,
|
||||
user_message: str,
|
||||
context: Optional[str] = None,
|
||||
knowledge_base: Optional[List[str]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""生成回复"""
|
||||
messages = []
|
||||
|
||||
# 系统提示词
|
||||
system_prompt = "你是一个专业的客服助手,请根据用户问题提供准确、 helpful的回复。"
|
||||
if context:
|
||||
system_prompt += f"\n\n上下文信息: {context}"
|
||||
if knowledge_base:
|
||||
system_prompt += f"\n\n相关知识库: {' '.join(knowledge_base)}"
|
||||
|
||||
messages.append({"role": "system", "content": system_prompt})
|
||||
messages.append({"role": "user", "content": user_message})
|
||||
|
||||
result = self.chat_completion(messages)
|
||||
|
||||
if "error" in result:
|
||||
return result
|
||||
|
||||
try:
|
||||
response_content = result["choices"][0]["message"]["content"]
|
||||
return {
|
||||
"response": response_content,
|
||||
"usage": result.get("usage", {}),
|
||||
"model": result.get("model", ""),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
except (KeyError, IndexError) as e:
|
||||
logger.error(f"解析API响应失败: {e}")
|
||||
return {"error": f"解析响应失败: {str(e)}"}
|
||||
|
||||
def extract_entities(self, text: str) -> Dict[str, Any]:
|
||||
"""提取文本中的实体信息"""
|
||||
prompt = f"""
|
||||
请从以下文本中提取关键信息,包括:
|
||||
1. 问题类型/类别
|
||||
2. 优先级(高/中/低)
|
||||
3. 关键词
|
||||
4. 情感倾向(正面/负面/中性)
|
||||
|
||||
文本: {text}
|
||||
|
||||
请以JSON格式返回结果。
|
||||
"""
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": "你是一个信息提取专家,请准确提取文本中的关键信息。"},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
|
||||
result = self.chat_completion(messages, temperature=0.3)
|
||||
|
||||
if "error" in result:
|
||||
return result
|
||||
|
||||
try:
|
||||
response_content = result["choices"][0]["message"]["content"]
|
||||
# 尝试解析JSON
|
||||
import re
|
||||
json_match = re.search(r'\{.*\}', response_content, re.DOTALL)
|
||||
if json_match:
|
||||
return json.loads(json_match.group())
|
||||
else:
|
||||
return {"raw_response": response_content}
|
||||
except Exception as e:
|
||||
logger.error(f"解析实体提取结果失败: {e}")
|
||||
return {"error": f"解析失败: {str(e)}"}
|
||||
|
||||
def test_connection(self) -> bool:
|
||||
"""测试API连接"""
|
||||
try:
|
||||
result = self.chat_completion([
|
||||
{"role": "user", "content": "你好"}
|
||||
], max_tokens=10)
|
||||
return "error" not in result
|
||||
except Exception as e:
|
||||
logger.error(f"API连接测试失败: {e}")
|
||||
return False
|
||||
103
src/core/models.py
Normal file
103
src/core/models.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, Float, Boolean, ForeignKey
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
class WorkOrder(Base):
|
||||
"""工单模型"""
|
||||
__tablename__ = "work_orders"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
order_id = Column(String(50), unique=True, nullable=False)
|
||||
title = Column(String(200), nullable=False)
|
||||
description = Column(Text, nullable=False)
|
||||
category = Column(String(100), nullable=False)
|
||||
priority = Column(String(20), nullable=False)
|
||||
status = Column(String(20), nullable=False)
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
resolution = Column(Text)
|
||||
satisfaction_score = Column(Float)
|
||||
|
||||
# 关联对话记录
|
||||
conversations = relationship("Conversation", back_populates="work_order")
|
||||
|
||||
class Conversation(Base):
|
||||
"""对话记录模型"""
|
||||
__tablename__ = "conversations"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
work_order_id = Column(Integer, ForeignKey("work_orders.id"))
|
||||
user_message = Column(Text, nullable=False)
|
||||
assistant_response = Column(Text, nullable=False)
|
||||
timestamp = Column(DateTime, default=datetime.now)
|
||||
confidence_score = Column(Float)
|
||||
knowledge_used = Column(Text) # 使用的知识库条目
|
||||
response_time = Column(Float) # 响应时间(秒)
|
||||
|
||||
work_order = relationship("WorkOrder", back_populates="conversations")
|
||||
|
||||
class KnowledgeEntry(Base):
|
||||
"""知识库条目模型"""
|
||||
__tablename__ = "knowledge_entries"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
question = Column(Text, nullable=False)
|
||||
answer = Column(Text, nullable=False)
|
||||
category = Column(String(100), nullable=False)
|
||||
confidence_score = Column(Float, default=0.0)
|
||||
usage_count = Column(Integer, default=0)
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
is_active = Column(Boolean, default=True)
|
||||
is_verified = Column(Boolean, default=False) # 是否已验证
|
||||
verified_by = Column(String(100)) # 验证人
|
||||
verified_at = Column(DateTime) # 验证时间
|
||||
vector_embedding = Column(Text) # 向量嵌入的JSON字符串
|
||||
|
||||
class VehicleData(Base):
|
||||
"""车辆实时数据模型"""
|
||||
__tablename__ = "vehicle_data"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
vehicle_id = Column(String(50), nullable=False) # 车辆ID
|
||||
vehicle_vin = Column(String(17)) # 车架号
|
||||
data_type = Column(String(50), nullable=False) # 数据类型(位置、状态、故障等)
|
||||
data_value = Column(Text, nullable=False) # 数据值(JSON格式)
|
||||
timestamp = Column(DateTime, default=datetime.now) # 数据时间戳
|
||||
is_active = Column(Boolean, default=True) # 是否有效
|
||||
|
||||
# 索引
|
||||
__table_args__ = (
|
||||
{'extend_existing': True}
|
||||
)
|
||||
|
||||
class Analytics(Base):
|
||||
"""分析统计模型"""
|
||||
__tablename__ = "analytics"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
date = Column(DateTime, nullable=False)
|
||||
total_orders = Column(Integer, default=0)
|
||||
resolved_orders = Column(Integer, default=0)
|
||||
avg_resolution_time = Column(Float, default=0.0)
|
||||
satisfaction_avg = Column(Float, default=0.0)
|
||||
knowledge_hit_rate = Column(Float, default=0.0)
|
||||
category_distribution = Column(Text) # JSON格式的类别分布
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
|
||||
class Alert(Base):
|
||||
"""预警模型"""
|
||||
__tablename__ = "alerts"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
rule_name = Column(String(100), nullable=False)
|
||||
alert_type = Column(String(50), nullable=False)
|
||||
level = Column(String(20), nullable=False) # info, warning, error, critical
|
||||
message = Column(Text, nullable=False)
|
||||
data = Column(Text) # JSON格式的预警数据
|
||||
is_active = Column(Boolean, default=True)
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
resolved_at = Column(DateTime)
|
||||
Reference in New Issue
Block a user