神經網路重新排序技術能有效提升搜尋結果的相關性,確保使用者獲得更精準的資訊。DrDecr Reranker 根據 ColBERT 模型,透過監督學習訓練,學習查詢與檔案間的相關性,並重新排序搜尋結果。生成式大語言模型則透過上下文學習,根據特定查詢調整模型,提供更精確的答案。文章中提供的程式碼範例展示瞭如何使用 Python 和相關函式庫實作 DrDecr Reranker,以及如何利用 LLM 進行上下文學習,並建構一個根據 Dash 的互動式問答系統。此外,文章也討論瞭如何透過資料驗證、受控生成、後生成驗證、領域自適應訓練及使用者回饋等策略降低 LLM 產生幻覺的風險。
增強搜尋結果的關鍵技術:神經網路重新排序與生成式LLM
在資訊檢索系統中,搜尋結果的準確性與相關性是至關重要的。為了提升搜尋體驗,企業級應用通常會採用多種先進技術來增強搜尋結果的品質。本篇文章將探討神經網路重新排序(Neural Reranker)與生成式大語言模型(Generative LLM)在搜尋結果增強中的作用。
神經網路重新排序(Neural Reranker)
神經網路重新排序是一種用於增強搜尋結果排名的技術。它利用先進的機器學習方法,尤其是根據神經網路的模型,來重新評估和排序初始搜尋結果。這種技術可以顯著提高搜尋結果的相關性,確保最相關的結果被呈現給使用者。
DrDecr Reranker
DrDecr Reranker是一種根據ColBERT模型的重新排序技術。它透過監督學習方法進行訓練,使用標註好的資料集來學習查詢與檔案之間的相關性。該模型的訓練過程包括以下步驟:
- 查詢與檔案編碼:使用Transformer編碼器對查詢和檔案進行編碼。
- 評分函式:透過神經網路評分函式預測檔案的相關性排名。
- 損失函式最小化:使用最佳化演算法(如隨機梯度下降)最小化預測排名與真實排名之間的差異。
以下是DrDecr Reranker的實作範例:
def drdecr_reranker(question, max_reranked_documents=10):
reranker = ColBERTReranker(model=model_name_or_path)
reranker.load()
search_results = solr_retriever(question)
if len(search_results) > 0:
reranked_results = reranker.predict(queries=[question], documents=[search_results], max_num_documents=max_reranked_documents)
print(reranked_results)
reranked_results_to_display = [result['document'] for result in reranked_results[0]]
df = pd.DataFrame.from_records(reranked_results_to_display, columns=['rank', 'document_id', 'text'])
print('=========================================================')
print(f'QUERY: {question}')
return df['text'][0]
else:
return "0 documents found", "None"
內容解密:
drdecr_reranker函式:接受一個問題和可選的最大重新排序檔案數作為輸入。- 初始化
ColBERTReranker:建立ColBERTReranker例項並載入模型。 - 檢索搜尋結果:呼叫
solr_retriever函式檢索搜尋結果。 - 重新排序:如果有搜尋結果,則使用
reranker.predict方法對結果進行重新排序。 - 結果處理:將重新排序的結果轉換為DataFrame並列印查詢和結果。
- 傳回最相關檔案:傳回重新排序後的第一個檔案的文字。
生成式大語言模型(Generative LLM)
生成式大語言模型(LLM)能夠根據特定的上下文或提示進行學習和適應。這種能力被稱為上下文學習(In-context Learning)。透過更新模型以適應特定領域或任務,LLM能夠提供更準確和相關的回應。
圖表翻譯:
此圖示展示了RAG(檢索增強生成)流程中的上下文學習元件。上下文學習使LLM能夠根據特定的查詢或任務進行適應,從而提高其回應的相關性和準確性。
使用上下文學習開發企業級應用
大語言模型(LLMs)如GPT-3已經在龐大的網路文字上進行了預訓練,這賦予了它們對語言和知識的廣泛理解。然而,它們可能需要更多的領域專業知識或最新的資訊。上下文學習允許這些模型在給定的上下文中專門化和改進其回應。
上下文學習的重要性
上下文學習有助於提高模型在特定領域中回應的準確性、相關性和安全性。它允許模型適應各種任務,例如提供醫療建議、回答法律查詢或協助客戶支援。透過納入特定於上下文的資訊,大語言模型可以提供更為量身定做和適當的回應,使其在現實世界的應用中更加有價值和可靠。
開發根據上下文學習的聊天機器人
我們將使用上下文學習的概念來建立一個能夠根據檢索-重新排序管道提供的上下文回答自定義查詢的聊天機器人。
示例程式碼
output = query({
"inputs": "根據以下上下文回答問題。\
上下文:X700 行動電話的一些功能。透過多媒體訊息和電子郵件訊息傳送彩色圖片和影片剪輯給朋友和家人。\
使用藍牙、紅外線或USB連線將圖片、影片、電子名片等傳送到其他手機或裝置。\
使用附帶的miniSD卡和介面卡在適當的裝置之間交換內容。\
使用組態好的無線網際網路瀏覽器瀏覽網際網路。\
對VGA尺寸的影像新增框架、文字和流行藝術。\
捕捉影片剪輯。播放40音多聲道鈴聲。不再需要有線耳機!使用藍牙無線耳機。\
將您的聯絡人和日曆與其他網路裝置同步。在X700外部顯示屏上檢視來電者的身份。\
下載遊戲、影像、主題、聲音、影片和Java及Series 60應用程式。在一個地方檢視所有媒體檔案,即媒體函式庫。\
搜尋您的檔案;包括遊戲、影像、安裝包以及影片和聲音剪輯。接收、編輯和檢視Microsoft Word、Excel和PowerPoint檔案。\
將檔案傳送到印表機和投影機(需搭配適當的配件)。使用語音命令撥打號碼。\
說“開啟訊息”或“開啟相機”,手機將直接進入應用程式。1 \
問題:Panasonic X700的功能是什麼?",
"parameters": {'temperature': 0.5,
'max_new_tokens': 200,
'return_full_text': False,},
})
內容解密:
query函式用於向大語言模型提交查詢。inputs引數包含了問題及其對應的上下文。parameters字典用於控制模型的生成行為,如temperature控制輸出的隨機性,max_new_tokens限制輸出的長度。- 模型的輸出是一個根據給定上下文生成的答案。
緩解幻覺風險的策略
在應用大語言模型時,一個已知的挑戰是幻覺風險,即模型生成看似合理但事實上不正確或無法驗證的資訊。以下是一些緩解幻覺風險的策略:
資料真實性檢查:納入額外的驗證層以檢查用於上下文學習的資料的事實準確性。
- 將檢索到的資訊與已驗證的資料函式庫或可信來源進行交叉參考。
- 應用資料來源技術以追溯資訊的來源。
受控生成:調整生成引數以限制模型的創造自由,從而降低幻覺的可能性。
- 校準
temperature引數以降低生成文字的隨機性。 - 限制
max_new_tokens以控制模型的冗長度並保持輸出簡潔且切題。
- 校準
後生成驗證:在生成回應後,應用後處理步驟,將輸出與已知事實或外部資料函式庫進行檢查。
- 在關鍵使用案例中採用人工迴圈驗證以確保回應的可靠性。
領域自適應訓練:對LLM進行特定領域資料集的微調,並糾正先前識別出的幻覺。
- 收集模型產生幻覺的例項,並將其用作訓練中的負面示例。
- 不斷更新訓練集,以涵蓋新出現的資訊和主題。
使用者反饋用於持續學習:納入使用者反饋機制,以識別和糾正幻覺,並利用這些資料來指導持續的模型訓練。
- 設計反饋迴圈,允許使用者標記錯誤的回應。
- 定期檢視被標記的內容,以改進模型並更新知識函式庫。
使用者介面
本練習中,我們將使用Dash框架來構建使用者介面。然而,與之前的練習類別似,您可以選擇任何框架,並將各個元件視為樂高積木,它們可以組合起來構建整體應用程式。
示例程式碼
import os
import time
from textwrap import dedent
import dash
from dash import html
from dash import dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
內容解密:
- 這段程式碼匯入了構建Dash應用程式所需的函式庫。
dash和dash_bootstrap_components用於構建使用者介面。Input、Output和State用於定義應用程式的互動行為。
透過實施這些策略,可以減少LLM中的幻覺風險,確保學習過程產生可靠和精確的結果。這種方法提高了生成式語言模型在現實世界場景中的有用性,並在使用者中建立了對AI驅動系統的信任。
企業級應用程式開發中的互動式問答系統建置
在開發企業級的互動式問答系統時,我們需要結合多種技術與工具來實作一個強大且使用者友好的應用程式。以下是一個根據Dash框架和多個AI技術的實作範例。
環境設定與API金鑰管理
首先,我們需要設定開發環境並管理必要的API金鑰。這包括OpenAI和Hugging Face的API金鑰。我們可以透過建立一個.env檔案來儲存這些金鑰。
# .env檔案內容
export HF_API_KEY="Bearer hf_XXXXXXXXX"
export OPENAI_API_KEY="sk-XXXXXXXXX"
然後在主應用程式檔案(rag_dash_app.py)中讀取這些環境變數。
import os
openai.api_key = os.getenv("OPENAI_API_KEY")
hf_key = os.getenv("HF_API_KEY")
內容解密:
- 這段程式碼的作用是從環境變數中讀取必要的API金鑰,以供後續的API呼叫使用。
- 使用
os.getenv()函式可以安全地讀取環境變數,避免將敏感資訊硬編碼在程式碼中。
UI元件定義
接下來,我們定義了幾個UI元件,包括標題元件和文字方塊元件。
標題元件
def Header(name, app):
title = html.H1(name, style={"margin-top": 5})
logo = html.Img(
src=app.get_asset_url("apress-logo.png"),
style={"float": "right", "height": 60}
)
return dbc.Row([dbc.Col(title, md=8), dbc.Col(logo, md=4)])
內容解密:
Header函式建立了一個包含標題和Logo的頁首元件。- 使用
dbc.Row和dbc.Col來進行佈局控制,實作回應式設計。 app.get_asset_url()用於取得Logo圖片的URL。
文字方塊元件
def textbox(text, box="AI", name="Knowa"):
# 省略部分程式碼...
if box == "user":
style["margin-left"] = "auto"
style["margin-right"] = 0
return dbc.Card(text, style=style, body=True, color="primary", inverse=True)
elif box == "AI":
style["margin-left"] = 0
style["margin-right"] = "auto"
thumbnail = html.Img(
src=app.get_asset_url("apress-logo.png"),
style={
"border-radius": 50,
"height": 36,
"margin-right": 5,
"float": "left",
},
)
textbox = dbc.Card(text, style=style, body=True, color="light", inverse=False)
return html.Div([thumbnail, textbox])
內容解密:
textbox函式根據box引數的不同,建立不同樣式的文字方塊,用於顯示使用者輸入或AI回應。- 對使用者和AI的訊息框採用了不同的樣式和佈局,以區分兩者的訊息。
應用程式佈局
最後,我們定義了整個Dash應用的佈局。
app.layout = dbc.Container(
fluid=False,
children=[
Header("Generative Q&A", app),
# 省略部分程式碼...
dcc.Tabs(id="tabs-example-graph", value='tab-1-example-graph',
children=[
dcc.Tab(label='AI powered QA', children=[
# 省略部分程式碼...
]),
]),
html.Br(),
html.Footer(children="Please note that this content is made available with the Generative AI book. \
The content may include systems & methods pending patent with USPTO and protected under US Patent Laws. \
Copyright - Apress Publication")
],
)
內容解密:
- 使用
dbc.Container作為主容器,並設定fluid=False以固定寬度。 - 佈局中包含了標題元件、分頁元件以及頁尾元件,實作了一個基本的頁面結構。
- 分頁元件中使用了
dcc.Tab來建立不同的分頁內容。
透過上述步驟,我們成功地建立了一個根據Dash的互動式問答系統,並結合了多個AI技術來實作強大的功能。這個系統不僅具有良好的使用者介面,還具備了企業級應用所需的穩定性和可擴充套件性。
企業級應用程式開發:結合檢索與生成式語言模型
更新顯示回呼函式
首先,我們定義第一個回呼函式來更新顯示內容。
@app.callback(
Output("display-conversation", "children"),
[Input("store-conversation", "data")]
)
def update_display(chat_history):
conversation_parts = chat_history.split("<split>")[:-1]
conversation_components = [
textbox(x, box="user") if i % 2 == 0 else textbox(x, box="AI")
for i, x in enumerate(conversation_parts)
]
return conversation_components
內容解密:
此程式碼定義了一個名為 update_display 的回呼函式,用於更新對話顯示。當 store-conversation 元件的資料發生變化時觸發此回呼。函式將對話歷史記錄作為輸入,並使用 <split> 分隔符號將其分割成多個對話部分。然後,透過迭代對話部分並根據對話部分的索引呼叫 textbox 函式,建立對話元件。如果索引為偶數,建立使用者文字方塊元件;否則,建立 AI 文字方塊元件。最後,函式傳回對話元件列表,這些元件將顯示為 display-conversation 元件的子項。
清除輸出回呼函式
第二個回呼函式用於在點選「提交」按鈕後清除文字輸入框,以便使用者重新輸入查詢。
@app.callback(
Output("user-input", "value"),
[Input("submit", "n_clicks"), Input("user-input", "n_submit")],
)
def clear_input(n_clicks, n_submit):
return "" if n_clicks or n_submit else dash.no_update
內容解密:
此程式碼設定了一個回呼函式,用於更新 user-input 元件的值。當點選「提交」按鈕或提交表單時,清除輸入值,否則保持目前值不變。
執行聊天機器人回呼函式
最後,我們建立最關鍵的回呼函式,用於執行聊天機器人。
@app.callback(
[Output("store-conversation", "data"), Output("loading-component", "children")],
[Input("submit", "n_clicks"), Input("user-input", "n_submit")],
[State("user-input", "value"), State("store-conversation", "data")],
)
def run_chatbot(n_clicks, n_submit, user_input, chat_history):
if n_clicks == 0 and n_submit is None:
return "", None
if user_input is None or user_input == "":
return chat_history, None
context = drdecr_reranker(user_input)
chat_history += f"根據以下內容回答問題。內容:{context} 問題:{user_input}"
model_input = chat_history.replace("<split>", "\n")
# HuggingFace LLM 模型
model_output = call_huggingface_api(model_input)
model_output = format_model_output(model_output)
# OpenAI LLM 模型 - 取消註解以使用 OpenAI 模型
# model_output = call_openai_api(model_input)
model_output = f"{model_output}<split>"
return model_output, None
內容解密:
此程式碼定義了一個名為 run_chatbot 的回呼函式,用於執行聊天機器人。當點選「提交」按鈕或提交使用者輸入欄位時觸發此回呼。函式執行以下步驟:
- 檢查按鈕是否未被點選且未發生提交事件,如果是,傳回空值。
- 檢查使用者輸入是否為空或 None,如果是,傳回目前的對話歷史記錄。
- 根據使用者輸入產生上下文。
- 將上下文、使用者輸入和額外文字附加到對話歷史記錄字串中。
- 將對話歷史記錄中的
<split>標記替換為換行符號,以格式化為模型輸入字串。 - 呼叫
call_huggingface_api函式與 Hugging Face 語言模型 API 互動。 - 使用
format_model_output函式格式化傳回的模型輸出。 - 將模型輸出與
<split>標記連線,以與前面的對話分開。 - 傳回包含模型輸出和載入元件的元組。
結合檢索與生成式語言模型的優勢
透過結合檢索式方法和生成式語言建模,我們實作了一個更強健和高效的問答系統。此管道能夠存取和處理龐大的知識函式庫,使其能夠準確和高效地處理廣泛的使用者查詢。