RAG
定義:檢索增強生成(Retrieval Augmented Generation),簡稱 RAG,已經成為當前最火熱的LLM應用方案。
目的:通過提供相關領域數據庫通過問題檢索信息,將相關信息合并到Prompt中,增強模型的專業性。
深入淺出RAG技術:
RAG=檢索技術+LLM提示
//LLM提示就是之前文章中提到過的promt工程,這里不再贅述,主要理解檢索技術
檢索技術
2019年,Faiss就實現了基于嵌入的向量搜索技術,但是 RAG 推動了向量搜索領域的發展。比如 chroma、weaviate.io和 pinecone這些基于開源搜索索引引擎(主要是 faiss 和 nmslib)向量數據庫初創公司,最近增加了輸入文本的額外存儲和其他工具。
向量化是將文本數據轉化為向量矩陣的核心過程,通常使用embedding模型來實現,常用的模型:
模型名稱 | 描述 |
ChatGPT-Embedding | ChatGPT-Embedding由OpenAI公司提供,以接口形式調用。 |
ERNIE-Embedding V1 | ERNIE-Embedding V1由百度公司提供,依賴于文心大模型能力,以接口形式調用。 |
M3E | M3E是一款功能強大的開源Embedding模型,包含m3e-small、m3e-base、m3e-large等多個版本,支持微調和本地部署。 |
BGE | BGE由北京智源人工智能研究院發布,同樣是一款功能強大的開源Embedding模型,包含了支持中文和英文的多個版本,同樣支持微調和本地部署。 |
本項目使用的模型為BAAI/bge-large-zh-v1.5BAAI/bge-small-zh,特點是體積小且適合中文。
向量數據庫:數據向量化后構建索引,并寫入數據庫的過程可以概述為數據入庫過程,適用于RAG場景的數據庫包括:FAISS、Chromadb、ES、milvus等,本項目選擇的數據庫為FAISS。
當我們要在數據庫中尋找與問題相關的數據時常用的方法:
常見計算方法:k-臨近
數據距離計算方法:歐式距離、曼哈頓距離、明科夫斯基距離。
RAG工作原理:
?
數據庫構建并應用
前期準備
環境
有兩個最著名的基于 LLM 的管道和應用程序的開源庫——LangChain 和 LlamaIndex,受 ChatGPT 發布的啟發,它們在 2022 年 10 月和 11 月創立,并在 2023 年獲得大量采用。
本項目使用的開源庫為LangChain。
數據積累
數據來源:https://github.com/LawRefBook/Laws
該項目目的是收集各類法律法規、部門規章、案例等,并將其按照章節等信息進行了處理。
項目提供了request.py
?腳本,支持從?BAAI/bge-large-zh-v1.5?爬取最新的法律法規。
數據庫構建
目錄結構
讀取數據
# 遍歷 Markdown 文件
docs = []
root_dir = Path("data/Laws-master/LAWS")
md_files = {}
for dir_name in os.listdir(root_dir):dir_path = os.path.join(root_dir, dir_name)if os.path.isdir(dir_path): # 確保是文件夾md_files[dir_name] = {}for file_name in os.listdir(dir_path):if file_name.endswith(".md"):
選擇分詞器并加載嵌入模型
embedding_model = HuggingFaceEmbeddings(model_name="../models/BAAI/bge-small-zh")
splitter = MarkdownTextSplitter(chunk_size=500, chunk_overlap=50)
構建數據庫
file_path = os.path.join(dir_path, file_name)loader = TextLoader(str(file_path), encoding='utf-8')raw_docs = loader.load()split_docs = splitter.split_documents(raw_docs)docs.extend(split_docs)
vectorstore = FAISS.from_documents(docs, embedding_model)
vectorstore.save_local("faiss_index")
數據庫應用
?
def rag_ask(question, top_k=2):# 檢索相關法條docs = db.similarity_search(question, k=top_k)# print(docs)#生成前k個相關的問題context = "\n\n".join([doc.page_content for doc in docs])print(context)prompt = f"""你是中國法律助手,請根據以下法條內容回答問題:
【法條內容】:
{context}【用戶問題】:{question}
【回答】:
"""print(prompt)response = pipe(prompt, max_new_tokens=512)[0]['generated_text']print(response[len(prompt):].strip())
效果展示
prompt
回答結果