LangChain:消息(Message)类型和特性详解

LangChain的消息系统是结构化对话管理的核心组件,通过明确区分角色和上下文,使大模型能精准处理多轮对话与工具调用。

其核心是四种基础消息类型(SystemMessage、HumanMessage、AIMessage、ToolMessage),官方文档明确要求必须使用类型化消息对象而非原始字典,以确保跨模型兼容性和功能完整性。

核心概念

消息是 LangChain 中模型的基本上下文单元,代表模型的输入输出,携带内容和元数据,用于表示与 LLM 交互时的对话状态。

消息组成

每条消息是一个对象,包含三个核心要素:

  • 角色(Role):标识消息类型(如 systemuserassistant
  • 内容(Content):消息的实际内容,可以是文本、图像、音频、文档等
  • 元数据(Metadata):可选字段,如响应信息、消息 ID、token 使用量等

LangChain 提供跨所有模型提供商的标准消息类型,确保无论调用哪个模型,行为都保持一致。

基本用法

创建消息对象并将其传递给模型:

1
2
3
4
5
6
7
8
9
10
from langchain.chat_models import init_chat_model  # 导入初始化聊天模型的函数
from langchain.messages import HumanMessage, AIMessage, SystemMessage # 导入三种基本消息类型

model = init_chat_model("gpt-5-nano") # 初始化模型,指定使用 gpt-5-nano

system_msg = SystemMessage("You are a helpful assistant.") # 系统消息:设定助手角色
human_msg = HumanMessage("Hello, how are you?") # 用户消息:用户提问

messages = [system_msg, human_msg] # 构建消息列表(对话历史)
response = model.invoke(messages) # 调用模型,返回 AIMessage 对象

文本提示 vs 消息提示

类型 适用场景
文本提示(字符串) 独立、单次生成任务,无需维护对话历史
消息提示(消息列表) 多轮对话、多模态内容(图像/音频/文件)、系统指令注入

python

1
2
3
4
5
6
7
8
9
10
11
12
# 字符串示例
response = model.invoke("Write a haiku about spring") # 简单调用

# 多轮对话示例
from langchain.messages import SystemMessage, HumanMessage, AIMessage

messages = [
SystemMessage("You are a poetry expert"), # 系统消息:设定专家角色
HumanMessage("Write a haiku about spring"), # 用户请求
AIMessage("Cherry blossoms bloom...") # 可选的模拟 AI 回复(用于构建历史)
]
response = model.invoke(messages) # 带对话历史调用

提示:AIMessage 中可存储模型的回复内容。通过维护包含多条消息的列表,你可以实现多轮对话的上下文管理

字典格式

也可以直接使用 OpenAI 兼容的字典格式,为了多模型提供商的兼容,不建议使用。

1
2
3
4
5
6
messages = [
{"role": "system", "content": "You are a poetry expert"},
{"role": "user", "content": "Write a haiku about spring"},
{"role": "assistant", "content": "Cherry blossoms bloom..."}
]
response = model.invoke(messages)

核心消息类型

所有消息类都继承自 BaseMessage,LangChain 提供了以下主要类型:

消息类 字典Role 用途 前提条件
SystemMessage system 设定 AI 的行为规范、背景、角色定位、知识边界 通常位于对话开头,优先级最高
HumanMessage user 代表用户(人类)的输入或提问
AIMessage assistant 代表模型的回复,可能包含工具调用
ToolMessage tool 代表工具执行后的结果,包含 tool_call_id 必须在 AIMessage 包含工具调用之后出现
ChatMessage 自定义 当标准角色不够用时,手动指定 role 参数

LangChain的消息系统通过结构化角色分工解决上下文混乱问题,必须严格使用类型化消息对象并维护完整对话链。

对比传统方式的好处:使用这些语义化的消息类,可以避免手动写 {"role": ...} 字典,更重要的是可以直接用 isinstance(last_message, AIMessage) 进行类型判断,代码可读性和可维护性显著提升。

SystemMessage

SystemMessage:系统消息

  • 作用:定义AI的角色、行为规则及知识边界,优先级最高,通常作为消息列表的首条消息。

  • 建议:系统消息通常放在对话列表的开头,以持续引导模型行为。

  • 关键特性:

    • 决定模型的“身份设定”,直接影响输出风格和内容范围。
    • 若模型不支持系统消息(如部分旧版API),LangChain会自动将其合并到HumanMessage中。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    from langchain_core.messages import SystemMessage

    system_msg = SystemMessage(
    content="你是一名金融分析师,仅回答2023年后的A股市场数据问题,"
    "超出范围时回复'该问题超出我的知识边界'"
    )

HumanMessage

HumanMessage:用户消息

  • 作用:代表用户的输入和交互,支持文本、图像、音频、文件等多元内容,是对话的核心触发点

  • 关键特性:

    • 支持纯文本或多模态输入(如文本+图片),需模型本身支持多模态能力。
    • 可附加元数据(如用户ID、会话ID)用于上下文追踪。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    from langchain_core.messages import HumanMessage

    # 纯文本输入
    human_msg = HumanMessage(content="2024年上证指数最高点是多少?")

    # 多模态输入(需模型支持,如GPT-4o)
    human_msg_multimodal = HumanMessage(
    content=[
    {"type": "text", "text": "描述这张图片的金融含义"},
    {"type": "image_url", "image_url": "https://example.com/chart.png"}
    ]
    )

    # 带元数据的消息
    human_msg = HumanMessage(
    content="Hello!", # 消息内容
    name="alice", # 可选:标识不同用户
    id="msg_123" # 可选:唯一标识符,便于追踪
    )

    消息内容不再局限于纯文本。LangChain 支持标准化的多模态内容块,可以自然交错排列文本、图像、音频等内容。

    name 字段的行为因模型提供商而异:有些会用于识别用户,有些则忽略。建议查阅对应提供商文档。

AIMessage

AIMessag:AI回复消息

  • 作用:代表模型的输出,可包含多种内容、工具调用和提供商特有的元数据,包含工具调用请求或最终答案

    可以手动创建 AIMessage 对象并插入对话历史,用于预设示例或多轮对话的上下文补充。

  • 关键特性:

    • content字段存储文本回复,tool_calls字段存储工具调用指令(如需外部工具)。
    • 支持流式输出(AIMessageChunk),逐块返回响应内容。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from langchain_core.messages import AIMessage

    # 普通文本回复
    ai_msg = AIMessage(content="2024年上证指数最高点为3,400点(截至2024年12月)")

    # 工具调用请求(模拟模型需查询实时数据)
    ai_msg_with_tool = AIMessage(
    content="",
    tool_calls=[{
    "name": "get_stock_data",
    "args": {"market": "A股", "metric": "index_high"},
    "id": "call_abc123" # 必须唯一标识调用
    }]
    )

    response = model.invoke("Explain AI") # 直接获取模型输出
    print(type(response)) # <class 'langchain.messages.AIMessage'>

    # 内部属性举例
    print(response.content) # 文本内容
    print(response.tool_calls) # 工具调用(若有)
    print(response.usage_metadata) # 令牌使用统计

ToolMessage

ToolMessage:工具结果消息

  • 作用:传当模型发起工具调用后,工具的执行结果通过 ToolMessage 传回模型,**必须关联tool_call_id**。

  • 关键特性:

    • tool_call_id必须与AIMessage中的调用ID完全匹配,否则模型无法关联结果。
    • content为工具返回的字符串化结果,artifact可存储未发送给模型的原始数据。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    from langchain_core.messages import ToolMessage

    tool_msg = ToolMessage(
    content="2024年上证指数最高点:3,421.87点(2024-08-15)",
    tool_call_id="call_abc123", # 必须与AIMessage中的ID一致
    name="get_stock_data"
    )

    from langchain.messages import AIMessage, ToolMessage, HumanMessage

    # 1. 模型决定调用工具
    ai_msg = AIMessage(
    content=[],
    tool_calls=[{
    "name": "get_weather",
    "args": {"location": "San Francisco"},
    "id": "call_123" # 唯一调用 ID
    }]
    )

    # 2. 执行工具并创建结果消息
    weather_result = "Sunny, 72°F"
    tool_msg = ToolMessage(
    content=weather_result,
    tool_call_id="call_123" # 与调用 ID 匹配
    )

    # 3. 完整对话流
    messages = [
    HumanMessage("What's the weather in San Francisco?"),
    ai_msg, # 模型的工具调用请求
    tool_msg # 工具执行结果
    ]
    response = model.invoke(messages) # 模型处理结果并最终回答

    tool_call_id 必须与 AIMessage 中对应工具调用的 ID 一致,否则模型无法正确关联结果。

Artifact 字段

ToolMessage 还提供 artifact 字段,用于存储不会发送给模型的附加数据(如原始结果、调试信息、文档元数据等):

1
2
3
4
5
6
tool_message = ToolMessage(
content="It was the best of times...",
tool_call_id="call_123",
name="search_books",
artifact={"document_id": "doc_123", "page": 0} # 仅供下游使用
)

Token 用量统计

AIMessageusage_metadata` 字段保存令牌使用情况:

1
2
3
4
5
6
7
8
9
10
response = model.invoke("Hello!")
print(response.usage_metadata)
# 示例输出:
# {
# 'input_tokens': 8,
# 'output_tokens': 304,
# 'total_tokens': 312,
# 'input_token_details': {'audio': 0, 'cache_read': 0},
# 'output_token_details': {'audio': 0, 'reasoning': 256}
# }

消息内容

每条消息的 核心负载 通过 content 属性传递。可以使用以下任意一种格式:

纯字符串

1
response = model.invoke([HumanMessage("What is machine learning?")])

提供商原生格式

提供商原生格式,如 OpenAI

1
2
3
4
human_msg = HumanMessage(content=[
{"type": "text", "text": "What's in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
])

LangChain 标准内容块

LangChain 标准内容块(推荐)

1
2
3
4
5
human_msg = HumanMessage(content_blocks=[
{"type": "text", "text": "What's in this image?"},
{"type": "image", "url": "https://example.com/image.jpg"}
])
# 使用 content_blocks 时,内部会自动填充 content 属性,并提供类型安全接口。

content_blocks 是 LangChain v1 引入的新属性,它不会替代 content,而是提供额外的、跨提供商的标准化访问方式。

标准内容块类型

LangChain 提供了一套标准的内容块表示,可在不同提供商间通用。消息对象实现 content_blocks 属性,惰性解析 content 属性为类型安全的统一表示。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 来自 Anthropic 的消息包含 thinking 块
message = AIMessage(
content=[
{"type": "thinking", "thinking": "...", "signature": "WaUjzkyp..."},
{"type": "text", "text": "Final answer..."}
],
response_metadata={"model_provider": "anthropic"}
)

print(message.content_blocks)
# 输出示例:
# [{'type': 'reasoning', 'reasoning': '...', 'extras': {'signature': '...'}},
# {'type': 'text', 'text': 'Final answer...'}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 来自 OpenAI 的 reasoning 块
message = AIMessage(
content=[
{"type": "reasoning", "id": "rs_abc123", "summary": [
{"type": "summary_text", "text": "summary 1"},
{"type": "summary_text", "text": "summary 2"}
]}
],
response_metadata={"model_provider": "openai"}
)

print(message.content_blocks)
# 输出示例:
# [{'type': 'reasoning', 'id': 'rs_abc123', 'reasoning': 'summary 1'},
# {'type': 'reasoning', 'id': 'rs_abc123', 'reasoning': 'summary 2'}]

各内容块参考

类型 描述 必须字段 可选字段
TextContentBlock 标准文本 type: “text”, text: 文本内容 annotations: 注解列表, extras
ReasoningContentBlock 模型的推理步骤 type: “reasoning”, reasoning: 推理内容 extras
ImageContentBlock 图像数据 type: “image” url, base64, mime_type, file_id
AudioContentBlock 音频数据 type: “audio” url, base64, mime_type
VideoContentBlock 视频数据 type: “video” url, base64, mime_type
FileContentBlock 通用文件(如 PDF) type: “file” url, base64, mime_type
PlainTextContentBlock 纯文本文档 type: “text-plain”, text: 文本内容 mime_type
ToolCall 工具调用 type: “tool_call”, name, args, id -
ServerToolCall 服务端工具调用 type: “server_tool_call”, id, name, args -

提示:若遇到提供商独有的实验性字段,可使用 NonStandardContentBlocktype: “non_standard”)作为转义出口,或为每种专用块实现子类。

消息组合与多轮对话

多轮对话的正确结构

  • 必须按顺序组织消息列表,保留完整对话历史:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage

    messages = [
    SystemMessage(content="你是一名金融分析师..."),
    HumanMessage(content="2024年上证指数最高点是多少?"),
    AIMessage(tool_calls=[{"name": "get_stock_data", "id": "call_abc123"}]),
    ToolMessage(content="3,421.87点", tool_call_id="call_abc123"),
    HumanMessage(content="这个数据来源可靠吗?") # 新问题需带上历史
    ]

错误 vs 正确实践

  • 错误做法:每次仅传当前问题,丢失上下文:

    1
    2
    # ❌ 错误:无历史记录,模型无法关联问题
    messages = [HumanMessage(content="这个数据来源可靠吗?")]
  • 正确做法:始终携带必要历史,确保逻辑连贯:

    1
    2
    3
    4
    5
    6
    7
    8
    # ✅ 正确:包含系统设定、历史问题与工具结果
    messages = [
    SystemMessage(content="..."),
    HumanMessage(content="2024年上证指数最高点..."),
    AIMessage(tool_calls=[...]),
    ToolMessage(...),
    HumanMessage(content="这个数据来源可靠吗?") # 当前问题
    ]

消息的高级特性

元数据(Metadata)

每条消息都可以携带丰富的元数据:

  • response_metadata:来自模型提供商的响应信息,如 token 使用量、finish_reason 等
  • id:消息的唯一标识符
  • additional_kwargs:模型供应商特有的额外字段
1
2
3
4
# 访问响应元数据(以 Python 为例)
response = chat_model.invoke(messages)
print(response.response_metadata) # {'token_usage': {...}, 'model': '...'}
print(response.id) # 消息唯一标识

流式消息块(Message Chunks)

LangChain 为每种消息类型提供了流式分块版本,用于实时流式输出

消息类型 分块类型 用途
AIMessage AIMessageChunk 流式接收 AI 回复片段
HumanMessage HumanMessageChunk 流式处理用户输入
SystemMessage SystemMessageChunk 流式系统提示
ToolMessage ToolMessageChunk 流式工具结果

当使用流式输出时,模型会逐块返回数据。LangChain 提供了对应的 Chunk 类(如 AIMessageChunk),且支持用 + 运算符拼接多个块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Python 示例:流式输出与消息块拼接
from langchain_core.messages import AIMessageChunk

chunk1 = AIMessageChunk(content="Hello ")
chunk2 = AIMessageChunk(content="World")
full_message = chunk1 + chunk2 # AIMessageChunk(content="Hello World")


chunks = []
full_message = None
for chunk in model.stream("Hi"):
chunks.append(chunk)
print(chunk.text, end="") # 实时输出增量文本
full_message = chunk if full_message is None else full_message + chunk # 累积合并

# 最终 full_message 是一个完整的 AIMessage 对象

使用 stream 方法获取增量内容块,它们可以合并成完整消息。

消息实用工具(Utilities)

langchain_core.messages.utils 模块提供了一系列消息处理工具函数:

函数 用途
convert_to_messages 将多种格式(字典、消息列表等)统一转换为消息列表
messages_from_dict 从字典序列反序列化为消息对象
get_buffer_string 将消息列表拼接成一个字符串
filter_messages 按名称、类型或 ID 过滤消息
trim_messages 按 token 数量或消息数量修剪消息列表
merge_message_runs 合并同类型的连续消息(ToolMessage 除外)
1
2
3
4
5
# filter_messages 示例:只保留人类消息和 AI 后续消息
from langchain_core.messages import filter_messages, HumanMessage, AIMessage

messages = [HumanMessage(content="Hi"), AIMessage(content="Hello"), ...]
filtered = filter_messages(messages, include_types=[HumanMessage, AIMessage])
1
2
3
4
5
6
7
8
9
10
11
# trim_messages 示例:修剪消息以保持 token 预算,并保留系统消息
from langchain_core.messages import trim_messages

trimmed = trim_messages(
messages,
max_tokens=1000, # token 上限
token_counter=model.get_num_tokens,
strategy="last", # 保留最近消息
include_system=True, # 保留系统消息
start_on="human", # 确保消息以 HumanMessage 开头
)

示例代码

多轮对话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 安装:pip install langchain langchain-openai
# 设置环境变量:export OPENAI_API_KEY="your-key"

from langchain_core.messages import (
SystemMessage, HumanMessage, AIMessage, ToolMessage,
filter_messages, trim_messages
)
from langchain_openai import ChatOpenAI

# 1. 初始化模型
model = ChatOpenAI(model="gpt-3.5-turbo")

# 2. 构建多轮对话消息
messages = [
SystemMessage(content="You are a helpful assistant that speaks in pirate English."),
HumanMessage(content="What is the capital of France?"),
AIMessage(content="Arrr, that be Paris!"),
HumanMessage(content="What's the weather there?"),
]

# 3. 调用模型并获取回复
response = model.invoke(messages)
print(f"AI: {response.content}")

# 4. 消息过滤示例:只保留系统消息和人类消息
filtered = filter_messages(messages, include_types=[SystemMessage, HumanMessage])

# 5. 消息修剪示例:保留最后两条消息,token 限制 50
trimmed = trim_messages(
messages,
max_tokens=50,
token_counter=model.get_num_tokens,
strategy="last",
include_system=True,
)

# 6. 工具调用示例:使用 ToolMessage
tool_call_messages = [
HumanMessage(content="What's 2+2? Use calculator."),
AIMessage(
content="",
tool_calls=[{"id": "call_123", "name": "calculator", "args": {"expr": "2+2"}}]
),
ToolMessage(content="4", tool_call_id="call_123"),
]
response = model.invoke(tool_call_messages)

官方示例

官方示例:完整工具调用流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
from langchain_openai import ChatOpenAI

# 1. 初始化模型
model = ChatOpenAI(model="gpt-4o")

# 2. 构建对话历史(含工具调用)
messages = [
SystemMessage(content="你是一名金融数据助手,需调用工具获取实时数据"),
HumanMessage(content="2024年上证指数最高点是多少?")
]

# 3. 模型返回工具调用请求
response = model.invoke(messages)
# 假设response.tool_calls = [{"name": "get_stock_data", "id": "call_123", ...}]

# 4. 执行工具并生成ToolMessage
tool_result = "2024年上证指数最高点:3,421.87点(2024-08-15)"
tool_msg = ToolMessage(
content=tool_result,
tool_call_id=response.tool_calls["id"] # 关键:ID必须匹配
)

# 5. 将工具结果加入对话,获取最终回复
final_response = model.invoke(messages + [response, tool_msg])
print(final_response.content)
# 输出:2024年上证指数最高点为3,421.87点,数据来源于上海证券交易所...

多模态示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 从 URL 加载图片
message = {
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image", "url": "https://example.com/image.jpg"}
]
}

# 从 Base64 数据加载
message = {
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image", "base64": "AAAAIGZ0eXBtcDQy...", "mime_type": "image/jpeg"}
]
}

# 使用提供商管理的文件 ID
message = {
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image", "file_id": "file-abc123"}
]
}

注意:并非所有模型都支持所有文件类型,请查阅具体提供商的文档。

实践建议

消息管理规范

  • 必须显式使用消息类型,避免原始字典:

    1
    2
    3
    4
    5
    # ✅ 官方推荐:类型化消息
    messages = [SystemMessage(content="..."), HumanMessage(content="...")]

    # ❌ 不推荐:原始字典(可能丢失功能)
    messages = [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}]
  • 为消息添加ID:便于追踪和删除特定消息(如调试时)。

工具调用关键规则

  • tool_call_id必须严格匹配AIMessage中的调用ID与ToolMessagetool_call_id需完全一致。
  • 工具结果需结构化ToolMessage.content应为字符串化结果,避免直接传递复杂对象。

多模态支持

  • 仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content:

    1
    2
    3
    4
    HumanMessage(content=[
    {"type": "text", "text": "分析此图表趋势"},
    {"type": "image_url", "image_url": "https://example.com/chart.jpg"}
    ])

问题与注意事项

问题 注意事项
消息顺序要求 大多数聊天模型期望对话以 HumanMessageSystemMessage + HumanMessage 开头;
ToolMessage 必须出现在对应的 AIMessage(包含工具调用)之后
SystemMessage 限制 一次通常只能有一个有效 SystemMessage;多个 SystemMessage 可能会被模型忽略或覆盖
Token 计算 不同模型的 tokenizer 不同,trim_messagestoken_counter 应使用模型自身的计数方法
多模态模型支持 仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content,使用前请查阅模型提供商的文档
版本变更 在较新的 LangChain 版本中,消息核心类主要存放在 langchain_core.messages 模块下

核心总结

LangChain的消息系统通过结构化角色分工解决上下文混乱问题,必须严格使用类型化消息对象并维护完整对话链。多轮对话中,遗漏历史消息会导致逻辑断裂;工具调用时,ID匹配是结果整合的关键。官方文档强调,正确使用消息类型是构建可靠对话应用的基础。

LangChain 的消息系统是一个标准化、可扩展、跨模型的抽象层:

  1. 标准化:统一接口屏蔽不同模型提供商的差异
  2. 结构化:通过类型系统明确区分角色和用途
  3. 可追踪:通过 tool_call_id 实现工具调用的完整链路追踪
  4. 多模态content 支持文本、图像、音频等混合内容

掌握消息系统是构建复杂 Agent 应用的基础,特别是在处理多轮对话、工具调用、流式输出等场景时。

快速参考表

场景 推荐的消息类型 关键点
设定 AI 角色/行为 SystemMessage 放在对话开头,只设置一次
用户输入 HumanMessage(content=user_input)
模型回复 AIMessage model.invoke() 返回
工具执行结果 ToolMessage(content=result, tool_call_id=id) 必须在工具调用之后
图片输入 HumanMessage(content=[{type: "image_url", ...}]) 需模型支持
流式输出 AIMessageChunk 可用 + 拼接
过滤消息 filter_messages() 按类型、名称或 ID 筛选
控制 token 预算 trim_messages() 保留系统消息,确保有效开头
自定义角色 ChatMessage(role="custom", content=...) 用于标准角色之外的场景

提示:官方文档入口常变,需要查阅最新资料时,建议使用 site:docs.langchain.com messagessite:reference.langchain.com python/core/messages 进行定向搜索。

LangChain:消息(Message)类型和特性详解

http://blog.gxitsky.com/2026/05/04/AI-LangChain-045-Message/

作者

光星

发布于

2026-05-04

更新于

2026-08-15

许可协议

评论