【零基础入门 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("你还记得我叫什么名字嘛?我最爱吃什么?"))
相关推荐
奈落241 小时前
AI辅助的另一面:从2026年国际AI安全报告的“故障”清单到国内专家的可靠性短板,自主行动的Agent为什么更难及时干预
人工智能·安全·agent·本地部署·ai 办公
火山引擎开发者社区3 小时前
eMudhra 证书失陷:容器用户最容易忽略的镜像信任链漏洞
人工智能
LabVIEW开发4 小时前
LabVIEW 机载 DIAL:每秒万次甲烷测量
人工智能·labview·labview知识·labview功能·labview程序
实名上网宋凯宣5 小时前
Django
后端·python·django
飞猫的边缘AI5 小时前
英特尔量子生意
人工智能·量子计算·边缘ai
深蓝AI5 小时前
桌面 Agent 缺的不是视觉:Vercel 开源 agent-desktop,用无障碍树 ref 替代截图坐标
人工智能·程序员
镜子AI5 小时前
镜子AI 技术复盘:三条自动化链路上的“停止条件“设计
运维·人工智能·自动化
向哆哆6 小时前
羊行为目标检测数据集:4类别、2,000张图像 | 目标检测
人工智能·yolo·目标检测·目标跟踪
如若1236 小时前
【论文复现】CoFailMed:从零复现医学图像分割的共享失败审计,含完整代码流程与科研绘图
人工智能·python
赛博守夜人7 小时前
AI安全攻防与治理之十六:对抗样本、恶意文件与多模态攻击,AI 内容安全检测的真实盲区
人工智能·安全