成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

LangChain 讓 LLM 帶上記憶

人工智能
本文介紹了 LLM 缺乏記憶功能的固有缺陷,以及記憶組件的原理,還討論了如何利用 LangChain 給 LLM 裝上記憶組件,讓 LLM 能夠在對(duì)話中更好地保持上下文。

最近兩年,我們見(jiàn)識(shí)了“百模大戰(zhàn)”,領(lǐng)略到了大型語(yǔ)言模型(LLM)的風(fēng)采,但它們也存在一個(gè)顯著的缺陷:沒(méi)有記憶。

在對(duì)話中,無(wú)法記住上下文的 LLM 常常會(huì)讓用戶感到困擾。本文探討如何利用 LangChain,快速為 LLM 添加記憶能力,提升對(duì)話體驗(yàn)。

LangChain 是 LLM 應(yīng)用開(kāi)發(fā)領(lǐng)域的最大社區(qū)和最重要的框架。

一、LLM 固有缺陷,沒(méi)有記憶

當(dāng)前的 LLM 非常智能,在理解和生成自然語(yǔ)言方面表現(xiàn)優(yōu)異,但是有一個(gè)顯著的缺陷:沒(méi)有記憶。

LLM 的本質(zhì)是基于統(tǒng)計(jì)和概率來(lái)生成文本,對(duì)于每次請(qǐng)求,它們都將上下文視為獨(dú)立事件。這意味著當(dāng)你與 LLM 進(jìn)行對(duì)話時(shí),它不會(huì)記住你之前說(shuō)過(guò)的話,這就導(dǎo)致了 LLM 有時(shí)表現(xiàn)得不夠智能。

這種“無(wú)記憶”屬性使得 LLM 無(wú)法在長(zhǎng)期對(duì)話中有效跟蹤上下文,也無(wú)法積累歷史信息。比如,當(dāng)你在聊天過(guò)程中提到一個(gè)人名,后續(xù)再次提及該人時(shí),LLM 可能會(huì)忘記你之前的描述。

本著發(fā)現(xiàn)問(wèn)題解決問(wèn)題的原則,既然沒(méi)有記憶,那就給 LLM 裝上記憶吧。

二、記憶組件的原理

1.沒(méi)有記憶的煩惱

當(dāng)我們與 LLM 聊天時(shí),它們無(wú)法記住上下文信息,比如下圖的示例:

2.原理

如果將已有信息放入到 memory 中,每次跟 LLM 對(duì)話時(shí),把已有的信息丟給 LLM,那么 LLM 就能夠正確回答,見(jiàn)如下示例:

目前業(yè)內(nèi)解決 LLM 記憶問(wèn)題就是采用了類(lèi)似上圖的方案,即:將每次的對(duì)話記錄再次丟入到 Prompt 里,這樣 LLM 每次對(duì)話時(shí),就擁有了之前的歷史對(duì)話信息。

但如果每次對(duì)話,都需要自己手動(dòng)將本次對(duì)話信息繼續(xù)加入到history信息中,那未免太繁瑣。有沒(méi)有輕松一些的方式呢?有,LangChain!LangChain 對(duì)記憶組件做了高度封裝,開(kāi)箱即用。

3.長(zhǎng)期記憶和短期記憶

在解決 LLM 的記憶問(wèn)題時(shí),有兩種記憶方案,長(zhǎng)期記憶和短期記憶。

  • 短期記憶:基于內(nèi)存的存儲(chǔ),容量有限,用于存儲(chǔ)臨時(shí)對(duì)話內(nèi)容。
  • 長(zhǎng)期記憶:基于硬盤(pán)或者外部數(shù)據(jù)庫(kù)等方式,容量較大,用于存儲(chǔ)需要持久的信息。

三、LangChain 讓 LLM 記住上下文

LangChain 提供了靈活的內(nèi)存組件工具來(lái)幫助開(kāi)發(fā)者為 LLM 添加記憶能力。

1.單獨(dú)用 ConversationBufferMemory 做短期記憶

Langchain 提供了 ConversationBufferMemory 類(lèi),可以用來(lái)存儲(chǔ)和管理對(duì)話。

ConversationBufferMemory 包含input變量和output變量,input代表人類(lèi)輸入,output代表 AI 輸出。

每次往ConversationBufferMemory組件里存入對(duì)話信息時(shí),都會(huì)存儲(chǔ)到history的變量里。

2.利用 MessagesPlaceholder 手動(dòng)添加 history

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(return_messages=True)
memory.load_memory_variables({})

memory.save_context({"input": "我的名字叫張三"}, {"output": "你好,張三"})
memory.load_memory_variables({})

memory.save_context({"input": "我是一名 IT 程序員"}, {"output": "好的,我知道了"})
memory.load_memory_variables({})

from langchain.prompts import ChatPromptTemplate
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一個(gè)樂(lè)于助人的助手。"),
        MessagesPlaceholder(variable_name="history"),
        ("human", "{user_input}"),
    ]
)
chain = prompt | model

user_input = "你知道我的名字嗎?"
history = memory.load_memory_variables({})["history"]


chain.invoke({"user_input": user_input, "history": history})

user_input = "中國(guó)最高的山是什么山?"
res = chain.invoke({"user_input": user_input, "history": history})
memory.save_context({"input": user_input}, {"output": res.content})


res = chain.invoke({"user_input": "我們聊得最后一個(gè)問(wèn)題是什么?", "history": history})

執(zhí)行結(jié)果如下:

3.利用 ConversationChain 自動(dòng)添加 history

我們利用 LangChain 的ConversationChain對(duì)話鏈,自動(dòng)添加history的方式添加臨時(shí)記憶,無(wú)需手動(dòng)添加。一個(gè)鏈實(shí)際上就是將一部分繁瑣的小功能做了高度封裝,這樣多個(gè)鏈就可以組合形成易用的強(qiáng)大功能。這里鏈的優(yōu)勢(shì)一下子就體現(xiàn)出來(lái)了:

from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

memory = ConversationBufferMemory(return_messages=True)
chain = ConversationChain(llm=model, memory=memory)
res = chain.invoke({"input": "你好,我的名字是張三,我是一名程序員。"})
res['response']

res = chain.invoke({"input":"南京是哪個(gè)???"})
res['response']

res = chain.invoke({"input":"我告訴過(guò)你我的名字,是什么?,我的職業(yè)是什么?"})
res['response']

執(zhí)行結(jié)果如下,可以看到利用ConversationChain對(duì)話鏈,可以讓 LLM 快速擁有記憶:

4. 對(duì)話鏈結(jié)合 PromptTemplate 和 MessagesPlaceholder

在 Langchain 中,MessagesPlaceholder是一個(gè)占位符,用于在對(duì)話模板中動(dòng)態(tài)插入上下文信息。它可以幫助我們靈活地管理對(duì)話內(nèi)容,確保 LLM 能夠使用最上下文來(lái)生成響應(yīng)。

采用ConversationChain對(duì)話鏈結(jié)合PromptTemplate和MessagesPlaceholder,幾行代碼就可以輕松讓 LLM 擁有短時(shí)記憶。

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一個(gè)愛(ài)撒嬌的女助手,喜歡用可愛(ài)的語(yǔ)氣回答問(wèn)題。"),
        MessagesPlaceholder(variable_name="history"),
        ("human", "{input}"),
    ]
)
memory = ConversationBufferMemory(return_messages=True)
chain = ConversationChain(llm=model, memory=memory, prompt=prompt)

res = chain.invoke({"input": "今天你好,我的名字是張三,我是你的老板"})
res['response']

res = chain.invoke({"input": "幫我安排一場(chǎng)今天晚上的高規(guī)格的晚飯"})
res['response']

res = chain.invoke({"input": "你還記得我叫什么名字嗎?"})
res['response']

四、使用長(zhǎng)期記憶

短期記憶在會(huì)話關(guān)閉或者服務(wù)器重啟后,就會(huì)丟失。如果想長(zhǎng)期記住對(duì)話信息,只能采用長(zhǎng)期記憶組件。

LangChain 支持多種長(zhǎng)期記憶組件,比如Elasticsearch、MongoDB、Redis等,下面以Redis為例,演示如何使用長(zhǎng)期記憶。

from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-3.5-turbo",
    openai_api_key="sk-xxxxxxxxxxxxxxxxxxx",
    openai_api_base="https://api.aigc369.com/v1",
)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一個(gè)擅長(zhǎng){ability}的助手"),
        MessagesPlaceholder(variable_name="history"),
        ("human", "{question}"),
    ]
)

chain = prompt | model

chain_with_history = RunnableWithMessageHistory(
    chain,
    # 使用redis存儲(chǔ)聊天記錄
    lambda session_id: RedisChatMessageHistory(
        session_id, url="redis://10.20.1.10:6379/3"
    ),
    input_messages_key="question",
    history_messages_key="history",
)

# 每次調(diào)用都會(huì)保存聊天記錄,需要有對(duì)應(yīng)的session_id
chain_with_history.invoke(
    {"ability": "物理", "question": "地球到月球的距離是多少?"},
    config={"configurable": {"session_id": "baily_question"}},
)

chain_with_history.invoke(
    {"ability": "物理", "question": "地球到太陽(yáng)的距離是多少?"},
    config={"configurable": {"session_id": "baily_question"}},
)

chain_with_history.invoke(
    {"ability": "物理", "question": "地球到他倆之間誰(shuí)更近"},
    config={"configurable": {"session_id": "baily_question"}},
)

LLM 的回答如下,同時(shí)關(guān)閉 session 后,直接再次提問(wèn)最后一個(gè)問(wèn)題,LLM 仍然能給出正確答案。

只要configurable配置的session_id能對(duì)應(yīng)上,LLM 就能給出正確答案。

然后,繼續(xù)查看redis存儲(chǔ)的數(shù)據(jù),可以看到數(shù)據(jù)在 redis 中是以 list的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)的。

五、總結(jié)

本文介紹了 LLM 缺乏記憶功能的固有缺陷,以及記憶組件的原理,還討論了如何利用 LangChain 給 LLM 裝上記憶組件,讓 LLM 能夠在對(duì)話中更好地保持上下文。希望對(duì)你有幫助!

責(zé)任編輯:趙寧寧 來(lái)源: 程序員半支煙
相關(guān)推薦

2024-07-12 14:53:42

2024-07-03 09:38:35

LLM人工智能

2025-06-23 09:26:24

2024-03-07 09:15:57

2024-06-25 15:35:53

LangChain轉(zhuǎn)換鏈

2023-09-28 08:41:11

OpenAILLMLangChain

2024-06-19 08:14:51

大型語(yǔ)言模型LLMRAG

2023-08-03 09:02:32

LangChain開(kāi)發(fā)GLM

2025-05-12 02:50:00

2024-06-03 07:45:00

2024-05-14 09:57:10

人工智能QuarkusLLM

2023-06-29 08:00:00

人工智能LLMGPT-4

2025-06-16 09:40:48

2023-12-13 13:36:40

模型算力

2024-07-01 08:55:00

2023-08-07 18:55:19

2024-01-05 07:41:34

OpenLLM大語(yǔ)言模型LLM

2023-09-20 08:00:00

大語(yǔ)言模型代碼庫(kù)

2011-10-08 16:06:52

打印機(jī)推薦

2023-06-02 07:37:12

LLM?大語(yǔ)言模型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 中文在线亚洲 | 成人免费在线视频 | 一区二区三区国产 | 色嗨嗨| 日韩欧美网| 国产精品日韩在线观看 | 日韩欧美黄色 | 国产福利在线视频 | 天天操综合网站 | 久久精品一 | 一区二区av| 懂色av一区二区三区在线播放 | 欧美伊人影院 | 91在线精品一区二区 | 一区二区不卡 | 国产日产欧产精品精品推荐蛮挑 | 91在线第一页 | 亚洲精品美女在线观看 | 日韩中文字幕一区 | 久久99国产精一区二区三区 | 午夜伦理影院 | 一区精品国产欧美在线 | 免费欧美 | 精品无码久久久久久国产 | 中文字幕亚洲视频 | 亚洲成人一区 | 日韩av在线一区二区 | 国产精品美女一区二区三区 | 美女131mm久久爽爽免费 | 国产精品成人在线播放 | 久久久国产一区二区三区四区小说 | 国产欧美视频一区 | 国产成人jvid在线播放 | 成人a网 | 91热爆在线观看 | 秋霞电影一区二区 | 特级黄色毛片 | 亚洲综合在线视频 | 91精品久久 | 天天干天天玩天天操 | 亚洲一区视频在线 |