LlamaIndex 面试八股文 · 100题
面向大厂 AI / 大模型 / RAG 工程师岗位,覆盖 LlamaIndex 核心概念、组件原理、源码机制、生产实践,配套 Python 代码示例、对比表格与速记清单。
信息来源:LlamaIndex 官方文档(v0.10+/v0.12+/v0.13+)、CSDN/掘金/腾讯云开发者社区面经、daily.dev 招聘指南、RAGAs / DeepEval 官方文档、知乎/今日头条高频问答等。
标注说明:⭐ 为高频必考,🔥 为加分项/趋势题;
🔥 大厂JD重点为大厂 JD 明确要求的技能点。
一、基础概念(Q1 - Q8)
Q1. ⭐ 什么是 LlamaIndex?它的核心定位和"口号"是什么?
难度:入门
参考答案:
LlamaIndex(早期名 GPT Index)是一个面向上下文增强 LLM 应用(Context-Augmented LLM Applications)的数据框架。它把"私有/领域数据"和"大模型"之间的桥搭起来,本质是专门为 RAG 场景设计的数据层。
- 官方口号:“为你的数据提供 LLM 接口”(A data framework for your LLM application)
- 核心价值:
- 简化数据接入:支持 100+ 数据源(PDF、Word、Markdown、Notion、Slack、数据库、API 等)
- 多索引策略:向量索引、列表索引、树索引、关键字索引、属性图索引,按数据特点选型
- 高级检索:混合检索、重排序、递归检索、自动合并检索等开箱即用
- Agent 工具化:可把 Query Engine 包装成 Tool 接入 Agent / Workflow
- 解决痛点:大模型不知道企业私域知识。RAG(检索增强生成)是性价比最高的解决方案——不重训模型,而是把相关上下文动态喂给 LLM。
来源:LlamaIndex 官方文档 https://docs.llamaindex.ai ;《面试题:LlamaIndex 全栈解析》http://m.toutiao.com/group/7641169856452166153/
Q2. ⭐ LlamaIndex 和 LangChain 有什么区别?真实项目里怎么选?
难度:入门
参考答案:
| 特性 | LlamaIndex | LangChain |
|---|---|---|
| 焦点 | 数据连接与检索(RAG 专家) | 应用编排与 Agent(通用框架) |
| 核心功能 | 数据索引、高级查询、结构化数据提取 | Chain、Agent、Tool、Memory 管理 |
| 设计哲学 | 提供开箱即用的数据管道,封装度高 | 提供高度灵活、可组合的底层组件 |
| 学习曲线 | 简单,3 行代码可起 RAG | 较陡,抽象层多 |
| 关系 | 可作为 LangChain 的一个组件(LlamaIndexRetriever) |
包含并集成多种检索方式 |
| 生态 | LlamaHub(Reader 库)、LlamaParse(高级文档解析) | LangSmith(追踪)、LangServe(部署) |
选型建议:
- 纯 RAG 知识库问答 → LlamaIndex 优先,检索组件更专业
- 复杂多步 Agent、Tool 编排、工作流 → LangChain 优先
- 真实生产里经常组合使用:LlamaIndex 做数据/检索,LangGraph 做流程/状态
来源:《AI 大模型面试题解析之 LangChain & LlamaIndex》https://blog.csdn.net/m0_59614665/article/details/152085484
Q3. ⭐ LlamaIndex 的核心组件有哪些?Data Framework 包含哪几层?
难度:入门
参考答案:
LlamaIndex 体系自下而上分为 5 层:
- Data Connectors(Reader/Loader):把 PDF/Word/Notion/DB 等异构数据读入为
Document对象 - Data Indexes(Index):把
Document切成Node,再按选定策略构建索引结构(向量/列表/树/图) - Query Engines / Chat Engines:对外提供查询接口,返回自然语言答案
- Agents / Workflows:把 Query Engine 包装成 Tool,让 LLM 自动决策调用
- Observability / Evaluators:回调埋点、Token 统计、检索/生成质量评估
核心数据对象:
Document:原始文档对象,含text和metadataNode:从 Document 切出的可检索单元,最小知识块NodeWithScore:Node + 相似度得分(检索器返回类型)QueryBundle:封装查询字符串及其转换
来源:LlamaIndex 官方文档;CSDN《深入理解三大核心组件》https://blog.csdn.net/xiangxi1204/article/details/154834658
Q4. ⭐ Document 和 Node 的区别是什么?
难度:入门
参考答案:
from llama_index.core import Document
from llama_index.core.node_parser import SentenceSplitter
# Document: 原始文档对象
doc = Document(
text="LlamaIndex 是一个 RAG 框架...",
metadata={"file_name": "intro.md", "category": "tech"}
)
# Node: 从 Document 切出的可检索单元
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = splitter.get_nodes_from_documents([doc])
for n in nodes:
print(n.text, n.metadata, n.node_id)
关键区别:
| 维度 | Document | Node |
|---|---|---|
| 定位 | 承载原始数据 | 进入索引和检索的最小单元 |
| 来源 | Reader 读取直接得到 | Document 切分后产生 |
| 元数据 | 含来源、文件名、页码等 | 继承 Document 元数据 + 节点 id、位置 |
| 关系 | 一对多 Document | 可建立 Parent-Child/Prev-Next 关系 |
面试快答:Document 负责承载原始数据,Node 负责进入索引和检索。
来源:今日头条《LlamaIndex 全栈解析》http://m.toutiao.com/group/7641169856452166153/
Q5. ⭐ Retriever 和 Query Engine 的区别是什么?
难度:入门
参考答案:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(documents)
# Retriever: 只负责找资料,返回 NodeWithScore 列表
retriever = index.as_retriever(similarity_top_k=3)
nodes = retriever.retrieve("什么是 RAG?")
for n in nodes:
print(f"score={n.score:.3f} | {n.node.text[:80]}")
# Query Engine: 完整问答引擎,找资料+重排+生成
query_engine = index.as_query_engine(similarity_top_k=3)
response = query_engine.query("什么是 RAG?")
print(response)
print(response.source_nodes) # 溯源节点
核心区别:
- Retriever:检索器(I/O),输入 query,输出
List[NodeWithScore] - Query Engine:完整问答引擎(Pipeline),输入 query,输出
Response对象(含答案 + source_nodes)
Query Engine 内部组成:Retriever + Node Postprocessor + Response Synthesizer。
来源:腾讯云《LlamaIndex RAG 系统工作流程详解》https://cloud.tencent.com/developer/article/2629911
Q6. ⭐ LlamaIndex 安装和包结构是怎样的?v0.10+ 有什么重要变更?
难度:入门
参考答案:
# v0.10+ 拆分式安装
pip install llama-index-core # 核心
pip install llama-index-llms-openai # OpenAI LLM
pip install llama-index-embeddings-openai # OpenAI Embedding
pip install llama-index-vector-stores-chroma # 向量库
pip install llama-index-readers-file # 文件 Reader
# 一键全装
pip install llama-index[all]
v0.10+ 重大变更(2024年发布):
- 拆包:核心(
llama-index-core)与各类集成(llama-index-llms-*、llama-index-vector-stores-*等)独立 - ServiceContext 弃用 → 改用全局
Settings - AgentRunner/AgentWorker 弃用 → 改用
AgentWorkflow+Workflows(事件驱动) - GPTSimpleVectorIndex 改名 →
VectorStoreIndex - 提供 legacy 兼容包:
from llama_index.legacy import ...兜底 - CLI 工具:
llamaindex-cli upgrade-file <file_path>自动迁移
v0.12+/v0.13+ 进一步变化:
- Settings 全面替代 ServiceContext,移除
service_context=参数 - 强化 Workflows(事件驱动,支持 Human-in-the-Loop 暂停恢复)
- LCEL 兼容,RouterQueryEngine 成为标准
来源:LlamaIndex 官方迁移文档 https://developers.llamaindex.ai/python/framework/changes/deprecated_terms/
Q7. LlamaIndex 适合哪些场景?哪些场景不推荐?
难度:入门
参考答案:
✅ 适合:
- 企业知识库 / 制度问答 / 客服机器人
- 文档检索(合同、产品手册、技术白皮书)
- 多模态 RAG(图搜图、PDF 图表理解)
- Graph RAG(实体关系推理:金融风控、医疗、法律)
- Agent 工具化(把不同知识库包装成 Tool 让 Agent 选择)
❌ 不推荐:
- 纯聊天 / 闲聊场景(用 LLM 本身即可)
- 高频写入、低频查询的 OLTP 系统
- 强事务、强一致性的业务(向量库不是事务型存储)
- 数据量极小(< 10 文档)——索引开销大于收益
经验法则:70% 的工作应该是数据质量(清洗、切片、metadata),而不是框架本身。框架只是工具,瓶颈在数据。
来源:daily.dev Hiring Guide https://recruiter.daily.dev/stacks/llamaindex/
Q8. LlamaIndex 最新版本(v0.12+/v0.13+)引入了哪些新特性?
难度:中级
参考答案:
核心新特性:
- Workflows 1.0 正式版(2025年6月发布):事件驱动框架,支持异步/并发/Human-in-the-Loop
- AgentWorkflow:基于 Workflows 的多 Agent 协作框架,支持 handoff
- PropertyGraphIndex 成熟化:替代旧的 KnowledgeGraphIndex,成为图索引首选
- 增强的多模态:LlamaParse + Multi-Modal Index 一键启用图文混合检索
- OpenTelemetry 原生支持:可观测性大幅提升
- Workflows 状态持久化:支持暂停-恢复,适合长任务/异步人工审批
废弃清单(必记):
ServiceContext→SettingsAgentRunner/AgentWorker→AgentWorkflowQueryPipeline→WorkflowsGPTSimpleVectorIndex→VectorStoreIndexLLMPredictor→ 直接用LLM类PromptHelper→ 拆分到Settings
来源:LlamaIndex Breaking Changes https://theneuralbase.com/llamaindex-advanced/learn/beginner/version-upgrade-breaking-changes/
二、数据加载与处理(Q9 - Q18)
Q9. ⭐ LlamaIndex 怎么加载本地文件?SimpleDirectoryReader 的常见用法?
难度:入门
参考答案:
from llama_index.core import SimpleDirectoryReader
# 1. 加载整个目录(自动识别格式)
docs = SimpleDirectoryReader(input_dir="./data").load_data()
# 2. 递归加载子目录
docs = SimpleDirectoryReader(input_dir="./data", recursive=True).load_data()
# 3. 加载指定文件
docs = SimpleDirectoryReader(
input_files=["a.pdf", "b.docx", "c.md"]
).load_data()
# 4. 限制扩展名 + 文件数
docs = SimpleDirectoryReader(
input_dir="./data",
required_exts=[".pdf", ".docx"],
num_files_limit=100
).load_data()
# 5. 并行加载(Linux/Mac 才有收益)
docs = SimpleDirectoryReader(
input_dir="./data",
recursive=True
).load_data(num_workers=4)
默认支持的格式(无需额外依赖):.csv .docx .epub .hwp .ipynb .jpeg/.jpg .mbox .md .mp3/.mp4 .pdf .png .ppt/.pptx 等。
生产坑点:
- 默认 UTF-8 编码,非 UTF-8 文件需传
encoding="latin-1" - 解析失败默认静默跳过,必须用
assert len(docs) == expected校验 - 大目录加载完立即设
doc.metadata["source_id"],否则后续需全量重索引
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/module_guides/loading/simpledirectory_reader/
Q10. ⭐ 怎么加载 PDF?PDF Reader 怎么选?
难度:中级
参考答案:
# 方案1: PyPDFReader (轻量,文本型 PDF)
from llama_index.readers.file import PyPDFReader
reader = PyPDFReader()
docs = reader.load_data(file="./paper.pdf")
# 方案2: PyMuPDFReader (速度快,支持扫描件) — 推荐
from llama_index.readers.file import PyMuPDFReader
reader = PyMuPDFReader()
docs = reader.load_data(file="./paper.pdf")
# 方案3: 在 SimpleDirectoryReader 中按需指定
from llama_index.core import SimpleDirectoryReader
from llama_index.readers.file import PDFReader
file_extractor = {".pdf": PDFReader()}
docs = SimpleDirectoryReader(
"./data", file_extractor=file_extractor
).load_data()
选型建议:
| Reader | 适用场景 | 性能 | 表格识别 |
|---|---|---|---|
PDFReader |
普通文本 PDF | 中 | 弱 |
PyPDFReader |
简单 PDF | 中 | 弱 |
PyMuPDFReader |
复杂 PDF / 扫描件 | 快 | 中 |
LlamaParse (云) |
高精度生产(图表、公式) | 慢但准 | 强 |
生产实践:复杂 PDF(年报、研报、技术白皮书)用 LlamaParse 云服务或 MinerU 等专业解析器,普通 PDF 用 PyMuPDFReader 即可。
来源:llama-index-readers-file 0.6.0 https://pypi.org/project/llama-index-readers-file/
Q11. ⭐ 文档切分(Chunking)为什么重要?有哪些策略?
难度:中级
参考答案:
为什么重要:
- LLM 有上下文窗口限制,必须切块
- 切片质量直接决定检索精度——块太大含噪声,太小丢上下文
- 合理 overlap 避免句子割裂
策略对比:
| 策略 | 原理 | 适用场景 |
|---|---|---|
| TokenTextSplitter | 按 token 数切 | 通用 |
| SentenceSplitter | 按句子+token 边界切 | 最常用,默认推荐 |
| RecursiveCharacterTextSplitter | 递归尝试不同分隔符(\n\n→\n→.) |
通用(来自 LangChain) |
| SemanticSplitter | 用嵌入相似度在语义变化处切 | 高质量但慢 |
| MarkdownNodeParser | 按 Markdown 标题/层级切 | Markdown 文档 |
| CodeNodeParser | 按代码函数/类切 | 代码库 |
| SentenceWindowNodeParser | 切句子+保留窗口 | Small-to-Big 检索 |
推荐默认:SentenceSplitter(chunk_size=512, chunk_overlap=50),根据业务评估调整。
来源:CSDN《LlamaIndex 高级使用》https://www.cnblogs.com/shouyin/p/19493867
Q12. ⭐ chunk_size 和 chunk_overlap 怎么设?调优方法是什么?
难度:中级
参考答案:
经验值:
- chunk_size:通用 512;技术文档 256-512;长文本总结 1024-2048
- chunk_overlap:通常 10%-20% 的 chunk_size(50-100 tokens)
调优方法(重要):
- 建评估集:准备 50-100 个真实问题+人工标注的标准答案
- 扫参:从 (256, 25)、(512, 50)、(1024, 100) 起步
- 看检索指标:Hit Rate、MRR、NDCG@K
- 看生成指标:Faithfulness、Answer Relevancy
- 看 Badcase:是召回少、噪声多、还是上下文不全
判断准则:
- 召回率低 → 加大 chunk_size + overlap,或加元数据
- 噪声多 → 减小 chunk_size,或加 Rerank
- 上下文不全 → 改用 Small-to-Big / Auto-Merging
来源:daily.dev Hiring Guide《Questions That Reveal Expertise》https://recruiter.daily.dev/stacks/llamaindex/
Q13. ⭐ SentenceSplitter 和 TokenTextSplitter 怎么选?
难度:中级
参考答案:
from llama_index.core.node_parser import SentenceSplitter, TokenTextSplitter
# 1. SentenceSplitter (推荐): 按句子边界切,再按 token 切
splitter = SentenceSplitter(
chunk_size=512,
chunk_overlap=50,
paragraph_separator="\n\n\n",
tokenizer=tiktoken.encoding_for_model("gpt-4").encode
)
# 2. TokenTextSplitter: 严格按 token 切,可能切到句子中间
splitter = TokenTextSplitter(
chunk_size=512,
chunk_overlap=50,
separator=" "
)
核心区别:
SentenceSplitter:感知句子边界,避免把一个句子切两半TokenTextSplitter:严格按 token 切,速度快但可能破坏语义SentenceSplitter是 LlamaIndex 默认推荐,对绝大多数场景更友好
坑点:中文场景 tiktoken 不准,建议用 SentenceSplitter 配合自定义分词器,或换 jieba 分句。
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q14. ⭐ Document 的 metadata 怎么设计?为什么重要?
难度:中级
参考答案:
必须设计的 metadata 字段:
doc = Document(
text=content,
metadata={
# 1. 来源追溯
"source": "合同库",
"file_name": "服务协议_2024.pdf",
"file_path": "/data/contracts/...",
"page": 5,
# 2. 业务分类
"category": "服务合同",
"department": "商务部",
# 3. 权限控制
"permission_level": "L2", # 后续做 metadata filter
# 4. 时效性
"created_at": "2024-01-15",
"effective_date": "2024-02-01",
"expire_at": "2025-12-31",
"version": "v2.1",
# 5. 文档结构
"heading_path": "第三章 违约责任 > 第二节 违约金",
# 6. 业务标签
"tags": ["SLA", "违约金", "高优先级"]
}
)
为什么重要:
- 溯源:可解释性 + 合规审计
- 权限过滤:metadata filter 避免越权召回
- 时效控制:过期文档自动过滤
- 检索增强:用户问"2024年的合同"可以直接用时间字段过滤
- 避免重索引:metadata 可以在 indexing 之后修改而不重算 embedding
生产铁律:metadata 必须在 load_data 之后立刻注入,否则要全量重索引。
来源:今日头条《LlamaIndex 全栈解析》http://m.toutiao.com/group/7641169856452166153/
Q15. Transformations(Ingestion Pipeline)是什么?生产中怎么用?
难度:中级
参考答案:
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.extractors import (
TitleExtractor,
SummaryExtractor,
QuestionsAnsweredExtractor,
)
from llama_index.core import Settings
# 1. 定义 Pipeline
pipeline = IngestionPipeline(
transformations=[
SentenceSplitter(chunk_size=512, chunk_overlap=50), # 切分
TitleExtractor(nodes=5), # 抽取小标题
SummaryExtractor(summaries=["self"]), # 摘要
QuestionsAnsweredExtractor(questions=3), # 抽取假设问题
]
)
# 2. 跑 Pipeline
nodes = pipeline.run(documents=documents)
# 3. 带缓存的 Pipeline(生产必备)
pipeline_with_cache = IngestionPipeline(
transformations=[...],
cache=True, # 避免重复跑
)
生产价值:
- 解耦:切分、metadata 抽取、嵌入、存储各步骤可独立配置
- 缓存:相同输入不重跑,省 token
- 可观测:每步都有 callback 埋点
- 可组合:可以加自定义 TransformComponent
来源:LlamaIndex 官方 Ingestion Pipeline 文档
Q16. LlamaIndex 怎么加载数据库 / API / Notion / Slack 数据?
难度:中级
参考答案:
LlamaIndex 通过 LlamaHub(llama-hub.com)提供 100+ 数据源 Reader,常见的:
| 数据源 | Reader |
|---|---|
| Notion | NotionPageReader |
| Slack | SlackReader |
| Discord | DiscordReader |
| GitHub | GithubRepositoryReader |
| PostgreSQL | DatabaseReader |
| MongoDB | MongoDBReader |
| Web | SimpleWebPageReader、BeautifulSoupWebReader |
| YouTube | YoutubeTranscriptReader |
| Twitter/X | TwitterTweetReader |
| Gmail | GmailReader |
# 示例:加载 Notion
from llama_index.readers.notion import NotionPageReader
reader = NotionPageReader(integration_token="...")
docs = reader.load_data(page_ids=["..."])
生产建议:
- Web 抓取一定要加 User-Agent 头
- 定期同步任务用 IngestionPipeline + 缓存 避免重复消耗
- API 类 Reader 做好限流和重试
来源:LlamaHub https://llamahub.ai
Q17. ⭐ 怎么处理复杂文档(PDF 表格、扫描件、多栏)?
难度:高级
参考答案:
核心难点:常规 PDF 解析器把表格打碎、扫描件无文字、栏间错位。
解决方案:
-
专业解析器:
LlamaParse(LlamaIndex 官方云服务,AI 增强,最推荐)MinerU(开源,PDF/扫描件/公式支持强)Unstructured.io(开源,layout 感知)
-
OCR:扫描件需先 OCR(
pytesseract、PaddleOCR) -
视觉模型兜底:表格用 GPT-4V / Qwen-VL 直接看图
-
多模态索引:LlamaParse + Multi-Modal Indexing 一键启用图文混合检索
# LlamaParse 示例
from llama_parse import LlamaParse
parser = LlamaParse(
api_key="llx-...",
result_type="markdown", # 或 "text"
parsing_instruction="保留表格结构和数学公式"
)
docs = parser.load_data("./complex.pdf")
生产经验:70% RAG 失败是文档解析问题,不是模型问题。
来源:CSDN《Llama-Index 七大企业级落地场景实战》https://blog.csdn.net/fufan_llm/article/details/156057698
Q18. Ingestion Pipeline 的缓存机制怎么用?
难度:中级
参考答案:
from llama_index.core.ingestion import IngestionPipeline, DocstoreStrategy
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core import StorageContext, SimpleDocumentStore
# 1. 初始化带 cache 的 pipeline(默认基于输入 hash)
pipeline = IngestionPipeline(
transformations=[SentenceSplitter(chunk_size=512)],
cache=True # 默认 SimpleCache
)
# 2. 用 docstore 配合去重(生产推荐)
docstore = SimpleDocumentStore()
pipeline = IngestionPipeline(
transformations=[SentenceSplitter()],
docstore=docstore,
docstore_strategy=DocstoreStrategy.UPSERTS, # 增量更新
)
# 3. 跑一次,后续相同文件跳过
nodes = pipeline.run(documents=docs)
nodes2 = pipeline.run(documents=docs) # 命中缓存,不重跑
三种 DocstoreStrategy:
DUPLICATES_ONLY:跳过重复UPSERTS:增量更新(生产推荐)UPSERTS_AND_DELETE:完全同步(删除源中已不存在的)
生产价值:100 万 PDF 切分可能跑 24 小时,开启缓存后增量更新只跑新文件,几分钟搞定。
来源:LlamaIndex 官方 https://docs.llamaindex.ai
三、核心组件(Q19 - Q30)
Q19. ⭐ Index 是什么?LlamaIndex 支持哪几种索引类型?
难度:入门
参考答案:
Index 是 LlamaIndex 中"组织 Node 让 LLM 高效查询"的数据结构。
官方支持的索引类型:
| 索引类型 | 核心思路 | 适用场景 |
|---|---|---|
VectorStoreIndex |
Node → Embedding → 向量库,相似度检索 | 最常用,通用 RAG |
SummaryIndex(原 ListIndex) |
Node 顺序链,遍历/汇总 | 小规模总结、扫描全文 |
TreeIndex |
层级树,从根到叶遍历 | 长文档摘要 |
KeywordTableIndex |
提取关键词 → 映射 Node | 关键词检索 |
PropertyGraphIndex |
知识图谱(实体+关系+属性) | 多跳推理、Graph RAG |
MultiModalVectorStoreIndex |
文本+图像多模态向量库 | 图文混排 |
DocumentSummaryIndex |
文档级摘要 | 大规模文档 |
选型决策树:
- 默认场景 →
VectorStoreIndex - 跨文档总结 →
SummaryIndex或TreeIndex - 实体关系强 →
PropertyGraphIndex - 多模态 →
MultiModalVectorStoreIndex - 复杂场景 → RouterQueryEngine 组合多索引
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/module_guides/indexing/lpg_index_guide/
Q20. ⭐ VectorStoreIndex 的工作原理是什么?
难度:中级
参考答案:
工作流程:
-
构建期:
- 遍历 Node,通过 embed_model 把每段 text 转成向量(如 1536 维)
- 把 (Node ID → 向量 → Node metadata) 存到 VectorStore
- 原始 Node 存到 DocStore
-
查询期:
- 用户 query 用相同 embed_model 转向量
- 用余弦相似度/点积计算与所有 Node 的匹配度
- 返回 Top-K 最相似的 Node
# 完整流程
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
# 1. 加载 + 切分
docs = SimpleDirectoryReader("./data").load_data()
nodes = SentenceSplitter(chunk_size=512).get_nodes_from_documents(docs)
# 2. 构建索引(内部调 embed_model)
index = VectorStoreIndex(nodes)
# 3. 查询(内部用向量相似度)
retriever = index.as_retriever(similarity_top_k=3)
results = retriever.retrieve("RAG 的核心思想是什么?")
底层依赖:需要一个 BaseEmbedding(默认 OpenAIEmbedding)和一个 VectorStore(默认内存 SimpleVectorStore)。
生产部署:必须把 SimpleVectorStore 替换为生产级向量库(Chroma/Milvus/Qdrant/Weaviate/Pinecone)。
来源:腾讯云《LlamaIndex RAG 工作流程详解》https://cloud.tencent.com/developer/article/2629911
Q21. ⭐ SummaryIndex(原 ListIndex)什么时候用?怎么工作?
难度:中级
参考答案:
核心思路:把 Node 按顺序链接成 list,查询时默认加载所有 Node 给 LLM。适合"通读全文"类任务。
适用场景:
- 文档量小(< 100 节点)
- 总结/摘要/全局理解类问题
- 不需要精确语义检索
- 配合 embedding 检索做 keyword filter
from llama_index.core import SummaryIndex
index = SummaryIndex.from_documents(docs)
query_engine = index.as_retriever(retriever_mode="embedding") # 嵌入检索
# 或
query_engine = index.as_query_engine(response_mode="tree_summarize")
三种检索模式:
default:返回所有 Nodeembedding:embedding 相似度取 top-kllm:用 LLM 迭代筛选
坑点:默认模式把所有 Node 都塞进 prompt,文档一大就爆 token。生产中用 embedding 模式 + tree_summarize。
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q22. ⭐ TreeIndex 是什么?适合什么场景?
难度:中级
参考答案:
TreeIndex 把 Node 构建成一棵层级树(根 → 中间节点 → 叶子)。查询时从根向下遍历。
构造过程:
- 叶子节点是原始 Node
- 每个父节点是其子节点的 LLM 生成摘要
- 一直向上汇总直到根节点
两种查询方式:
child_branch_factor=1:从根选 1 个子节点向下(精确但易漏)child_branch_factor=2:从根选 2 个子节点(覆盖面广)
from llama_index.core import TreeIndex
index = TreeIndex.from_documents(docs, num_children=10)
query_engine = index.as_query_engine(child_branch_factor=2)
适用场景:
- 超长文档(万级以上)
- 摘要、归纳、概览类问题
- 不推荐用于精确问答(检索召回率低)
面试要点:TreeIndex 本质是"用 LLM 调用换 token",构建期 1 个 Node 1 次 LLM 调用,慎用。
来源:LlamaIndex 官方文档
Q23. ⭐ PropertyGraphIndex 和 KnowledgeGraphIndex 有什么区别?v0.10+ 怎么迁移?
难度:高级
参考答案:
核心区别:
| 特性 | PropertyGraphIndex(推荐) | KnowledgeGraphIndex(已弃用) |
|---|---|---|
| 数据模型 | 属性图(节点/边带 KV 属性) | 知识图谱(实体-关系-实体三元组) |
| 属性支持 | 强(节点和边都有) | 弱(主要实体和关系) |
| 关系类型 | 灵活,不强制 | 严格,需预定义 schema |
| 可扩展性 | 强 | 中 |
| 抽取器 | SimpleLLMPathExtractor、ImplicitPathExtractor |
SchemaLLMPathExtractor |
v0.10+ 迁移要点:
- 旧
KnowledgeGraphIndex→ 新PropertyGraphIndex - 旧
SchemaLLMPathExtractor(possible_relations=[...])→ 新SimpleLLMPathExtractor(allowed_relations=[...]) - 默认抽取器:
SimpleLLMPathExtractor+ImplicitPathExtractor
from llama_index.core import PropertyGraphIndex
from llama_index.core.indices.property_graph import (
SimpleLLMPathExtractor, ImplicitPathExtractor
)
index = PropertyGraphIndex.from_documents(
docs,
kg_extractors=[
SimpleLLMPathExtractor(llm=llm, max_paths_per_chunk=10),
ImplicitPathExtractor()
]
)
retriever = index.as_retriever(include_text=True, similarity_top_k=2)
类比:属性图像社交网络(可任意打 tag),知识图谱像族谱(关系类型严格)。
来源:CSDN《属性图索引》https://blog.csdn.net/csdn122345/article/details/155579705
Q24. ⭐ StorageContext 是什么?为什么不能只用一个向量库?
难度:中级
参考答案:
StorageContext 是 LlamaIndex 中管理所有存储组件的"上下文",包含 4 个核心 store:
from llama_index.core import StorageContext
from llama_index.core.vector_stores import SimpleVectorStore
from llama_index.core.storage.docstore import SimpleDocumentStore
from llama_index.core.storage.index_store import SimpleIndexStore
from llama_index.core.graph_stores import SimpleGraphStore
storage_context = StorageContext.from_defaults(
vector_store=SimpleVectorStore(), # 向量
docstore=SimpleDocumentStore(), # 原始 Node
index_store=SimpleIndexStore(), # 索引元数据
graph_store=SimpleGraphStore(), # 图结构
)
index = VectorStoreIndex(nodes, storage_context=storage_context)
index.storage_context.persist(persist_dir="./storage") # 持久化
为什么不能只用一个向量库:
- 向量库只解决相似度搜索,不存原文 / metadata / 图结构
- 生产需要权限过滤、增量更新、文档版本、回滚、审计——这都要完整存储
- 粗暴塞向量库 → 后期无法维护
生产铁律:DocStore 必须持久化原始 Node 文本,否则 response 溯源失效。
来源:今日头条《LlamaIndex 全栈解析》http://m.toutiao.com/group/7641169856452166153/
Q25. ⭐ SentenceWindowNodeParser 是什么?Small-to-Big 检索怎么用?
难度:高级
参考答案:
核心思想:“小索引,大窗口”——用小颗粒(句子级别)做精确检索,输出时自动扩展到大窗口(包含该句子的整个段落),解决"切片小检索准但丢上下文,切片大检索不准但上下文全"的矛盾。
from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core.postprocessor import MetadataReplacementPostProcessor
# 1. 切分(每个 Node 是单个句子,但带 window 上下文)
node_parser = SentenceWindowNodeParser.from_defaults(
window_size=3, # 包含前后各3个句子
)
nodes = node_parser.get_nodes_from_documents(docs)
# 2. 建索引
index = VectorStoreIndex(nodes)
# 3. 检索(按句子相似度)
retriever = index.as_retriever(similarity_top_k=5)
# 4. 关键:检索后用 MetadataReplacementPostProcessor 把句子替换为窗口
postproc = MetadataReplacementPostProcessor(
target_metadata_key="window"
)
query_engine = index.as_query_engine(
similarity_top_k=5,
node_postprocessors=[postproc]
)
response = query_engine.query("...")
生产经验:在高精度 RAG 场景(法律、医疗)效果显著优于普通切片。
来源:CSDN《Llama-Index 高级特性》https://blog.csdn.net/Langchain/article/details/157909040
Q26. ⭐ AutoMergingRetriever 是什么?和 SentenceWindow 有什么区别?
难度:高级
参考答案:
AutoMergingRetriever 同样解决"小切片检索准、大切片上下文全"的矛盾,但思路不同:
工作原理:
- 把文档切分成层级 Node(小 chunk → 中 chunk → 大 chunk),建立父子关系
- 检索时按小 chunk 找
- 如果多个子节点命中同一个父节点,自动合并为父节点输出
- 否则保持子节点
from llama_index.core.node_parser import HierarchicalNodeParser, get_leaf_nodes
from llama_index.core.retrievers import AutoMergingRetriever
# 1. 层级切分
node_parser = HierarchicalNodeParser.from_defaults(
chunk_sizes=[2048, 512, 128] # 父→中→子
)
nodes = node_parser.get_nodes_from_documents(docs)
# 2. 只对叶子节点建索引(细粒度)
index = VectorStoreIndex(get_leaf_nodes(nodes))
index.storage_context.docstore.add_documents(nodes) # 父节点放 docstore
# 3. 检索(自动合并)
retriever = AutoMergingRetriever(
index.as_retriever(similarity_top_k=6),
storage_context=index.storage_context
)
对比 SentenceWindow:
| 维度 | SentenceWindow | AutoMerging |
|---|---|---|
| 切片方式 | 句子 + 固定窗口 | 层级 chunk_sizes |
| 输出策略 | 强制替换为窗口 | 命中阈值才合并 |
| 灵活性 | 中 | 高 |
| 实现复杂度 | 简单 | 较复杂 |
| 适用 | 文档结构均匀 | 文档结构有章节 |
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q27. ⭐ Retriever 有哪些类型?怎么选?
难度:中级
参考答案:
主要 Retriever:
| Retriever | 原理 | 适用 |
|---|---|---|
VectorIndexRetriever |
向量相似度 | 默认 |
BM25Retriever |
BM25 关键词统计 | 关键词精确匹配 |
KeywordTableSimpleRetriever |
关键词表查找 | 简单关键词 |
SentenceWindowRetriever |
句子级 + 窗口 | Small-to-Big |
AutoMergingRetriever |
层级 chunk 合并 | 章节结构化文档 |
MultiVectorRetriever |
同文档多向量 | 一文多角度 |
RecursiveRetriever |
递归检索(小→大) | 引用关系 |
RouterRetriever |
路由到不同子检索器 | 多数据源 |
# 混合检索:BM25 + 向量 + Rerank
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.retrievers.bm25 import BM25Retriever
vector_retriever = index.as_retriever(similarity_top_k=10)
bm25_retriever = BM25Retriever.from_defaults(nodes=nodes, similarity_top_k=10)
# 融合(用 QueryFusionRetriever)
from llama_index.core.retrievers import QueryFusionRetriever
fusion_retriever = QueryFusionRetriever(
retrievers=[vector_retriever, bm25_retriever],
similarity_top_k=5,
num_queries=4, # 自动生成多个 query
mode="reciprocal_rerank" # RRF 融合
)
面试要点:实际生产中混合检索 + Rerank 几乎必用,单纯向量检索召回率有上限。
来源:LlamaIndex 官方文档
Q28. ⭐ Node Postprocessor 是什么?常用后处理器有哪些?
难度:中级
参考答案:
Node Postprocessor 在 Retriever 之后、Response Synthesizer 之前对节点做过滤/重排/增强。
常用后处理器:
from llama_index.core.postprocessor import (
SimilarityPostprocessor, # 相似度阈值过滤
KeywordNodePostprocessor, # 必含/排除关键词
MetadataReplacementPostProcessor, # 窗口替换
SentenceEmbeddingOptimizer, # 句子级精排
CohereRerank, # Cohere Rerank
LongContextReorder, # 长上下文重排
FixedRecencyPostprocessor, # 时效性优先
)
# 1. 相似度过滤
postproc = SimilarityPostprocessor(similarity_cutoff=0.7)
# 2. Rerank(强烈推荐)
from llama_index.postprocessor.cohere_rerank import CohereRerank
rerank = CohereRerank(api_key=cohere_api_key, top_n=5)
# 3. BGE Rerank(开源免费)
from llama_index.postprocessor.bge_rerank import BGERerank
bge = BGERerank(top_n=5, model="BAAI/bge-reranker-large")
# 4. 链式:先过滤 + 再 Rerank
query_engine = index.as_query_engine(
similarity_top_k=10,
node_postprocessors=[
SimilarityPostprocessor(similarity_cutoff=0.6),
bge,
]
)
生产经验:Rerank 是性价比最高的优化(10→5 节点,精度大幅提升,成本只增 1 次小模型调用)。
来源:CSDN《Llama-Index 高级特性》https://blog.csdn.net/Langchain/article/details/157909040
Q29. ⭐ 怎么实现 Rerank?BGE Rerank 怎么用?
难度:中级
参考答案:
Rerank(重排序)是用更强的 Cross-Encoder 模型对初检结果精排,二阶段检索的标准做法。
# 1. BGE Rerank(开源、本地、免费)— 推荐生产
from llama_index.postprocessor.bge_rerank import BGERerank
bge = BGERerank(
model="BAAI/bge-reranker-large", # 或 bge-reranker-base
top_n=5
)
# 2. Cohere Rerank(云端、要钱)
from llama_index.postprocessor.cohere_rerank import CohereRerank
cohere = CohereRerank(api_key="...", top_n=5)
# 3. 接入 Query Engine
query_engine = index.as_query_engine(
similarity_top_k=20, # 粗筛 20
node_postprocessors=[bge] # 精排到 5
)
# 4. 配合元数据过滤
from llama_index.core.postprocessor import MetadataReplacementPostProcessor
sentence_window = MetadataReplacementPostProcessor(target_metadata_key="window")
query_engine = index.as_query_engine(
node_postprocessors=[bge, sentence_window]
)
Rerank 原理:用 Cross-Encoder 把 (query, doc) 一起编码,比向量相似度(Bi-Encoder)精度高但慢。
性能数据:粗排 20 → Rerank 精排 5,NDCG@10 通常能提升 10-30%。
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q30. ⭐ Hybrid Search(混合检索)怎么实现?有什么坑?
难度:高级
参考答案:
核心思路:向量检索(懂语义)+ 关键词检索(懂字面),融合后 Rerank。专治生僻词、专有名词、数字型号。
# 方案1: QueryFusionRetriever(推荐)
from llama_index.core.retrievers import QueryFusionRetriever
from llama_index.retrievers.bm25 import BM25Retriever
vector_retriever = index.as_retriever(similarity_top_k=10)
bm25_retriever = BM25Retriever.from_defaults(nodes=nodes, similarity_top_k=10)
fusion_retriever = QueryFusionRetriever(
retrievers=[vector_retriever, bm25_retriever],
similarity_top_k=5,
num_queries=4, # 用 LLM 生成多 query 变体
mode="reciprocal_rerank", # RRF 融合算法
use_async=True
)
# 方案2: 自定义融合(更灵活)
def hybrid_search(query, k=5):
vector_nodes = vector_retriever.retrieve(query)
bm25_nodes = bm25_retriever.retrieve(query)
# RRF 融合
fused = reciprocal_rerank_fusion([vector_nodes, bm25_nodes])
return fused[:k]
坑点:
- BM25 对中文不友好,需配合 jieba 分词
- num_queries=4 会让 LLM 调用 4 次,慎用
- alpha 参数(向量权重):生僻词场景调低 alpha,通用场景保持 0.7+
- 必须做 Rerank,否则融合效果差
来源:CSDN《Llama-Index 七大企业实战》https://blog.csdn.net/fufan_llm/article/details/156057698
四、QueryEngine 与 ResponseSynthesizer(Q31 - Q40)
Q31. ⭐ QueryEngine 的工作流程是什么?6步走完一遍?
难度:入门
参考答案:
Query Engine 内部 6 步流程:
- 问题向量化:用 embed_model 把 query 转成向量
- 检索相关 Node:调 Retriever 取 Top-K Node
- 后处理:Node Postprocessor 过滤/重排/窗口替换
- Prompt 拼接:把 query + Node 文本拼成 LLM prompt
- 调 LLM 生成:原始回答
- 格式化输出:剔除冗余,返回 Response 对象(含 source_nodes)
手动组装版(看清全流程):
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.core import get_response_synthesizer
from llama_index.core.query_engine import RetrieverQueryEngine
# 1. 检索器
retriever = VectorIndexRetriever(index=index, similarity_top_k=3)
# 2. 合成器
synthesizer = get_response_synthesizer(response_mode="compact")
# 3. 引擎
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=synthesizer
)
关键特性:
- 端到端封装:用户只调
query(),无需关注中间环节 - 可扩展性:Retriever、LLM、Response Mode 均可自定义
- 溯源性:
response.source_nodes可追溯到每个 Node - 异常处理:检索为空时 LLM 会自动 fallback 到通用知识(可配置)
来源:腾讯云《LlamaIndex RAG 系统工作流程详解》https://cloud.tencent.com/developer/article/2629911
Q32. ⭐ response_mode 有哪些?compact / refine / tree_summarize 怎么选?
难度:中级
参考答案:
8 种 response_mode 对比:
| Mode | 原理 | LLM 调用 | 适用场景 |
|---|---|---|---|
| compact (默认) | 把尽可能多 chunk 塞进同一 prompt | 1 次(必要时多轮 refine) | 通用首选 |
| refine | 第 1 个 chunk 生成初稿,后续 chunk 迭代优化 | N 次(每 chunk 1 次) | 详细答案、多角度综合 |
| tree_summarize | 两两合成,再两两合成,树形汇总 | log2(N) 次 | 长文总结、10+ chunk |
| simple_summarize | 一次性截断拼接所有 chunk 直接生成 | 1 次 | 短答案 |
| generation | 不用检索结果,直接 LLM 回答 | 1 次 | 对比测试 |
| no_text | 不调 LLM,只返回 source nodes | 0 次 | 调试检索 |
| accumulate | 每 chunk 单独 LLM 一次,返回 List[Response] | N 次 | 保留各节点独立观点 |
| compact_accumulate | 合并后 accumulate | N 次 | 整合+独立输出 |
# 切换 response_mode
qe = index.as_query_engine(response_mode="tree_summarize")
qe = index.as_query_engine(response_mode="refine")
qe = index.as_query_engine(response_mode="compact")
选型黄金法则:
- 极致细节 → refine
- 平衡效率 → compact(默认)
- 长文总结 → tree_summarize
- 保留观点 → accumulate
- 调试 → no_text
来源:腾讯云《LlamaIndex RAG 详解》https://cloud.tencent.com/developer/article/2629911
Q33. ⭐ tree_summarize 和 refine 的性能成本差多少?
难度:中级
参考答案:
LLM 调用次数对比(10 个 Node 场景):
| Mode | LLM 调用 | Token 成本 | 延迟 |
|---|---|---|---|
| compact | 1-2 次 | 1x | 低 |
| simple_summarize | 1 次 | 1x(但截断风险) | 最低 |
| refine | 10 次 | ~10x | 高 |
| tree_summarize | ~14 次(3层树) | ~14x | 最高 |
| accumulate | 10 次 | ~10x | 高 |
生产经验:
- 默认 compact:大多数场景够用
- 复杂多文档综合:tree_summarize 质量高但贵
- 精确细节:refine,但 token 烧钱
- 成本敏感:simple_summarize,但答案可能不完整
坑点:tree_summarize 在 10+ Node 上比 simple_summarize 贵 10-35 倍,小数据上反而贵不了多少。
来源:theneuralbase https://theneuralbase.com/llamaindex/learn/intermediate/choosing-the-right-synthesizer-for-your-use-case/
Q34. ⭐ Streaming(流式输出)怎么实现?有什么坑?
难度:中级
参考答案:
# 1. 启用流式(需要 LLM 支持 streaming)
from llama_index.core import VectorStoreIndex
query_engine = index.as_query_engine(
streaming=True,
similarity_top_k=3
)
# 2. 调用 query 返回 StreamingResponse
streaming_response = query_engine.query("什么是 RAG?")
# 3. 迭代 token
for text in streaming_response.response_gen:
print(text, end="", flush=True)
# 4. 完整响应(流结束后可用)
print(streaming_response.get_response())
# 5. 或直接 print
streaming_response.print_response_stream()
坑点:
- 必须 LLM 支持:OpenAI / HuggingFace / LangChain LLM 支持;不支持的 LLM 会 raise
NotImplementedError - 多次 LLM 调用只流最后一段:refine 模式下只有最后一轮 stream
- 同步 vs 异步:生产推荐
await query_engine.aquery(...) - SSE 推送到前端:FastAPI 配合
StreamingResponse
生产价值:用户感知延迟降低 2-3x,体感"秒回"。
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/module_guides/deploying/query_engine/streaming/
Q35. ⭐ 如何让 LLM 输出结构化结果(Pydantic / JSON)?
难度:中级
参考答案:
from pydantic import BaseModel, Field
from typing import List
from llama_index.core import get_response_synthesizer
from llama_index.core.query_engine import RetrieverQueryEngine
class PhoneInfo(BaseModel):
name: str = Field(description="手机型号")
description: str = Field(description="型号描述")
features: List[str] = Field(description="主要功能")
# 方案1: 通过 output_cls
synthesizer = get_response_synthesizer(
response_mode="tree_summarize",
output_cls=PhoneInfo
)
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=synthesizer
)
response = query_engine.query("介绍 iPhone 16 Pro")
# response 是结构化对象
print(response.name, response.features)
# 方案2: 通过 Pydantic 风格的 program
from llama_index.core.program import LLMTextCompletionProgram
prompt = """
根据上下文信息提取手机参数:
{context}
"""
program = LLMTextCompletionProgram.from_defaults(
output_cls=PhoneInfo,
prompt_template_str=prompt,
llm=llm
)
result = program(context=context_str)
生产坑点:
- 结构化输出会增加 LLM 调用次数
- Pydantic schema 字段名要清晰,描述要具体
- 配合
structured_answer_filtering=True过滤无关节点
来源:CSDN《LlamaIndex ResponseSynthesizer》https://blog.csdn.net
Q36. ⭐ QueryEngine 的 as_query_engine() 常用参数有哪些?
难度:入门
参考答案:
query_engine = index.as_query_engine(
# 检索参数
similarity_top_k=3, # 向量检索返回 top-k
vector_store_query_mode="default", # default / sparse / hybrid
alpha=0.7, # hybrid 模式下向量权重
filters=MetadataFilters(...), # 元数据过滤
# 响应参数
response_mode="compact", # compact / refine / tree_summarize
text_qa_template=None, # 自定义 QA prompt
refine_template=None, # 自定义 refine prompt
# LLM
llm=llm, # 自定义 LLM
# 流式
streaming=False,
# 调试
verbose=True, # 打印检索过程
# 后处理
node_postprocessors=[bge_rerank], # 节点后处理器
# 回调
callback_manager=CallbackManager([handler])
)
易错点:
similarity_top_k不是全局参数,是 query engine 级别- 改
response_mode不改similarity_top_k不会自动同步
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q37. Query Engine 怎么查不到时强制"我不知道"?
难度:中级
参考答案:
# 方案1: 设置相似度阈值过滤
from llama_index.core.postprocessor import SimilarityPostprocessor
qe = index.as_query_engine(
similarity_top_k=5,
node_postprocessors=[
SimilarityPostprocessor(similarity_cutoff=0.7)
]
)
# 方案2: 自定义 Prompt 强制 LLM 答"不知道"
from llama_index.core import PromptTemplate
qa_prompt = PromptTemplate(
"你是一个严谨的助手。基于以下上下文回答问题。\n"
"如果上下文中没有答案,直接回答'我不知道',不要编造。\n"
"上下文:\n{context_str}\n"
"问题:{query_str}\n"
"答案:"
)
qe = index.as_query_engine(text_qa_template=qa_prompt)
# 方案3: 配合 Faithfulness 评估检测幻觉
生产经验:"我不知道"是 RAG 系统的关键能力,比强行答错要好得多。
来源:CSDN《LlamaIndex 高级使用》https://www.cnblogs.com/shouyin/p/19493867
Q38. ⭐ MultiStepQueryEngine 和 SubQuestionQueryEngine 区别?
难度:高级
参考答案:
SubQuestionQueryEngine:把复杂问题拆成多个子问题,并行检索后汇总。
from llama_index.core.query_engine import SubQuestionQueryEngine
from llama_index.llms.openai import OpenAI
sub_qe = SubQuestionQueryEngine.from_args(
index=index,
llm=OpenAI(model="gpt-4"),
use_async=True, # 并行子问题
)
response = sub_qe.query("比较 LlamaIndex 和 LangChain 在 RAG 实现上的差异")
MultiStepQueryEngine:步骤间可以传递和迭代信息,前一步结果影响下一步问题。
from llama_index.core.query_engine import MultiStepQueryEngine
multi_qe = MultiStepQueryEngine(
query_engine=base_qe,
query_transform=step_decompose_transform
)
对比:
| 维度 | SubQuestionQueryEngine | MultiStepQueryEngine |
|---|---|---|
| 拆解方式 | 一次性拆子问题,并行 | 步骤拆解,串行 |
| 信息流 | 各子问题独立 | 步骤间传递 |
| 适用 | 多角度独立问题 | 多跳推理、需要前步结果 |
| 复杂度 | 中 | 高 |
来源:LlamaIndex 官方文档
Q39. ⭐ RouterQueryEngine 是什么?怎么路由到不同索引?
难度:高级
参考答案:
RouterQueryEngine 是个路由器 + 多个子 Query Engine,根据用户问题自动选择最合适的子引擎。
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector, LLMMultiSelector
from llama_index.core.tools import QueryEngineTool
# 1. 定义子引擎
vector_tool = QueryEngineTool.from_defaults(
query_engine=vector_qe,
name="vector_search",
description="用于语义相似度检索,例如事实查询、概念解释"
)
summary_tool = QueryEngineTool.from_defaults(
query_engine=summary_qe,
name="summary_search",
description="用于文档总结、概览类问题"
)
kg_tool = QueryEngineTool.from_defaults(
query_engine=kg_qe,
name="kg_search",
description="用于实体关系推理,例如'X 和 Y 的关系'"
)
# 2. 路由引擎
router_qe = RouterQueryEngine(
selector=LLMSingleSelector.from_defaults(llm=llm),
query_engine_tools=[vector_tool, summary_tool, kg_tool]
)
response = router_qe.query("总结今年的产品趋势")
两种 Selector:
LLMSingleSelector:选 1 个最合适(默认)LLMMultiSelector:选多个,分别查询后综合
生产经验:RouterQueryEngine 替代了 LangChain 的 LLMChain,是 0.12+ 推荐的路由模式。
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q40. ⭐ 怎么实现 Multi-Document Agent(多文档 Agent 路由)?
难度:高级
参考答案:
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.query_engine import RouterQueryEngine
# 1. 为每个数据源建索引
contract_index = VectorStoreIndex.from_documents(contract_docs)
hr_index = VectorStoreIndex.from_documents(hr_docs)
product_index = VectorStoreIndex.from_documents(product_docs)
# 2. 各自建 QueryEngine
contract_qe = contract_index.as_query_engine(similarity_top_k=3)
hr_qe = hr_index.as_query_engine(similarity_top_k=3)
product_qe = product_index.as_query_engine(similarity_top_k=3)
# 3. 包装成 Tool
contract_tool = QueryEngineTool(
query_engine=contract_qe,
metadata=ToolMetadata(
name="合同库",
description="查询合同条款、违约责任、SLA 条款"
)
)
hr_tool = QueryEngineTool(
query_engine=hr_qe,
metadata=ToolMetadata(
name="HR制度库",
description="查询员工手册、年假、考勤制度"
)
)
product_tool = QueryEngineTool(
query_engine=product_qe,
metadata=ToolMetadata(
name="产品手册库",
description="查询产品参数、功能、使用方法"
)
)
# 4. RouterQueryEngine 整合
multi_doc_qe = RouterQueryEngine.from_defaults(
query_engine_tools=[contract_tool, hr_tool, product_tool]
)
# 5. 复杂查询
response = multi_doc_qe.query("合同里关于员工培训的违约条款是什么?")
生产要点:
- Tool description 写清楚:Selector 依赖 description 判断路由
- description 模糊会导致路由失败:要具体说明适用场景
来源:theneuralbase https://theneuralbase.com/llamaindex-advanced/learn/beginner/version-upgrade-breaking-changes/
五、ChatEngine 与记忆(Q41 - Q47)
Q41. ⭐ ChatEngine 和 QueryEngine 有什么区别?
难度:入门
参考答案:
| 维度 | QueryEngine | ChatEngine |
|---|---|---|
| 核心 | 单次问答(无状态) | 多轮对话(有状态) |
| 历史管理 | 不管 | 自动维护 chat history |
| API | query() |
chat() / stream_chat() |
| 记忆 | 无 | 内置 Memory |
| 底层 | Retriever + Synthesizer | ChatEngine + Memory |
# Query Engine
query_engine = index.as_query_engine()
response = query_engine.query("什么是 RAG?")
# Chat Engine(带记忆)
chat_engine = index.as_chat_engine()
response = chat_engine.chat("什么是 RAG?")
response = chat_engine.chat("它和微调有什么区别?") # 记得上文
什么时候用:
- 单次问答、API 调用 → QueryEngine
- 机器人、对话系统 → ChatEngine
来源:LlamaIndex 官方文档
Q42. ⭐ ChatEngine 有哪几种模式?condense_question / context / react 区别?
难度:中级
参考答案:
4 种 ChatEngine 模式:
| 模式 | 原理 | 适用 |
|---|---|---|
| SimpleChatEngine | LLM 直接聊,不查知识库 | 闲聊 |
| CondenseQuestionChatEngine | 把历史 + 新问题压缩成独立问题,再检索 | 通用对话 |
| ContextChatEngine | 把历史 + 检索结果都喂给 LLM | 强上下文依赖 |
| ReActChatEngine | ReAct 推理 + 工具调用 | 复杂决策 |
# 1. CondenseQuestion(默认)
from llama_index.core.chat_engine import CondenseQuestionChatEngine
chat_engine = CondenseQuestionChatEngine.from_defaults(
query_engine=query_engine,
llm=llm
)
# 2. Context 模式(带 chat history 作为 context)
from llama_index.core.chat_engine import ContextChatEngine
chat_engine = ContextChatEngine.from_defaults(
retriever=retriever,
llm=llm,
chat_memory=memory
)
# 3. ReAct Agent Chat
chat_engine = index.as_chat_engine(chat_mode="react", verbose=True)
选型:
- 简单 Q&A 机器人 → CondenseQuestion
- 强上下文("它"指代上文)→ Context
- 多工具决策 → ReAct
来源:LlamaIndex 官方文档
Q43. ⭐ ChatEngine 怎么管理 ChatMemory?Memory 类型有哪些?
难度:中级
参考答案:
from llama_index.core.memory import (
ChatMemoryBuffer,
VectorMemory,
SimpleComposableMemory
)
# 1. 简单 buffer 记忆
memory = ChatMemoryBuffer.from_defaults(
token_limit=3000, # 控制 token 上限
)
# 2. 注入 ChatEngine
chat_engine = index.as_chat_engine(
chat_mode="condense_question",
memory=memory,
system_prompt="你是一个专业的助手..."
)
# 3. 手动管理
memory.put("user", "你好")
memory.put("assistant", "你好,有什么可以帮你?")
chat_memory = memory.get() # 获取全部
# 4. 自定义 Memory(多个来源组合)
custom_memory = SimpleComposableMemory.from_defaults(
primary_memory=ChatMemoryBuffer.from_defaults(token_limit=2000),
secondary_memory=[VectorMemory.from_defaults(...)]
)
Memory 类型:
ChatMemoryBuffer:FIFO 缓冲,按 token 限制VectorMemory:用向量检索找相关历史SimpleComposableMemory:组合多种 Memory
来源:LlamaIndex 官方文档
Q44. ⭐ 怎么让 ChatEngine 持久化记忆(跨 Session)?
难度:高级
参考答案:
# 方案1: 序列化到文件
import json
from llama_index.core.memory import ChatMemoryBuffer
# 保存
memory = ChatMemoryBuffer.from_defaults(token_limit=3000)
memory.put("user", "你好")
memory_data = {"chat_history": memory.chat_store.get_all()} # 持久化
# 加载
from llama_index.core.llms import ChatMessage
restored = ChatMemoryBuffer.from_defaults(token_limit=3000)
for msg in memory_data["chat_history"]:
restored.put(msg.role, msg.content)
# 方案2: 用外部存储(Redis / DB)
import redis
r = redis.Redis()
r.set(f"chat:{user_id}", json.dumps(memory.chat_store.get_all()))
生产方案:
- Redis:分布式 session,最常用
- PostgreSQL/MySQL:长时记忆,可分析
- 向量库:长期历史检索增强
- 多 Memory 组合:短期 buffer + 长期向量记忆
来源:LlamaIndex 官方 Memory 文档
Q45. ChatEngine 和 Agent 怎么选?
难度:中级
参考答案:
| 维度 | ChatEngine | Agent |
|---|---|---|
| 目标 | 知识库对话 | 自主决策、调用工具 |
| 工具调用 | 不支持 | 支持(Function Call) |
| 推理 | 单轮 | 多轮(ReAct) |
| 适用 | Q&A 机器人 | 复杂任务自动化 |
| 可控性 | 高 | 中(依赖 LLM 决策) |
经验法则:
- 强业务可控性 → ChatEngine(用 Router)
- 灵活但要接受不确定性 → Agent
- 生产首选:ChatEngine + Router + 多个 QueryEngineTool
来源:LlamaIndex 官方
Q46. ⭐ system_prompt 怎么写?有什么模板?
难度:入门
参考答案:
from llama_index.core import PromptTemplate
# 1. 直接传字符串
chat_engine = index.as_chat_engine(
system_prompt="""
你是一个专业的金融知识助手,名叫小金。
规则:
1. 只基于上下文回答,不要编造。
2. 如果不知道,答"未找到相关信息"。
3. 回答不超过 200 字,使用专业语气。
4. 引用时附上文件名。
"""
)
# 2. 用 PromptTemplate 动态注入
prompt_tmpl = PromptTemplate("""
你是 {role},名叫 {name}。
当前用户:{user_name}
上下文:{context_str}
问题:{query_str}
""")
query_engine.update_prompts({"response_synthesizer:text_qa_template": prompt_tmpl})
# 3. 不同模式用不同模板
text_qa_template = PromptTemplate("基于上下文:{context_str}\n问题:{query_str}\n答案:")
refine_template = PromptTemplate("现有答案:{existing_answer}\n新上下文:{context_msg}\n问题:{query_str}\n优化答案:")
query_engine = index.as_query_engine(
text_qa_template=text_qa_template,
refine_template=refine_template
)
来源:LlamaIndex 官方 Prompt 文档
Q47. ChatEngine 流式输出怎么实现?
难度:中级
参考答案:
# 1. 启用 streaming
chat_engine = index.as_chat_engine(streaming=True)
# 2. 流式调用
streaming_response = chat_engine.stream_chat("什么是 RAG?")
for token in streaming_response.response_gen:
print(token, end="", flush=True)
# 3. 同步 API
response = chat_engine.chat("什么是 RAG?")
异步版:
import asyncio
async def stream_chat():
chat_engine = index.as_chat_engine(streaming=True)
streaming_response = await chat_engine.astream_chat("什么是 RAG?")
async for token in streaming_response.async_response_gen():
print(token, end="", flush=True)
asyncio.run(stream_chat())
生产价值:配合 SSE/WebSocket 推送到前端,用户体感"秒回"。
来源:LlamaIndex 官方
六、Agent 与 Workflows(Q48 - Q58)
Q48. ⭐ LlamaIndex 的 Agent 类型有哪些?v0.10+ 怎么迁移?
难度:中级
参考答案:
v0.10+ Agent 体系:
| Agent | 位置 | 特点 |
|---|---|---|
ReActAgent |
llama_index.core.agent.workflow |
ReAct 推理循环 |
FunctionCallingAgent |
llama_index.core.agent.workflow |
OpenAI Function Calling |
CodeActAgent |
llama_index.core.agent.workflow |
代码执行 |
AgentWorkflow |
多 Agent 协作 | handoff / state |
v0.9 → v0.10+ 迁移:
- ❌ 旧:
from llama_index.core.agent import AgentRunner, ReActAgent, FunctionCallingAgent - ✅ 新:
from llama_index.core.agent.workflow import ReActAgent, FunctionCallingAgent, AgentWorkflow - ❌ 旧:
agent = AgentRunner.from_agent_worker(...) - ✅ 新:
agent = ReActAgent(tools=tools, llm=llm)或AgentWorkflow(agents=[...])
# ReActAgent 示例
from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.tools import FunctionTool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers"""
return a * b
multiply_tool = FunctionTool.from_defaults(fn=multiply)
agent = ReActAgent(tools=[multiply_tool], llm=llm)
response = await agent.run(query="3 * 5 = ?")
来源:LlamaIndex Deprecated Terms 文档
Q49. ⭐ ReAct Agent 的工作原理是什么?
难度:中级
参考答案:
ReAct = Reason + Act:
Thought: 用户问 3*5,我需要计算
Action: multiply(3, 5)
Action Input: {"a": 3, "b": 5}
Observation: 15
Thought: 拿到结果了,可以回答
Final Answer: 3 * 5 = 15
核心循环:
- Think:LLM 思考下一步该做什么
- Act:选择工具和参数
- Execute:执行工具
- Observe:拿到结果
- 判断:是否拿到最终答案,否则回到 1
from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
def search(query: str) -> str:
"""搜索工具"""
return f"搜索结果: {query}"
agent = ReActAgent(
tools=[FunctionTool.from_defaults(fn=search)],
llm=OpenAI(model="gpt-4o"),
verbose=True
)
response = await agent.run("北京今天天气如何?")
print(response)
生产坑点:
- 最多 10-20 轮循环(防止死循环)
- 工具 description 要清晰,否则选错工具
- 复杂任务成本高(每轮 1 次 LLM 调用)
来源:CSDN《LangChain & LlamaIndex 面试题》
Q50. ⭐ FunctionCallingAgent 和 ReActAgent 怎么选?
难度:中级
参考答案:
| 维度 | FunctionCallingAgent | ReActAgent |
|---|---|---|
| 原理 | OpenAI Function Calling 原生支持 | ReAct 文本循环 |
| 速度 | 快(原生支持) | 较慢(解析文本) |
| 稳定性 | 高(结构化输出) | 中(依赖解析) |
| 兼容性 | 需 LLM 支持 Function Call | 几乎所有 LLM |
| 可调试 | 较难(黑盒) | 强(看 Thought/Action) |
| 推荐 | GPT-4 / Claude / Qwen | 调试期 / 小模型 |
# FunctionCallingAgent
from llama_index.core.agent.workflow import FunctionCallingAgent
agent = FunctionCallingAgent(
tools=tools,
llm=OpenAI(model="gpt-4o"),
verbose=True
)
# ReActAgent
from llama_index.core.agent.workflow import ReActAgent
agent = ReActAgent(tools=tools, llm=llm, verbose=True)
选型:
- 生产 + 主流 LLM → FunctionCallingAgent
- 调试 + 兼容性优先 → ReActAgent
来源:LlamaIndex 官方文档
Q51. ⭐ QueryEngineTool 是什么?怎么把 Query Engine 变成 Tool?
难度:中级
参考答案:
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core import VectorStoreIndex
# 1. 假设有两个索引
contract_index = VectorStoreIndex.from_documents(contract_docs)
hr_index = VectorStoreIndex.from_documents(hr_docs)
# 2. 把每个索引变成 Tool
contract_tool = QueryEngineTool(
query_engine=contract_index.as_query_engine(),
metadata=ToolMetadata(
name="contract_search",
description="查询合同条款、违约责任、SLA 条款相关问题"
)
)
hr_tool = QueryEngineTool(
query_engine=hr_index.as_query_engine(),
metadata=ToolMetadata(
name="hr_search",
description="查询员工手册、年假、考勤制度等 HR 问题"
)
)
# 3. 给 Agent 使用
from llama_index.core.agent.workflow import FunctionCallingAgent
agent = FunctionCallingAgent(
tools=[contract_tool, hr_tool],
llm=llm
)
response = await agent.run("合同里关于年假的规定是什么?")
关键点:
description决定路由:Agent 靠它选工具,写得不好直接路由失败name要唯一:Agent 返回的 Action 会引用它- production 经验:description 写"用于 X 类问题,例如 Y、Z"
来源:LlamaIndex 官方文档
Q52. ⭐ FunctionTool 怎么自定义?复杂参数怎么传?
难度:中级
参考答案:
from llama_index.core.tools import FunctionTool
from typing import Optional, List
from pydantic import BaseModel, Field
# 1. 简单函数
def search_weather(city: str) -> str:
"""查询指定城市的天气"""
return f"{city} 今天晴,25度"
tool = FunctionTool.from_defaults(fn=search_weather)
# 2. 复杂参数(用 Pydantic)
class SearchQuery(BaseModel):
keyword: str = Field(description="搜索关键词")
max_results: int = Field(default=10, description="返回结果数量")
language: str = Field(default="zh", description="语言")
def advanced_search(query: SearchQuery) -> List[str]:
"""高级搜索工具"""
return [f"结果 {i}: {query.keyword}" for i in range(query.max_results)]
tool = FunctionTool.from_defaults(fn=advanced_search)
# 3. 异步函数
async def async_fetch(url: str) -> str:
"""异步抓取网页"""
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()
async_tool = FunctionTool.from_defaults(fn=async_fetch)
生产要点:
- docstring 写清楚:Agent 靠 docstring 理解功能
- 参数类型注解必须:LLM 用类型生成参数
- Pydantic Field description:复杂参数必备
来源:LlamaIndex 官方文档
Q53. ⭐ 🔥 LlamaIndex Workflows 是什么?事件驱动架构怎么理解?
难度:高级
参考答案:
Workflows 是 LlamaIndex 推出的轻量级事件驱动框架(2024年发布,2025年6月 1.0 正式版),用来编排复杂多步 AI 应用。
核心组件:
from llama_index.core.workflow import (
Workflow, step, Event, StartEvent, StopEvent, Context
)
from llama_index.llms.openai import OpenAI
# 1. 定义事件
class JokeEvent(Event):
joke: str
class AnalysisEvent(Event):
analysis: str
# 2. 定义 Workflow
class JokeFlow(Workflow):
llm = OpenAI(model="gpt-4o-mini")
@step
async def generate_joke(self, ev: StartEvent) -> JokeEvent:
topic = ev.topic
prompt = f"讲一个关于{topic}的笑话"
response = await self.llm.acomplete(prompt)
return JokeEvent(joke=str(response))
@step
async def critique_joke(self, ev: JokeEvent) -> StopEvent:
prompt = f"分析笑话笑点: {ev.joke}"
response = await self.llm.acomplete(prompt)
return StopEvent(result=str(response))
# 3. 运行
w = JokeFlow(timeout=60, verbose=True)
result = await w.run(topic="程序员")
print(result)
核心概念:
- Event:事件,Pydantic 模型
- StartEvent / StopEvent:内置起止事件
- @step 装饰器:标记方法为步骤(基于入参/返回类型自动连接)
- Context:全局共享状态,类似"数据黑板"
核心优势:异步/并发/可观测/可视化调试/支持 Human-in-the-Loop。
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/workflows/
Q54. ⭐ 🔥 Workflows 的 Context 是什么?怎么用?
难度:高级
参考答案:
Context 是工作流中全局共享的状态对象(数据黑板),解决事件传递数据的繁琐。
from llama_index.core.workflow import Context
class MyWorkflow(Workflow):
@step
async def step1(self, ctx: Context, ev: StartEvent) -> SomeEvent:
# 写 Context
await ctx.set("user_name", ev.user_name)
await ctx.set("query", ev.query)
return SomeEvent(...)
@step
async def step2(self, ctx: Context, ev: SomeEvent) -> StopEvent:
# 读 Context
user_name = await ctx.get("user_name")
query = await ctx.get("query")
return StopEvent(result=...)
高级用法:
# 1. Context 存 LLM 调用的中间结果
@step
async def retrieve_step(self, ctx: Context, ev: StartEvent) -> NextEvent:
nodes = retriever.retrieve(ev.query)
await ctx.set("nodes", nodes)
return NextEvent(...)
# 2. 多步骤共享数据
@step
async def process_step(self, ctx: Context, ev: NextEvent) -> StopEvent:
nodes = await ctx.get("nodes")
# ...
# 3. 流式事件(context 在多 step 间共享)
async for event in wf.stream(topic="..."):
print(event)
坑点:ctx 操作是 async,必须 await!
来源:CSDN《LlamaIndex Workflows 从入门到实战》https://blog.csdn.net/SearchB/article/details/159896003
Q55. ⭐ 🔥 Workflows Human-in-the-Loop(HITL)怎么实现?
难度:高级
参考答案:
from llama_index.core.workflow import (
InputRequiredEvent, HumanResponseEvent, Context
)
class DangerousTool:
async def execute(self, ctx: Context) -> str:
question = "确认要删除这条记录吗?(yes/no)"
# 发出中断事件
response = await ctx.wait_for_event(
HumanResponseEvent,
waiter_id=question,
waiter_event=InputRequiredEvent(question)
)
if response.user_response.lower().startswith("y"):
return "已删除"
else:
return "操作取消"
# 配合外部系统
# 前端监听 InputRequiredEvent → 展示问题
# 用户回答后 → 触发 HumanResponseEvent → 继续 Workflow
生产级持久化模式:
# 1. 启动 Workflow,序列化状态
ctx_dict = ctx.to_dict()
db.save(f"workflow:{user_id}", ctx_dict)
# 2. 用户回答后,从 DB 恢复
ctx = Context.from_dict(workflow, ctx_dict)
ctx.send_event(HumanResponseEvent(user_response="yes"))
# 3. 继续运行
result = await wf.run(ctx=ctx)
生产场景:
- 危险操作确认(删库、转账)
- 人工审校(AI 写报告,主管确认)
- 多轮决策(AI 给选项,用户选)
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/workflows/
Q56. ⭐ AgentWorkflow 多 Agent 协作(handoff)怎么用?
难度:高级
参考答案:
from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
# 1. 定义多个 Agent
def search_docs(query: str) -> str:
"""搜索文档"""
return f"找到 {query} 相关文档"
def write_report(topic: str) -> str:
"""写报告"""
return f"已生成 {topic} 报告"
research_agent = ReActAgent(
name="research_agent",
description="负责检索资料",
tools=[FunctionTool.from_defaults(fn=search_docs)],
llm=OpenAI(model="gpt-4o"),
system_prompt="你是研究助理"
)
write_agent = ReActAgent(
name="write_agent",
description="负责写报告",
tools=[FunctionTool.from_defaults(fn=write_report)],
llm=OpenAI(model="gpt-4o"),
system_prompt="你是写作助理"
)
# 2. 编排多 Agent
workflow = AgentWorkflow(
agents=[research_agent, write_agent],
root_agent="research_agent", # 入口
)
# 3. 运行(agent 间自动 handoff)
response = await workflow.run("研究 AI Agent 最新进展并写报告")
print(response)
生产经验:
- 按职责拆分 agent,不要把每个微操都拆
- handoff 时记得传上下文(state 显式维护对话历史)
- state 要精简,大对象只存 ID/摘要
来源:CSDN《AgentWorkflow 实战》https://blog.csdn.net/puzi0315/article/details/152566151
Q57. ⭐ Workflows 的可视化调试怎么用?
难度:中级
参考答案:
# 安装工具
# pip install llama-index-utils-workflow
from llama_index.utils.workflow import (
draw_all_possible_flows, # 静态流程图
draw_most_recent_execution # 动态执行轨迹
)
# 1. 静态流程图(基于代码分析)
draw_all_possible_flows(MyWorkflow, filename="workflow_structure.html")
# 2. 动态执行图(最近一次)
workflow = MyWorkflow()
await workflow.run(topic="程序员")
draw_most_recent_execution(workflow, filename="recent_execution.html")
# 3. 流式事件调试
async for event in workflow.stream(topic="..."):
print(f"事件: {type(event).__name__}, 数据: {event}")
价值:
- 结构图看清有哪些步骤、怎么连
- 执行图看出实际走了哪条分支、哪步慢
- 流式事件实时调试
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/workflows/
Q58. Workflows 和 LangGraph 怎么选?
难度:高级
参考答案:
| 维度 | LlamaIndex Workflows | LangGraph |
|---|---|---|
| 定位 | LlamaIndex 生态的事件框架 | LangChain 生态的图编排 |
| 核心抽象 | 事件 + Step | Node + Edge + State |
| 状态管理 | Context(数据黑板) | State(结构化状态) |
| 可视化 | 内置(draw_all_possible_flows) | 需 LangSmith |
| HITL | 原生(InputRequiredEvent) | 需配置 interrupt |
| 多 Agent | AgentWorkflow(handoff) | 原生支持 |
| 学习曲线 | 中 | 较陡 |
选型:
- 项目以 LlamaIndex 为主 → Workflows
- 复杂图(条件分支、循环、状态机)→ LangGraph(更灵活)
- 真实项目经常组合:LlamaIndex 做检索,LangGraph 做主流程
来源:CSDN《LlamaIndex Workflows》
七、向量数据库与 Embedding(Q59 - Q67)
Q59. ⭐ LlamaIndex 怎么对接主流向量数据库(Chroma / Milvus / Qdrant / FAISS)?
难度:中级
参考答案:
通用模式:
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.core.vector_stores import ...
# 1. Chroma
import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_store = ChromaVectorStore(chroma_collection=chroma_client.get_or_create_collection("docs"))
# 2. Milvus
from llama_index.vector_stores.milvus import MilvusVectorStore
milvus_store = MilvusVectorStore(
uri="./milvus.db",
collection_name="docs",
dim=1536,
overwrite=True
)
# 3. Qdrant
from llama_index.vector_stores.qdrant import QdrantVectorStore
import qdrant_client
qclient = qdrant_client.QdrantClient(path="./qdrant_db")
qdrant_store = QdrantVectorStore(client=qclient, collection_name="docs")
# 4. FAISS
from llama_index.vector_stores.faiss import FaissVectorStore
import faiss
faiss_index = faiss.IndexFlatL2(1536)
faiss_store = FaissVectorStore(faiss_index=faiss_index)
然后:
storage_context = StorageContext.from_defaults(vector_store=<your_store>)
index = VectorStoreIndex(nodes, storage_context=storage_context)
来源:LlamaIndex 官方 https://docs.llamaindex.ai
Q60. ⭐ 主流向量库选型对比?
难度:中级
参考答案:
| 向量库 | 性能 | 规模 | 运维 | 适用 |
|---|---|---|---|---|
| Chroma | 中 | 小-中(< 1M) | 极简 | 原型 / 中小项目 |
| FAISS | 最快(CPU) | 中(亿级) | 自管 | 离线 / 嵌入引擎 |
| Milvus | 高(GPU) | 大(百亿级) | 重 | 大规模生产 |
| Qdrant | 高 | 中-大 | 中 | 通用生产 |
| Weaviate | 中 | 中 | 中 | 需 GraphQL? |
| Pinecone | 高 | 大 | 零运维 | 不想运维的云生产 |
| pgvector | 中 | 小-中 | SQL 一体 | 已有 PG 栈 |
选型建议:
- 个人/小项目 → Chroma
- 生产且不愿运维 → Pinecone / Zilliz Cloud
- 大规模 + 自有运维 → Milvus
- 已有 PG → pgvector
- 离线/嵌入式 → FAISS
来源:LlamaIndex Vector Store Integrations
Q61. ⭐ LlamaIndex 支持哪些 Embedding 模型?怎么切换?
难度:入门
参考答案:
# 1. OpenAI(默认)
from llama_index.embeddings.openai import OpenAIEmbedding
embed_model = OpenAIEmbedding(model="text-embedding-3-small", api_key="...")
# 2. BGE(开源、中文强)
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-large-zh-v1.5")
# 3. Cohere
from llama_index.embeddings.cohere import CohereEmbedding
embed_model = CohereEmbedding(api_key="...", model="embed-english-v3.0")
# 4. 本地 Sentence-Transformers
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
# 5. 全局设置(v0.10+ 推荐)
from llama_index.core import Settings
Settings.embed_model = embed_model
模型选型建议:
- 英文通用 → text-embedding-3-small / bge-large-en-v1.5
- 中文 → bge-large-zh-v1.5 / M3E
- 多语言 → bge-m3 / text-embedding-3-large
- 代码 → code-embeddings / jina-embeddings
来源:LlamaIndex Embeddings 文档
Q62. ⭐ 自定义 Embedding 模型怎么实现?
难度:高级
参考答案:
from llama_index.core.embeddings import BaseEmbedding
from typing import List
import numpy as np
class MyCustomEmbedding(BaseEmbedding):
def __init__(self, model_path: str, **kwargs):
super().__init__(**kwargs)
# 加载自定义模型
from sentence_transformers import SentenceTransformer
self._model = SentenceTransformer(model_path)
def _get_query_embedding(self, query: str) -> List[float]:
emb = self._model.encode(query)
return emb.tolist()
def _get_text_embedding(self, text: str) -> List[float]:
return self._model.encode(text).tolist()
async def _aget_query_embedding(self, query: str) -> List[float]:
return self._get_query_embedding(query)
async def _aget_text_embedding(self, text: str) -> List[float]:
return self._get_text_embedding(text)
# 使用
embed_model = MyCustomEmbedding(model_path="BAAI/bge-large-zh-v1.5")
生产要点:
- 实现所有 4 个方法(同步 query / text + 异步 query / text)
- batch encode 提高性能
- 缓存常见 query 减少重复计算
来源:LlamaIndex Embeddings 自定义文档
Q63. ⭐ 怎么持久化和加载 VectorStoreIndex?
难度:入门
参考答案:
# 1. 持久化
index = VectorStoreIndex.from_documents(docs)
index.storage_context.persist(persist_dir="./storage")
# 2. 加载
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
# 3. 继续用
query_engine = index.as_query_engine()
response = query_engine.query("...")
生产要点:
- 持久化会保存 4 个 store(vector / docstore / index_store / graph_store)
- 大索引加载慢,建议启动时预热
- 增量更新:
index.insert_nodes(new_nodes),再persist
来源:LlamaIndex 官方文档
Q64. 怎么实现 Embedding 的混合向量(稠密 + 稀疏)?
难度:高级
参考答案:
# 方案1: 用支持 sparse+dense 的向量库(如 Qdrant / Milvus)
from qdrant_client import models
# 上传时同时给 dense 和 sparse vector
qclient.upsert(
collection_name="docs",
points=[
models.PointStruct(
id=1,
vector={
"dense": dense_emb, # BGE
"sparse": sparse_emb, # BM25
},
payload={"text": "..."}
)
]
)
# 方案2: LlamaIndex 内置 hybrid(QueryFusionRetriever)
# 见 Q30
生产建议:
- 真正需要混合检索就用 Qdrant/Milvus 原生 hybrid
- LlamaIndex 的
QueryFusionRetriever已经够用 - 谨慎使用
num_queries=4(LLM 调用 4 次)
来源:Qdrant / Milvus 官方文档
Q65. ⭐ Embedding 模型微调怎么做?
难度:高级
参考答案:
# 1. 准备数据(query, positive_doc, negative_doc)
train_data = [
{
"query": "如何申请年假?",
"positive": "年假申请流程:登录 OA → 提交申请",
"negative": "病假申请流程:..."
},
# ...
]
# 2. 用 sentence-transformers 微调
from sentence_transformers import InputExample, losses
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-small-zh")
train_examples = [InputExample(texts=[d["query"], d["positive"], d["negative"]]) for d in train_data]
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
train_loss = losses.MultipleNegativesRankingLoss(model)
model.fit(
train_objectives=[(train_dataloader, train_loss)],
epochs=3,
output_path="./fine_tuned_bge"
)
# 3. 接入 LlamaIndex
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embed_model = HuggingFaceEmbedding(model_name="./fine_tuned_bge")
微调要点:
- 数据质量 > 数量(100 条高质量 > 10000 条噪声)
- 用
MultipleNegativesRankingLoss(对比学习) - 必须有 evaluation set 防止过拟合
- Hard negative mining 很重要
来源:sentence-transformers 文档
Q66. ⭐ 怎么提升 Embedding 的中文效果?
难度:中级
参考答案:
-
选对模型:
BAAI/bge-large-zh-v1.5(最常用)BAAI/bge-m3(多语言 + 长文本)MokaAI/M3E-large(开源)shibing624/text2vec-large-chinese
-
领域微调:用业务数据 fine-tune(见 Q65)
-
混合检索:BM25 + 向量(见 Q30)
-
查询重写:用 LLM 把口语化 query 改写为标准化 query
-
元数据过滤:减少搜索空间
# 查询重写示例
from llama_index.core.query_engine import TransformQueryEngine
from llama_index.core.indices.query.query_transform import HyDEQueryTransform
hyde = HyDEQueryTransform(llm=llm, include_original=True)
transformed_qe = TransformQueryEngine(qe, query_transform=hyde)
response = transformed_qe.query("用户口语化的问题")
来源:LlamaIndex HyDE 文档
Q67. Embedding 维度对成本和精度的影响?
难度:中级
参考答案:
| 模型 | 维度 | 精度 | 成本/1M token | 存储 |
|---|---|---|---|---|
| text-embedding-3-small | 512-1536 | 中 | $0.02 | 中 |
| text-embedding-3-large | 256-3072 | 高 | $0.13 | 大 |
| BGE-small-zh | 512 | 中 | 免费 | 小 |
| BGE-large-zh | 1024 | 高 | 免费 | 大 |
| BGE-M3 | 1024 | 高 | 免费 | 大 |
生产经验:
- 小型项目 / 原型:512 维够用
- 高精度场景:1024-1536 维
- 降维:text-embedding-3 支持
dimensions=512参数动态降维 - 存储成本:1M 向量 × 1536 维 × 4 bytes ≈ 6GB
来源:OpenAI Embeddings 定价、LlamaIndex 官方
八、嵌入向量化与 RAG 流程(Q68 - Q75)
Q68. ⭐ 完整的 RAG Pipeline 代码怎么写?
难度:中级
参考答案:
from llama_index.core import (
VectorStoreIndex, SimpleDirectoryReader, Settings
)
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core.postprocessor import SimilarityPostprocessor
from llama_index.postprocessor.bge_rerank import BGERerank
# 1. 全局配置
Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=50)
# 2. 加载
docs = SimpleDirectoryReader("./data", recursive=True).load_data()
# 3. 注入 metadata
for doc in docs:
doc.metadata["source"] = "公司制度"
doc.metadata["version"] = "v2.1"
# 4. 建索引
index = VectorStoreIndex.from_documents(docs)
# 5. 建 Query Engine(带 Rerank + 阈值)
bge = BGERerank(top_n=5, model="BAAI/bge-reranker-large")
sim = SimilarityPostprocessor(similarity_cutoff=0.7)
query_engine = index.as_query_engine(
similarity_top_k=10,
node_postprocessors=[sim, bge],
response_mode="compact",
streaming=True
)
# 6. 查询
response = query_engine.query("公司年假政策是什么?")
print(response)
for node in response.source_nodes:
print(f" score={node.score:.3f} | {node.node.text[:100]}")
来源:LlamaIndex 官方 Quickstart
Q69. ⭐ Graph RAG / Property Graph RAG 怎么实现?
难度:高级
参考答案:
from llama_index.core import PropertyGraphIndex, SimpleDirectoryReader
from llama_index.core.indices.property_graph import (
SimpleLLMPathExtractor, ImplicitPathExtractor
)
# 1. 加载
docs = SimpleDirectoryReader("./data").load_data()
# 2. 建图索引
pg_index = PropertyGraphIndex.from_documents(
docs,
kg_extractors=[
SimpleLLMPathExtractor(llm=llm, max_paths_per_chunk=10),
ImplicitPathExtractor()
]
)
# 3. 查询
query_engine = pg_index.as_query_engine(
include_text=True, # 返回 source text
similarity_top_k=2
)
response = query_engine.query("苹果公司的 CEO 是谁?")
# 自动找 实体(苹果公司) - 关系(CEO_of) - 实体(Tim Cook)
# 4. 自定义子检索器
from llama_index.core.indices.property_graph import (
VectorContextRetriever, LLMSynonymRetriever
)
retriever = pg_index.as_retriever(
sub_retrievers=[
VectorContextRetriever(pg_index.property_graph_store, embed_model=embed_model),
LLMSynonymRetriever(llm=llm)
]
)
Graph RAG vs 向量 RAG:
| 维度 | 向量 RAG | Graph RAG |
|---|---|---|
| 适合 | 语义相似 | 实体关系、多跳推理 |
| 召回 | 模糊 | 精确 |
| 成本 | 低 | 高(LLM 抽取三元组) |
| 维护 | 易 | 难 |
来源:LlamaIndex 官方 https://docs.llamaindex.ai/en/stable/module_guides/indexing/lpg_index_guide/
Q70. ⭐ Multi-Modal RAG 怎么实现?
难度:高级
参考答案:
# 方案1: LlamaParse + Multi-Modal Index(最简单)
from llama_parse import LlamaParse
from llama_index.core import SimpleDirectoryReader
parser = LlamaParse(api_key="llx-...", result_type="markdown")
file_extractor = {".pdf": parser}
docs = SimpleDirectoryReader("./pdfs", file_extractor=file_extractor).load_data()
# 启用多模态检索
from llama_index.indices.managed.llama_cloud import LlamaParseIndex
index = LlamaParseIndex(name="my_index", project_name="default", api_key="llx-...")
retriever = index.as_retriever(retrieve_image_nodes=True)
# 方案2: 自定义多模态查询引擎
from llama_index.core.query_engine import CustomQueryEngine
from llama_index.multi_modal_llms.openai import OpenAIMultiModal
class MultimodalQueryEngine(CustomQueryEngine):
qa_prompt: PromptTemplate
retriever: BaseRetriever
multi_modal_llm: OpenAIMultiModal
def custom_query(self, query_str: str):
nodes = self.retriever.retrieve(query_str)
img_nodes = [n for n in nodes if isinstance(n.node, ImageNode)]
text_nodes = [n for n in nodes if isinstance(n.node, TextNode)]
context_str = "\n\n".join([r.get_content() for r in nodes])
prompt = self.qa_prompt.format(context_str=context_str, query_str=query_str)
llm_response = self.multi_modal_llm.complete(
prompt=prompt,
image_documents=[n.node for n in img_nodes]
)
return Response(response=str(llm_response), source_nodes=nodes)
生产要点:
- 多模态 LLM 选型:GPT-4o(贵但强)、Claude 3.5 Sonnet、Qwen-VL(性价比高)
- 图文混合检索必须用专门的 multi-modal embedder
- 注意 token 成本(图片 = 几百到几千 token)
来源:CSDN《07-LlamaIndex 多模态与企业级》https://blog.csdn.net/wayle123/article/details/159518324
Q71. ⭐ SQL RAG 怎么实现?让 LLM 查数据库?
难度:高级
参考答案:
from llama_index.core.query_engine import NLSQLTableQueryEngine, SQLTableRetrieverQueryEngine
from llama_index.core import SQLDatabase
from sqlalchemy import create_engine
# 1. 连接数据库
engine = create_engine("sqlite:///example.db")
sql_db = SQLDatabase(engine, include_tables=["users", "orders"])
# 2. NLSQLTableQueryEngine(单表)
query_engine = NLSQLTableQueryEngine(
sql_database=sql_db,
tables=["users", "orders"]
)
response = query_engine.query("查询 2024 年注册用户数")
# 3. SQLTableRetrieverQueryEngine(多表 + 表检索)
from llama_index.core.indices.struct_store import SQLTableRetrieverQueryEngine
from llama_index.core.objects import SQLTableNodeMapping, ObjectIndex, SQLTableSchema
from llama_index.core import VectorStoreIndex
table_node_mapping = SQLTableNodeMapping(sql_db)
table_schema_objs = [
SQLTableSchema(table_name="users"),
SQLTableSchema(table_name="orders")
]
obj_index = ObjectIndex.from_objects(
table_schema_objs,
table_node_mapping,
VectorStoreIndex,
)
table_retriever = obj_index.as_retriever(similarity_top_k=1)
query_engine = SQLTableRetrieverQueryEngine(
sql_database=sql_db,
table_retriever=table_retriever
)
response = query_engine.query("查 2024 年订单量最高的用户")
生产经验:
- 必须设数据库只读账户,防 SQL 注入
- 用 Text-to-SQL Guardrails 验证生成的 SQL
- 大表要分表 / 预聚合,避免扫描全表
来源:LlamaIndex Structured Data 文档
Q72. ⭐ Agentic RAG 和普通 RAG 区别是什么?
难度:高级
参考答案:
普通 RAG:固定流程(retrieve → generate)
Agentic RAG:Agent 自主决策检索策略
Agentic RAG 实现:
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.agent.workflow import FunctionCallingAgent
# 1. 多种检索策略建多个 Tool
vector_tool = QueryEngineTool(
query_engine=vector_qe,
metadata=ToolMetadata(name="vector_search", description="语义检索")
)
keyword_tool = QueryEngineTool(
query_engine=bm25_qe,
metadata=ToolMetadata(name="keyword_search", description="关键词检索")
)
sql_tool = QueryEngineTool(
query_engine=sql_qe,
metadata=ToolMetadata(name="sql_search", description="查结构化数据库")
)
# 2. Agent 决策
agent = FunctionCallingAgent(
tools=[vector_tool, keyword_tool, sql_tool],
llm=llm
)
response = await agent.run("查 2024 年 Q3 销售额最高的产品的客户评价")
# Agent 自动选:先 SQL 查产品,再向量查评价
对比:
| 维度 | 普通 RAG | Agentic RAG |
|---|---|---|
| 流程 | 固定 | 灵活 |
| 成本 | 低 | 高(多次 LLM) |
| 准确性 | 中 | 高 |
| 延迟 | 低 | 高 |
| 适用 | 通用 Q&A | 复杂决策 |
来源:LlamaIndex Agentic RAG 文档
Q73. ⭐ HyDE(Hypothetical Document Embeddings)是什么?怎么用?
难度:高级
参考答案:
HyDE = 让 LLM 先生成"假设答案",再用假设答案做检索。原理是 query 和 answer 都在同一 embedding 空间。
from llama_index.core.indices.query.query_transform import HyDEQueryTransform
from llama_index.core.query_engine import TransformQueryEngine
hyde = HyDEQueryTransform(llm=llm, include_original=True)
transformed_qe = TransformQueryEngine(query_engine, query_transform=hyde)
response = transformed_qe.query("RAG 的核心思想")
# 1. LLM 生成"假设答案":RAG 是检索增强生成...
# 2. 用假设答案做向量检索
# 3. 用检索到的真实 Node 生成最终答案
适用:
- Query 短 / 不规范
- 用户用口语化表达
- 检索质量不理想时
坑点:
- 多 1 次 LLM 调用(成本翻倍)
- 假设答案可能不准确
来源:LlamaIndex 官方文档
Q74. ⭐ Recursive Retriever 是什么?怎么用?
难度:高级
参考答案:
Recursive Retriever 处理有引用关系的文档(如论文里引用其他论文、小节引用章节)。
from llama_index.core.retrievers import RecursiveRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
# 场景:doc 里有 [REF:其他doc_id] 这种引用
recursive_retriever = RecursiveRetriever(
root_id="root",
retriever_dict={
"root": vector_retriever,
"other_doc": other_retriever, # 引用目标
}
)
# 用法
nodes = recursive_retriever.retrieve("查找所有相关引用")
应用:
- 论文知识图谱(引用关系)
- 文档-摘要 双层
- 多跳检索
来源:LlamaIndex 官方文档
Q75. ⭐ 怎么在生产环境部署 LlamaIndex 应用?
难度:高级
参考答案:
部署方式:
- REST API(FastAPI):
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
query_engine = index.as_query_engine(streaming=True)
class Query(BaseModel):
question: str
@app.post("/query")
async def query(q: Query):
response = await query_engine.aquery(q.question)
return {"answer": str(response), "sources": [n.node.text for n in response.source_nodes]}
- LlamaIndex Server(v0.10+ 推荐):
from llama_index.server import LlamaIndexServer
server = LlamaIndexServer(index=index)
server.run(host="0.0.0.0", port=8000)
-
Serverless:AWS Lambda / Vercel Functions
-
Docker + K8s:标准容器化
生产铁律:
- 预热模型:启动时 load 索引,避免冷启动
- 异步优先:
aquery/astream_query - 限流熔断:防止 OOM
- 监控埋点:Callback + Prometheus
- 健康检查:索引可加载
来源:LlamaIndex 部署文档
九、评估与可观测性(Q76 - Q85)
Q76. ⭐ LlamaIndex 怎么评估 RAG 质量?内置评估指标有哪些?
难度:中级
参考答案:
LlamaIndex 内置指标:
from llama_index.core.evaluation import (
FaithfulnessEvaluator, # 答案是否忠实于上下文
AnswerRelevancyEvaluator, # 答案与问题相关性
ContextRelevancyEvaluator, # 上下文与问题相关性
CorrectnessEvaluator, # 答案正确性(需 ground_truth)
PairwiseComparisonEvaluator, # 两个引擎对比
)
# 1. Faithfulness
evaluator = FaithfulnessEvaluator(llm=llm)
result = evaluator.evaluate_response(
query="什么是 RAG?",
response=response
)
print(f"Faithfulness: {result.score}, passing: {result.passing}")
# 2. 批量评估
from llama_index.core.evaluation import BatchEvalRunner
runner = BatchEvalRunner(
{
"faithfulness": FaithfulnessEvaluator(llm=llm),
"relevancy": AnswerRelevancyEvaluator(llm=llm),
},
workers=4
)
results = await runner.aevaluate_queries(
query_engine=query_engine,
queries=["q1", "q2", ...]
)
指标含义:
- Faithfulness:答案内容是否源自上下文(抗幻觉关键)
- Answer Relevancy:答案和问题的匹配度
- Context Relevancy:召回的上下文是否相关
- Correctness:vs 人工标注的标准答案
来源:CSDN《评估大模型 RAG》https://blog.csdn.net/m0_59596990/article/details/140058653
Q77. ⭐ RAGAs 怎么和 LlamaIndex 集成?
难度:中级
参考答案:
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
context_relevancy,
)
from ragas.llama_index import evaluate
# 1. 准备数据
questions = ["什么是 RAG?", "RAG 和微调的区别?"]
ground_truth = ["RAG 是检索增强生成...", "RAG 实时检索,微调改模型参数..."]
# 2. 评估
metrics = [faithfulness, answer_relevancy, context_precision, context_recall]
result = evaluate(query_engine, metrics, questions, ground_truth)
print(result)
# {'faithfulness': 0.9, 'answer_relevancy': 0.89, ...}
# 3. 转 DataFrame 分析
df = result.to_pandas()
df.to_csv("eval_results.csv", index=False)
4 大核心指标:
- Faithfulness:答案忠实上下文(0-1,越高越好)
- Answer Relevancy:答案相关问题
- Context Precision:相关 context 排序是否靠前
- Context Recall:答案是否覆盖 ground truth
生产价值:每次改 pipeline(换 embedder、换 chunk size)就跑一遍,看指标变化。
来源:RAGAs 官方 https://docs.ragas.io/en/v0.1.21/howtos/integrations/llamaindex.html
Q78. ⭐ Faithfulness 和 Correctness 有什么区别?
难度:中级
参考答案:
| 指标 | 衡量 | 需要的输入 |
|---|---|---|
| Faithfulness | 答案是否基于上下文(无幻觉) | query + response |
| Correctness | 答案是否等于 ground truth | query + response + reference |
Faithfulness 测的是"幻觉程度"——LLM 自己加戏了没?
Correctness 测的是"准确性"——答对了没?
# Faithfulness
from llama_index.core.evaluation import FaithfulnessEvaluator
f_eval = FaithfulnessEvaluator(llm=llm)
result = f_eval.evaluate(query="X是什么?", response=response)
# score 接近 1 = 答案都来自上下文
# score 接近 0 = LLM 编造内容
# Correctness
from llama_index.core.evaluation import CorrectnessEvaluator
c_eval = CorrectnessEvaluator(llm=llm)
result = c_eval.evaluate(
query="X是什么?",
response=response,
reference="X 的标准答案..."
)
# score 0-5,5 = 完全正确
生产组合:Faithfulness 必用(保底),Correctness 抽样用(需 ground truth)。
来源:CSDN《Advanced RAG 03》https://blog.csdn.net/Baihai_IDP/article/details/137865226
Q79. ⭐ DeepEval 怎么和 LlamaIndex 集成?
难度:中级
参考答案:
from deepeval.metrics import (
AnswerRelevancyMetric,
FaithfulnessMetric,
ContextualPrecisionMetric,
)
from deepeval.test_case import LLMTestCase
# 1. 定义指标
answer_relevancy = AnswerRelevancyMetric()
faithfulness = FaithfulnessMetric()
contextual_precision = ContextualPrecisionMetric()
# 2. 运行 RAG 应用拿到 response
rag_application = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=synthesizer,
node_postprocessors=[SimilarityPostprocessor(similarity_cutoff=0.7)]
)
response = rag_application.query("What is LlamaIndex?")
# 3. 创建 TestCase
test_case = LLMTestCase(
input="What is LlamaIndex?",
actual_output=str(response),
retrieval_context=[n.node.get_content() for n in response.source_nodes]
)
# 4. 评估
answer_relevancy.measure(test_case)
faithfulness.measure(test_case)
contextual_precision.measure(test_case)
print(f"Answer Relevancy: {answer_relevancy.score}")
print(f"Faithfulness: {faithfulness.score}")
print(f"Contextual Precision: {contextual_precision.score}")
DeepEval vs RAGAs:
- RAGAs:开源、轻量
- DeepEval:50+ 指标、多模态支持、企业级
来源:LlamaIndex 博客 https://www.llamaindex.ai/blog/evaluating-rag-with-deepeval-and-llamaindex
Q80. ⭐ Callback 机制是什么?Token 计数怎么实现?
难度:中级
参考答案:
from llama_index.core.callbacks import CallbackManager, TokenCountingHandler
import tiktoken
# 1. Token 计数 handler
token_counter = TokenCountingHandler(
tokenizer=tiktoken.encoding_for_model("gpt-4").encode,
verbose=True
)
# 2. 注册到 Settings
Settings.callback_manager = CallbackManager([token_counter])
# 3. 跑 query
response = query_engine.query("什么是 RAG?")
# 4. 查看 token 用量
print(f"Total LLM tokens: {token_counter.total_llm_token_count}")
print(f"Prompt tokens: {token_counter.prompt_llm_token_count}")
print(f"Completion tokens: {token_counter.completion_llm_token_count}")
print(f"Embedding tokens: {token_counter.total_embedding_token_count}")
# 5. 重置
token_counter.reset_counts()
生产价值:监控 LLM 成本、优化 token 消耗、限流。
来源:LlamaIndex Token Counter 文档 https://docs.llamaindex.ai/en/stable/api_reference/callbacks/token_counter/
Q81. ⭐ 自定义 Callback Handler 怎么写?
难度:高级
参考答案:
from llama_index.core.callbacks import BaseCallbackHandler
from llama_index.core.callbacks.schema import CBEventType
class MyObservabilityHandler(BaseCallbackHandler):
def __init__(self):
super().__init__()
self.llm_calls = []
self.retrieve_calls = []
def on_event_start(
self,
event_type: CBEventType,
payload: Optional[Dict] = None,
event_id: str = "",
parent_id: str = "",
**kwargs
) -> str:
return event_id
def on_event_end(
self,
event_type: CBEventType,
payload: Optional[Dict] = None,
event_id: str = "",
**kwargs
) -> None:
if event_type == CBEventType.LLM:
self.llm_calls.append({
"timestamp": time.time(),
"payload": payload,
})
elif event_type == CBEventType.RETRIEVE:
self.retrieve_calls.append({
"timestamp": time.time(),
"nodes": len(payload.get("nodes", [])),
})
# 注册
handler = MyObservabilityHandler()
Settings.callback_manager = CallbackManager([handler])
生产场景:
- 推送 LLM 调用日志到 ELK / Datadog
- 实时监控慢检索
- 统计每个 Node 被召回次数(优化索引)
来源:LlamaIndex Callback 文档
Q82. ⭐ LlamaIndex 可观测性怎么做?生产监控指标有哪些?
难度:高级
参考答案:
生产监控体系:
- LlamaIndex 原生 OpenTelemetry:
from llama_index.core import set_global_handler
set_global_handler("arize_phoenix") # 推送到 Phoenix
# 或
set_global_handler("langfuse") # 推送到 Langfuse
- 关键指标:
| 类别 | 指标 | 监控工具 |
|---|---|---|
| 性能 | Query 延迟 P50/P95/P99 | Prometheus + Grafana |
| 质量 | Faithfulness、Answer Relevancy | RAGAs + 定时任务 |
| 成本 | LLM Token、Embedding Token | TokenCountingHandler |
| 检索 | 召回率、TopK 命中 | 自定义 Callback |
| 业务 | 答案采纳率、用户反馈 | 前端埋点 |
- 告警规则:
- 延迟 P95 > 5s → 告警
- Faithfulness < 0.7 → 告警
- Token 消耗超预算 → 告警
来源:LlamaIndex Observability 文档
Q83. ⭐ 怎么生成 RAG 评估集(TestSet)?
难度:中级
参考答案:
# RAGAs Testset Generator
from ragas.testset.generator import TestsetGenerator
from ragas.testset.evolutions import simple, reasoning, multi_context
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
# 1. 加载文档
documents = SimpleDirectoryReader("./data").load_data()
# 2. 初始化生成器
generator_llm = OpenAI(model="gpt-3.5-turbo-16k")
critic_llm = OpenAI(model="gpt-4")
embeddings = OpenAIEmbedding()
generator = TestsetGenerator.from_llama_index(
generator_llm=generator_llm,
critic_llm=critic_llm,
embeddings=embeddings,
)
# 3. 生成测试集
testset = generator.generate_with_llamaindex_docs(
documents,
test_size=50,
distributions={simple: 0.4, reasoning: 0.3, multi_context: 0.3}
)
3 种 Question Evolution:
- Simple:单文档直接答案
- Reasoning:需要多步推理
- Multi-Context:跨文档综合
来源:RAGAs 官方文档
Q84. Pairwise Comparison 评估怎么做?
难度:中级
参考答案:
from llama_index.core.evaluation import PairwiseComparisonEvaluator
# 比较两个 query engine 的输出
evaluator = PairwiseComparisonEvaluator(llm=llm)
result = evaluator.evaluate(
query="什么是 RAG?",
response_a=engine_a.query("什么是 RAG?"),
response_b=engine_b.query("什么是 RAG?"),
)
# 返回哪个更好
print(f"Winner: {result.choice}") # "A" / "B" / "Tie"
print(f"Score: {result.score}")
生产场景:
- A/B test 两个版本的 RAG pipeline
- 对比不同 chunk_size / embedder / LLM
- 比单一指标更贴近真实偏好
来源:LlamaIndex 官方评估文档
Q85. 检索评估的 Hit Rate、MRR、NDCG 怎么算?
难度:中级
参考答案:
# Hit Rate: 至少有一个相关 doc 在 top-k
hit_rate = 1 if any(g in retrieved[:k] for g in ground_truth) else 0
# MRR (Mean Reciprocal Rank): 第一个相关 doc 排名的倒数
rr = 1 / rank_of_first_relevant_doc
mrr = mean(rr for all queries)
# NDCG (Normalized Discounted Cumulative Gain)
import numpy as np
def dcg(relevances, k):
relevances = relevances[:k]
return sum(rel / np.log2(i + 2) for i, rel in enumerate(relevances))
def ndcg(retrieved, ground_truth, k=10):
relevances = [1 if d in ground_truth else 0 for d in retrieved[:k]]
ideal = sorted(relevances, reverse=True)
return dcg(relevances, k) / (dcg(ideal, k) + 1e-10)
目标值:
- Hit Rate@10 > 0.85
- MRR@10 > 0.6
- NDCG@10 > 0.7
来源:RAG 评估通用指标
十、性能优化与生产实践(Q86 - Q93)
Q86. ⭐ LlamaIndex 性能调优有哪些关键点?
难度:高级
参考答案:
全链路优化清单:
| 环节 | 优化 | 收益 |
|---|---|---|
| 加载 | 多进程 num_workers=4 |
50%↓ |
| 切分 | 合理 chunk_size + overlap | 20%↑ 质量 |
| 嵌入 | 用本地 BGE 替代 OpenAI | 成本 0、延迟 -200ms |
| 检索 | 向量库用 HNSW 索引 | 10x 速度 |
| 检索 | 加 Rerank | 质量 +30% |
| 检索 | 混合检索 | 召回 +15% |
| 生成 | 异步 aquery |
并发 10x |
| 生成 | streaming | 体感延迟 -50% |
| 生成 | Prompt 压缩 | token -30% |
| 缓存 | 相同 query 缓存 | 成本 -50% |
| 缓存 | Token 计数监控 | 防止爆预算 |
来源:LlamaIndex 官方 Performance 文档
Q87. ⭐ 异步和流式怎么用?
难度:中级
参考答案:
import asyncio
# 1. 异步查询
async def async_query():
response = await query_engine.aquery("什么是 RAG?")
return response
# 2. 异步流式
async def stream_query():
streaming_response = await query_engine.astream_query("什么是 RAG?")
async for token in streaming_response.async_response_gen():
print(token, end="", flush=True)
# 3. 并发多个 query
async def batch_queries():
queries = ["q1", "q2", "q3"]
tasks = [query_engine.aquery(q) for q in queries]
responses = await asyncio.gather(*tasks)
return responses
# 4. 异步 + 多个索引
async def multi_index_query():
tasks = [
index_a.aquery(q) for q in queries
] + [
index_b.aquery(q) for q in queries
]
responses = await asyncio.gather(*tasks)
return responses
asyncio.run(async_query())
生产经验:
- 同步代码改异步是性价比最高的优化(吞吐提升 5-10x)
- async 让 LLM 的网络等待时间不阻塞
来源:LlamaIndex 官方 async 文档
Q88. ⭐ 怎么实现 LLM 调用缓存?生产怎么做?
难度:中级
参考答案:
# 方案1: LangChain Cache(如果有 LangChain 集成)
from langchain.cache import InMemoryCache
import langchain
langchain.llm_cache = InMemoryCache()
# 方案2: LlamaIndex 自带缓存(基于 query hash)
from llama_index.core.callbacks import CallbackManager
from llama_index.core import Settings
# 方案3: Redis 分布式缓存
import redis
r = redis.Redis()
def cached_query(q):
key = f"rag:{hash(q)}"
cached = r.get(key)
if cached:
return cached.decode()
response = query_engine.query(q)
r.setex(key, 3600, str(response)) # TTL 1h
return str(response)
生产经验:
- 缓存命中率通常 30-60%
- 缓存粒度:按 query / query 改写后 hash
- 配合查询改写(HyDE/Query Rewriting)提高命中率
来源:LlamaIndex 缓存文档
Q89. ⭐ Token 优化怎么做?
难度:中级
参考答案:
5 大优化策略:
-
减少 Prompt 长度:
- 合理
similarity_top_k(5-10 别太多) - 用
compact模式替代refine - 缩短 system_prompt
- 合理
-
压缩检索结果:
from llama_index.core.postprocessor import LongContextReorder
from llama_index.core.response_synthesizers import CompactAndRefine
# 上下文压缩(用小 LLM 提取关键信息)
from llama_index.core.postprocessor import SentenceEmbeddingOptimizer
optimizer = SentenceEmbeddingOptimizer(percentile_cutoff=0.5)
-
Embedding 压缩:
- 减小维度(text-embedding-3 支持
dimensions=512) - 量化(int8)
- 减小维度(text-embedding-3 支持
-
缓存(见 Q88)
-
小模型:
- 默认用
gpt-4o-mini,关键场景用gpt-4o - 评估/QA 用
gpt-3.5-turbo - 嵌入用 BGE 本地
- 默认用
来源:LlamaIndex 性能文档
Q90. ⭐ 索引重建 vs 增量更新怎么选?
难度:高级
参考答案:
全量重建(drop & rebuild):
# 1. 删除旧索引
import shutil
shutil.rmtree("./storage")
# 2. 重新构建
docs = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(docs)
index.storage_context.persist(persist_dir="./storage")
增量更新(推荐):
# 1. 加载旧索引
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
# 2. 增量插入新文档
new_docs = SimpleDirectoryReader("./new_data").load_data()
for doc in new_docs:
index.insert(doc)
# 3. 删除过期文档
index.delete_ref_doc(doc_id="old_doc_id")
# 4. 保存
index.storage_context.persist(persist_dir="./storage")
决策:
- < 1M Node:增量更新
- > 10M Node + 频繁更新:考虑重建 + 版本号
- 嵌入模型升级:必须全量重建
生产经验:版本化索引 + 蓝绿发布(新索引构建完再切流量)。
来源:LlamaIndex Ingestion Pipeline 文档
Q91. ⭐ 怎么处理大批量文档(百万级)的索引构建?
难度:高级
参考答案:
完整生产方案:
# 1. 加载阶段
reader = SimpleDirectoryReader(
"./data",
recursive=True,
required_exts=[".pdf", ".docx"]
)
docs = reader.load_data(num_workers=8) # 并行
# 2. 切分 + 嵌入(分批处理避免 OOM)
from llama_index.core.node_parser import SentenceSplitter
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=50)
# 3. 写入生产级向量库
import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import VectorStoreIndex, StorageContext
chroma_client = chromadb.PersistentClient(path="./chroma_prod")
collection = chroma_client.get_or_create_collection(
"docs",
metadata={"hnsw:space": "cosine"}
)
chroma_store = ChromaVectorStore(chroma_collection=collection)
storage_context = StorageContext.from_defaults(vector_store=chroma_store)
# 4. 分批构建
batch_size = 1000
all_nodes = splitter.get_nodes_from_documents(docs)
for i in range(0, len(all_nodes), batch_size):
batch = all_nodes[i:i+batch_size]
index = VectorStoreIndex(batch, storage_context=storage_context)
print(f"Processed {i+len(batch)}/{len(all_nodes)} nodes")
生产经验:
- 先小批测试,再放大
- 持久化中间状态(IngestionPipeline + 缓存)
- HNSW 索引参数调优:
M=16, ef_construction=200是好的起点
来源:LlamaIndex 官方 Ingestion 文档
Q92. ⭐ LlamaIndex 的 open_source_helpers(observability 生态)有哪些?
难度:中级
参考答案:
主要可观测性平台:
# 1. Phoenix (Arize)
import phoenix as px
from llama_index.core import set_global_handler
set_global_handler("arize_phoenix")
# 2. Langfuse
set_global_handler("langfuse")
# 3. OpenLLMetry (Traceloop)
set_global_handler("traceloop")
# 4. HoneyHive
set_global_handler("honeyhive")
# 5. Weights & Biases
set_global_handler("wandb")
生产推荐:
- Phoenix:开源、本地、自部署
- Langfuse:开源 + 云、易用
- Arize:企业级
- OpenLLMetry:OpenTelemetry 标准
统一标准:OpenTelemetry(OTel),所有平台都支持。
来源:LlamaIndex Observability 文档
Q93. ⭐ LlamaIndex 在企业级落地需要补哪些能力?
难度:高级
参考答案:
Demo 能跑 ≠ 生产能用。企业级必须补齐:
-
数据治理:
- 权限过滤(metadata level)
- 文档版本管理
- 增量更新
- 删除机制
-
质量保障:
- 评估闭环(RAGAs + 定时)
- Badcase 收集 + 回流
- A/B test
- 答案引用(溯源)
-
可观测性:
- 全链路 trace
- Token 监控
- 告警机制
- 用户反馈采集
-
性能与成本:
- 异步 + 流式
- 缓存层
- 模型分级(小模型优先)
- 冷热数据分离
-
安全合规:
- 敏感数据脱敏
- 审计日志
- API 限流
- 鉴权
-
工程化:
- CI/CD
- 容器化部署
- 灾备
- 灰度发布
来源:今日头条《LlamaIndex 全栈解析》
十一、高级特性与趋势(Q94 - Q100)
Q94. ⭐ SentenceWindowNodeParser 和 Small-to-Big 检索的优缺点?
难度:高级
参考答案:
优点:
- 检索精度高:小颗粒(句子)匹配精确
- 生成上下文全:大窗口给 LLM 完整语义
- 实现简单:配置少,效果明显
缺点:
- 节点多,存储大:每句 1 个 Node
- 窗口固定:不能跨窗口合并
- 依赖 PostProcessor:必须用
MetadataReplacementPostProcessor
适用场景:
- 文档结构相对均匀
- 需要精确引用(如法律条文)
- 句子级别证据
生产数据:在合同/法律 RAG 场景,NDCG@10 比普通切片高 15-25%。
来源:CSDN《Llama-Index RAG 黑科技》
Q95. ⭐ RecursiveRetriever 怎么用?和 ParentDocumentRetriever 关系?
难度:高级
参考答案:
RecursiveRetriever 处理"小节点检索,父节点输出"的场景(类似 AutoMerging):
from llama_index.core.retrievers import RecursiveRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
# 场景:小 node(精确检索)→ 大 node(完整上下文)
recursive_retriever = RecursiveRetriever(
root_id="root",
retriever_dict={
"root": small_node_retriever, # 小 node 检索
# 自动跳转到对应父节点
},
node_dict=node_dict, # id → Node 映射
)
和 AutoMerging 的关系:
- 思路相同(先小后大)
- AutoMerging 用父子关系,RecursiveRetriever 用 id 索引
- AutoMerging 更推荐(API 更优雅)
来源:LlamaIndex 官方文档
Q96. ⭐ KnowledgeGraphIndex 在 v0.10+ 后为什么被替代?
难度:高级
参考答案:
替代原因:
- Schema 过于僵硬:
SchemaLLMPathExtractor(possible_relations=[...])必须预定义关系类型 - 属性支持弱:节点和边只能存基本三元组,不能存丰富属性
- Graph RAG 需求变化:现代应用需要更灵活的数据模型
PropertyGraphIndex 优势:
- 属性丰富:节点/边都支持 KV 属性
- 结构灵活:无需预定义 schema
- 多种 Extractor 组合:
SimpleLLMPathExtractor+ImplicitPathExtractor - 多 sub-retriever 融合:向量 + 关键词 + 文本
迁移:
# 旧
from llama_index.core import KnowledgeGraphIndex
kg_index = KnowledgeGraphIndex.from_documents(docs)
# 新
from llama_index.core import PropertyGraphIndex
pg_index = PropertyGraphIndex.from_documents(
docs,
kg_extractors=[SimpleLLMPathExtractor(llm=llm)]
)
来源:LlamaIndex 官方迁移文档
Q97. ⭐ Structured Data Extraction(结构化数据抽取)怎么实现?
难度:中级
参考答案:
from pydantic import BaseModel, Field
from llama_index.core.program import LLMTextCompletionProgram
class Invoice(BaseModel):
"""发票信息"""
invoice_no: str = Field(description="发票号码")
amount: float = Field(description="金额")
date: str = Field(description="开票日期")
items: list[str] = Field(description="项目明细")
# 1. Pydantic 风格抽取
prompt = """
从以下文本中抽取发票信息:
{text}
"""
program = LLMTextCompletionProgram.from_defaults(
output_cls=Invoice,
prompt_template_str=prompt,
llm=llm
)
invoice = program(text="发票号 12345,金额 1000 元...")
print(invoice.invoice_no, invoice.amount)
# 2. 批量抽取
from llama_index.core.extractors import PydanticExtractor
extractor = PydanticExtractor(
output_cls=Invoice,
llm=llm
)
extracted_nodes = extractor.extract(nodes)
生产应用:
- 合同关键信息抽取
- 简历解析
- 发票/订单结构化
- 知识图谱实体抽取
来源:LlamaIndex 官方 Structured Data 文档
Q98. ⭐ LangChain 和 LlamaIndex 2025-2026 趋势:哪个更值得学?
难度:高级
参考答案:
当前趋势:
-
LlamaIndex 持续强化数据层:
- Workflows 1.0 正式版
- LlamaParse(云服务)成为强项
- PropertyGraphIndex 成熟
- 企业级多模态 RAG 落地
-
LangChain 持续强化编排层:
- LangGraph(图编排)
- LangSmith(追踪)
- LangServe(部署)
- LCEL(表达式语言)
-
生态融合:
langchain-llama-index互操作LlamaIndexRetriever可被 LangChain 链调用- 真实项目99% 都是组合使用
学习建议:
- RAG 方向:LlamaIndex 优先(数据层更专业)
- Agent 方向:LangGraph 优先(图编排更灵活)
- 面试:两个都要懂,LlamaIndex 重点(题目要求)
来源:综合 LlamaIndex / LangChain 2025-2026 路线图
Q99. ⭐ LlamaIndex 在大厂面试中的高频追问有哪些?
难度:高级
参考答案:
大厂高频追问 TOP 20:
- ⭐ LlamaIndex 和 LangChain 区别?怎么选?
- ⭐ 100 万 PDF 怎么建索引?详细方案
- ⭐ chunk_size 怎么选?调优方法?
- ⭐ 用户反馈答案不准,你怎么 debug?
- ⭐ 召回率和答案质量哪个重要?怎么平衡?
- ⭐ 怎么评估 RAG?指标有哪些?
- ⭐ Graph RAG 和向量 RAG 区别?什么场景用?
- ⭐ 多模态 RAG 怎么做?图文混合检索?
- ⭐ v0.10+ 怎么从 ServiceContext 迁移?
- ⭐ Workflows 是什么?和 Agent 关系?
- ⭐ Function Calling 和 ReAct 区别?
- ⭐ 索引重建 vs 增量更新?
- ⭐ 怎么实现权限过滤?
- ⭐ 怎么降低 LLM 成本?Token 优化方法?
- ⭐ 流式输出怎么实现?
- ⭐ Multi-Document Agent 怎么路由?
- ⭐ SQL RAG / Text-to-SQL 怎么保证安全?
- ⭐ PropertyGraphIndex 和 KnowledgeGraphIndex 区别?
- ⭐ HyDE / Query Rewrite 怎么用?
- ⭐ 生产环境怎么监控 RAG 质量?
来源:CSDN/掘金/腾讯云开发者社区高频面经
Q100. ⭐ 大模型时代,RAG 和微调(Fine-tuning)怎么选?
难度:高级
参考答案:
| 维度 | RAG | 微调(Fine-tuning) |
|---|---|---|
| 适用 | 知识更新频繁 / 需要溯源 | 改变模型行为/风格/格式 |
| 数据需求 | 文档库(结构化/非结构化) | 高质量 QA 对(千-万级) |
| 成本 | 低(检索+生成) | 高(GPU + 数据标注) |
| 更新速度 | 实时 | 慢(重新训练) |
| 可解释性 | 强(能引用) | 弱(黑盒) |
| 风险 | 召回不准 | 灾难性遗忘、幻觉 |
| 典型场景 | 客服、知识库、合同 | 文风统一、格式转换 |
实战建议:
- 80% 场景 RAG 优先
- 两者经常组合:用 RAG 提供事实 + 微调控制风格
- 微调不是越多越好,能 RAG 就别微调
- “企业知识更新快” → 100% RAG
- “模型需要遵循特定行业话术” → 微调
趋势:Agent + RAG 是 2025-2026 主旋律,小模型 + RAG 比"大模型一刀切"更经济。
来源:综合大厂 JD 和面经
🔥 速记清单(面试前 1 小时过一遍)
| # | 知识点 | 一句话总结 |
|---|---|---|
| 1 | LlamaIndex 定位 | 数据层框架,RAG 专家 |
| 2 | vs LangChain | 数据 vs 编排,常组合 |
| 3 | 核心组件 | Document→Node→Index→Retriever→QueryEngine |
| 4 | 索引类型 | VectorStoreIndex 是默认,PropertyGraphIndex 是图 |
| 5 | ServiceContext→Settings | v0.10+ 必须用 Settings 全局配置 |
| 6 | Retriever vs QueryEngine | 检索器 vs 完整问答引擎 |
| 7 | response_mode | compact 默认,tree_summarize 适合多 Node 总结 |
| 8 | Hybrid Search | 向量 + BM25 混合,专治生僻词 |
| 9 | Rerank | 性价比最高的优化,10 粗筛 → 5 精排 |
| 10 | Small-to-Big | 小索引大窗口,SentenceWindow/AutoMerging |
| 11 | Workflows | v0.10+ 事件驱动框架,async + HITL |
| 12 | Agent 类型 | FunctionCallingAgent 优先,ReAct 调试用 |
| 13 | AgentWorkflow | 多 Agent 协作 + handoff |
| 14 | Multi-Modal | LlamaParse + MultiModalVectorStoreIndex |
| 15 | Graph RAG | PropertyGraphIndex + SimpleLLMPathExtractor |
| 16 | KnowledgeGraphIndex | 已弃用,被 PropertyGraphIndex 替代 |
| 17 | 评估 | Faithfulness 必用 + RAGAs 集成 |
| 18 | 性能优化 | async + streaming + cache + 小模型 + Rerank |
| 19 | 生产铁律 | 70% 功夫在数据,metadata 必须设计好 |
| 20 | 趋势 | Workflows + Agent + RAG 三件套 |
📚 参考资料
- LlamaIndex 官方文档:https://docs.llamaindex.ai
- LlamaIndex Deprecated Terms:https://developers.llamaindex.ai/python/framework/changes/deprecated_terms/
- LlamaIndex Workflows:https://docs.llamaindex.ai/en/stable/workflows/
- RAGAs 官方文档:https://docs.ragas.io/en/v0.1.21/howtos/integrations/llamaindex.html
- DeepEval + LlamaIndex:https://www.llamaindex.ai/blog/evaluating-rag-with-deepeval-and-llamaindex
- LlamaIndex Multi-Modal RAG:https://www.llamaindex.ai/blog/multi-modal-rag-621de7525fea
- CSDN 大模型面试题系列:https://blog.csdn.net/m0_59614665/article/details/152085484
- 腾讯云 LlamaIndex RAG 详解:https://cloud.tencent.com/developer/article/2629911
- CSDN LlamaIndex Workflows:https://blog.csdn.net/SearchB/article/details/159896003
- daily.dev LlamaIndex Hiring Guide:https://recruiter.daily.dev/stacks/llamaindex/
- CSDN LlamaIndex 高级使用:https://www.cnblogs.com/shouyin/p/19493867
- CSDN 属性图索引:https://blog.csdn.net/csdn122345/article/details/155579705
- CSDN AgentWorkflow 实战:https://blog.csdn.net/puzi0315/article/details/152566151
- theneuralbase Breaking Changes:https://theneuralbase.com/llamaindex-advanced/learn/beginner/version-upgrade-breaking-changes/
文档生成于 2025-2026 大模型面试备考季,配套大厂 AI/RAG 工程师岗位。如有错误欢迎指正。
本内容由 Coze AI 生成,请遵循相关法律法规及《人工智能生成合成内容标识办法》使用与传播。
评论区