Agent角色扮演实战:我做了个7x24小时的客服Agent
Agent角色扮演实战:我做了个7x24小时的客服Agent
说实话,之前我一直觉得让Agent"扮演"某个角色是个锦上添花的功能——不就是改个system prompt吗?
直到上周我接手了一个客服系统的需求,才发现角色扮演远不止改prompt那么简单。
为什么需要角色扮演
先说说场景。
我们有个电商SaaS平台,商家想要一个7x24小时的AI客服。这不是普通的问答——每个商家有自己的产品目录、售后政策、促销规则,而且语气风格还要跟品牌一致。
有的是搞怪潮牌,客服要跟用户打成一片;有的是高端美妆,客服要专业优雅。
同一个LLM,要同时扮演N种不同性格的角色。
角色设计:不只是改system prompt
很多人觉得角色扮演 = 写个System Prompt就完事了。
我一开始也这么想。
你是一个资深客服...
结果呢?聊两句就崩了。该专业的变啰嗦,该亲和的变敷衍。
角色金字塔
搞了三个版本后,我总结出一个方法:角色金字塔。
第一层:身份设定
- 你是谁?什么岗位?什么性格?
- 语气要专业还是随和?
- 回复长度偏好?
第二层:行为规则
- 遇到投诉怎么办?
- 超出权限如何升级?
- 促销信息怎么引导?
第三层:领域知识
- 商品SKU库
- 售后政策条款
- 最近活动规则
每一层单独定义,然后按优先级合并。
实际代码
这是我的角色配置结构:
@dataclass
class AgentPersona:
name: str
brand_voice: str # 品牌语调
tone: str # "professional" | "casual" | "friendly"
response_style: str # 回复风格偏好
max_response_tokens: int # 回复长度限制
def build_system_prompt(self, product_catalog, policy_rules):
return f"""
你叫{self.name},是XX品牌的客服。
性格特点:{self.tone}
回复风格:{self.response_style}
【行为准则】
1. 用户问商品 → 先查产品目录再回答
2. 遇到投诉 → 表示理解 + 给出解决方案
3. 超过权限 → 转接人工客服
【产品信息】
{format_catalog(product_catalog)}
【售后政策】
{format_policy(policy_rules)}
"""
动态知识注入
这里有个坑:商家每天都在更新产品和活动。你不可能每次更新都重新微调。
我的做法是动态RAG注入。
每次用户提问时,先通过向量检索找到相关的商品信息和当前促销活动,拼接到prompt中。
async def handle_user_query(query: str, persona: AgentPersona):
# 1. 检索相关知识
products = await vector_search(query, index="products", top_k=3)
policies = await vector_search(query, index="policies", top_k=2)
promos = await vector_search(query, index="promotions", top_k=2)
# 2. 构建带角色的prompt
system_msg = persona.build_system_prompt()
context = f"相关商品:{products}\n售后政策:{policies}\n当前活动:{promos}"
# 3. 调用LLM
response = await llm.chat([
{"role": "system", "content": system_msg},
{"role": "user", "content": f"上下文:{context}\n用户提问:{query}"}
])
return response
这个方案有一个好处:不需要微调,换角色就换一套persona配置,商家自己都能配。
情绪管理:最难的地方
客服场景里,用户有时候就是来发泄的。Agent怎么应对情绪化对话,我踩了不少坑。
一开始的版本,遇到用户骂人,Agent会一本正经地说:“请不要使用不文明语言。”
结果用户更怒了。
后来我加了个情绪标签系统:
用户情绪识别:
- anger → 先共情,再解决问题
- frustration → 快速给方案
- confusion → 拆解问题,一步步引导
- neutral → 直接回答问题
EMOTION_PROMPTS = {
"anger": "先表达理解,不要解释或反驳:'{user_name},我很理解您的心情...'",
"frustration": "直接给出明确方案:'这个情况我们需要这样处理...'",
"confusion": "拆解问题:'我帮您梳理一下,主要有这几个方面...'",
"neutral": "直接回答用户问题,简洁清晰。"
}
这一改,用户满意度直接从72%干到了89%。
多角色切换的工程挑战
最坑的一个场景:一个用户同时问售前和售后问题。
Agent需要同时扮演"销售顾问"和"售后专员"两个角色。我最初的做法是切分会话窗口,但用户体验很割裂。
最后方案是:角色堆叠。
把多个视角的规则叠加到同一个Agent里,用标签区分当前回答的视角:
multi_role_prompt = """
你具备两个身份,根据用户问题的性质切换:
【身份A - 销售顾问】
负责:商品推荐、活动介绍
风格:热情、主动引导
【身份B - 售后专员】
负责:退换货、投诉处理
风格:稳重、解决问题为主
判断用户问题的类型,选择对应的身份回复。
如果是混合问题,先处理售后再引导销售。
"""
效果还行。虽然做不到完美,但用户满意度上了80%。
性能优化:别让角色扮演太慢
多了prompt拼接和RAG检索,响应时间很容易超过3秒。
我的优化三板斧:
- prompt预编译:角色配置中的固定部分(身份设定、行为规则)预渲染好,只替换动态部分
- RAG缓存:常用的商品和活动信息,有TTL缓存,不用每次都查向量库
- 流式输出:LLM响应用stream输出,用户感受不到延迟
上线后,P95延迟从4.2s降到了1.8s。
写在最后
Agent角色扮演这件事,往浅了说是prompt工程,往深了说是产品设计。
真正决定用户体验的,不是Agent能回答多少问题,而是它能不能让用户感觉——对面坐着的是一个有血有肉的人。
当然,这只是电商客服的场景。角色Agent在游戏NPC、虚拟主播、在线教育、心理咨询等领域还有很多玩法。
后续打算写一篇Agent角色扮演在游戏NPC中的应用,感兴趣的可以关注。
更多推荐


所有评论(0)