
市面上的开箱即用知识库工具虽然简单,但一旦业务需要深度接入自己的 CRM 数据库、实现复杂的动态权限过滤,或者要针对行业特定文档做高度定制的检索排序,图形界面的死板限制就会暴露无遗。
对于开发者来说,直接用代码构建知识库是掌控力最高的方案。而在 Python 研发领域,LangChain 和 LlamaIndex 是两大绕不开的核心框架。很多人纠结到底该用哪一个,其实它们在知识库架构中的分工完全不同:LlamaIndex 专精于深度的索引切分与高效检索,而 LangChain 则长于复杂的多工具调度与应用链编排。今天我们就用最清晰的代码,把这两个框架自建知识库的核心链路彻底打通。
两大框架定位与架构分工对比
在编写代码前,理清它们的底层哲学能帮你少走很多弯路:
| 评估维度 | LlamaIndex | LangChain | 生产级结合推荐 |
|---|---|---|---|
| 核心定位 | 数据索引与检索专家(Data Framework for LLM) | 通用大模型应用编排引擎(Application Orchestration) | 用 LlamaIndex 做检索内核,LangChain 做流程调度 |
| 文档解析与切块 | 极强(内置丰富高级分块器、父子节点索引) | 良好(通用文本拆分器与多种加载器) | 数据入库层首选 LlamaIndex 管道 |
| 高级检索技术 | 原生支持 Auto-Merging、Sentence Window、多路重排 | 依赖扩展模块与自定义 Chain 组装 | 复杂研报长文深度检索推荐 LlamaIndex |
| Agent与工具扩展 | 基础(聚焦在知识库 Query Engine 上) | 极强(海量第三方生态生态与 Tool 库) | 外部 API 与自动化任务调用推荐 LangChain |
实战一:基于 LlamaIndex 搭建高性能知识库内核
LlamaIndex 的强项在于仅需几行代码就能完成从非结构化文档到带索引的向量引擎转换。
1. 核心依赖安装
pip install llama-index llama-index-llms-openai llama-index-embeddings-openai chromadb
2. 向量索引与持久化存储实战
下面的代码演示了如何使用 LlamaIndex 加载本地目录下的所有技术 Markdown 文档,完成切块后持久化存入 Chroma 向量数据库:
import os
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, StorageContext, Settings
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
import chromadb
# 1. 基础模型配置(使用高性价比接口,如 DeepSeek 或通义千问)
Settings.llm = OpenAI(model="deepseek-chat", api_base="https://api.deepseek.com", api_key="sk-xxx")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small", api_key="sk-xxx")
# 2. 读取本地文件夹文档
documents = SimpleDirectoryReader("./data/docs").load_data()
# 3. 初始化本地持久化 ChromaDB
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_or_create_collection("tech_kb")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# 4. 构建并落盘索引
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
# 5. 组装查询引擎并实测提问
query_engine = index.as_query_engine(similarity_top_k=4)
response = query_engine.query("请总结微服务架构设计文档中提到的降级熔断策略。")
print("【回答内容】:", response.response)
print("【引用来源】:", [node.node.metadata.get("file_name") for node in response.source_nodes])
实战二:基于 LangChain 封装带自定义逻辑的 RAG Chain
当你的知识库需要根据用户的会员等级、所属部门做动态过滤,或者需要在回答前执行前置合规审查时,LangChain 最新的 LCEL(LangChain Expression Language) 提供了极简的管道编排能力。
1. 核心依赖安装
pip install langchain langchain-openai langchain-community langchain-core
2. 构建可控的检索生成管道
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 1. 加载持久化向量库与检索器
embeddings = OpenAIEmbeddings(model="text-embedding-3-small", api_key="sk-xxx")
vector_db = Chroma(persist_directory="./chroma_db", embedding_function=embeddings)
retriever = vector_db.as_retriever(search_type="similarity", search_kwargs={"k": 3})
# 2. 定义严格对齐业务的提示词模版
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一名严谨的软件架构专家。必须仅根据提供的上下文作答。如果不知道,直接回答不知道,严禁编造。nn【参考上下文】:n{context}"),
("human", "{question}")
])
llm = ChatOpenAI(model="deepseek-chat", base_url="https://api.deepseek.com", api_key="sk-xxx", temperature=0.1)
# 3. 辅助函数:格式化检索到的文档块
def format_docs(docs):
return "nn".join(f"[文档片段: {d.metadata.get('source', '')}]n{d.page_content}" for d in docs)
# 4. 组装 LCEL 极简生产链
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt_template
| llm
| StrOutputParser()
)
# 5. 执行调用
answer = rag_chain.invoke("生产环境遇到内存泄漏时,排查的标准SOP是什么?")
print(answer)
生产级落地的四大核心优化建议
1.引入父子节点索引(Parent-Document Retrieval):传统切块如果切得小,语义精确但上下文缺失;切得大,上下文完整但向量表示太泛化。使用 LlamaIndex 的 `SentenceWindowNodeParser`,检索时只用核心句子做相似度匹配,递给大模型时自动抓取前后 3 句话的完整窗口,检索召回率提升明显。
2.务必串联重排序模型(Reranker):初级向量相似度只能作为粗筛。在代码管道最后加上一行 `BGERerank`,在召回的 Top-10 候选中精打细算选出最相关的 Top-3,能直接砍掉一半的大模型幻觉。
3.元数据过滤(Metadata Filtering)优先于语义检索:多租户场景下,不要让大模型去辨别这篇文档属于哪个部门。在存储阶段就把 `department: ‘finance’` 写入向量元数据,检索时直接通过原生条件硬过滤。
4.控制返回 Token 成本:在 Prompt 中明确要求“如果检索内容无关,仅返回‘未查询到相关记录’并停止生成”,避免模型在无意义的检索切片上耗费大量昂贵的生成算力。
原创文章,作者:七点互动,如若转载,请注明出处:https://ai.qidianhudong.com/aikonw/3596.html