解密Prompt系列14. LLM Agent之搜索應用設計:WebGPT & WebGLM & WebCPM
前兩章,我們分別介紹了基于微調和prompt的工具調用方案,核心都是如何讓大模型和工具進行交互,包括生成工具調用語句和處理工具調用請求。不過在實際應用中,想要設計一個可以落地的LLM Agent,需要更全面整體的系統設計。本章我們以搜索工具為例,介紹如何更好和搜索引擎進行交互的LLM Agent。
搜索Agent方案
為啥需要整體方案,直接調用搜索接口取Top1返回不成嘛?要是果真如此Simple&Naive,New Bing豈不是很容易復刻->.->
我們先來看個例子,前一陣火爆全網的常溫超導技術,如果想回答LK99哪些板塊會漲,你會得到以下搜索答案

從以上的搜索結果不難發現,Top1答案并不能回答問題,在和搜索引擎交互中幾個可能的問題有
-
Query:用戶的query不適配搜索引擎,導致搜索不到有效內容;或者問題需要通過類似Self Ask的思維鏈拆解通過多輪搜索來解決
-
Ranking:細看langchain的搜索Wrapper,會發現它默認只使用搜索的Top1返回,但是除了傳統百科問題,這類問題因為做過優化,Top1往往是最優答案。但其他場景,例如當前問題,第三個內容顯然更合適。當前傳統搜索引擎并非為大模型使用設計,因此需要后接一些優化排序模塊,例如REPLUG論文
-
Snippet: Bing的網頁標題下面會默認展示150字左右根據query定位的正文摘要內容,也是langchain等框架使用的網頁結果。但是不難發現,snippet太短或者定位不準會導致snippet缺乏有效信息
為了解決上述提到的3個主要問題,我們會基于WebGPT,WebGLM,WebCPM的3篇論文,詳述如何更有效的和搜索引擎進行交互,來解決長文本開放問答LFQA問題。和搜索引擎的交互主要分成以下4個模塊
-
Search:生成搜索請求query,或基于結果進行query改寫,請求搜索API。類似self-Ask里面的Thought,只不過selfask強調問題拆解,而這里的search還有query改寫,追問等功能
-
Retrieve:從搜索返回的大段內容中,定位可以回答query的支撐性事實,進行抽取式摘要、生成式摘要。類似React里面的LookUp行為,只不過更加復雜不是簡單的定位文字。
-
Synthesis: 對多個內容進行組裝,輸入模型進行推理得到答案
-
Action: 針對需要和搜索引擎進行自動化多輪交互的場景,需要預測下一步的行為,是繼續搜索,抽取摘要,還是停止搜索,組裝內容進行推理等等,對應LLM Agent中的規劃模塊。其實就是豐富了React/SelfAsk里面的Action,加入了更多和搜索引擎交互的行為,例如繼續瀏覽,翻頁等等
雖然論文的發布順序是webcpm>webglm>webgpt,但考慮webcpm開源了很全面的中文數據哈哈,手動點贊!我會以webcpm作為基準詳細介紹,再分別介紹webglm和webgpt的異同點。
webcpm
- paper:WEBCPM: Interactive Web Search for Chinese Long-form Question Answering
- github:https://github.com/thunlp/WebCPM

WebCPM其實是這三篇論文中最新的一篇,所以集成了webgpt和webglm的一些方案。構建了通過和搜索引擎進行多輪交互,來完成長文本開放問答(LFQA)的整體方案。它使用的搜索API是Bing。23名標注人員通過和搜索進行多輪交互,來獲取回答問題所需的支撐性事實。
webCPM的問題來自Reddit上的英文QA轉成中文。之所以使用Reddit而非知乎,百度知道,是因為后兩者的答案往往經過很好的處理,直接搜索一輪就能獲得很好的答案,降低了多輪搜索的交互難度。人工標注的搜索數據微調10B的CPM模型并在LFQA任務拿到了不錯的效果。
WebCPM的整體框架就是上面提到的4個模塊,下面我們來分別介紹。強烈建議和源碼結合起來看,論文本身寫的略簡單,哈哈給讀者留下了充分的想象空間。
Action:行為規劃
首先是行為規劃,也就是讓模型學習人和搜索引擎交互生成的行為鏈路。webcpm針對交互式搜索問題,定義了包括搜索,頁面加載,頁面下滑等以下10個行為。不過個人感覺如果只從解決長文本問答出發,以下行為中的Scroll,load page等操作其實可能可以被優化掉,因為內容的遍歷可以通過引入排序模塊,和以上的摘要模塊來篩選相關和不相關的內容,并不一定要通過Action來實現。這樣可能可以進一步簡化Action空間,提升效果。

針對行為序列的建模,被抽象為文本分類問題。把當前狀態轉化為文本表述,預測下一步Action是以上10分類中的哪一個。當前狀態的描述包括以下內容
- 最初的問題:question
- 當前的搜索query:title
- 歷史Action序列拼接:last_few_actions,消融實驗中證明歷史Action序列是最重要的,哈哈所以可能可以簡化成個HMM?
- 歷史全部摘要內容拼接:quotes
- 上一步的搜索界面:past_view, 上一步頁面中展示所有內容的標題和摘要拼接的文本
- 當前搜索界面:text, 當前頁面中展示所有內容的標題和摘要拼接的文本
- 剩余Action步驟:actions_left
以下為指令樣本的構建代碼,就是把以上的狀態拼接作為input,把下一步Action作為Output
def make_input(self, info_dict, type="action"):
context_ids = ""
def convert_nothing(info):
return "無" if len(info) == 0 else info
context_ids += "問題:\n" + info_dict["question"] + "\n"
context_ids += "摘要:\n" + convert_nothing(info_dict["quotes"]) + "\n"
last_few_actions = ""
for past_action in info_dict["past_actions"]:
if past_action != []:
last_few_actions += past_action
context_ids += "當前搜索:\n" + convert_nothing(info_dict["title"]) + "\n"
context_ids += "上回界面:\n" + convert_nothing(info_dict["past_view"]) + "\n"
context_ids += "當前界面:\n" + convert_nothing(info_dict["text"]) + "\n"
context_ids += "剩余操作步數:" + str(info_dict["actions_left"]) + "\n"
if type == "action":
context_ids += "可選操作:"
for idx, k in enumerate(self.action2idx):
context_ids += self.action2idx[k]
if idx != len(self.action2idx) - 1:
context_ids += ";"
context_ids += "\n"
context_ids += "歷史操作:" + convert_nothing(last_few_actions) + "\n"
if type == "action":
context_ids += "下一步操作:"
elif type == "query":
context_ids += "請生成新的合適的查詢語句:"
elif type == "abstract":
context_ids += "請對當前界面內容摘取和問題相關的內容:"
next_action = info_dict["next_action"]
return context_ids, next_action
具體分類模型的微調就沒啥好說的了。不過這里需要提一下,源碼中其實給出了兩種webcpm的實現方案。兩種方案均開源了數據。
-
Interactive方案:對應當前的行為建模,每一步執行什么行為會由Action模型預測得到,同時以下query改寫,摘要等模塊,也會獲得之前所有執行步驟已有的上文輸出,進行條件文本生成任務
-
pipeline方案:整體行為鏈路固定依次是,query改寫 -> 所有改寫query搜索得到Top-K內容 -> 針對每個頁面進行摘要抽取 -> 整合所有內容回答問題。 因此Pipeline方案并不需要Action模型,同時以下的摘要改寫等模塊,也會簡化為不依賴上文的文本生成任務
這么說有些抽象,讓我們用Query改寫來看下以上兩種方案的差異,假設用戶提問:網頁布局都有哪種?一般都用什么布局?
-
Interactive:第一個改寫query=網頁布局種類, 然后搜索+摘要獲得網頁布局總結性的概述后,第二個query在已有摘要內容的基礎上,改寫query=網頁布局最佳實踐, 這樣綜合兩個query的內容就可以回答上述問題
-
pipeline:在最初就調用query改寫模型生成一堆改寫query,例如網頁布局種類,網頁布局技巧,網頁布局模式,網頁布局優勢。然后全部去調用搜索引擎,再對所有返回結果進行整合。
雖然看上去Interactive似乎能得到更優解,但其實只對明顯串行的搜索任務有邊際增益,整體沒有pipeline模式更加簡潔優雅。因為pipeline模型的無條件生成,使得每一步都可以并發處理,更容易落地。并且每個模塊可以獨立優化,可以相互解耦。因此以下三個模塊的介紹,我們都以pipeline方案來進行介紹
Search:query改寫
query改寫模型,是一個seq2seq的文本生成模型。其實和Self-Ask通過自我提問,來對問題進行拆解的本質相似。改寫核心是為了解決兩個問題
- Decompose:用戶的問題由多個并聯、串聯的內容組合而成,因此需要對問題進行拆解,得到子query。例如Self-Ask那一章的例子,提問漲幅最高的板塊成交量如何?需要拆解成漲幅最高的板塊+XX板塊成交量
- Rephrase:用戶的問題本身不適配搜索引擎,需要改寫成更加簡潔,關鍵詞更明確的搜素query。例如"微軟的new bing上線了,使用體驗如何?"可以改寫為"new bing使用體驗"
以下為webcpm微調得到的query生成模型的效果,webcpm提供了這部分訓練數據,包括一個query和改寫得到的多個query

Retriever:摘要抽取
Retriever負責從網頁正文中,抽取和Query相關的內容,也就是一個閱讀理解/抽取式摘要問題。這樣就不需要依賴搜索API直接提供的snippet摘要,可以針對你的場景來設計抽取的長度,以及是整段抽取,還是抽取多個段落組合。
為了降低推理延時,webcpm通過decoder實現了類似span抽取的方案,解碼器只解碼應當抽取的段落的第一個字和最后一個字。例如
Query = 麥田怪圈是什么?
Content= 麥田怪圈(Crop Circle),是指在麥田或其它田地上,通過某種未知力量(大多數怪圈是人類所為)把農作物壓平而產生出來的幾何圖案。這個神秘現象有時被人們稱之為“Crop Formation”。麥田怪圈的出現給了對支持外星人存在論的人們多種看法。
假設應該抽取段落中的第一句話
Fact=麥田怪圈(Crop Circle),是指在麥田或其它田地上,通過某種未知力量(大多數怪圈是人類所為)把農作物壓平而產生出來的幾何圖案
則模型的解碼器輸出的結果是起始字符:麥-結束字符:案,如果首尾兩字能匹配到多端文本,則取最長能匹配到的文本段落。刨了刨代碼,發現pipeline和interactive在摘要部分的樣本構建方式不同,只有以下互動式的樣本構建中采用了以上類span抽取的方案
abstract = "起始字符:" + self.tokenizer.decode(decoded_abstract[: num_start_end_tokens]) + "-結束字符:" + self.tokenizer.decode(decoded_abstract[-num_start_end_tokens: ])
Synthesis:信息聚合
Synthesis負責整合以上search+Retriever得到的多個Fact,拼接作為上文,通過人工標注的答案,來讓模型學習如何基于多段事實生成一致,流暢,基于上文內容的長回答。
為了解決模型本身在自動檢索過程中會收集到無關信息,而[1]中提到,無關的上文輸入會影響推理結果的問題。Webcpm在構建基于多段上文的QA問答指令集時,在人工收集的每個query對應的多個摘要fact的基礎上,會從其他樣本中隨機采樣同等量級的無關上文,和原始的事實進行shuffle之后,拼接作為輸入,來進行Query+content -> Answer的模型微調。讓模型學會區分相關事實和無關事實,并在推理時不去關注無關的信息輸入。
同時論文對比了加入無關Fact,和只使用相關Fact微調后的模型效果差異,如下。只使用相關內容的Baseline模型的偏好率18%顯著低于,加入隨機無關內容微調后的43.7%。因此加入無關上文訓練,確實可以提升模型對噪聲上文的判別能力。

WebGPT
- paper: WebGPT:Browser-assisted question-answering with human feedback
- Demo: https://openaipublic.blob.core.windows.net/webgpt-answer-viewer/index.html
webgpt的論文發表最早,但論文本身寫的比較"高山仰止",可能先讀完webcpm再來讀webgpt,會更容易理解些,只看收集交互式搜索數據使用的界面,就會發現二者非常相似。
webgpt的問題以ELI5為主,混合了少量TriviaQA,AI2,手寫問題等其他問題。搜索引擎也是使用了Bing API。和webcpm相同,為了避免直接找到答案簡化搜索流程,webgpt過濾了Reddit,quora等類知乎的站點信息,提高任務難度。
多數細節和webcpm比較類似,最大的不同是webgpt除了使用指令微調,還加入了強化學習/拒絕采樣的偏好打分方案。
數據收集
webgpt的數據收集分成兩部分:
- Demonstrations:和webcpm的全流程搜索數據類似,從鍵入query,搜索,摘要,到問題回答,收集人類的交互數據,這里不再細說
- Comparison: 同一個query模型生成的兩個回答的偏好數據,用于訓練偏好模型。webgpt開源了這部分的數據
以下我們細說下Comparison的數據集構建。為了降低偏好標注的噪音,和人類偏好主觀性的影響,webgpt只使用引用源來判斷模型回答的優劣,具體標注步驟如下
- Flags:剔除不合理,爭議性問題
- Trustworthiness:先對模型引用的數據源進行標注:分為Trustworthy,Netural, Suspicious三擋,區分不同網頁的權威性和真實性
- Annotations:選定模型回答的每一個觀點(高亮),根據該觀點是否有引用支持,以及支持該觀點的引用在以上的權威性分類中屬于哪一檔,來綜合評價每個觀點。也分為三擋strong support, weak support, no support。同時需要標注每個觀點對于回答最終提問的重要性,有core,side,irrelevant三擋。
- Ratings:分別對模型采樣生成的AB兩個答案標注完以上3步之后,才到對比打分的環節。webgpt給出了很詳細的如何綜合每個觀點的重要性和是否有支撐,對AB答案進行覺得打分,再對比兩個打分得到相對打分,此處有無數人工智能中智能的人工.......詳見論文中的標注文檔鏈接~

訓練
對應上面的數據收集,webgpt的訓練過程和InstructGPT基本是一致的。先使用Demonstration數據進行指令微調,論文稱之為Behaviour Cloning,顧名思義模仿人類的搜索過程(BC)。再基于BC模型,使用Comparison對比數據訓練偏好模型(RM)。最后基于偏好模型使用PPO算法微調BC模型得到強化微調后的模型(RL)。訓練細節可以直接參考InstructGPT。
在解密Prompt7. 偏好對齊RLHF-OpenAI·DeepMind·Anthropic對比分析中我們討論過強化學習的本質之一其實就是拒絕采樣,論文也對比了使用BC/RL模型為基座,加入拒絕采樣,隨機采樣4/16/64個模型回答,從中選取偏好模型打分最高的回答作為結果的方案。論文中效果最好的方案是BC+Best of 64拒絕采樣。RL模型相比BC略有提升,但提升幅度沒有拒絕采樣來的高。
評估方案,論文把webgpt生成的結果,和Eli5數據集的原始結果(Reddit上的高贊答案),以及Demonstration中人工標注的答案進行偏好對比,讓標注同學選擇更偏好的答案。效果上,175B的微調模型,在64個回答中采樣RM打分最高的答案,效果上是可以顯著超越人工回答的。

WebGLM
- paper: WebGLM: Towards An Efficient Web-Enhanced Question Answering System with Human Preferences
- github: https://github.com/THUDM/WebGLM
webglm介于二者中間,是用google search api, 英文數據做的項目。整個項目數據集構建過程自動化程度更高,人工標注依賴更少,性價比更高一些。這里主要介紹數據集構建上的一些差異,架構和前兩者差不多。

Retriever
和webcpm使用抽取的方案來定位網頁內容中和qurery相關的部分不同,webglm采取了先對網頁進行分段,然后每個段落和query計算相似度,通過相似度來篩選相關內容的方案。作者選取了基于對比學習的Contriever預訓練模型,不過評估準確率只有不到70%。
因此這里使用大模型的閱讀理解能力來補充構建了query*reference樣本對。論文使用GPT-3 1-shot 。也就是給一個相關段落抽取的case,讓大模型來從眾多段落中篩選和query相關的。并對模型構建的樣本集過濾query-reference相關度較低,大概率是模型發揮的低質量樣本。
然后基于大模型構造的樣本,使用query和reference embedding的內積作為相似度打分,微調目標是擬合相似度打分的MSE Loss。
synthesis
sysnthesis,也就是基于引用內容,大模型進行QA問答的部分,webglm使用davinci-003來進行樣本生成, 這里主要包含四個步驟
- 大模型生成指令:這里作者使用了APE的方案,不熟悉的同學看這里# APE+SELF=自動化指令集構建代碼實現。輸入是Question+Refernce,輸出是Answer, 問大模型,什么樣的指令可以更好描述這類LFQA任務。大模型給出的指令是:Read the Refernces Provided and answer the corresponding question
- few-shot構造樣本:基于生成的instruction,人工編寫幾個few-shot樣本,給大模型更多的query+Reference,讓davinci-003來構建推理樣本
- 引用校準:論文發現模型生成結果存在引用內容正確,但是引用序號錯誤的情況,這里作者用Rouge-1進行相似度判斷,校準引用的Reference。
- 樣本過濾:再強的大模型也是模型,davinci-003造的樣本質量參差不齊,部分模型會自己發揮。因此加入了質量過濾模塊,主要過濾引用占比較低,引用太少,以及以上引用需要錯誤率較高的。
通過以上的生成+過濾,最終從模型生成的83K樣本過濾得到45K質量更高的LFQA樣本用于推理部分的模型微調
RM模型
webglm沒有像webgpt一樣使用人工標注對比偏好數據,而是使用線上QA論壇的點贊數據作為偏好數據,高贊的是正樣本。并通過過濾掉回答較少的問題,對長文本進行截斷,以及使用點贊數差異較大的回答構建對比樣本對,等數據預處理邏輯,得到質量相對較高,偏好差異較大,長度相對無偏的偏好樣本。整體量級是93K個問題,249K個樣本對。
其實現在大模型的樣本構建往往有兩種方案,一個是高質量小樣本,另一個就是中低質量大樣本,前者直接告訴模型如何做,后者是在質量參差不齊的樣本中不斷求同存異中讓模型抽取共性特征。webglm是后者,而webgpt是前者。
其次RL的初始模型,對標以上webgpt的BC模型。在之前RL的博客中我們有提到過,初始模型需要是有能力生成人類偏好答案的對齊后的模型。這里webglm直接使用Reddit的摘要數據,通過指令微調得到,也沒有使用人工標注數據,考慮摘要任務也屬于閱讀理解的子任務。
基于搜索工具的大模型應用設計,這一章我們就說這么多。針對query改寫,和retriever的一些優化嘗試Reference[3][4]的論文也有提到。想看論文概述的,戳這里幾句話聊論文
想看更全的大模型相關論文梳理·微調及預訓練數據和框架·AIGC應用,移步Github >> DecryPrompt
Reference
[1] Large Language Models Can Be Easily Distracted by Irrelevant Context
[3] Query Rewriting for Retrieval-Augmented Large Language Models
[4] REPLUG: Retrieval-Augmented Black-Box Language Models
未經許可請勿轉載哦~

本章介紹如何和搜索引擎進行交互的LLM Agent設計,主要包含以下幾個模塊:搜索改寫,事實抽取,聚合推理,行為交互。我們會以WebCPM為基礎,同時介紹WebGPT,WebGLM的異同
浙公網安備 33010602011771號