feat: 完整功能部署 v1.0

新增功能:
- 天网协作系统 (HTTP API 端口 6060)
- 三种工作流 (查找图片/处理图片/转人工派单)
- 图片任务数据库 (支持客户后续增加需求)
- 图绘派单系统集成 (API: 8005)
- 文字检测与加价 (60-80 元高价值订单)
- 风险评估与接单判断
- 作图失败自动转人工

新增文档:
- 项目功能汇总.md
- 三种工作流功能说明.md
- 文字加价功能说明.md
- 风险评估功能说明.md
- 图片任务数据库功能说明.md
- 图绘派单系统集成说明.md
- 作图失败转接人工说明.md
- DEPLOYMENT.md
- TIANWANG_INTEGRATION.md

核心修改:
- core/pydantic_ai_agent.py
- core/workflow.py
- core/websocket_client.py
- image/image_analyzer.py
- services/service_tuhui_dispatch.py
- db/image_tasks_db.py

版本:v1.0
日期:2026-02-28
This commit is contained in:
2026-02-28 11:20:40 +08:00
parent 5aedf1665d
commit a6c42d505a
171 changed files with 7979 additions and 328 deletions

371
core/workflow.py Normal file → Executable file
View File

@@ -418,13 +418,13 @@ class CustomerServiceWorkflow:
f"原因:{err_msg[:200]}\n"
f"请人工跟进"
)
# 通知客户稍等,人工跟进
# 通知客户稍等,并告知转人工
if self._send_message:
await self._send_message(
customer_id=task.customer_id,
acc_id=acc_id,
acc_type=acc_type,
content="您好,图片正在处理中,稍后发您,请稍",
content="您好,图片处理遇到点问题,已帮您转接人工客服处理,请稍",
msg_type=0,
)
except Exception as e:
@@ -614,3 +614,370 @@ class CustomerServiceWorkflow:
# ========== 全局实例 ==========
workflow = CustomerServiceWorkflow()
# ========== 客户需求变更 ==========
async def add_customer_requirement(self, task_id: str, customer_id: str,
requirement: str, changed_by: str = 'customer') -> bool:
"""
客户添加/修改需求细节
Args:
task_id: 任务 ID
customer_id: 客户 ID
requirement: 需求内容(如:"需要去掉背景""要分层文件"
changed_by: 修改者customer/staff
Returns:
bool: 是否成功
"""
# 检查任务是否存在
task = self.get_task(task_id)
if not task:
# 尝试从数据库加载
db_task = self.db.get_task(task_id)
if db_task:
print(f"[Workflow] 从数据库加载任务:{task_id[:8]}...")
# 可以在这里重建内存任务
else:
print(f"[Workflow] 任务不存在:{task_id}")
return False
# 添加到数据库
success = self.db.add_customer_note(task_id, requirement, changed_by)
if success:
print(f"[Workflow] 客户添加需求:{task_id[:8]}... | {requirement}")
# 如果任务还在待处理状态,通知 AI 客服
if task and task.status.value == 'pending':
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=task.acc_id,
acc_type=task.acc_type,
content=f"好的,已记录您的需求:{requirement},处理时会注意的",
msg_type=0,
)
return success
async def modify_operation(self, task_id: str, customer_id: str,
new_operation: str, changed_by: str = 'customer') -> bool:
"""
客户修改操作类型
Args:
task_id: 任务 ID
customer_id: 客户 ID
new_operation: 新操作enhance/remove_bg/vectorize 等)
changed_by: 修改者
Returns:
bool: 是否成功
"""
task = self.get_task(task_id)
if not task:
db_task = self.db.get_task(task_id)
if not db_task:
print(f"[Workflow] 任务不存在:{task_id}")
return False
# 检查状态,已处理完成的不允许修改
if task and task.status.value in ['completed', 'processing']:
print(f"[Workflow] 任务已开始处理,不允许修改操作:{task_id}")
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=task.acc_id,
acc_type=task.acc_type,
content="抱歉,图片已经开始处理了,无法修改操作类型",
msg_type=0,
)
return False
# 修改数据库
success = self.db.modify_operation(task_id, new_operation, changed_by)
if success and task:
task.operation = new_operation
print(f"[Workflow] 修改操作类型:{task_id[:8]}... -> {new_operation}")
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=task.acc_id,
acc_type=task.acc_type,
content=f"好的,已为您修改为{new_operation}操作",
msg_type=0,
)
return success
def get_task_requirement_history(self, task_id: str) -> List[dict]:
"""获取任务需求变更历史"""
return self.db.get_requirement_history(task_id)
# ========== 三种工作流 ==========
async def find_image_workflow(self, customer_id: str, image_url: str,
acc_id: str = "", acc_type: str = "AliWorkbench") -> bool:
"""
工作流 1查找图片
客户说"找一下这个图" → 自己处理 → 上传到图绘 → 返回 URL
Args:
customer_id: 客户 ID
image_url: 图片 URL
acc_id: 店铺 ID
acc_type: 平台类型
Returns:
bool: 是否成功
"""
try:
print(f"[Workflow] 启动查找图片工作流 | 客户:{customer_id}")
# 1. 创建任务
task_id = self.create_image_task(
customer_id=customer_id,
customer_name=customer_id,
original_image=image_url,
operation="find", # 查找操作
requirements="type:find",
acc_id=acc_id,
acc_type=acc_type
)
# 2. 这里调用图绘 API 上传图片
# TODO: 调用图绘上传 API
# tuhui_url = await self._upload_to_tuhui(image_url)
# 临时模拟
tuhui_url = f"http://tuhui.cloud/works/123"
# 3. 更新任务结果
self.db.update_result(task_id, tuhui_url)
self.db.update_status(task_id, DBTaskStatus.COMPLETED)
# 4. 回复客户
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=acc_id,
acc_type=acc_type,
content=f"找到了!图片在这里:{tuhui_url}",
msg_type=0,
)
print(f"[Workflow] 查找图片完成 | 客户:{customer_id} | URL: {tuhui_url}")
return True
except Exception as e:
logger.error(f"查找图片工作流失败:{e}")
return False
async def process_image_workflow(self, customer_id: str, image_url: str,
acc_id: str = "", acc_type: str = "AliWorkbench") -> bool:
"""
工作流 2处理图片
客户说"做一下" → 评估图片 → 稍等做
Args:
customer_id: 客户 ID
image_url: 图片 URL
acc_id: 店铺 ID
acc_type: 平台类型
Returns:
bool: 是否成功
"""
try:
print(f"[Workflow] 启动处理图片工作流 | 客户:{customer_id}")
# 1. 创建任务
task_id = self.create_image_task(
customer_id=customer_id,
customer_name=customer_id,
original_image=image_url,
operation="enhance",
requirements="type:process",
acc_id=acc_id,
acc_type=acc_type
)
# 2. 回复客户稍等
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=acc_id,
acc_type=acc_type,
content="稍等,我看看...好的,可以做,马上处理",
msg_type=0,
)
# 3. 启动处理
await self.trigger_processing_on_payment(customer_id, acc_id, acc_type)
print(f"[Workflow] 处理图片已启动 | 客户:{customer_id}")
return True
except Exception as e:
logger.error(f"处理图片工作流失败:{e}")
return False
async def transfer_to_designer_workflow(self, customer_id: str, image_url: str,
acc_id: str = "", acc_type: str = "AliWorkbench",
reason: str = "做不了") -> bool:
"""
工作流 3转人工派单
做不了 → 查询企业微信在线设计师 → 派单
Args:
customer_id: 客户 ID
image_url: 图片 URL
acc_id: 店铺 ID
acc_type: 平台类型
reason: 转接原因
Returns:
bool: 是否成功
"""
try:
print(f"[Workflow] 启动转人工派单工作流 | 客户:{customer_id} | 原因:{reason}")
# 1. 创建任务
task_id = self.create_image_task(
customer_id=customer_id,
customer_name=customer_id,
original_image=image_url,
operation="manual",
requirements=f"type:transfer|reason:{reason}",
acc_id=acc_id,
acc_type=acc_type
)
# 2. 查询企业微信在线设计师
online_designers = await self._get_online_designers()
if not online_designers:
# 无人在线,通知客户
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=acc_id,
acc_type=acc_type,
content="抱歉,现在设计师都不在线,稍后会有人联系您",
msg_type=0,
)
# 企业微信预警
await _wechat_notify(
f"⚠️ **人工派单但无人在线**\n"
f"客户:{customer_id}\n"
f"店铺:{acc_id}\n"
f"原因:{reason}\n"
f"请安排设计师上线"
)
print(f"[Workflow] 无人在线 | 客户:{customer_id}")
return False
# 3. 派单给在线设计师
designer_name = online_designers[0] # 取第一个在线的
success = await self._dispatch_to_designer(task_id, designer_name, customer_id, image_url, reason)
if not success:
logger.error("派单失败")
return False
# 4. 回复客户
if self._send_message:
await self._send_message(
customer_id=customer_id,
acc_id=acc_id,
acc_type=acc_type,
content="好的,已帮您安排设计师处理,请稍候",
msg_type=0,
)
print(f"[Workflow] 已派单给设计师:{designer} | 客户:{customer_id}")
return True
except Exception as e:
logger.error(f"转人工派单工作流失败:{e}")
return False
async def _get_online_designers(self) -> list:
"""
查询在线设计师(使用图绘派单 API
Returns:
list: 在线设计师名单 ["橘子", "婷婷", ...]
"""
try:
designers = await self.dispatch_client.get_online_designers()
print(f"[Workflow] 查询在线设计师:{len(designers)}人在线 | {designers}")
return designers
except Exception as e:
logger.error(f"查询在线设计师失败:{e}")
return []
async def _dispatch_to_designer(self, task_id: str, designer_name: str,
customer_id: str, image_url: str, reason: str) -> bool:
"""
派单给设计师(使用图绘派单 API
Args:
task_id: 任务 ID
designer_name: 设计师姓名
customer_id: 客户 ID
image_url: 图片 URL
reason: 转接原因
Returns:
bool: 是否成功
"""
try:
# 1. 在派单系统创建任务
dispatch_task_id = await self.dispatch_client.create_task(
task_name=f"图片处理-{customer_id[-4:]}",
description=f"{reason}\n客户:{customer_id}\n图片:{image_url}",
task_type="image_process",
priority=2,
deadline=None
)
if not dispatch_task_id:
logger.error("创建派单任务失败")
return False
# 2. 分配给设计师
success = await self.dispatch_client.assign_task(
task_id=dispatch_task_id,
designer_name=designer_name,
notes=f"AI 客服自动派单\n原因:{reason}\n客户:{customer_id}"
)
if success:
print(f"[Workflow] 派单成功:{dispatch_task_id}{designer_name} | 客户:{customer_id}")
# 企业微信通知
await _wechat_notify(
f"📋 **新任务派单**\n"
f"设计师:{designer_name}\n"
f"任务 ID: {dispatch_task_id}\n"
f"客户:{customer_id}\n"
f"原因:{reason}\n"
f"请及时处理"
)
return True
else:
logger.error("分配任务失败")
return False
except Exception as e:
logger.error(f"派单失败:{e}")
return False