系列篇章💥

No. 文章
1 LangChain4j Java AI 应用开发实战(一):LangChain4j 快速入门指南
2 LangChain4j Java AI 应用开发实战(二):大模型参数调优实战:Temperature、TopP、MaxTokens 深度解析
3 LangChain4j Java AI 应用开发实战(三):多模态 AI 开发 - 图片理解与图像生成实战
4 LangChain4j Java AI 应用开发实战(四):提示词工程进阶 - 模板化与结构化 Prompt 设计
5 LangChain4j Java AI 应用开发实战(五):流式响应与对话记忆 - 提升用户体验的关键技术
6 LangChain4j Java AI 应用开发实战(六):声明式 AI Service - LangChain4j 的核心编程模型
7 LangChain4j Java AI 应用开发实战(七):结构化输出实战 - 从非结构化文本提取 POJO 对象
8 LangChain4j Java AI 应用开发实战(八):用户隔离与持久化记忆 - 企业级对话系统设计
9 LangChain4j Java AI 应用开发实战(九):Few-Shot Learning - 少样本提示提升模型准确率


前言

直接让 AI 回答问题(Zero-shot)往往效果不稳定,但微调模型又成本高昂、周期漫长。有没有折中方案?Few-Shot Learning(少样本学习)通过在 Prompt 中提供少量示例,就能显著提升模型准确率和一致性。本文将深入讲解 LangChain4j 的 Few-shot 实现技巧,从基础的示例拼接、到动态示例检索、再到 Token 优化策略。你将学会如何构建高质量的示例库,如何在客服意图分类、代码生成等场景中应用 Few-shot,让模型快速"学会"特定任务的处理模式,无需训练即可获得接近微调的效果。


一、为什么需要 Few-Shot Learning?

1.1 Zero-shot 的局限性

Zero-shot(零样本):直接提问,不提供任何示例

// ❌ Zero-shot:直接提问
String response = chatModel.chat("用户说:'应用太慢了,能改进吗?'");
// 输出可能不一致:
// 第一次:"抱歉给您带来不便..."
// 第二次:"我们会努力优化的..."
// 第三次:"感谢您的反馈..."

问题

  • 格式不统一:每次回答风格可能不同
  • 缺少关键信息:可能忘记执行某些操作(如创建工单)
  • 准确率较低:复杂任务容易出错
  • 难以控制:无法精确引导模型行为

1.2 Few-shot 的优势

Few-shot(少样本):提供 2-5 个示例后再提问

// ✅ Few-shot:先给示例,再提问
List<ChatMessage> history = new ArrayList<>();

// 示例 1
history.add(UserMessage.from("我喜欢这个更新!"));
history.add(AiMessage.from("Action: forward to positive feedback\nReply: 感谢..."));

// 示例 2
history.add(UserMessage.from("应用总是崩溃!"));
history.add(AiMessage.from("Action: open ticket - crash\nReply: 抱歉..."));

// 真实问题
history.add(UserMessage.from("应用太慢了"));
String response = chatModel.chat(history);
// 输出稳定且规范:
// "Action: open ticket - performance issue
//  Reply: 我们抱歉给您带来不便..."

优势

  • 格式统一:模型模仿示例的输出格式
  • 包含必要步骤:不会遗漏关键操作
  • 准确率提升:示例提供明确指导
  • 易于控制:通过示例精确引导行为

1.3 三种学习方式对比

方式 说明 优点 缺点 适用场景
Zero-shot 直接提问,无示例 简单、省 Token 准确率低、不稳定 简单问答
Few-shot 提供 2-5 个示例 准确率高、易控制 消耗更多 Token 分类、格式化输出
Fine-tuning 训练专属模型 效果最好、成本低 开发周期长、需数据 大规模生产环境

推荐策略

  • 原型阶段 → Zero-shot 快速验证
  • 生产环境 → Few-shot 平衡效果与成本
  • 大规模应用 → Fine-tuning 降低成本

二、基础 Few-shot:FewShotExamples 详解

2.1 完整代码解析

public class T07_FewShotExamples {

    public static void main(String[] args) {

        OpenAiStreamingChatModel model = OpenAiStreamingChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .modelName("gpt-4o-mini")
                .apiKey("demo")
                .timeout(ofSeconds(100))
                .build();

        // 创建 Few-shot 对话历史
        List<ChatMessage> fewShotHistory = new ArrayList<>();

        // ===== 示例 1:正面反馈 =====
        fewShotHistory.add(UserMessage.from(
            "I love the new update! The interface is very user-friendly and the new features are amazing!"
        ));
        fewShotHistory.add(AiMessage.from(
            "Action: forward input to positive feedback storage\n" +
            "Reply: Thank you very much for this great feedback! We have transmitted your message to our product development team who will surely be very happy to hear this. We hope you continue enjoying using our product."
        ));

        // ===== 示例 2:负面反馈(技术问题)=====
        fewShotHistory.add(UserMessage.from(
            "I am facing frequent crashes after the new update on my Android device."
        ));
        fewShotHistory.add(AiMessage.from(
            "Action: open new ticket - crash after update Android\n" +
            "Reply: We are so sorry to hear about the issues you are facing. We have reported the problem to our development team and will make sure this issue is addressed as fast as possible. We will send you an email when the fix is done, and we are always at your service for any further assistance you may need."
        ));

        // ===== 示例 3:正面反馈 =====
        fewShotHistory.add(UserMessage.from(
            "Your app has made my daily tasks so much easier! Kudos to the team!"
        ));
        fewShotHistory.add(AiMessage.from(
            "Action: forward input to positive feedback storage\n" +
            "Reply: Thank you so much for your kind words! We are thrilled to hear that our app is making your daily tasks easier. Your feedback has been shared with our team. We hope you continue to enjoy using our app!"
        ));

        // ===== 示例 4:负面反馈(功能问题)=====
        fewShotHistory.add(UserMessage.from(
            "The new feature is not working as expected. It's causing data loss."
        ));
        fewShotHistory.add(AiMessage.from(
            "Action: open new ticket - data loss by new feature\n" +
            "Reply: We apologize for the inconvenience caused. Your feedback is crucial to us, and we have reported this issue to our technical team. They are working on it on priority. We will keep you updated on the progress and notify you once the issue is resolved. Thank you for your patience and support."
        ));

        // ===== 真实用户消息 =====
        UserMessage customerComplaint = UserMessage.from(
            "How can your app be so slow? Please do something about it!"
        );
        fewShotHistory.add(customerComplaint);

        System.out.println("[User]: " + customerComplaint.singleText());
        System.out.print("[LLM]: ");

        // 流式调用
        CompletableFuture<ChatResponse> futureChatResponse = new CompletableFuture<>();

        model.chat(fewShotHistory, new StreamingChatResponseHandler() {
            
            @Override
            public void onPartialResponse(String partialResponse) {
                System.out.print(partialResponse);
            }

            @Override
            public void onCompleteResponse(ChatResponse completeResponse) {
                futureChatResponse.complete(completeResponse);
            }

            @Override
            public void onError(Throwable error) {
                futureChatResponse.completeExceptionally(error);
            }
        });

        futureChatResponse.join();
    }
}

运行结果

[User]: How can your app be so slow? Please do something about it!
[LLM]: Action: open new ticket - app performance issue
Reply: We apologize for the performance issues you're experiencing with the app. Your feedback is important, and we've forwarded your concerns to our engineering team for investigation. They will look into optimizing the app for better speed. Thank you for your understanding, and we appreciate your patience as we work to improve the experience.

关键点

  • ✅ 模型学会了输出格式:Action: ...\nReply: ...
  • ✅ 正确识别为负面反馈(性能问题)
  • ✅ 自动创建工单并给出道歉回复

2.2 Few-shot 工作原理

发送给模型的完整 Prompt:

System: (隐式)你是一个客服助手

User: I love the new update! ...          ← 示例 1 用户输入
AI:   Action: forward to positive...      ← 示例 1 AI 回复

User: I am facing frequent crashes...     ← 示例 2 用户输入
AI:   Action: open new ticket - crash...  ← 示例 2 AI 回复

User: Your app has made my daily...       ← 示例 3 用户输入
AI:   Action: forward to positive...      ← 示例 3 AI 回复

User: The new feature is not working...   ← 示例 4 用户输入
AI:   Action: open new ticket - data...   ← 示例 4 AI 回复

User: How can your app be so slow?        ← 真实问题
AI:   ???                                  ← 模型根据示例推断

模型推理过程

  1. 观察模式:看到 4 个示例的用户输入和 AI 回复
  2. 提取规则
    • 正面反馈 → Action: forward to positive feedback storage
    • 负面反馈 → Action: open new ticket - [问题描述]
    • 回复语气要友好、专业
  3. 应用规则:将规则应用到新的用户输入
  4. 生成回复:按照示例格式输出

三、Few-shot 设计原则

3.1 示例数量选择

数量 适用场景 优点 缺点
0 个 简单任务 省 Token、快速 准确率低
1-2 个 中等难度 平衡效果与成本 覆盖不全
3-5 个 复杂任务 准确率高、稳定 Token 消耗大
6+ 个 极复杂任务 效果接近微调 成本高、可能超出上下文限制

推荐:大多数场景 3-5 个示例即可。

3.2 示例质量要求

好的示例

示例 1:用户抱怨崩溃 → 创建工单 + 道歉
示例 2:用户称赞功能 → 转发正面反馈 + 感谢
示例 3:用户报告数据丢失 → 创建工单 + 承诺修复

特点

  • 覆盖不同场景(正面/负面/技术问题/功能问题)
  • 输出格式一致
  • 清晰展示处理流程

差的示例

示例 1:用户说你好 → AI 说你好
示例 2:用户说谢谢 → AI 说不客气
示例 3:用户说再见 → AI 说再见

问题

  • 过于简单,没有实际价值
  • 未展示复杂逻辑
  • 对目标任务帮助有限

3.3 示例多样性

覆盖多种情况

// ✅ 多样性好
示例 1:正面反馈(界面友好)
示例 2:负面反馈(崩溃问题)
示例 3:正面反馈(功能实用)
示例 4:负面反馈(数据丢失)

// ❌ 多样性差
示例 1:负面反馈(崩溃)
示例 2:负面反馈(卡顿)
示例 3:负面反馈(闪退)
示例 4:负面反馈(黑屏)

原则

  • 正负样本均衡
  • 覆盖常见场景
  • 包含边界情况

四、高级技巧

4.1 动态 Few-shot:基于相似度检索示例

(1)问题

固定示例无法覆盖所有场景,且浪费 Token。

(2)解决方案

根据用户输入,动态检索最相关的示例。

(3)完整实现

@Service
public class DynamicFewShotService {

    @Autowired
    private EmbeddingModel embeddingModel;

    @Autowired
    private InMemoryEmbeddingStore<TextSegment> exampleStore;

    /**
     * 初始化示例库
     */
    @PostConstruct
    public void initExamples() {
        
        List<Example> examples = Arrays.asList(
            new Example(
                "应用总是崩溃",
                "Action: open ticket - crash\nReply: 抱歉...",
                "负面反馈-崩溃"
            ),
            new Example(
                "界面很友好",
                "Action: forward to positive\nReply: 感谢...",
                "正面反馈-界面"
            ),
            new Example(
                "功能很实用",
                "Action: forward to positive\nReply: 感谢...",
                "正面反馈-功能"
            ),
            new Example(
                "数据丢失了",
                "Action: open ticket - data loss\nReply: 抱歉...",
                "负面反馈-数据"
            )
        );

        // 向量化并存储
        for (Example example : examples) {
            TextSegment segment = TextSegment.from(example.getInput());
            segment.metadata().put("response", example.getResponse());
            segment.metadata().put("category", example.getCategory());
            
            Embedding embedding = embeddingModel.embed(example.getInput()).content();
            exampleStore.add(embedding, segment);
        }
    }

    /**
     * 动态检索相关示例
     */
    public List<ChatMessage> getRelevantExamples(String userInput, int maxExamples) {
        
        // 计算用户输入的向量
        Embedding queryEmbedding = embeddingModel.embed(userInput).content();
        
        // 检索最相似的示例
        List<EmbeddingMatch<TextSegment>> matches = exampleStore.findRelevant(
            queryEmbedding, 
            maxExamples
        );

        // 构建 Few-shot 历史
        List<ChatMessage> history = new ArrayList<>();
        
        for (EmbeddingMatch<TextSegment> match : matches) {
            String input = match.embedded().text();
            String response = match.embedded().metadata().getString("response");
            
            history.add(UserMessage.from(input));
            history.add(AiMessage.from(response));
        }

        return history;
    }

    /**
     * 带动态 Few-shot 的聊天
     */
    public String chatWithDynamicFewShot(String userInput) {
        
        // 检索相关示例
        List<ChatMessage> fewShotHistory = getRelevantExamples(userInput, 3);
        
        // 添加真实问题
        fewShotHistory.add(UserMessage.from(userInput));
        
        // 调用模型
        ChatResponse response = chatModel.chat(fewShotHistory);
        
        return response.aiMessage().text();
    }
}

优势

  • ✅ 只使用相关示例,节省 Token
  • ✅ 覆盖更多场景
  • ✅ 准确率更高

劣势

  • ❌ 需要维护示例库
  • ❌ 增加向量检索开销

4.2 Token 优化技巧

(1)精简示例

冗长示例

User: I absolutely love the new update that you released last week! The interface is very user-friendly and intuitive, and the new features are amazing and helpful!
AI: Thank you very much for this great feedback! We have transmitted your message to our product development team who will surely be very happy to hear this wonderful news. We hope you continue enjoying using our product and if you have any more suggestions, please feel free to share them with us.

精简示例

User: 我喜欢这个更新!
AI: Action: forward to positive\nReply: 感谢反馈!

效果:Token 减少 80%,效果几乎不变。

(2)共享 System Message

每个示例重复 System Message

System: 你是客服助手
User: ...
AI: ...

System: 你是客服助手  ← 重复
User: ...
AI: ...

只在开头设置一次

System: 你是客服助手
User: ...
AI: ...
User: ...
AI: ...

(3)使用缩写

// ❌ 完整拼写
Action: forward input to positive feedback storage

// ✅ 缩写
Action: forward_positive

4.3 示例库管理

(1)版本控制

@Data
public class FewShotExample {
    
    private String id;
    private String category;      // 分类
    private String input;         // 用户输入
    private String output;        // AI 输出
    private String version;       // 版本号
    private LocalDateTime createdAt;
    private boolean active;       // 是否启用
}

(2)效果评估

@Service
public class ExampleEvaluationService {

    /**
     * 评估示例效果
     */
    public EvaluationResult evaluateExample(FewShotExample example) {
        
        // 在测试集上运行
        int totalTests = 100;
        int correctPredictions = 0;
        
        for (TestCase testCase : testSet) {
            List<ChatMessage> history = buildFewShotHistory(example, testCase);
            String prediction = chatModel.chat(history);
            
            if (isCorrect(prediction, testCase.expectedOutput)) {
                correctPredictions++;
            }
        }
        
        double accuracy = (double) correctPredictions / totalTests;
        
        return new EvaluationResult(example.getId(), accuracy);
    }

    /**
     * 自动淘汰低效示例
     */
    @Scheduled(cron = "0 0 2 * * ?")  // 每天凌晨 2 点
    public void pruneExamples() {
        
        List<FewShotExample> allExamples = repository.findAll();
        
        for (FewShotExample example : allExamples) {
            EvaluationResult result = evaluateExample(example);
            
            if (result.getAccuracy() < 0.8) {
                example.setActive(false);  // 禁用低效示例
                repository.save(example);
                
                logger.warn("示例 {} 准确率过低({:.2f}),已禁用", 
                    example.getId(), result.getAccuracy());
            }
        }
    }
}

五、实战案例

5.1 客服意图分类

(1)需求

将用户消息分类为:咨询、投诉、建议、表扬

(2)实现

@Service
public class IntentClassifier {

    private final ChatModel chatModel;
    private final List<ChatMessage> fewShotExamples;

    public IntentClassifier(ChatModel chatModel) {
        this.chatModel = chatModel;
        this.fewShotExamples = buildExamples();
    }

    private List<ChatMessage> buildExamples() {
        
        List<ChatMessage> examples = new ArrayList<>();

        // 示例 1:咨询
        examples.add(UserMessage.from("如何重置密码?"));
        examples.add(AiMessage.from("Intent: inquiry"));

        // 示例 2:投诉
        examples.add(UserMessage.from("应用总是崩溃!"));
        examples.add(AiMessage.from("Intent: complaint"));

        // 示例 3:建议
        examples.add(UserMessage.from("希望能增加夜间模式"));
        examples.add(AiMessage.from("Intent: suggestion"));

        // 示例 4:表扬
        examples.add(UserMessage.from("这个功能太好用了!"));
        examples.add(AiMessage.from("Intent: praise"));

        return examples;
    }

    public String classify(String userInput) {
        
        List<ChatMessage> history = new ArrayList<>(fewShotExamples);
        history.add(UserMessage.from(userInput));

        ChatResponse response = chatModel.chat(history);
        
        // 提取意图
        String output = response.aiMessage().text();
        return output.replace("Intent: ", "").trim();
    }
}

// 使用
String intent = classifier.classify("我想退款");
System.out.println(intent);  // complaint

5.2 代码生成

(1)需求

根据自然语言描述生成 Java 代码

(2)实现

@Service
public class CodeGenerator {

    private final ChatModel chatModel;

    public String generateCode(String description) {
        
        List<ChatMessage> examples = new ArrayList<>();

        // 示例 1
        examples.add(UserMessage.from("创建一个计算两个数之和的方法"));
        examples.add(AiMessage.from("""
            ```
java
            public int add(int a, int b) {
                return a + b;
            }
            ```
            """));

        // 示例 2
        examples.add(UserMessage.from("创建一个判断字符串是否为空的方法"));
        examples.add(AiMessage.from("""
            ```
java
            public boolean isEmpty(String str) {
                return str == null || str.isEmpty();
            }
            ```
            """));

        // 真实问题
        examples.add(UserMessage.from(description));

        ChatResponse response = chatModel.chat(examples);
        
        return response.aiMessage().text();
    }
}

// 使用
String code = generator.generateCode("创建一个反转字符串的方法");
System.out.println(code);
// 输出:
// ```
java
// public String reverse(String str) {
//     return new StringBuilder(str).reverse().toString();
// }
// 

---

# 六、常见问题与避坑指南

## 6.1 示例冲突

❌ **现象**

示例 1:用户抱怨 → AI 道歉
示例 2:用户抱怨 → AI 反驳

模型困惑,输出不稳定



✅ **解决方案**:确保示例一致性

```java
// ✅ 所有负面反馈示例都采用相同处理方式
示例 1:崩溃 → 创建工单 + 道歉
示例 2:卡顿 → 创建工单 + 道歉
示例 3:闪退 → 创建工单 + 道歉

6.2 Token 超限

现象

Error: This model's maximum context length is 8192 tokens.
However, your messages resulted in 9500 tokens.

原因:示例太多或太长

解决方案

  1. 减少示例数量
// 从 5 个减少到 3 个
List<ChatMessage> examples = getTop3RelevantExamples(userInput);
  1. 精简示例内容
// ❌ 冗长
User: 我非常非常喜欢你们的应用,它让我的工作变得轻松多了...
AI: 非常感谢您的夸奖,我们很高兴听到这样的反馈...

// ✅ 精简
User: 应用很好用
AI: Action: forward_positive\nReply: 感谢!
  1. 使用更小的模型
.modelName("gpt-4o-mini")  // 128K 上下文
// vs
.modelName("gpt-3.5-turbo")  // 16K 上下文

6.3 示例过拟合

现象

模型只会处理与示例完全相同的情况,稍有变化就出错

原因:示例过于单一

解决方案:增加示例多样性

// ❌ 单一
示例 1:应用崩溃
示例 2:应用闪退
示例 3:应用卡死

// ✅ 多样
示例 1:应用崩溃(技术问题)
示例 2:界面不好看(体验问题)
示例 3:价格太贵(业务问题)
示例 4:功能缺失(需求问题)

七、最佳实践

7.1 示例设计 checklist

  • 数量适中:3-5 个示例
  • 覆盖全面:正负样本均衡
  • 格式一致:输出结构统一
  • 简洁明了:避免冗余信息
  • 真实场景:来自实际数据
  • 定期更新:根据效果优化

7.2 何时使用 Few-shot?

推荐使用

  • 分类任务(意图识别、情感分析)
  • 格式化输出(JSON、代码、SQL)
  • 复杂逻辑(多步推理)
  • 领域特定任务(医疗、法律)

不推荐使用

  • 简单问答(天气、时间)
  • 创意写作(诗歌、故事)
  • 开放性问题(哲学讨论)

7.3 性能监控

@Component
public class FewShotMetrics {

    @Autowired
    private MeterRegistry meterRegistry;

    /**
     * 记录 Few-shot 使用情况
     */
    public void recordUsage(String taskId, int exampleCount, 
                            int tokenCount, long latencyMs) {
        
        meterRegistry.counter("fewshot.usage.count", 
            "task", taskId).increment();
        
        meterRegistry.gauge("fewshot.example.count", 
            exampleCount);
        
        meterRegistry.gauge("fewshot.token.count", 
            tokenCount);
        
        meterRegistry.timer("fewshot.latency").record(latencyMs, TimeUnit.MILLISECONDS);
    }

    /**
     * 告警:Token 消耗过高
     */
    @Scheduled(fixedRate = 60_000)
    public void checkTokenUsage() {
        
        double avgTokens = meterRegistry.get("fewshot.token.count")
            .gauge().value();
        
        if (avgTokens > 5000) {
            alertService.sendAlert("Few-shot Token 消耗过高:" + avgTokens);
        }
    }
}

结语

通过本文的学习,你已经掌握了 Few-Shot Learning 的核心技术。从基础的示例拼接、到动态示例检索、再到 Token 优化策略,这些技巧能让你的 AI 应用在不训练模型的前提下,显著提升准确率和一致性。记住,好的 Few-shot 设计需要三个要素:高质量的示例、合理的数量控制、以及持续的优化迭代。在实际项目中,建议从 3-5 个精心设计的示例开始,通过 A/B 测试验证效果,再逐步扩展到动态检索方案。Few-shot 是连接 Zero-shot 和 Fine-tuning 的桥梁,既能快速见效,又能为后续的模型微调积累宝贵数据。


在这里插入图片描述

🎯🔖更多专栏系列文章:AI大模型提示工程完全指南AI大模型探索之路(零基础入门)AI大模型预训练微调进阶AI大模型开源精选实践AI大模型Spring AI开发实战🔥🔥🔥 其他专栏可以查看博客主页

🔔 关于作者:资深程序老猿,10年+架构经验,现专注 AIGC 探索与实践。
👍 若文章对你有所触动,恳请点赞 ⭐ 关注 ⭐ 收藏!AI 浪潮已至,愿与你同行。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐