08-OpenAI和Claude集成详解

2 阅读6分钟

掌握如何在LangChain4J中集成多个LLM供应商,实现灵活的模型切换

时间:30分钟 | 难度:⭐⭐ | Week 2


官方Example信息

  • GitHub链接OpenAiExample.java
  • 相关Example:OpenAiExample、AnthropicExample
  • 所在路径:src/main/java/dev/langchain4j/examples/
  • 代码行数:约40-60行
  • 难度:初级-中级 ⭐⭐

学习目标

  • 理解OpenAI和Claude的区别
  • 学会集成OpenAI ChatGPT
  • 学会集成Anthropic Claude
  • 掌握模型参数配置
  • 实现LLM工厂模式
  • 能在项目中灵活切换模型

🚀 快速入门:多LLM集成

为什么需要多LLM?

为什么?:
1. 成本优化 - 不同模型价格不同
2. 性能对比 - 同一任务不同模型效果可能不同
3. 可用性 - 某个模型宕机时可自动切换
4. 专业化 - 某些任务可能只有特定模型表现好

现实场景:
- 简单问题 → gpt-4o-mini(便宜)
- 复杂推理 → gpt-4o(贵但准)
- 代码生成 → Claude 3 Opus(最强)
- 快速响应 → Claude 3 Haiku(最快)

多LLM的基本架构

┌─────────────────┐
│   应用层        │
└────────┬────────┘
         │
┌────────▼──────────┐
│ LLMFactory        │
│ (LLM工厂)         │
└────────┬──────────┘
         │
    ┌────┴─────────────┐
    │                  │
┌───▼────┐      ┌──────▼──┐
│ OpenAI │      │ Anthropic│
│  GPT   │      │  Claude  │
└────────┘      └──────────┘
    │                │
  API调用          API调用

实现一个简单的MultiLlmService

@Service
public class MultiLlmService {
    private final ChatModel openAiModel;
    private final ChatModel claudeModel;

    public MultiLlmService(
        @Value("${openai.api-key}") String openaiKey,
        @Value("${anthropic.api-key}") String claudeKey
    ) {
        // OpenAI初始化
        this.openAiModel = OpenAiChatModel.builder()
            .apiKey(openaiKey)
            .modelName("gpt-4o-mini")
            .build();

        // Claude初始化
        this.claudeModel = AnthropicChatModel.builder()
            .apiKey(claudeKey)
            .modelName("claude-3-haiku-20240307")
            .build();
    }

    // 根据任务类型选择模型
    public String chat(String question, String modelType) {
        ChatModel model = "openai".equals(modelType) ? openAiModel : claudeModel;
        return model.chat(question);
    }
}

深度讲解

OpenAI集成完全指南

1️⃣ OpenAiChatModel配置

// 最小化配置
OpenAiChatModel model = OpenAiChatModel.builder()
    .apiKey("sk-proj-xxx")
    .modelName("gpt-4o-mini")
    .build();

// 完整配置
OpenAiChatModel model = OpenAiChatModel.builder()
    .apiKey("sk-proj-xxx")
    .baseUrl("https://api.openai.com/v1/")
    .modelName("gpt-4o-mini")
    .temperature(0.7)
    .maxTokens(1000)
    .topP(1.0)
    .frequencyPenalty(0.0)
    .presencePenalty(0.0)
    .build();

参数说明

  • apiKey:OpenAI API密钥
  • baseUrl:API端点(支持代理URL,如国内镜像)
  • modelName:模型名称(gpt-4o、gpt-4o-mini等)
  • temperature:创意度(0-2,0最确定,2最随机)
  • maxTokens:最大输出长度
  • topP:核心采样(0-1)
  • frequencyPenalty:频率惩罚(减少重复词)
  • presencePenalty:新颖性惩罚(鼓励新话题)

2️⃣ 支持的OpenAI模型

最新模型(推荐):
- gpt-4o(最强,多模态)
- gpt-4o-mini(推荐,性价比最高)
- gpt-4-turbo(高级推理)

过时模型(不推荐新项目):
- gpt-3.5-turbo(便宜但弱)
- gpt-4(比4o差)

3️⃣ OpenAI API代理配置

国内用户,可使用代理:

// 使用国内镜像(如果key支持)
OpenAiChatModel model = OpenAiChatModel.builder()
    .apiKey("sk-proj-xxx")
    .baseUrl("https://api.openai-proxy.com/v1/")  // 代理URL
    .modelName("gpt-4o-mini")
    .build();

Anthropic Claude集成完全指南

1️⃣ AnthropicChatModel配置

// 最小化配置
AnthropicChatModel model = AnthropicChatModel.builder()
    .apiKey("sk-ant-xxx")
    .modelName("claude-3-haiku-20240307")
    .build();

// 完整配置
AnthropicChatModel model = AnthropicChatModel.builder()
    .apiKey("sk-ant-xxx")
    .modelName("claude-3-opus-20240229")
    .temperature(0.7)
    .maxTokens(1024)
    .topK(40)
    .topP(1.0)
    .build();

2️⃣ 支持的Claude模型对比

模型系列           性能    速度    成本     用途
─────────────────────────────────────────────
Claude 3 Opus      ★★★★★  慢     最贵    复杂推理、代码
Claude 3 Sonnet    ★★★★   中等   中等    均衡使用
Claude 3 Haiku     ★★★    快     便宜    简单任务、快速
Claude 2           ★★★★   中等   便宜    通用任务(过时)

3️⃣ Claude vs OpenAI对比

维度              Claude 3 Opus       GPT-4o
─────────────────────────────────────────
推理能力          ⭐⭐⭐⭐⭐(最强)  ⭐⭐⭐⭐⭐
代码质量          ⭐⭐⭐⭐⭐          ⭐⭐⭐⭐
多模态            ⭐⭐                ⭐⭐⭐⭐⭐
成本              贵                  中等
速度              慢                  快
上下文窗口        200K                128K
中文理解          ⭐⭐⭐              ⭐⭐⭐⭐

💻 实战代码

LLMFactory工厂模式

@Component
public class LlmFactory {
    @Value("${openai.api-key}")
    private String openaiKey;

    @Value("${anthropic.api-key}")
    private String anthropicKey;

    private final Map<String, ChatModel> models = new ConcurrentHashMap<>();

    /**
     * 获取指定模型的ChatModel实例
     */
    public ChatModel getModel(LlmType type) {
        return models.computeIfAbsent(type.getName(), k -> createModel(type));
    }

    /**
     * 创建新的ChatModel实例
     */
    private ChatModel createModel(LlmType type) {
        return switch (type) {
            case GPT_4O_MINI -> OpenAiChatModel.builder()
                .apiKey(openaiKey)
                .modelName("gpt-4o-mini")
                .temperature(0.7)
                .build();

            case GPT_4O -> OpenAiChatModel.builder()
                .apiKey(openaiKey)
                .modelName("gpt-4o")
                .temperature(0.7)
                .build();

            case CLAUDE_3_OPUS -> AnthropicChatModel.builder()
                .apiKey(anthropicKey)
                .modelName("claude-3-opus-20240229")
                .temperature(0.7)
                .build();

            case CLAUDE_3_HAIKU -> AnthropicChatModel.builder()
                .apiKey(anthropicKey)
                .modelName("claude-3-haiku-20240307")
                .temperature(0.7)
                .build();
        };
    }
}

// 模型类型枚举
public enum LlmType {
    GPT_4O_MINI("gpt-4o-mini", "openai"),
    GPT_4O("gpt-4o", "openai"),
    CLAUDE_3_OPUS("claude-3-opus", "anthropic"),
    CLAUDE_3_HAIKU("claude-3-haiku", "anthropic");

    private final String modelName;
    private final String provider;

    LlmType(String modelName, String provider) {
        this.modelName = modelName;
        this.provider = provider;
    }

    public String getName() { return modelName; }
    public String getProvider() { return provider; }
}

使用工厂的Service

@Service
public class MultiLlmService {
    @Autowired
    private LlmFactory llmFactory;

    /**
     * 自动选择最优模型
     */
    public String chatWithOptimalModel(String question) {
        // 简单的启发式选择
        if (isComplexQuestion(question)) {
            return llmFactory.getModel(LlmType.GPT_4O).chat(question);
        } else {
            return llmFactory.getModel(LlmType.GPT_4O_MINI).chat(question);
        }
    }

    /**
     * 对比两个模型的输出
     */
    public ModelComparison compareModels(String question) {
        String openaiResult = llmFactory.getModel(LlmType.GPT_4O_MINI).chat(question);
        String claudeResult = llmFactory.getModel(LlmType.CLAUDE_3_HAIKU).chat(question);

        return ModelComparison.builder()
            .question(question)
            .openaiAnswer(openaiResult)
            .claudeAnswer(claudeResult)
            .timestamp(LocalDateTime.now())
            .build();
    }

    private boolean isComplexQuestion(String question) {
        // 简单的复杂度判断
        return question.length() > 100 ||
               question.contains("为什么") ||
               question.contains("如何");
    }
}

🔧 常见问题

Q1:如何处理API Key?

A: 最佳实践:

# application.yml
openai:
  api-key: ${OPENAI_API_KEY}  # 从环境变量读取
  base-url: https://api.openai.com/v1/

anthropic:
  api-key: ${ANTHROPIC_API_KEY}
# 设置环境变量
export OPENAI_API_KEY=sk-proj-xxx
export ANTHROPIC_API_KEY=sk-ant-xxx

Q2:成本和速度该如何选择?

A: 根据场景:

快速响应(<1秒)  → GPT-4o-mini 或 Claude-3-Haiku
均衡方案(<5秒)  → Claude-3-Sonnet 或 GPT-4o
最佳质量(无限制) → Claude-3-Opus 或 GPT-4o

Q3:如何实现自动故障转移?

A:

public String chatWithFallback(String question) {
    try {
        return llmFactory.getModel(LlmType.GPT_4O_MINI).chat(question);
    } catch (Exception e) {
        log.warn("GPT-4o-mini failed, switching to Claude");
        return llmFactory.getModel(LlmType.CLAUDE_3_HAIKU).chat(question);
    }
}

📊 成本对比

模型                    输入价格          输出价格      推荐场景
─────────────────────────────────────────────────────
GPT-4o-mini            $0.15/1M tokens   $0.60/1M      日常任务
GPT-4o                 $5/1M tokens      $15/1M        复杂推理
Claude 3 Haiku         $0.25/1M tokens   $1.25/1M      快速处理
Claude 3 Sonnet        $3/1M tokens      $15/1M        均衡使用
Claude 3 Opus          $15/1M tokens     $75/1M        最复杂任务

✅ 最佳实践

1️⃣ 模型选择策略

// ✅ 好的做法
public ChatModel selectModel(TaskType taskType) {
    return switch (taskType) {
        case SIMPLE_QA -> gptMini;      // 便宜
        case CODE_GENERATION -> claude; // 代码最强
        case COMPLEX_REASONING -> gpt4o;// 推理最强
    };
}

// ❌ 坏的做法
public ChatModel getModel() {
    return gpt4o; // 总用最贵的,浪费钱
}

2️⃣ 并发调用多个模型

// 获取多个模型的输出用于投票
CompletableFuture<String> openai = CompletableFuture.supplyAsync(() ->
    llmFactory.getModel(LlmType.GPT_4O_MINI).chat(question)
);

CompletableFuture<String> claude = CompletableFuture.supplyAsync(() ->
    llmFactory.getModel(LlmType.CLAUDE_3_HAIKU).chat(question)
);

CompletableFuture.allOf(openai, claude).join();
// 对多个回答进行投票或组合

3️⃣ 模型性能监控

@Service
public class ModelMonitor {
    private final Map<String, ModelMetrics> metrics = new ConcurrentHashMap<>();

    public void recordModelPerformance(String modelName, long latency, String result) {
        metrics.computeIfAbsent(modelName, k -> new ModelMetrics())
            .record(latency, result);
    }

    public ModelMetrics getMetrics(String modelName) {
        return metrics.get(modelName);
    }
}

💭 思考问题

  1. 成本vs质量的平衡:如何在不同场景下选择合适的模型?
  2. 多模型投票:3个不同的LLM给出不同答案,如何判断哪个更好?
  3. 实时模型切换:如何根据响应时间动态切换模型?
  4. 模型微调:不同模型的temperature参数应该如何设置?

学习成果检查

  • 能区分OpenAI和Claude的优劣 ✅ 2026-03-07
  • 能配置OpenAiChatModel和AnthropicChatModel ✅ 2026-03-07
  • 能实现简单的LLM工厂模式 ✅ 2026-03-07
  • 能根据任务选择合适的模型 ✅ 2026-03-07
  • 能实现模型的自动故障转移 ✅ 2026-03-07

下一步:学习Chain设计模式,将多个步骤组织成完整的流程。