1、内存模式 RunnableWithMessageHistory
"""
可持续记忆(RunnableWithMessageHistory)
"""
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.chat_history import InMemoryChatMessageHistory # 内存型消息记录
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
import os
load_dotenv()
# 设置本地模型
llm = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 定义全局的“会话存储”,用来保存每个 session 的聊天历史
# (真实项目中可改为 Redis、SQLite 等)
store = {}
def get_session_history(session_id: str):
"""
根据 session_id 获取对应的历史消息对象。
如果不存在则创建一个新的 InMemoryChatMessageHistory。
"""
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
# 定义 Prompt 模板
# - system: 给模型设定角色
# - MessagesPlaceholder: 历史消息将注入这里
# - human: 当前用户输入
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个友好的中文助理,会根据上下文回答问题。"),
MessagesPlaceholder("history"),
("human", "{question}")
])
#构建基本链:Prompt → LLM → 输出解析
memory_chain = prompt | llm | StrOutputParser()
# -----------------------------------------------------
# 将链包装为支持记忆的版本
with_history = RunnableWithMessageHistory(
memory_chain, # 原始链
get_session_history, # 获取历史函数
input_messages_key="question", # 对应 prompt 输入的 key
history_messages_key="history", # 对应 MessagesPlaceholder 的变量名
)
# -----------------------------------------------------
# 模拟一个会话,用 session_id 区分不同用户
cfg = {"configurable": {"session_id": "user-001"}}
# 第一次提问:告诉模型“我叫张三”
print("用户:我叫张三。")
print("AI:", with_history.invoke({"question": "我叫张三。"}, cfg))
# 第二次提问:让模型回忆前面的对话
print("\n 用户:我叫什么?")
print("AI:", with_history.invoke({"question": "我叫什么?"}, cfg))
2、持久化记忆 Redis
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableConfig
import os
import redis #导入原生redis库,pip install redis==5.3.1
from loguru import logger
load_dotenv()
REDIS_URL = "redis://:123456@localhost:6379"
# 创建原生Redis客户端,decode_responses 控制 Redis 返回数据的类型:False 返字节串,True 返字符串
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
# 设置本地模型
llm = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
MessagesPlaceholder("history"),
("human", "{question}")
])
def get_session_history(session_id: str) -> RedisChatMessageHistory:
"""获取或创建会话历史(使用 Redis)"""
# 创建 Redis 历史对象
history = RedisChatMessageHistory(
session_id=session_id,
url=REDIS_URL,
# ttl=3600 # 注释:关闭自动过期,避免重启后数据被清理
)
return history
# 创建带历史的链
chain = RunnableWithMessageHistory(
prompt | llm,
get_session_history,
input_messages_key="question",
history_messages_key="history"
)
# 配置
# session_id 就是登录大模型的各自帐户,类似登录手机号码,各不相同
config = RunnableConfig(configurable={"session_id": "user-001"})
# 主循环
print("开始对话(输入 'quit' 退出)")
while True:
question = input("\n输入问题:")
if question.lower() in ['quit', 'exit', 'q']:
break
response = chain.invoke({"question": question}, config)
logger.info(f"AI回答:{response.content}")
# 等同于redis-cli的SAVE命令,强制写入dump.rdb
redis_client.save()

连接redis redis-cli -a 123456
127.0.0.1:6379> keys *
1) "message_store:user-001"
LRANGE message_store:user-001 0 -1
查看redis保存的数据 power命令执行
.\.venv\Scripts\python.exe -X utf8 -c "import redis,json; c=redis.Redis.from_url('redis://:123456@localhost:6379',decode_responses=True); [print(json.dumps(json.loads(x),ensure_ascii=False,indent=2)) for x in c.lrange('message_store:user-001',0,-1)]"
返回数据:总共四条
{
"type": "ai",
"data": {
"content": "你是小明!😄 \n刚刚你已经自我介绍啦~名字简洁有力,听起来就充满朝气和亲切感!✨ \n(悄悄说:我还记得呢,不会忘~) \n\n如果你愿意,也可以告诉我更多关于你的事——比如你喜欢什么、最近在学什么、有什么小目标,或者今天心情怎么样?我在这里,认真听,也真心想了解你 🌈",
"additional_kwargs": {
"refusal": null
},
"response_metadata": {
"token_usage": {
"completion_tokens": 83,
"prompt_tokens": 79,
"total_tokens": 162,
"completion_tokens_details": null,
"prompt_tokens_details": {
"audio_tokens": null,
"cache_write_tokens": null,
"cached_tokens": 0,
"image_tokens": null,
"text_tokens": null
}
},
"model_provider": "openai",
"model_name": "qwen-plus",
"system_fingerprint": null,
"id": "chatcmpl-c054fcae-fadc-9f50-93f6-8f69237f0dff",
"finish_reason": "stop",
"logprobs": null
},
"type": "ai",
"name": null,
"id": "lc_run--01a1063a-8e35-7e21-b899-1c4598fbb86f-0",
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 79,
"output_tokens": 83,
"total_tokens": 162,
"input_token_details": {
"cache_read": 0
},
"output_token_details": {}
}
}
}
{
"type": "human",
"data": {
"content": "我是谁",
"additional_kwargs": {},
"response_metadata": {},
"type": "human",
"name": null,
"id": null
}
}
{
"type": "ai",
"data": {
"content": "你好,小明!很高兴认识你~😊 \n有什么想聊的、需要帮忙的,或者最近在忙什么?无论是学习、生活、兴趣爱好,还是遇到的小困惑,我都很乐意听你说说,一起探讨或帮你出出 主意!🌟",
"additional_kwargs": {
"refusal": null
},
"response_metadata": {
"token_usage": {
"completion_tokens": 55,
"prompt_tokens": 12,
"total_tokens": 67,
"completion_tokens_details": null,
"prompt_tokens_details": {
"audio_tokens": null,
"cache_write_tokens": null,
"cached_tokens": 0,
"image_tokens": null,
"text_tokens": null
}
},
"model_provider": "openai",
"model_name": "qwen-plus",
"system_fingerprint": null,
"id": "chatcmpl-6e3c3b67-c5be-9fb2-a079-01a11dbab809",
"finish_reason": "stop",
"logprobs": null
},
"type": "ai",
"name": null,
"id": "lc_run--01a10638-2663-72b2-9824-64a94d1c0e0b-0",
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 12,
"output_tokens": 55,
"total_tokens": 67,
"input_token_details": {
"cache_read": 0
},
"output_token_details": {}
}
}
}
{
"type": "human",
"data": {
"content": "我叫小明",
"additional_kwargs": {},
"response_metadata": {},
"type": "human",
"name": null,
"id": null
}
}
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!
浙公网安备 33010602011771号