【零基础入门 LLM 开发 · Day 13】:LangChain 的对话记忆——Message 对象版

【零基础入门 LLM 开发 · Day 13】:LangChain 的对话记忆------Message 对象版

和 Day 6 是什么关系?

原理一模一样:还是那个"历史列表 + 全量发送"的套路。区别只是------

  • Day 6(原生 SDK):历史是字典列表 [{"role": "user", ...}, ...]
  • 今天(LangChain):历史是对象列表 [HumanMessage(...), AIMessage(...), ...]

框架没变魔术,只是给了你更体面的写法。

完整代码

python 复制代码
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

load_dotenv()

llm = ChatOpenAI(
    model=os.getenv("YUMC_MODEL_NAME"),
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),
)

# 历史列表:用 SystemMessage 开场定人设
history = [SystemMessage(content="你是一个友好的AI助手,请记住用户告诉你的所有事情。")]


def chat(user_input):
    # 1. 把用户的新问题加到历史中
    history.append(HumanMessage(content=user_input))
    # 2. 把整个历史发给大模型
    response = llm.invoke(history)
    # 3. 把大模型的回复也加到历史中
    history.append(AIMessage(content=response.content))
    return response.content


print("-----多轮对话测试-----")
print("你:", "我叫小明,我最喜欢吃火锅。")
print("AI:", chat("我叫小明,我最喜欢吃火锅。"))

print("你:", "你还记得我叫什么名字嘛?我最爱吃什么?")
print("AI:", chat("你还记得我叫什么名字嘛?我最爱吃什么?"))

三种消息对象对照表

LangChain 对象 等价的原生字典 谁在说话
SystemMessage {"role": "system", ...} 导演(人设/规矩)
HumanMessage {"role": "user", ...} 用户
AIMessage {"role": "assistant", ...} AI

llm.invoke() 既接受字符串(单轮快速调用),也接受消息列表(多轮记忆),今天用的是后者。

这次代码比 Day 6 好在哪?

  1. 封装成 chat() 函数:记忆逻辑收进一个函数,调用方不用关心实现细节;
  2. 类型化的消息对象 :HumanMessage(content=...) 比 {"role": "user", "content": ...} 少打字、有补全、拼错角色名会立刻报错(字典写错 role 只会静默失败);
  3. 为后续铺路:Day 14 的链式调用、Day 17 的 Agent 消息管理,都基于这套对象体系。

运行效果

复制代码
-----多轮对话测试-----
你: 我叫小明,我最喜欢吃火锅。
AI: 你好小明!火锅爱好者你好呀,你最喜欢哪种锅底呢?
你: 你还记得我叫什么名字嘛?我最爱吃什么?
AI: 当然记得,你叫小明,你最喜欢吃火锅。

今日踩坑点

  1. 漏了第 3 步 append AIMessage:Day 6 的老坑,换了框架照样栽。症状:AI 只记得你说的,不记得自己答过的。
  2. history 是全局变量:练习阶段无所谓;真实项目里每个用户/每个会话要独立一份历史(或交给 LangGraph 的 checkpointer 这类组件管理)。
  3. 把字符串直接 append 进历史 :history.append("你好") 会报错,历史里只能放消息对象。

今日小练习

  1. 必做:把 chat() 改造成 while True 交互循环(参考 Day 6 的 quit 逻辑),并结合 Day 12 的 .stream() 做流式回复。
  2. 进阶:写一个 trim_history(max_rounds=5) 函数,保留 SystemMessage + 最近 5 轮,控制历史长度。

明日预告

Day 14:让 AI 的输出从"人话"变成"机器能用的 JSON"------结构化输出,提测数据提取、API 联动的第一步。这里埋着本系列最大的一个语法坑。


附录:完整练习代码

memoryTest.py

python 复制代码
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

load_dotenv()

llm = ChatOpenAI(
    model=os.getenv("YUMC_MODEL_NAME"),
    api_key=os.getenv("YUMC_MODEL_API_KEY"),
    base_url=os.getenv("YUMC_MODEL_BASE_URL"),
)

history = [SystemMessage(content="你是一个友好的AI助手,请记住用户告诉你的所有事情。")]


def chat(user_input):
    # 1.把用户的新问题加到历史中
    history.append(HumanMessage(content=user_input))
    # 2.把整个历史发给大模型
    response = llm.invoke(history)

    # 3. 把大模型的回复也加到历史中
    history.append(AIMessage(content=response.content))

    return response.content


print("-----多轮对话测试-----")
print("你:", "我叫小明,我最喜欢吃火锅。")
print("AI:", chat("我叫小明,我最喜欢吃火锅。"))

print("你:", "你还记得我叫什么名字嘛?我最爱吃什么?")
print("AI:", chat("你还记得我叫什么名字嘛?我最爱吃什么?"))
相关推荐
半个落月1 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
2603_965148111 小时前
社区与学习资源:从入门到精通的API选品学习路径
数据库·人工智能·python·学习·数据挖掘
LiuPig刘皮哥1 小时前
2026年开源3D陪玩对比:xiaoke.ai、AIRI、Open-LLM-VTuber、Amica 有什么、没有什么
人工智能·3d·开源
半个落月1 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
西柚小萌新1 小时前
【岗位面试】--成都博维数孪 - 工业 AI 解决方案顾问
人工智能·面试·职场和发展
Luminbox紫创测控1 小时前
车载LiDAR强光测试的实验设计方法与数据分析
人工智能·数据挖掘·数据分析·车载系统·安全性测试·太阳光模拟器
CCblandy2 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
建筑工程企业管理系统3 小时前
工程进度统计管理系统自动化汇总数据,解决施工企业手工对账误差难题
大数据·人工智能·自动化
唠点键盘之外的3 小时前
27 存量系统接大模型:旁挂一个 AI 微服务,老架构一行不改
人工智能·微服务·架构