本文作者是賴冠州(Edison Lai),曾任職於國內大型媒體的資深數據工程師。這篇文章是他記錄自己今年三月參加 ALPHA Camp 與 ihower 共同推出的「Generative AI Engineer:LLM 應用開發工作坊」完課心得與收穫,我們獲得授權刊登,原文刊登在他的 Medium。
自從ChatGPT在2022年底問世以來,以LLMs為中心的應用服務已掀起一股革命。因緣際會在AI Your Summer – AI Builder Day聽到ihower老師的分享,發現老師很用心地在準備,就這樣趁勝追擊地報名了Generative AI Engineer:LLM 應用開發工作坊,透過短暫且密集地訓練來提升自己的能力。
紮實地上完課後發現工作坊帶給我的比想像中的還要多更多。工作坊的課程安排循序漸進,從OpenAI和Google Gemini APIs開始講起,接著提到多模態模型、Chain-of-Thought Prompting、如何串接多個Prompts,到最後講到各式各樣的LLM應用如Summarization、Retrieval-Augmented Generation (RAG)、Reasoning and Actioning (ReAct) Agents、Conversation等,帶我紮紮實實的走過一輪LLM應用領域的方方面面。
不僅如此,課程還有提供進階教材,節省自己研究,探索的許多時間。像是我最感興趣的RAG應用,老師上課時也直接示範多種進階策略來提升成效,也提供多篇進階RAG相關文章供自主學習,節省我許多時間。
此外,老師所設計的將近30個範例程式碼和直播課程30天回放的特色,都大大地協助我在課後能反覆學習以加深對LLM複雜技術的理解。
完成一系列課程後,我有三個Key Takeaways:
- RAG比我原本想得還有趣
- 次世代LLM應用——打造虛擬團隊
- 「軟體工程」仍是打造生產級LLM應用的關鍵
RAG比我原本想的還有趣
在上工作坊之前,早就知道建立RAG大概會經歷哪些環節,心想不就是「先拆解文件,接著取得每個文件區塊的embeddings並放入向量資料庫,再來進行相似性搜尋相關文件區塊,最後根據相關文件進行生成」嗎?上完工作坊後才發現RAG其實是個相當精細的LLM應用,比我想像得還要有趣許多。根據LangChain,RAG可以分為五個環節:
每個環節都有很大的發揮空間可以提升成效。舉例來說,使用者提出的查詢並不一定適合作為資訊檢索用途。因此,在Query Transformation階段會改寫、擴展、拆解、假設性地回答使用者提出的查詢等,目的都是盡可能地在接下來的階段能有更多相關文件被檢索出來。常見策略像是:
- Query Expansion:將使用者提出的問題改寫成多個相似問題,接著將多個相似問題都作為檢索使用。
- Query Decomposition:有時候使用者提出的問題過於複雜,這時候就可以將一個大問題拆解成多個子問題,接著將多個子問題都作為檢索使用。
- Hypothetical Document Embeddings (HyDE):在進行語義相似性搜尋時,原始問題的embeddings可能與相關文件的不相似。這時候就可以先以LLM原有知識,假設性地回答原始問題。接著以假設性回答的embeddings作為輸入,進行資訊檢索。
- Step-back Prompting:有時候原始問題過於具體也會造成資訊檢索的困難。這時候就可以先將原始問題先轉換成相對廣泛、抽象的問題,接著將轉換過後的問題作為檢索使用。
- 等等…
在Building Index階段,怎麼拆解文件、建立索引,都有可能會影響到RAG成效。常見做法有:
- 根據文件結構拆解區塊。
- 保留文件區塊的metadata。
- 針對同份文件區塊存好幾種不同的indices,可能是使用不同的embeddings模型,或是將文件轉換成假設性問題,再根據假設性問題建立indices。
- …
在Query Construction和Retrieval階段,也有不少提升成效的做法:
- Self-querying / Auto Retrieval:從使用者原始問題中,擷取metadata。並以metadata作為篩選,進行更精確的資訊檢索。
- Small-to-big Retrieval:先將文件進行兩階段拆解,第一階段先將文件拆解成「大區塊」,接著第二階段再從每個「大區塊」拆解成「小區塊」並儲存至向量資訊庫。進行資訊檢索時,還是以「小區塊」作為檢索標的,但最後是以每個「小區塊」所屬的「大區塊」,作為最終檢索出來的資訊進行生成。
- Semantic Layer:也有其它公司使用Semantic Layer作為LLM與資料庫的中介層,以減少LLM生成時的幻覺。
- …
有趣是有趣,但學完這麼多提升RAG成效的技巧後,我第一個念頭是「有需要每個技巧都用上嗎?」反覆思索後,我認為最核心還是在於「使用者反饋」,只要抱持簡單的心,也就是以「使用者體驗」為出發,去面對複雜的RAG應用就可以了。觀察使用者怎麼與RAG服務互動?問哪些問題?再根據使用者反饋來挑選合適技巧以提升成效即可。
次世代LLM應用——打造虛擬團隊
工作坊除了在RAG應用有很深入的內容外,也在「串接外部工具」和「打造虛擬代理人」下了不少工夫。
課程一開始先示範如何使用LLM串接單一外部工具開始:
- 先從使用者問題中,使用LLM擷取出需要的外部工具參數。
- 接著呼叫外部工具取得結果。
- 使用LLM將結果轉換成自然語言,回傳給使用者。
接著談到進階的ReAct Prompting:
- 先定義LLM有哪些工具可以使用,以及每項工具的內部參數描述。
- 根據使用者問題,推論該使用什麼外部工具。
- 執行外部工具取得結果。
- 觀察結果,若能回答使用者,則將結果轉換成自然語言,回傳給使用者;若沒辦法回答使用者,則重複上述步驟直到問題解決。
最後更示範如何使用Function Calling,更容易、成本更低、更有效率地打造虛擬代理人以協助使用者。
ReAct Prompting和Function Calling打開了我對於LLM應用的想像:如果我們能打造多位虛擬代理人並提供互動機制,那是不是就有機會打造一個虛擬團隊,解決更複雜的任務?
AutoGen正是其中一個多重代理人對話溝通的框架。它不僅提供Two-Agent Chat、Sequential Chat、Group Chat等多種互動模式,還有Human-in-the-loop機制,協助開發者發揮創意,打造次世代LLM應用。
另個例子則是MetaGPT,模擬一個有工程師、架構師、產品經理和專案經理的產品團隊和軟體開發流程,自動化完成產品需求文件、設計圖、程式碼等。
以LLM打造虛擬團隊的相關研究只會越來越多,相信在可預見的未來可以看到商業化成功的相關應用。
「軟體工程」仍是打造生產級LLM應用的關鍵
課程除了常見的LLM應用外,也有提到LLM在軟體工程面需要關注的議題,像是
- 內容審查機制:避免特定主題輸出,實際產品如AWS Bedrock Guardrails和Arthur Shield。
- 抵抗Prompt Injection:常見做法像是使用分隔符號以區隔使用者輸入、先行偵測使用者輸入是否有惡意行為、防禦性prompts等。
- 評估LLM應用成效:如使用傳統NLP常見的BLEU或ROUGE、使用LLM embeddings比較相似度、提供評分指南、準確率等都是可能的做法。
- 降低成本
- 降低延遲性
- 可擴展性
- LLMOps
- …
雖然LLM帶給我們前所未知的能力,能讓我們發揮想像力打造次世代AI產品,但在建構生產級、面向消費者的LLM服務時仍免不了「軟體工程」需注意的各個面向。我相信安全、低成本、穩定地提供LLM服務應用,仍是決定該服務能不能發佈至正式環境的重要因素。不僅如此,如何有效率地根據評估成效來迭代LLM服務應用,也會是重要的一環。
最後,我相當推薦這次的Generative AI Engineer:LLM 應用開發工作坊,它協助我:
- 節省自主研究、探索、學習的時間:這次工作坊,老師的教材整理得很有系統,由淺入深的示範近30個範例程式碼,大大地幫助我節省時間。
- 打好LLM基礎,快速建構知識地圖:這次工作坊帶我走過LLM應用的方方面面,協助我快速地建構相關知識地圖,打好基礎,讓我在未來自學上可以更快地進入狀況。
- 深化理解LLM:除了有將近30個範例程式碼和直播課程30天回放,讓我可以好好地複習相關課程,還有進階學習教材,可以讓我更深化地認識每種應用的細節。