【Langchain4j-Java AI开发】02-模型参数配置与调优

LangChain4j 模型参数配置与调优

概述

本教程将详细介绍如何配置和调优 LangChain4j 中的模型参数,包括温度(temperature)、超时设置、日志记录、流式响应等高级功能。

核心模型参数

1. Temperature(温度)

Temperature 控制模型输出的随机性和创造性:

  • 低温度 (0.0 - 0.3): 输出更确定、更一致,适合事实性任务
  • 中温度 (0.5 - 0.7): 平衡创造性和一致性
  • 高温度 (0.8 - 2.0): 输出更随机、更有创造性,适合创意写作

代码示例 (参考:tutorials/src/main/java/_01_ModelParameters.java

java 复制代码
package dev.langchain4j.example;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

import java.time.Duration;

import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;

public class TemperatureExample {

    public static void main(String[] args) {

        String prompt = "用一句话描述春天";

        // 低温度 - 输出更稳定、可预测
        ChatLanguageModel conservativeModel = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName(GPT_4_O_MINI)
                .temperature(0.1)  // 低温度
                .build();

        System.out.println("【低温度输出】");
        System.out.println(conservativeModel.generate(prompt));
        System.out.println(conservativeModel.generate(prompt));  // 两次输出会非常相似

        // 高温度 - 输出更有创意、随机性高
        ChatLanguageModel creativeModel = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName(GPT_4_O_MINI)
                .temperature(1.5)  // 高温度
                .build();

        System.out.println("\n【高温度输出】");
        System.out.println(creativeModel.generate(prompt));
        System.out.println(creativeModel.generate(prompt));  // 两次输出差异较大
    }
}

输出示例

复制代码
【低温度输出】
春天是万物复苏、生机勃勃的季节。
春天是万物复苏、生机盎然的季节。

【高温度输出】
春天是花朵绽放、蝴蝶翩翩起舞的诗意时光。
春暖花开,万物苏醒,大地披上绿色的新装,鸟儿欢唱着季节的赞歌。

2. Timeout(超时设置)

设置请求超时时间,避免长时间等待:

java 复制代码
ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .timeout(Duration.ofSeconds(60))  // 设置 60 秒超时
        .build();

推荐配置

  • 快速查询: 30 秒
  • 常规对话: 60 秒
  • 复杂任务: 120 秒

3. Max Tokens(最大令牌数)

控制生成内容的最大长度:

java 复制代码
ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .maxTokens(500)  // 最多生成 500 个 token
        .build();

Token 估算

  • 1 个中文字符 ≈ 2-3 tokens
  • 1 个英文单词 ≈ 1-2 tokens
  • 500 tokens ≈ 200-250 个中文字

4. Top P(核采样)

控制模型考虑的词汇范围:

java 复制代码
ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .topP(0.9)  // 只考虑累积概率达到 90% 的词汇
        .build();
  • topP = 1.0: 考虑所有可能的词汇
  • topP = 0.9: 只考虑最可能的 90% 词汇(推荐)
  • topP = 0.5: 输出更保守

日志与调试

启用请求/响应日志

LangChain4j 提供内置的日志功能,帮助调试和监控:

java 复制代码
import dev.langchain4j.model.openai.OpenAiChatModel;

ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .logRequests(true)   // 记录请求内容
        .logResponses(true)  // 记录响应内容
        .build();

String response = model.generate("你好");

日志输出示例

复制代码
Request:
- model: gpt-4o-mini
- messages: [UserMessage { contents = [TextContent { text = "你好" }] }]
- temperature: 0.7
- max tokens: null

Response:
- id: chatcmpl-abc123
- model: gpt-4o-mini
- usage: {prompt_tokens=8, completion_tokens=15, total_tokens=23}
- content: 你好!有什么我可以帮助你的吗?

自定义日志记录器

对于生产环境,使用自定义监听器:

java 复制代码
import dev.langchain4j.model.chat.listener.ChatModelListener;
import dev.langchain4j.model.chat.listener.ChatModelRequest;
import dev.langchain4j.model.chat.listener.ChatModelResponse;

ChatModelListener customListener = new ChatModelListener() {
    @Override
    public void onRequest(ChatModelRequest request) {
        System.out.println("发送请求: " + request.messages().size() + " 条消息");
    }

    @Override
    public void onResponse(ChatModelResponse response) {
        System.out.println("收到响应,耗时: " + response.metadata().finishReason());
        System.out.println("Token 使用: " + response.tokenUsage());
    }

    @Override
    public void onError(Throwable error) {
        System.err.println("请求失败: " + error.getMessage());
    }
};

ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .listeners(List.of(customListener))  // 添加监听器
        .build();

流式响应(Streaming)

流式响应可以逐步返回内容,提供更好的用户体验。

代码示例 (参考:tutorials/src/main/java/_04_Streaming.java

java 复制代码
package dev.langchain4j.example;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.output.Response;

import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;

public class StreamingExample {

    public static void main(String[] args) throws InterruptedException {

        // 1. 创建流式模型
        OpenAiStreamingChatModel model = OpenAiStreamingChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName(GPT_4_O_MINI)
                .build();

        // 2. 定义响应处理器
        StreamingResponseHandler<AiMessage> handler = new StreamingResponseHandler<>() {

            @Override
            public void onNext(String token) {
                // 每收到一个 token 就立即打印
                System.out.print(token);
            }

            @Override
            public void onComplete(Response<AiMessage> response) {
                System.out.println("\n\n[响应完成]");
                System.out.println("完整消息: " + response.content().text());
            }

            @Override
            public void onError(Throwable error) {
                System.err.println("发生错误: " + error.getMessage());
            }
        };

        // 3. 发送流式请求
        System.out.println("请写一首关于春天的诗:\n");
        model.generate("请写一首关于春天的短诗", handler);

        // 等待流式响应完成
        Thread.sleep(10000);
    }
}

AI Service 中使用流式响应

java 复制代码
import dev.langchain4j.service.TokenStream;

interface StreamingAssistant {
    TokenStream chat(String message);
}

StreamingAssistant assistant = AiServices.builder(StreamingAssistant.class)
        .streamingChatModel(streamingModel)  // 使用流式模型
        .build();

assistant.chat("讲个笑话")
        .onNext(System.out::print)
        .onComplete(response -> System.out.println("\n完成"))
        .onError(Throwable::printStackTrace)
        .start();

重试与错误处理

配置重试策略

java 复制代码
import dev.langchain4j.model.openai.OpenAiChatModel;

ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .maxRetries(3)  // 最多重试 3 次
        .build();

手动错误处理

java 复制代码
try {
    String response = model.generate("你好");
    System.out.println(response);
} catch (Exception e) {
    if (e.getMessage().contains("timeout")) {
        System.err.println("请求超时,请稍后重试");
    } else if (e.getMessage().contains("rate limit")) {
        System.err.println("触发速率限制,请降低请求频率");
    } else {
        System.err.println("发生错误: " + e.getMessage());
    }
}

响应格式控制

JSON 模式

强制模型返回有效的 JSON:

java 复制代码
ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .responseFormat("json_object")  // 强制 JSON 输出
        .build();

String response = model.generate("用 JSON 格式返回:姓名张三,年龄25,城市北京");
System.out.println(response);
// 输出: {"姓名": "张三", "年龄": 25, "城市": "北京"}

严格 JSON Schema(推荐)

java 复制代码
ChatLanguageModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_4_O_MINI)
        .responseFormat("json_schema")  // 使用 JSON Schema
        .strictJsonSchema(true)          // 严格模式
        .build();

// 结合 AI Service 使用
interface PersonExtractor {
    Person extractFrom(String text);
}

static class Person {
    private String name;
    private int age;
    private String city;
    // getters and setters...
}

PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);
Person person = extractor.extractFrom("我叫张三,今年25岁,住在北京");

模型选择建议

OpenAI 模型对比

模型 成本 速度 能力 适用场景
gpt-4o-mini 开发测试、简单任务
gpt-4o 生产环境、复杂推理
gpt-4-turbo 最高 高精度任务
gpt-3.5-turbo 最低 最快 大规模简单任务

使用示例

java 复制代码
// 开发环境
ChatLanguageModel devModel = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-4o-mini")
        .temperature(0.7)
        .build();

// 生产环境
ChatLanguageModel prodModel = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-4o")
        .temperature(0.3)
        .timeout(Duration.ofSeconds(60))
        .maxRetries(3)
        .logRequests(false)   // 生产环境关闭详细日志
        .logResponses(false)
        .build();

完整配置示例

java 复制代码
package dev.langchain4j.example;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

import java.time.Duration;

import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;

public class CompleteConfigExample {

    public static void main(String[] args) {

        ChatLanguageModel model = OpenAiChatModel.builder()
                // 基础配置
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName(GPT_4_O_MINI)

                // 生成参数
                .temperature(0.7)           // 创造性
                .topP(0.9)                  // 核采样
                .maxTokens(2000)            // 最大长度

                // 网络配置
                .timeout(Duration.ofSeconds(60))  // 超时
                .maxRetries(3)                     // 重试次数

                // 日志配置
                .logRequests(true)           // 记录请求
                .logResponses(true)          // 记录响应

                // 响应格式
                .responseFormat("json_object")  // JSON 模式

                .build();

        // 使用模型
        String response = model.generate("介绍一下 LangChain4j");
        System.out.println(response);
    }
}

性能优化建议

1. 批量处理

java 复制代码
List<String> questions = List.of("问题1", "问题2", "问题3");

// 不推荐:逐个调用
for (String question : questions) {
    String answer = model.generate(question);  // 每次都是独立请求
}

// 推荐:批量处理(如果支持)
List<ChatMessage> messages = questions.stream()
        .map(q -> UserMessage.from(q))
        .collect(Collectors.toList());

2. 缓存响应

java 复制代码
Map<String, String> cache = new ConcurrentHashMap<>();

String getCachedResponse(String prompt) {
    return cache.computeIfAbsent(prompt, p -> model.generate(p));
}

3. 并行请求

java 复制代码
ExecutorService executor = Executors.newFixedThreadPool(5);

List<CompletableFuture<String>> futures = questions.stream()
        .map(q -> CompletableFuture.supplyAsync(() -> model.generate(q), executor))
        .collect(Collectors.toList());

List<String> answers = futures.stream()
        .map(CompletableFuture::join)
        .collect(Collectors.toList());

常见问题

Q1: Temperature 和 Top P 应该如何搭配?

A: 通常只需要调整其中一个:

  • Temperature: 更直观,推荐使用
  • Top P: 更精细的控制
  • 不要同时设置极端值(如 temperature=2.0 + topP=0.1)

Q2: 如何处理速率限制?

A:

java 复制代码
// 使用指数退避重试
int maxRetries = 5;
for (int i = 0; i < maxRetries; i++) {
    try {
        return model.generate(prompt);
    } catch (Exception e) {
        if (e.getMessage().contains("rate limit") && i < maxRetries - 1) {
            Thread.sleep((long) Math.pow(2, i) * 1000);  // 1s, 2s, 4s, 8s, 16s
        } else {
            throw e;
        }
    }
}

Q3: 如何估算 Token 消耗?

A: 使用 Tokenizer:

java 复制代码
import dev.langchain4j.model.openai.OpenAiTokenizer;

Tokenizer tokenizer = new OpenAiTokenizer(GPT_4_O_MINI);
int tokenCount = tokenizer.estimateTokenCountInText("你好,世界!");
System.out.println("Token 数量: " + tokenCount);

下一步学习

参考资料

相关推荐
啥都不懂的小小白2 小时前
CyclicBarrier深度解析:Java中的“循环栅栏“同步工具
java·juc·cyclicbarrier
一路往蓝-Anbo2 小时前
【第14期】裸机中断优先级:抢占与嵌套的逻辑
c语言·开发语言·stm32·单片机·物联网
代码代码快快显灵2 小时前
Windows下Anaconda安装OpenCV以及OpenCV入门
图像处理·人工智能·opencv
码农进厂打螺丝2 小时前
Stable Diffusion 3.5 FP8:量化优化与部署实践
人工智能·计算机视觉·stable diffusion
Niuguangshuo2 小时前
DeepDream:窥视神经网络内部世界的梦幻之窗
人工智能·深度学习·神经网络
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于uni—app的民宿预订系统为例,包含答辩的问题和答案
java·eclipse
bjxiaxueliang2 小时前
一文详解Cpp多线程编程:从传统pthread到现代thread实践指南
java·开发语言·jvm
机智的人猿泰山2 小时前
spring boot 运行测试类时:Error creating bean with name ‘serverEndpointExporter‘ 问题
java·spring boot·后端
美狐美颜SDK开放平台2 小时前
实时直播场景下,美颜sdk美型功能开发的技术难点与解决思路
人工智能·美颜sdk·直播美颜sdk·美颜api·美狐美颜sdk