【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);

下一步学习

参考资料

相关推荐
敬往事一杯酒哈几秒前
OpenCV入门:第一章 图像的基本操作
人工智能
橘子hhh2 分钟前
Netty基础服务器实现
java·nio
咬_咬2 分钟前
go语言学习(数组与切片)
开发语言·学习·golang·数组·切片
小陈工4 分钟前
Python Web开发入门(十八):跨域问题解决方案——从“为什么我的请求被拦了“到“我让浏览器乖乖听话“
开发语言·python·机器学习·架构·数据挖掘·回归·状态模式
墨雪遗痕4 分钟前
工程架构认知(二):从 CDN 到 Keep-Alive,理解流量如何被“消化”在系统之外
java·spring·架构
m0_497214155 分钟前
Qt事件系统
开发语言·qt
AI科技星5 分钟前
全维度相对论推导、光速螺旋时空与北斗 GEO 钟差的统一理论
开发语言·线性代数·算法·机器学习·数学建模
Chef_Chen5 分钟前
Agent学习--LLM--推理熵
人工智能·学习·机器学习
小鹿软件办公6 分钟前
OpenAI 面向高频用户推出全新 100 美元档 ChatGPT Pro 套餐
人工智能·chatgpt
ECT-OS-JiuHuaShan9 分钟前
科学的本来意义,是基于规范的共识逻辑,而非共识方法
人工智能·科技·学习·算法·生活