
文档分段
当LlamaIndex加载一份文档后,首先需要对文档进行分段。之所以要进行分段,核心目的就是将长文档变成文档片段,进而检索出与提示词关联度较高的片段用于大模型对话处理。以下代码可以查看文档的分段数据。
如果使用MarkdownReader()来读取MD文件,(LlamaIndex)则分段时会按照MD文档中的章节结构来进行分段,每一段就是一个章节的内容。而如果读取的是PDF文件,则分段时会优先按照每页一段进行拆分。分段策略是RAG中非常关键的环节,如果分段效果不好,则将无法获取关联度较高的信息,甚至导致最后大模型答非所问。
from llama_index.core import SimpleDirectoryReader# ---------- 读取所有 PDF ----------pdf_docs = SimpleDirectoryReader(input_dir="./static/docs",required_exts=[".pdf"]).load_data()# ---------- 读取所有 Markdown ----------md_docs = SimpleDirectoryReader(input_dir="./static/docs",required_exts=[".md", ".markdown"]).load_data()# print(f"PDF 数量:{len(pdf_docs)}")print(f"Markdown 数量:{len(md_docs)}")for document in md_docs:print(document.get_content())print("====================")for document in pdf_docs:print(document.get_content())print("====================")

创建索引
通过Settings指定为Ollama词嵌入模型
index = VectorStoreIndex.from_documents(documents)# 将向量持久化保存到dbstore目录中,并设置索引ID为'uncle_tuu'# 后续可以通过索引编号来对索引进行过滤,以指定更小范围的内容进行检索index.set_index_id("uncle_tuu")# 将索引持久化保持到 /dbstore/uncle_tuu 目录中index.storage_context.persist(persist_dir="./dbstore/uncle_tuu")

文档检索
from dotenv import load_dotenvimport osfrom llama_index.core import Settingsfrom llama_index.embeddings.ollama import OllamaEmbeddingfrom llama_index.core import StorageContextfrom llama_index.core import load_index_from_storageload_dotenv()ollama_url = os.getenv("OLLAMA_BASE_URL") #http://localhost:11434# 通过Settings来配置词嵌入模型,此处使用Ollama的qwen3:8bSettings.embed_model = OllamaEmbedding(model_name="bge-m3:latest",ollama_url=ollama_url,)# 从指定的目录中加载索引和文档内容storage_context = StorageContext.from_defaults(persist_dir="./dbstore/uncle_tuu")# 参数index_id为可选性,若不指定该参数,则加载整个目录下的索引文件index = load_index_from_storage(storage_context, index_id="uncle_tuu")# index.as_retriever()函数只检查结果,无大模型参与回答,默认情况下会检索出两个相似度最高的文档片段retriever = index.as_retriever()# 通过retriever.retrieve()函数获取检索结果# results = retriever.retrieve("乔峰是谁?")# 可以通过设置similarity_top_k参数来控制返回的相似度最高的文档片段数量retriever = index.as_retriever(similarity_top_k=3)results = retriever.retrieve("南慕容打赢过谁?")for result in results:print(result.text +"\n\n\n")
另外,特别补充讲解一下index.as_retriever()和index.as_query_engine()函数,两者均接收参数similarity_top_k。但是index.as_retriever()函数只负责检索文档片段,不做其他处理。而index.as_query_engine()函数既可以检索,又可以根据Settings.llm所指定的对话模型,将检索出的文档片段配合用户提问作为提示词交由对话模型进行回答
夜雨聆风