RAG維保案例分享:如何實現(xiàn)"文+圖"的答案呈現(xiàn)
RAG一直被看成是大模型在企業(yè)應用落地的標準配置,基于企業(yè)內部文檔的問答,已經(jīng)解鎖出大量使用需求和場景。在這些眾多類型的文檔中,有相當一部分包含了各類復雜圖表,也就是所謂的多模態(tài)數(shù)據(jù)。
本篇以近期實施項目中的一個挖掘機維修場景為例,試圖給出一個針對標準化排版PDF 文檔(本文演示的固定格式維修手冊),使用基于坐標區(qū)域截取方法,結合Markdown 語法在回答中顯示圖片的示例,供大家參考。
以下,enjoy:
1、業(yè)務背景
說起挖掘機不禁讓人想到了藍翔,搜了下說是截止到 23 年年底,全國范圍的液壓挖掘機保有量在 200 萬臺左右。對于一名具體機主而言,在實際干活的過程中,可能碰到的來自發(fā)動機、電器、液壓、工作裝置等大大小小幾百個故障,這也讓專業(yè)的挖機維修需求一直很旺盛。
但對于維修人員而言,顯然有幾個一直以來的痛點沒有被很好解決,比如設備故障類型繁多,單靠個人經(jīng)驗難以覆蓋所有問題。再有就是傳統(tǒng)老帶新的模式下,培訓帶教周期過長等。
注:維修案例示例內容
后文會介紹一個基于包含 500 多個維修案例合集,開發(fā)的挖掘機故障診斷知識庫系統(tǒng),維修人員只需描述故障現(xiàn)象即可獲取相關案例,并支持圖文結合的答案呈現(xiàn),直觀展示故障部位和維修方法。
2、系統(tǒng)架構
注:本項目擴展自阿里云官方的 local_rag 示例,添加了本地 PDF 圖片提取和顯示功能,
?? 支持多種文檔類型(PDF、DOCX、TXT、XLSX、CSV)的上傳和處理
??? 智能 PDF 圖片提取與顯示
?? 本地知識庫構建與管理
?? 集成阿里云通義千問系列大語言模型
?? 支持非結構化數(shù)據(jù)和結構化數(shù)據(jù)處理
?? 可自定義 RAG 參數(shù)(召回數(shù)量、相似度閾值等)
3、核心技術實現(xiàn)
3.1文檔處理與圖片提取
系統(tǒng)提供了多種 PDF 圖片提取和處理方法,以適應不同場景需求:
1. 基于坐標的區(qū)域截?。ㄍ扑]方法)
針對標準化排版的文檔(如固定格式的維修手冊),使用基于坐標的精確截?。?/span>
def extract_images_from_maintenance_pdf(pdf_path, label_name):
image_mapping = {}
doc = fitz.open(pdf_path)
# 根據(jù)文檔格式定義的圖片區(qū)域坐標
image_rect = fitz.Rect(400, 160, 750, 320) # 右側中間區(qū)域
for page_index, page in enumerate(doc):
# 直接從固定區(qū)域截取圖片
pix = page.get_pixmap(matrix=fitz.Matrix(2, 2), clip=image_rect)
if is_valid_image(pix):
# 保存和映射圖片...
優(yōu)勢:
對固定格式文檔效果極佳
不受 PDF 內部圖像對象表示形式限制
可以捕獲矢量圖形和復合元素
提高圖片提取的準確率和質量
2. 基于對象標記的提取(備選方法)
使用 PyMuPDF 的內置功能識別 PDF 中的圖像對象:
def extract_images_from_pdf(pdf_path, label_name):
doc = fitz.open(pdf_path)
for page in doc:
image_list = page.get_images(full=True)
for img in image_list:
# 提取和處理圖片...
局限性:
僅能提取 PDF 中顯式存儲的圖像對象
無法提取矢量圖形或作為背景的圖片
可能會提取裝飾性元素或無關圖形
3. 其他優(yōu)化方案
基于內容分析的智能提取:結合文本標記定位圖片
多模態(tài) LLM 輔助:使用視覺模型輔助識別復雜文檔中的圖片
3.2圖片處理流程
3.3RAG 技術實現(xiàn)
分塊策略
系統(tǒng)針對不同類型的數(shù)據(jù)采用不同的分塊策略:
非結構化文檔:
documents = SimpleDirectoryReader(input_files=enhanced_files).load_data()
index = VectorStoreIndex.from_documents(documents)
結構化數(shù)據(jù):
nodes = []
for doc in documents:
doc_content = doc.get_content().split('\n')
for chunk in doc_content:
node = TextNode(text=chunk)
node.metadata = {'source': doc.get_doc_id()}
nodes = nodes + [node]
嵌入模型
默認使用通義千問文檔嵌入模型:
EMBED_MODEL = DashScopeEmbedding(
model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,
text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT,
)
# 若使用本地嵌入模型,請取消以下注釋:
# from langchain_community.embeddings import ModelScopeEmbeddings
# from llama_index.embeddings.langchain import LangchainEmbedding
# embeddings = ModelScopeEmbeddings(model_id="modelscope/iic/nlp_gte_sentence-embedding_chinese-large")
# EMBED_MODEL = LangchainEmbedding(embeddings)
檢索策略
采用兩階段檢索策略:
向量相似度初篩:
retriever_engine = index.as_retriever(similarity_top_k=20)
retrieve_chunk = retriever_engine.retrieve(prompt)
語義重排序:
dashscope_rerank = DashScopeRerank(top_n=chunk_cnt)
results = dashscope_rerank.postprocess_nodes(retrieve_chunk, query_str=prompt)
注:比較初步的檢索策略,可根據(jù)實際情況進行調整
4. 圖片鏈接處理
只保留最相關文本塊中的圖片鏈接
移除其他文本塊的圖片鏈接
使用 Markdown 語法在回答中顯示圖片
prompt_template = """請參考以下內容,僅使用第一個最相關文本塊中的圖片鏈接。
如果在第一個文本塊中看到"圖片鏈接:",將其轉換為Markdown圖片語法。
請忽略其他文本塊中的圖片鏈接。
"""
4、使用指南
4.1上傳數(shù)據(jù)
系統(tǒng)支持兩種文件上傳方式:臨時上傳:直接在 RAG 問答頁面上傳文件,臨時使用
創(chuàng)建知識庫:在"上傳數(shù)據(jù)"頁面中上傳文件,并在"創(chuàng)建知識庫"頁面構建永久知識庫
支持的文件類型
非結構化數(shù)據(jù):PDF、DOCX、TXT
結構化數(shù)據(jù):XLSX、CSV
4.2創(chuàng)建知識庫
進入"創(chuàng)建知識庫"頁面
選擇已上傳的類目或數(shù)據(jù)表
設置知識庫名稱
點擊"確認創(chuàng)建知識庫"
4.3RAG 問答
flowchart TD
A[用戶提問] --> B[獲取知識庫]
B --> C[檢索相關文檔]
C --> D[重排序文檔]
D --> E[構建提示詞]
E --> F[調用大語言模型]
F --> G[生成回答]
G --> H[顯示回答及圖片]
5、項目結構
main.py - FastAPI 應用入口和 Gradio 界面定義
chat.py - RAG 問答核心功能和大模型調用
upload_file.py - 文件上傳和處理邏輯,包括 PDF 圖片提取
create_kb.py - 知識庫創(chuàng)建和管理
html_string.py - Web 界面 HTML 模板
File/ - 存放上傳的文件
VectorStore/ - 存放向量數(shù)據(jù)庫
static/images/ - 存放提取的圖片
images/ - UI 頭像圖片
6、自定義與擴展
修改嵌入模型
可以使用本地嵌入模型替代云端 API。
在create_kb.py和chat.py中取消相關注釋并安裝額外依賴。
優(yōu)化提示詞模板
修改chat.py中的prompt_template變量以定制提示詞模板。
添加新的文檔類型支持
擴展upload_file.py中的處理邏輯以支持更多文件類型。