环境准备

在开始之前,确保你的开发环境已经安装了以下必要的库和工具:

  • Python:3.10.0
  • vllm:0.4.1+cu118
  • numba:0.62.1
  • langchain:0.3.27
  • langchain-community:0.3.27
  • langchain-core:0.3.75
  • langchain-openai:0.3.27
  • langchain-text-splitters:0.3.11
  • langsmith:0.4.34
  • faiss:用于高效相似性搜索
  • fitz(PyMuPDF):用于处理 PDF 文件

你可以使用以下命令来安装这些依赖项:

pip install python==3.10.0 vllm==0.4.1+cu118 numba==0.62.1 langchain==0.3.27 langchain-community==0.3.27 langchain-core==0.3.75 langchain-openai==0.3.27 langchain-text-splitters==0.3.11 langsmith==0.4.34 faiss fitz

启动 VLLM 服务器

首先,我们需要启动一个 VLLM 服务器,用于提供模型推理服务。运行以下命令来启动服务器:

python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-1.5B-Instruct \
    --port 8000 \
    --dtype float16 \
    --gpu-memory-utilization 0.8

这将启动一个监听 8000 端口的服务器,使用 Qwen2.5-1.5B-Instruct 模型进行推理。

构建知识库

接下来,我们需要从 PDF 文件中提取文本内容,并将其存储到 FAISS 索引中。以下是完整的代码:

import faiss
import fitz  # PyMuPDF
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.schema import Document
import os

# 定义保存路径和文件夹路径
save_path = "/home/AI/yuanxianpeng/vllm/faiss_index"
folder = "/home/AI/yuanxianpeng/vllm/docs/"
texts = []

# 读取 PDF 文件并提取文本
for filename in os.listdir(folder):
    if filename.endswith(".pdf"):
        file_path = os.path.join(folder, filename)
        doc = fitz.open(file_path)
        content = ""
        for page in doc:
            content += page.get_text()
        if content.strip():
            texts.append(content)

# 分割文本
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = []
for text in texts:
    chunks.extend(splitter.split_text(text))

# 转换为 Document 对象
doc_objects = [Document(page_content=chunk) for chunk in chunks]

# 向量化并存储到 FAISS 索引
embeddings_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vector_store = FAISS.from_documents(doc_objects, embeddings_model)
vector_store.save_local(save_path)

代码解释

  1. 读取 PDF 文件:使用 fitz 库读取指定文件夹中的 PDF 文件,并提取每一页的文本内容。
  2. 分割文本:使用 RecursiveCharacterTextSplitter 将提取的文本分割成大小为 500 字符的块,块之间有 50 字符的重叠。
  3. 转换为 Document 对象:将每个文本块转换为 Document 对象。
  4. 向量化并存储到 FAISS 索引:使用 Hugging Face 的 all-MiniLM-L6-v2 模型将文本块向量化,并将向量化的文档存储到 FAISS 索引中。

构建问答系统

现在我们已经构建了知识库,接下来我们将构建问答系统。以下是完整的代码:

from langchain.chains import RetrievalQA
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS

# 初始化嵌入模型
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

# 加载本地 FAISS 索引
vector_store = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)

# 初始化 LLM(语言模型)
llm = ChatOpenAI(
    model_name="Qwen/Qwen2.5-1.5B-Instruct",  # 与 vLLM 加载名保持一致
    openai_api_key="EMPTY",                   # vLLM 不校验可随意
    openai_api_base="http://localhost:8000/v1",
    temperature=0.7,
    max_tokens=256,
)

# 构建问答系统
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vector_store.as_retriever(search_kwargs={"k": 3}),
    return_source_documents=True
)

# 提出问题并获取答案
query = "陆士曾是谁?"
result = qa_chain({"query": query})
print(result)

代码解释

  1. 加载 FAISS 索引:使用 FAISS.load_local 方法加载之前保存的 FAISS 索引。
  2. 初始化 LLM:使用 ChatOpenAI 初始化语言模型,指定模型名称、API 基地址、温度参数和最大生成的 token 数量。
  3. 构建问答链:使用 RetrievalQA.from_chain_type 方法构建问答链,指定语言模型、链类型、检索器和是否返回源文档。
  4. 提出问题并获取答案:使用问答链处理用户的问题,并打印结果。

总结

通过上述步骤,我们成功构建了一个基于 VLLM、LangChain 和 FAISS 的知识库问答系统。这个系统可以从 PDF 文件中提取文本内容,将其存储到 FAISS 索引中,并使用语言模型生成答案。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐