戰(zhàn):從財(cái)報(bào)解析到可信問(wèn)答的完整鏈路搭建)
把一份五十頁(yè)的年度財(cái)報(bào)丟給大模型讓它準(zhǔn)確說(shuō)出“去年第四季度毛利率是多少比第三季度變化了多少”你會(huì)得到什么如果直接問(wèn)通用大模型它大概率會(huì)給你一個(gè)看似合理、其實(shí)是編出來(lái)的數(shù)字。這正是我想通過(guò) Financial RAG Demo 解決的核心問(wèn)題用一條完整的RAG服務(wù)鏈路把金融文檔變成可問(wèn)答、可溯源、可驗(yàn)證的“本地知識(shí)庫(kù)”。這篇內(nèi)容會(huì)完整拆解這個(gè)Demo從文檔解析、切片、向量檢索到生成回答的整個(gè)設(shè)計(jì)與實(shí)操過(guò)程適合正在做知識(shí)庫(kù)問(wèn)答、金融NLP場(chǎng)景或者剛接觸RAG應(yīng)用開(kāi)發(fā)的同學(xué)參考。金融場(chǎng)景對(duì)RAG的要求和通用文檔問(wèn)答不太一樣數(shù)據(jù)密度高、術(shù)語(yǔ)密集、表格多、對(duì)數(shù)字準(zhǔn)確性要求極高。整個(gè)Demo做完我最大的感受是RAG服務(wù)的難點(diǎn)不在“接入大模型”而在前面的數(shù)據(jù)準(zhǔn)備和檢索質(zhì)量。鏈路中任何一個(gè)環(huán)節(jié)偷懶最后都會(huì)在回答質(zhì)量上暴露出來(lái)。下面直接進(jìn)入正題按我實(shí)際開(kāi)發(fā)的順序把所有關(guān)鍵技術(shù)決策和踩坑經(jīng)驗(yàn)逐一講清楚。1. 為什么做Financial RAG Demo金融場(chǎng)景對(duì)RAG服務(wù)的特殊要求1.1 金融文檔問(wèn)答難在哪里金融領(lǐng)域的文檔管理是個(gè)典型的海量數(shù)據(jù)場(chǎng)景。上市公司的年報(bào)、季報(bào)、臨時(shí)公告、研報(bào)、監(jiān)管政策文件動(dòng)輒幾十上百頁(yè)P(yáng)DF格式居多內(nèi)部還塞滿了財(cái)務(wù)報(bào)表、管理層討論、腳注注釋。過(guò)去這些文檔的利用方式基本就是“存起來(lái)、搜出來(lái)、人肉看”想要跨文檔得到一個(gè)綜合性的答案效率非常低。我把這個(gè)項(xiàng)目定位在“金融文檔問(wèn)答”而不是泛泛的“聊天機(jī)器人”就是因?yàn)榻鹑趩?wèn)答有幾個(gè)很難繞開(kāi)的痛點(diǎn)。第一個(gè)痛點(diǎn)是術(shù)語(yǔ)密集。像“毛利率”“凈資產(chǎn)收益率”“經(jīng)營(yíng)活動(dòng)產(chǎn)生的現(xiàn)金流量?jī)纛~”這種表述一個(gè)概念有多種叫法縮寫(xiě)和全稱(chēng)混用。通用問(wèn)答系統(tǒng)很難理解這些術(shù)語(yǔ)之間的關(guān)聯(lián)檢索時(shí)容易出現(xiàn)“關(guān)鍵詞命中了但拿到的段落根本不是用戶想問(wèn)的那個(gè)指標(biāo)”。第二個(gè)痛點(diǎn)是數(shù)字敏感。金融問(wèn)答最怕胡說(shuō)一個(gè)人問(wèn)“去年研發(fā)投入多少錢(qián)”如果系統(tǒng)回答里數(shù)字跟真實(shí)財(cái)報(bào)對(duì)不上這個(gè)系統(tǒng)基本就失去信任了。數(shù)字對(duì)錯(cuò)的根源往往不在大模型而在檢索階段有沒(méi)有把正確的表格和上下文段落召回來(lái)。RAG服務(wù)如果不針對(duì)表格做專(zhuān)門(mén)處理檢索到的內(nèi)容經(jīng)常是殘缺的。第三個(gè)痛點(diǎn)是來(lái)源必須可溯。“根據(jù)哪份報(bào)告、哪一頁(yè)得出這個(gè)結(jié)論”在金融場(chǎng)景幾乎是剛需?;鸾?jīng)理、風(fēng)控人員、研究員拿到一個(gè)AI回答第一反應(yīng)就是去看原始依據(jù)。沒(méi)有引用來(lái)源的答案在金融場(chǎng)景等于無(wú)效答案。第四個(gè)痛點(diǎn)是時(shí)效性。財(cái)報(bào)是定期發(fā)布的公告是實(shí)時(shí)增加的模型固有的知識(shí)永遠(yuǎn)滯后。RAG天然適合這種“知識(shí)庫(kù)持續(xù)變化、需要即時(shí)更新”的場(chǎng)景換數(shù)據(jù)源就能換知識(shí)不需要重新訓(xùn)練。1.2 為什么是RAG而不是微調(diào)大模型在做這個(gè)Demo之前一個(gè)繞不開(kāi)的問(wèn)題是為什么不用微調(diào)的方式把財(cái)報(bào)內(nèi)容直接喂給大模型訓(xùn)練我當(dāng)時(shí)把兩種方案放在一起對(duì)比過(guò)結(jié)論非常明確。對(duì)比維度RAG方案全量微調(diào)方案知識(shí)更新成本換索引、加文檔即可分鐘級(jí)生效需要重新訓(xùn)練小時(shí)到天級(jí)成本高輸出可信度回答基于檢索到的原文片段可溯源知識(shí)固化在參數(shù)里無(wú)法定位證據(jù)幻覺(jué)控制能力可在提示詞層強(qiáng)約束“只能依據(jù)上下文”模型容易把訓(xùn)練知識(shí)與上下文混雜實(shí)施成本無(wú)需訓(xùn)練GPU開(kāi)發(fā)成本集中在檢索鏈路需要訓(xùn)練環(huán)境和高質(zhì)量標(biāo)注數(shù)據(jù)適合場(chǎng)景動(dòng)態(tài)知識(shí)庫(kù)、專(zhuān)有文檔、持續(xù)更新的資料固定領(lǐng)域語(yǔ)料的指令遵循能力提升微調(diào)解決的是“讓模型更懂這個(gè)領(lǐng)域的說(shuō)話方式”而不是“讓模型記住這份文檔里寫(xiě)了什么”。你把一份三千行的財(cái)報(bào)PDF塞進(jìn)微調(diào)數(shù)據(jù)集訓(xùn)練完之后你問(wèn)它其中某個(gè)具體數(shù)字它依然可能編造。因?yàn)榇竽P偷膶W(xué)習(xí)本質(zhì)是壓縮和泛化不是精確存儲(chǔ)。RAG的思路完全不同我不要求模型記住文檔內(nèi)容我只要求它學(xué)會(huì)“基于給定的材料回答問(wèn)題”。知識(shí)存儲(chǔ)在檢索系統(tǒng)里模型負(fù)責(zé)組織和表達(dá)。這一層解耦是金融場(chǎng)景格外看重的因?yàn)槲臋n是流動(dòng)的、權(quán)限是分級(jí)的、答案是必須能翻到原始頁(yè)面的。1.3 Demo項(xiàng)目的目標(biāo)與邊界一個(gè)Demo不能什么都做否則會(huì)變成“什么都很糙的半成品”。我在動(dòng)手之前先劃定了邊界明確這個(gè)Financial RAG Demo要證明三件事一是能對(duì)結(jié)構(gòu)化程度低的金融PDF完成高質(zhì)量解析與切片二是能準(zhǔn)確檢索到包含關(guān)鍵數(shù)字和對(duì)比信息的片段三是能基于檢索內(nèi)容生成帶來(lái)源引用的可讀回答。演示數(shù)據(jù)源我選的是公開(kāi)的模擬財(cái)報(bào)PDF、模擬公司公告和模擬行業(yè)研報(bào)一共準(zhǔn)備了十幾份。為什么不直接用真實(shí)財(cái)務(wù)數(shù)據(jù)一是合規(guī)風(fēng)險(xiǎn)二是不想在Demo階段花大量時(shí)間處理數(shù)據(jù)授權(quán)問(wèn)題。模擬數(shù)據(jù)已經(jīng)足夠把鏈路跑通、把問(wèn)題暴露出來(lái)。這個(gè)項(xiàng)目的定位是“最小可用的金融問(wèn)答參考實(shí)現(xiàn)”不是生產(chǎn)級(jí)系統(tǒng)。在這個(gè)定位下我要的是快速驗(yàn)證方案、沉淀可復(fù)用的工程代碼而不是一開(kāi)始就去追求過(guò)高的準(zhǔn)確率。2. RAG鏈路逐個(gè)拆從金融PDF到可信答案2.1 文檔解析金融PDF結(jié)構(gòu)化處理不能只做文本抽取RAG服務(wù)的上游是文檔解析。很多人一開(kāi)始覺(jué)得解析很簡(jiǎn)單不就是把PDF里的文字提取出來(lái)嘛。金融PDF分分鐘教你做人。我遇到的第一個(gè)坑是表格。財(cái)報(bào)的利潤(rùn)表、資產(chǎn)負(fù)債表、現(xiàn)金流量表全是表格。如果用最簡(jiǎn)單的文本抽取工具直接提取表格會(huì)變成一行行沒(méi)有任何結(jié)構(gòu)邏輯的文字堆疊數(shù)字和項(xiàng)目名稱(chēng)的對(duì)應(yīng)關(guān)系全部丟失。比如“營(yíng)業(yè)收入 1023456789”和“營(yíng)業(yè)成本 987654321”在一張表里提取成純文本后你根本不知道哪個(gè)數(shù)字對(duì)應(yīng)哪個(gè)指標(biāo)。要解決這個(gè)問(wèn)題必須使用能識(shí)別表格結(jié)構(gòu)邊界、能按單元格關(guān)系輸出的解析流程。我實(shí)際用的方案是兩層處理先用布局分析方式識(shí)別頁(yè)面中的文本塊和表格區(qū)域再對(duì)表格區(qū)域單獨(dú)走表格結(jié)構(gòu)識(shí)別邏輯嘗試還原出行列關(guān)系。解析完成后每條內(nèi)容都帶上坐標(biāo)信息、所在頁(yè)碼和所屬章節(jié)標(biāo)題這一步為后面的切片和引用打基礎(chǔ)。頁(yè)眉頁(yè)腳也是必須去掉的不然每頁(yè)重復(fù)的“某某公司2023年年度報(bào)告”字樣會(huì)被切進(jìn)多個(gè)切片檢索時(shí)嚴(yán)重干擾相關(guān)性排序。這里有一個(gè)容易被忽視的點(diǎn)解析結(jié)果不要直接扔給切片器而是要轉(zhuǎn)成統(tǒng)一的中間結(jié)構(gòu)。我給每個(gè)文檔塊設(shè)計(jì)了一個(gè)簡(jiǎn)單的元數(shù)據(jù)模型包括doc_id、page、section、content、type文本/表格/圖表標(biāo)題字段。后面所有環(huán)節(jié)都依賴(lài)這套元數(shù)據(jù)作用類(lèi)似給每塊內(nèi)容貼上了身份證檢索到之后能回答“這段出自哪里”。2.2 切片策略保留語(yǔ)義、保住上下文、還要留得住表格切片是RAG里看似簡(jiǎn)單、實(shí)際影響非常大的環(huán)節(jié)。切片太粗檢索粒度大相關(guān)性漂移嚴(yán)重一個(gè)大片段里只含一小段有效信息浪費(fèi)向量空間切片太細(xì)語(yǔ)義不完整一個(gè)財(cái)務(wù)指標(biāo)的定義被切斷或者表格的表頭和數(shù)據(jù)被拆到兩個(gè)切片里檢索到了也沒(méi)法用。我測(cè)試過(guò)三種切片方式結(jié)果差異非常明顯切片方式優(yōu)點(diǎn)缺點(diǎn)適合場(chǎng)景固定長(zhǎng)度切片如每512字一刀實(shí)現(xiàn)簡(jiǎn)單索引穩(wěn)定切斷段落語(yǔ)義表格極易拆散純文本資料按章節(jié)/標(biāo)題切片語(yǔ)義完整邊界自然章節(jié)長(zhǎng)度差異大長(zhǎng)章節(jié)片段過(guò)大結(jié)構(gòu)化良好的文檔自定義語(yǔ)義切片標(biāo)題段落表格保護(hù)兼顧語(yǔ)義與檢索精度需要額外開(kāi)發(fā)規(guī)則金融財(cái)報(bào)、公告我最終用的是第三種核心邏輯很簡(jiǎn)單先把文檔按標(biāo)題層級(jí)切成大的區(qū)塊再對(duì)超過(guò)長(zhǎng)度閾值的區(qū)塊按段落邊界二次切分同時(shí)加了一個(gè)保護(hù)規(guī)則——表格區(qū)域凡是檢測(cè)到表頭和首行數(shù)據(jù)的就整個(gè)作為一個(gè)獨(dú)立切片不允許切散。切片之間加少量重疊窗口避免把一個(gè)概念的結(jié)尾和下一個(gè)概念的開(kāi)頭隔開(kāi)。重疊窗口大小我設(shè)了64個(gè)字符左右。這個(gè)數(shù)值不是拍腦袋定的是通過(guò)檢索召回率對(duì)比得出來(lái)的。太小起不到銜接作用太大會(huì)讓相鄰切片高度相似檢索結(jié)果里出現(xiàn)四五條高度重復(fù)的內(nèi)容白白占用上下文窗口。2.3 Embedding與檢索混合檢索加排序?yàn)槭裁词菢?biāo)配這個(gè)Demo的檢索模塊沒(méi)有只依賴(lài)向量相似度而是用了“稀疏檢索稠密檢索”的混合方案。原因很現(xiàn)實(shí)向量檢索擅長(zhǎng)處理語(yǔ)義相近但字面不同的表達(dá)比如“公司賺了多少錢(qián)”和“凈利潤(rùn)”的語(yǔ)義關(guān)聯(lián)但在金融場(chǎng)景關(guān)鍵詞精確匹配依然非常重要尤其是年份、股票代碼、專(zhuān)有指標(biāo)名這種字符特征強(qiáng)烈的查詢(xún)稀疏檢索的精確命中率往往高于向量召回。我使用的Embedding特征不是自己訓(xùn)練的而是選擇了在通用語(yǔ)料上預(yù)訓(xùn)練好的模型來(lái)生成向量。選擇模型時(shí)主要看兩方面一是對(duì)中文長(zhǎng)文檔的支持二是金融術(shù)語(yǔ)的理解能力。實(shí)測(cè)下來(lái)通用Embedding模型對(duì)“ROE”“經(jīng)營(yíng)性現(xiàn)金流”這類(lèi)術(shù)語(yǔ)的字面匹配還行但有時(shí)會(huì)抓不住“股東回報(bào)能力”這種同義表達(dá)。當(dāng)時(shí)時(shí)間有限沒(méi)有自訓(xùn)練模型但我在檢索層做了補(bǔ)償加入BM25稀疏召回再用重排序模型把兩路結(jié)果合并打分這樣即使向量語(yǔ)義召回沒(méi)抓住精確關(guān)鍵詞BM25也能補(bǔ)位反之亦然。混合檢索的合并我用的是RRF算法對(duì)兩路候選按排名融合而不是簡(jiǎn)單加權(quán)平均分?jǐn)?shù)。因?yàn)椴煌瑱z索算法產(chǎn)出的分?jǐn)?shù)區(qū)間差異很大直接加權(quán)容易被某一方帶偏。排序階段再通過(guò)一個(gè)輕量級(jí)的重排序模型對(duì)召回的Top 20段重新打分取Top 5作為上下文。這一步的效果立竿見(jiàn)影Top 5命中率明顯提升冗余內(nèi)容也被濾掉不少。2.4 生成增強(qiáng)提示詞約束、來(lái)源引用與拒答機(jī)制檢索做得再好生成環(huán)節(jié)設(shè)計(jì)不到位回答質(zhì)量同樣拉跨。我在提示詞層面做了三個(gè)重要設(shè)計(jì)。第一個(gè)是上下文約束。原原本本在系統(tǒng)提示詞里寫(xiě)清楚“只根據(jù)下面提供的資料回答問(wèn)題。如果資料未提及直接回答‘未在現(xiàn)有資料中找到相關(guān)信息’嚴(yán)禁編造?!边@是對(duì)抗幻覺(jué)的第一道防線雖然不能完全消除幻覺(jué)但能大幅降低模型自由發(fā)揮的概率。第二個(gè)是來(lái)源標(biāo)注。我要求模型在回答的每個(gè)關(guān)鍵結(jié)論后用中括號(hào)標(biāo)注資料編號(hào)例如“[資料1][資料3]”。這些編號(hào)對(duì)應(yīng)檢索結(jié)果的元數(shù)據(jù)最終在展示層映射回“報(bào)告名稱(chēng)頁(yè)碼”。用戶看到數(shù)字想核實(shí)只要照著頁(yè)碼翻原文就行。這是金融場(chǎng)景必須有的能力。第三個(gè)是拒答機(jī)制。對(duì)于檢索相關(guān)度不夠高的提問(wèn)我設(shè)置了一個(gè)門(mén)檻邏輯如果重排序后的最高分?jǐn)?shù)低于設(shè)定閾值或者上下文與問(wèn)題的關(guān)鍵詞重疊度太低服務(wù)端就直接返回“當(dāng)前資料庫(kù)中沒(méi)有覆蓋到您的問(wèn)題”。寧可說(shuō)不知道也不硬答。這個(gè)思路在可靠性要求高的場(chǎng)景非常值得推廣。3. 實(shí)操記錄我如何搭起這個(gè)RAG服務(wù)3.1 技術(shù)選型與環(huán)境準(zhǔn)備技術(shù)選型只有一個(gè)原則能用最簡(jiǎn)方案搞定的就不引入重型組件。整套R(shí)AG服務(wù)驗(yàn)證下來(lái)我的核心組成是一個(gè)PDF解析模塊負(fù)責(zé)布局分析和文本抽取、一個(gè)向量化模塊負(fù)責(zé)將切片轉(zhuǎn)為向量、一個(gè)向量數(shù)據(jù)庫(kù)負(fù)責(zé)存儲(chǔ)和召回、一個(gè)搜索引擎做BM25稀疏檢索、一個(gè)重排序模型負(fù)責(zé)精排以及一個(gè)大模型服務(wù)負(fù)責(zé)生成最終答案。為什么向量數(shù)據(jù)庫(kù)我選了本地部署而不是云服務(wù)因?yàn)檫@個(gè)Demo涉及金融資料處理數(shù)據(jù)不出本地是更穩(wěn)妥的姿態(tài)。實(shí)際選型時(shí)看重的點(diǎn)也不復(fù)雜是否支持過(guò)濾條件、是否有穩(wěn)定易用的客戶端、查詢(xún)延遲能不能控制在幾百毫秒以?xún)?nèi)。開(kāi)源方案完全夠用。大模型這一層我同時(shí)測(cè)試了本地部署的開(kāi)源輕量模型和商業(yè)API兩種方案。Demo階段為了效果展示更穩(wěn)定最終選擇了API方式因?yàn)轱@卡資源有限。但代碼層面我把模型服務(wù)封裝成了可替換的接口后期如果要在純內(nèi)網(wǎng)環(huán)境部署只需要把接口實(shí)現(xiàn)換成本地模型其他邏輯完全不用動(dòng)。這一點(diǎn)對(duì)金融項(xiàng)目尤其重要因?yàn)樯a(chǎn)環(huán)境很可能不允許調(diào)用外部服務(wù)。3.2 離線索引構(gòu)建的完整流程索引構(gòu)建是RAG服務(wù)的離線環(huán)節(jié)我剛才梳理了一下完整流程大概是這樣的讀取PDF文件逐頁(yè)做布局分析識(shí)別正文、表格區(qū)域和頁(yè)眉頁(yè)腳對(duì)表格區(qū)域走表格結(jié)構(gòu)還原邏輯整理成帶有行列信息的Markdown格式文本將每頁(yè)內(nèi)容按“章節(jié)切片區(qū)塊切分表格保護(hù)”的規(guī)則切分同時(shí)記錄元數(shù)據(jù)對(duì)每個(gè)切片做清洗去掉空白字符修正編碼問(wèn)題調(diào)用Embedding接口生成向量將切片文本、元數(shù)據(jù)、向量全部寫(xiě)入向量數(shù)據(jù)庫(kù)同時(shí)將文本寫(xiě)入稀疏檢索引擎構(gòu)建完成后做一個(gè)抽樣自檢把幾個(gè)典型問(wèn)題對(duì)應(yīng)的切片撈出來(lái)確認(rèn)內(nèi)容是否完整。清洗這一步在代碼里必須做好否則后面檢索會(huì)出現(xiàn)各種奇怪問(wèn)題金融文本里常見(jiàn)的全角半角混用、制表符殘留、編號(hào)列表的縮進(jìn)符號(hào)都需要在這一步抹平。索引構(gòu)建完成后我建議加個(gè)自動(dòng)統(tǒng)計(jì)腳本輸出切片總數(shù)、平均長(zhǎng)度、表格切片數(shù)量等指標(biāo)。這一步能幫你迅速發(fā)現(xiàn)解析環(huán)節(jié)有沒(méi)有出問(wèn)題。我第一次跑完發(fā)現(xiàn)表格切片數(shù)量異常少回去排查才發(fā)現(xiàn)表格識(shí)別邏輯對(duì)某些樣式的表格失效了這個(gè)腳本直接幫我定位了問(wèn)題非常實(shí)用。3.3 在線問(wèn)答服務(wù)的關(guān)鍵代碼實(shí)現(xiàn)在線問(wèn)答服務(wù)我拆成了三個(gè)模塊Query理解、檢索召回、生成回答。以下是我核心鏈路簡(jiǎn)化后的實(shí)現(xiàn)邏輯# 檢索模塊混合召回 RRF融合 重排序 def retrieve_documents(query: str, top_k: int 20, final_k: int 5): # 1. 稀疏召回BM25 sparse_results sparse_searcher.search(query, top_k) # 2. 稠密召回向量 query_vector embedding_service.embed(query) dense_results vector_db.search(query_vector, top_k) # 3. RRF融合兩路結(jié)果 fused rrf_fusion(sparse_results, dense_results) # 4. 用重排序模型做精排取Top K reranked rerank_service.rerank(query, fused) return reranked[:final_k]# RRF融合按排名倒數(shù)累加分?jǐn)?shù) def rrf_fusion(sparse_results, dense_results, k: int 60): score_dict {} for rank, doc in enumerate(sparse_results): doc_id doc[id] score_dict[doc_id] score_dict.get(doc_id, 0) 1 / (k rank) for rank, doc in enumerate(dense_results): doc_id doc[id] score_dict[doc_id] score_dict.get(doc_id, 0) 1 / (k rank) return sorted(score_dict.items(), keylambda x: x[1], reverseTrue)生成模塊的提示詞我構(gòu)建成了一段結(jié)構(gòu)化的文本把檢索到的片段按編號(hào)排列并要求大模型嚴(yán)格按照編號(hào)引用請(qǐng)回答用戶問(wèn)題。只允許參考下面列出的資料嚴(yán)禁使用資料以外的知識(shí)作答。 資料 [1] 來(lái)源模擬公司2023年度報(bào)告 第12頁(yè) 內(nèi)容報(bào)告期內(nèi)公司實(shí)現(xiàn)營(yíng)業(yè)收入142.8億元同比增長(zhǎng)18.5%... [2] 來(lái)源模擬公司2023年三季度報(bào)告 第5頁(yè) ... 要求 - 回答每一點(diǎn)關(guān)鍵信息后標(biāo)注來(lái)源編號(hào)例如[1] - 若資料中沒(méi)有相關(guān)信息直接回復(fù)“現(xiàn)有資料中未找到相關(guān)信息” - 語(yǔ)言簡(jiǎn)潔使用金融行業(yè)常用表述。有個(gè)接口細(xì)節(jié)必須注意問(wèn)答接口的響應(yīng)時(shí)間幾乎全花在大模型生成上檢索階段一般耗時(shí)不大。用戶側(cè)體驗(yàn)上建議加流式輸出一邊生成一邊推送而不是等全部生成完再一次性返回。金融場(chǎng)景里用戶看到的是逐段出現(xiàn)的答案加引用標(biāo)注體驗(yàn)會(huì)好很多。3.4 演示界面與效果評(píng)估Demo要給別人看一個(gè)丑陋的命令行界面肯定不行。我花了一下午用輕量級(jí)Web框架搭了個(gè)極簡(jiǎn)的聊天界面左側(cè)是文檔目錄和索引狀態(tài)右側(cè)是對(duì)話窗口回答內(nèi)容下面的“查看來(lái)源”按鈕可以直接定位到原始PDF的頁(yè)碼。界面本身只做展示重點(diǎn)是把檢索鏈路的所有中間信息暴露出來(lái)。展示中間信息是我特別堅(jiān)持的一點(diǎn)。每次問(wèn)答界面右側(cè)會(huì)顯示命中的Top 5片段、各片段的重排序分?jǐn)?shù)、用了哪些資料。別小看這個(gè)設(shè)計(jì)它能極大增強(qiáng)使用者的信任感也讓這個(gè)Demo更適合用于內(nèi)部技術(shù)評(píng)審。別人看到的不只是一個(gè)“漂亮的回答”而是一條可解釋的處理路徑。效果評(píng)估我建了一個(gè)小規(guī)模的人工評(píng)測(cè)集三十個(gè)問(wèn)題覆蓋三類(lèi)事實(shí)查詢(xún)型“去年?duì)I收是多少”、對(duì)比分析型“四季度毛利率環(huán)比變化”、跨文檔綜合型“兩份報(bào)告中關(guān)于研發(fā)投入的描述有什么差異”。我按四個(gè)維度打分檢索命中率、回答準(zhǔn)確率、來(lái)源引用準(zhǔn)確率、拒答合理率。初版全量跑完回答準(zhǔn)確率大概在七成左右后來(lái)經(jīng)過(guò)切片策略和重排序調(diào)優(yōu)后有明顯提升。這里說(shuō)一句構(gòu)建評(píng)測(cè)集不需要很多條但要保證問(wèn)題的典型性和多樣性比盲目堆數(shù)量有用得多。4. 踩坑實(shí)錄金融RAG的常見(jiàn)問(wèn)題與排查4.1 表格數(shù)據(jù)解析后“散架”了我踩過(guò)無(wú)數(shù)次的坑表格數(shù)據(jù)解析成Markdown后行錯(cuò)位、列錯(cuò)位。原因很隱蔽PDF里某些單元格的文字過(guò)長(zhǎng)會(huì)自動(dòng)換行如果解析器沒(méi)有正確處理“單元格內(nèi)換行”就會(huì)把下一列的內(nèi)容頂?shù)较乱恍姓麄€(gè)表的結(jié)構(gòu)直接崩掉。排查方式是把解析后的表格與原文并排對(duì)比逐列檢查。修復(fù)方式有兩種一是選用對(duì)單元格邊界更敏感的解析配置二是在解析后增加一條校驗(yàn)邏輯對(duì)項(xiàng)目名與數(shù)字的對(duì)應(yīng)關(guān)系做簡(jiǎn)單規(guī)則檢查發(fā)現(xiàn)明顯異常就觸發(fā)重新解析。這個(gè)教訓(xùn)讓我明白一件事金融PDF解析永遠(yuǎn)需要人工抽檢不能只看一兩個(gè)頁(yè)面的效果就默認(rèn)全部沒(méi)問(wèn)題。4.2 財(cái)報(bào)數(shù)字檢索錯(cuò)位指標(biāo)和數(shù)值對(duì)不上有一次測(cè)試問(wèn)“經(jīng)營(yíng)活動(dòng)現(xiàn)金流凈額”系統(tǒng)返回的是“投資活動(dòng)現(xiàn)金流”那個(gè)表的片段。乍一看兩個(gè)表結(jié)構(gòu)非常像但指標(biāo)名差了幾個(gè)字?jǐn)?shù)字完全不是用戶想要的。原因在于Embedding模型對(duì)“經(jīng)營(yíng)活動(dòng)”和“投資活動(dòng)”這兩個(gè)高度相似短語(yǔ)的區(qū)分能力不足向量距離太近導(dǎo)致錯(cuò)誤召回。解決辦法是引入字段級(jí)元數(shù)據(jù)的硬約束檢索時(shí)如果問(wèn)題中識(shí)別到“經(jīng)營(yíng)”“投資”“籌資”這類(lèi)關(guān)鍵詞就在向量檢索的過(guò)濾條件中限定對(duì)應(yīng)的表頭區(qū)域不讓其他表的數(shù)據(jù)參與候選。混合檢索加規(guī)則化是金融RAG必須有的組合純粹靠語(yǔ)義理解來(lái)處理財(cái)務(wù)術(shù)語(yǔ)的精確對(duì)應(yīng)目前還不可靠。4.3 金融縮寫(xiě)與專(zhuān)業(yè)術(shù)語(yǔ)讓向量檢索失效“ROE”這個(gè)詞通用Embedding模型大概率能關(guān)聯(lián)到“凈資產(chǎn)收益率”但“EBITDA”這種更專(zhuān)業(yè)的縮寫(xiě)向量召回效果就明顯差了。測(cè)試問(wèn)“公司EBITDA情況”召回到的片段經(jīng)常是正文里順帶提到這個(gè)縮寫(xiě)的那句話而不是真正披露指標(biāo)的表格頁(yè)。我之前一直強(qiáng)調(diào)混合檢索和重排序就是在這里發(fā)揮作用的。BM25對(duì)“EBITDA”這種精確詞命中很好重排序模型也能根據(jù)上下文重新識(shí)別真正包含指標(biāo)的表格段落。此外我還手動(dòng)維護(hù)了一小份金融術(shù)語(yǔ)同義詞詞典查詢(xún)進(jìn)來(lái)先做一遍術(shù)語(yǔ)擴(kuò)展把“ROE”映射成“凈資產(chǎn)收益率”這樣一來(lái)向量檢索的命中率有明顯提高。4.4 答案仍然幻覺(jué)提示詞約束并不萬(wàn)能就算提示詞寫(xiě)了“嚴(yán)禁編造”模型在上下文中找不到明確答案時(shí)依然可能把相鄰年份的數(shù)據(jù)張冠李戴或者把上下文沒(méi)有的因果關(guān)系編出來(lái)。我見(jiàn)過(guò)最典型的情況是上下文中只有2022年和2023年的營(yíng)收數(shù)據(jù)問(wèn)“2021年?duì)I收”的時(shí)候模型硬是從兩句數(shù)據(jù)的表述里推測(cè)了一個(gè)數(shù)字還說(shuō)得很篤定。應(yīng)對(duì)幻覺(jué)靠?jī)傻婪谰€。第一道是檢索質(zhì)量只要正確的切片被召回到Top位置幻覺(jué)概率就大降第二道是“拒答門(mén)檻”我在生成前置邏輯里加了相關(guān)性閘門(mén)如果檢索結(jié)果綜合分?jǐn)?shù)過(guò)低就不再調(diào)用生成接口而是直接返回提示讓用戶換種問(wèn)法。前面提到過(guò)寧可答不上來(lái)也不要給一個(gè)貌似嚴(yán)謹(jǐn)?shù)腻e(cuò)誤答案這在金融領(lǐng)域是一條底線。4.5 檢索性能與索引更新問(wèn)題文本量放大之后檢索延遲會(huì)明顯上升。我曾在索引里塞了幾千份文檔發(fā)現(xiàn)一次查詢(xún)到了秒級(jí)趕緊查了原因——向量索引的索引參數(shù)沒(méi)有調(diào)優(yōu)導(dǎo)致暴力檢索。解決方式是把索引類(lèi)型切換成更高效的近鄰檢索并調(diào)整構(gòu)建參數(shù)延遲立刻降到了百毫秒以?xún)?nèi)。建議在壓測(cè)階段就關(guān)注這個(gè)參數(shù)不要等線上慢了再來(lái)排查。索引更新是另一個(gè)容易被忽略的環(huán)節(jié)。業(yè)務(wù)上新增了一份財(cái)報(bào)需要讓新知識(shí)立刻被檢索到。我采用的是全量重建與增量寫(xiě)入結(jié)合的方式常規(guī)更新走增量接口文檔結(jié)構(gòu)大改或數(shù)據(jù)清洗規(guī)則變化時(shí)觸發(fā)重建。增量更新時(shí)務(wù)必維護(hù)好文檔ID與切片ID的映射表否則舊切片無(wú)法定位更新后容易出現(xiàn)新老數(shù)據(jù)混答的問(wèn)題。最后再分享一個(gè)小技巧整套Financial RAG Demo跑下來(lái)如果要我說(shuō)最值得關(guān)注的優(yōu)化點(diǎn)不是換更大的模型而是把數(shù)據(jù)準(zhǔn)備和檢索調(diào)優(yōu)做扎實(shí)。數(shù)據(jù)準(zhǔn)備階段的每個(gè)決策都會(huì)在最終的回答質(zhì)量上加分或減分。我建議每個(gè)做類(lèi)似項(xiàng)目的人在第一次跑通端到端之后不要急著加強(qiáng)大模型能力而是建立一個(gè)“檢索失敗案例臺(tái)賬”把問(wèn)答中檢索不到正確片段的案例一條條記錄下來(lái)分析是切片問(wèn)題、解析問(wèn)題還是Embedding問(wèn)題。我自己就是這樣連續(xù)記錄和修復(fù)了三周數(shù)據(jù)準(zhǔn)確率才真正穩(wěn)定下來(lái)。這個(gè)臺(tái)賬方法免費(fèi)、實(shí)用、任何場(chǎng)景都能用強(qiáng)烈推薦。