本文是 refine-rag 系列教程的第一篇,帶你體驗(yàn)一下 RAG 的簡單流程。
本文所有代碼都在:https://github.com/zonezoen/refine-rag
前言
在學(xué)習(xí) RAG 之前,我們先來對比一下 RAG 和 AI Agent 的概念,只有先了解這些概念,才能繼續(xù)往前推進(jìn)。
什么是RAG
簡單來說就是允許你查閱書本,再來回答問題。
標(biāo)準(zhǔn)一點(diǎn)來說(也是簡化過的):
- 整理原始文檔,比如:pdf、word、excel、ppt 等
- 把整理好的文檔內(nèi)容進(jìn)行清洗、切塊
- 把切塊好的數(shù)據(jù)向量化,并存儲到向量數(shù)據(jù)庫中
- 用戶問一個問題
- 把這個問題的字符串向量化
- 然后根據(jù)【問題向量】去向量數(shù)據(jù)庫查找相似的知識點(diǎn)
- 把查到的知識和問題一起傳遞給大模型
- 大模型根據(jù)查到的知識點(diǎn)來回答問題
當(dāng)然了,這個流程也是簡化過的,不過不用在意,這個只是便于你理解這個概念。
還有你需要知道的是:RAG 可以解決一些時效性的問題和幻覺問題。相比 Fing-turning 微調(diào),RAG 更節(jié)省成本,而且數(shù)據(jù)可以溯源,可以知道相關(guān)的知識點(diǎn)源自哪個文檔。
或許看這個流程圖或許會更直觀一點(diǎn)
[圖片上傳失敗...(image-dc436d-1772686621447)]
什么是AI Agent
如果把 RAG 比作是查知識庫,那么 AI Agent 就是可以執(zhí)行具體任務(wù)的助手。主要包括這幾個特點(diǎn):
- 規(guī)劃:規(guī)劃步驟,比如說買機(jī)票可以先查日期,再查天氣,然后買機(jī)票
- 記憶:可以記住聊天上下文
- 工具使用:可以決定使用查天氣的 API 還是執(zhí)行一段 Python 代碼
- 執(zhí)行:規(guī)劃好之后,可以執(zhí)行具體的任務(wù),并根據(jù)結(jié)果來執(zhí)行下一步任務(wù)
主流RAG框架
目前主流的 RAG 框架有 LlamaIndex、langchain、Dify 等,我這邊選擇前面兩個來做個示例:
大模型也分別選了 千問和 DeepSeek 來做展示:
環(huán)境準(zhǔn)備
1. Python 環(huán)境要求
- Python 3.8 或更高版本(推薦 3.10+)
- 建議使用虛擬環(huán)境
2. 安裝依賴包
LlamaIndex 示例所需依賴:
pip install llama-index
pip install llama-index-llms-dashscope
pip install llama-index-embeddings-dashscope
pip install dashscope
pip install python-dotenv
LangChain 示例所需依賴:
pip install langchain
pip install langchain-community
pip install langchain-huggingface
pip install langchain-deepseek
pip install langchain-text-splitters
pip install python-dotenv
pip install sentence-transformers # HuggingFace embeddings 依賴
一鍵安裝所有依賴:
pip install llama-index llama-index-llms-dashscope llama-index-embeddings-dashscope \
dashscope langchain langchain-community langchain-huggingface \
langchain-deepseek langchain-text-splitters python-dotenv sentence-transformers
3. API Key 配置
本文所有代碼都在:https://github.com/zonezoen/refine-rag
創(chuàng)建 .env 文件,放到項(xiàng)目根目錄:
# DeepSeek API 配置
DEEPSEEK_API_KEY=sk-xxx
# 千問
DASHSCOPE_API_KEY=sk-yyy
如何獲取 API Key:
- DeepSeek: https://platform.deepseek.com/
- 千問(DashScope): https://dashscope.aliyun.com/
LlamaIndex 示例(千問)
文件名: 01_LlamaIndex.py
import os
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModels
from llama_index.embeddings.dashscope import DashScopeEmbedding
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from dotenv import load_dotenv
os.environ['USER_AGENT'] = 'my-rag-app/1.0'
load_dotenv()
DATA_DIR = "./data"
# 1. 配置 LLM
Settings.llm = DashScope(
model_name=DashScopeGenerationModels.QWEN_MAX,
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 2. 設(shè)置嵌入模型
Settings.embed_model = DashScopeEmbedding(
model_name='text-embedding-v2',
api_key=os.getenv("DASHSCOPE_API_KEY"),
timeout=60, # 增加超時時間
max_retries=5 # 增加重試次數(shù)
)
# 3. 加載與索引
if not os.path.exists(DATA_DIR):
print(f"錯誤:未找到路徑 {DATA_DIR}")
else:
# 建議直接使用絕對路徑,避免相對路徑帶來的困擾
print("正在加載文檔...")
documents = SimpleDirectoryReader(DATA_DIR).load_data()
print("正在創(chuàng)建索引(此步涉及 Embedding 接口調(diào)用)...")
index = VectorStoreIndex.from_documents(documents)
# 4. 查詢
query_engine = index.as_query_engine()
print("正在提問...")
response = query_engine.query("2026春運(yùn)時間是什么時候?")
print(f"AI 回答結(jié)果:\n{response}")
運(yùn)行方式:
python 01_LlamaIndex.py
運(yùn)行結(jié)果:
正在加載文檔...
正在創(chuàng)建索引(此步涉及 Embedding 接口調(diào)用)...
正在提問...
AI 回答結(jié)果:
2026年春運(yùn)的時間是從2月2日至3月13日。
LangChain 示例(DeepSeek)
文件名: 02_LangChain_DeepSeek.py
import os
from dotenv import load_dotenv
os.environ['USER_AGENT'] = 'my-rag-app/1.0'
load_dotenv()
# 1. 加載數(shù)據(jù)
from langchain_community.document_loaders import TextLoader
# 隨便復(fù)制一些即時新聞放到 txt 文件中,例如:https://baike.baidu.com/item/2026%E5%B9%B4%E6%98%A5%E8%BF%90/66941026?fromModule=home_hotspot
loader = TextLoader(
file_path="data/a.txt",
encoding="utf-8" # 如果是中文文件,確保使用 utf-8 編碼
)
docs = loader.load()
# 2. 文檔分塊
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
all_splits = text_splitter.split_documents(docs)
# 3. 設(shè)置嵌入模型
# 使用本地 HuggingFace 模型(推薦,免費(fèi)且穩(wěn)定),可能需要科學(xué)網(wǎng)絡(luò)
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-small-zh-v1.5", # 中文模型
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
# 4. 存到向量數(shù)據(jù)庫中,為了方便測試,這里使用內(nèi)存數(shù)據(jù)庫
from langchain_core.vectorstores import InMemoryVectorStore
vector_store = InMemoryVectorStore(embeddings)
vector_store.add_documents(all_splits)
# 5. 構(gòu)建用戶查詢,針對前面的即時新聞提問
question = "2026春運(yùn)時間是什么時候?"
# 6. 在向量數(shù)據(jù)庫中搜索最相似的文檔
retrived_docs = vector_store.similarity_search(question, k=3)
docs_content = "\n\n".join(doc.page_content for doc in retrived_docs)
# 7. 構(gòu)建提示模板
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template(
"""
基于以下上下文回答問題。如果沒有結(jié)果,就說沒有找到對應(yīng)信息。
上下文: {context}
問題: {question}
回答:
"""
)
# 8. 把結(jié)果和問題都發(fā)給大模型,生成答案
from langchain_deepseek import ChatDeepSeek
llm = ChatDeepSeek(
model="deepseek-chat", # DeepSeek API 支持的模型名稱
temperature=0.7, # 隨機(jī)性
max_tokens=2048, # 最大輸出長度
api_key=os.getenv("DEEPSEEK_API_KEY") # 從環(huán)境變量加載API key
)
answer = llm.invoke(prompt.format(question=question, context=docs_content))
print(answer.content) # 只打印回答內(nèi)容
運(yùn)行方式:
python 02_LangChain_DeepSeek.py
運(yùn)行結(jié)果:
2026年春運(yùn)時間為2026年2月2日至2026年3月13日。
學(xué)習(xí)路徑
- 簡易RAG 學(xué)習(xí)
- LCEL 語法學(xué)習(xí)
- LangChain 讀取數(shù)據(jù)
- LangChain 讀取文本數(shù)據(jù)
- LangChain 讀取圖片數(shù)據(jù)
- LangChain 讀取 PDF 數(shù)據(jù)
- LangChain 讀取表格數(shù)據(jù)
- 文本切塊
- 向量嵌入
- 向量存儲
- 檢索前處理
- 索引優(yōu)化
- 檢索后處理
- 響應(yīng)生成
- 系統(tǒng)評估
項(xiàng)目地址
本文所有代碼示例都在 GitHub 開源:
https://github.com/zonezoen/refine-rag
歡迎 Star 和 Fork,一起學(xué)習(xí) RAG 技術(shù)!