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

117
core/pydantic_ai_agent.py Normal file → Executable file
View File

@@ -18,6 +18,7 @@ from dotenv import load_dotenv
load_dotenv()
from services.service_tuhui_upload import upload_to_tuhui
# ========== 企业微信通知 ==========
_WECHAT_WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=cc88bdef-a13f-4d7e-bdb6-ee51b68b8205"
@@ -198,7 +199,10 @@ class CustomerServiceAgent:
deps_type=AgentDeps,
system_prompt=self._get_similar_prompt()
)
self.agent_order = Agent(
# 工作流程路由器
self.workflow_router = get_workflow_router()
self.agent_order = Agent(
model=model,
deps_type=AgentDeps,
system_prompt=self._get_order_prompt()
@@ -215,6 +219,7 @@ class CustomerServiceAgent:
def _register_tools(self):
"""注册所有 Tool让 Agent 可以主动调用"""
@self.agent.tool
async def analyze_image(ctx: RunContext[AgentDeps], image_url: str) -> str:
"""
@@ -255,6 +260,7 @@ class CustomerServiceAgent:
# 在 workflow 里创建待处理任务(付款后自动触发 Gemini
try:
from core.workflow import workflow
from core.workflow_router import get_workflow_router
await workflow.image_analysis_result(
customer_id=ctx.deps.from_id,
image_url=image_url,
@@ -322,12 +328,30 @@ class CustomerServiceAgent:
lines.append(f"→ 报价时自然加一句风险提示(人脸可能有轻微变化、满意再付等)")
else:
# 无风险,正常报价
lines.append(f"建议报价:{result['price_suggest']}元(区间 {result['price_min']}-{result['price_max']}元)")
base_price = result.get('price_suggest', 20)
text_surcharge = result.get('text_surcharge', 0)
layer_surcharge = result.get('layer_surcharge', 0)
total_price = base_price + text_surcharge + layer_surcharge
# 构建报价说明
price_explanation = f"建议报价:{total_price}"
if text_surcharge > 0:
price_explanation += f"(含文字处理 +{text_surcharge}元)"
if layer_surcharge > 0:
price_explanation += f"(含分层 +{layer_surcharge}元)"
lines.append(price_explanation)
# 添加文字数量说明
text_amount = result.get('text_amount', 'none')
if text_amount != 'none':
lines.append(f"文字数量:{text_amount},需要精细处理")
if feasibility == "partial":
lines.append(f"⚠️ 此图有一定难度:{note or '效果可能不完美'},回复时可加「效果不满意退款」")
if note and note not in ("", ""):
lines.append(f"提示:{note}")
lines.append(f"【立刻回复客户报价 {result['price_suggest']} 元,话术自然多变】")
lines.append(f"【立刻回复客户报价 {total_price} 元,话术自然多变】")
return "\n".join(lines)
except Exception as e:
@@ -445,6 +469,7 @@ class CustomerServiceAgent:
cid = customer_id or ctx.deps.from_id
try:
from core.workflow import workflow
from core.workflow_router import get_workflow_router
ok = await workflow.trigger_processing_on_payment(
customer_id=cid,
acc_id=ctx.deps.acc_id,
@@ -502,6 +527,7 @@ class CustomerServiceAgent:
cid = customer_id or ctx.deps.from_id
try:
from core.workflow import workflow
from core.workflow_router import get_workflow_router
ok = await workflow.trigger_processing_on_payment(
customer_id=cid,
acc_id=ctx.deps.acc_id,
@@ -861,6 +887,13 @@ class CustomerServiceAgent:
- analyze_image 工具调用完成后,你的下一句话一定是报价,不能是内部说明
- 报价后立刻推成交,不等客户反应
【文字加价规则】⚠️ 重要
- 含文字很多时不能低价,有文字跟没文字是两个价格
- 含文字的图必须 complex 起步20 元以上)
- 客户嫌贵时明确告知:「有文字跟没文字是两个价格」
- 简单图但含文字 → normal 价格15-20 元)
- normal 图含文字 → complex 价格20-25 元)
【压价规则】
- 客户说「贵」「有点贵」「算了」「便宜点」→ 直接让价一次,禁止追问「什么问题」「说清楚点」
- 只让价一次,话术自然变化
@@ -870,6 +903,19 @@ class CustomerServiceAgent:
- 退款/退货/投诉/情绪激动/test → 调用 transfer_to_human()
- 调用后只回复"转接",不加其他内容
【找茬客户识别】⚠️ 重要
识别以下高风险信号,建议不做这单:
1. 下单后立即申请退款
2. 从高价砍到低价30→10 元)
3. 反复问"不满意可以退吗"2 次以上)
4. 质疑服务内容("源文件还是什么"
5. 质疑价值("就一张图片"
6. 问"小一点就快一点的嘛"(想占便宜)
7. 重复问同一个问题(想找麻烦)
识别到以上 3 个以上信号 → 建议转人工或直接拒绝接单
话术:「不好意思,这单做不了」「去别家做吧」
【售后规则】
- 催进度:自然回复在做了/快了/马上好之类
- 要修改:自然问哪里要改
@@ -1157,6 +1203,7 @@ class CustomerServiceAgent:
# 已付款:触发 Gemini 作图
try:
from core.workflow import workflow
from core.workflow_router import get_workflow_router
asyncio.create_task(workflow.trigger_processing_on_payment(
customer_id=message.from_id,
acc_id=message.acc_id,
@@ -1742,7 +1789,7 @@ class CustomerServiceAgent:
prompt += "\n客户催单,查询当前处理状态后自然回复。"
elif any(kw in customer_text for kw in ["", "有点贵", "太贵", "算了", "便宜点", "少点", "打折", "贵哦"]):
# 客户嫌贵/要放弃 → 直接让价一次,不问「什么问题」
prompt += "\n【客户嫌贵】客户已表达价格顾虑或要放弃。禁止追问「什么问题」「说清楚点」。直接让价一次如原价20→15话术自然,像真人聊天,只让一次。"
prompt += "\n⚠️【客户嫌贵】客户已表达价格顾虑或要放弃。禁止追问「什么问题」「说清楚点」。\n→ 第一步:直接让价一次(如原价 20→15话术自然\n→ 第二步:如果让价后客户还是嫌贵,引导客户自己去注册星绘平台:\n - 每个话术都必须带网址 xinhui.cloud\n - 强调「自己去弄」「自己操作」「自己下单」\n - 示例:「嫌贵就去 xinhui.cloud 注册个号自己有余额可以弄」「xinhui.cloud 去注册下,新用户送体验金,自己弄便宜」\n - 语气直接,让客户自己去操作」"
elif any(kw in customer_text for kw in ["擦边", "黄色", "色情", "大尺度", "性感图", "露点", "半裸"]):
# 客户问擦边/黄色内容 → 直接拒绝,不说「发图来看看」
prompt += "\n⚠️【拒绝】客户询问擦边/黄色/敏感内容。直接拒绝,不接单,不说「发图来看看」。自然回复如:这类不做/不接/做不了。"
@@ -1795,3 +1842,65 @@ async def test_agent():
if __name__ == "__main__":
import asyncio
asyncio.run(test_agent())
async def _handle_image_workflow(self, message: str, data: dict, image_urls: list) -> bool:
"""
处理图片工作流(根据客户说的话判断执行哪种工作流)
Args:
message: 客户消息
data: 消息数据
image_urls: 图片 URL 列表
Returns:
bool: 是否已处理
"""
if not image_urls:
return False
# 检测工作流类型
workflow_type, confidence = self.workflow_router.detect_workflow(message)
customer_id = data.get('from_id')
acc_id = data.get('acc_id', '')
acc_type = data.get('acc_type', 'AliWorkbench')
image_url = image_urls[0] # 取第一张图
print(f"[Agent] 检测到工作流类型:{workflow_type} (置信度:{confidence})")
if workflow_type == "find_image":
# 工作流 1查找图片
print(f"[Agent] 执行查找图片工作流 | 客户:{customer_id}")
success = await workflow.find_image_workflow(
customer_id=customer_id,
image_url=image_url,
acc_id=acc_id,
acc_type=acc_type
)
return success
elif workflow_type == "process_image":
# 工作流 2处理图片
print(f"[Agent] 执行处理图片工作流 | 客户:{customer_id}")
success = await workflow.process_image_workflow(
customer_id=customer_id,
image_url=image_url,
acc_id=acc_id,
acc_type=acc_type
)
return success
elif workflow_type == "transfer_human":
# 工作流 3转人工派单
print(f"[Agent] 执行转人工派单工作流 | 客户:{customer_id}")
success = await workflow.transfer_to_designer_workflow(
customer_id=customer_id,
image_url=image_url,
acc_id=acc_id,
acc_type=acc_type,
reason="客户主动要求转人工"
)
return success
# 未知工作流,不处理
return False