☰
第四单元 —— 第十四课:控制发送给模型的聊天历史长度
2026/10/15 8:02:00 网站建设 项目流程

上一课每次都发送全部聊天记录。聊得越久,请求就越大。这次我们只发送最近几轮,同时继续读取数据库里的阅读偏好。

1. 复制上一课文件

将上一课文件另存为:

C:\Users\Administrator\langchain-study\unit4_lesson14_trim_history.py

保留原有代码,只改下面三处。

2. 添加导入

在文件顶部添加:

from langchain_core.messages.utils import trim_messages

3. 修改chat函数末尾

找到原来调用模型的部分:

response = model.invoke([system_message, *state["messages"]]) return {"messages": [response]}

替换为以下代码,注意保持在chat函数内部:

# 从完整历史中,选出最近几条消息 recent_messages = trim_messages( state["messages"], max_tokens=5, token_counter=len, strategy="last", start_on="human", allow_partial=False, ) print("完整历史消息数:", len(state["messages"])) print("本次发送的历史消息数:", len(recent_messages)) # 阅读偏好仍然通过 system_message 每次提供给模型 response = model.invoke([ system_message, *recent_messages, ]) return {"messages": [response]}

这里几个参数的含义:

参数含义
token_counter=len用列表长度计数,也就是按消息条数计数
max_tokens=5配合上面的len,表示最多保留5 条消息,不是 5 个 token
strategy="last"优先保留最新的消息
start_on="human"保留的对话从用户消息开始,避免从半截回答开始
allow_partial=False保留完整消息,不截断消息正文

一条用户问题和一条模型回答,共算2 条消息。官方参数说明

4. 测试四轮对话

把原来的questions列表换成:

questions = [ "请根据我的阅读偏好,推荐两本书。", "请介绍你刚才推荐的第一本书。", "请为这本书安排一个三天阅读计划。", "请把刚才的阅读计划压缩成三个要点。", ]

保留原来的循环,因此每一轮仍然会输出问题和回答。

在已激活.venv的项目目录运行:

python unit4_lesson14_trim_history.py

预期会看到这些计数——不包含额外添加的系统消息:

调用模型前完整历史消息数本次发送的历史消息数
第 1 轮11
第 2 轮33
第 3 轮55
第 4 轮75

第四轮调用模型前,有前三轮的 6 条消息,加上当前问题,共 7 条。裁剪后,第一轮的问题和回答不再发送。

这节最重要的区别

少发给模型,不等于删除历史。

我们没有修改state["messages"],只从中选出一个较短的列表。因此:

  • 完整聊天记录仍由本课的内存检查点保留;程序退出后不会保留。
  • 模型只看到选出的最近消息,以及额外添加的系统消息。
  • 阅读偏好仍从 SQLite 数据库读取,每轮放进系统消息,不受这次历史裁剪影响。

先运行到第四轮,确认看到完整历史 7 条、本次发送 5 条,就说明这课的历史裁剪生效了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询