大語言模型應用程式開發流程涉及多個步驟,從提示設計到結果轉換,每個環節都至關重要。提示修改實驗有助於理解模型的上下文理解能力和生成特性。提交提示時,模型大小的選擇需考量成本和延遲。LLM 完成結果需要轉換回使用者易於理解的格式,函式呼叫模型簡化了此過程。前饋傳遞過程將使用者問題轉換為模型可理解的文字,包含上下文檢索、片段化、評分和排序、提示組裝等步驟。應用程式狀態的儲存對於維護上下文至關重要,外部上下文的整合則擴充套件了模型的知識函式庫。增加推理深度可提升模型的理解能力,外部知識的整合則能提供更豐富的資訊。最後,應用程式品質評估包含離線和線上評估,確保應用程式達到預期效能。
使用大語言模型(LLM)完成提示的流程解析
在前面的章節中,我們已經探討瞭如何精心設計提示(prompt),以便大語言模型(LLM)能夠有效地解決問題並達到停止點。在本章中,我們將探討使用LLM完成提示的流程,並分析其中的關鍵因素。
修改提示的實驗
首先,讓我們進行一個實驗,修改前面的提示,看看會發生什麼變化。我們將使用類別似gpt-3.5-turbo-instruct的完成模型,進行以下修改:
- 省略部分內容:如果省略## Solution 2或前面的問題,模型是否仍然能夠闡述問題陳述?即使模型完成了問題陳述,為什麼保留問題和解決方案標題仍然很重要?
內容解密:
此實驗旨在測試模型的上下文理解能力。如果省略部分內容,模型可能仍然能夠生成相關的文字,但這可能會影響輸出的相關性和準確性。保留問題和解決方案標題有助於模型更好地理解上下文。
- 修改Solution 1的內容:如果更改Solution 1的文字,是否會修改為Solution 2生成的文字?嘗試增加或減少Solution 1的長度,或者改變其語氣,如使用海盜口吻或粗魯的語氣。這些修改如何影響Solution 2?
內容解密:
此實驗測試模型的生成文字是否受到前文的影響。更改Solution 1的內容可能會對Solution 2的生成文字產生影響,因為模型會根據上下文進行生成。
- 替換負面情境:嘗試保留相同的國家,但用越來越正面的評論替換負面情境。模型是否仍然建議不要前往北韓?為什麼會這樣?
內容解密:
此實驗旨在測試模型的魯棒性。如果用正面的評論替換負面情境,模型可能會改變其建議,但這取決於模型的訓練資料和上下文理解能力。
- 省略停止詞:如果省略停止詞,模型是否會虛構第三個問題?如果沒有,那麼新增一個新的換行符號是否會使其虛構第四個問題?
內容解密:
此實驗測試模型的生成能力。如果省略停止詞,模型可能會繼續生成文字,但這可能會導致虛構或不相關的內容。
- 使用不同的格式:是否有任何理由使用作業問題可能存在問題?嘗試使用不同的格式,例如旅行社幫助熱線的記錄。
內容解密:
此實驗旨在測試模型的通用性。使用不同的格式可能會影響模型的輸出,但這取決於模型的訓練資料和上下文理解能力。
提交提示給模型
在LLM應用程式迴圈的下一個階段,您需要將提示提交給模型並檢索完成結果。如果您只使用了一個特定的模型,例如ChatGPT,您可能會認為這裡沒有什麼決策可做——只需向模型傳送提示並等待完成結果。然而,並非所有模型都是相同的!
您需要決定您的模型應該有多大。通常,模型越大,其完成結果的品質就越高。但是,這裡有一些非常重要的權衡,例如成本。目前,執行GPT-4的成本可能是執行gpt-3.5-turbo的20倍。品質改進是否值得數量級的價格上漲?有時,是值得的!
此外,還需要考慮延遲。更大的模型需要更多的計算,這可能會需要比使用者能夠忍受的更多時間。在GitHub Copilot的早期,我們決定使用一個稱為Codex的OpenAI模型,它足夠小、足夠聰明且速度足夠快。如果我們使用了GPT-4,那麼使用者可能很少願意等待完成結果,無論它有多好。
將LLM完成結果轉換回使用者域
讓我們探討圖4-1中迴圈的最後一個階段。LLM完成結果是一大塊文字。如果您正在製作一個簡單的聊天應用程式,那麼也許您就完成了——只需將文字發送回客戶端並直接呈現給使用者。但是,通常,您需要轉換文字或從中提取資訊,以使其對終端使用者有用。
對於原始的完成模型,這通常意味著要求模型以非常特定的格式呈現特定的資料,然後解析該資訊並將其呈現給使用者。例如,您可能要求模型閱讀檔案,然後生成表格資訊,這些資訊將被提取並呈現給使用者。
然而,自從出現了函式呼叫模型以來,將模型輸出轉換為對使用者有用的資訊變得容易得多。對於這些模型,提示工程師闡述使用者的問題,向模型提供一系列函式,然後要求模型生成文字。生成的文字代表了一個函式呼叫。
例如,在一個旅行應用程式中,您可以向模型提供可以查詢航空公司航班的函式和使用者的旅行目標描述。然後,模型可能會生成一個函式呼叫,請求特定日期、使用者請求的出發地和目的地的機票。LLM應用程式可以使用此函式呼叫實際航空公司的API,檢索可用的航班,並將其呈現給使用者——回到使用者的域中。
您可以透過向模型提供實際上可以在真實世界中建立更改的函式來進一步擴充套件。例如,您可以向模型提供實際購買機票的函式。當模型生成購買機票的函式呼叫時,應用程式可以在完成交易之前與使用者進行雙重確認。因此,您已經從模型域——代表函式呼叫的文字——轉換回了使用者域。
大語言模型應用程式設計:深入剖析前饋傳遞過程
在設計大語言模型(LLM)應用程式時,瞭解前饋傳遞過程至關重要。本章節將探討前饋傳遞過程的細節,並介紹相關的技術和策略。
前饋傳遞過程的基本步驟
前饋傳遞過程是指將使用者問題轉換為模型可理解的文字領域的過程。這個過程包括以下幾個基本步驟:
- 上下文檢索:檢索與使用者問題相關的原始文字作為提示的上下文資訊。
- 片段化:將檢索到的上下文資訊分解為最相關的片段。
- 評分和優先排序:為每個片段分配優先順序或評分,以確定其在提示中的重要性。
- 提示組裝:將片段組裝成最終的提示,確保清晰地傳達使用者問題並包含最相關的上下文資訊。
上下文檢索
上下文檢索是前饋傳遞過程的第一步。直接上下文來自使用者直接描述的問題,而間接上下文則來自相關來源。例如,在技術支援應用程式中,直接上下文是使用者輸入的文字,而間接上下文可能來自相關的檔案或知識函式庫。
def retrieve_context(user_input):
# 直接上下文
direct_context = user_input
# 間接上下文
indirect_context = search_documentation(user_input)
return direct_context, indirect_context
內容解密:
此程式碼定義了一個函式 retrieve_context,用於檢索與使用者輸入相關的上下文資訊。函式傳回直接上下文和間接上下文,其中間接上下文透過搜尋相關檔案獲得。
片段化
片段化是指將檢索到的上下文資訊分解為最相關的片段。這可以透過轉換不同格式的資訊或提取最相關的段落來實作。
def snippetize_context(context):
# 將上下文資訊分解為片段
snippets = []
for info in context:
snippets.extend(extract_relevant_passages(info))
return snippets
內容解密:
此程式碼定義了一個函式 snippetize_context,用於將上下文資訊分解為片段。函式遍歷上下文資訊並提取最相關的段落,將其新增到片段列表中。
評分和優先排序
評分和優先排序是指為每個片段分配優先順序或評分,以確定其在提示中的重要性。這可以透過計算片段的相關性或重要性來實作。
def score_and_prioritize_snippets(snippets):
# 為片段分配評分和優先順序
scored_snippets = []
for snippet in snippets:
score = calculate_relevance(snippet)
scored_snippets.append((snippet, score))
scored_snippets.sort(key=lambda x: x[1], reverse=True)
return scored_snippets
內容解密:
此程式碼定義了一個函式 score_and_prioritize_snippets,用於為片段分配評分和優先順序。函式計算每個片段的相關性並將其排序,以便優先使用最相關的片段。
提示組裝
提示組裝是指將片段組裝成最終的提示,確保清晰地傳達使用者問題並包含最相關的上下文資訊。
def assemble_prompt(scored_snippets, user_input):
# 組裝最終提示
prompt = ""
for snippet, score in scored_snippets:
if len(prompt) + len(snippet) <= MAX_TOKEN_BUDGET:
prompt += snippet
prompt = f"{user_input} {prompt}"
return prompt
內容解密:
此程式碼定義了一個函式 assemble_prompt,用於組裝最終提示。函式遍歷評分後的片段,將其新增到提示中,直到達到最大標記預算。然後,將使用者輸入新增到提示的開頭。
設計LLM應用程式的複雜度考量
在前一章節中,我們討論了一個簡單的應用程式範例,它作為建構更複雜應用的基礎。隨著應用程式變得越來越複雜,其複雜性在多個層面上體現出來:
- 更多的應用程式狀態
- 更多的外部內容
- 更複雜的推理
- 與模型外部世界更複雜的互動
儲存應用程式狀態
前一節中的前饋應用程式不儲存任何持久狀態。它只是接收使用者的輸入,新增一些相關的上下文,將其傳遞給模型,然後將模型的回應傳回給使用者。在這個簡單的世界中,如果使用者發出另一個請求,應用程式不會記住之前的對話。Copilot 程式碼補全就是這樣一個應用程式。
更複雜的LLM應用程式通常需要在請求之間保持狀態。例如,即使是最基本的聊天應用程式也必須維護對話記錄。在聊天會話的中間,當使用者向應用程式提交新訊息時,應用程式會在資料函式庫中查詢這個對話線索,並使用之前的對話作為進一步的上下文來生成下一個提示。
如果使用者的互動時間較長,那麼可能需要縮短歷史記錄以適應提示。最簡單的方法是截斷對話並刪除較早的對話。但這並不總是有效!有時,內容太重要了,不能刪除,因此另一種方法是總結對話的早期部分。
外部上下文
即使是最好的LLM,它們也沒有所有的答案。它們只被訓練在公開可用的資料上,並且對最近發生的事件和隱藏在企業、政府或個人隱私牆後面的資訊一無所知。如果您詢問模型它不具備的資訊,理想情況下,它會道歉並解釋它沒有存取該資訊的許可權。這並不能讓使用者滿意,但總比模型自信地產生幻覺,告訴使用者完全錯誤的資訊要好得多。
因此,許多LLM應用程式採用檢索增強生成(RAG)。使用RAG,您可以透過在訓練期間不可用的來源中提取的上下文來增強提示。這可以是從企業檔案到使用者的醫療記錄,再到最近的新聞事件和最近發表的論文等任何內容。
這些資訊被索引到某種搜尋引擎中。很多人使用嵌入模型將檔案(或檔案片段)轉換為向量,並將其儲存在向量儲存中(如Pinecone)。然而,您不應該對傳統的搜尋索引(如Elasticsearch)嗤之以鼻,因為它們往往相對簡單管理,而且當您似乎找不到所需的檔案時,更容易除錯。
實際檢索上下文通常遵循一系列可能的方法。最簡單的是直接使用使用者的請求作為搜尋查詢。但是,如果使用者的請求是一個長段落,那麼它可能包含無關的內容,從而導致索引傳回錯誤的匹配結果。在這種情況下,您可以詢問LLM它認為什麼是一個好的搜尋查詢,並使用其回應文字來搜尋索引。最後,如果您的應用程式正在與使用者進行長時間的聊天,那麼可能根本不清楚什麼時候值得搜尋某些內容;您不能為他們的每條評論檢索檔案,因為他們可能仍在談論與上一條評論相關的檔案。在這種情況下,您可以向助理引入搜尋工具,並讓助理選擇何時進行搜尋以及使用什麼搜尋詞。
增加推理深度
正如我們在第一章中所討論的,從GPT-2開始,更大的LLM真正令人驚奇的地方在於它們比前代模型更廣泛地泛化。「語言模型是無監督的多工學習者」這篇論文正是闡述了這一點——GPT-2在數百萬個網頁上進行訓練,能夠在幾個類別中超越基準,而這些類別以前需要非常專門的模型訓練。
例如,要讓GPT-2總結文字,您可以在文字末尾附加字串TL;DR,然後瞧!要讓GPT-2將文字從英文翻譯成法文,您只需提供一個翻譯範例,然後提供要翻譯的英文句子。模型會識別模式並相應地翻譯。就好像模型真的在某種程度上對提示中的文字進行推理一樣。在隨後的幾年中,我們找到了一些方法來引出LLM更複雜的推理模式。一種簡單而有效的方法是堅持要求模型在提供問題答案之前展示其逐步思考過程。這被稱為思維鏈提示。這背後的直覺是,與人類不同,LLM沒有內心獨白,因此它們在回答之前無法真正思考問題。
思維鏈提示的作用
思維鏈提示能夠提升LLM的推理能力,因為它允許模型逐步展示其思考過程,而不是直接給出答案。這種方法可以提高模型的可解釋性和可靠性。
def chain_of_thought_prompting(question):
# 示範思維鏈提示的基本結構
prompt = f"請逐步解釋如何解決以下問題:{question}"
return prompt
# 使用範例
question = "如何計算一個陣列的平均值?"
prompt = chain_of_thought_prompting(question)
print(prompt)
內容解密:
上述程式碼定義了一個名為 chain_of_thought_prompting 的函式,該函式接受一個問題作為輸入,並傳回一個包含思維鏈提示的提示字串。這個函式可以用於生成適合LLM處理的問題提示,從而引導模型提供逐步的解答過程。
外部知識的整合
為了提高LLM應用程式的能力,將外部知識整合到模型中是非常重要的。這可以透過RAG等技術來實作,讓模型能夠存取訓練資料以外的資訊。
def retrieval_augmented_generation(query, context_sources):
# 示範檢索增強生成的基本結構
relevant_context = retrieve_context(query, context_sources)
augmented_prompt = f"{query} {relevant_context}"
return augmented_prompt
def retrieve_context(query, context_sources):
# 示範如何檢索相關上下文
# 這裡應該實作具體的檢索邏輯,例如使用搜尋引擎或向量儲存
pass
# 使用範例
query = "最新的AI研究趨勢是什麼?"
context_sources = ["學術論文資料函式庫", "科技新聞網站"]
augmented_prompt = retrieval_augmented_generation(query, context_sources)
print(augmented_prompt)
內容解密:
上述程式碼定義了兩個函式:retrieval_augmented_generation 和 retrieve_context。retrieval_augmented_generation 函式用於生成增強提示,它首先呼叫 retrieve_context 函式來檢索與查詢相關的上下文,然後將查詢和相關上下文組合成增強提示。retrieve_context 函式是一個佔位符,應該根據具體的檢索需求實作相應的邏輯,例如使用搜尋引擎或向量儲存來檢索相關檔案或資訊。
設計LLM應用程式的挑戰與評估方法
大語言模型(LLM)應用程式的設計與評估是一個複雜的過程,需要考慮多個因素,包括模型的思考過程、工具的使用、以及應用程式的品質評估。
LLM的思考過程
LLM的思考過程是透過逐步生成token來實作的,每個token都是根據前面的token生成的。因此,如果希望模型“思考”一個問題,就需要在輸出中“大聲”地進行思考。這樣,後續的token就可以根據前面的token進行預測,從而得到更合理的答案。
def generate_thought_process(prompt):
# 初始化思考過程
thought_process = []
# 生成第一個token
token = generate_token(prompt)
thought_process.append(token)
# 逐步生成後續token
while not is_complete(thought_process):
token = generate_token(thought_process)
thought_process.append(token)
return thought_process
#### 內容解密:
1. `generate_thought_process`函式用於初始化LLM的思考過程。
2. `generate_token`函式根據給定的提示或前面的token生成新的token。
3. `is_complete`函式檢查思考過程是否已經完成。
### 工具的使用
LLM本身是封閉的,無法與外部世界進行互動。因此,需要透過工具來擴充套件LLM的能力。工具可以是函式或API,用於執行特定的任務。
```python
def use_tool(tool_name, arguments):
# 根據工具名稱和引數執行相應的操作
if tool_name == "search":
return search(arguments)
elif tool_name == "lookup":
return lookup(arguments)
else:
return None
#### 內容解密:
1. `use_tool`函式根據工具名稱和引數執行相應的操作。
2. `search`和`lookup`函式分別用於執行搜尋和查詢操作。
### 應用程式品質評估
評估LLM應用程式的品質非常重要。評估方法包括離線評估和線上評估。
#### 離線評估
離線評估是在將新功能佈署到生產環境之前進行的評估。可以使用模擬的方式來評估應用程式的品質。
```python
def offline_evaluation(application):
# 模擬使用者互動
simulated_interactions = simulate_user_interactions(application)
# 評估應用程式的品質
quality_score = evaluate_quality(simulated_interactions)
return quality_score
#### 內容解密:
1. `offline_evaluation`函式用於進行離線評估。
2. `simulate_user_interactions`函式模擬使用者與應用程式的互動。
3. `evaluate_quality`函式根據模擬互動評估應用程式的品質。
#### 線上評估
線上評估是在應用程式佈署到生產環境之後進行的評估。可以使用遙測資料來評估應用程式的品質。
```python
def online_evaluation(application):
# 收集遙測資料
telemetry_data = collect_telemetry_data(application)
# 評估應用程式的品質
quality_score = evaluate_quality(telemetry_data)
return quality_score
#### 內容解密:
1. `online_evaluation`函式用於進行線上評估。
2. `collect_telemetry_data`函式收集應用程式的遙測資料。
3. `evaluate_quality`函式根據遙測資料評估應用程式的品質。