AI Agent開發學習系列 - langchain之LCEL(4):Memory

Memory的添加方式

from operator import itemgetterfrom langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
from pydantic import SecretStr
import os
from dotenv import load_dotenvload_dotenv()model = ChatOpenAI(api_key=SecretStr(os.environ.get("HUNYUAN_API_KEY", "")),  # 混元 APIKeybase_url="https://api.hunyuan.cloud.tencent.com/v1",  # 混元 endpointmodel="hunyuan-lite",  # 模型名稱temperature=0
)
prompt = ChatPromptTemplate.from_messages([("system", "你是一個可以幫助人類的機器人"),MessagesPlaceholder(variable_name="history"),("human", "{input}"),]
)

MessagesPlaceholder 是 LangChain 中用于在聊天提示模板中插入消息列表的占位符。它主要用于處理對話歷史和動態消息內容。

  • variable_name: 指定占位符的變量名,用于在運行時匹配對應的消息列表
  • 這個變量名需要與 Memory 組件的 memory_key 或 history_messages_key 保持一致
memory = ConversationBufferMemory(return_messages=True)

ConversationBufferMemory 是 LangChain 中最基礎、最常用的記憶組件,用于存儲對話歷史。它將所有的對話消息按順序保存在內存中,形成一個完整的對話緩沖區。
return_message參數:

  • True:返回消息對象列表(HumanMessage, AIMessage)
  • False:返回格式化的字符串
memory.load_memory_variables({})

load_memory_variables 是 LangChain 中所有 Memory 組件的核心方法,用于從記憶組件中加載記憶變量。它返回一個字典,包含當前存儲的記憶內容。
示例:基于當前輸入查詢相關記憶
variables = memory.load_memory_variables({"input": "Where is Lisa?"})

# 增加一條鏈
chain = (RunnablePassthrough.assign(history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"))| prompt| model
)

RunnablePassthrough 是一個特殊的可運行組件,用于在鏈中傳遞數據。它可以:

  • 直接傳遞輸入數據
  • 使用assign方法添加新的鍵值對到輸入字典中
  • 作為數據流的"橋梁"

RunnableLambda 是 LangChain LCEL 中用于將任意 Python 函數包裝成可運行組件的工具。它允許您在鏈中插入自定義函數邏輯。
itemgetter 是 Python 標準庫 operator 模塊中的一個函數,用于從字典、列表等可索引對象中提取特定位置的元素。在 LangChain LCEL 中,它常用于數據流處理中提取特定的鍵值。

  • 這里 itemgetter(“history”) 從 memory.load_memory_variables() 返回的字典中提取 “history” 鍵對應的值。

這段代碼構建了一個帶記憶功能的對話鏈。RunnablePassthrough.assign() 在保持原始輸入的同時,通過 RunnableLambda(memory.load_memory_variables) 從記憶組件中加載歷史對話,然后用 itemgetter(“history”) 提取出對話歷史列表,將其作為 history 字段添加到輸入數據中。這樣,當數據流經 prompt 模板時,歷史對話會被注入到提示詞中,最終讓 model 能夠基于完整的對話上下文生成回復,實現連續對話的記憶功能。

inputs = {"input": "你好,我是小明,很高興認識你。"}
response = chain.invoke(inputs)
response

輸出:

AIMessage(content='你好,小明!我也很高興認識你,希望我們能成為好朋友😄 無論是聊天、玩耍還是其他方面,都可以隨時找我哦。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 34, 'prompt_tokens': 18, 'total_tokens': 52, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '202f461322c14a2b37232dcb3e72cd56', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--e16a133a-6c92-46d0-a6a0-32deff6d2d7a-0', usage_metadata={'input_tokens': 18, 'output_tokens': 34, 'total_tokens': 52, 'input_token_details': {}, 'output_token_details': {}})
#保存記憶
memory.save_context(inputs, {"output": str(response.content)})
memory.load_memory_variables({})

輸出:

{'history': [HumanMessage(content='你好,我是小明,很高興認識你。', additional_kwargs={}, response_metadata={}),AIMessage(content='你好,小明!我也很高興認識你,希望我們能成為好朋友😄 無論是聊天、玩耍還是其他方面,都可以隨時找我哦。', additional_kwargs={}, response_metadata={})]}
inputs = {"input": "我是誰?"}
response = chain.invoke(inputs)
response
AIMessage(content='你是小明呀,我記得你。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 57, 'total_tokens': 66, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '021589cde3e5617bedeacaeff5363d11', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--20559b8d-df04-447a-ad7f-a66524eabb0d-0', usage_metadata={'input_tokens': 57, 'output_tokens': 9, 'total_tokens': 66, 'input_token_details': {}, 'output_token_details': {}})

這個 AIMessage 顯示模型回答"你是小明呀,我記得你",說明記憶功能正常工作。記憶的實現原理是:

  • 歷史注入:通過 RunnablePassthrough.assign() 將 memory.load_memory_variables() 返回的歷史對話作為 history 字段添加到輸入中
  • 提示詞構建:prompt 模板中的 MessagesPlaceholder(variable_name=“history”) 會將歷史對話插入到提示詞中,形成完整的上下文
  • 上下文感知:模型接收到包含歷史對話的完整提示詞,能夠理解之前的對話內容,因此能夠記住用戶之前介紹過自己叫"小明"

使用Redis來實現長時記憶

先確保本地安裝了redis sever并啟動:

brew install redis
brew services start redis
pip install redis
from typing import Optionalfrom langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from pydantic import SecretStr
import os
from dotenv import load_dotenvload_dotenv()prompt = ChatPromptTemplate.from_messages([("system", "你是一個擅長{ability}的助手"),MessagesPlaceholder(variable_name="history"),("human", "{question}"),]
)chain = prompt | ChatOpenAI(api_key=SecretStr(os.environ.get("HUNYUAN_API_KEY", "")),  # 混元 APIKeybase_url="https://api.hunyuan.cloud.tencent.com/v1",  # 混元 endpointmodel="hunyuan-lite",  # 模型名稱temperature=0
)chain_with_history = RunnableWithMessageHistory(chain,# 使用redis存儲聊天記錄lambda session_id: RedisChatMessageHistory(session_id, url="redis://localhost:6379/0"),input_messages_key="question",history_messages_key="history",
)# 每次調用都會保存聊天記錄,需要有對應的session_id
chain_with_history.invoke({"ability": "歷史", "question": "中國建都時間最長的城市是哪個?"},config={"configurable": {"session_id": "alex"}},
)

結果:

AIMessage(content='中國建都時間最長的城市是北京。北京作為中國的首都,有著悠久的歷史和豐富的文化底蘊。早在西周時期,北京就是諸侯國的都城之一,稱為“燕京”。在漫長的歷史進程中,北京曾多次成為中國的都城,包括金朝的燕京、元朝的大都(今北京)、明朝的首都以及清朝的京師。經過這些朝代的統治,北京成為了中國政治、經濟、文化的中心,至今已有超過800年的建都歷史。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 105, 'prompt_tokens': 18, 'total_tokens': 123, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '51335c0cd7911a579bb1db283adb907b', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--64edee75-ae46-49de-9802-9f6a9ed21f53-0', usage_metadata={'input_tokens': 18, 'output_tokens': 105, 'total_tokens': 123, 'input_token_details': {}, 'output_token_details': {}})

RunnableWithMessageHistory 是 LangChain 中用于為任何可運行組件(Runnable)自動添加消息歷史管理功能的包裝器。它簡化了記憶功能的實現,特別適合需要持久化對話歷史的場景。
RedisChatMessageHistory 是 LangChain 中基于 Redis 數據庫實現的消息歷史存儲類,用于持久化存儲聊天對話歷史。它繼承自 BaseChatMessageHistory,提供了高性能、可擴展的對話歷史管理功能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91326.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91326.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91326.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

向Coze學習,我們把這些工作流也開源了

要說現在最火的工作流是什么,那非視頻工作流莫屬了。我每天也都能接到不少咨詢短視頻工作流的需求。 這大半年來我們團隊也制作和整理了超過 100 工作流,其中很大一部分都是現在最火的視頻工作流。 為了向Coze開源致敬,這次我們斑碼團隊也決…

Git 從零開始:完整項目上傳指南

一、準備工作 1. 安裝 Git Windows:下載安裝包macOS:在終端運行 brew install gitLinux: # Ubuntu/Debian sudo apt update && sudo apt install git# CentOS/Fedora sudo yum install git2. 配置用戶信息(首次使用&am…

【AI】入門級提示詞模板:適用于ChatGPT、文心一言等主流模型

入門級提示詞模板:適用于 ChatGPT、文心一言等主流模型**在當下這個人工智能飛速發展的時代,ChatGPT、文心一言等主流大模型已經廣泛地融入到我們的工作與生活當中。不管是創作文章、生成代碼,還是進行數據分析、獲取創意靈感,這些…

如何解決 undetected_chromedriver 啟動慢問題

要解決 undetected_chromedriver 啟動慢的問題,可以從以下幾個方面優化配置和代碼: 1. 指定本地 Chrome 二進制路徑 避免自動搜索 Chrome 路徑,直接指定位置: driver uc.Chrome(browser_executable_pathrC:\Program Files\Google…

Python 程序設計講義(42):組合數據類型——元組類型:創建元組

Python 程序設計講義(42):組合數據類型——元組類型:創建元組 目錄Python 程序設計講義(42):組合數據類型——元組類型:創建元組一、元組的特征二、創建元組1、使用圓括號&#xff0…

windows 設置 vscode 免密遠程

我們可以使用 vscode ssh 進行遠程編輯文件項目。也可以使用 ssh 密匙 來實現免密登錄。 本人在本地windows系統有多個密匙,使用 D:\SPB_Data\.ssh\id_rsa_local 進行本地設備進行登錄。 在 vscode ssh 配置文件中添加 IdentityFile 配置 Host 本地設備ipHostName …

ubuntu自動搭建Android平臺NDK編譯環境

sh setup_ndk_env.sh自動下載NDK并解壓 提取Android平臺工具鏈 驗證Android工具鏈 設置工具鏈變量 export CROSS_TRIPLE=aarch64_linux_android export CROSS_ROOT=/home/ubuntu/${CROSS_TRIPLE} export ANDROID_NDK=${CROSS_ROOT} export AS=${CROSS_ROOT}/bin/llvm-as exp…

添加捕捉吸附標識(使用QT+OpenGL開發三維CAD)

捕捉吸附標識怎么畫出來?在點吸附的時候能夠展示吸附標識可以讓用戶更直觀的看到當前捕捉點,從而更準確的進行設計和繪制。 效果視頻見原文:添加捕捉吸附標識(使用QTOpenGL開發三維CAD) 16.Add snap label 鼠標捕捉吸…

元宇宙中的“蟲洞“:技術實現、應用場景與未來挑戰

一、技術定義與核心架構1.1 蟲洞的元宇宙隱喻概念來源:蟲洞在物理學中是連接不同時空的通道,而在元宇宙中,這一概念被引申為連接不同虛擬世界的跨平臺協議。英偉達Omniverse平臺通過USD(通用場景描述)實現了這一隱喻&a…

使用GIS中基于森林的分類與回歸模型來估算房屋價值

“基于森林的分類與回歸”,它可以幫助分析師有效地設計、測試和部署預測模型。 基于森林的分類與回歸應用了 Leo Breiman 的隨機森林算法,這是一種用于分類和預測的流行監督機器學習方法。該工具允許分析師輕松整合表格屬性、基于距離的要素和解釋柵格來…

《 java 隨想錄》| LeetCode鏈表高頻考題

前言:這是專門針對java語言講解的算法解析(題目順序大致參考《代碼隨想錄》)思維導圖操作鏈表刪除節點刪除鏈表中 D 節點時,只需將其前驅節點 C 的 next 指針指向 D 的下一個節點 E。添加節點?先讓 新節點 F 的 next 指針 指向 C…

學習嵌入式的第三十一天-數據結構-(2025.7.23)網絡協議封裝

今天的內容主要是網絡協議以及常用工具的介紹。協議頭與數據封包/拆包數據封包示例:MAC|IP|TCP|hello| ———————————— IP數據報IP頭信息默認20字節常用網絡測試工具telnetnetstatpingarpwiresharktcpdumpssh2secure crt工具安裝命令sudo ufw disable sud…

STL學習(十、常用排序、拷貝、替換算法)

目錄 一、常用排序算法 1.sort (1) 內置數據類型 (2)自定義數據類型 2. random_shuffle(iterator beg, iterator end) 3.merge 4.reverse 二、常用的拷貝和替換算法 1.copy(起始不如直接賦值) 2.replace 3.replace_if 4.swap 一、常用排序算法 1.sort 函數原型 s…

【Datawhale AI夏令營】科大訊飛AI大賽(大模型技術)/夏令營:讓AI理解列車排期表(Task3)

我沒招了jpgimport pandas as pd import requests import re import json from tqdm import tqdm from datetime import datetime, timedeltadef calculate_stop_duration(arrival_time_str, departure_time_str):"""計算列車停留時長,處理跨天和異常…

【前后端】node mock.js+json-server

JSON-Server 一個在前端本地運行,可以存儲json數據的server。前端開發可以模擬服務端接口數據,在本地搭建一個JSON服務,自己產生測試數據。 使用npm全局安裝json-server :npm install -g json-server可以通過查看版本號&#xff0…

疏老師-python訓練營-Day30模塊和庫的導入

浙大疏錦行 知識點回顧: 導入官方庫的三種手段導入自定義庫/模塊的方式導入庫/模塊的核心邏輯:找到根目錄(python解釋器的目錄和終端的目錄不一致) 作業:自己新建幾個不同路徑文件嘗試下如何導入 一.學習知識點 DAY30 …

神經網絡知識討論

AI 核心任務與數據類型:特征提取核心:AI 的核心是從原始輸入數據中提取特征,CV 是將圖像數據轉換為計算機可識別的特征,NLP 是將文本數據轉換為特征,數據挖掘是將結構化數據轉換為特征。數據類型特點:圖像數…

kotlin類型可為空,進行空安全的區別

定義一個可為空的變量b(String?),默認沒有?是不可以為空的 var b: String? "Kotlin" b null print(b) // 輸出 null默認不可為空 var a: String "Kotlin" a null // 編譯器報錯,null 不能被賦給不為空的變量空安全調用&#x…

Mysql事務基礎

事務是一個不可分割的數據庫操作序列,也是數據庫并發控制的基本單位,其執行的結果必須使數據庫從一種一致性狀態變到另一種一致性狀態。事務是邏輯上的一組操作,要么都執行,要么都不執行 事務的特點 A(Atomicity&#…

FastAPI入門:安裝、Pydantic、并發和并行

本系列參考FastAPI官方文檔:https://fastapi.tiangolo.com/zh/python-types/安裝 使用pip安裝: pip install fastapi此外還需要 ASGI 服務器,生產環境可以使用 Uvicorn 或者 Hypercorn。 ASGI服務器:異步服務網關接口,…