一、前言

上下文学习(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 昇腾硬件侧的执行流程

  1. 将指令、示例、查询拼接成完整 Prompt 文本;

  2. Tokenizer 编码为 token 序列,送入 MindFormers 推理;

  3. Prefill 预填充阶段:对全部 Prompt 序列做完整 Attention 计算,生成 KV‑Cache;

  4. Decode 解码阶段:复用 KV‑Cache,逐 token 生成输出;

  5. 输出结果解析,得到任务答案。

痛点:示例越多,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 模板规范建议

  1. 任务指令写在最开头,清晰描述任务目标、输出格式;

  2. 示例格式统一,输入输出分隔符固定,格式保持一致;

  3. 示例尽量覆盖任务不同 case(正负样本、边界 case);

  4. 待查询样本格式与示例格式严格对齐;

  5. 尽量减少冗余文本,降低 token 消耗。

4.3 评估 ICL 效果

准备测试数据集,把 ICL 推理输出与真值对比,统计准确率;如果效果差,优先调整 Prompt 模板、增加多样性示例,而不是直接修改模型。

五、昇思 NPU 侧性能优化手段

上下文学习最大性能压力来自长 Prompt Prefill 阶段以及 KV‑Cache 显存占用。

5.1 长序列内存优化

  1. 开启 use_past(KV‑Cache 增量推理):Decode 阶段复用 Prefill 计算结果,避免每一步重算全部上下文,是 ICL 推理的基础开关。

  2. 序列并行 Sequence‑Parallel / Ring‑Attention:Prompt 示例多导致序列很长,开启序列并行,在序列维度切分 Attention 计算,降低单卡激活内存开销,支持更大长度 ICL 输入。

  3. 权重量化 W8A8:降低模型权重 HBM 占用,留出更多显存给 KV‑Cache。

5.2 Prefill 速度优化

  1. 大模型 ICL 推理使用张量并行 TP 多卡分布推理,分摊 Prefill 计算压力;

  2. 重复示例 Prompt 场景,开启前缀缓存 Prefix‑Cache:多条 ICL 请求拥有同样指令与示例前缀时,复用公共部分 KV‑Cache,大幅减少重复 Prefill 计算,降低 TTFT 首 token 时延。

5.3 业务工程化技巧

  1. 离线统计示例部分 token 数量,提前校验输入总 token,避免运行时超过max_seq_len;

  2. 示例数量动态可控,超过阈值自动降级调用微调模型;

  3. 批量 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 推理输出乱码、不遵守示例格式

  1. Prompt 模板格式不一致,示例和待查询格式不统一;

  2. 示例数量不足,缺少边界 case;

  3. temperature 设置过高,随机采样打乱输出格式;ICL 分类抽取任务建议关闭采样do_sample=False。

6.3 Prefill 时间很长,首 token TTFT 高

  1. Prompt 中示例过多,序列很长,Prefill 计算量大,属于 ICL 固有特性;

  2. 多请求共享同一套示例,开启 Prefix‑Cache 复用 KV;

  3. 开启 TP 张量并行、Ring‑Attention,加速长序列 Prefill。

6.4 KV‑Cache 显存占用很高,容易 OOM

  1. 每条 ICL 请求 Prompt 很长,KV‑Cache 随序列长度线性增长;

  2. 开启序列并行、权重量化;控制推理 batch 大小;

  3. 推理结束及时释放会话 KV‑Cache,不要累积多条大序列请求。

6.5 use_past=False 未开启增量推理

现象:推理速度极慢,每一步 token 都完整重算全部 Prompt。 ICL 场景必须打开use_past=True,启用 KV‑Cache 增量推理。

七、ICL 适用与不适用场景

适合上下文学习

  1. 业务快速验证,来不及做标注微调;

  2. 任务逻辑简单,少量示例即可说明规则:分类、简单抽取、格式转换;

  3. 多临时小任务,不想维护多套微调权重。

不建议纯 ICL,建议改用微调 SFT

  1. 任务逻辑复杂,需要大量示例;Prompt 总 token 过大;

  2. 高并发线上服务,Prefill 时延不可接受;

  3. 对任务精度稳定性要求很高。

八、总结

上下文学习 ICL 依托大模型预训练先验,完全不修改模型权重,通过 Prompt 内置指令与少量示例,推理期完成新任务适配,可以快速验证新业务。在昇思 MindSpore‑Transformers 上开展 ICL 推理,核心要点:合理构造 Prompt 模板、控制示例数量、预留足够max_seq_len,开启use_pastKV‑Cache 增量推理;当 Prompt 序列过长,可开启张量并行、Ring‑Attention 序列并行、Prefix‑Cache 前缀缓存优化内存与 Prefill 性能。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐