LangChain 原理學習筆記
最新越發覺得 AI 的發展,對未來是一場革命,LangChain 已經在工程設計上有了最佳實踐,類似於 AI 時代的編程模型或編程框架,有點 Spring 框架的意思。之前在 LangChain 上也有些最佳實踐,所以在這裏分享記錄下。
LangChain 解決什麼問題
LangChain 是基於 LLM 之上的,在應用層和底層 LLM 之前的一個很好的編程框架,如果把 LLM 比喻爲各種類型的數據庫、中間件等這些基礎設施,應用層是各種業務邏輯的組合之外,那麼 LangChain 就負責橋接與業務層和底層 LLM 模型,讓開發者可以快速地實現對接各種底層模型和快速實現業務邏輯的軟件開發框架。
那麼 LangChain 是如何做到的呢?試想一下,現在底層有一個大模型的推理能力,除了在對話框手動輸入跟他聊天之外。如何用計算機方式跟它互動呢?如果把一次 LLM 調用當作一個原子能力,如何編排這些原子能力來解決一些業務需求呢?Langchain 就是來解決這個事情的。
LangChain 的幾個核心概念
Model I/O
這裏重點把背後的 LLM 模型做了一層封裝,開發者可以通過更改配置的方式快速切換底層 LLM 模型,比如 chatgpt,chatGLM、通義千問等模型。
同時還有些高階功能:比如提供了緩存等功能,這樣對於語義上類似的 query,如果緩存有,那麼 langchain 可以快速返回結果,而不需要調用大模型。
Retriver
檢索是爲了解決大模型打通用戶的本身數據,做一些面向業務屬性的東西。這裏的檢索並非傳統的關係型數據庫,更多的是與大模型的本身邏輯相似的,比如向量數據庫。
一個經典的結合 LLM 和外部用戶的文檔進行智能答疑的場景
文檔 -> 分詞 ->embedding-> 向量數據庫
query-> 向量數據庫查詢 ->TOP N-> 上下文 + 用戶提問 + prompt -> LLM -> 返回結果
一個經典的圖如下:
關鍵技術:文檔如何拆分、embedding 過程、 TOPN 向量距離的選擇
embedding 技術選型
embedding 是將現實中的物體通過向量化的方法轉化爲高維向量,可被機器學習模型所識別。他是一種映射,同時也保證了能清晰地表達現實物體的特徵。基於此,可以進行一些歸類分析、迴歸分析等。
現在市面上常見的 embedding 方法有通義千問的 embedding 等方法。
向量數據庫:
向量數據庫底層存儲的是一堆向量,它提供了根據向量相似度進行查詢的能力,一般情況下,向量相似度代表了現實世界中物體的相似度。比如”我的名字是小明 “和“我叫小明” 這兩句話所代表的含義幾乎是相同的,那麼在 embedding 之後,基於向量數據庫進行查詢的時候,它們倆的相似度就會很近。
Chain
各種類型的 chain,chain 代表了各種業務類型的組合,類似於工作流的編排。
Memory
LLM 本身提供了記憶的能力,同時提供了接口,開發者可以將歷史的對話記錄傳入給 LLM。LangChain 需要使用外部存儲保存這些歷史的會話和記憶。可以使用數據庫、緩存等進行保存。
Agent
重點是代理工具
代理工具可以讓應用程序基於大模型的推理能力,然後進行代理工具或代理服務的調用。因爲 LLM 是沒有 “聯網” 的能力的,如果想解決特定的應用場景,代理工具是個完美的選擇。
代理工具通常包含三個方面:用戶輸入、prompt 編排 LLM 思考與路由代理的過程、背後的代理服務。其中難點可能就在於 prompt 設計了。通常的 “套路” 是這樣的:
ReAct 模型
輸入:用戶的問題
思考過程:如果是情況 1(這個是需要 LLM 進行意圖識別進行思考的),那麼推理和提取出一些關鍵參數,調用 agent1,如果是情況 2,那麼推理和提取出一些關鍵參數,調用 agent2
Act:調用 agent1 對應一個 JSON 格式化的輸入,調用 function1,返回結果。
觀察:觀察調用後的結果,再結合推理的能力,再進行循環思考。
LangChain 的在實際場景中的實踐
集團內部開發了一個 JAVA 版本的 LangChain 框架,以下實踐基於此框架與開源大模型 chatGLM-6B 進行。
淘寶開放平臺智能問答
淘寶開放平臺對內託管了上萬個 API,每天在內部羣裏都會有開發者諮詢 API 發佈問題,之前我們是通過 NLP 來實現智能問答的,現將它升級爲基於大模型的智能問答,以下是具體的技術實現過程。
-
知識庫 Embedding 過程
由於之前已經沉澱好了很多知識庫,都是 Question-Answer 的這種形式,這裏我們對 Question,也就是問題進行 Embedding,此處採用通義千問提供的 Embedding 方法。
知識庫 embedding:
TongYiEmbeddings embeddings = new TongYiEmbeddings();
embeddings.setServerAccessId(ALINLP_EMBEDDINGS_ACCESSID);
embeddings.setServerUrl(ALINLP_EMBEDDINGS_SERVER_URL);
embeddings.setServerUuid(ALINLP_EMBEDDINGS_UUID);
Document document = new Document();
document.setPageContent(rawText);
List<Document> documents = embeddings.embedDocument(Arrays.asList(document));
Document vecDocument= documents.get(0);
// 向量化知識
String embeddingString = JSON.toJSONString(vecDocument.getEmbedding()).replaceAll("\\[", "{")
.replaceAll("\\]", "}");
return embeddingString;
-
向量數據庫存儲和查詢
此處採用 hologres 向量數據庫,圖中紅框表示知識庫問題與回答在數據庫中具體的向量化存儲數據。
向量距離數據庫查詢:
select origin_content as originContent,
origin_title as originTitle,
pm_approx_squared_euclidean_distance(embedding_title, #{embeddingTitle}) as distance
from vs_knowledge
order by distance asc
limit #{limit}
- 大模型問答鏈路
問答 chain 的基本實現:
//1. 初始化ChatGLM的參數
ChatGLMV2Internal chatGLMV2Internal = new ChatGLMV2Internal();
chatGLMV2Internal.setTemperature(0.01d);
chatGLMV2Internal.setMaxLength(2048);
//2. 提示詞編寫
PromptTemplate prompt = new PromptTemplate();
String template = "已知信息:\n" +
"{context} \n" +
"\n" +
"根據上述已知信息,簡潔和專業的來回答用戶的問題。如果無法從中得到答案,請說 “根據已知信息無法回答該問題” 或 “沒有提供足夠的相關信息”,不允許在答案中添加編造成分,答案請使用中文。問題是:{question}";
prompt.setTemplate(template);
//3. 向量數據庫檢索配置,比如最大向量距離
RetrievalQA qa = new RetrievalQA();
qa.setRecommend(5);
qa.setMaxDistanceValue(10000.0d);
qa.setLlm(chatGLMV2Internal);
qa.setPrompt(prompt);
qa.setRetriever(holoRetriver.asRetriever());
qa.init();
//4. LLM大模型問答
Map<String, Object> inputs = new HashMap<>();
inputs.put("question", question);
inputs.put("input", question);
Map<String, Object> outputs = qa.run(inputs);
llmKonwledgeDO.setContent(String.valueOf(outputs.get("text")));
// 補充 doclist
return llmKonwledgeDO;
AI Agent 實踐
以下實現了一個網關 API 調用日誌解析的 agent。
Agent 工具註冊:
this.setName("ApiLogTool");
this.setDescription("這是一個調用日誌查詢接口,如果[{question}]中包含requestId關鍵字,你可以請求這個工具與日誌系統進行交互,調用這個工具。\n" +
"請先提取出requestId的值,將它賦值爲value。調用參數:[{\"requestId\": \"value\", \"type\": \"String\", \"description\": \"調用請求id\"}]。");
工具解析:
Map<String,Object> parse = (Map<String,Object>)JSON.parse(toolInput);
if(parse.get("requestId")==null){
return new ToolExecuteResult("");
}
String requestId = parse.get("requestId").toString();
ApiLogSearchQuery apiLogSearchQuery = new ApiLogSearchQuery();
//日誌查詢解析處理
思考決策邏輯:
public static final String FORMAT_INSTRUCTIONS_CH =
"用戶提出了一個問題: {question} \n" +
"你可以選擇使用下面這些工具:\n"+
"{tool_list_description}"+
"\n"+
"同時你的思考過程如下:"+
"Thought: 每一次你需要首先思考你應該做什麼\n" +
"Action: 你需要決定是否使用工具,應該是[{tool_names}] 中的一個Action,格式爲JSON。如果匹配不到工具,就不要思考了,直接返回結果,請不要把思考過程返回給用戶。\n" +
"Input: 如果匹配到工具,使用的工具的輸入參數,賦值給params\n" +
"Observation: 如果匹配到工具,工具的輸出結果 格式爲[]。\n" +
"Answer: 每一步回答問題的答案,格式爲JSON。你可以多次使用Thought/Action/Input/Observation/Answer來一步一步的思考如何回答問題。\n";
個人小思考
-
未來微服務 HSF 這種形式會向上往 agent 工廠或者 agent 服務框架這種形式演進,因爲這個框架搭好了後,後面各個業務方快速集成到 agent 服務上,可被上層 AI 應用層調用
-
如果多個 agent 聯動了,纔是真正的智能
-
如何定義 agent?
Agent 體系架構可以分爲慎思型、反應型和混合型。
慎思型構建負責規劃和推理行爲,反應型構建處理需要快速響應的重要事件。
信念 - 期望 - 意圖(Belief-Desire-ltension, BDI) 體系架構是混合型體系架構的一個重要類型。 Agent 的表示形式,Agent 的行爲可以被描述成好像擁有信念、期望和意圖等思維狀態。信念表示 Agent 擁有的知識,期望描述 Agent 追求的目標,意圖說明 Agent 選擇計劃以實現哪些目標。
openai 提供的 agent 概念
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/0xzCAqiXOsscBItpN9R0lA