LangChain 系列 4:消息与消息类型从入门到多轮对话


前两篇已经完成了本地 Qwen3 部署,并分别使用 OpenAI Python SDK 和 LangChain 调用了这个模型。

调用 ChatOpenAI 时,既可以直接传入一个字符串,也可以传入一个消息列表。字符串适合一次独立的问题;当程序需要设置模型身份、保存历史对话或者区分用户与 AI 的发言时,就需要使用消息。

本文从最基础的 SystemMessage、HumanMessage 和 AIMessage 开始,依次介绍单轮对话、多轮对话、消息字段、其他消息类型和历史裁剪。代码只围绕消息本身展开,不提前实现 Tool、Agent 或其他复杂功能。

一次模型调用中,消息对象、消息列表和模型返回值的关系如下:

LangChain 消息如何组成一次模型调用

图中的 messages 列表由应用程序按对话顺序组装,再整体传给聊天模型。模型返回新的 AIMessage 后,是否把它保存到历史并用于下一轮,仍然由应用程序决定。

1. 为什么聊天模型需要消息

1.1 字符串只能表达当前问题

最简单的模型调用可以直接传入一个字符串:

response = llm.invoke("请用两句话介绍春天。")

这段代码能表达用户当前的问题,但没有明确告诉模型:

  1. 模型应该扮演什么角色。
  2. 回答时要遵守什么规则。
  3. 用户之前说过什么。
  4. 模型上一轮回答了什么。

如果只是一次独立问答,这些信息可能并不需要。对话开始出现规则和历史以后,一段普通字符串就不够用了。

1.2 消息列表保存一段对话

例如,用户先说:

我最喜欢的水果是苹果。

下一轮再问:

我最喜欢的水果是什么?

如果模型只看到第二句话,它无法知道答案。应用程序需要把前面的对话一起传给模型:

系统:你是一个友好的聊天助手。
用户:我最喜欢的水果是苹果。
AI:好的,我记住了,你最喜欢的水果是苹果。
用户:我最喜欢的水果是什么?

这就是消息列表的作用:按时间顺序保存模型当前需要看到的上下文。

1.3 一条消息包含什么

一条消息通常包含三类信息:

信息 作用
消息类型或角色 说明这句话来自系统、用户、AI 还是工具
content 保存消息正文,例如文字或其他内容块
元数据 保存消息 ID、模型信息、Token 用量等附加数据

初学阶段最常见的 content 是字符串。LangChain 的消息也可以承载图片、音频、文件等内容块,但是否能真正处理这些内容,还取决于所连接的模型和服务是否支持多模态输入。本文只使用文字消息。

2. 运行环境与代码目录

代码位于:

~/Documents/git/blog/source/_posts/llm_learning/langchain/p04_messages

当前目录包含八个示例:

p04_messages/
├── 01_message_objects_basic.py
├── 02_single_turn_messages.py
├── 03_multi_turn_messages.py
├── 04_json_role_messages.py
├── 05_message_name_metadata.py
├── 06_other_message_types.py
├── 07_keep_recent_messages.py
└── 08_invoke_model_with_messages.py

进入项目并激活 Python 3.12 虚拟环境:

cd ~/Documents/git/blog/source/_posts/llm_learning
source .venv/bin/activate

检查本篇直接使用的 langchain-core:

python -c 'import importlib.metadata as m; print(m.version("langchain-core"))'

本文固定使用的 langchain-core 版本为:

1.0.2

前七个脚本只创建和打印消息,不需要启动本地模型服务。第八个脚本会真正调用 Qwen3,运行前需要先启动第二篇文章中的 mlx_lm.server。

3. 三种基础消息类型

3.1 SystemMessage:系统消息

SystemMessage 用来给模型提供初始规则和上下文,通常放在消息列表最前面。

适合放在系统消息中的内容包括:

内容 例子
身份 你是一个耐心的生活小助手
回答语言 请使用中文回答
回答风格 回答要简洁,适合初学者阅读
行为边界 不确定时说明原因,不要编造
输出要求 用三句话回答,先给结论再解释

例如:

SystemMessage(content="你是一个友好的中文助手。")

系统消息不是用户问题,也不是程序中的强制校验。它会引导模型的行为,但不能像 if 判断或数据库约束一样保证模型绝对服从。

3.2 HumanMessage:用户消息

HumanMessage 表示用户输入的问题、指令或数据。

HumanMessage(content="请用两句话介绍春天。")

它可以表示不同形式的请求:

请介绍一种适合早餐的食物。
把下面这段话总结成三点。
帮我写一句生日祝福。

在 OpenAI 兼容接口中,用户角色通常写作 user;在 LangChain 消息对象中,对应的类名是 HumanMessage,message.type 为 human。

3.3 AIMessage:AI 消息

AIMessage 表示模型返回的消息。

AIMessage(content="春天是万物复苏的季节。")

调用 LangChain 聊天模型后,llm.invoke() 通常就会返回一个 AIMessage。它不只可能包含文本,还可能带有:

字段 作用
content 模型生成的正文
tool_calls 模型提出的工具调用请求
usage_metadata 输入、输出和总 Token 数量
response_metadata 模型名、结束原因等响应信息
id 消息或模型响应 ID

本文只使用 content。工具调用会在后续专门学习 Tool 时再展开。

3.4 创建三种消息对象

代码文件为 01_message_objects_basic.py:

# 这个文件演示 LangChain 中最基础的三种消息对象:系统消息、用户消息、AI 消息。

from langchain_core.messages import AIMessage, HumanMessage, SystemMessage


# SystemMessage 通常用来告诉模型:你是谁、要遵守什么规则、回答风格是什么。
system_message = SystemMessage(content="你是一个耐心的生活小助手。")

# HumanMessage 表示用户输入的问题、需求或指令。
human_message = HumanMessage(content="请用一句话介绍一种适合早餐的食物。")

# AIMessage 表示模型已经回答过的内容,常用于保存历史对话。
ai_message = AIMessage(content="燕麦粥营养丰富、做法简单,是一种适合早餐的食物。")

messages = [system_message, human_message, ai_message]

print("三种基础消息对象:")
for message in messages:
    print("-" * 40)
    print("消息类型:", type(message).__name__)
    print("消息内容:", message.content)
    print("消息 type:", message.type)

运行:

python langchain/p04_messages/01_message_objects_basic.py

真实输出:

三种基础消息对象:
----------------------------------------
消息类型: SystemMessage
消息内容: 你是一个耐心的生活小助手。
消息 type: system
----------------------------------------
消息类型: HumanMessage
消息内容: 请用一句话介绍一种适合早餐的食物。
消息 type: human
----------------------------------------
消息类型: AIMessage
消息内容: 燕麦粥营养丰富、做法简单,是一种适合早餐的食物。
消息 type: ai

这里同时打印了 Python 类名和 LangChain 的 message.type。它们与 OpenAI 兼容接口中常见的 role 对应关系如下:

OpenAI 兼容 role LangChain 类 LangChain message.type
system SystemMessage system
user HumanMessage human
assistant AIMessage ai

不要把 role 和 message.type 当成同一个字段。它们属于不同表示方式,只是表达的角色含义相互对应。

4. 单轮对话

单轮对话表示用户提出一次问题,模型返回一次回答。最常见的输入结构是:

SystemMessage + HumanMessage

代码文件为 02_single_turn_messages.py:

# 这个文件演示单轮对话:一次用户提问,加上必要的系统规则。

from langchain_core.messages import HumanMessage, SystemMessage


# 单轮对话通常包含一条 system 消息和一条 human 消息。
messages = [
    SystemMessage(content="你是一个友好的中文助手。"),
    HumanMessage(content="请用两句话介绍春天。"),
]

print("单轮对话消息列表:")
for index, message in enumerate(messages, start=1):
    print(f"{index}. {type(message).__name__}: {message.content}")

print("\n说明:")
print("真正调用聊天模型时,会把这个 messages 列表整体传给模型。")

运行:

python langchain/p04_messages/02_single_turn_messages.py

真实输出:

单轮对话消息列表:
1. SystemMessage: 你是一个友好的中文助手。
2. HumanMessage: 请用两句话介绍春天。

说明:
真正调用聊天模型时,会把这个 messages 列表整体传给模型。

如果把这个列表交给第二篇创建的 ChatOpenAI,写法就是:

response = llm.invoke(messages)

模型返回的 response 是一个 AIMessage。

5. 多轮对话

5.1 模型不会自动记住上一轮

大模型每次调用都只处理当前收到的输入。网页聊天工具看起来能够“记住”前面的内容,是因为应用程序保存了历史消息,并在下一次调用时重新发送给模型。

一个基本的多轮消息列表通常是:

SystemMessage
HumanMessage
AIMessage
HumanMessage
AIMessage
...

消息顺序不能打乱,因为模型会按照这个顺序理解对话过程。

下面这张图展示了两次请求之间真正发生的事情:第一轮消息由应用保存,第二轮再与当前问题一起发送给模型。

LangChain 多轮对话中的历史消息传递

第二次请求不是只发送“我最喜欢的水果是什么?”,而是重新发送系统消息、第一轮用户消息、第一轮 AI 回答和当前问题。模型能够回答“苹果”,依赖的是这次请求中包含的完整上下文。

5.2 构造多轮消息列表

代码文件为 03_multi_turn_messages.py:

# 这个文件演示多轮对话:把前面用户问过的话和 AI 回答过的话继续放回 messages。

from langchain_core.messages import AIMessage, HumanMessage, SystemMessage


# 多轮对话不是模型自动记住历史,而是我们把历史消息再次传给模型。
messages = [
    SystemMessage(content="你是一个友好的聊天助手。"),
    HumanMessage(content="我最喜欢的水果是苹果。"),
    AIMessage(content="好的,我记住了,你最喜欢的水果是苹果。"),
    HumanMessage(content="我最喜欢的水果是什么?"),
]

print("多轮对话消息列表:")
for index, message in enumerate(messages, start=1):
    print(f"{index}. {message.type}: {message.content}")

print("\n说明:")
print("模型需要看到前面的消息,才知道用户最喜欢的水果是苹果。")

运行:

python langchain/p04_messages/03_multi_turn_messages.py

真实输出:

多轮对话消息列表:
1. system: 你是一个友好的聊天助手。
2. human: 我最喜欢的水果是苹果。
3. ai: 好的,我记住了,你最喜欢的水果是苹果。
4. human: 我最喜欢的水果是什么?

说明:
模型需要看到前面的消息,才知道用户最喜欢的水果是苹果。

前三条消息表示历史,最后一条 HumanMessage 表示当前问题。

5.3 把多轮消息真正传给本地模型

前面的示例只打印消息。下面使用 08_invoke_model_with_messages.py 把同样的多轮消息真正传给本地 Qwen3:

# 这个文件演示把多轮 LangChain 消息列表真正传给本地 Qwen3 模型。
# 运行前需要先按照第二篇文章启动 mlx_lm.server。

import httpx
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI


# 创建 LangChain 聊天模型,并连接本地 OpenAI 兼容接口。
llm = ChatOpenAI(
    base_url="http://127.0.0.1:18080/v1",
    api_key="not-needed",
    model="default_model",
    temperature=0,
    max_tokens=32,
    http_client=httpx.Client(trust_env=False),
)

# 前三条消息表示上一轮对话,最后一条消息是当前问题。
messages = [
    SystemMessage(content="你是一个友好的中文助手。"),
    HumanMessage(content="我最喜欢的水果是苹果。"),
    AIMessage(content="好的,我记住了,你最喜欢的水果是苹果。"),
    HumanMessage(content="我最喜欢的水果是什么?只回答水果名称。"),
]

# 把完整消息列表交给模型,返回值是 AIMessage。
response = llm.invoke(messages)

print("返回消息类型:", type(response).__name__)
print("模型回答:", response.content)

运行前先在另一个终端启动模型服务:

"$VIRTUAL_ENV/bin/python" -m mlx_lm server \
  --model model \
  --host 127.0.0.1 \
  --port 18080 \
  --chat-template-args '{"enable_thinking": false}'

然后运行:

python langchain/p04_messages/08_invoke_model_with_messages.py

本次真实输出:

PyTorch was not found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
返回消息类型: AIMessage
模型回答: 苹果

模型回答“苹果”,说明它确实读取了前面的历史消息。返回类型是 AIMessage,说明 LangChain 又把本次模型回答包装成了一条新的 AI 消息。

真实程序通常会把这条 response 追加到消息列表:

messages.append(response)

下一轮再加入新的 HumanMessage,就形成了持续增长的多轮对话。

6. 字典消息与 LangChain 消息对象

OpenAI 兼容接口通常使用字典表示消息:

{"role": "user", "content": "你好,很高兴认识你。"}

LangChain 可以使用对应的消息对象:

HumanMessage(content="你好,很高兴认识你。")

代码文件为 04_json_role_messages.py:

# 这个文件演示字典消息和 LangChain 消息对象之间的对应关系。

from langchain_core.messages import AIMessage, HumanMessage, SystemMessage


# OpenAI 兼容接口常见的是这种 JSON / dict 风格。
json_messages = [
    {"role": "system", "content": "你是一个友好的 AI 助手。"},
    {"role": "user", "content": "你好,很高兴认识你。"},
    {"role": "assistant", "content": "你好,我也很高兴认识你。"},
]

# LangChain 也可以使用更明确的消息对象。
object_messages = [
    SystemMessage(content="你是一个友好的 AI 助手。"),
    HumanMessage(content="你好,很高兴认识你。"),
    AIMessage(content="你好,我也很高兴认识你。"),
]

print("字典消息:")
for message in json_messages:
    print(message)

print("\nLangChain 消息对象:")
for message in object_messages:
    print(type(message).__name__, message.content)

print("\n对应关系:")
print("system -> SystemMessage")
print("user / human -> HumanMessage")
print("assistant / ai -> AIMessage")

运行:

python langchain/p04_messages/04_json_role_messages.py

真实输出:

字典消息:
{'role': 'system', 'content': '你是一个友好的 AI 助手。'}
{'role': 'user', 'content': '你好,很高兴认识你。'}
{'role': 'assistant', 'content': '你好,我也很高兴认识你。'}

LangChain 消息对象:
SystemMessage 你是一个友好的 AI 助手。
HumanMessage 你好,很高兴认识你。
AIMessage 你好,我也很高兴认识你。

对应关系:
system -> SystemMessage
user / human -> HumanMessage
assistant / ai -> AIMessage

两种写法表达的是同一段对话。字典格式接近 HTTP 接口原始数据,消息对象则更适合继续使用 LangChain 的模板、模型和消息处理能力。

7. 消息中的可选字段

除了 content,消息还可以包含可选字段。

字段 作用
name 标识同一种消息类型下的不同发言人
id 保存消息唯一标识,便于日志和追踪
additional_kwargs 保存模型服务商返回的额外字段
response_metadata 保存模型名、结束原因等响应信息
usage_metadata 保存输入、输出和总 Token 数量

代码文件为 05_message_name_metadata.py:

# 这个文件演示消息里的可选字段:name、id、additional_kwargs、response_metadata。

from langchain_core.messages import AIMessage, HumanMessage


# name 可以标识同一种角色下的不同说话人。
human_message = HumanMessage(
    content="我叫小明,很高兴认识你。",
    name="小明",
    id="user-message-001",
)

# additional_kwargs 常用来保存模型服务商返回的额外字段。
# response_metadata 常用来保存 token、模型名、结束原因等响应元数据。
ai_message = AIMessage(
    content="你好,小明,我也很高兴认识你。",
    id="ai-message-001",
    additional_kwargs={"example_extra_field": "这里演示额外字段"},
    response_metadata={"model_name": "local-qwen3-demo", "finish_reason": "stop"},
)

print("带 name 的用户消息:")
print(human_message)

print("\n带元数据的 AI 消息:")
print(ai_message)

print("\n单独读取字段:")
print("human_message.name =", human_message.name)
print("ai_message.response_metadata =", ai_message.response_metadata)

运行:

python langchain/p04_messages/05_message_name_metadata.py

真实输出:

带 name 的用户消息:
content='我叫小明,很高兴认识你。' additional_kwargs={} response_metadata={} name='小明' id='user-message-001'

带元数据的 AI 消息:
content='你好,小明,我也很高兴认识你。' additional_kwargs={'example_extra_field': '这里演示额外字段'} response_metadata={'model_name': 'local-qwen3-demo', 'finish_reason': 'stop'} id='ai-message-001'

单独读取字段:
human_message.name = 小明
ai_message.response_metadata = {'model_name': 'local-qwen3-demo', 'finish_reason': 'stop'}

这些字段不是每条消息都必须提供。name 是否会被模型服务使用也取决于服务商;response_metadata 和 usage_metadata 通常由模型响应填充。初学阶段先掌握消息类型和 content,再根据实际需要读取元数据。

8. 其他消息类型

SystemMessage、HumanMessage 和 AIMessage 足以完成普通文本对话。LangChain 还提供了其他消息类型,用于工具结果、自定义角色、流式输出和消息管理。

类型 作用 本文范围
ToolMessage 把一次工具执行结果返回给模型 只理解结构
FunctionMessage 表示函数执行结果的消息格式 了解兼容用途
ChatMessage 使用任意自定义 role 简单展示
AIMessageChunk 表示流式输出中的一段 AI 内容 演示合并
HumanMessageChunk 用户消息分块类型 了解名称
SystemMessageChunk 系统消息分块类型 了解名称
ToolMessageChunk 工具消息分块类型 了解名称
RemoveMessage 表示从消息状态中删除指定消息 只理解概念

代码文件为 06_other_message_types.py:

# 这个文件概念性展示其他消息类型:ToolMessage、FunctionMessage、ChatMessage、消息 chunk。

from langchain_core.messages import (
    AIMessageChunk,
    ChatMessage,
    FunctionMessage,
    ToolMessage,
)


# ToolMessage 表示工具执行后的结果,通常要和 AIMessage 中的 tool_call_id 对上。
tool_message = ToolMessage(
    content="北京今天晴,气温 25 摄氏度。",
    tool_call_id="call_weather_001",
)

# FunctionMessage 是早期函数调用格式中常见的消息类型。
function_message = FunctionMessage(
    name="get_weather",
    content="北京今天晴,气温 25 摄氏度。",
)

# ChatMessage 可以自定义 role,普通初学阶段更常用 System/Human/AIMessage。
chat_message = ChatMessage(
    role="teacher",
    content="今天我们来聊聊周末计划。",
)

# Chunk 表示流式输出中的一小段内容,多个 chunk 可以拼成完整 AIMessage。
chunk1 = AIMessageChunk(content="你好,")
chunk2 = AIMessageChunk(content="很高兴认识你。")
merged_chunk = chunk1 + chunk2

print("ToolMessage:")
print(tool_message)

print("\nFunctionMessage:")
print(function_message)

print("\nChatMessage:")
print(chat_message)

print("\nAIMessageChunk 合并结果:")
print(merged_chunk)

运行:

python langchain/p04_messages/06_other_message_types.py

真实输出:

ToolMessage:
content='北京今天晴,气温 25 摄氏度。' tool_call_id='call_weather_001'

FunctionMessage:
content='北京今天晴,气温 25 摄氏度。' additional_kwargs={} response_metadata={} name='get_weather'

ChatMessage:
content='今天我们来聊聊周末计划。' additional_kwargs={} response_metadata={} role='teacher'

AIMessageChunk 合并结果:
content='你好,很高兴认识你。' additional_kwargs={} response_metadata={}

ToolMessage.tool_call_id 必须对应模型提出的那次工具调用。本文只是手动创建对象,不实现工具执行流程。AIMessageChunk 则常见于 llm.stream(),多个 chunk 可以使用 + 合并;合并结果仍是 AIMessageChunk,只是其中的 content 已经拼接起来。

9. 历史消息太长怎么办

多轮对话会不断追加 HumanMessage 和 AIMessage。历史越长,需要发送给模型的 Token 越多,并且可能超过模型上下文窗口。

最简单的教学方案是:保留系统消息,再保留最近 N 轮用户与 AI 对话。

代码文件为 07_keep_recent_messages.py:

# 这个文件演示如何手动保留最近 N 轮对话,避免历史消息无限增长。


def keep_recent_messages(messages, max_pairs=2):
    """保留 system 消息和最近 N 轮 user/assistant 对话。"""
    # system 消息通常是全局规则,应该保留下来。
    system_messages = [m for m in messages if m["role"] == "system"]

    # 对话消息指用户和助手之间来回产生的消息。
    conversation_messages = [m for m in messages if m["role"] != "system"]

    # 一轮对话通常包含 user + assistant 两条消息,所以 N 轮就是 N * 2 条。
    recent_messages = conversation_messages[-(max_pairs * 2) :]

    return system_messages + recent_messages


messages = [
    {"role": "system", "content": "你是一个友好的聊天助手。"},
    {"role": "user", "content": "我叫小明。"},
    {"role": "assistant", "content": "你好,小明。"},
    {"role": "user", "content": "我喜欢吃苹果。"},
    {"role": "assistant", "content": "好的,我记住了你喜欢吃苹果。"},
    {"role": "user", "content": "我周末想去公园。"},
    {"role": "assistant", "content": "祝你周末在公园玩得开心。"},
]

recent_messages = keep_recent_messages(messages, max_pairs=2)

print("原始消息数量:", len(messages))
print("裁剪后消息数量:", len(recent_messages))
print("\n裁剪后的消息:")
for message in recent_messages:
    print(message)

运行:

python langchain/p04_messages/07_keep_recent_messages.py

真实输出:

原始消息数量: 7
裁剪后消息数量: 5

裁剪后的消息:
{'role': 'system', 'content': '你是一个友好的聊天助手。'}
{'role': 'user', 'content': '我喜欢吃苹果。'}
{'role': 'assistant', 'content': '好的,我记住了你喜欢吃苹果。'}
{'role': 'user', 'content': '我周末想去公园。'}
{'role': 'assistant', 'content': '祝你周末在公园玩得开心。'}

最早一轮“我叫小明”被删除,因此模型之后也不会再知道这个名字。裁剪能够控制长度,但会丢失信息。

这个函数只是帮助初学者理解原理,它假设每一轮严格由一条 user 和一条 assistant 组成。真实对话如果包含工具消息、连续用户消息或尚未回答的问题,就不能简单地每两条切一次。

10. 初学者常见误区

10.1 把多轮对话理解成模型自己的记忆

模型不是自动记住历史,而是应用程序把历史消息再次发送给模型。没有把旧消息放入当前请求,模型就看不到旧内容。

10.2 把 SystemMessage 当成绝对命令

系统消息用于引导模型,不是安全边界。真正不能违反的权限、输入校验和业务规则仍然要由普通程序代码处理。

10.3 混淆 role、type 和 Python 类名

user、human 和 HumanMessage 都表示用户一方,但分别属于接口 role、LangChain type 和 Python 类名。编写代码时要看当前 API 需要哪种格式。

10.4 只保存用户消息,不保存 AIMessage

多轮历史必须包含双方已经说过的内容。如果只保存用户问题,模型无法知道自己上一轮回答了什么,也无法正确理解“刚才那个结果”之类的指代。

10.5 无限保存全部历史

历史消息会占用上下文窗口。消息越多,不代表回答一定越好;过多无关内容还可能干扰当前任务。需要根据应用需求保留、删除或整理历史。

10.6 认为 content 永远是字符串

本文为了教学只使用字符串。LangChain 消息还可以使用内容块表示图片、音频和文件,但客户端、模型服务和模型本身必须同时支持相应格式,不能只修改 content 就认为多模态调用一定可用。

11. 小结

消息是 LangChain 向聊天模型提供上下文的基本单位。系统消息负责提供初始规则,用户消息表示当前输入,AI 消息保存模型返回内容;把这些消息按时间顺序组成列表,就能表达单轮或多轮对话。

本篇还验证了一个关键事实:将历史 HumanMessage 和 AIMessage 一起传给本地 Qwen3 后,模型能够根据历史回答“苹果”,并返回新的 AIMessage。

下一篇将继续学习提示词模板,解决消息中的固定内容、变量和历史占位符应该怎样组织和复用。

12. 最终知识整理

知识点 需要掌握的结论
SystemMessage 给模型提供身份、规则和回答要求,但不是强制安全边界
HumanMessage 表示用户输入,对应 OpenAI 兼容接口中的 user
AIMessage 表示模型输出,可包含文本、工具调用和响应元数据
单轮对话 常见结构是 SystemMessage + HumanMessage
多轮对话 需要按顺序重新发送必要的历史 Human/AI 消息
role 与 type user/assistant 与 human/ai 含义对应,但字段体系不同
字典与消息对象 都能表达对话;消息对象更方便继续使用 LangChain 组件
ToolMessage 保存工具执行结果,并通过 tool_call_id 对应工具调用
Message Chunk 表示流式输出片段,可以合并成完整消息
消息元数据 可保存 ID、Token 用量、模型信息和结束原因
历史裁剪 可以控制上下文长度,但被删除的信息模型将无法再看到
本地模型实测 多轮消息列表成功传给 Qwen3,返回 AIMessage(content=”苹果”)

文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录