大模型:上下文学习的使用
一、前言
上下文学习(In‑Context Learning,ICL)是大模型非常重要的能力:不需要对模型权重做任何微调更新,仅在输入 Prompt 中嵌入任务指令与少量示例样本,模型在推理阶段从上下文中识别任务模式,直接完成新查询任务输出。在分类、抽取、翻译、小样本问答等业务中,可以省去数据集标注、微调训练的成本,快速适配新业务。
昇思 MindSpore‑Transformers(MindFormers)完整支持上下文学习,依托增量推理 KV‑Cache、序列并行、Ring‑Attention 长序列能力,在昇腾 NPU 上实现少样本 ICL 推理。但实际落地经常遇到示例过多触发序列超限、Prefill 耗时高、ICL 效果不稳定、KV‑Cache 显存占用暴涨等问题。本文介绍上下文学习原理、与微调的差异、MindFormers 完整实践流程、Prompt 工程、性能调优、常见问题排查。
二、上下文学习基础原理
2.1 什么是上下文学习 ICL
上下文学习属于推理期的小样本范式,不更新模型参数。输入由三部分拼接而成:任务指令 + 若干组演示示例(输入‑输出对) + 待预测的查询样本,整体作为 Prompt 送入模型,模型自回归输出结果。
ICL 不是模型 “现场学会新权重”,而是激活预训练阶段已经学到的任务范式、语义、逻辑模式,仅作用于当前这一条输入 Prompt,任务结束模型权重不会发生任何改变。
Prompt 通用格式示例:
【任务指令】:请把下面句子转为情感标签,标签只有正向/负向。
【示例1】
句子:这家饭菜很好吃。
标签:正向
【示例2】
句子:体验很差,不推荐。
标签:负向
【待预测】
句子:服务热情,性价比很高。
标签:
2.3 昇腾硬件侧的执行流程
-
将指令、示例、查询拼接成完整 Prompt 文本;
-
Tokenizer 编码为 token 序列,送入 MindFormers 推理;
-
Prefill 预填充阶段:对全部 Prompt 序列做完整 Attention 计算,生成 KV‑Cache;
-
Decode 解码阶段:复用 KV‑Cache,逐 token 生成输出;
-
输出结果解析,得到任务答案。
痛点:示例越多,Prompt 总 token 越长,Prefill 计算量与 KV‑Cache 显存会显著上升,容易打满模型最大上下文窗口。
三、MindFormers 上下文学习完整开发流程
整体流程分为:Prompt 构造 → 加载模型与 Tokenizer → 执行生成推理 → 结果解析,支持单卡与分布式分布推理。
3.1 环境依赖
source /usr/local/Ascend/ascend‑toolkit/latest/bin/set_env.sh
pip install mindspore>=2.6 mindformers
3.2 Python 代码示例(上下文学习推理)
from mindformers import AutoModel, AutoTokenizer, GenerationConfig
# 加载模型与分词器
model_name = "./qwen2‑7b‑instruct‑ms"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
# 生成配置,开启增量推理KV‑Cache
gen_cfg = GenerationConfig(
max_new_tokens=128,
max_length=8192,
use_past=True, # 开启KV‑Cache增量推理,ICL必开
do_sample=False, # ICL小样本任务优先贪婪解码
temperature=1.0
)
# 构造ICL上下文Prompt
icl_prompt = """任务:判断句子情感,输出标签【正向】或者【负向】。
示例1:
句子:风景很美,玩的很开心。
标签:正向
示例2:
句子:质量差,完全不值得购买。
标签:负向
待预测:
句子:做工精细,价格实惠。
标签:"""
inputs = tokenizer(icl_prompt, return_tensors="ms")
output = model.generate(**inputs, generation_config=gen_cfg)
result = tokenizer.decode(output[0], skip_special_tokens=True)
print(result)
3.3 yaml 配置要点(predict_icl.yaml)
model:
model_config:
max_seq_len: 8192 # ICL示例会占用序列长度,需要预留足够窗口
use_past: True # 开启KV‑Cache增量推理
is_dynamic: True
infer:
max_new_tokens: 128
do_sample: False
# 长ICL Prompt序列过长,开启序列并行降低激活内存
parallel:
model_parallel: 2
use_sequence_parallel: True
max_seq_len必须大于【指令 + 示例 + 查询 + 输出】全部 token 总和;示例越多,需要设置越大的 max_seq_len。
四、上下文学习 Prompt 工程实践
4.1 示例数量选择
-
普通任务:3‑8 组示例效果较佳;
-
示例过多会带来两个问题:①总序列超限报错;②Prefill 时间变长,TTFT 升高;
-
若示例太多,优先考虑微调,而不是全部塞进 Prompt。
4.2 模板规范建议
-
任务指令写在最开头,清晰描述任务目标、输出格式;
-
示例格式统一,输入输出分隔符固定,格式保持一致;
-
示例尽量覆盖任务不同 case(正负样本、边界 case);
-
待查询样本格式与示例格式严格对齐;
-
尽量减少冗余文本,降低 token 消耗。
4.3 评估 ICL 效果
准备测试数据集,把 ICL 推理输出与真值对比,统计准确率;如果效果差,优先调整 Prompt 模板、增加多样性示例,而不是直接修改模型。
五、昇思 NPU 侧性能优化手段
上下文学习最大性能压力来自长 Prompt Prefill 阶段以及 KV‑Cache 显存占用。
5.1 长序列内存优化
-
开启 use_past(KV‑Cache 增量推理):Decode 阶段复用 Prefill 计算结果,避免每一步重算全部上下文,是 ICL 推理的基础开关。
-
序列并行 Sequence‑Parallel / Ring‑Attention:Prompt 示例多导致序列很长,开启序列并行,在序列维度切分 Attention 计算,降低单卡激活内存开销,支持更大长度 ICL 输入。
-
权重量化 W8A8:降低模型权重 HBM 占用,留出更多显存给 KV‑Cache。
5.2 Prefill 速度优化
-
大模型 ICL 推理使用张量并行 TP 多卡分布推理,分摊 Prefill 计算压力;
-
重复示例 Prompt 场景,开启前缀缓存 Prefix‑Cache:多条 ICL 请求拥有同样指令与示例前缀时,复用公共部分 KV‑Cache,大幅减少重复 Prefill 计算,降低 TTFT 首 token 时延。
5.3 业务工程化技巧
-
离线统计示例部分 token 数量,提前校验输入总 token,避免运行时超过
max_seq_len; -
示例数量动态可控,超过阈值自动降级调用微调模型;
-
批量 ICL 推理,控制 batch size,Prefill 阶段激活内存暴涨,batch 不可设置过大。
六、常见问题与踩坑实践
6.1 报错:sequence length exceed max_seq_len
现象:输入序列超过模型配置最大序列长度。
-
原因:指令 + 示例 + 查询总 token 超出
max_seq_len; -
解决:调大 yaml 中
model_config.max_seq_len;精简 Prompt 冗余文字;减少示例数量;过长任务改用 SFT 微调。
6.2 ICL 推理输出乱码、不遵守示例格式
-
Prompt 模板格式不一致,示例和待查询格式不统一;
-
示例数量不足,缺少边界 case;
-
temperature 设置过高,随机采样打乱输出格式;ICL 分类抽取任务建议关闭采样
do_sample=False。
6.3 Prefill 时间很长,首 token TTFT 高
-
Prompt 中示例过多,序列很长,Prefill 计算量大,属于 ICL 固有特性;
-
多请求共享同一套示例,开启 Prefix‑Cache 复用 KV;
-
开启 TP 张量并行、Ring‑Attention,加速长序列 Prefill。
6.4 KV‑Cache 显存占用很高,容易 OOM
-
每条 ICL 请求 Prompt 很长,KV‑Cache 随序列长度线性增长;
-
开启序列并行、权重量化;控制推理 batch 大小;
-
推理结束及时释放会话 KV‑Cache,不要累积多条大序列请求。
6.5 use_past=False 未开启增量推理
现象:推理速度极慢,每一步 token 都完整重算全部 Prompt。 ICL 场景必须打开use_past=True,启用 KV‑Cache 增量推理。
七、ICL 适用与不适用场景
适合上下文学习
-
业务快速验证,来不及做标注微调;
-
任务逻辑简单,少量示例即可说明规则:分类、简单抽取、格式转换;
-
多临时小任务,不想维护多套微调权重。
不建议纯 ICL,建议改用微调 SFT
-
任务逻辑复杂,需要大量示例;Prompt 总 token 过大;
-
高并发线上服务,Prefill 时延不可接受;
-
对任务精度稳定性要求很高。
八、总结
上下文学习 ICL 依托大模型预训练先验,完全不修改模型权重,通过 Prompt 内置指令与少量示例,推理期完成新任务适配,可以快速验证新业务。在昇思 MindSpore‑Transformers 上开展 ICL 推理,核心要点:合理构造 Prompt 模板、控制示例数量、预留足够max_seq_len,开启use_pastKV‑Cache 增量推理;当 Prompt 序列过长,可开启张量并行、Ring‑Attention 序列并行、Prefix‑Cache 前缀缓存优化内存与 Prefill 性能。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐

所有评论(0)