langchain 入門中篇:數據封裝,Memory 封裝

數據的處理流程可以看一張圖來幫助理解

數據來源可以是網絡,可以是郵件,可以是本地文件

經過 Document Loaders 加載,再在 Transform 階段對文檔進行 split, filter, translate, extract metadata 等操作,之后在?Embed 階段進行向量化,存儲在向量數據庫中后期用于檢索。

加載文檔

準備工作:

安裝依賴庫:pip install pypdf

加載本地文檔

from langchain_community.document_loaders import PyPDFLoaderloader = PyPDFLoader("./data/spyl.pdf") # pdf 是從網上下載的,放在了 ./data 目錄下
pages = loader.load_and_split()print(pages[0].page_content)

輸出:

加載 web 網頁:

from langchain_community.document_loaders import WebBaseLoaderloader = WebBaseLoader("https://docs.smith.langchain.com/user_guide")  # LangSmith 的官方介紹
pages = loader.load_and_split()
print(pages[2].page_content)

輸出:

文檔處理器

1. TextSplitter

安裝依賴庫:pip install?--upgrade langchain-text-splitters

接下來我們將前面的文檔進一步切分處理

from langchain_text_splitters import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=300,chunk_overlap=50,length_function=len,add_start_index=True
)paragraphs = text_splitter.create_documents([p.page_content for p in pages])
for para in paragraphs:print(para.page_content)print("=====================")

輸出:

每個 chunk 300 個 token,重疊最多 50 個 token

注意:L昂Chain 的 PDFLoader 和 TextSplitter 實現都比較粗糙,實際生產不建議使用

向量數據庫與向量檢索

文檔已經加載到內存中,接下來就需要將文檔向量化,然后灌入向量數據庫

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS# 灌庫
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(paragraphs, embeddings)# 檢索 top-5 結果
retriever = db.as_retriever(search_kwargs={"k": 5})docs = retriever.invoke("白酒最近的產量")for doc in docs:print(doc.page_content)print("+++++++++++++++++++++")

輸出:

根據檢索結果,檢索成功匹配到了最相關的信息

小結:

  1. 文檔處理部分 LangChain 實現較為粗糙,實際生產中不建議使用
  2. 與向量數據庫的鏈接部分本質是接口封裝,向量數據庫需要自己選型

記憶封裝

先來看幾個簡單的例子:

對話上下文:ConversationBufferMemory

from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemoryhistory = ConversationBufferMemory()
history.save_context({"input": "你好啊"}, {"output": "你也好啊"})print(history.load_memory_variables({}))history.save_context({"input": "你再好啊"}, {"output": "你又好啊"})print(history.load_memory_variables({}))
{'history': 'Human: 你好啊\nAI: 你也好啊'}
{'history': 'Human: 你好啊\nAI: 你也好啊\nHuman: 你再好啊\nAI: 你又好啊'}

只保留一個窗口的上下文:ConversationBufferWindowMemory

from langchain.memory import ConversationBufferWindowMemorywindow = ConversationBufferWindowMemory(k=2)
window.save_context({"input":"第一輪問"}, {"output":"第一輪答"})
window.save_context({"input":"第二輪問"}, {"output":"第二輪答"})
window.save_context({"input":"第三輪問"}, {"output":"第三輪答"})print(window.load_memory_variables({}))
{'history': 'Human: 第二輪問\nAI: 第二輪答\nHuman: 第三輪問\nAI: 第三輪答'}

限制上下文長度:ConversationTokenBufferMemory

from langchain.memory import ConversationTokenBufferMemory
from langchain_openai import ChatOpenAIllm = ChatOpenAI()
memory = ConversationTokenBufferMemory(max_token_limit=200,llm=llm
)
memory.save_context({"input":"你好"}, {"output":"你好,我是你的AI助手。"})
memory.save_context({"input":"你會干什么?"}, {"output":"我上知天文下知地理,什么都會。"})
print(memory.load_memory_variables({}))
{'history': 'Human: 你會干什么?\nAI: 我上知天文下知地理,什么都會。'}

應用場景:

我們通過一個簡單的示例來展示 memory 的作用,這里設置 verbose=True ,這樣我們就可以看到 prompt 的生成。

from langchain.chains import ConversationChainconversation_with_summary = ConversationChain(llm=llm,# We set a very low max_token_limit for the purposes of testing.memory=memory,verbose=True,
)
conversation_with_summary.predict(input="今天天氣真不錯!")
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:
Human: 你好
AI: 你好,我是你的AI助手。
Human: 你會干什么?
AI: 我上知天文下知地理,什么都會。
Human: 今天天氣真不錯!
AI: 是的,今天天氣晴朗,氣溫適宜,適合出門活動。您有什么計劃嗎?
Human: 今天天氣真不錯!
AI:> Finished chain.

[13]:

'是的,今天天氣確實很好,陽光明媚,適合戶外活動。您想去哪里呢?'
conversation_with_summary.predict(input="我喜歡跑步,喜歡放風箏")
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:
Human: 你好
AI: 你好,我是你的AI助手。
Human: 你會干什么?
AI: 我上知天文下知地理,什么都會。
Human: 今天天氣真不錯!
AI: 是的,今天天氣晴朗,氣溫適宜,適合出門活動。您有什么計劃嗎?
Human: 今天天氣真不錯!
AI: 是的,今天天氣確實很好,陽光明媚,適合戶外活動。您想去哪里呢?
Human: 我喜歡跑步,喜歡放風箏
AI:> Finished chain.

[14]:

'那真是個好主意!跑步和放風箏都是很棒的戶外活動。您喜歡在什么樣的地方跑步呢?有沒有特別喜歡去的公園或者跑步道?'
conversation_with_summary.predict(input="獲取爬山也不錯,不如去爬一次黃山吧")
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:
AI: 是的,今天天氣晴朗,氣溫適宜,適合出門活動。您有什么計劃嗎?
Human: 今天天氣真不錯!
AI: 是的,今天天氣確實很好,陽光明媚,適合戶外活動。您想去哪里呢?
Human: 我喜歡跑步,喜歡放風箏
AI: 那真是個好主意!跑步和放風箏都是很棒的戶外活動。您喜歡在什么樣的地方跑步呢?有沒有特別喜歡去的公園或者跑步道?
Human: 獲取爬山也不錯,不如去爬一次黃山吧
AI:> Finished chain.

[15]:

'黃山是一個非常著名的旅游勝地,有著壯麗的風景和豐富的自然資源。黃山位于安徽省,被譽為中國的五大名山之一。登上黃山,您可以欣賞到奇松怪石、云海日出等壯麗景觀。不過需要注意的是,黃山地勢險峻,需要一定的體力和意志力來完成登山之旅。希望您在黃山能夠享受到美妙的風景和登山的樂趣!您需要我為您提供黃山的相關信息嗎?'
conversation_with_summary.predict(input="我喜歡什么運動?")
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:
AI: 黃山是一個非常著名的旅游勝地,有著壯麗的風景和豐富的自然資源。黃山位于安徽省,被譽為中國的五大名山之一。登上黃山,您可以欣賞到奇松怪石、云海日出等壯麗景觀。不過需要注意的是,黃山地勢險峻,需要一定的體力和意志力來完成登山之旅。希望您在黃山能夠享受到美妙的風景和登山的樂趣!您需要我為您提供黃山的相關信息嗎?
Human: 我喜歡什么運動?
AI:> Finished chain.

[16]:

'很抱歉,我不知道您喜歡什么運動。您可以告訴我您感興趣的領域,我會盡力為您提供相關信息。比如,如果您喜歡戶外活動,我可以為您介紹一些常見的戶外運動項目。如果您喜歡健身運動,我也可以為您提供一些健身的建議和指導。請告訴我您的興趣方向,我會盡力幫助您。'

從上面的實驗結果看,前面的對話長度 token 沒到 200 的時候,AI 能根據前面的對話來回答你的問題,但是當超過 200 之后,前面的信息就丟了,相當于遺忘了。

ConversationSummaryMemory

如果對話歷史如果很長,可以通過摘要記憶對信息進行濃縮

from langchain.memory import ConversationSummaryMemory, ChatMessageHistory
from langchain_openai import OpenAImemory = ConversationSummaryMemory(llm=OpenAI(temperature=0))
memory.save_context({"input": "你好"}, {"output": "你好,有什么需要幫助?"})
memory.load_memory_variables({})
{'history': '\nThe human greets the AI in Chinese. The AI responds in Chinese and asks if there is anything it can help with.'}
通過已經存在的messages或者摘要初始化
history = ChatMessageHistory()
history.add_user_message("hi")
history.add_ai_message("hi there!")memory = ConversationSummaryMemory.from_messages(llm=OpenAI(temperature=0),chat_memory=history,return_messages=True
)memory.buffer輸出:'\nThe human greets the AI, to which the AI responds with a friendly greeting.'
通過之前的摘要進行初始化來加快初始化速度
memory = ConversationSummaryMemory(llm=OpenAI(temperature=0),buffer="The human asks what the AI thinks of artificial intelligence. The AI thinks artificial intelligence is a force for good because it will help humans reach their full potential.",chat_memory=history,return_messages=True
)

在 chain 使用

from langchain_openai import OpenAI
from langchain.chains import ConversationChain
llm = OpenAI(temperature=0)
conversation_with_summary = ConversationChain(llm=llm,memory=ConversationSummaryMemory(llm=OpenAI()),verbose=True
)
conversation_with_summary.predict(input="Hi, what's up?")

輸出:

? ? > Entering new ConversationChain chain...
? ? Prompt after formatting:
? ? The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.

? ? Current conversation:

? ? Human: Hi, what's up?
? ? AI:

? ? > Finished chain.

? ? " Hi there! I'm doing great. I'm currently helping a customer with a technical issue. How about you?"

向量數據庫支持的VectorStoreRetrieverMemory?

當想引用對話中之前提到過的一些信息,這個 memory 會比較有用

初始化向量數據庫:

這一步會因使用的向量數據庫不同而有所區別,具體細節可以看向量數據庫的文檔

import faiss
from langchain_openai import OpenAIEmbeddings
from langchain_community.docstore import InMemoryDocstore
from langchain_community.vectorstores import FAISSembedding_size = 1536
index = faiss.IndexFlatL2(embedding_size)
embedding = OpenAIEmbeddings()
vectorstore = FAISS(embedding, index, InMemoryDocstore({}), {})
創建 VectorStoreRetrieverMemory
from langchain.memory import VectorStoreRetrieverMemoryretriever = vectorstore.as_retriever(search_kwargs={"k":2}) # 實際使用時 k 值會設置得比較高
memory = VectorStoreRetrieverMemory(retriever=retriever)# When added to an agent, the memory object can save pertinent information from conversations or used tools
memory.save_context({"input": "我喜歡披薩"}, {"output": "哦,那太好了"})
memory.save_context({"input": "我喜歡足球"}, {"output": "..."})
memory.save_context({"input": "我不喜歡梅西"}, {"output": "ok"}) #
print(memory.load_memory_variables({"prompt": "我該看什么體育節目?"})["history"])

輸出:

input: 我喜歡足球
output: ...
input: 我不喜歡梅西
output: ok
在 chain 中使用
from langchain_core.prompts import PromptTemplatellm = OpenAI(temperature=0) # Can be any valid LLM
_DEFAULT_TEMPLATE = """The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Relevant pieces of previous conversation:
{history}(You do not need to use these pieces of information if not relevant)Current conversation:
Human: {input}
AI:"""
PROMPT = PromptTemplate(input_variables=["history", "input"], template=_DEFAULT_TEMPLATE
)
conversation_with_summary = ConversationChain(llm=llm,prompt=PROMPT,memory=memory,verbose=True
)
conversation_with_summary.predict(input="你好,我是 Gem")

輸出:

> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Relevant pieces of previous conversation:
input: 我不喜歡梅西
output: ok
input: 我喜歡披薩
output: 哦,那太好了(You do not need to use these pieces of information if not relevant)Current conversation:
Human: 你好,我是 Gem
AI:> Finished chain.

[79]:

' 你好,Gem!我是你的AI助手。我可以回答你關于任何事情的問題。你有什么想知道的嗎?'
conversation_with_summary.predict(input="我喜歡什么?")

輸出:

> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Relevant pieces of previous conversation:
input: 我喜歡披薩
output: 哦,那太好了
input: 我喜歡足球
output: ...(You do not need to use these pieces of information if not relevant)Current conversation:
Human: 我喜歡什么?
AI:> Finished chain.

[80]:

' 你喜歡什么?我不太清楚,因為我是一個人工智能,我沒有自己的喜好。但是我可以告訴你一些我所知道的事情。比如,我知道你喜歡披薩和足球。你還喜歡什么?'

小結:

  1. LangChain 的 Memory 管理機制屬于可用的部分,尤其是簡單情況如按輪數或按 Token 數管理;
  2. 對于復雜情況,它不一定是最優的實現,例如檢索向量庫方式,建議根據實際情況和效果評估;
  3. 但是它對內存的各種維護方法的思路在實際生產中可以借鑒

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

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

相關文章

Keil用ST-LINK下載STM32程序后不自動運行

之后程序可以運行了,但是串口還沒有輸出,在debug模式下都是ok的。

加權 KNN 算法的原理與詳解

加權kNN,k近鄰算法的增強改進版本。 加權KNN算法 近鄰算法(k-Nearest Neighbors, kNN)是一種用于分類和回歸的非參數方法。它的基本思想是“看鄰居”,即通過查找離目標點最近的 K 個數據點,來判斷目標點的類別或數值。…

docker安裝elasticesarch-head

安裝 Elasticsearch-Head 通常涉及以下步驟: 拉取 Elasticsearch-Head 的 Docker 鏡像。 運行 Elasticsearch-Head 容器并連接到 Elasticsearch 實例。 以下是具體的命令: 拉取 Elasticsearch-Head 的 Docker 鏡像 docker pull mobz/elasticsearch-…

Sqlserver 如何創建全局只讀賬號?

由于SQL Server不支持全局數據庫權限,因此需要在每個數據庫中創建用戶并授予其只讀權限。可以使用動態SQL腳本來為所有現有數據庫設置權限,具體腳本如下 ##創建登陸賬號CREATE LOGIN user01 WITH PASSWORD password; ##除了系統庫外給user01 db_datare…

FactoryBean原理及用法

它的作用是用制造創建過程較為復雜的產品, 如 SqlSessionFactory, 但 Bean 已具備等價功能 使用 被 FactoryBean 創建的產品 會認為創建、依賴注入、Aware 接口回調、前初始化這些都是 FactoryBean 的職責, 這些流程都不會走 唯有后初始化的流程會走, 也就是產品可以被代理增…

學習aurora64/66b.20240703

簡介 The AMD LogiCORE?IP Aurora 64B/66B core是一種可擴展的輕量級高數據速率鏈路層協議,用于高速串行通信。該協議是開放的,可以使用AMD設備技術實現。 Aurora 64B/66B是一種輕量級的串行通信協議,適用于多千兆位鏈路 (如下圖所示)。它…

【MATLAB源碼-第139期】基于matlab的OFDM信號識別與相關參數的估計,高階累量/小波算法調制識別,循環譜估計,帶寬估計,載波數目估計等等。

操作環境: MATLAB 2022a 1、算法描述 在現代無線通信系統中,正交頻分復用(OFDM)因其高效的頻譜利用率、強大的抗多徑衰落能力以及靈活的帶寬分配等優勢,成為了一種非常重要的調制技術。然而,隨著無線通信…

采沙船智能監測識別攝像機

對于現代河流管理來說,采沙船智能監測識別攝像機正逐漸成為解決非法采砂和保護河流生態環境的重要工具。這類攝像機通過先進的視覺識別和數據分析技術,有效監控和管理河道上的采沙行為,對保護水域資源和改善生態環境具有顯著的意義。 采沙船智…

Linux容器篇-使用kubeadm搭建一個kubernetes集群

kubernetes集群架構和組件 master節點組件 kube-apiserver:Kubernetes API,集群的統一入口,各組件的協調者,以RESTful API提供接口服務,所有對象資源的增刪改查和監聽操作都交給APIserver處理后再交給Etcd存儲。 kube…

學習Mybatis

Mybatis 第一節 引言 1. 什么是框架 框架是一個半成品,解決了軟件開發過程中的普遍性問題,簡化了開發步驟,提高了開發效率。 2. 什么是ORM ORM全稱為Object Relational Mapping,意為對象關系映射,主要實現了將程序…

usecallback()與usememo()

簡單的說 都是用來監聽數據變化 來進行控制渲染、減少不必要的渲染 、優化性能 usecallback()是用來監聽數據變化從而調用方法 usememo()是用來監聽數據變化從而改變數據 使用return返回變化的數據 當然return 也可以返回方法 所以usememo()可以代替usecallback() 下面詳解 …

常見的編碼技術簡介

常見的編碼技術簡介 文章目錄 常見的編碼技術簡介1. 字符編碼1.1 ASCII1.2 Unicode 2. 數據傳輸編碼2.1 Base系列編碼2.1.1 Base642.1.2 Base162.1.3 Base322.1.4 Base852.1.5 其他Base編碼 2.2 URL編碼2.3 JSON2.4 XML2.5 Protobuf (Protocol Buffers) 1. 字符編碼 1.1 ASCII…

AI是在幫助開發者還是取代他們?——探討AI在軟件開發中的角色與未來

引言 隨著人工智能技術的迅猛發展,AI工具在軟件開發中的應用越來越廣泛。有人認為AI可以顯著提升開發者的效率,而也有人擔心AI會取代開發者的工作。本文將從三個方面探討AI在軟件開發中的角色:AI工具現狀、AI對開發者的影響以及AI開發的未來…

學習springAOP

第三章 Spring AOP 第一節 AOP 簡介 1. 概念 AOP全稱為Aspect Oriented Programming,表示面向切面編程。何為切面呢? 由此可以得出,切面是一種將那些與業務無關,但業務模塊都需要使用的功能封裝起來的技術。這樣便于減少系統的…

昇思25天學習打卡營第4天|應用實踐

昇思25天學習打卡營第4天 文章目錄 昇思25天學習打卡營第4天基于 MindSpore 實現 BERT 對話情緒識別模型簡介環境配置數據集數據加載和數據預處理input_idsattention_mask 模型構建模型驗證模型推理自定義推理數據集 打卡記錄 基于 MindSpore 實現 BERT 對話情緒識別 模型簡介…

奧比中光astra_pro相機使用記錄

一、信息獲取 1、官網 用于了解產品信息 http://www.orbbec.com.cn/sys/37.html 2、開發者社區 咨詢問題下載開發部https://developer.orbbec.com.cn/ 二 、windowvs19 1、相機型號 orbbec_astro_pro 根據對應的型號找到需要的包工具 踩坑1,因為這個相機型號…

第20章 Mac+VSCode配置C++環境

1. 下載VSCode VSCode下載地址在mac終端里輸入xcode- select --install命令,根據提示安裝xcode工具。 2. 安裝插件(4個) 打開VScode,點擊應用右側菜單欄 C/C(必裝) Code Runner(必裝&#xf…

UCOS-III 任務調度與就緒列表管理

01. 就緒優先級位圖 在實時操作系統中,任務調度的效率至關重要。UCOS-III通過就緒優先級位圖來快速查找最高優先級的就緒任務,從而實現高效調度。就緒優先級位圖是一個按位表示的結構,每個位代表一個優先級,當某個優先級上有任務就…

高效管理 TensorFlow 2 GPU 顯存的實用指南

前言 在使用 TensorFlow 2 進行訓練或預測時,合理管理 GPU 顯存至關重要。未能有效管理和釋放 GPU 顯存可能導致顯存泄漏,進而影響后續的計算任務。在這篇文章中,我們將探討幾種方法來有效釋放 GPU 顯存,包括常規方法和強制終止任…

【FFmpeg】avcodec_open2函數

目錄 1. avcodec_open21.1 編解碼器的預初始化(ff_encode_preinit & ff_decode_preinit)1.2 編解碼器的初始化(init)1.3 釋放編解碼器(ff_codec_close) FFmpeg相關記錄: 示例工程&#xff…