691 字
3 分钟
LangChain链路与会话历史

LangChain链路与会话历史#

本篇聚焦项目中的 LangChain 初始化部分,重点不是“如何写出一条最短链”,而是看 ChatPromptTemplateSQLChatMessageHistoryRunnableWithMessageHistory 在真实项目里是如何组合起来的。


三个核心对象#


1. ChatPromptTemplate#

prompt = ChatPromptTemplate.from_messages([
# ① system 消息:每次都发给模型,设定人格和能力范围
('system', "你是一个强大的多模态AI助手,可以精准地处理文本和图像输入。"),
# ② 历史占位符:运行时被替换为真实的历史消息列表
# variable_name 必须与 invoke({'messages': [...]}) 的键名一致
MessagesPlaceholder(variable_name="messages"),
])
MessagesPlaceholder 的作用

它是一个「空位」,告诉 LangChain:

  • 调用时把 messages 参数的值插到这里
  • RunnableWithMessageHistory 会在这个位置前自动插入历史消息

实际发给模型的消息结构:

[system] 你是一个强大的多模态AI助手...
[user] (历史消息1)
[assistant](历史回复1)
[user] (历史消息2)
[assistant](历史回复2)
...
[user] (本轮新消息) ← invoke() 传入的 messages

2. Chain 组合(管道符 |#

chain = prompt | multiModal_llm

| 是 LangChain 的管道操作符,等价于:

# 手动写就是这样,但用 | 更简洁
def chain(input):
prompt_value = prompt.format_messages(**input)
return multiModal_llm.invoke(prompt_value)

数据流向:

用户输入字典
→ prompt 模板渲染(填入 system + 历史 + 当前消息)
→ multiModal_llm 调用(发给阿里云 API)
→ AIMessage 对象(包含回复文字)

3. get_session_history#

def get_session_history(session_id: str) -> SQLChatMessageHistory:
return SQLChatMessageHistory(
session_id=session_id,
connection='sqlite:///chat_history.db',
)
这个函数什么时候被调用?

RunnableWithMessageHistory 在每次 invoke 时自动调用它:

  1. 调用前:用 session_id 查数据库,取出历史消息注入 Prompt
  2. 调用后:把新的 user + assistant 消息写回数据库

你不需要手动调这个函数,只是把它作为「工厂函数」传给框架。

SQLite 连接字符串格式
sqlite:///相对路径.db → 相对于当前工作目录
sqlite:////绝对路径.db → 四个斜杠

4. RunnableWithMessageHistory#

chain_history = RunnableWithMessageHistory(
chain, # 要包装的链
get_session_history # 如何获取历史存储对象
)
config = {"configurable": {"session_id": "usr000"}}

调用方式:

resp = chain_history.invoke(
{'messages': [input_message]}, # 只传本轮新消息!历史由框架自动加载
config # 指定 session_id
)
当前代码的限制:session_id 硬编码
config = {"configurable": {"session_id": "usr000"}}

所有用户共享同一段历史,适合单用户本地使用。

多用户场景的改进方案:

import uuid
# 每次启动生成新 session(无记忆)
config = {"configurable": {"session_id": str(uuid.uuid4())}}
# 或者根据用户身份生成固定 ID(跨会话记忆)
config = {"configurable": {"session_id": f"user_{user_id}"}}

完整调用时序#


相关笔记