如何在LangChain中构建兼具对话能力与文档知识库的聊天机器人?
实现兼具对话能力与个人信息检索的聊天机器人方案
核心思路
要解决机器人过度依赖文档、无法正常聊天的问题,关键是让模型在“需要用个人信息回答”和“普通聊天”两种场景间灵活切换,避免无相关文档时生硬回复“无信息”。
1. 给检索器加相关性阈值过滤
RetrievalQA和ConversationalRetrievalChain默认会返回最匹配的文档,哪怕相关性极低。你可以给向量检索器设置相似度阈值,当返回的文档得分低于阈值时,不将文档内容传入prompt,让模型自由对话。
- 示例代码(以LangChain的FAISS为例):
from langchain.vectorstores import FAISS from langchain.embeddings import OpenAIEmbeddings vector_store = FAISS.from_documents(your_personal_docs, OpenAIEmbeddings()) retriever = vector_store.as_retriever(search_kwargs={"k": 3, "score_threshold": 0.6})
- 逻辑说明:当检索到的文档相似度低于0.6时,retriever会返回空列表,此时prompt里的
{context}为空,模型就会忽略文档检索逻辑,转而基于对话历史正常回复。
2. 设计灵活的混合Prompt模板
写一个明确的prompt,告诉模型什么时候用个人信息、什么时候正常聊天:
你是一个能正常聊天的助手,以下是用户提供的个人信息(如果有相关内容的话): {context} 对话历史: {chat_history} 用户当前问题:{question} 注意:如果没有相关个人信息,或者问题和个人信息无关,直接像普通聊天一样回答,不要说“无相关信息”这类内容。
- 把这个模板传入RetrievalQA或ConversationalRetrievalChain的
prompt参数,模型会根据上下文自动切换回复逻辑。
3. 用内存组件维护对话历史
确保链正确保存对话历史,让模型能延续之前的对话:
- 使用
ConversationBufferMemory或ConversationSummaryMemory,初始化链时传入memory参数:
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) chain = ConversationalRetrievalChain.from_llm( llm=your_llm, retriever=retriever, memory=memory, combine_docs_chain_kwargs={"prompt": your_custom_prompt} )
- 这样模型能记住之前的对话内容,哪怕用户问的是和个人信息无关的问题,也能自然延续聊天。
4. 小体量个人信息的简化处理
因为你的个人信息只有3页,体量很小,完全可以不用做向量检索,直接把所有个人信息嵌入到系统prompt里:
- 示例系统prompt:
你是一个能正常聊天的助手,同时你了解以下关于用户的个人信息: [这里粘贴3页个人信息的整理文本] 当用户问和这些信息相关的问题时,结合内容回答;其他问题就像普通聊天一样回应。
- 这种方式更简单,不需要维护向量库,模型直接记住所有个人信息,同时不影响正常对话能力。
5. 自定义分支逻辑(进阶方案)
如果需要更精准的场景切换,可以用LangChain的路由链或自定义条件判断:
- 先让模型判断用户问题属于“个人信息相关”还是“普通聊天”;
- 如果是前者,调用检索链结合个人信息回答;
- 如果是后者,直接用普通对话模型回复,跳过检索步骤。
- 示例代码逻辑:
def route_question(question): # 用大模型做分类,比如用OpenAI的ChatCompletion classification_prompt = f"判断以下问题是否和用户个人信息相关:{question},回答'是'或'否'" response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": classification_prompt}] ) return response.choices[0].message.content.strip() # 主逻辑 user_question = "你今天吃什么了?" if route_question(user_question) == "是": answer = retrieval_chain.run(user_question) else: answer = chat_llm.predict(user_question)
内容的提问来源于stack exchange,提问作者iXrst
相关产品推荐
相关产品推荐

