文章目录
rag是一个概念。llama-index是一个实现rag的具体框架。
这么理解,无论哪个rag工具,都会有这些问题,而llama都实现了:
你想读 PDF?它有 SimpleDirectoryReader。
你想切分文字?它有 SentenceSplitter。
你想存向量?它有 VectorStoreIndex。
你想提问?它有 QueryEngine。
llama大概的流程是:
读取文件 | 根据文件创建向量索引 | 根据索引存库、或者查询。
示例用的llama-index版本是0.14.19。
基础示例
1、安装依赖
bash
安装 LlamaIndex 核心和文件读取支持
pip install llama-index llama-index-readers-file
安装 Ollama 连接器 (用于连接本地 LLM)
pip install llama-index-llms-ollama llama-index-embeddings-ollama
这里用的阿里云百炼openApi,所以额外安装如下依赖。
pip install llama-index-llms-dashscope llama-index-embeddings-dashscope
2、创建data目录,data目录下常见文件test.txt,内容为:
txt
阿里云百炼是阿里云推出的一站式大模型应用开发平台。
它集成了通义千问系列模型,支持快速构建 RAG 应用。
LlamaIndex 可以通过 DashScope 连接器轻松调用百炼上的模型。
3、创建python文件llama_index_demo.py,代码:
python
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.dashscope import DashScopeEmbedding
def main():
# 1. 设置 API Key
# 建议将 Key 设置到环境变量中,或者在这里直接替换字符串
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR API KEY")
print(f"🔍 代码读取到的API_KEY:{API_KEY}")
# 2. 配置模型
# model_name 可以是 qwen-turbo, qwen-plus, qwen-max 等
llm = DashScope(model_name="qwen-plus", api_key=os.getenv("DASHSCOPE_API_KEY"))
# 配置嵌入模型 (DashScope 提供了专门的 embedding 模型)
# model_name 通常是 text-embedding-v1 或 text-embedding-v2
embed_model = DashScopeEmbedding(model_name="text-embedding-v2", api_key=os.getenv("DASHSCOPE_API_KEY"))
# 将配置应用到全局设置
Settings.llm = llm
Settings.embed_model = embed_model
# 3. 加载数据
if not os.path.exists("data"):
os.makedirs("data")
with open("data/test.txt", "w", encoding="utf-8") as f:
f.write("阿里云百炼提供了一站式的大模型服务,通义千问是其核心模型。")
documents = SimpleDirectoryReader("data").load_data()
print(f"📚 成功加载了 {len(documents)} 个文档。")
# 4. 构建索引
print("⚙️ 正在构建向量索引 (调用百炼 Embedding API)...")
index = VectorStoreIndex.from_documents(documents)
# 5. 创建查询引擎
query_engine = index.as_query_engine()
# 6. 开始问答
print("\n✅ 准备就绪!请输入问题:")
while True:
query = input("\n❓ 用户: ")
if query.lower() == 'quit' or query.lower() == 'exit':
break
try:
# 这里会触发:检索 -> 组装提示词 -> 调用通义千问 -> 返回结果
response = query_engine.query(query)
print(f"🤖 通义千问: {response}")
except Exception as e:
print(f"发生错误: {e}")
if __name__ == "__main__":
main()
4、运行该代码,会弹出交互对话框
5、依次测试如下问题,看看效果
python
阿里云百炼是什么 # 期待效果 按照文档里的内容来答
这段文档里提到了哪个核心模型 # 期待效果 按照文档里的内容来答
文档里提到的作者是谁 # 期待效果 文本里并没有,所以应该回答文档里没有提到
文档里有没有说李彦宏是谁 # 期待效果 文本里并没有,所以应该回答文档里没有提到
我想搭建一个 AI 应用,这个平台能帮我吗 # 期待效果 文档里并没有,但是它可以智能的答出来
实测输出结果和预期基本一致,成功。
SimpleDirectoryReader
读取整个文件夹
代码:
python
from llama_index.core import SimpleDirectoryReader
# 读取 ./data 目录下所有支持的文件
documents = SimpleDirectoryReader(input_dir="./data").load_data()
读取单个或指定多个文件
python
# 只读取这一个文件
documents = SimpleDirectoryReader(
input_files=["./data/only_this_file.pdf"]
).load_data()
# 或者读取多个指定的文件
documents = SimpleDirectoryReader(
input_files=["./data/a.txt", "./data/b.docx"]
).load_data()
读取文件夹(包含子目录)
python
documents = SimpleDirectoryReader(
input_dir="./data",
recursive=True # 开启递归,连子文件夹里的文件也读出来
).load_data()
只读特定格式或排除特定文件
这个示例,既包含需要的格式,也包含排除的格式:
python
documents = SimpleDirectoryReader(
input_dir="./data",
required_exts=[".pdf"], # 只要 PDF 文件,其他的忽略
exclude=["./data/ignore_me.txt"] # 排除这个文件
).load_data()
VectorStoreIndex
VectorStoreIndex 的方法主要围绕创建、检索和管理 这三个环节。
它是与知识库沟通的总枢纽,从数据的入库、查询、更新,几乎所有核心的操作都离不开它。
创建
VectorStoreIndex.from_documents(documents, ...)
这是最常用、最便捷的方法。你只需要把加载好的文档列表传给它,它就会自动完成文档切分、向量化和索引构建的全过程。
VectorStoreIndex(nodes, ...)
如果你需要对索引过程进行更精细的控制,比如手动定义和预处理每一个文本块(Node),就可以先创建好 Node 列表,然后通过这个构造函数直接创建索引。
根据textNode进行创建
例如这里就是先定义了根据nodes创建,然后再往里面添加数据。
代码:
python
import os
from llama_index.core import VectorStoreIndex, Settings
from llama_index.core.schema import TextNode
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.dashscope import DashScopeEmbedding
def main():
print("🚀 正在初始化阿里云百炼环境...")
# --- 1. 配置 API Key ---
# 建议先在终端运行: export DASHSCOPE_API_KEY="sk-你的KEY"
# 如果没有环境变量,代码会尝试使用下面的占位符(记得替换!)
API_KEY = os.getenv("DASHSCOPE_API_KEY", "sk-这里替换成你的真实KEY")
if "这里替换" in API_KEY:
print("⚠️ 警告:请记得在代码中填入真实的 DASHSCOPE_API_KEY!")
# --- 2. 配置 LLM (大语言模型) ---
# 用于最后的回答生成
llm = DashScope(model_name="qwen-plus", api_key=API_KEY)
# --- 3. 配置 Embedding (向量化模型) ---
# 【关键】用于将 TextNode 的文本转化为向量
# 阿里云百炼常用的 embedding 模型是 text-embedding-v1 或 v2
embed_model = DashScopeEmbedding(model_name="text-embedding-v2", api_key=API_KEY)
# --- 4. 全局应用配置 (可选但推荐) ---
# 这样后面创建索引时,不需要每次都传 llm 和 embed_model
Settings.llm = llm
Settings.embed_model = embed_model
print("✅ 模型配置完成!\n")
# --- 5. 手动构建 TextNode 列表 ---
print("🧱 正在构建手动数据...")
node_list = []
node_1 = TextNode(
text="LlamaIndex 是一个用于构建 RAG 应用的框架,它能连接你的私有数据和大模型。",
metadata={"来源": "技术文档", "标签": "定义"}
)
node_list.append(node_1)
node_2 = TextNode(
text="阿里云百炼提供了通义千问系列模型,包括 qwen-turbo, qwen-plus 和 qwen-max。",
metadata={"来源": "阿里云官网", "标签": "产品介绍"}
)
node_list.append(node_2)
node_3 = TextNode(
text="DashScopeEmbedding 是 LlamaIndex 中用于调用阿里云 Embedding API 的类。",
metadata={"来源": "开发文档", "标签": "API说明"}
)
node_list.append(node_3)
# --- 6. 基于 Node 创建索引 ---
print("⚙️ 正在调用阿里云 API 计算向量并构建索引...")
# 因为上面配置了 Settings,这里直接传 nodes 即可
index = VectorStoreIndex(nodes=node_list)
# --- 7. 查询验证 ---
query_engine = index.as_query_engine()
print("\n" + "=" * 30)
response = query_engine.query("阿里云百炼提供了哪些模型?")
print(f"❓ 问题: 阿里云百炼提供了哪些模型?")
print(f"🤖 回答: {response}")
print("=" * 30)
# 打印参考来源,确认检索到了 node_2
print("\n🔍 参考来源节点:")
for node in response.source_nodes:
print(f"- {node.node.text[:50]}... (元数据: {node.node.metadata})")
if __name__ == "__main__":
main()
检索
主要有两种:
index.as_query_engine()
这是最常用的方法。它会返回一个查询引擎,你直接调用 query_engine.query("你的问题") 就能获得一个完整的答案。这个引擎内部封装了"检索-增强-生成"(RAG)的完整流程。
index.as_retriever()
这个方法返回一个检索器。它只负责"检索",即根据问题找到最相关的文本块(Node),但不负责生成最终答案。当你需要更灵活地处理检索结果时(例如,先检索再自己拼接提示词),就会用到它。
管理
index.insert(document)
当你有新文档加入时,不需要重建整个索引,可以直接用这个方法将新文档插入到现有索引中。
index.delete(ref_doc_id)
当某个文档过期或需要删除时,可以通过这个方法将其从索引中移除。
index.refresh(ref_doc_id)
如果某个源文档的内容被更新了,可以用这个方法刷新索引中对应的部分。
总而言之,VectorStoreIndex 是你与知识库交互的总枢纽,从数据的"入库"到"查询"再到"更新",几乎所有核心操作都围绕着它展开。
settings
在 LlamaIndex 中,Settings 是一个全局单例对象,相当于整个应用的"总控制台"。通过配置它,你可以避免在每个函数里重复传递参数。
python
import os
from llama_index.core import Settings
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.dashscope import DashScopeEmbedding
from llama_index.core.node_parser import SentenceSplitter
# 1. LLM 配置 (大脑)
# 负责生成回答、理解语义
Settings.llm = DashScope(
model_name="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 2. Embedding Model 配置 (翻译官)
# 负责将文本转化为向量,用于检索
Settings.embed_model = DashScopeEmbedding(
model_name="text-embedding-v2",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 3. 文本切分配置 (工匠)
# 控制文档如何被切成小块 (Nodes)
# chunk_size: 每个块的大小 (一般 512-1024)
# chunk_overlap: 块之间的重叠部分 (保持上下文连贯,一般设为 chunk_size 的 10%-20%)
Settings.text_splitter = SentenceSplitter(
chunk_size=1024,
chunk_overlap=20
)
# 4. 上下文窗口配置 (记忆容量)
# 告诉 LlamaIndex 你的模型最多能"读"多少字
# qwen-plus 通常支持 32k 或更长,这里设置一个保守值防止报错
Settings.context_window = 4096
# 5. 其他高级参数
# Settings.num_output = 512 # 限制模型生成的最大长度
# Settings.callback_manager = ... # 用于日志监控或 Token 统计
settings常见参数说明
| 参数名 | 作用 | 推荐值 (阿里云百炼) | 说明 |
|---|---|---|---|
llm |
指定大模型 | DashScope(model_name="qwen-plus") |
决定回答的质量。 |
embed_model |
指定向量化模型 | DashScopeEmbedding(model_name="text-embedding-v2") |
必须配置,否则默认走 OpenAI 会报错。 |
text_splitter |
指定切分规则 | SentenceSplitter(chunk_size=1024, chunk_overlap=20) |
决定检索的颗粒度。太小丢失语义,太大检索不精准。 |
context_window |
上下文窗口大小 | 4096 或 8192 |
防止检索回来的内容太多,超过了模型的承受能力。 |
num_output |
最大生成长度 | 512 |
限制回答的长度,防止模型啰嗦。 |