172 lines
5.9 KiB
Python
172 lines
5.9 KiB
Python
from __future__ import annotations
|
||
|
||
import logging
|
||
import re
|
||
from typing import Any
|
||
|
||
from utils.metrics_tracker import emit as metrics_emit
|
||
|
||
CASE_LIBRARY_LINK = "https://www.yuque.com/zuowei-dfvpq/kge0in/mynala0g35b8cec5"
|
||
logger = logging.getLogger("cs_agent")
|
||
|
||
|
||
def detect_price(reply: str, state: Any) -> None:
|
||
numbers = re.findall(r"(\d+)[元]", reply or "")
|
||
if not numbers:
|
||
return
|
||
price = round(int(numbers[0]) / 5) * 5
|
||
state.last_price = price
|
||
metrics_emit("quote_generated", customer_id=state.customer_id, price=price)
|
||
try:
|
||
from db.customer_db import db
|
||
|
||
db.update_last_price(state.customer_id, price)
|
||
except Exception:
|
||
pass
|
||
|
||
|
||
def detect_discount(message: str, state: Any) -> None:
|
||
text = message or ""
|
||
if any(kw in text for kw in ["贵", "便宜", "太贵", "有点贵"]):
|
||
state.discount_count += 1
|
||
if state.last_price:
|
||
try:
|
||
from db.customer_db import db
|
||
|
||
db.record_discount(state.customer_id, state.last_price)
|
||
except Exception:
|
||
pass
|
||
m = re.search(r"(\d+)\s*元|\b(\d+)\s*块", text)
|
||
offer = None
|
||
if m:
|
||
offer = int(m.group(1) or m.group(2))
|
||
if offer:
|
||
try:
|
||
from config.config import MIN_PRICE_FLOOR
|
||
|
||
if offer < MIN_PRICE_FLOOR:
|
||
state.last_price = state.last_price or 0
|
||
except Exception:
|
||
pass
|
||
|
||
|
||
def negotiation_strategy_reply(customer_text: str, state: Any) -> str:
|
||
text = (customer_text or "").strip()
|
||
if not text:
|
||
return ""
|
||
if any(k in text for k in ["先发效果图", "先看效果", "不放心", "没法确认"]):
|
||
return (
|
||
f"小妹整理了一些案例图,亲点这个链接就能看到啦({CASE_LIBRARY_LINK})。"
|
||
"有什么想要的效果随时告诉我哈,不满意我们这边包退。"
|
||
)
|
||
if "有点贵" in text or "就是贵" in text:
|
||
base = state.last_price if isinstance(state.last_price, int) and state.last_price > 0 else 25
|
||
two_pack = max(10, round(((base * 2) - 5) / 5) * 5)
|
||
return f"理解你这边的预算,我给你个实在点的:两张一起按 {two_pack} 元做,行不行?"
|
||
if any(k in text for k in ["优惠点", "便宜点", "少点", "打折"]):
|
||
return "可以的,你这边数量上来我就好给价,3张以上我给你打包价。"
|
||
return ""
|
||
|
||
|
||
async def record_deal_success(
|
||
*,
|
||
customer_id: str,
|
||
customer_name: str,
|
||
acc_id: str,
|
||
platform: str,
|
||
order: dict,
|
||
state: Any,
|
||
) -> None:
|
||
try:
|
||
from db.deal_outcome_db import record_deal
|
||
|
||
order_id = order.get("order_id", "")
|
||
raw_amount = order.get("amount", "")
|
||
m = re.search(r"[\d.]+", str(raw_amount))
|
||
amount = float(m.group()) if m else 0
|
||
reason = "让价后成交" if (state.discount_count or 0) > 0 else "直接成交"
|
||
record_deal(
|
||
customer_id=customer_id,
|
||
outcome="成交",
|
||
reason=reason,
|
||
customer_name=customer_name or "",
|
||
acc_id=acc_id or "",
|
||
platform=platform or "",
|
||
order_id=order_id,
|
||
amount=amount,
|
||
discount_given=(state.discount_count or 0) > 0,
|
||
)
|
||
try:
|
||
from db.customer_db import db
|
||
|
||
if order_id:
|
||
db.add_order(customer_id, order_id, amount)
|
||
db.clear_quote_no_convert(customer_id)
|
||
except Exception:
|
||
pass
|
||
logger.info("[Agent] 成交记录: %s %s %s元", customer_id, reason, amount)
|
||
except Exception as e:
|
||
logger.exception("[Agent] 成交记录失败: %s", e)
|
||
|
||
|
||
async def record_deal_fail(
|
||
*,
|
||
customer_id: str,
|
||
customer_name: str,
|
||
acc_id: str,
|
||
platform: str,
|
||
reason: str,
|
||
) -> None:
|
||
try:
|
||
from db.deal_outcome_db import record_deal
|
||
from db.customer_db import db
|
||
|
||
record_deal(
|
||
customer_id=customer_id,
|
||
outcome="未成交",
|
||
reason=reason,
|
||
customer_name=customer_name or "",
|
||
acc_id=acc_id or "",
|
||
platform=platform or "",
|
||
)
|
||
db.mark_quote_no_convert(customer_id)
|
||
logger.info("[Agent] 未成交记录: %s %s", customer_id, reason)
|
||
except Exception as e:
|
||
logger.exception("[Agent] 未成交记录失败: %s", e)
|
||
|
||
|
||
async def auto_tag(message: Any, state: Any) -> None:
|
||
try:
|
||
from db.customer_db import db
|
||
|
||
cid = message.from_id
|
||
msg = (message.msg or "").lower()
|
||
if any(kw in msg for kw in ["还有", "多张", "好几张", "一批", "下次还"]):
|
||
db.set_bulk_potential(cid, "有")
|
||
db.add_upsell_opportunity(cid, "批量打包")
|
||
if any(kw in msg for kw in ["psd", "分层", "源文件"]):
|
||
db.add_upsell_opportunity(cid, "分层PSD")
|
||
db.update_preferred_format(cid, "psd")
|
||
if "jpg" in msg or "jpeg" in msg:
|
||
db.update_preferred_format(cid, "jpg")
|
||
if "png" in msg:
|
||
db.update_preferred_format(cid, "png")
|
||
if any(kw in msg for kw in ["分辨率", "dpi", "尺寸", "大图", "印刷"]):
|
||
db.update_preferred_size(cid, message.msg[:30])
|
||
if any(kw in msg for kw in ["拍了", "下单了", "好的", "行"]) and state.last_price:
|
||
db.update_decision_speed(cid, "快")
|
||
type_keywords = {
|
||
"印花": ["印花", "花纹", "图案", "面料", "布料", "纺织"],
|
||
"logo": ["logo", "标志", "品牌", "商标"],
|
||
"人物": ["人物", "人像", "照片", "脸", "头像"],
|
||
"产品": ["产品", "商品", "包装", "实物"],
|
||
"老照片": ["老照片", "旧照片", "发黄", "修复"],
|
||
}
|
||
for img_type, keywords in type_keywords.items():
|
||
if any(kw in message.msg for kw in keywords):
|
||
db.add_image_type(cid, img_type)
|
||
break
|
||
db.auto_compute_tags(cid)
|
||
except Exception:
|
||
pass
|