LangChain多语言聊天机器人知识库差异问题及配置咨询
瑞士房产领域聊天机器人多语言知识调用问题
问题背景
基于LangChain开发了一款带记忆功能的瑞士房产领域聊天机器人,通过PDF导入自定义领域知识库,支持多语言交互且运行正常。为验证知识范围,做了测试:
- 用英文提问通用知识(如“瑞士的首都是什么?”),机器人回复“不知道”,判断未调用预训练知识;
- 用德语提问相同通用知识,机器人能给出正确答案。
咨询问题
- 这种多语言下的差异行为是正常现象还是Bug?
- 如何配置机器人,使其仅聚焦自定义知识库,或者启用预训练通用知识?
实现代码
import os import pandas as pd import matplotlib.pyplot as plt from transformers import GPT2TokenizerFast from langchain.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import FAISS from langchain.chains.question_answering import load_qa_chain from langchain.llms import OpenAI from langchain.chains import ConversationalRetrievalChain from IPython.display import display import ipywidgets as widgets os.environ["OPENAI_API_KEY"] = "..." # STEP 1: Split by chunk # Convert PDF to text import textract doc = textract.process("./Allgemeine Bedingungen.pdf") # Save to .txt and reopen with open('Allgemeine Bedingungen.txt', 'w') as f: f.write(doc.decode('utf-8')) with open('Allgemeine Bedingungen.txt', 'r') as f: text = f.read() # Create function to count tokens tokenizer = GPT2TokenizerFast.from_pretrained("gpt2") def count_tokens(text: str) -> int: return len(tokenizer.encode(text)) # Split text into chunks text_splitter = RecursiveCharacterTextSplitter( chunk_size = 512, chunk_overlap = 24, length_function = count_tokens, ) chunks = text_splitter.create_documents([text]) # STEP 2: Embed text and store embeddings # Get embedding model embeddings = OpenAIEmbeddings() # Create vector database db = FAISS.from_documents(chunks, embeddings) # STEP 3: Setup retrieval function chain = load_qa_chain(OpenAI(temperature=0), chain_type="stuff") query = "Was ist die Unterhaltspflicht des Mieters?" docs = db.similarity_search(query) chain.run(input_documents=docs, question=query) # STEP 4: Create chatbot with chat memory qa = ConversationalRetrievalChain.from_llm(OpenAI(temperature=0.1), db.as_retriever()) chat_history = [] def on_submit(_): query = input_box.value input_box.value = "" if query.lower() == 'stop': print("Cheers!") return result = qa({"question": query, "chat_history": chat_history}) chat_history.append((query, result['answer'])) display(widgets.HTML(f'<b>User:</b> {query}')) display(widgets.HTML(f'<b><font color="blue">Chatbot:</font></b> {result["answer"]}')) print("Welcome! Type 'stop' to quit.") input_box = widgets.Text(placeholder='Enter your question:') input_box.on_submit(on_submit) display(input_box)
问题解答
1. 行为是否正常?
这不是Bug,是多语言检索与LLM提示词交互的正常现象,原因如下:
- 知识库PDF是德语文档(文件名
Allgemeine Bedingungen.pdf),生成的嵌入向量基于德语文本。用德语提问通用知识时,检索器可能返回语义看似相关的德语文档片段(哪怕内容和问题无关),LLM处理这些片段时结合自身预训练知识给出了答案; - 用英文提问时,检索器找不到语义匹配的英文文档片段,返回结果为空或无关内容,LLM在无上下文支撑的情况下,按默认逻辑回复“不知道”。
2. 配置方案
方案一:强制仅聚焦自定义知识库
修改ConversationalRetrievalChain的提示词,明确要求LLM只能基于提供的文档回答,禁止使用外部知识:
from langchain.prompts import PromptTemplate prompt_template = """仅根据以下提供的文档内容回答问题,不要使用任何外部知识。如果文档中没有相关信息,直接回复“不知道”。 文档内容: {context} 问题: {question} 回答:""" PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question"] ) # 替换原有链的prompt qa = ConversationalRetrievalChain.from_llm( OpenAI(temperature=0.1), db.as_retriever(search_kwargs={"k":1}), # 限制返回1份文档,减少无关片段干扰 combine_docs_chain_kwargs={"prompt": PROMPT} )
方案二:启用预训练通用知识
让机器人在知识库无相关内容时调用预训练知识,需修改链的逻辑,判断检索结果是否为空,再决定是否直接调用LLM回答:
from langchain.chains import RetrievalQA qa = RetrievalQA.from_chain_type( llm=OpenAI(temperature=0.1), chain_type="stuff", retriever=db.as_retriever(), return_source_documents=True ) # 修改交互逻辑 def on_submit(_): query = input_box.value input_box.value = "" if query.lower() == 'stop': print("Cheers!") return result = qa({"query": query}) # 无相关文档时直接调用LLM回答 if not result["source_documents"]: direct_answer = OpenAI(temperature=0.1)(query) result["result"] = direct_answer chat_history.append((query, result['result'])) display(widgets.HTML(f'<b>用户:</b> {query}')) display(widgets.HTML(f'<b><font color="blue">聊天机器人:</font></b> {result["result"]}'))
内容的提问来源于stack exchange,提问作者nicoe
相关产品推荐
相关产品推荐

