我正在参加「豆包MarsCode AI练中学体验活动」详情请看:掘金小册上线 AI练中学功能 | 你的 AI 编程助教喊你免费领小册啦!
LangChain实战课 - “易速鲜花”内部员工知识库问答系统
项目背景与目标
“易速鲜花”作为一个大型在线鲜花销售平台,面临着内部知识分散、更新不及时等问题。为了解决这些问题,我们计划开发一个基于内部知识手册的“Doc-QA”系统,即文档问答系统,利用LangChain框架处理员工手册中的问题,提供精准答案。
开发框架与核心机制
整个框架分为三个部分:数据源、大模型应用(LLM App)、用例。核心实现机制是数据处理管道(Pipeline),具体流程包括:
- Loading(加载):文档加载器将文档加载为LangChain可读格式。
- Splitting(分割):文本分割器将文档切分为指定大小的块。
- Storage(存储):将分割好的文档块以嵌入形式存储到向量数据库中。
- Retrieval(检索):应用程序从存储中检索分割后的文档。
- Output(输出):将问题和相似的嵌入片传递给语言模型(LLM),生成答案。
数据的准备和载入
我们首先使用LangChain中的document_loaders
来加载各种格式的文本文件。以下是代码示例:
import os
from langchain.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
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())
文本的分割
接下来,我们将加载的文本分割成更小的块,以便进行嵌入和向量存储。代码示例如下:
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=10)
chunked_documents = text_splitter.split_documents(documents)
向量数据库存储
我们将分割后的文本转换成嵌入形式,并存储在向量数据库中。代码示例如下:
from langchain.vectorstores import Qdrant
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Qdrant.from_documents(
documents=chunked_documents,
embedding=OpenAIEmbeddings(),
location=":memory:",
collection_name="my_documents",
)
相关信息的获取
当内部文档存储到向量数据库之后,我们需要根据问题和任务来提取最相关的信息。我们创建一个聊天模型,并实例化一个RetrievalQA
链。代码示例如下:
import logging
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.chains import RetrievalQA
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)
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)
生成回答并展示
最后,我们创建一个Flask应用来接收用户的问题,并生成相应的答案。代码示例如下:
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)
HTML网页的关键代码如下:
<body>
<div class="container">
<div class="header">
<h1>易速鲜花内部问答系统</h1>
<img src="{{ url_for('static', filename='flower.png') }}" alt="flower logo" width="200">
</div>
<form method="POST">
<label for="question">Enter your question:</label><br>
<input type="text" id="question" name="question"><br>
<input type="submit" value="Submit">
</form>
{% if result is defined %}
<h2>Answer</h2>
<p>{{ result.result }}</p>
{% endif %}
</div>
</body>
总结
通过这个项目,我们学习了如何使用LangChain框架来构建一个基于文档的问答系统。我们了解了文档的加载、分割、存储、检索和输出的整个流程,并实际操作了代码。这个系统不仅提高了内部知识的可访问性和更新效率,也展示了LangChain框架的强大功能。
思考题
- 简述基于文档的QA系统的实现流程。
- 使用Chroma实现任务。
- 使用HuggingFace的google/flan-t5-x1模型代替GPT-3.5完成这个任务。
思考题回答
1. 简述基于文档的QA系统的实现流程
基于文档的QA系统实现流程大致如下:
-
数据准备:首先,收集并整理“易速鲜花”内部的知识文档,这些文档可能包括PDF、Word和TXT格式的文件。
-
文档加载:使用LangChain提供的文档加载器(Document Loaders),将不同格式的文档转换成可读的文本格式,并存储在列表中。
-
文本分割:将加载的文档文本分割成小块,每块大约200个字符,以便于后续的嵌入和存储。
-
嵌入与存储:利用大模型将每个文本块转换成嵌入向量,并存储到向量数据库中,这里使用的是Qdrant。
-
信息检索:当用户提出问题时,系统将问题也转换成向量,并在向量数据库中检索与问题最相关的文档块。
-
生成回答:将检索到的文档块和原始问题一起输入到语言模型中,由模型生成答案。
-
展示答案:最后,将生成的答案展示给用户,完成整个问答流程。
2. 使用Chroma实现任务
使用Chroma作为向量数据库来实现这个任务是可行的。Chroma是一个开源的向量数据库,支持高维数据的存储和近似最近邻搜索。以下是使用Chroma实现的基本步骤:
-
安装Chroma:首先需要安装Chroma及其Python客户端库。
-
配置Chroma:设置Chroma的配置参数,如维度、距离度量等。
-
生成嵌入:使用OpenAI的Embedding模型为文档块生成嵌入向量。
-
存储嵌入:将生成的嵌入向量存储到Chroma数据库中。
-
检索嵌入:当接收到用户问题时,将问题转换为向量,并在Chroma中检索最相似的文档块。
-
集成到LangChain:将Chroma作为向量存储和检索的后端,集成到LangChain的Pipeline中。
代码层面,需要替换原有的Qdrant相关代码为Chroma的API调用,确保数据的存储和检索可以在Chroma中正确执行。
3. 使用HuggingFace的google/flan-t5-x1模型代替GPT-3.5完成这个任务
使用HuggingFace提供的开源模型google/flan-t5-x1代替GPT-3.5也是可行的。以下是大致步骤:
-
安装HuggingFace库:确保安装了Transformers库,这是HuggingFace提供的用于加载和使用预训练模型的库。
-
加载模型:使用Transformers库加载google/flan-t5-x1模型。
-
调整问答系统:将问答系统中原来调用GPT-3.5的部分替换为调用加载的flan-t5-x1模型。
-
模型微调:如果可能,对flan-t5-x1模型进行微调,使其更好地适应“易速鲜花”的特定领域知识。
-
集成到LangChain:确保模型可以接收问题并生成答案,然后集成到LangChain的Pipeline中。
代码层面,需要替换原有的ChatOpenAI模型实例化为HuggingFace的模型实例,并确保模型的输入输出接口与LangChain的其他组件兼容。