创新实训个人:主agent意图识别功能实现
一、核心设计补全:意图识别与 Agent 路由的底层逻辑
多 Agent 系统的核心是 “精准路由”—— 让用户的自然语言问题,被正确分配到专业的子 Agent 处理,而这一切的前提是主 Agent 的双层意图识别机制。
1. 主 Agent 的双层意图识别:从 “泛识别” 到 “精准匹配”
在/chat接口中,我设计了 “第一层:基础意图分类(闲聊 / 无效 / 业务)+ 第二层:业务意图拆解(情感分析 / 主题挖掘等)” 的双层识别逻辑,核心实现如下:
核心代码与设计思考
# 主Agent对话接口中核心意图识别逻辑
intent_result = await dispatcher.scheduling_agent._identify_intent(request.message)
intent_type = intent_result.get("intent_type", IntentType.FULL_ANALYSIS)
routed_to = intent_type.value if hasattr(intent_type, "value") else str(intent_type)
yield f"data: {json.dumps({'routed_to': routed_to, 'intent_layer': intent_result.get('matched_layer', 1)}, ensure_ascii=False)}\n\n"
# ── 第一层意图短路逻辑:闲聊/无效问题快速响应 ──
if intent_type == IntentType.SMALL_TALK:
async for chunk in llm_client.astream(
[
{"role": "system", "content": _SmallTalk.SYSTEM_PROMPT},
{"role": "user", "content": request.message},
],
temperature=0.8,
max_tokens=400,
):
yield f"data: {json.dumps({'content': chunk}, ensure_ascii=False)}\n\n"
yield "data: [DONE]\n\n"
return
if intent_type == IntentType.INVALID_QUESTION:
yield f"data: {json.dumps({'content': '抱歉,您的问题超出了本系统的分析范围...'}, ensure_ascii=False)}\n\n"
yield "data: [DONE]\n\n"
return
# ── 第二层意图:业务分析意图拆解 ──
agent_names = dispatcher.scheduling_agent._decompose_tasks(intent_type, context)
sub_results = {}
for name in agent_names:
if name in dispatcher.agents:
sub_results[name] = await dispatcher.agents[name].execute(context)
设计思考:
- 分层识别的价值:第一层识别解决 “非业务问题快速响应”(如闲聊直接走 SmallTalkAgent,无需加载数据集),第二层识别解决 “业务问题精准分工”,既提升响应速度,又保证分析专业性;
- 意图结果透传:通过 SSE 将
routed_to(路由目标 Agent)、intent_layer(匹配层级)推送给前端,便于前端展示 “当前分析维度”,提升交互透明度; - 容错兜底:默认兜底为
FULL_ANALYSIS(全量分析),避免意图识别失败导致系统不可用。
2. 子 Agent 专属接口:精细化承接特定场景需求
除了主 Agent 的 “自动路由”,我还设计了/sub-chat接口,支持用户直接指定子 Agent 对话(如仅调用营销文案 Agent),核心实现与设计如下:
核心代码与设计思考
# 子Agent能力映射表:固化Prompt与数据集依赖
AGENT_SYSTEM_PROMPTS = {
"data_summary": ("你是数据摘要专家,专注于电商评论数量、评分分布、时间趋势等基础统计分析。只回答数据摘要相关问题。", True),
"sentiment_analysis": ("你是情感分析专家,专注于电商评论的情感倾向、好差评比例、情感趋势分析。只回答情感分析相关问题。", True),
"topic_mining": ("你是主题挖掘专家,专注于LDA主题建模、关键词聚类、评论话题识别。只回答主题挖掘相关问题。", True),
"competitor": ("你是竞品分析专家,专注于产品横向对比、竞争优劣势分析。只回答竞品分析相关问题。", True),
"marketing": ("你是营销文案专家,专注于基于用户评论生成营销文案、卖点提炼、差评应对话术。只回答营销文案相关问题。", True),
"small_talk": (_SmallTalk.SYSTEM_PROMPT, False),
}
@router.post("/sub-chat", summary="子Agent专属对话(SSE流式)")
async def sub_agent_chat(request: SubAgentChatRequest, db: AsyncSession = Depends(get_db)):
agent_key = request.agent_key
if agent_key not in AGENT_SYSTEM_PROMPTS:
async def err_gen():
yield f"data: {json.dumps({'conversation_id': conversation_id, 'cannot_answer': True, 'content': '未知的 Agent 类型'}, ensure_ascii=False)}\n\n"
yield "data: [DONE]\n\n"
return _sse_stream(err_gen())
system_prompt, needs_dataset = AGENT_SYSTEM_PROMPTS[agent_key]
# 加载数据集(如需)+ 执行子Agent逻辑
if needs_dataset and request.dataset_id:
df = await _load_df(request.dataset_id, db)
if df is not None and agent_key in dispatcher.agents:
context = {...}
agent_result = await dispatcher.agents[agent_key].execute(context)
context_text = f"\n\n当前数据集分析结果:\n{json.dumps(agent_result, ensure_ascii=False, default=str)[:1500]}"
# 流式返回子Agent响应
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": request.message + context_text},
]
async for chunk in llm_client.astream(messages, temperature=0.6, max_tokens=600):
yield f"data: {json.dumps({'content': chunk}, ensure_ascii=False)}\n\n"
设计思考:
- 能力映射表的价值:将 “Agent 类型 → 专属 System Prompt → 数据集依赖” 固化为映射表,既保证每个子 Agent 的 Prompt 专业性(避免回答越界),又统一管理 “是否需要数据集” 的规则,降低接口逻辑复杂度;
- 上下文裁剪:将子 Agent 的分析结果截断到 1500 字内拼接到 Prompt 中,既保证 LLM 有足够的上下文,又避免 Token 超限;
- 明确的不可回答机制:当子 Agent 无法处理(如无数据集、Agent 不存在)时,返回
cannot_answer标识,前端可针对性提示,避免模糊的错误信息。
二、Prompt 工程:从 “通用提问” 到 “约束式生成”
Prompt 是 LLM 能力落地的核心,我在系统中设计了三类 Prompt 范式:子 Agent 专属 System Prompt、营销文案约束式 Prompt、分析结果总结 Prompt,以下是核心实现与思考:
1. 子 Agent 专属 System Prompt:边界约束 + 专业定位
如上文AGENT_SYSTEM_PROMPTS所示,每个子 Agent 的 System Prompt 都遵循 “身份定位 + 能力边界” 的设计原则:
# 示例:情感分析Agent的System Prompt
"你是情感分析专家,专注于电商评论的情感倾向、好差评比例、情感趋势分析。只回答情感分析相关问题。"
设计思考:
- 身份锚定:明确 “专家” 身份,提升 LLM 回答的专业性;
- 能力边界:通过 “只回答 XXX 相关问题” 约束回答范围,避免答非所问;
- 简洁性:不堆砌冗余信息,保证 Prompt 的轻量化(降低 Token 消耗)。
2. 营销文案约束式 Prompt:结构化输出 + 数据驱动
营销文案生成是核心业务场景,我设计了 “数据输入 + 格式约束 + 内容要求” 的三层 Prompt,核心实现如下:
核心代码与设计思考
prompt = f"""你是专业电商营销文案师。根据以下用户好评高频词,生成三种风格的标题文案。
好评高频词(Top30):{', '.join(top_words)}
请生成:
1. 情感种草风文案(3条,如"一用就爱上"风格)
2. 功能卖点风文案(3条,突出技术/材质/体验)
3. 数据背书风文案(3条,用数据说话)
4. 卖点提炼清单(3-5条,每条≤20字,可直接用于详情页)
5. 差评应对话术(关切型/解释型/补偿型各1条)
请以JSON格式返回:
{{
"emotional_copy": ["文案1", "文案2", "文案3"],
"feature_copy": ["文案1", "文案2", "文案3"],
"data_copy": ["文案1", "文案2", "文案3"],
"key_points": ["卖点1", "卖点2", "卖点3"],
"response_templates": {{
"caring": "关切型话术",
"explanatory": "解释型话术",
"compensatory": "补偿型话术"
}}
}}"""
设计思考:
- 数据驱动:将好评高频词作为输入,避免 LLM “凭空创作”,保证文案贴合真实用户反馈;
- 格式约束:明确要求 JSON 格式 + 字段名称,前端可直接解析,无需额外处理;
- 风格示例:通过 “如 ' 一用就爱上 ' 风格” 降低 LLM 的理解偏差,保证生成内容符合业务预期;
- 长度限制:卖点提炼要求 “每条≤20 字”,适配电商详情页的展示场景。
3. 分析结果总结 Prompt:轻量化 + 场景化
主 Agent 在聚合子 Agent 分析结果后,需要将结构化数据转为自然语言回答,此时的 Prompt 设计核心是 “轻量化 + 场景化”:
summary_ctx = json.dumps(sub_results, ensure_ascii=False, default=str)[:2000]
prompt = f"""用户问题:{request.message}
以下是各分析模块的结果:
{summary_ctx}
请根据以上数据,用自然语言简洁地回答用户的问题。"""
设计思考:
- 上下文截断:限制在 2000 字内,平衡 “信息完整性” 与 “Token 消耗”;
- 用户问题前置:让 LLM 优先聚焦用户核心诉求,避免回答偏离;
- 指令简洁化:仅要求 “自然语言简洁回答”,避免过度约束导致回答僵硬。
三、工程化落地:意图识别与 Prompt 的避坑指南
在落地意图识别和 Prompt 工程的过程中,我踩了多个关键坑,也总结了对应的解决方案:
1. 意图识别的 “误判” 问题:多轮验证 + 兜底逻辑
- 问题:初期直接通过关键词匹配意图,导致 “用户问‘竞品的情感分析’” 被误判为 “情感分析” 而非 “竞品分析”;
- 解决方案:
- 升级为 LLM 驱动的意图识别(而非关键词),Prompt 中明确要求识别 “核心诉求 + 分析维度”;
- 增加
FULL_ANALYSIS兜底逻辑,即使意图识别失败,也会调用全量子 Agent 分析,保证回答可用; - 前端透传
routed_to字段,用户可手动切换子 Agent,弥补机器识别的不足。
2. Prompt 的 “格式失控” 问题:正则提取 + 兜底返回
- 问题:营销文案生成时,LLM 偶尔返回非 JSON 格式(如额外的解释文字),导致前端解析失败;
- 解决方案:
- 用正则
re.search(r'\{.*\}', response, re.DOTALL)提取 JSON 片段,忽略冗余内容; - 解析失败时返回兜底文案,保证接口可用性;
- System Prompt 中强化 “仅返回 JSON,无需额外解释” 的约束。
- 用正则
3. 子 Agent 接口的 “数据集依赖” 问题:前置校验 + 友好提示
- 问题:用户调用需要数据集的子 Agent(如情感分析)但未传
dataset_id,导致接口报错; - 解决方案:
- 在
AGENT_SYSTEM_PROMPTS中标记needs_dataset,前置校验数据集是否存在; - 无数据集时返回友好提示(如 “请先选择数据集,我才能帮你分析哦”),而非技术错误;
- 加载数据集失败时,仍保留纯 LLM 的 “通用回答” 能力(如 “情感分析通常包括好差评比例、情感趋势等维度...”)。
- 在
四、补充总结:多 Agent 系统的 “灵魂” 是 “精准分工 + 可控生成”
本次补充的「主 Agent 意图识别」「子 Agent 接口承接」「Prompt 工程」三大模块,是多 Agent 系统的 “灵魂”—— 意图识别解决 “该让谁做” 的问题,子 Agent 接口解决 “精准做” 的问题,Prompt 工程解决 “怎么做才符合预期” 的问题。
从技术落地角度,我最深的体会是:
- 意图识别不是 “越精准越好”,而是 “容错性越好越好”:即使识别有误,也要通过兜底逻辑保证系统可用;
- Prompt 不是 “越长越好”,而是 “约束越清晰越好”:结构化、轻量化的 Prompt,比大段模糊的描述更有效;
- 子 Agent 的 “专业化” 与 “易用性” 要平衡:既要有专属接口满足精细化需求,也要有主 Agent 的自动路由降低用户使用成本。
未来的优化方向也将围绕这三点展开:
- 意图识别引入用户反馈闭环(标记误判案例,优化 Prompt);
- Prompt 模板化管理(支持配置化修改,无需改代码);
- 子 Agent 能力动态扩展(支持新增 Agent 时自动注册到映射表)。
多 Agent 系统的本质,是用工程化的方式让 LLM 的能力 “分而治之”,而意图识别和 Prompt 则是连接用户需求与 Agent 能力的桥梁 —— 只有桥梁搭得稳、搭得准,整个系统才能真正从 “能用” 走向 “好用”。
更多推荐
所有评论(0)