摘要
模型调用不只是传字符串那么简单。SystemMessage控制角色,HumanMessage传问题,AIMessage存回复,这三者组合起来才能做出真正的多轮对话。本文用一个客服助手的例子,把消息结构和上下文管理讲清楚。
一、为什么不能只传字符串
上一章我们调模型的时候,直接往里扔了一个字符串:
python
model.invoke("介绍一下你自己")
这种写法在测试的时候没问题,但做真实项目就不够用了。因为实际场景里,你需要告诉模型:
-
你是谁,扮演什么角色
-
回答要遵守什么规则
-
用户问了什么
-
之前聊过什么
这些信息需要用结构化的方式传进去,而不是堆在一个字符串里。
二、三种核心消息角色
大模型对话里有三种基本的消息类型:
SystemMessage
开发者用来设定AI的身份和规则。比如"你是客服,说话要客气,只回答订单相关问题"。这条消息在一轮对话的最开始发,比用户的所有问题优先级都高。
HumanMessage
用户发的内容。就是普通人问的问题、提的需求。
AIMessage
模型返回的回复。在多轮对话里,需要把模型的回复存下来,下次请求时再传回去,这样模型才能记住之前说过什么。
LangChain里对应的导入方式:
python
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
三、SystemMessage的用法
SystemMessage相当于给AI立规矩。在用户开口之前,先告诉AI它该怎么做。
例子:
python
from langchain_core.messages import SystemMessage
system_msg = SystemMessage(content="""你是XX电商平台的客服助手。
规则:
1. 称呼用户为"亲"
2. 回答要简洁,不超过50字
3. 遇到订单问题,要求用户提供订单号
4. 不回答与平台业务无关的问题
""")
常见的用法包括:限定角色身份、限定语气风格、限定回答长度、限定输出格式、限定不能回答的范围。
注意一点:SystemMessage的规则不是硬性约束,大模型不是传统程序,规则只能提高按要求回答的概率,不能保证百分百执行。如果规则太复杂或者互相矛盾,模型反而容易跑偏。
四、HumanMessage和AIMessage
HumanMessage就是用户输入:
python
from langchain_core.messages import HumanMessage
user_msg = HumanMessage(content="我买的手机还没发货")
AIMessage是模型的回复,在多轮对话里要把它保存下来,下次请求时带回去:
python
from langchain_core.messages import AIMessage
ai_msg = AIMessage(content="亲,请提供您的订单号,我帮您查询")
把这三条消息放到一个列表里,传给模型:
python
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
model = init_chat_model(…)
messages = [
SystemMessage(content="你是客服助手,说话客气"),
HumanMessage(content="我买的手机还没发货"),
AIMessage(content="亲,请提供订单号"),
HumanMessage(content="订单号是123456")
]
response = model.invoke(messages)
五、完整的客服助手示例
新建 01_customer_service.py:
python
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, HumanMessage
import os
load_dotenv()
model = init_chat_model(
model="deepseek-v4-flash",
model_provider="openai",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url=os.getenv("DEEPSEEK_BASE_URL")
)
system_msg = SystemMessage(content="""你是电商客服小助手。
规则:
1. 称呼用户为"亲"
2. 回答控制在50字以内
3. 订单问题必须先索要订单号
4. 不回答业务以外的问题
""")
while True:
user_input = input("\\n用户:")
if user_input.lower() == "q":
break
messages = [system_msg, HumanMessage(content=user_input)]
response = model.invoke(messages)
print(f"客服:{response.content}")
运行之后输入"我的快递到哪了",模型会先问你要订单号。这就是SystemMessage在起作用。
六、temperature参数
调用模型时可以设置temperature,控制输出的随机性。
取值范围一般是0到2:
设为0时,相同输入每次都返回一模一样的答案。适合代码生成、数学计算、订单查询这类需要精确结果的场景。
设在0.1到0.4之间,输出轻微随机但逻辑稳定,极少胡编。适合客服、知识库问答、结构化信息提取。
设在0.5到0.8之间,创意和逻辑相对平衡,适合文案、总结、日常聊天。
设在1.0以上,随机性很强,适合写故事和诗歌,但容易虚构内容。
客服场景建议用0.1到0.3,确保回答稳定。
设置方式:
python
model = init_chat_model(
…,
temperature=0.2
)
七、带多轮对话的客服助手
前面那个例子每次只问一轮,模型记不住之前说过什么。要让它记住,得把历史消息存下来。
新建 02_chat_with_history.py:
python
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
load_dotenv()
model = init_chat_model(
model="deepseek-v4-flash",
model_provider="openai",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url=os.getenv("DEEPSEEK_BASE_URL"),
temperature=0.2
)
system_msg = SystemMessage(content="你是电商客服小助手,说话客气,回答简洁。")
messages = [system_msg]
while True:
user_input = input("\\n用户:")
if user_input.lower() == "q":
break
messages.append(HumanMessage(content=user_input))
response = model.invoke(messages)
messages.append(AIMessage(content=response.content))
print(f"客服:{response.content}")
对话过程:
用户:我买的东西还没到
客服:亲,请提供订单号帮您查询
用户:订单号是ABC123
客服:查询到您的包裹已发出,预计后天送达
因为每次请求都带上了之前所有的对话记录,所以模型知道"ABC123"是前面提到的那个订单号。
八、限制历史消息长度
上面的写法有个问题:对话越长,每次请求带的文本越多,成本和响应时间都会增加。还可能超过模型的上下文窗口限制。
简单处理方式:只保留最近几轮。
新建 03_chat_with_limited_history.py:
python
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
load_dotenv()
model = init_chat_model(
model="deepseek-v4-flash",
model_provider="openai",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url=os.getenv("DEEPSEEK_BASE_URL"),
temperature=0.2
)
system_msg = SystemMessage(content="你是电商客服小助手,说话客气,回答简洁。")
MAX_HISTORY = 6
messages = [system_msg]
while True:
user_input = input("\\n用户:")
if user_input.lower() == "q":
break
messages.append(HumanMessage(content=user_input))
response = model.invoke(messages)
messages.append(AIMessage(content=response.content))
if len(messages) > MAX_HISTORY + 1:
messages = [system_msg] + messages[-(MAX_HISTORY):]
print(f"客服:{response.content}")
这里的逻辑是:保留SystemMessage不动,然后从历史消息里截取最后6条。一轮对话包含用户消息和AI回复,6条大约相当于3轮对话。


