Few-shot 示例¶
演示如何通过少量示例引导模型按期望格式与风格输出,包括示例选择、 模板拼接与去重。Few-shot 是提升输出稳定性的常用手段。 对应教程:第4卷《提示工程》第2章 Few-shot 与模板。
文件路径: examples/volume-04-prompt-engineering\few_shot.py
源代码¶
"""Few-shot 提示示例。
演示如何通过少量示例引导模型按期望格式与风格输出,包括示例选择、
模板拼接与去重。Few-shot 是提升输出稳定性的常用手段。
对应教程:第4卷《提示工程》第2章 Few-shot 与模板。
"""
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass(frozen=True)
class Example:
"""单个 few-shot 示例。
Attributes:
input: 示例输入。
output: 期望输出。
"""
input: str
output: str
@dataclass
class FewShotTemplate:
"""Few-shot 提示模板。
Attributes:
instruction: 任务说明。
examples: 示例列表。
input_label: 输入行的前缀标签。
output_label: 输出行的前缀标签。
"""
instruction: str
examples: list[Example] = field(default_factory=list)
input_label: str = "输入"
output_label: str = "输出"
def add_example(self, ex: Example) -> FewShotTemplate:
"""添加示例。
Args:
ex: 示例。
Returns:
``self``。
"""
self.examples.append(ex)
return self
def render_example(self, ex: Example) -> str:
"""渲染单个示例为文本。
Args:
ex: 示例。
Returns:
形如 ``输入: ...\n输出: ...`` 的文本。
"""
return f"{self.input_label}: {ex.input}\n{self.output_label}: {ex.output}"
def build(self, query: str) -> str:
"""构建完整 prompt。
Args:
query: 当前用户查询。
Returns:
拼接好的完整 prompt。
"""
sections = [self.instruction]
for ex in self.examples:
sections.append(self.render_example(ex))
sections.append(f"{self.input_label}: {query}\n{self.output_label}:")
return "\n\n".join(sections)
def select_examples_by_keyword(
pool: list[Example],
query: str,
k: int = 2,
) -> list[Example]:
"""根据关键词重叠从示例池中选择最相关的 k 个示例。
Args:
pool: 示例池。
query: 用户查询。
k: 返回数量。
Returns:
按相关度降序排列的至多 k 个示例。
"""
query_tokens = set(query.lower())
scored: list[tuple[int, Example]] = []
for ex in pool:
overlap = len(query_tokens & set(ex.input.lower()))
scored.append((overlap, ex))
scored.sort(key=lambda x: x[0], reverse=True)
return [ex for _, ex in scored[:k]]
def deduplicate_examples(examples: list[Example]) -> list[Example]:
"""按 (input, output) 去重,保持顺序。
Args:
examples: 示例列表。
Returns:
去重后的列表。
"""
seen: set[tuple[str, str]] = set()
result: list[Example] = []
for ex in examples:
key = (ex.input, ex.output)
if key not in seen:
seen.add(key)
result.append(ex)
return result
def build_sentiment_template() -> FewShotTemplate:
"""构建一个情感分类的 few-shot 模板。
Returns:
含正/负/中三个示例的模板。
"""
return FewShotTemplate(
instruction="请对用户评论进行情感分类,只输出:正面、负面 或 中性。",
examples=[
Example(input="这个产品太好用了,强烈推荐!", output="正面"),
Example(input="用了两天就坏了,非常失望。", output="负面"),
Example(input="功能一般,价格还行。", output="中性"),
],
)
def main() -> None:
"""演示 few-shot 提示构建。"""
template = build_sentiment_template()
prompt = template.build("质量超出预期,很满意!")
print(prompt)
print("\n--- 关键词示例选择 ---")
pool = [
Example("退货流程是什么", "请进入订单页点击申请退货。"),
Example("如何修改密码", "在设置-账号安全中修改密码。"),
Example("退款多久到账", "退款一般 3-5 个工作日到账。"),
]
for ex in select_examples_by_keyword(pool, "退款什么时候到", k=2):
print(f" {ex.input} -> {ex.output}")
if __name__ == "__main__":
main()