如何設計結合Agent的可靠AI知識庫
「如何設計可靠的AI知識庫」這堂課程將為你提供完整的AI知識管理解決方案。無論你是企業主、數位轉型負責人還是技術開發人員,這堂課都將幫助你掌握如何運用RAG技術來打造智能化知識管理系統,為企業提升效能
內容簡介
作者介紹
適合人群
你將會學到什麼
購買須知
-
-
講者介紹
Cupoy 如何設計一個可靠的AI知識庫 Hi 我是June 聖杰國際股份有限公司 電控工程師 AI4kids 共同創辦人 Cupoy 特聘講師 派斯客 業界顧問 台灣人工智慧學校 AI工程師 亞達科技 AI工程師
-
課程大綱
今天聽完分享會得到的內容 結合RAG的LLM應用典範 1. 什麼是LLM,LLM為什麼需要RAG 4. 知識的數位化: RAG怎麼將知識擷取到知識庫 5. 關於檢索: RAG怎麼從知識庫中找到相關資料 6. RAG怎麼幫助LLM回答問題 7. From top-k RAG to Advanced RAG 8. RAG的優勢與弱點 如何設計謹慎的AI知識庫 LLM RAG + Agent 1. Langchain agent 2. SQL agent + RAG
-
什麼是LLM與RAG
Chap1: 什麼是LLM,LLM為什麼需要RAG LLM (Large Language Model) 大型語言模型 是基於深度學習實現的自然語言模型,因為使用大量的參數來計算,所以加上大型的前綴。他的主要作用包括自然語言領域的分類、摘要、翻譯、問答、情感分析、文本生成等等,可以處理廣泛的自然語言任務。 知名的應用包括 ChatGPT Gamma(簡報AI生成器) 台灣大哥大智能客服 (台灣大嚐鮮) Microsoft Copilot 程式碼與文本生產力工具 引述Andrej Karpathy(OpenAI 共同創辦人、知名AI科學家)的貼文原文 大型語言模型(LLM)創造了一個全新的抽象層和職業。 到目前為止,我將這個角色稱為「提示工程師」,但我同意這名稱有些誤導。這不僅僅是提示,還涉及許多膠水代碼和基礎架構。也許「AI 工程師」這個稱呼還算可用,但它把一個過於具體的概念變得過於廣泛。 機器學習(ML)的人通常從頭開始訓練算法/網絡,這些網路通常是規模較小的模型。 由於其系統負荷繁重的工作,大型語言模型的訓練正變得與傳統機器學習不同,並分化出一種新型角色,專注於在超級電腦上進行大規模的Transformer 訓練。 從數量上來看,AI工程師的數量可能會顯著多於ML工程師或LLM工程師。在這個角色中,即使從未訓練過任何東西,也能取得很大的成功。 我對「軟體 1.0/2.0」的框架不完全理解。軟體 3.0(在我看來大約是 LLM 的提示操作)很有趣,因為提示是人類設計的「代碼」,但以英文表達,並由一個 LLM 來解釋(而 LLM 本身就是軟體 2.0 的產物)。AI 工程師同時在三種範式中進行編程,這有點讓人頭暈 😵💫 什麼是RAG? RAG是用來調整大型語言模型輸出的方式之一 可以把RAG當成LLM可以參考的一本筆記本。 透過RAG知識庫的參考當我們跟GPT或其他LLM交談時,提高回答的表現。
-
知識的數位化: RAG怎麼將知識擷取到知識庫
Chap2: 知識的數位化: RAG怎麼將知識擷取到知識庫 問題1: 筆記怎麼寫的 aka. RAG怎麼將知識擷取到知識庫 先獲得文字內容 將內容根據字元切分成Chunk 產生Embedding(嵌入) 存入資料庫 Embedding 圖片和表格會發生什麼事? 以Ollama和大多RAG工具來看,會直接被忽略掉 但並不是完全沒辦法處理,例如我們可以用更複雜的多模態模型來處理圖片 多模態的執行範例 利用LangChain 實作多模態模型的RAG... Langchain Multi-modal RAG 如果很難想像多模態的世界,可以回想一下駭客任務的場景。在那個世界景象、聲音、記憶甚至存在都是數位的,這些數位化的內容都是存在於數學上的一個空間中,這點已經不再科幻。多模態就是選擇性地把特定資料連結到一起的方法,例如貓的聲音與貓的照片。 一個常見迷思: RAG的嵌入也來自GPT4等大語言模型 實際上,我們只是需要內容與嵌入互相對應,所以用相對簡單的Bert等就可以了。但確實可以用GPT或其他LLM來進行,並獲得語意上更可靠的嵌入(但會貴的嚇人)。或者針對圖像型資料,才特別選擇用GPT4o來產生嵌入。 關於檢索: RAG怎麼從知識庫中找到相關資料 RAG怎麼從知識庫中找到相關資料 這個問題有關檢索方法,也就是到底怎麼找到想要的資料 簡單方案 計算嵌入之間的距離(餘弦相似度等),並排序top-K。 這裡的K是一個整數,例如5,就會找出前五個相似度最高的內容 進階RAG技巧 推薦閱讀: Advance RAG- Improve RAG performance Retrieval-Augmented Generation for Large Language Models: A Survey RAG怎麼幫助LLM回答問題 如何利用搜索到的相關內容 ?把搜索到的內容整合到用戶訊息裡面,一起送給LLM做回答。 RAG的效果 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks RAG就是創建數位化的第二大腦 一個筆記本: 擷取、檢索、儲存 第二大腦: 擷取、檢索、儲存、轉化
-
進階RAG技巧: From top-k RAG to Advanced RAG
進階RAG技巧: From top-k RAG to Advanced RAG 前檢索階段(Pre-Retrieval) 檢索階段(Retrieval) 後檢索階段(Post-Retrieval) 改善 RAG 效能的關鍵技術 前檢索階段(Pre-Retrieval) 數據準備與清理:清理數據,去除不必要的特殊字符、無用元數據、拼寫錯誤等,確保索引數據的質量。(知識清理) 添加元數據(metadata):在資料中加入額外的元數據,如概念、日期、章節,這有助於提高檢索效率。(知識的歸納) 索引結構(index)優化:可以使用知識圖譜(Knowledge Graphs or Graph Neural Network)或向量索引技術(更好的向量化方式)來增強檢索的精度和效率。 段落劃分優化(chunk optimize):選擇適當的 chunk 大小可以平衡檢索的精細度和系統效能,避免 chunk 過小導致資訊不足,或過大造成過多噪音。 Chunk控制了知識的頁面大小,RAG會找出有用的知識來參考,單位是Chunk,概念類似筆記本的某幾頁,頁面越大(A1)要找到重點資訊就更困難,頁數太小(A5)能容納的知識卻有限 目前最大的障礙和研究目標之一就是如何將知識自動並有效率的濃縮、歸納在一起 檢索階段(Retrieval) 就是一般我們認知到的檢索工作,在這個階段中可以: 查詢重寫(Query Rewriting):通過重寫用戶的查詢來提高檢索準確性,讓系統更好理解用戶需求。 多查詢檢索(Multi-Query Retrieval):從不同角度為單一查詢生成多個檢索,增加找到相關文件的可能性,解決多子問題的檢索挑戰。 混合檢索(Hybrid Search):結合關鍵字檢索和語義檢索來增強檢索的準確性,發揮各自優勢。 後檢索階段(Post-Retrieval) 重排序(Re-ranking):在 LLM 生成結果前對檢索結果重新排序,優先顯示最相關的內容,並避免過多無關文檔進入模型上下文。 上下文壓縮(Contextual Compression):壓縮檢索到的上下文,只保留對應查詢最相關的部分,減少噪音並加速生成速度。 改善 RAG 效能的關鍵技術: 資料清理與優化:清理無用或噪音數據,並將語義上重要的元素突出顯示,以提升檢索的精確性。 適當選擇 chunk 大小:針對不同任務選擇合適的 chunk 大小及重疊範圍,確保在檢索過程中能夠提供足夠的上下文。 多重檢索方法結合:將語義檢索、關鍵字檢索以及向量檢索混合使用,從而增強檢索的準確度和覆蓋面。 重新排序與壓縮文檔:優先提供高相關性的文檔,並對檢索出的文檔進行上下文壓縮,減少不相關信息的干擾。
-
Review: 如何設計謹慎的AI知識庫
Review 什麼是RAG RAG怎麼將知識擷取到知識庫 RAG怎麼從知識庫中找到相關資料 RAG怎麼幫助LLM回答問題 進階RAG技巧 如何設計謹慎的AI知識庫 Garbage in Garbage out 準則 (開始之前)設定適合公司的審核標準,確保回應內容的規範,輸入資料的整理原則 (當開始建立知識庫)對每一份新的資料,設立負責人,對知識庫的內容編寫回應內容的允許範疇。(例如: 客服機器人回應內容不能超出現有客服回應資料範例中) (當開始建立知識庫)工程師建立合理的資料擷取路徑,將新資料納入知識庫。 (新資料開始推論前)工程師建立Parser,確保輸出內容符合公司的標準,以及該新資料由負責人訂立的範疇。 (推論)上線後透過評分機制收集回應,或跟付費的高階LLM對談,並收集回饋 (維護)持續更新、管理知識庫。刪除廢、舊、重複知識 最大挑戰 範疇與審核標準定義 挑戰1: 關鍵資訊萃取 如何萃取到重要的資訊? 如何確保到的資訊是正確的? 混合結構和非結構化資料 用以產生結構化資料的AI - LayoutLM家族 使用LLM Agent從資料庫中存取準確無誤的資訊 LLM Agent還是LLM,但他透過跟運算環境連結,並多上了任務規劃和任務執行的能力。簡單的說,他現在不只能建議你做什麼,還能直接幫你做! 挑戰2: 圖文混合 如何解決圖文混合問題 使用CLIP家族產生嵌入(Local) 使用GPT4理解圖片產生嵌入(Recommend) 挑戰3: 正規化回應 Layout Parser 挑戰4: 持續更新 對RAG知識庫來說,必要且最大的支出就是更新知識庫。特別是在專業領域,或需要語言工程師參與的場景,例如建立Question-Answer的對應,或是醫療或法律相關知識是涉及到案例或臨床資料。 如何將使用者的問題與回應收入知識庫 評分 使用高階語言模型產生 No-code 關鍵知識管理知識庫 No-code 關鍵資訊萃取器 混合結構與非結構資料的知識庫 優化的Layout Parser
-
如何設計謹慎的AI知識庫
如何設計謹慎的AI知識庫 Garbage in Garbage out 準則 (開始之前)設定適合公司的審核標準,確保回應內容的規範,輸入資料的整理原則 (當開始建立知識庫)對每一份新的資料,設立負責人,對知識庫的內容編寫回應內容的允許範疇。(例如: 客服機器人回應內容不能超出現有客服回應資料範例中) (當開始建立知識庫)工程師建立合理的資料擷取路徑,將新資料納入知識庫。 (新資料開始推論前)工程師建立Parser,確保輸出內容符合公司的標準,以及該新資料由負責人訂立的範疇。 (推論)上線後透過評分機制收集回應,或跟付費的高階LLM對談,並收集回饋 (維護)持續更新、管理知識庫。刪除廢、舊、重複知識 最大挑戰 範疇與審核標準定義 挑戰1: 關鍵資訊萃取 如何萃取到重要的資訊? 如何確保到的資訊是正確的? 混合結構和非結構化資料 用以產生結構化資料的AI - LayoutLM家族 使用LLM Agent從資料庫中存取準確無誤的資訊 LLM Agent還是LLM,但他透過跟運算環境連結,並多上了任務規劃和任務執行的能力。簡單的說,他現在不只能建議你做什麼,還能直接幫你做! 挑戰2: 圖文混合 如何解決圖文混合問題 使用CLIP家族產生嵌入(Local) 使用GPT4理解圖片產生嵌入(Recommend) 挑戰3: 正規化回應 Layout Parser 挑戰4: 持續更新 對RAG知識庫來說,必要且最大的支出就是更新知識庫。特別是在專業領域,或需要語言工程師參與的場景,例如建立Question-Answer的對應,或是醫療或法律相關知識是涉及到案例或臨床資料。 如何將使用者的問題與回應收入知識庫 評分 使用高階語言模型產生 No-code 關鍵知識管理知識庫 No-code 關鍵資訊萃取器 混合結構與非結構資料的知識庫 優化的Layout Parser
-
langchain-agents範例
LangChain 手冊 langchain-agents範例 Agents 就像是 LLM 的「工具」。它們允許 LLM 存取 Google 搜尋、執行 Python的複雜計算,甚至進行 SQL 查詢。 在本筆記本中,我們將探索 Agents 以及如何在 LangChain 中使用它們。 我們將從安裝示例中所需的前置程式庫開始。 !pip install -qU openai google-search-results wikipedia sqlalchemy !pip install langchain==0.3.7 !pip install langchain_community==0.3.7 import langchain langchain.__version__ 要執行此筆記本,我們需要使用 OpenAI 的LLM。在此我們將設定將用於整個筆記本的 LLM,當提示時輸入您的 OpenAI API金鑰即可。 from getpass import getpass # OPENAI_API_KEY = getpass() OPENAI_API_KEY = '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' from langchain import OpenAI llm = OpenAI( openai_api_key=OPENAI_API_KEY, temperature=0 ) 我們會計算每次呼叫中使用的 tokens 數量。 from langchain.callbacks import get_openai_callback def count_tokens(agent, query): with get_openai_callback() as cb: result = agent(query) print(f'Spent a total of {cb.total_tokens} tokens') return result 設定完成後,讓我們進入 Agents 的主題。 什麼是 Agent? 定義:Agents 的核心在於為 LLM 提供使用工具的能力。這正是 LangChain與 ChatGPT的實現有所區別的地方,也讓我們初步了解它能為開發者帶來的價值。到目前為止,我們只介紹了幾個獨立的構建模組。現在,讓我們看看它們是如何組合起來的。 Agents 的官方定義如下: Agents 使用 LLM來決定要採取哪些行動以及行動的順序。行動可以是使用工具並觀察其輸出,或者直接返回結果給使用者。 在本節中,我們將介紹所謂的「通用」Agents,它們能執行許多元任務。此外,還有針對不同任務進行調整的更專用Agents(稱為 "agent-toolkits"),我們將在未來的章節中介紹。 建立資料庫 我們將使用 Agents來與一個小型的股票示例資料庫進行互動。由於這只是用於說明的工具,我們不會深入詳細內容。現在讓我們開始建立它。 from sqlalchemy import MetaData metadata_obj = MetaData() from sqlalchemy import Column, Integer, String, Table, Date, Float stocks = Table( "stocks", metadata_obj, Column("obs_id", Integer, primary_key=True), Column("stock_ticker", String(4), nullable=False), Column("price", Float, nullable=False), Column("date", Date, nullable=False), ) from sqlalchemy import create_engine engine = create_engine("sqlite:///:memory:") metadata_obj.create_all(engine) from datetime import datetime observations = [ [1, 'ABC', 200, datetime(2023, 1, 1)], [2, 'ABC', 208, datetime(2023, 1, 2)], [3, 'ABC', 232, datetime(2023, 1, 3)], [4, 'ABC', 225, datetime(2023, 1, 4)], [5, 'ABC', 226, datetime(2023, 1, 5)], [6, 'XYZ', 810, datetime(2023, 1, 1)], [7, 'XYZ', 803, datetime(2023, 1, 2)], [8, 'XYZ', 798, datetime(2023, 1, 3)], [9, 'XYZ', 795, datetime(2023, 1, 4)], [10, 'XYZ', 791, datetime(2023, 1, 5)], ] from sqlalchemy import insert def insert_obs(obs): stmt = insert(stocks).values( obs_id=obs[0], stock_ticker=obs[1], price=obs[2], date=obs[3] ) with engine.begin() as conn: conn.execute(stmt) for obs in observations: insert_obs(obs) 我們在這裡安裝 langchain_experimental 程式庫,因為 SQLDatabaseChain位於其中。未來可能會將其移至官方的 langchain 程式庫中。 !pip install langchain_experimental -qU from langchain.utilities import SQLDatabase from langchain_experimental.sql import SQLDatabaseChain db = SQLDatabase(engine) sql_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True) Agent 類型 在本節中,我們將回顧多種 Agent 並看看它們如何「思考」以及它們能做什麼。 使用 LangChain 的預建 Agent 涉及三個變數: 定義工具或工具包 定義 LLM 定義 Agent 類型 在 LangChain 中,這些都非常容易完成,我們將在以下示例中看到。 Agent 類型 #1:Zero Shot React 在這個示例中,我們將使用稍有不同類型的 Agent ------ SQLAgent,它可以通過自己的方法 create_sql_agent 實例化。其他 Agents將以更通用的方式進行實例化,我們將在後續示例中看到。 這種方法使用 toolkit 而不是簡單的工具清單。您可以在文件中了解更多相關內容。對於此用例,我們將使用 SQLDatabaseToolkit。 顧名思義,我們將使用這個 Agent對輸入執行「零記憶」任務。這意味著我們不會進行多次相互依賴的交互,而僅僅執行一次。換句話說,這個Agent 沒有記憶功能。 現在我們準備初始化 Agent!我們將 verbose 設為True,這樣我們就可以觀察到 Agent 的「思考」過程。 重要提示: 當與 Agents 互動時,設置 max_iterations參數非常重要,因為 Agents 可能陷入無限循環,消耗大量 tokens。預設值為15,允許使用多個工具和進行複雜推理,但對於大多數應用,您應該將其設置得更低。 from langchain.agents import create_sql_agent from langchain.agents.agent_toolkits import SQLDatabaseToolkit from langchain.agents.agent_types import AgentType agent_executor = create_sql_agent( llm=llm, toolkit=SQLDatabaseToolkit(db=db, llm=llm), verbose=True, agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION, max_iterations=3 ) 讓我們看看我們新創建的 Agent的效果!我們將向它提出一個涉及股票價格數學運算的問題。 result = count_tokens( agent_executor, "What is the multiplication of the ratio between stock " + "prices for 'ABC' and 'XYZ' in January 3rd and the ratio " + "between the same stock prices in January the 4th?" ) from pprint import pprint pprint(vars(agent_executor.agent)) # 深入检查 Runnable 中的结构 pprint(vars(agent_executor.agent.runnable)) 一如既往,我們來看看這裡的 Prompt 是什麼: from langchain.prompts import PromptTemplate # 提取 middle 部分的组件 middle_components = agent_executor.agent.runnable.middle # 遍历 middle 找到 PromptTemplate for component in middle_components: if isinstance(component, PromptTemplate): prompt_template = component.template print(prompt_template) 我們必須問自己:Agents 與 Chains 有什麼不同? 如果我們查看 Agent 的邏輯和剛才打印的Prompt,我們會看到一些明顯的差異。首先,Prompt中包含了工具。其次,原本在 Chains中是立即完成的思考過程,現在則涉及到「思考」、「行動」、「行動輸入」、「觀察」的序列。這是什麼意思? 簡單來說,LLM現在能夠「推理」如何最佳使用工具來解決問題,並且僅憑工具的簡短描述就可以以智能的方式結合它們。如果您想詳細了解這種MRKL(Modular Reasoning, Knowledge and Language)模式,請參考這篇論文。 最後,我們來關注「agent_scratchpad」。這是什麼?這是我們將每次 Agent執行的思考或行動追加的地方。通過這種方式,Agent在每個時間點都知道已經找到了哪些信息,並可以繼續其思考過程。換句話說,在使用工具後,Agent會將其思考和觀察追加到 Scratchpad,然後繼續推進。 Agent 類型 #2:Conversational React Zero Shot Agent很有趣,但正如我們之前所說,它沒有記憶功能。如果我們希望助手能記住我們之前談過的事情,並能對其進行推理和使用工具,這時我們需要使用Conversational React Agent。 我們將在這個示例中使用數學工具並按如下方式加載: from langchain.agents import load_tools tools = load_tools( ["llm-math"], llm=llm ) 這裡使用的記憶類型是一種簡單的緩衝記憶,它允許我們記住推理鏈中的前幾步。關於記憶的更多信息,請參考本系列的第三章。 from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory(memory_key="chat_history") from langchain.agents import initialize_agent conversational_agent = initialize_agent( agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, tools=tools, llm=llm, verbose=True, max_iterations=3, memory=memory, ) result = count_tokens( conversational_agent, "What's the result of an investment of $10,000 growing at 8% annually for 5 years with compound interest?" ) 如下所見,Prompt類似,但它包含了一個出色的指令開頭,使其成為一個有效的助手,並在內存模組中包含了聊天歷史記錄的欄位: print(conversational_agent.agent.llm_chain.prompt.template) 讓我們看看,如果我們試圖回答與之前問題相關的問題,會發生什麼: result = count_tokens( conversational_agent, "If we start with $15,000 instead and follow the same 8% annual growth for 5 years with compound interest, how much more would we have compared to the previous scenario?" ) Agent 類型 #3:React Docstore 這種類型的 Agent與我們之前看到的類似,但它包括與文檔存儲(Docstore)的互動。它只有兩個工具可用:「搜尋(Search)」和「查找(Lookup)」。 使用「搜尋」,它將調出相關文章;使用「查找」,Agent會在文章中找到正確的資訊片段。這可能通過示例最容易理解: from langchain import Wikipedia from langchain.agents.react.base import DocstoreExplorer, Tool docstore=DocstoreExplorer(Wikipedia()) tools = [ Tool( name="Search", func=docstore.search, description='search wikipedia' ), Tool( name="Lookup", func=docstore.lookup, description='lookup a term in wikipedia' ) ] docstore_agent = initialize_agent( tools, llm, agent="react-docstore", verbose=True, max_iterations=3 ) count_tokens(docstore_agent, "What were Archimedes' last words?") 我們不會在這裡打印Prompt,因為它太大了。但如果您想看到它,可以自己嘗試(我們已經知道如何操作了)。 簡而言之,它包含了幾個 Question > Thought > Action >Observation 循環的示例,這些循環包括「搜尋」和「查找」工具。 如果您想了解這種方法的更多信息,請參考這篇論文。 Agent 類型 #4:Self Ask with Search 當使用 LLM 從搜索引擎提取資訊時,這是首選 Agent。Agent會提問後續問題,並使用搜索功能來獲取中間答案,以幫助它達到最終答案。 from langchain import OpenAI, SerpAPIWrapper from langchain.agents import initialize_agent, Tool search = SerpAPIWrapper(serpapi_api_key='api_key') tools = [ Tool( name="Intermediate Answer", func=search.run, description='google search' ) ] self_ask_with_search = initialize_agent(tools, llm, agent="self-ask-with-search", verbose=True) 我們不會與此 Agent 互動,因為需要使用 SerpAPI 金鑰。然而,通過檢查Prompt,我們可以看到其運作的幾個示例: print(self_ask_with_search.agent.llm_chain.prompt.template) 如我們所見,Prompt 基本上是一系列示例,向 LLM展示如何對搜索工具進行後續提問,直到獲得最終答案。 再次強調,您可以在 這裡查看相關論文以進一步深入研究! 總結 這就是關於 Agents 的全部內容!它還有很多其他可以完成的事情,僅舉幾例: 創建您自己的自定義 Agent 與其他工具(甚至是自定義工具)一起使用 通過方便的用戶界面追踪 Agent 的每次呼叫 查看這些操作指南以了解更多!
-