一、为什么采购和销售需要"自动谈判"?
一个典型的企业场景:销售Agent接到客户订单,需要向采购Agent申请原材料。销售想压低成本以保证利润,采购想保证质量和交期。双方目标冲突,但必须达成一致------否则订单无法履约。
传统做法是:销售发邮件给采购,采购报价,销售还价,来回几轮,耗时数小时到数天。如果涉及多个供应商、多个物料,谈判组合爆炸。
自动谈判要解决的,是让两个AI Agent在秒级内完成多轮博弈,找到一个双方都能接受的均衡点。
这不是简单的"讨价还价"。它涉及三个工程问题:
- 效用函数建模:采购和销售各自"想要什么",必须可量化
- 博弈策略选择:每一轮该出什么价,取决于对方的策略和历史行为
- 失控熔断:谈判陷入僵局或一方越界时,如何止损
二、整体架构:三层博弈系统
┌─────────────────────────────────────────────────────────────────┐
│ 谈判任务发起层 │
│ 销售Agent:需要采购1000个连接器,目标单价≤1.2元,交期≤7天 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 博弈协商层(核心) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 效用函数 │ │ 策略选择 │ │ 均衡求解 │ │
│ │ 双方偏好量化 │ │ 出价/还价 │ │ 纳什均衡搜索 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 迁移学习模块(历史谈判经验复用) │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 熔断层(安全兜底) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 轮次超限 │ │ 偏离红线 │ │ 人工接管 │ │
│ │ 僵局检测 │ │ 权限越界 │ │ 升级审批 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 成交/升级决策层 │
│ 成交:生成采购订单 / 升级:转人工谈判 / 终止:放弃交易 │
└─────────────────────────────────────────────────────────────────┘
三层各司其职:博弈层"谈",迁移层"学",熔断层"兜"。
三、效用函数:把"想要什么"变成可计算的数
3.1 采购Agent的效用函数
采购的目标不是"价格最低",而是"综合成本最优"。价格、交期、质量、付款条件,都是变量。
python
from dataclasses import dataclass
@dataclass
class PurchasePreference:
"""采购Agent的偏好参数"""
price_weight: float = 0.5 # 价格权重
delivery_weight: float = 0.3 # 交期权重
quality_weight: float = 0.2 # 质量权重
max_price: float = 1.5 # 可接受最高单价
target_price: float = 1.0 # 理想单价
max_lead_time: int = 14 # 可接受最长交期(天)
target_lead_time: int = 7 # 理想交期
quality_threshold: float = 0.9 # 最低质量合格率
class PurchaseUtility:
"""采购效用函数:综合成本越低,效用越高"""
def __init__(self, pref: PurchasePreference):
self.pref = pref
def compute(self, offer: dict) -> float:
"""计算某个报价方案的效用(0-1)"""
# 价格效用:越接近目标价越高
price_score = self._normalize(
offer["price"],
self.pref.target_price,
self.pref.max_price,
reverse=True # 价格越低越好
)
# 交期效用:越短越好
delivery_score = self._normalize(
offer["lead_time"],
self.pref.target_lead_time,
self.pref.max_lead_time,
reverse=True
)
# 质量效用:高于阈值即可,边际递减
quality_score = min(1.0, offer["quality"] / self.pref.quality_threshold)
# 硬约束:低于质量阈值直接判负
if offer["quality"] < self.pref.quality_threshold:
return 0.0
# 加权综合
return (
self.pref.price_weight * price_score +
self.pref.delivery_weight * delivery_score +
self.pref.quality_weight * quality_score
)
def _normalize(self, value, target, limit, reverse=False):
if reverse:
if value <= target:
return 1.0
if value >= limit:
return 0.0
return 1 - (value - target) / (limit - target)
else:
return min(1.0, value / target)
3.2 销售Agent的效用函数
销售的效用逻辑与采购相反:价格越高越好,交期越宽松越好。但销售有"成交底线"------低于成本价不卖。
python
@dataclass
class SalesPreference:
"""销售Agent的偏好参数"""
price_weight: float = 0.6
delivery_weight: float = 0.2
volume_weight: float = 0.2 # 订单量权重
cost_price: float = 0.8 # 成本价(低于此不卖)
target_price: float = 1.3 # 理想售价
max_discount: float = 0.15 # 最大折扣率
class SalesUtility:
"""销售效用函数:利润越高,效用越高"""
def __init__(self, pref: SalesPreference):
self.pref = pref
def compute(self, offer: dict) -> float:
# 硬约束:低于成本价直接拒绝
if offer["price"] < self.pref.cost_price:
return 0.0
# 利润效用
profit_margin = (offer["price"] - self.pref.cost_price) / self.pref.cost_price
profit_score = min(1.0, profit_margin / 0.5) # 50%毛利为满分
# 交期效用:交期越宽松,履约压力越小
delivery_score = min(1.0, offer["lead_time"] / 14)
# 订单量效用
volume_score = min(1.0, offer["quantity"] / 1000)
return (
self.pref.price_weight * profit_score +
self.pref.delivery_weight * delivery_score +
self.pref.volume_weight * volume_score
)
四、博弈策略:每一轮该出什么价
4.1 谈判模型:交替出价博弈
采购和销售交替出价,每轮一方提出方案,另一方接受或还价。这是一个经典的鲁宾斯坦议价博弈(Rubinstein Bargaining Game) 的变体。
python
@dataclass
class Offer:
"""报价方案"""
price: float
lead_time: int
quantity: int
quality: float
round_num: int
proposer: str # "purchase" | "sales"
class NegotiationGame:
"""谈判博弈引擎:交替出价,寻找均衡"""
def __init__(self, purchase_agent, sales_agent,
max_rounds=10, discount_factor=0.95):
self.purchase = purchase_agent
self.sales = sales_agent
self.max_rounds = max_rounds
self.discount = discount_factor # 时间成本:轮次越多,效用打折
def negotiate(self, initial_demand: dict) -> dict:
"""执行谈判"""
history = []
current_offer = None
for round_num in range(1, self.max_rounds + 1):
# 采购出价(奇数轮)
if round_num % 2 == 1:
current_offer = self.purchase.propose(history, round_num)
# 销售评估是否接受
if self.sales.accept(current_offer):
return self._deal(current_offer, round_num, history)
else:
# 销售还价(偶数轮)
current_offer = self.sales.propose(history, round_num)
if self.purchase.accept(current_offer):
return self._deal(current_offer, round_num, history)
history.append(current_offer)
# 轮次耗尽,未达成一致
return self._no_deal(history)
4.2 策略选择:让步策略与底线守卫
每一轮出价的策略,决定了谈判的效率和结果。常见的策略有三类:
线性让步:每轮让步固定比例。简单但容易被对方"摸到底"。
基于对方历史的让步:如果对方连续强硬,己方也强硬;对方让步,己方也让步。这是"针锋相对"策略。
基于时间压力的让步:越接近截止时间,让步幅度越大。适用于有明确交期要求的场景。
python
class ConcessionStrategy:
"""让步策略:基于对方历史行为的动态调整"""
def __init__(self, base_concession=0.05, time_pressure=0.02):
self.base = base_concession
self.time_pressure = time_pressure
def compute_concession(self, history: list,
current_round: int, max_rounds: int,
opponent_behavior: str) -> float:
"""
计算本轮让步幅度
opponent_behavior: "hard" | "soft" | "neutral"
"""
# 基础让步
concession = self.base
# 时间压力:越接近截止,让步越大
time_ratio = current_round / max_rounds
concession += self.time_pressure * time_ratio
# 对手行为调整
if opponent_behavior == "hard":
# 对手强硬,己方收敛让步
concession *= 0.5
elif opponent_behavior == "soft":
# 对手让步,己方也适度让步
concession *= 1.2
# 但永远不超过最大让步幅度
return min(concession, 0.15)
def detect_opponent_behavior(self, history: list) -> str:
"""检测对手行为模式"""
if len(history) < 3:
return "neutral"
# 计算对手最近三轮的让步幅度
recent = history[-3:]
concessions = []
for i in range(1, len(recent)):
if recent[i].proposer != recent[i-1].proposer:
# 同一方连续出价,计算让步
delta = abs(recent[i].price - recent[i-1].price)
concessions.append(delta)
if not concessions:
return "neutral"
avg_concession = sum(concessions) / len(concessions)
if avg_concession < 0.02:
return "hard" # 几乎不让步
elif avg_concession > 0.08:
return "soft" # 让步较大
return "neutral"
五、迁移学习:让谈判策略"举一反三"
5.1 为什么需要迁移学习
一个新品类(比如从"连接器"谈判切换到"芯片"谈判)的谈判,不需要从零开始学习。谈判的底层逻辑是通用的------让步节奏、底线守卫、僵局识别------这些策略可以迁移。需要重新学习的是"业务特定参数":芯片的成本结构、市场行情、供应商议价能力。
5.2 迁移学习实现
python
class TransferNegotiationPolicy:
"""迁移学习谈判策略:共享底层逻辑,微调业务参数"""
def __init__(self, base_policy, task_specific_head):
self.base = base_policy # 预训练的谈判逻辑(冻结)
self.head = task_specific_head # 业务特定的参数预测(可训练)
def propose(self, history: list, round_num: int,
market_context: dict) -> Offer:
"""生成报价方案"""
# 1. 底层逻辑:从历史中提取谈判特征
features = self.base.encode(history, round_num)
# 2. 业务特定:根据市场上下文调整
business_params = self.head.predict(market_context)
# 3. 综合生成报价
return self._build_offer(features, business_params)
def transfer_to_new_category(self, new_category_data: list,
freeze_base=True):
"""迁移到新品类"""
if freeze_base:
for param in self.base.parameters():
param.requires_grad = False
# 用少量新品类数据微调决策头
for batch in new_category_data:
loss = self._compute_loss(batch)
loss.backward()
optimizer.step()
5.3 迁移的边界
能迁移的:让步节奏、底线守卫逻辑、僵局识别、对手行为分类。
不能迁移的:成本价、市场行情、供应商等级、物料紧缺程度。这些必须针对新品类重新配置。
六、熔断:谈判失控时的安全阀
自动谈判最大的风险不是"谈不成",而是"谈成了不该谈的"------比如销售Agent为了成交,答应了低于成本价的价格;或者采购Agent为了压价,接受了无法满足的交期。
python
class NegotiationCircuitBreaker:
"""谈判熔断器:防止谈判失控"""
def __init__(self, price_floor: float, lead_time_ceiling: int,
max_rounds: int = 10):
self.price_floor = price_floor # 价格底线
self.lead_time_ceiling = lead_time_ceiling # 交期上限
self.max_rounds = max_rounds
self.failure_count = 0
self.state = "closed"
def check_offer(self, offer: Offer, side: str) -> dict:
"""检查报价是否触发熔断"""
if self.state == "open":
return {"action": "abort", "reason": "circuit_open"}
# 1. 价格底线检查
if side == "sales" and offer.price < self.price_floor:
self.failure_count += 1
return {
"action": "reject",
"reason": "below_cost_price",
"floor": self.price_floor
}
# 2. 交期上限检查
if offer.lead_time > self.lead_time_ceiling:
self.failure_count += 1
return {
"action": "reject",
"reason": "lead_time_exceeded",
"ceiling": self.lead_time_ceiling
}
# 3. 连续违规触发熔断
if self.failure_count >= 3:
self.state = "open"
return {
"action": "escalate",
"reason": "repeated_violations",
"message": "谈判连续触碰底线,转人工处理"
}
return {"action": "pass"}
def check_round(self, round_num: int) -> dict:
"""检查轮次是否超限"""
if round_num > self.max_rounds:
return {
"action": "escalate",
"reason": "max_rounds_exceeded",
"message": "谈判轮次超限,转人工决策"
}
return {"action": "continue"}
熔断触发后,谈判暂停,生成一份"谈判摘要"推送给人工------包括双方出价历史、分歧点、建议方案。人工决定是继续谈、换条件、还是放弃。
七、完整谈判流程伪代码
python
async def auto_negotiate(purchase_agent, sales_agent,
initial_demand, config):
"""完整的自动谈判流程"""
# 初始化
game = NegotiationGame(purchase_agent, sales_agent,
max_rounds=config.max_rounds)
breaker = NegotiationCircuitBreaker(
price_floor=config.cost_price * 1.05, # 成本价上浮5%为底线
lead_time_ceiling=config.max_lead_time,
max_rounds=config.max_rounds
)
history = []
for round_num in range(1, config.max_rounds + 1):
# 轮次检查
round_check = breaker.check_round(round_num)
if round_check["action"] == "escalate":
return await escalate_to_human(history, round_check)
# 当前出价方
proposer = purchase_agent if round_num % 2 == 1 else sales_agent
side = "purchase" if round_num % 2 == 1 else "sales"
# 生成报价
offer = proposer.propose(history, round_num)
# 熔断检查
breaker_check = breaker.check_offer(offer, side)
if breaker_check["action"] in ("reject", "escalate"):
if breaker_check["action"] == "escalate":
return await escalate_to_human(history, breaker_check)
continue # 拒绝该报价,对方重新出价
# 对方评估是否接受
opponent = sales_agent if side == "purchase" else purchase_agent
if opponent.accept(offer):
# 达成一致
return {
"status": "deal",
"offer": offer,
"rounds": round_num,
"history": history
}
history.append(offer)
# 轮次耗尽
return await escalate_to_human(history, {"reason": "no_deal"})
八、工程实践要点
效用函数要"硬约束+软偏好"分层。 低于成本价、低于质量阈值是硬约束,一票否决;价格、交期是软偏好,可以权衡。
让步策略要"看对手"。 对方强硬时收敛让步,对方让步时适度跟进。固定让步策略容易被对手"摸到底"。
迁移学习只迁"逻辑",不迁"参数"。 让步节奏可以跨品类迁移,成本价和市场行情必须重新配置。
熔断器要检查"谈成了什么",而不只是"谈没谈成"。 一个低于成本价的成交,比没谈成更危险。
审计覆盖全链路。 每一轮出价、每一次熔断、每一次转人工,都需要记录。出了问题能追溯"哪一轮、谁、为什么"。
在行业实践中,沈管家AI数字员工的任务执行引擎采用DAG编排和状态持久化,支持条件分支和人工审批节点。当谈判触发熔断时,任务暂停并推送审批请求,由授权人员确认后继续执行或终止------这种"AI谈判、人兜底"的设计,为多Agent博弈提供了安全的执行环境。
FAQ
Q1:自动谈判和人工谈判,哪个效果更好?
A:取决于场景。规则明确、标的标准化(如标准件采购)的场景,自动谈判更快、更一致。涉及长期合作关系、非标条款、复杂商务背景的场景,人工谈判仍有优势。实践中常用"AI谈标准条款,人谈关键分歧"的混合模式。
Q2:如果两个Agent都"不让步",谈判会不会永远僵住?
A:不会。熔断器设了最大轮次限制。轮次耗尽后自动升级人工。同时,让步策略中的"时间压力"机制会让双方在接近截止时自动加大让步幅度。
Q3:迁移学习需要多少历史谈判数据?
A:底层逻辑(让步节奏、对手行为分类)通常需要数百条历史谈判记录。业务特定参数(成本价、行情)不需要训练数据,直接配置即可。
Q4:熔断触发后,人工怎么接手?
A:系统生成"谈判摘要",包括双方出价历史、当前分歧点、AI的建议方案。人工在此基础上做决策:接受某个方案、修改条件重新谈、或放弃交易。
Q5:中小企业需要多Agent自动谈判吗?
A:如果采购和销售的协作频繁、标的标准化,可以试点。建议从一个品类、一个供应商开始,跑通后再扩展。沈管家AI数字员工的多组织架构和任务引擎可以作为基础平台。
你在实际业务中遇到过"采购和销售谈不拢"的场景吗?是价格分歧、交期冲突,还是责任划分不清?欢迎在评论区聊聊你的经历。如果你正在探索多Agent协同方案,也可以留言说说你的场景和困惑。