基于 LlamaIndex 实现RAG向量检索入门
本章将通过多个案例实现私有数据集检索功能,虽然 LangChain 也可以实现向量检索,但在企业级项目中,通常会选用 LlamaIndex 这类专门面向检索场景的框架。LlamaIndex 是 MIT 协议开源、以 RAG 为核心的大模型应用开发框架。它充当大模型与私有数据之间的中间层,能够接入 PDF、Word 等各类本地或内网文档,对原始数据构建索引,以此解决大模型无法读取私有资料、容易产生幻觉的问题,可用于搭建知识问答、AI 智能体等应用。
一、环境部署
本项目需要部署两个轻量化GGUF量化模型,分别承担对话交互与语义向量检索能力,适配本地低资源部署场景。其中对话大模型负责承接用户提问、逻辑推理、文本生成等通用对话任务;Embedding向量嵌入模型负责将文本、语句等非结构化数据转化为低维稠密向量,让计算机能够量化计算文本间的语义相似度,实现精准检索、内容匹配、知识库召回等功能。
- 对话模型:https://www.modelscope.cn/models/LoveSeaW/Qwen2.5-1.5b-instruct-gguf
- 向量模型:https://www.modelscope.cn/models/guweigui/Qwen3-Embedding-0.6B-Q8_0-GGUF
我们通过llama-server分别启动两个模型服务,绑定不同本地端口,独立提供对话推理和向量生成能力。
加载通义千问对话量化模型,绑定127.0.0.1本地11433端口,设置4096上下文窗口,满足日常对话、文本生成、问答推理需求。
CMD> llama-server.exe -m qwen2.5-1.5b-instruct-q4_k_m.gguf --host 127.0.0.1 --port 11433 -c 4096
load_model: loading model 'qwen2.5-1.5b-instruct-q4_k_m.gguf'
llama_server: model loaded
llama_server: listening on http://127.0.0.1:11433
加载向量量化模型,需额外配置专属参数开启向量生成能力 --embeddings 开启向量嵌入功能,--pooling mean 采用均值池化策略聚合文本向量,保证语义表征精准;同时限制批次参数提升本地部署稳定性。
CMD> llama-server.exe -m Qwen3-Embedding-0.6B-Q8_0.gguf --host 127.0.0.1 --port 11434 -c 4096 --embeddings --pooling mean -b 512 -ub 512
load_model: loading model 'Qwen3-Embedding-0.6B-Q8_0.gguf'
llama_server: model loaded
llama_server: listening on http://127.0.0.1:11434
批量安装RAG项目所需核心依赖,包含框架、向量数据库、文档解析、接口适配等全量包。
# 配置国内PIP源
CMD> pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
CMD> pip config set global.trusted-host mirrors.tuna.tsinghua.edu.cn
CMD> pip config list
# 安装核心包
CMD> pip install llama-index
# 或安装完整版本(包含所有依赖)
CMD> pip install llama-index[complete]
# 向量数据库支持
CMD> pip install chromadb
CMD> pip install pinecone-client
CMD> pip install weaviate-client
# 文档解析支持
CMD> pip install pypdf
CMD> pip install docx2txt
CMD> pip install python-pptx
# 检索接口通信包
CMD> pip install llama-index-core llama-index-llms-openai-like
CMD> pip install llama-index-embeddings-openai
CMD> pip list
Package Version
---------------------------------------- -----------
llama-index 0.14.24
llama-index-core 0.14.24
llama-index-embeddings-openai 0.6.0
llama-index-instrumentation 0.6.0
llama-index-llms-openai 0.7.10
llama-index-llms-openai-like 0.8.0
llama-index-workflows 2.23.3
测试Chat对话接口
通过LlamaIndex的OpenAI兼容接口,对接本地11433端口对话服务,实现基础大模型问答调用,验证对话服务可用性。本地llama-server兼容OpenAI接口格式,可直接通过通用类适配调用,无需额外改造服务端。
import os
from llama_index.core import Settings
from llama_index.llms.openai_like import OpenAILike
os.environ["OPENAI_API_KEY"] = "dummy"
os.environ["OPENAI_BASE_URL"] = "http://127.0.0.1:11433/v1"
llm = OpenAILike(
model="qwen2.5-1.5b-instruct-q4_k_m.gguf",
api_base=os.environ["OPENAI_BASE_URL"],
api_key=os.environ["OPENAI_API_KEY"],
is_chat_model=True,
context_window=4096
)
if __name__ == "__main__":
Settings.llm = llm
resp = llm.complete("你好,大模型!")
print(resp)
代码运行输出提示信息:
你好!我是阿里云的大规模语言模型,我叫通义千问。
测试Embedding向量接口
LlamaIndex无默认的本地llama-server向量模型适配接口,因此需要自定义Embedding调用类,对接11434端口向量服务,搭建完整的「文档加载-分块向量化-索引存储-语义检索-大模型生成」RAG流程。
在项目根目录新建 data 文件夹,创建 test.txt 测试文档,写入RAG相关测试语料,用于后续检索验证
1. 人工智能大模型能够理解人类自然语言
2. 大模型基于海量文本数据进行预训练
3. 向量数据库用来存储文本对应的向量嵌入
4. 向量检索通过计算向量相似度找到相似内容
5. 文本嵌入模型可以把句子转为多维向量
6. 语义检索不依赖关键词匹配,理解句子含义
7. 关键词检索只匹配字面文字,无法理解语义
8. RAG检索增强生成依靠检索外部知识库
9. RAG可以降低大模型产生幻觉的概率
10. 分块策略会影响知识库检索的效果
使用向量检索代码,先自定义对接本地 embedding 服务LocalLlamaServerEmbedding实现文本向量化,配置OpenAILike接入本地大模型作为LLM,设置全局 Settings 指定模型,运行时读取文档,加载文档后构建内存向量索引,生成查询引擎,最后发起查询让大模型基于检索到的文档片段总结文档核心内容。
- 运行逻辑:自定义本地向量模型调用类 → 绑定本地对话LLM与向量Embedding模型 → 加载本地文档构建向量索引 → 语义检索+大模型总结生成答案
import os
import requests
from typing import List
from llama_index.core import Settings, SimpleDirectoryReader, VectorStoreIndex
from llama_index.core.embeddings import BaseEmbedding
from llama_index.llms.openai_like import OpenAILike
# 自定义Embedding模型
class LocalLlamaServerEmbedding(BaseEmbedding):
api_base: str
api_key: str = "dummy"
def _get_embedding(self, text: str) -> List[float]:
url = f"{self.api_base}/embeddings"
payload = {
"input": text,
"model": "Qwen3-Embedding-0.6B-Q8_0.gguf"
}
headers = {"Authorization": f"Bearer {self.api_key}"}
resp = requests.post(url, json=payload, headers=headers)
resp.raise_for_status()
return resp.json()["data"][0]["embedding"]
def _get_text_embedding(self, text: str) -> List[float]:
return self._get_embedding(text)
def _get_query_embedding(self, query: str) -> List[float]:
return self._get_embedding(query)
async def _aget_query_embedding(self, query: str) -> List[float]:
return self._get_embedding(query)
async def _aget_text_embedding(self, text: str) -> List[float]:
return self._get_embedding(text)
# 对话模型地址
os.environ["OPENAI_API_KEY"] = "dummy"
os.environ["OPENAI_BASE_URL"] = "http://127.0.0.1:11433/v1"
llm = OpenAILike(
model="qwen2.5-1.5b-instruct-q4_k_m.gguf",
api_base=os.environ["OPENAI_BASE_URL"],
api_key=os.environ["OPENAI_API_KEY"],
is_chat_model=True,
context_window=1024
)
# 向量模型地址
Settings.llm = llm
Settings.embed_model = LocalLlamaServerEmbedding(api_base="http://127.0.0.1:11434/v1")
if __name__ == "__main__":
# 构建RAG索引 过滤出pdf.docx.txt文件
documents = SimpleDirectoryReader(
"./data/",
required_exts=[".pdf", ".docx", ".txt"]
).load_data()
# 创建索引
index = VectorStoreIndex.from_documents(documents)
# 创建查询引擎
query_engine = index.as_query_engine()
# 进行查询
response = query_engine