利用檢索增強生成(RAG)技術快速開發解決方案,助力問答 LLM 工作流程,由此催生出新型系統架構。NVIDIA 將 AI 用于內部運營,并在系統功能與用戶期望之間取得了多項重要發現。
我們發現,無論預期的范圍或用例如何,用戶通常都希望能夠執行非 RAG 任務,例如執行文檔翻譯、編輯電子郵件甚至編寫代碼。一個普通的 RAG 應用程序可能會這樣實現:對每個消息執行檢索管道,從而導致令牌的過度使用,并由于包含不相關的結果而導致不必要的延遲。
我們還發現,即使應用程序專為訪問內部私有數據而設計,用戶也非常喜歡訪問 Web 搜索和摘要功能。我們使用 Perplexity 的搜索 API 來滿足這一需求。
在本文中,我們分享了用于解決這些問題的基本架構,即使用路由和多源 RAG 生成能夠回答各種問題的聊天應用程序。這是我們已用于 NVIDIA 生產的應用程序的精簡版本,用于支持銷售業務。有關更多信息,請參閱 NVIDIA/GenerativeAIExamples GitHub 存儲庫。
我們特別重點介紹了如何使用 LlamaIndex、NVIDIA NIM 微服務和 Chainlit 快速部署此應用。您可以將此項目用作 NVIDIA 和 LlamaIndex 開發者競賽 的靈感,展示這些技術在真實應用中的創新用途,并有機會贏取豐厚的獎品。
我們發現這些技術之間存在巨大的協同效應。NVIDIA NIM 微服務及其 LlamaIndex 連接器使開發具有自我管理或托管 LLM 的 LLM 應用變得輕而易舉。Chainlit 和 LlamaIndex Workflow
事件因其共享的事件驅動架構而完美契合,因此可以輕松為用戶界面提供有關 LLM 響應的完整追蹤信息。我們將在本文中詳細介紹系統詳情。

用于 LLM 部署的 NIM 微服務?
我們的項目圍繞 NVIDIA NIM 微服務構建,適用于以下模型:
盡管我們的團隊中沒有任何機器學習工程師或 LLM 推理專家,但我們在短短幾個小時內就申請并部署了自己的 llama-3.1-70b-instruct 實例,使用的是在配備 NVIDIA A100 的節點(8 個 GPU)上運行的 NIM 容器。這幫助我們避免了一些企業 LLM API 的可用性和延遲問題。
要試用 NIM API,請在 build.nvidia.com 上注冊帳戶并獲取 API 密鑰。要在此項目中使用 API 密鑰,請確保在位于項目目錄的 .env
文件中提供該 API 密鑰。 Python 包 llama-index-llms-nvidia
中提供了用于 NVIDIA 模型和 API 的 LlamaIndex 連接器。有關基于 NIM 的 LLM 部署的性能優勢的更多信息,請參閱《 使用 NVIDIA NIM 微服務優化大規模 LLM 的推理效率 》。
LlamaIndex Workflow
活動?
此應用程序的第一版基于 LlamaIndex 的 ChatEngine 類構建,后者為部署由向量數據庫支持的對話式 AI 助手提供了一站式解決方案。雖然效果不錯,但我們發現我們希望注入更多步驟來增強上下文,并以需要更高可擴展性的方式切換功能。
幸運的是,LlamaIndex Workflow
events 通過其事件驅動、基于步驟的方法來控制應用程序的執行流程,準確地提供了我們所需的解決方案。我們發現,將應用程序擴展為 Workflow
events 要容易得多,速度也更快,同時仍保留關鍵的 LlamaIndex 功能,例如必要時的向量存儲和檢索器。
圖 2 顯示了我們的 Workflow
事件,我們稍后會在本文中詳細說明。

Chainlit?
對于我們基于 LLM 的聊天應用來說, Chainlit 是一個不錯的解決方案。它使用 chainlit.Step
裝飾器支持進度指標和步驟摘要,而 LlamaIndexCallbackHandler
支持自動追蹤。我們為每個 LlamaIndex Workflow
事件使用了 Step
裝飾器,以在不會讓用戶不堪重負的情況下展示應用的內部運作。
Chainlit 對企業身份驗證和 PostgreSQL 數據層的支持對于生產也至關重要。
設置項目環境、依賴項和安裝
要部署此項目,請克隆位于 /NVIDIA/GenerativeAIExamples 的存儲庫,并創建一個虛擬 Python 環境,運行以下命令以創建和激活環境,然后再安裝依賴項:
mkdir .venv pip - m venv .venv source .venv / bin / activate pip install - r requirements.txt |
配置?
安裝依賴項后,請確保項目的頂層目錄中有一個 .env
文件,其中的值對應以下內容:
NVIDIA_API_KEY
:必填項。您可以從 build.nvidia.com 獲取 NVIDIA 服務的 API 密鑰。PERPLEXITY_API_KEY
. 可選。如果未提供,則應用程序在運行時不使用 Perplexity 的搜索 API。要獲取 Perplexity 的 API 密鑰,請 按照說明操作 。
項目結構?
我們將項目代碼整理成單獨的文件:
- LlamaIndex
Workflow
(workflow.py
):路由查詢并聚合來自多個來源的響應。 - 文檔提取 (
ingest.py
):將文檔加載到 Milvus Lite 數據庫中,這是一種在沒有容器的情況下從 Milvus 開始的簡單方法。Milvus Lite 的主要限制是低效的向量查找,當文檔集合增長時,可以考慮切換到專用集群。提取模塊使用 LlamaIndex 的SimpleDirectoryReader
來解析和加載 PDF。 - Chainlit 應用 (
chainlit_app.py
):Chainlit 應用包含由事件觸發的函數,主函數 (on_message
) 在用戶發送消息時激活。 - 配置 (
config.py
):若要使用不同的模型類型,請編輯默認值。在此,您可以選擇不同的模型用于路由和聊天完成,以及每次完成時從聊天歷史記錄中使用的過去消息的數量,以及 Perplexity 用于網絡搜索和總結的模型類型。
您還可以調整 prompts.py
中列出的提示,以適應您的用例。
構建核心功能?
此應用通過 Chainlit 集成了 LlamaIndex 和 NIM 微服務。為了展示如何實現這種邏輯,我們討論以下步驟:
- 創建用戶界面
- 實施
Workflow
事件 - 集成 NIM 微服務
創建用戶界面?
以下是從 chainlit_app.py
中的 Chainlit 應用開始,介紹此項目的實施方式。在 set_starter
函數中創建 Starter
對象列表,以將初始問題預填充為可單擊按鈕。這些內容有助于指導用戶了解可能的操作或問題,并將其引導至特定功能。
主聊天功能在 main 函數中進行管理,使用 cl.user_session
變量處理消息歷史記錄。 Chainlit 不需要這一點來顯示對話歷史記錄,但它使我們能夠在客戶端而不是 LlamaIndex 對象中保持狀態。
這種方法使原型設計更加直接,并促進了向傳統用戶前端后端應用程序的過渡,而有狀態的 LlamaIndex ChatEngine
則使 REST API 部署變得復雜化。
使用 workflow.run
調用 Workflow 時,會通過 Workflow 觸發一系列異步函數調用,這只需要當前用戶查詢和過去的聊天消息作為輸入。生成流式響應時,請使用 Chainlit 的 Message
類上的 stream_token
方法在用戶界面中顯示該響應。我們還添加了少量帶有樣式的 HTML,以顯示令牌數量和所用時間。
實施工作流事件?
RAG 邏輯包含在 workflow.py
中的 QueryFlow
類中,由定義為 QueryFlow
方法的多個步驟組成。每個方法都在其簽名中的事件發生時觸發。使用 nodes 屬性在步驟之間傳遞節點列表是構建工作流的一種簡單方法。一個節點代表 LlamaIndex 中的離散信息單元。
工作流步驟如下:
workflow_start
:將用戶查詢和聊天記錄添加到工作流的上下文(ctx.data
)中,并使用LLMTextCompletionProgram
在 RAG 和非 RAG 查詢之間路由。根據結果,它會生成RawQueryEvent
(觸發 RAG 邏輯)或ShortcutEvent
(觸發即時響應合成)。rewrite_query
:通過刪除可能會阻礙文檔查找的指令關鍵字,如“email”和“table”,轉換用戶的查詢,以獲得更好的搜索結果。它會觸發 TransformedQueryEvent
,用于 Milvus 檢索和 Perplexity 搜索步驟。embed_query
:為轉換后的查詢產生向量嵌入。milvus_retrieve
:使用向量嵌入進行向量搜索。pplx_retrieve
:使用用于 Perplexity 搜索 API 的 LlamaIndex 連接器獲取 Web 搜索結果,并匯總為單個節點。collect_nodes
:結合 Milvus 和 Perplexity 檢索的結果。完成兩個檢索事件后,此步驟便會觸發。在此處添加重新排序器可以優先考慮高值節點。
ready = ctx.collect_events( qe, expected = [ MilvusQueryEvent, PerplexityQueryEvent, ], ) if ready is None : logger.info( "Still waiting for all input events!" ) return None |
response_synthesis
:使用過去的聊天記錄上下文和檢索到的文檔構建提示字符串。我們手動形成此字符串,雖然也可以使用 LlamaIndex 模板。此步驟觸發StopEvent
,結束Workflow
事件,并通過為 LLM 生成的每個令牌生成CompletionResponse
對象來返回對 Chainlit 應用的響應。
總的來說,用戶的查詢首先經過一個路由步驟,其中 LLM 決定是否值得使用檢索來查找文檔來回答查詢。如果不值得,則使用后續完成調用來生成答案。
當用戶希望使用 LLM 執行不需要檢索的任務(例如編輯電子郵件或總結現有文本的段落)時,系統會觸發此分支。如果選擇檢索,則用戶的查詢將轉換為更適合搜索的形式。然后,使用 NVIDIA 嵌入模型以及 Milvus 向量存儲,這可用于對提取的文檔進行向量查找。
然后,使用 Perplexity 的 API 搜索結果來增強從這些步驟返回的文本,該 API 可以從 Web 查找數據以形成答案。最后,這些結果用于響應合成。圖 2 顯示了使用 llama-index-utils-workflow
生成的圖表。
集成 NIM 微服務?
得益于 llama-index-llms-nvidia
和 llama-index-embeddings-nvidia
軟件包中提供的連接器,可快速將 NVIDIA NIM 微服務用于 LLM 和嵌入功能。
由于 build.nvidia.com 提供了一系列模型,我們可以選擇小型、快速執行模型 Meta 的 meta/llama-3.1-8b-instruct 來執行路由查詢,同時還可以使用更大的模型 Mistral 的 mistralai/mistral-large-2-instruct 來生成具有出色推理能力的最終響應。
對于高性能的大型模型,另一個不錯的選擇是 Meta 的 Meta/LLAMA-3.1-405B-INSTRUCT。
使用 NIM 微服務的一大優勢是,如果您想遷移到本地或自我管理的 LLM 推理部署,除了為創建 LLM 設置 base_url 參數外,無需更改代碼。否則,完全相同!
對于我們自己的內部開發,我們通常會在 NVIDIA 推理的公共 API(位于 build.nvidia.com )與我們自己的自我管理的 Llama 3.1 部署之間進行切換。這為我們提供了很大的靈活性,可以在決定要自行管理和部署的 NIM 微服務類型之前,嘗試多個模型進行原型設計。
其他功能?
雖然其中一些功能超出了本文的討論范圍,但以下是一些易于添加的功能,可提升價值:
- 通過使用視覺語言模型(VLM)讀取表格、執行光學字符識別和描述圖像來實現 多模態攝入 。您可以在 Vision Language Models 中找到許多此類模型。
- 使用 Chainlit 的 Postgres 連接器的 用戶聊天記錄 。要保持用戶對話持續進行,您可以使用
chainlit.data_layer
的功能向 Chainlit 提供 PostgreSQL 連接詳細信息。 - RAG 使用基于 NVIDIA Mistral 的重新排名器進行排名。
- 提示 LLM 使用 HTML 樣式顯示帶有答案的超鏈接引文,從而 添加引文
- 通過錯誤處理和超時管理 來增強可靠性。雖然像 Perplexity 這樣的 API 對于回答各種查詢非常強大,但由于所涉及的底層組件的復雜性,它們的執行時間可能會非常可變。設置合理的超時并在此類答案不可用時迅速恢復是實現生產就緒型應用的重要一步。
參加 NVIDIA 和 LlamaIndex 開發者競賽,探索高級聊天功能改進后的譯文:參加 NVIDIA 和 LlamaIndex 開發者競賽,探索高級聊天功能
我們希望這篇博文對您有用,因為您可以詳細了解生成式 AI,以及如何將 NIM 微服務和 LlamaIndex Workflow
事件結合使用,以快速開發高級聊天功能。
如果您受到此項目的啟發,可以考慮參加 NVIDIA 和 LlamaIndex 開發者競賽 ,構建自己的 AI 解決方案,即有機會贏取現金獎勵、NVIDIA GeForce RTX 4080 SUPER GPU、DLI 積分等。
如果您有興趣了解更多信息或探索類似的應用,可以考慮深入了解此處的代碼,或嘗試使用 GitHub 上的 GenerativeAI Examples 庫 中的其他類似參考應用。
?