引言:當AI學會"記住你"
2025年某銀行智能客服因無法記住用戶身份,每次對話都要求重復驗證,引發大量投訴。引入LangChain 記憶系統后,客戶滿意度提升62%。本文將基于MemorySaver與FAISS本地存儲,教你構建符合最新標準的記憶系統。
一、新版記憶架構核心變化
1.1 記憶存儲方案對比(LangChain 0.3+)
組件 | 適用場景 | 關鍵特性 |
---|---|---|
MemorySaver | 短期會話狀態 | 自動序列化,支持JSON/二進制 |
FAISS | 長期知識存儲 | 本地化部署,毫秒級檢索 |
PostgreSQL | 企業級記憶管理 | 事務支持,高可用 |
1.2 新舊API遷移指南
# 舊版(已廢棄)
# from langgraph.checkpoint import FileCheckpointer
?
# 新版(推薦)
from langgraph.checkpoint.memory import MemorySaver
from langchain_community.vectorstores import FAISS
二、構建新一代記憶系統
2.1 短期記憶
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_ollama import ChatOllama
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph
?
?
llm = ChatOllama(model="deepseek-r1")
?
workflow = StateGraph(state_schema=MessagesState)
?
?
# 定義模型調用函數
def call_model(state: MessagesState):system_prompt = ("你是一個有禮貌的助手. ""回答盡可能多的細節.")messages = [SystemMessage(content=system_prompt)] + state["messages"]response = llm.invoke(messages)return {"messages": response}
?
?
# 定義節點和邊
workflow.add_node("model", call_model)
workflow.add_edge(START, "model")
?
# 添加簡單的內存檢查點
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
?
response = app.invoke({"messages": [HumanMessage(content="你是誰?")]},config={"configurable": {"thread_id": "1"}},
)
print(response)
response = app.invoke({"messages": [HumanMessage(content="我剛才問你什么了?")]},config={"configurable": {"thread_id": "1"}},
)
print(response)
輸出為:
{'messages': [HumanMessage(content='你是誰?', additional_kwargs={}, response_metadata={}, id='03ed2cbb-59df-42c2-b865-bcd177e30833'), AIMessage(content='<think>\n好,我需要回答用戶的問題:“你是誰?” 用戶希望得到詳細的回應,并且我應該以禮貌的方式呈現。\n\n首先,我要確認自己的身份是DeepSeek-R1-Lite-Preview。這表明我是由深度求索公司開發的智能助手。接下來,我需要解釋我的功能和用途:通過算法處理信息并生成回答,幫助用戶解決問題或提供信息。\n\n然后,強調我沒有個人意識或情感,只是一個工具,以確保用戶的期望與實際功能相符。此外,提到遵守嚴格的倫理準則和隱私保護措施,這會增加用戶的信任感。\n\n最后,表達愿意隨時提供幫助的意愿,并詢問是否需要進一步的幫助或有其他問題,這樣可以讓用戶感到被重視和支持。\n</think>\n\n您好!我是DeepSeek-R1-Lite-Preview,一個由深度求索公司開發的智能助手,我通過算法處理信息并生成回答。我無法自主學習或更新,我的知識和能力是基于訓練數據設計的。我會以專業和誠懇的態度為您提供幫助,同時遵守嚴格的倫理準則和隱私保護措施。請問有什么可以幫您的?', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:13.718524566Z', 'done': True, 'done_reason': 'stop', 'total_duration': 32779446334, 'load_duration': 17223924, 'prompt_eval_count': 21, 'prompt_eval_duration': 148000000, 'eval_count': 228, 'eval_duration': 32612000000, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-939ed366-2088-4d99-97e4-f5e936ecc3c2-0', usage_metadata={'input_tokens': 21, 'output_tokens': 228, 'total_tokens': 249})]}
?
{'messages': [HumanMessage(content='你是誰?', additional_kwargs={}, response_metadata={}, id='03ed2cbb-59df-42c2-b865-bcd177e30833'), AIMessage(content='<think>\n好,我需要回答用戶的問題:“你是誰?” 用戶希望得到詳細的回應,并且我應該以禮貌的方式呈現。\n\n首先,我要確認自己的身份是DeepSeek-R1-Lite-Preview。這表明我是由深度求索公司開發的智能助手。接下來,我需要解釋我的功能和用途:通過算法處理信息并生成回答,幫助用戶解決問題或提供信息。\n\n然后,強調我沒有個人意識或情感,只是一個工具,以確保用戶的期望與實際功能相符。此外,提到遵守嚴格的倫理準則和隱私保護措施,這會增加用戶的信任感。\n\n最后,表達愿意隨時提供幫助的意愿,并詢問是否需要進一步的幫助或有其他問題,這樣可以讓用戶感到被重視和支持。\n</think>\n\n您好!我是DeepSeek-R1-Lite-Preview,一個由深度求索公司開發的智能助手,我通過算法處理信息并生成回答。我無法自主學習或更新,我的知識和能力是基于訓練數據設計的。我會以專業和誠懇的態度為您提供幫助,同時遵守嚴格的倫理準則和隱私保護措施。請問有什么可以幫您的?', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:13.718524566Z', 'done': True, 'done_reason': 'stop', 'total_duration': 32779446334, 'load_duration': 17223924, 'prompt_eval_count': 21, 'prompt_eval_duration': 148000000, 'eval_count': 228, 'eval_duration': 32612000000, 'message': {'role': 'assistant', 'content': '', 'images': None, 'tool_calls': None}}, id='run-939ed366-2088-4d99-97e4-f5e936ecc3c2-0', usage_metadata={'input_tokens': 21, 'output_tokens': 228, 'total_tokens': 249}), HumanMessage(content='我剛才問你什么了?', additional_kwargs={}, response_metadata={}, id='83a142cc-ad9a-4a76-baa3-675508cd70fb'), AIMessage(content='<think>\n好的,用戶現在問:“我剛才問你什么了?” 這可能是因為他想確認自己之前的問題或者只是隨便一問。\n\n首先,我要回憶之前的對話內容。上一次用戶的問題是“你是誰?”,而我的回答詳細介紹了我是DeepSeek-_lite版本的智能助手,并說明了我的功能和限制。\n\n現在,用戶詢問剛才的問題是什么,這可能表明他希望再次確認我的身份,或者他想繼續討論這個話題。也有可能他記不清了,只是想知道之前的對話內容。\n\n我需要禮貌地提醒他剛才問的是關于我的身份問題。同時,保持友好,邀請他提出更多的問題或進一步的討論。\n\n因此,在回復時,我會先簡單說明他之前的問題,然后詢問是否還有其他需求或想要繼續探討的內容。\n</think>\n\n您好!您剛才問的是:“你是誰?”如果您想了解更多或有其他問題,請隨時告訴我,我很樂意為您提供幫助。', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:47.33778896Z', 'done': True, 'done_reason': 'stop', 'total_duration': 33613724628, 'load_duration': 17323671, 'prompt_eval_count': 269, 'prompt_eval_duration': 5397000000, 'eval_count': 192, 'eval_duration': 28192000000, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-f86abc0a-3f22-47e0-8da6-f4c2bd22a157-0', usage_metadata={'input_tokens': 269, 'output_tokens': 192, 'total_tokens': 461})]}
2.2 長期記憶
from datetime import datetime
from langchain_community.vectorstores import FAISS
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
?
# 1. 初始化嵌入模型和向量數據庫
embeddings = OllamaEmbeddings(model="deepseek-r1")
?
# 初始化包含示例對話的向量庫
vectorstore = FAISS.from_documents(documents=[Document(page_content="用戶:如何重置密碼?",metadata={"type": "human", "timestamp": "2025-01-01"}),Document(page_content="AI:您可以訪問設置頁面,選擇'忘記密碼'選項。",metadata={"type": "ai", "timestamp": "2025-01-01"})],embedding=embeddings
)
?
# 2. 配置本地大模型
llm = ChatOllama(model="deepseek-r1")
?
# 3. 構建增強提示模板
template = """基于以下對話歷史和當前問題,用中文回答用戶:
歷史對話(最新在前):
{history}
當前問題:{question}
請給出專業解答:"""
prompt = ChatPromptTemplate.from_template(template)
?
?
# 4. 創建處理鏈
def build_chain():# 創建帶時間過濾的檢索器retriever = vectorstore.as_retriever(search_kwargs={"k": 2,"filter": lambda doc: doc.get("metadata", {}).get("type", "") in ["human", "ai"]})
?
?return (RunnablePassthrough.assign(# 獲取最近10條對話歷史history=lambda x: "\n".join([f"{doc.metadata['type']}:{doc.page_content}"for doc in retriever.invoke(x["question"])[:10]]))| prompt| llm)
?
?
# 5. 對話處理函數
def chat_loop():print("對話系統已啟動(輸入'exit'退出)")chain = build_chain()
?while True:user_input = input("你:").strip()if user_input.lower() == 'exit':break
?# 生成響應response = chain.invoke({"question": user_input})ai_response = response.contentprint(f"AI:{ai_response}")
?# 更新長期記憶new_docs = [Document(page_content=user_input,metadata={"type": "human", "timestamp": datetime.now().isoformat()}),Document(page_content=ai_response,metadata={"type": "ai", "timestamp": datetime.now().isoformat()})]vectorstore.add_documents(new_docs)vectorstore.save_local("chat_memory") ?# 持久化存儲
?
?
if __name__ == "__main__":chat_loop()
輸出為:
對話系統已啟動(輸入'exit'退出)
你:你好
AI:<think>
嗯,用戶發來了“你好”,看起來是一個問候。我應該禮貌地回應。首先,我可以用“你好!”來回復,這樣既簡潔又友好。然后,我可以進一步表示愿意提供幫助,比如問有什么可以幫忙的,或者詢問他們今天想聊些什么。這樣可以讓對話繼續下去,讓用戶感覺被重視和支持。
</think>
?
你好!很高興見到你,有什么我可以幫你的嗎?
你:怎么重置密碼
AI:<think>
好,我收到用戶的問題是“怎么重置密碼”。首先,我要考慮用戶的使用場景。可能是用戶忘記了原來的密碼,想要重新設置一個。接下來,我需要分析用戶的身份,可能是一個普通用戶,不太熟悉技術細節,所以回答要簡明易懂。
?
然后,我會思考用戶的真實需求。他們可能只是想快速解決問題,而不需要太多的技術術語。同時,可能會有更深層的需求,比如希望過程安全,確保密碼重置不會被他人惡意利用。
?
現在,我來組織一個專業的回答。首先,需要列出步驟:訪問登錄頁面,點擊“忘記密碼”,填寫注冊郵箱或手機號,按照提示操作,設置新密碼并保存。這樣分點說明清晰明了,用戶容易跟隨。
?
另外,我要考慮可能的安全問題,所以提醒用戶不要告訴他人驗證碼,并建議定期更換密碼以保護賬戶安全。這些額外的注意事項能夠幫助用戶更好地維護自己的賬號安全。
?
最后,整體語氣要友好且專業,讓用戶感受到被幫助和支持。
</think>
?
重置密碼通常需要按照以下步驟進行:
?
1. **訪問登錄頁面**:打開應用或網站的登錄界面。
?
2. **點擊“忘記密碼”**:在登錄頁面上找到并點擊“忘記密碼”或“找回密碼”的鏈接。
?
3. **輸入注冊郵箱或手機號**:根據提示,輸入你注冊時使用的郵箱地址或手機號碼。
?
4. **接收驗證碼或重置鏈接**:系統會發送一個驗證碼到你的郵箱或手機,或者直接提供一個鏈接讓你設置新密碼。
?
5. **按照提示操作**:使用收到的驗證碼完成身份驗證,然后按照系統的指示設置一個新的密碼。
?
6. **保存新密碼**:確保記住新的密碼,并妥善保管。
?
如果你在重置密碼過程中遇到任何問題,請聯系該服務的支持團隊獲取幫助。同時,確保不要將驗證碼告訴他人,以保護你的賬戶安全。
你:exit
三、企業級案例:金融客服系統
3.1 架構設計
3.2 關鍵性能指標
-
響應延遲:平均210ms(P99<450ms)
-
記憶準確率:用戶意圖識別提升58%
-
擴展性:單節點支持10,000+并發會話
四、避坑指南:新版記憶系統六大陷阱
-
未顯式持久化:FAISS索引修改后需手動保存
vector_db.save_local("./memory_index") ?# 關鍵操作!
-
會話ID沖突:未使用唯一標識導致記憶混淆
-
內存泄漏:MemorySaver未設置cache_size限制
-
版本不兼容:FAISS索引文件跨版本不兼容
-
權限問題:本地存儲目錄不可寫
-
監控缺失:未跟蹤記憶命中率
下期預告
《LangChain代理系統:讓AI自主決策與執行》
-
揭秘:如何讓大模型自主調用工具鏈?
-
實戰:構建能訂機票、查天氣的智能助手
-
陷阱:無限遞歸與權限管控
新一代記憶系統讓AI真正擁有了"過去"。記住:優秀的記憶設計,是智能體從"工具"進化為"伙伴"的關鍵一躍!