- ? RAG 是什么
- ? Reranker 是什么
- ? embedding 是什么
-
? chunk分塊 是什么
h7.png
業(yè)務(wù)場景
這里要說明的是,大模型本身不會聯(lián)網(wǎng)、知識有限的,例如:"娛樂圈今天xxx出軌了"大模型是不知道的,你數(shù)據(jù)庫里有一些資料文件大模型也是不知道的!
A 股現(xiàn)在上市有五六千家,每個季度都會公布一份pdf文件財報,一份財報文件少說有十幾頁,多的有上百頁,現(xiàn)在我們要做一個AI搜索功能
按照2年的數(shù)據(jù)量,5000 X 4 X 2 = 40000 份文件要存入數(shù)據(jù)庫中
這個量已經(jīng)非常的大了,現(xiàn)在要做一個大模型搜索功能,比如你詢問 茅臺2025年第一季度凈利潤多少?
在以前大模型沒有誕生的年代,通常的做法是
- 將這4W份pdf解析成文字,存入數(shù)據(jù)庫或者elasticsearch
- 將問題
茅臺2025年第一季度凈利潤多少?進(jìn)行分詞拆分
2.1 例如es的ik分詞器拆分為茅臺2025第一季度凈利潤多少?
2.2 進(jìn)行es的打分搜索,取出來分值靠前的幾個pdf文件 - 如果使用mysql的話,也可以將整句話進(jìn)行全文/like搜索(沒幾個人這么干)
這種方式會將與關(guān)鍵詞有關(guān)聯(lián)的原始文章搜索出來
現(xiàn)在有了大模型,要對大模型進(jìn)行數(shù)據(jù)交互,發(fā)送大模型的提示詞可以寫
請讀取是我的資料庫,回答我的問題 "茅臺2025年第一季度凈利潤多少?"
4萬份pdf文件解析的財報文本……
……
……
然后你就會發(fā)現(xiàn),4W份pdf文件解析的文本一并發(fā)送給了大模型,token直接干了上千萬。。。。
但即使你使用上面的步驟搜索出來的有關(guān)聯(lián)原始文章發(fā)給大模型,也會有兩個問題
- 即使是幾篇pdf,token也是非常之大
- 由于全靠詞的相似度進(jìn)行搜索,里面沒有自然語言的理解成分在內(nèi),例如中石化的財報里提到了
2025年茅臺第一季度與我公司合作這幾個字,也會被搜出來,其實與我們要問的問題八桿子打不著
下面,我們以一種高效的、自然語言方式的存儲搜索方法來實現(xiàn)
檢索增強(qiáng)生成(RAG)
步驟一:原始數(shù)據(jù)解析
例如,我們的4萬份A股財報,我們對其預(yù)處理,其中可能會有html、pdf、word、text格式文件,我們在程序上進(jìn)行適配解析,確保能夠解析成為文本,這里面有幾個技術(shù)點需要自己慢慢磨、調(diào)試,這是一個很折磨的過程!
- 文件中有圖片的,如果也要解析,就要引入ocr識別
- 有一些文件內(nèi)容有大范圍的空格,例如pdf換頁的時候,段落會有數(shù)行的空格,看是否需要保留
- 表格、目錄、標(biāo)題、圖表等,這類內(nèi)容解析成文本時格式異常的錯亂無序
- ……
LangChain 提供了很多種文件解析方案,但如果要做到精益求精,也得需要對解析結(jié)果格式不斷的測試
步驟二:解析分塊chunk
? 4萬份 pdf 文件解析成文本后,存入數(shù)據(jù)庫中的數(shù)據(jù)是4萬表記錄么?
? 茅臺的財報pdf文件85頁,講 凈利潤 的只有短短兩句話,你要把整個pdf文件發(fā)給大模型么?
我們有提到過,有些單個文件里面的內(nèi)容非常之大,例如 中石化1個季度的財報pdf文件有80多頁,這種內(nèi)容是很多的,我們應(yīng)當(dāng)對單個 pdf 文件或其他類型的文件,再進(jìn)行拆分分割,例如有這么幾種方式
- 直接按照pdf頁碼拆分,一頁到了強(qiáng)制分割(這會出現(xiàn)一段話跨頁時被分成了2塊)
- 按照內(nèi)容的token數(shù)量,例如 800 個token切割一次(token是干嘛的自行g(shù)g)
- 按照自然語言進(jìn)行拆分,例如 一段 或者 兩段 完整的段落切塊一次
這里和步驟一一樣,是一個技術(shù)打磨的過程,這里不在細(xì)講
LangChain 是個偉大解決方案框架,也為文件內(nèi)容分塊做了很多基礎(chǔ)方法封裝,上面列的幾種情況都有現(xiàn)成的方法可供調(diào)用
這樣,一個原始文件就被拆分成了>=1個字文件內(nèi)容
步驟三:向量化
將自然語言文本(如單詞、句子或段落)轉(zhuǎn)換為數(shù)值向量(即一串?dāng)?shù)字)的過程。
例如,有一段很長的內(nèi)容
2月3日,媒體報道稱從權(quán)威渠道獲悉,浙江天臺夫妻食用網(wǎng)購?fù)尥薏撕蟊辉\斷出老鼠藥中毒一案,警方進(jìn)一步偵查發(fā)現(xiàn),下毒者系楊女士的丈夫,目前涉事男子已被警方采取刑事強(qiáng)制措施,案件還在進(jìn)一步調(diào)查之中。
3日,紅星新聞記者聯(lián)系當(dāng)?shù)毓俜饺耸?,對方表示上述報道“部分不屬實”“警方還在進(jìn)一步調(diào)查”。紅星新聞了解到,楊女士丈夫系陳某波,二人已結(jié)婚十幾年。二人家鄉(xiāng)的村支書表示,夫妻二人平時關(guān)系很好,村民均反映沒有什么矛盾。
3日下午,紅星新聞從浙江臺州天臺縣相關(guān)官方人士處進(jìn)一步了解到,警方在進(jìn)一步偵查過程中發(fā)現(xiàn),丈夫的下毒行為系夫妻雙方共謀,兩人試圖通過網(wǎng)購?fù)尥薏耸秤煤笾圃熘卸聚E象,以此要挾,向平臺或商家騙取巨額賠償。但最終被警方偵查識破。
該人士指出,“他其實不是給他老婆下毒”,夫妻二人為了騙取錢財“自己給自己下毒”。目前,楊女士、陳某波均已被刑拘。
對此,紅星新聞記者也詢問了夫妻二人家鄉(xiāng)的村支書。村支書告訴紅星新聞,1月31日,他和另一名村干部出于對村民的關(guān)愛,去縣醫(yī)院探望楊女士、陳某波,夫妻二人均尚在病房治療,“楊女士血液里的老鼠藥毒素還沒清除干凈”。2月3日看到新聞后,村支書多次撥打二人電話,希望了解真實情況,但已無人接聽
將其轉(zhuǎn)化為完整的轉(zhuǎn)換成向量,例如阿里云提供了 1024 緯度的文本向量轉(zhuǎn)換API,這個轉(zhuǎn)化過程就稱為 embedding
大致長這樣 [0.23232323, 0.2389273923,0.237943934,0.984973924..............] 類似一個1024個元素的數(shù)組
截至2024年3月份是這么用的,現(xiàn)在是2026年,據(jù)說一些云數(shù)據(jù)庫pgsql內(nèi)部自帶embedding方法了
步驟四:存儲
| id | aid(源文件) | chunk_id(分塊id) | content(內(nèi)容) | embedding(向量值) |
|---|---|---|---|---|
| 1 | 1 | 1 | 2月3日,媒體報道稱從權(quán)威渠道獲悉,浙江天臺夫妻食用網(wǎng)購?fù)尥薏撕蟊辉\斷出老鼠藥中毒一案,警方進(jìn)一步偵查發(fā)現(xiàn),下毒者系楊女士的丈夫,目前涉事男子已被警方采取刑事強(qiáng)制措施,案件還在進(jìn)一步調(diào)查之中。 | [0.23232323, 0.2389273923,0.237943934,0.984973924..............] |
| 2 | 1 | 2 | 3日,紅星新聞記者聯(lián)系當(dāng)?shù)毓俜饺耸?,對方表示上述報道“部分不屬實”“警方還在進(jìn)一步調(diào)查”。紅星新聞了解到,楊女士丈夫系陳某波,二人已結(jié)婚十幾年。二人家鄉(xiāng)的村支書表示,夫妻二人平時關(guān)系很好,村民均反映沒有什么矛盾。 | [0.23232323, 0.2389273923,0.237943934,0.984973924..............] |
| 3 | 1 | 3 | 3日下午,紅星新聞從浙江臺州天臺縣相關(guān)官方人士處進(jìn)一步了解到,警方在進(jìn)一步偵查過程中發(fā)現(xiàn),丈夫的下毒行為系夫妻雙方共謀,兩人試圖通過網(wǎng)購?fù)尥薏耸秤煤笾圃熘卸聚E象,以此要挾,向平臺或商家騙取巨額賠償。但最終被警方偵查識破。 | [0.23232323, 0.2389273923,0.237943934,0.984973924..............] |
| 4 | 1 | 4 | 對此,紅星新聞記者也詢問了夫妻二人家鄉(xiāng)的村支書。村支書告訴紅星新聞,1月31日,他和另一名村干部出于對村民的關(guān)愛,去縣醫(yī)院探望楊女士、陳某波,夫妻二人均尚在病房治療,“楊女士血液里的老鼠藥毒素還沒清除干凈”。2月3日看到新聞后,村支書多次撥打二人電話,希望了解真實情況,但已無人接聽 | [0.23232323, 0.2389273923,0.237943934,0.984973924..............] |
這是一個表結(jié)構(gòu),我們將一個文件內(nèi)容,分成了4塊,并分別進(jìn)行了向量化存儲
目前,postgresql數(shù)據(jù)庫的Vector,是用的多的向量存儲數(shù)據(jù)類型(這里要測試一下,Vector字段是否能夠有效命中索引)
步驟五:搜索
queryDb.Raw("select id, aid, page_index, chunk_index, doc, 1-(embedding <=> ?) as score from reportify_chunk_embedding_test where article_category=? and 1-(embedding <=> ?) > ? order by score desc limit ?", sliceStr, base.Category, sliceStr, threshold, limit).Scan(&result)
上面是一個真實的向量字段搜索sql
postgresql 提供了向量字段,也提供了對應(yīng)的 sql 搜索方式,例如余弦搜索
例如你詢問,茅臺有多少位股東,我們將這句話轉(zhuǎn)化為向量值,然后通過余弦搜索sql去表里面搜全表,取出來前10條記錄拿去使用
注意,文本=>embedding 的過程,結(jié)果值是非冪等的,且不能混用的
- 有1000份文本需要向量化入庫,
- 前500條使用阿里云的 embedding api 入庫
- 后500條使用百度的 embedding api 入庫
這時去通過 sql 去查庫,查出來的肯定是不精準(zhǔn)的
檢索增強(qiáng)生成(Reranker)
向量搜索有個非常雞肋的缺點,幻聽嚴(yán)重
例如,你詢問 茅臺董事長叫什么? 向量搜索的10條記錄,排名第一的可能是包含 茅臺的股東是誰、茅臺的老板是誰之類的原文所在段落,包含茅臺的董事長的段落可能在地第5條
這時候需要重新拍一下序,來更一步精確打分與問題解決的記錄
這個就叫做 Reranker(重排序器),也是很多的商業(yè)API可供調(diào)用
這個過程屬于精確優(yōu)化內(nèi)容,例如你通過向量搜索從海量數(shù)據(jù)表中取出來10條記錄,再通過 Reranker 排個序,獲取前 3 條記錄,扔給大模型,從而提高內(nèi)容僅準(zhǔn)率,也節(jié)省了token
