Python/生成式AI/大语言模型:聊天机器人中用于澄清用户意图的跟进提问最佳实践
这个问题我之前在做企业级RAG聊天机器人的时候也踩过坑——上千个主题的知识库,概念重叠得一塌糊涂,用户一句模糊提问就把硬规则全干破了。结合你用的Python + Gemini 2.0 Flash Lite + Pydantic-AI技术栈,分享几个完全不用硬编码、可扩展的通用方案:
一、用大模型做结构化歧义检测(核心逻辑)
直接让Gemini帮你判断用户提问是否存在歧义,而且用Pydantic把输出结构化,避免模型输出杂乱无章,后续逻辑处理起来也省心。
步骤1:定义歧义检测的结构化输出
用Pydantic定一个清晰的模型,让模型返回明确的布尔值和相似概念列表,杜绝模棱两可的输出:
from pydantic import BaseModel, Field from typing import List class AmbiguityCheckResult(BaseModel): needs_clarification: bool = Field(description="是否需要用户进一步澄清意图") possible_concepts: List[str] = Field(description="知识库中与用户提问相似的潜在概念列表")
步骤2:调用Gemini做歧义判断
结合Pydantic-AI把模型输出映射到结构化对象,不用再写一堆字符串解析的逻辑:
import google.generativeai as genai from pydantic_ai import PydanticAI # 初始化Gemini模型 genai.configure(api_key="你的API密钥") gemini_model = genai.GenerativeModel('gemini-2.0-flash-lite') pydantic_ai = PydanticAI(model=gemini_model) def check_query_ambiguity(user_query: str, similar_concepts: List[str]) -> AmbiguityCheckResult: prompt = f""" 用户提问:"{user_query}" 从知识库检索到的相似主题:{', '.join(similar_concepts)} 请判断这个提问是否存在歧义:如果多个主题都能匹配且差异明显,就需要澄清;反之则不需要。 请严格按照给定的Pydantic模型返回结果,不要添加额外内容。 """ return pydantic_ai.generate(AmbiguityCheckResult, prompt=prompt)
二、向量检索+相似度校验:前置过滤歧义场景
光靠模型判断还不够,先通过向量检索把用户提问和知识库主题做匹配,用相似度数据辅助判断是否有歧义——毕竟模型也可能“走神”,双重校验更靠谱。
1. 向量检索相似主题
用Gemini的embedding模型把文本转成向量,再用FAISS做快速相似检索:
import faiss import numpy as np def get_text_embedding(text: str) -> np.ndarray: """把文本转为Gemini embedding向量""" embedding = genai.embed_content( model="models/embedding-001", content=text, task_type="retrieval_query" ) return np.array(embedding['embedding']).astype('float32') def retrieve_similar_topics(user_query: str, vector_index: faiss.IndexFlatL2, topic_list: List[str], top_k: int=3) -> List[str]: """检索与用户提问最相似的知识库主题""" query_vec = get_text_embedding(user_query).reshape(1, -1) distances, indices = vector_index.search(query_vec, top_k) # 筛选相似度达标(距离小于阈值)的主题,阈值根据知识库实际情况调优 valid_topics = [] for idx, dist in zip(indices[0], distances[0]): if dist < 0.2: # 示例阈值,需实际测试调整 valid_topics.append(topic_list[idx]) return valid_topics
2. 双重校验触发澄清
比如用户问“如何获取SIM卡”,检索到SIM卡、eSIM、extraSIM三个相似度极高的主题,再结合模型的歧义判断结果,就可以确定需要触发澄清逻辑。
三、动态生成自然的澄清问题
确定需要澄清后,让Gemini生成贴合场景的自然提问,别用生硬的“你指的是哪个?”。提示词要明确要求口语化、贴合用户语境:
def generate_clarify_question(user_query: str, possible_concepts: List[str]) -> str: prompt = f""" 用户现在问:"{user_query}" 这个问题可能涉及以下几个不同的概念:{', '.join(possible_concepts)} 请生成1-2个自然的中文跟进问题,引导用户明确具体需求,不要用太技术化的术语。 """ response = gemini_model.generate_content(prompt) return response.text
针对SIM卡的场景,模型可能生成:“你是想了解实体SIM卡、eSIM还是extraSIM的获取方式呢?” 或者 “请问你需要的是实体SIM卡,还是电子形式的eSIM/extraSIM呀?”
四、整合到RAG pipeline的完整流程
把所有逻辑串起来,还要记得维护对话历史,避免重复澄清已经明确过的需求——用户刚说过要eSIM,下一句问激活方式又被澄清,体验直接拉胯:
def chatbot_pipeline(user_query: str, conversation_history: List[str] = None): conversation_history = conversation_history or [] # 先检查对话历史,是否已经明确过相关概念 mentioned_concepts = set() all_history_text = ' '.join(conversation_history) # 这里可以动态从possible_concepts里匹配,不用硬编码SIM相关术语 for concept in ['SIM卡', 'eSIM', 'extraSIM']: if concept in all_history_text: mentioned_concepts.add(concept) if mentioned_concepts: # 已经明确意图,直接检索知识库生成回答 similar_topics = retrieve_similar_topics(user_query, vector_index, topic_list) # 这里写生成回答的逻辑,比如拼接知识库内容 + 大模型润色 return f"根据你的需求,{mentioned_concepts.pop()}的获取方式是..." # 1. 检索相似主题 similar_topics = retrieve_similar_topics(user_query, vector_index, topic_list) if not similar_topics: return "抱歉,我暂时没有相关的信息哦" # 2. 检查是否存在歧义 ambiguity_result = check_query_ambiguity(user_query, similar_topics) # 3. 处理结果 if ambiguity_result.needs_clarification: return generate_clarify_question(user_query, ambiguity_result.possible_concepts) else: # 无歧义,用知识库内容生成回答 return f"获取{similar_topics[0]}的方式是..."
实战注意事项
- 阈值调优:向量相似度的阈值(比如0.2)和模型的歧义判断逻辑,一定要结合你的知识库实际情况测试。如果知识库概念区分度低,阈值可以适当调高。
- 对话历史维护:必须把用户之前的提问和回答存在上下文里,不然用户体验会很差。
- 提示词迭代:可以把用户喜欢的澄清提问例子加入提示词,让模型生成的问题更贴合你的用户群体的语言习惯。
- 性能优化:向量检索的top K不要设太大(比如top3足够),太多结果会让模型判断混乱;另外可以批量预生成知识库的向量,减少实时计算的耗时。
这种方案完全是通用的,不管知识库有多少主题,只要维护好向量库和提示词,就能自动处理歧义场景,不用硬编码任何规则,扩展性拉满~




