用 LangChain 快速构建基于“易速鲜花”本地知识库的智能问答系统
在人工智能领域,尤其是自然语言处理(NLP)技术的飞速发展下,基于知识库的智能问答系统已经成为许多企业和开发者探索的热点。OpenAI 提供的 GPT 系列语言模型具有强大的文本理解和生成能力,结合 LangChain 库的强大功能,可以快速构建出一个高效的智能问答系统。在这篇文章中,我们将探讨如何使用 LangChain 构建一个基于“易速鲜花”本地知识库的智能问答系统,并详细说明实现的步骤。
系统概述
本项目的目标是构建一个智能问答系统,该系统能够从本地存储的文档中提取信息,基于用户的输入问题生成精确的答案。为了实现这一目标,我们将结合 LangChain 提供的文档加载器、文本分割工具、向量存储以及检索模型,最终通过 Flask 构建一个简单的 Web 界面,使用户能够通过浏览器与系统进行交互。
系统实现步骤
1. 加载文档
首先,我们需要将存储在本地的文档加载到系统中。在本示例中,文档存放在 OneFlower 文件夹中,包含 PDF、Word 和纯文本格式的文件。为了处理这些不同格式的文件,LangChain 提供了多种文档加载器,包括 PyPDFLoader、Docx2txtLoader 和 TextLoader。
python
复制代码
import os
from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
# 加载Documents
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())
在上述代码中,我们遍历文件夹中的所有文件,并根据文件类型选择适当的加载器。每个加载器能够提取出文档中的文本内容,并将其存储在 documents 列表中。
2. 切分文档
由于从文档中提取的文本内容可能会非常庞大,直接进行向量化和存储会带来很大的计算压力,因此需要将文档内容切分成较小的块。这里我们使用了 LangChain 提供的 RecursiveCharacterTextSplitter 工具,按照字符长度将文本切割成 200 个字符的小块,重叠部分为 10 个字符。
python
复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=10)
chunked_documents = text_splitter.split_documents(documents)
通过这种方式,文档被拆解为多个小段,这些小段更适合进行向量化处理,也可以有效减少计算负担。
3. 向量存储
在将文档切分成小块后,我们需要将这些小块的文本进行嵌入(embedding)处理,将其转换为向量表示。嵌入向量能够捕捉文本的语义信息,使得模型可以通过向量空间进行高效的相似性检索。
我们使用了 DoubaoEmbeddings 类,它继承自 LangChain 提供的 Embeddings 类,借助 OpenAI 的 Embedding 模型来生成文本的嵌入向量。然后,使用 Qdrant 向量数据库将这些嵌入向量存储起来。
python
复制代码
from langchain_community.vectorstores import Qdrant
from langchain.embeddings.base import Embeddings
from volcenginesdkarkruntime import Ark
from langchain.pydantic_v1 import BaseModel
from typing import Any, List
class DoubaoEmbeddings(BaseModel, Embeddings):
client: Ark = None
api_key: str = ""
model: str
def __init__(self, **data: Any):
super().__init__(**data)
if self.api_key == "":
self.api_key = os.environ["OPENAI_API_KEY"]
self.client = Ark(
base_url=os.environ["OPENAI_BASE_URL"],
api_key=self.api_key
)
def embed_query(self, text: str) -> List[float]:
embeddings = self.client.embeddings.create(model=self.model, input=text)
return embeddings.data[0].embedding
def embed_documents(self, texts: List[str]) -> List[List[float]]:
return [self.embed_query(text) for text in texts]
class Config:
arbitrary_types_allowed = True
vectorstore = Qdrant.from_documents(
documents=chunked_documents,
embedding=DoubaoEmbeddings(model=os.environ["EMBEDDING_MODELEND"]),
location=":memory:",
collection_name="my_documents",
)
这里我们使用了 Qdrant 作为向量存储工具,它可以高效地支持大规模向量数据的检索。DoubaoEmbeddings 类负责将每个文档的小块转换为嵌入向量,并存储到 Qdrant 数据库中。
4. 构建检索和问答链
为了能够高效地从存储的文档中检索到相关信息,我们需要构建一个检索链。我们选择了 MultiQueryRetriever 作为检索工具,它可以基于用户输入的多个问题进行检索,返回最相关的文档片段。
接下来,我们使用 RetrievalQA 链将检索到的文档与 OpenAI 的 GPT 模型结合,生成最终的答案。
python
复制代码
import logging
from langchain_openai import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.chains import RetrievalQA
# 设置Logging
logging.basicConfig()
logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)
# 实例化OpenAI的GPT模型
llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)
# 实例化MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(), llm=llm
)
# 实例化RetrievalQA链
qa_chain = RetrievalQA.from_chain_type(llm, retriever=retriever_from_llm)
通过将检索工具与语言模型结合,系统能够基于文档库中的信息生成高质量的答案。RetrievalQA 链自动处理检索、答案生成等步骤。
5. 搭建Web界面
最后,我们使用 Flask 搭建了一个简单的 Web 界面,允许用户通过浏览器提交问题,系统会返回生成的答案。
python
复制代码
from flask import Flask, request, render_template
app = Flask(__name__) # Flask APP
@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)
Flask 提供了一个简单的 Web 框架,使得用户能够通过提交表单与智能问答系统交互。在 home 路由中,我们接收用户的问题,并通过 qa_chain 获取系统的答案,最后将答案返回并渲染到网页上。
总结
通过结合 LangChain 和 OpenAI 的强大功能,我们快速构建了一个基于本地知识库的智能问答系统。系统能够加载不同格式的文档,利用向量化技术高效存储和检索信息,并通过 GPT 模型生成高质量的回答。通过 Flask 构建的 Web 界面,用户可以方便地与系统进行交互。
该系统为基于特定知识库的问答应用提供了一个简单而有效的解决方案,在实际应用中可以根据需求进一步扩展和优化。例如,可以加入更多的知识管理和数据更新功能,或者针对特定领域进行定制化的训练和调优。
随着技术的不断进步,类似的智能问答系统将会越来越普及,为企业和个人提供更加智能、高效的信息服务。