项目概述
本文记录了如何使用LangChain框架构建一个企业内部知识库问答系统的实践过程。项目以"易速鲜花"公司为例,实现了一个能够智能回答员工关于公司政策、流程等问题的系统。
系统架构
整个系统分为三大模块:
- 数据源(Data Sources):处理PDF、Word、TXT等非结构化数据
- LLM应用(LLM App):使用大语言模型作为处理核心
- 应用场景(Use-Cases):实现智能问答功能
核心实现步骤
1. 文档加载
使用LangChain的document_loaders加载不同格式的文档:
python
Copy
from langchain.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
base_dir = './OneFlower' # 文档目录
documents = []
# 遍历目录加载不同格式文档
for file in os.listdir(base_dir):
file_path = os.path.join(base_dir, file)
if file.endswith('.pdf'):
loader = PyPDFLoader(file_path)
documents.extend(loader.load())
elif file.endswith('.docx'):
loader = Docx2txtLoader(file_path)
documents.extend(loader.load())
elif file.endswith('.txt'):
loader = TextLoader(file_path)
documents.extend(loader.load())
代码解析:
- 使用不同的loader处理不同格式文件
extend()方法将加载的文档添加到统一的documents列表- 通过文件扩展名判断使用哪种loader
2. 文本分割
使用RecursiveCharacterTextSplitter进行文本切分:
python
Copy
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # 每个文本块的大小
chunk_overlap=10 # 相邻块的重叠部分
)
chunked_documents = text_splitter.split_documents(documents)
代码解析:
chunk_size=200:将文档分割成200字符的块chunk_overlap=10:设置10字符的重叠,确保上下文的连贯性- 分割后的文档块便于后续向量化和存储
3. 向量存储
使用OpenAI Embeddings生成文本向量,并存储到Qdrant向量数据库:
python
Copy
from langchain.vectorstores import Qdrant
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Qdrant.from_documents(
documents=chunked_documents, # 分块后的文档
embedding=OpenAIEmbeddings(), # OpenAI的Embedding模型
location=":memory:", # 内存存储
collection_name="my_documents" # 集合名称
)
代码解析:
- 使用OpenAI的Embedding模型将文本转换为向量
- 选择Qdrant作为向量数据库,支持高效的相似度检索
:memory:表示数据存储在内存中,也可以配置持久化存储
4. 检索问答链配置
设置检索式问答模型:
python
Copy
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.chains import RetrievalQA
# 配置GPT模型
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
# 配置检索器
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(),
llm=llm
)
# 创建问答链
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=retriever_from_llm
)
代码解析:
temperature=0:确保输出的一致性- MultiQueryRetriever能够优化检索效果
- RetrievalQA链将检索和问答过程串联起来
5. Web接口实现
使用Flask构建简单的Web界面:
python
Copy
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
question = request.form.get('question')
result = qa_chain({"query": question})
return render_template('index.html', result=result)
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True, port=5000)
代码解析:
- 支持GET和POST请求
- POST请求处理用户提交的问题
- 调用qa_chain生成答案并返回
技术要点总结
-
模块化设计
- 各个组件职责明确
- 便于维护和扩展
-
文档处理
- 支持多种格式
- 智能分块策略
- 向量化存储
-
检索优化
- 使用向量数据库
- MultiQueryRetriever提升检索质量
- 余弦相似度匹配
-
问答生成
- 基于GPT-3.5模型
- 结合本地知识库
- 实时响应
优化建议
- 考虑使用其他向量数据库如Chroma进行对比测试
- 可以尝试使用不同的开源模型替代GPT-3.5
- 增加文档更新机制,确保知识库及时更新
- 添加用户反馈机制,持续优化回答质量