LangChain 入门系列 · 第 2 章

LangChain 入门系列 · 第 2 章

第02章 模型调用与消息结构


目录

  • 1. 本章目标
  • 2. 为什么需要消息结构
  • 3. 常见消息角色
  • 4. system 消息
  • 5. human 消息
  • 6. ai 消息
  • 7. 案例一:客服角色助手
  • 8. 模型参数
  • 9. 案例二:带上下文的命令行客服助手
  • 10. 多轮对话的注意事项
  • 11. 案例三:限制历史消息数量
  • 12. 多轮对话的后续写法
  • 13. 本章重点
  • 14. 常见问题

1. 本章目标

上一章我们完成了 LangChain 环境搭建,并使用 DeepSeek 模型完成了第一次调用。

本章继续学习模型调用中最常用的内容:消息结构。

学完本章后,你应该能够:

  • 理解模型调用中的role
  • 使用system消息控制助手角色
  • 使用human消息传递用户问题
  • 保存 AI 回复并形成多轮对话
  • 设置常用模型参数
  • 实现一个带上下文的命令行客服助手

2. 为什么需要消息结构

上一章中,我们直接传入了字符串:

response=model.invoke("请用一句话介绍 LangChain 的作用")

这种写法可以运行,但在真实项目中不够灵活。

因为我们经常需要告诉模型:

  • 你是什么角色
  • 回答要遵守什么规则
  • 用户问了什么问题
  • 前面聊过什么内容

这时就需要使用消息结构


3. 常见消息角色

大模型对话中常见 3 类消息:

角色作用
system设置模型角色、规则和回答风格
human用户输入
ai模型回复
  • SystemMessage(系统消息):开发者设定 —— AI 是谁、能干啥、不能干啥、输出格式、语气、专业规则。
  • HumanMessage(用户消息):普通人提问、需求、问题。
  • AIMessage(AI 回复):大模型返回的内容。

LangChain 中常用的消息类:

fromlangchain_core.messagesimportAIMessage,HumanMessage,SystemMessage

示例:

messages=[SystemMessage(content="你是一名客服助手,回答要礼貌、简洁。"),HumanMessage(content="我的订单什么时候发货?"),]response=model.invoke(messages)print(response.content)

4. system 消息

SystemMessage= 给 AI 定好永久身份、规则、行事标准。

在一轮对话最开头发给模型,优先级高于用户所有提问(HumanMessage),全程生效。

对应 OpenAI 接口里role: "system"

SystemMessage用来设定助手的角色和规则。例如:

SystemMessage(content="你是一名 Python 讲师,回答要适合初学者。")

常见用途:

  • 限定角色
  • 限定语气
  • 限定回答长度
  • 限定输出要求
  • 限定不能回答的范围

第一阶段不用写特别复杂的 system 规则。规则太多,模型反而可能执行不稳定。


5. human 消息

HumanMessage表示用户输入。

HumanMessage(content="我的订单什么时候发货?")

实际项目中,用户输入通常来自:

  • 命令行输入
  • Web 页面输入框
  • App 聊天框
  • API 请求参数

本章先用命令行输入演示。


6. ai 消息

AIMessage表示模型回复。

AIMessage(content="您的订单预计 24 小时内发货,请提供订单号以便查询。")

在多轮对话中,需要把模型回复加入历史消息:

messages=[SystemMessage(content="你是一名客服助手,回答要礼貌、简洁。"),HumanMessage(content="我的订单什么时候发货?"),AIMessage(content="请提供您的订单号,我帮您查询发货状态。"),HumanMessage(content="订单号是 123456。"),]

这样下一次调用模型时,模型就能看到之前的回答。


7. 案例一:客服角色助手

本案例使用system消息控制模型角色。

创建01_customer_service.py

fromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportSystemMessage,HumanMessage# 初始化模型(上一章已配置好 DeepSeek,此处用环境变量管理 Key 更规范)importos model=ChatOpenAI(model="deepseek-chat",api_key=os.getenv("DEEPSEEK_API_KEY"),base_url="https://api.deepseek.com/v1",)# 用 system 消息设定客服角色messages=[SystemMessage(content="你是一名电商客服助手,回答要礼貌、简洁,并提醒用户提供订单号。"),HumanMessage(content="我的订单什么时候发货?"),]response=model.invoke(messages)print(response.content)

运行:

python 01_customer_service.py

这个案例重点观察:

  • 模型是否使用客服语气
  • 模型是否提醒用户提供订单号

8. 模型参数

模型调用时可以设置一些常用参数。

参数作用
temperature控制回答随机性

temperature 温度参数详解

1. 核心作用

temperature控制大模型输出的随机性、创造性、幻觉程度,取值范围:0 ~ 2

  • 越接近 0:输出固定、严谨、重复度高,几乎不瞎编;
  • 越接近 2:脑洞大、自由发挥、容易编造不存在内容。

2. 分段取值对应场景

  • temperature = 0:完全确定性,相同输入每次返回一模一样的答案。
    适用:代码生成、RAG 知识库问答、数据提取、订单查询、数学计算,杜绝 AI 瞎编。
  • temperature = 0.1 ~ 0.4:轻微随机,逻辑稳定,极少幻觉,偶尔措辞略有差别,内容不会乱编。
    最适合场景:客服问答、RAG、文档解析、结构化信息提取、写规范代码。
  • temperature = 0.5 ~ 0.8:平衡创意与逻辑,适合文案、总结、普通聊天。
  • temperature ≥ 1.0:高创造性,适合写故事、诗歌、创意文案,容易出现虚构内容。

示例:

model=ChatOpenAI(model="deepseek-chat",temperature=0.3,# 客服场景:低随机、少幻觉)

建议:

  • 问答、客服、知识库:temperature可以低一些
  • 文案、创意、改写:temperature可以高一些

不要在第一阶段追求太多参数。先掌握temperature就够用了。


9. 案例二:带上下文的命令行客服助手

本案例实现一个可以连续对话的客服助手。

创建02_chat_with_history.py

fromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportSystemMessage,HumanMessage,AIMessageimportos model=ChatOpenAI(model="deepseek-chat",api_key=os.getenv("DEEPSEEK_API_KEY"),base_url="https://api.deepseek.com/v1",)# 系统设定,全程生效;后续消息不断追加到列表中messages=[SystemMessage(content="你是一名电商客服助手,回答要礼貌、简洁。"),]print("客服助手已启动,输入 exit 退出")whileTrue:user_input=input("你:")ifuser_input.lower()=="exit":breakmessages.append(HumanMessage(content=user_input))response=model.invoke(messages)reply=response.contentprint("客服:",reply)# 把 AI 回复也加入历史,下一次调用模型就能看到前面的对话messages.append(AIMessage(content=reply))

运行:

python 02_chat_with_history.py

可以按下面方式测试:

你:我的订单到哪了? 客服:请提供您的订单号,我帮您查询物流状态。 你:订单号 123456 客服:订单 123456 已发货,预计明天送达。

因为程序保存了历史消息,所以模型能看到前面的对话内容。


10. 多轮对话的注意事项

保存历史消息很有用,但不能无限保存。

原因:

  • 消息越多,请求成本越高
  • 上下文太长,模型处理速度会变慢
  • 超过模型上下文限制后可能报错
  • 很早之前的消息可能干扰当前回答

本章先使用最简单的方式保存所有历史。

后续课程会再讲如何控制上下文长度。


11. 案例三:限制历史消息数量

为了避免历史消息无限增长,可以只保留最近几轮对话。

创建03_chat_with_limited_history.py

fromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportSystemMessage,HumanMessage,AIMessageimportos model=ChatOpenAI(model="deepseek-chat",api_key=os.getenv("DEEPSEEK_API_KEY"),base_url="https://api.deepseek.com/v1",)history=[SystemMessage(content="你是一名电商客服助手,回答要礼貌、简洁。"),]print("客服助手已启动(仅保留最近 3 轮对话),输入 exit 退出")whileTrue:user_input=input("你:")ifuser_input.lower()=="exit":breakhistory.append(HumanMessage(content=user_input))response=model.invoke(history)reply=response.contentprint("客服:",reply)history.append(AIMessage(content=reply))# 只保留最近 6 条消息history=history[-6:]

这里的:

history=history[-6:]

表示只保留最近 6 条历史消息。

通常一轮对话包含:

  • 用户消息
  • AI 回复

所以 6 条消息大约是最近 3 轮对话。

复习:list 的切片用法list[-n:]取末尾 n 个元素。


12. 多轮对话的后续写法

本章通过下面的方式手动组织消息:

messages=[SystemMessage(content="..."),HumanMessage(content="..."),AIMessage(content="..."),]

这种写法简单直观,适合先理解多轮对话的基本原理。

后面学习ChatPromptTemplate时,还可以使用:

fromlangchain_core.promptsimportChatPromptTemplate prompt=ChatPromptTemplate.from_messages([("system","你是一名客服助手,回答要礼貌、简洁。"),("placeholder","{history}"),# 历史消息占位("human","{question}"),# 当前问题占位])chain=prompt|model response=chain.invoke({"history":[HumanMessage(content="..."),AIMessage(content="...")],"question":"我的订单到哪了?",})

在 Prompt 模板中预留历史消息的位置。其中:

  • history用来接收以前的HumanMessageAIMessage
  • question表示用户当前的问题

本章只需要知道它可以更方便地插入历史消息,具体用法和完整案例会在下一章 Prompt 模板中讲。


13. 本章重点

本章最重要的是掌握:

  • 模型调用可以传字符串,也可以传消息列表
  • SystemMessage用来设置角色和规则
  • HumanMessage表示用户输入
  • AIMessage表示模型回复
  • 多轮对话需要保存历史消息
  • 历史消息不能无限增长
  • temperature可以影响回答稳定性

14. 常见问题

14.1 为什么模型没有严格按 system 规则回答

大模型不是传统程序。

System 规则能提高模型按要求回答的概率,但不能保证百分百执行。

如果要求很重要,后续可以结合:

  • 更清晰的 Prompt
  • 结构化输出
  • 程序校验
  • 后处理逻辑

14.2 为什么多轮对话越来越慢

因为每次请求都带上了历史消息。

历史越长,请求内容越多。

可以限制历史消息数量,例如:

# 只保留最近 6 条(约 3 轮)消息history=history[-6:]

✍️ 如有问题,欢迎在评论区交流。