news 2026/9/16 7:17:39

LangChain 能力详解!:核心组件入门——消息、提示词模板与 Few-Shot 少样本!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain 能力详解!:核心组件入门——消息、提示词模板与 Few-Shot 少样本!

目录

一、核心组件概述

二、Messages:聊天模型中的消息

1. LangChain 中的消息类型

2. AIMessage 中有哪些内容

三、多轮对话与历史消息

1. 没有历史消息时

2. 手动携带历史消息

3. 历史消息为什么需要管理

4. 使用 trim_messages 裁剪消息

四、PromptTemplate:字符串提示词模板

1. 模板的核心结构

2. 模板为什么重要

五、ChatPromptTemplate:聊天消息模板

六、MessagesPlaceholder:消息占位符

七、Few-Shot:少样本提示

1. Few-Shot 示例

2. Few-Shot 的适用场景

3. Few-Shot 的注意点

八、Few-Shot 示例选择器

1. 语义相似度选择

2. MMR:最大边际相关性

九、总结


LangChain 的核心并不只是“调用模型”。
它更重要的价值,是将消息、提示词、模型、解析器、检索器等能力标准化,让开发者可以像搭积木一样构建 LLM 应用

一、核心组件概述

LangChain 中有很多核心组件,例如:

  • Messages;
  • Prompt Templates;
  • Output Parsers;
  • Document Loaders;
  • Text Splitters;
  • Embeddings;
  • Vector Stores;
  • Retrievers。

这些组件看起来很多,但本质上都围绕一个目标:

让大模型的输入更规范 让大模型的输出更稳定 让大模型能够使用外部知识 让整个调用流程更容易组合和维护

本篇先学习前三个基础组件:

消息 Messages ↓ 提示词模板 PromptTemplate ↓ 少样本提示 Few-Shot Prompting

二、Messages:聊天模型中的消息

聊天模型并不是简单接收一段字符串,而是接收一组消息。每条消息通常包括:

  • 角色 Role;
  • 内容 Content;
  • 元数据 Metadata;
  • 工具调用信息 Tool Calls;
  • Token 使用信息 Usage Metadata。

常见角色如下:

角色作用
system设置模型身份、规则、上下文
user用户输入
assistant模型回答
tool工具执行结果

1. LangChain 中的消息类型

LangChain 对不同模型厂商的消息格式进行了统一封装。

类名说明
SystemMessage系统消息
HumanMessage用户消息
AIMessage模型回复
ToolMessage工具执行结果
AIMessageChunk流式输出块

示例:

from langchain_core.messages import ( SystemMessage, HumanMessage, AIMessage ) messages = [ SystemMessage(content="你是一名专业的 Java 后端工程师。"), HumanMessage(content="什么是 IOC?"), AIMessage(content="IOC 是控制反转,是 Spring 的核心思想之一。"), HumanMessage(content="那 DI 又是什么?") ]

将消息交给模型:

from langchain_openai import ChatOpenAI model = ChatOpenAI(model="gpt-4o-mini") result = model.invoke(messages) print(result.content)

2.AIMessage中有哪些内容

模型调用后返回的通常是AIMessage。其中常用属性包括:

print(result.content) print(result.response_metadata) print(result.usage_metadata) print(result.tool_calls)

含义如下:

属性含义
content模型回答内容
response_metadata响应信息,如模型名、请求 ID、结束原因
usage_metadataToken 使用量
tool_calls模型请求调用的工具

如果模型没有调用工具,tool_calls通常为空列表。

三、多轮对话与历史消息

很多人第一次接触 LLM 时都会问:

模型能记住我上一句话吗?

严格来说,模型并不会自动保存会话记忆。每次调用模型时,模型只能看到本次请求发送给它的内容。

1. 没有历史消息时

from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage model = ChatOpenAI(model="gpt-4o-mini") result1 = model.invoke([ HumanMessage(content="你好,我叫小明") ]) print(result1.content) result2 = model.invoke([ HumanMessage(content="我叫什么名字?") ]) print(result2.content)

第二次调用中,模型没有收到“小明”这条信息,所以无法回答。

2. 手动携带历史消息

from langchain_core.messages import ( HumanMessage, AIMessage ) messages = [ HumanMessage(content="你好,我叫小明"), AIMessage(content="你好,小明,很高兴认识你。"), HumanMessage(content="我叫什么名字?") ] result = model.invoke(messages) print(result.content)

这样模型才能根据历史消息回答:

你叫小明。

3. 历史消息为什么需要管理

多轮对话越多,消息列表会越长。

系统消息 + 第一轮用户问题 + 第一轮模型回答 + 第二轮用户问题 + 第二轮模型回答 + ...

问题在于:

  • 上下文窗口有限;
  • Token 成本会持续增加;
  • 太多旧消息会干扰当前任务;
  • 模型可能无法聚焦真正重要的信息。

因此,历史消息管理通常包括:

  • 保留最近几轮对话;
  • 删除无关消息;
  • 对旧对话做摘要;
  • 按 Token 数量裁剪;
  • 将会话状态存入 Redis、数据库或 LangGraph。

4. 使用trim_messages裁剪消息

from langchain_core.messages import ( HumanMessage, AIMessage, SystemMessage, trim_messages ) messages = [ SystemMessage(content="你是一个技术助手。"), HumanMessage(content="你好,我叫小明。"), AIMessage(content="你好,小明。"), HumanMessage(content="我喜欢学习 Python。"), AIMessage(content="Python 很适合入门编程。"), HumanMessage(content="我叫什么名字?") ] trimmer = trim_messages( max_tokens=100, strategy="last", token_counter=model, include_system=True ) trimmed_messages = trimmer.invoke(messages) result = model.invoke(trimmed_messages) print(result.content)

这里的核心思想是:

保留系统消息和较新的对话内容,适当裁剪过早的历史消息。


四、PromptTemplate:字符串提示词模板

如果项目中需要频繁生成类似提示词,手动拼接字符串会很麻烦。

city = "西安" prompt = f"请介绍一下{city}的历史,并列出三个著名景点。"

如果换一个城市,就要重新拼接。LangChain 提供了PromptTemplate

from langchain_core.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请使用{language}介绍{city}的历史,并列出三个著名景点。" ) prompt_value = prompt_template.invoke({ "language": "中文", "city": "西安" }) print(prompt_value.text)

输出:

请使用中文介绍西安的历史,并列出三个著名景点。

1. 模板的核心结构

PromptTemplate( template="请介绍{city}的历史", input_variables=["city"] )
  • template:固定文本和变量占位符;
  • input_variables:模板需要传入的变量名称。

2. 模板为什么重要

提示词模板的价值包括:

  • 提高复用性;
  • 统一 Prompt 格式;
  • 将业务数据与提示词逻辑分离;
  • 更方便版本管理和维护;
  • 更容易构建复杂 LCEL 链。

五、ChatPromptTemplate:聊天消息模板

对于聊天模型,更常见的是ChatPromptTemplate。它可以一次性定义系统消息、用户消息、AI 消息等结构。

from langchain_core.prompts import ChatPromptTemplate prompt_template = ChatPromptTemplate.from_messages([ ("system", "你是一名{role}。请使用简洁、专业的语言回答。"), ("human", "{question}") ]) prompt_value = prompt_template.invoke({ "role": "Python 开发工程师", "question": "什么是生成器?" }) messages = prompt_value.to_messages() print(messages)

输出结果会包含:

SystemMessage(...) HumanMessage(...)

接下来可以将模板直接接入模型:

from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser model = ChatOpenAI(model="gpt-4o-mini") chain = prompt_template | model | StrOutputParser() result = chain.invoke({ "role": "Python 开发工程师", "question": "什么是生成器?" }) print(result)

这就是 LCEL 的一个典型链式写法。


六、MessagesPlaceholder:消息占位符

有时 Prompt 中不只是插入一个字符串,而是需要动态插入多条消息。例如聊天历史:

系统消息 + 历史对话 + 当前用户问题

这时可以使用MessagesPlaceholder

from langchain_core.prompts import ( ChatPromptTemplate, MessagesPlaceholder ) from langchain_core.messages import ( HumanMessage, AIMessage ) prompt_template = ChatPromptTemplate.from_messages([ ("system", "你是一名耐心的编程助手。"), MessagesPlaceholder(variable_name="history"), ("human", "{question}") ]) history = [ HumanMessage(content="什么是 Redis?"), AIMessage(content="Redis 是一个高性能内存数据库。") ] prompt_value = prompt_template.invoke({ "history": history, "question": "Redis 可以做缓存吗?" }) for message in prompt_value.to_messages(): print(message)

最终结构大致如下:

SystemMessage:你是一名耐心的编程助手。 HumanMessage:什么是 Redis? AIMessage:Redis 是一个高性能内存数据库。 HumanMessage:Redis 可以做缓存吗?

消息占位符常用于:

  • 多轮对话历史;
  • RAG 检索结果;
  • Few-Shot 示例;
  • 工具调用结果;
  • 动态注入系统上下文。

七、Few-Shot:少样本提示

Few-Shot Prompting,即少样本提示。它的思想是:

不只是告诉模型“做什么”,还给模型几个“正确示例”,让模型模仿示例完成任务。

例如,我们希望模型判断评论情绪。直接提问:

判断下面评论的情绪:物流很慢,但是商品质量很好。

模型可能会回答“中性”“积极”或“混合”,结果不一定稳定。如果先给它一些示例:

输入:商品很好,物流很快 输出:积极 输入:质量太差,再也不会买了 输出:消极 输入:物流很慢,但是商品质量很好 输出:

模型会更容易理解我们的分类规则和输出格式。

1. Few-Shot 示例

from langchain_core.prompts import ( ChatPromptTemplate, FewShotChatMessagePromptTemplate ) examples = [ { "input": "商品很好,物流很快", "output": "积极" }, { "input": "质量太差,再也不会买了", "output": "消极" }, { "input": "整体一般,没有特别惊喜", "output": "中性" } ] example_prompt = ChatPromptTemplate.from_messages([ ("human", "{input}"), ("ai", "{output}") ]) few_shot_prompt = FewShotChatMessagePromptTemplate( examples=examples, example_prompt=example_prompt ) final_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个商品评论情绪分类助手,只返回:积极、消极或中性。"), few_shot_prompt, ("human", "{input}") ])

调用:

model = ChatOpenAI(model="gpt-4o-mini") chain = final_prompt | model | StrOutputParser() result = chain.invoke({ "input": "价格比较贵,但做工不错。" }) print(result)

2. Few-Shot 的适用场景

Few-Shot 很适合:

  • 文本分类;
  • 信息抽取;
  • 格式化输出;
  • 特定写作风格;
  • 特定业务规则;
  • 多步骤推理任务;
  • 难以通过一句话描述清楚的任务。

3. Few-Shot 的注意点

Few-Shot 并不是示例越多越好。

示例过多会导致:

  • Token 消耗上升;
  • 调用成本提高;
  • 上下文窗口被占用;
  • 模型被无关示例干扰。

一个高质量示例应该具备:

  • 与真实输入相似;
  • 格式清晰;
  • 覆盖典型情况;
  • 包含边界情况;
  • 不包含互相矛盾的规则。

八、Few-Shot 示例选择器

实际项目中,示例可能有几百条甚至几千条,不可能全部放进 Prompt。因此需要根据当前问题,挑选最适合的几个示例。

常见策略包括:

选择方式思路
固定示例每次使用相同的几个示例
按长度选择根据上下文剩余空间选择示例
语义相似度选择选择与当前问题语义最接近的示例
MMR 选择兼顾相关性和多样性
N-Gram 重叠根据词语重叠程度选择示例

1. 语义相似度选择

例如有以下示例:

示例 1:如何学习 Python? 示例 2:Python 入门应该看什么书? 示例 3:Java 项目如何部署?

如果当前问题是:

Python 初学者如何开始学习?

那么应该优先选择示例 1 和示例 2。

语义相似度选择的核心是:

当前问题向量 ↓ 与示例库中的向量计算相似度 ↓ 挑选最相近的 K 个示例

2. MMR:最大边际相关性

如果只根据相似度选择,可能得到三条内容非常相近的示例。

MMR 的作用是:

既选择和当前问题相关的示例 又避免多个示例内容过于重复

它在 RAG 和 Few-Shot 中都很常见。

九、总结

本文学习了 LangChain 的前三个核心组件。

  1. Messages:聊天模型输入和输出的标准单位;
  2. PromptTemplate:构建可复用的字符串提示词;
  3. ChatPromptTemplate:构建多角色消息模板;
  4. MessagesPlaceholder:动态插入历史消息或上下文;
  5. Few-Shot:通过示例约束模型行为;
  6. 示例选择器:从大量示例中动态挑选最相关的内容。

下一篇将继续学习输出解析、RAG、文档加载、文本分割、向量化和检索器。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 7:17:37

K8s-零基础入门

Kubernetes 零基础入门:从认识概念到部署第一个网站 这篇教程面向第一次接触 Kubernetes 的读者。你不需要先记住所有缩写,先弄懂它解决什么问题,再跟着练习部署一个网站。 一、什么是 K8s? Kubernetes 是一个用于自动化部署、…

作者头像 李华
网站建设 2026/9/16 7:16:41

计算机三级:STP生成树协议

计算机三级:STP生成树协议一. 生成树协议STP二. STP的工作过程为2.1 BPDU(网桥协议数据单元)三. 交换机STP配置3.1 PortFast3.2 UplinkFast(直接链路失效)3.3 BackboneFast3.4 BPDU Filtering四. 例题一. 生成树协议STP 生成树协议STP是一种工作在 OSI参考模型第二…

作者头像 李华
网站建设 2026/9/16 7:16:37

JAVA-课堂笔记01

预科07 基本的DOS命令#盘符切换#查看当前目录下的所有文件 dir#切换目录 cd change directorycd ..#清理屏幕 cls(清理屏幕)#退出终端 exit#查看电脑的ip ipconfig#打开应用calcmspaintnotepad#ping命令ping www.baidu.com#文件操作md 文件名rd 目录名cd>文件名del…

作者头像 李华
网站建设 2026/9/16 7:15:39

Packet Tracer 9.0入门指南:从CCNA实验到网络排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 7:14:53

2026年首推PDF转换器免费版深度测评与使用指南

1. 项目概述作为一名长期与PDF文档打交道的文字工作者,我深知一款优秀的PDF转换器对工作效率的提升有多重要。最近在准备2026年度的文档处理工具评测时,发现市面上新出现了一款号称"2026年首推"的PDF转换器免费版。经过两周的深度使用和对比测…

作者头像 李华
网站建设 2026/9/16 7:14:51

DeepSeek Harness升级后插件集体罢工?根因排查与修复指南

如果你把 DeepSeek Harness 当成日常写代码、跑 Agent 任务的主力工具,那你大概率也经历过这种血压飙升的瞬间:屏幕上弹出新版本提示,顺手点了升级,结果启动器本身倒是能正常打开,排着队的插件却一个个罢工——插件图标…

作者头像 李华