纲要
- 静态示例与动态示例
- 静态示例:示例固定于模板中,无法根据任务或上下文动态调整
- 动态示例:依据任务输入和上下文窗口容量,实时选择最合适的示例子集
- 示例选择器核心概念
LengthBasedExampleSelector:基于最终提示词总长度,自动截取示例列表,确保不超出预设上限- 工作原理:计算前缀(指令)与后缀(含当前输入)的字符数,用剩余空间依次添加示例,直至达到
max_length阈值
- 关键组件
examples:示例池(输入-输出对列表)example_prompt:单个示例的格式化模板(PromptTemplate)FewShotPromptTemplate:整合前缀、动态示例集、后缀的完整提示词模板
- 实现示例:Python3 脚本,演示长短输入场景下示例数量的自适应变化
- 最佳实践:示例排序策略、
max_length设定、自定义长度计算函数
引言
在 Few Shot 提示词工程中,静态示例虽然直观,但会固定消耗上下文窗口。面对大模型有限的上下文容量,示例过多可能导致截断,过少则可能影响输出质量。LangChain 提供了一组示例选择器(Example Selector),其中 LengthBasedExampleSelector 以简单高效的策略,根据提示词总长度动态筛选示例,使提示词始终维持在合理长度,从而提升应用的稳定性和通用性。
静态示例与动态示例对比
静态示例将所有示例永久嵌入模板,无论输入内容长短,均完整拼接到提示词中。其缺陷显而易见:
- 上下文窗口被大量示例占据,挤占实际任务指令和输出空间。
- 固定示例可能包含与当前输入不相关的噪声,干扰模型判断。
动态示例选择器则维护一个较大的示例池,在每次提示词构建时,根据输入长度和预设长度上限,自动挑选合适的子集注入提示词。两者的主要差异如下:
| 特性 | 静态示例 | 动态示例(LengthBasedExampleSelector) |
|---|---|---|
| 示例调整 | 固定不变 | 随输入长度动态截取 |
| 上下文利用率 | 可能浪费或溢出 | 精确控制在阈值内 |
| 实现复杂度 | 低 | 中(借助选择器) |
| 典型适用场景 | 示例数量少且固定 | 示例丰富、输入长度变化显著 |
LengthBasedExampleSelector 工作原理
该选择器的核心逻辑在格式化阶段触发:
- 计算固定前缀(如系统指令)和后缀(包含当前用户输入及输出引导)的字符长度。
- 用预设的
max_length减去上述长度,得到可用于示例的剩余空间。 - 从示例列表的头部开始,逐个尝试添加示例。每添加一个,检查累计总长度是否超过
max_length。 - 若添加后未超限,则保留该示例并继续;若超限,则终止添加,后续示例均被丢弃。
这种顺序选择机制意味着示例列表的次序直接影响最终选中的结果。将最具代表性、最通用的示例置于列表前端,可最大程度保证它们在多数场景下被保留。
代码实现与解析
以下示例基于 LangChain 实现反义词任务,演示 LengthBasedExampleSelector 如何随输入长度自动压缩示例数量。
环境准备
安装所需依赖(使用 Python3.8+,LangChain >= 0.1.0):
pip install langchain langchain-core
完整脚本
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_core.example_selectors import LengthBasedExampleSelector
# 1. 定义示例池(反义词对)
examples = [
{"input": "happy", "output": "sad"},
{"input": "高兴", "output": "悲伤"},
{"input": "sunny", "output": "gloomy"},
{"input": "up", "output": "down"},
{"input": "大", "output": "小"},
]
# 2. 格式化单个示例的模板
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="原词: {input}\n反义词: {output}"
)
# 3. 创建长度选择器,设最大总长度为100字符(便于演示)
# 默认按字符数计算长度,可传入 get_text_length 自定义
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_prompt,
max_length=100,
)
# 4. 构建动态 Few Shot 提示词模板
dynamic_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
prefix="给出每个输入词的反义词:",
suffix="原词: {input}\n反义词:",
input_variables=["input"],
)
# 5. 短输入场景
short_input = "hot"
print("=== 短输入(hot)===")
print(dynamic_prompt.format(input=short_input))
print()
# 6. 长输入场景(构造超长字符串)
long_input = "非常" * 30
print("=== 长输入(" + "非常"*30 + ")===")
print(dynamic_prompt.format(input=long_input))
运行后,短输入时提示词将包含多个示例;长输入时示例数量自动减少,总长度始终被限制在 100 字符以内。
关键点说明
max_length的单位与get_text_length函数相关,默认按字符数计算。如需按 token 计数,可自定义get_text_length参数(例如使用tiktoken编码器)。- 示例选择器在
FewShotPromptTemplate内部被调用,无需显式调用选择方法。 - 若所有示例的总长度仍小于剩余空间,则全部保留。
API 速览
本节梳理本博客涉及的核心 API,便于快速查阅。
LengthBasedExampleSelector
所属库:langchain_core.example_selectors
class LengthBasedExampleSelector(BaseExampleSelector):
def __init__(
self,
examples: List[dict],
example_prompt: PromptTemplate,
max_length: int = 2048,
get_text_length: Optional[Callable[[str], int]] = None,
):
...
参数:
examples:示例列表,每个元素为包含输入/输出字段的字典。example_prompt:用于将单个示例格式化为字符串的PromptTemplate。max_length:提示词总字符数的上限(默认 2048)。get_text_length:可选函数,接收字符串返回长度值,默认使用len。
返回值:选择器实例,可传入 FewShotPromptTemplate。
FewShotPromptTemplate
所属库:langchain_core.prompts
class FewShotPromptTemplate(BasePromptTemplate):
def __init__(
self,
example_selector: Optional[BaseExampleSelector] = None,
examples: Optional[List[dict]] = None,
example_prompt: PromptTemplate,
prefix: str = "",
suffix: str = "",
input_variables: List[str],
...
):
...
参数:
example_selector或examples二选一,前者用于动态选择,后者用于静态示例。example_prompt:格式化单个示例的模板。prefix/suffix:固定在示例前后的文本。input_variables:模板中需要用户提供的变量名列表。
方法:
format(**kwargs):根据输入变量生成完整提示词字符串。
使用建议与注意事项
- 示例顺序至关重要:选择器按列表顺序从头开始选取,因此将最典型、最通用的示例置前,可保证在长度受限时优先保留它们。
- 合理设定
max_length:建议略低于模型实际上下文窗口(考虑输出 token 占位),若按 token 计费,可自定义get_text_length使用 token 编码器。 - 与其他选择器组合:当仅靠长度不足时,可考虑
SemanticSimilarityExampleSelector,它基于向量相似度选择与当前输入最相关的示例,后续文章将深入探讨。
Demo 示例
以下提供一个完整可运行的 Python 脚本,包含上述反义词示例的完整演示,并额外增加自定义长度计算(按 token 数)的注释示例。
运行说明
- 将上述“完整脚本”代码保存为
length_selector_demo.py。 - 在终端执行
python length_selector_demo.py。 - 观察输出结果,验证短输入和长输入下示例数量的变化。
代码说明
- 示例池包含中英文反义词对,演示混合语言场景。
max_length=100故意设小,以清晰展示截断效果。- 脚本未使用外部 API,完全本地运行,无额外费用。
技术点总结
- 动态示例选择机制的工作原理与集成方式。
FewShotPromptTemplate与ExampleSelector的协作模式。- 字符长度与 token 长度的概念区分及自定义扩展。
参考文档
官方文档
- LangChain 示例选择器概念指南: https://python.langchain.com/docs/modules/model_io/prompts/example_selectors/
- LangChain
LengthBasedExampleSelectorAPI 参考: https://api.python.langchain.com/en/latest/example_selectors/langchain_core.example_selectors.length_based.LengthBasedExampleSelector.html - LangChain
FewShotPromptTemplate详细用法: https://python.langchain.com/docs/modules/model_io/prompts/few_shot_examples/
参考链接
- 本博客涉及的代码仓库(示例): https://github.com/langchain-ai/langchain
- 关于 token 计数与长度控制的讨论: https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them
总结
LengthBasedExampleSelector 为 Few Shot 提示词提供了轻量且可靠的长度控制方案,适用于输入长度变化大、示例丰富的实际生产场景。
通过合理排序示例、精准设定长度阈值,并配合自定义长度计算,可有效优化上下文窗口利用,提升模型响应的一致性与准确性。
该选择器是 LangChain 提示词工程体系中的基础组件,为进一步引入语义选择器等高级策略奠定了良好基础。
421



被折叠的 条评论
为什么被折叠?



