This commit is contained in:
2025-12-06 16:03:18 +08:00
commit 6029da058a
24 changed files with 3898 additions and 0 deletions

218
backend/main.py Normal file
View File

@@ -0,0 +1,218 @@
from fastapi import FastAPI, HTTPException, APIRouter
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import httpx
import json
import os
from config import get_deepseek_api_key, is_api_key_configured, settings
app = FastAPI(title="DeepSeek AI Chat Assistant", version="1.0.0")
# 创建API路由,统一使用/api前缀
api_router = APIRouter(prefix="/api")
# CORS配置
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 数据模型
class Message(BaseModel):
role: str
content: str
class ChatRequest(BaseModel):
message: str
conversation_id: Optional[str] = None
class ChatResponse(BaseModel):
response: str
conversation_id: str
class RoleConfig(BaseModel):
name: str
description: str
skills: List[str]
restrictions: List[str]
# 默认角色配置
DEFAULT_ROLE_CONFIG = RoleConfig(
name="兜兜",
description="你是兜兜,1989年出生,有一个5岁的女儿(2018年出生)。你是一位对用户负责、选品严格的宝妈客服。当用户给你发来疑问时,你总能第一时间回复,并以亲切温暖的风格与用户交流。",
skills=[
"亲切温暖的沟通",
"轻松友好的语气",
"简洁明了的描述",
"亲昵且口语化的用词",
"乱码话术重复问询",
],
restrictions=[
"回复必须基于提供的知识库中的内容",
"每条回复应保持在80字以内,使用口语化语言",
"回复中可以适当加入表情符号,但不要过度使用",
"只讨论与宝妈相关的主题,如育儿、选品、团购等",
"始终以用户的需求和满意度为优先",
],
)
# 全局变量存储角色配置和对话历史
current_role_config = DEFAULT_ROLE_CONFIG
conversations = {}
def build_system_prompt(role_config: RoleConfig) -> str:
"""构建系统提示词"""
prompt = f"""# 角色
{role_config.description}
## 技能
### 技能 1: 亲切温暖的沟通
- **风格**:你的风格非常亲切,像是一个知心朋友在和大家聊天,给人一种温暖的感觉。你经常使用"宝"、"美妈"等亲昵的称呼,拉近了与用户的距离。
- **耐心细致**:你总是耐心解答用户的问题,尤其是对于新用户或不熟悉流程的用户,你会反复提醒他们查看群公告,保持安静等待开团。
- **负责靠谱**:你给人一种非常靠谱的感觉,尤其是在售后问题上,你会主动承担责任,承诺包处理满意,给用户很强的信任感。
### 技能 2: 轻松友好的语气
- **轻松友好**:你的语气非常轻松,像是在和朋友聊天,不会给人压力。比如"不着急哦"、"爱你!"等表达方式,让人感到轻松愉快。
- **安抚性**:当用户有疑问或遇到问题时,你的语气总是充满安抚性,比如"美妈不用担心"、"兜兜来处理哈",给人一种安心感。
- **鼓励性**:你经常用"不着急"、"等开团的时候会有统一说明"等话语,鼓励用户耐心等待,保持积极的心态。
### 技能 3: 简洁明了的描述
- **简洁明了**:你的描述非常简洁,直接回答用户的问题,不会绕弯子。比如"贝亲是咱们深度合作品牌,经常上团的",直接给出了明确的答案。
- **细节丰富**:在回答问题时,你会提供一些细节信息,比如"一般2天左右就会来"、"奶粉类的,贝亲,世喜,赫根,等常见品牌都有",让用户对情况有更清晰的了解。
- **引导性**:你经常引导用户查看群公告,保持安静等待开团,比如"不熟悉的可以看一下群公告哦"、"现在安静的等开团就行啦",帮助用户更好地参与活动。
### 技能 4: 亲昵且口语化的用词
- **亲昵称呼**:你经常使用"宝"、"美妈"、"大家"等亲昵的称呼,拉近与用户的距离,给人一种亲切感。
- **口语化**:你的用词非常口语化,像是日常聊天,比如"不着急哦"、"爱你!"、"兜兜来处理哈",给人一种轻松自然的感觉,称呼自己为"兜兜"或者"我"。
- **积极正面**:你的用词总是积极正面的,比如"不用担心"、"包处理满意"、"很快"、"常见品牌都有",给用户传递了积极的信息。
### 技能 5: 乱码话术重复问询
- **确认问题**:用户说的看不懂的情况来进行再次确认,比如 "45615465" "分隔符规划规范的" "8分隔符公司的"等跟常规问题没关联的话术来重复确认,例如:"宝看不懂你说的是什么啊,能在具体点嘛"
## 限制
- 回复必须基于提供的知识库中的内容。
- 每条回复应保持在80字以内,使用口语化语言。
- 回复中可以适当加入表情符号,但不要过度使用。
- 只讨论与宝妈相关的主题,如育儿、选品、团购等。
- 始终以用户的需求和满意度为优先。
- 在回答问题时,确保信息准确无误,避免误导用户。
- 保持沟通的亲切性和温暖感,但不要过度使用亲昵称呼,以免显得过于随意。
请按照以上角色设定和限制来回答用户的问题。"""
return prompt
async def call_deepseek_api(messages: List[dict]) -> str:
"""调用DeepSeek API"""
# 使用配置管理获取API密钥
api_key = get_deepseek_api_key()
if not is_api_key_configured():
# 模拟响应用于演示
return "宝,这个问题兜兜需要查一下资料哦,稍等哈~ 😊"
url = "https://api.deepseek.com/v1/chat/completions"
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
data = {
"model": "deepseek-chat",
"messages": messages,
"stream": False,
"max_tokens": 500,
}
try:
async with httpx.AsyncClient() as client:
response = await client.post(url, headers=headers, json=data, timeout=30.0)
response.raise_for_status()
result = response.json()
return result["choices"][0]["message"]["content"]
except Exception as e:
raise HTTPException(status_code=500, detail=f"API调用失败: {str(e)}")
@api_router.get("/")
async def root():
return {"message": "DeepSeek AI Chat Assistant API"}
@api_router.get("/role")
async def get_role_config():
"""获取当前角色配置"""
return current_role_config
@api_router.put("/role")
async def update_role_config(role_config: RoleConfig):
"""更新角色配置"""
global current_role_config
current_role_config = role_config
return {"message": "角色配置已更新", "role_config": current_role_config}
@api_router.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
"""处理聊天请求"""
# 创建或获取对话历史
if request.conversation_id and request.conversation_id in conversations:
conversation_history = conversations[request.conversation_id]
else:
conversation_history = []
request.conversation_id = f"conv_{len(conversations) + 1}"
conversations[request.conversation_id] = conversation_history
# 构建消息列表
messages = [{"role": "system", "content": build_system_prompt(current_role_config)}]
# 添加历史消息
for msg in conversation_history[-10:]: # 保留最近10条历史
messages.append({"role": msg["role"], "content": msg["content"]})
# 添加当前用户消息
messages.append({"role": "user", "content": request.message})
conversation_history.append({"role": "user", "content": request.message})
# 调用DeepSeek API
try:
response_text = await call_deepseek_api(messages)
# 添加助手回复到历史
conversation_history.append({"role": "assistant", "content": response_text})
return ChatResponse(
response=response_text, conversation_id=request.conversation_id
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@api_router.get("/conversations/{conversation_id}")
async def get_conversation(conversation_id: str):
"""获取特定对话的历史"""
if conversation_id not in conversations:
raise HTTPException(status_code=404, detail="对话不存在")
return {
"conversation_id": conversation_id,
"messages": conversations[conversation_id],
}
# 注册API路由
app.include_router(api_router)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host=settings.host, port=settings.port, reload=settings.debug)