LangChain4j 教程

LangChain4j 的 ChatModel 接口

ChatModel 是 langchain4j 中所有聊天型大语言模型的顶层抽象接口,定义了与聊天模型交互的标准化方法,目的是屏蔽不同厂商模型(如 OpenAI ChatGPT、Google Gemini、本地开源模型)的调用差异,让你用统一的 API 就能对接不同的聊天模型。

简单来说:它是 langchain4j 中 “和聊天模型对话” 的通用契约,所有具体的聊天模型实现(如 OpenAiChatModel、GeminiChatModel)都必须遵守这个接口的规范。

接口 JavaDoc 文档地址:https://docs.langchain4j.dev/apidocs/dev/langchain4j/model/chat/ChatModel.html

什么是聊天大模型?

聊天大模型(Chat Large Language Model,Chat LLM)是基于大语言模型(LLM)优化的、专门用于自然对话交互的人工智能模型,核心目标是模拟人类的聊天逻辑,与用户进行连贯、有逻辑、上下文感知的自然语言交互。它是大语言模型的一个细分方向,聚焦 “对话场景” 的实用性优化,也是 LangChain4j 中 ChatModel 接口的核心适配对象。

本质上,底层基于 Transformer 架构(大语言模型的核心骨架),通过海量文本数据训练,掌握语言的语法、语义、逻辑关联甚至常识。

与传统 “问答模型”、“文本生成模型” 的核心区别:以 “对话” 为第一视角,支持多轮上下文理解、角色区分(用户 / 助手 / 系统)、自然话术生成(而非机械回答)。

🎉聊天大模型的核心价值在于 “模拟人类对话逻辑”,具体能力包括:

  • 多轮上下文理解:记住对话历史(如用户先问 “什么是 ChatGPT?”,再问 “它的核心架构是什么?”,模型能关联前序问题,不重复解释基础概念);

  • 角色与指令遵循:严格执行 “系统指令”(如 “用技术人员口吻回答”“限制在 50 字内”),区分用户与助手的角色边界;

  • 自然语言交互:支持口语化、模糊化提问(如 “这个东西怎么用啊?”,结合上下文能理解 “东西” 指的是某产品),回复不生硬;

  • 任务型对话支持:除了闲聊,还能完成结构化任务(如 “帮我整理会议纪要”、“写一段 Java 代码并解释”、“规划旅游路线”);

  • 常识与逻辑推理:基于训练数据中的常识和逻辑,回答非事实性问题(如 “为什么夏天比冬天热?”),或进行简单推理(如 “如果 A 大于 B,B 大于 C,A 和 C 谁大?”)。

🎉聊天大模型是目前 AI 落地最广泛的场景之一,核心应用包括:

  • 智能聊天机器人:客服机器人(如电商售后、银行咨询)、闲聊机器人(如社交 APP 陪聊);

  • AI 助手:个人助手(如 ChatGPT、文心一言)、工作助手(如代码生成、文档翻译、会议记录);

  • 嵌入式对话功能:APP / 网站的交互入口(如 “智能客服按钮”)、硬件设备的语音对话(如智能音箱、车载 AI);

  • 多轮任务协作:如 “帮我写一封邮件 → 修改语气更正式 → 生成英文版本”,模型能连贯完成多步骤指令。

🎉常见聊天模型如下:

  • 闭源商用模型:OpenAI GPT-3.5-turbo/GPT-4、Anthropic Claude 3、Google Gemini Pro、百度文心一言、阿里通义千问;

  • 开源模型:Llama 2(Meta)、Mistral 7B/8x7B、Qwen(阿里)、ChatGLM(智谱 AI);

ChatModel 接口定义

查看 ChatModel 接口的 JavaDoc 文档,你会发现,该接口所有方法都是 default(默认)方法,即子类可以不进行实现。

下面代码是可行的,不会报错,即使一个方法也没有实现:

import dev.langchain4j.model.chat.ChatModel;

public class MyChatModel implements ChatModel {
}

下面将分别介绍 ChatModel 各个方法作用于用法。

chat(ChatMessage... messages)  

该方法接收可变数量的 ChatMessage(聊天消息),构建多轮对话并获取响应。

示例代码:

package com.hxstrive.langchain4j.chatModel;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class ChatModelDemo {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                .logRequests(true)
                .logResponses(true)
                .build();

        // 构建多轮对话消息
        ChatMessage systemMsg = SystemMessage.from("你是一个Java编程助手");
        ChatMessage userMsg1 = UserMessage.from("什么是ChatModel?");
        ChatMessage assistantMsg1 = AiMessage.from("ChatModel是聊天模型的抽象接口");
        ChatMessage userMsg2 = UserMessage.from("它的核心方法有哪些?");

        // 调用chat方法(可变参数)
        ChatResponse response = chatModel.chat(systemMsg, userMsg1, assistantMsg1, userMsg2);
        System.out.println("回复内容:" + response.toBuilder().toString());
    }

}

上述代码中:

  • SystemMessage 表示系统消息

  • UserMessage 表示用户消息

  • AiMessage 表示 AI 回复的消息

chat(ChatRequest chatRequest)

该方法是与聊天模型交互的主 API。用来接收完整的 ChatRequest(聊天请求)对象,是最灵活的核心方法,支持自定义模型参数(温度、最大令牌数等)和上下文。注意,ChatRequest 参数封装了消息列表、模型参数、请求配置等信息。

示例代码:

package com.hxstrive.langchain4j.chatModel;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class ChatModelDemo {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                .logRequests(true)
                .logResponses(true)
                .build();

        // 构建多轮对话消息
        ChatMessage systemMsg = SystemMessage.from("你是一个Java编程助手");
        ChatMessage userMsg1 = UserMessage.from("什么是ChatModel?");
        ChatMessage assistantMsg1 = AiMessage.from("ChatModel是聊天模型的抽象接口");
        ChatMessage userMsg2 = UserMessage.from("它的核心方法有哪些?");

        // 调用chat方法(可变参数)
        ChatResponse response = chatModel.chat(systemMsg, userMsg1, assistantMsg1, userMsg2);
        System.out.println("回复内容:" + response.aiMessage().text());
    }

}

chat(String userMessage)

该方法提供了一个极简封装,直接接收用户消息字符串,底层自动封装为 UserMessage 和 ChatRequest。调用成功后,直接返回 AI 回复内容,而非 ChatResponse 对象。

示例代码:

package com.hxstrive.langchain4j.chatModel;

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

public class ChatModelDemo3 {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                .logRequests(true)
                .logResponses(true)
                .build();

        // 调用chat方法
        String response = chatModel.chat("什么是ChatModel?");
        System.out.println("回复内容:" + response);
    }

}

chat(List<ChatMessage> messages)

该方法接收 List<ChatMessage> 类型的消息列表。

示例代码:

package com.hxstrive.langchain4j.chatModel;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;

import java.util.List;

public class ChatModelDemo4 {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                .logRequests(true)
                .logResponses(true)
                .build();

        // 调用chat方法
        ChatResponse response = chatModel.chat(List.of(SystemMessage.from("你是一个Java编程助手"),
                UserMessage.from("什么是ChatModel?"),
                AiMessage.from("ChatModel是聊天模型的抽象接口"),
                UserMessage.from("它的核心方法有哪些?")));
        System.out.println("回复内容:" + response.aiMessage().text());
    }

}

doChat(ChatRequest chatRequest)

chat() 系列方法的底层实际调用的方法,是接口的“真正核心”,虽然也是 default 方法,但具体实现类会重写它。例如 OpenAiChatModel 会重写 doChat,实现与特定模型 API 的对接(发送请求、解析响应)。

下面是 OpenAiChatModel 对 doChat() 方法的实现:

public ChatResponse doChat(ChatRequest chatRequest) {
    // 将通用的聊天请求参数强转为 OpenAI 专属的参数对象
    OpenAiChatRequestParameters parameters = (OpenAiChatRequestParameters)chatRequest.parameters();
    // 验证 OpenAI 请求参数的合法性(如必填项、参数格式等)
    OpenAiUtils.validate(parameters);
    // 将业务层请求转换为 OpenAI SDK 所需的 ChatCompletionRequest
    ChatCompletionRequest openAiRequest = OpenAiUtils.toOpenAiChatRequest(chatRequest, parameters, this.sendThinking, 
        this.thinkingFieldName, this.strictTools, this.strictJsonSchema).build();
    // 捕获并映射异常,最多重试 maxRetries 次
    ParsedAndRawResponse<ChatCompletionResponse> parsedAndRawResponse = (ParsedAndRawResponse)RetryUtils.withRetryMappingExceptions(() -> {
        return this.client.chatCompletion(openAiRequest).executeRaw();
    }, this.maxRetries);
    // 提取解析后的 OpenAI 响应结果
    ChatCompletionResponse openAiResponse = (ChatCompletionResponse)parsedAndRawResponse.parsedResponse();
    // 封装 OpenAI 返回的核心元信息(ID、模型名、token 使用量、结束原因等)
    OpenAiChatResponseMetadata responseMetadata = (
            (OpenAiChatResponseMetadata.Builder)(
                (OpenAiChatResponseMetadata.Builder)(
                    (OpenAiChatResponseMetadata.Builder)(
                        (OpenAiChatResponseMetadata.Builder)OpenAiChatResponseMetadata.builder().id(openAiResponse.id())
                    ).modelName(openAiResponse.model())
                ).tokenUsage(OpenAiUtils.tokenUsageFrom(openAiResponse.usage()))
            ).finishReason(OpenAiUtils.finishReasonFrom(((ChatCompletionChoice)openAiResponse.choices().get(0)).finishReason()))
        ).created(openAiResponse.created())
            .serviceTier(openAiResponse.serviceTier())
            .systemFingerprint(openAiResponse.systemFingerprint())
            .rawHttpResponse(parsedAndRawResponse.rawHttpResponse()).build();
    // 整合 AI 回复消息和元数据,构建业务层统一的 ChatResponse
    return ChatResponse.builder().aiMessage(OpenAiUtils.aiMessageFrom(openAiResponse, this.returnThinking))
        .metadata(responseMetadata).build();
}

defaultRequestParameters()

该方法用来获取该 ChatModel 的默认请求参数,如默认温度、最大令牌数、顶会惩罚等。返回值 ChatRequestParameters 封装了所有模型参数的对象。

示例代码:

package com.hxstrive.langchain4j.chatModel;

import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.request.ChatRequestParameters;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class ChatModelDemo5 {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                .logRequests(true)
                .logResponses(true)
                .build();

        // 获取默认参数
        ChatRequestParameters parameters = chatModel.defaultRequestParameters();
        System.out.println("模型名称:" + parameters.modelName());
        System.out.println("最大输出Token:" + parameters.maxOutputTokens());
        System.out.println("温度值:" + parameters.temperature());
        System.out.println("TopP值:" + parameters.topP());
    }

}

listeners()

该方法用来获取该 ChatModel 注册的所有监听器(ChatModelListener)。

ChatModelListener 是 LangChain4j 提供的一个监听器接口,主要用于监听 ChatModel(聊天模型)的完整交互生命周期,包括请求发送前、响应返回后、异常发生时等关键节点。通过实现这个接口,你可以轻松实现:

  • 日志记录(如记录请求 / 响应内容、耗时)

  • 性能监控(统计接口响应时间)

  • 请求 / 响应修改(如统一添加提示词、过滤敏感响应)

  • 异常捕获与处理(自定义异常逻辑)

  • 数据埋点 / 审计(合规记录交互内容)

示例代码:

package com.hxstrive.langchain4j.chatModel;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.listener.ChatModelErrorContext;
import dev.langchain4j.model.chat.listener.ChatModelListener;
import dev.langchain4j.model.chat.listener.ChatModelRequestContext;
import dev.langchain4j.model.chat.listener.ChatModelResponseContext;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;

import java.util.List;
import java.util.Optional;

public class ChatModelDemo6 {
    // 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
    // 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
    private static final String API_KEY = System.getenv("OPEN_API_KEY");

    public static void main(String[] args) {
        // 创建 ChatModel 实现类(OpenAI 为例)
        ChatModel chatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.xty.app/v1")
                .apiKey(API_KEY)
                .modelName("gpt-3.5-turbo")
                .temperature(0.7)
                // 注册监听器
                .listeners(List.of(new ChatModelListener() {
                    @Override
                    public void onRequest(ChatModelRequestContext requestContext) {
                        Optional.ofNullable(requestContext.chatRequest().messages()).ifPresent(chatMessages -> {
                            chatMessages.forEach(chatMessage -> {
                                System.out.println("请求内容:" + chatMessage.toString());
                            });
                        });
                    }

                    @Override
                    public void onResponse(ChatModelResponseContext responseContext) {
                        System.out.println("响应内容:" + responseContext.chatResponse().aiMessage().text());
                    }

                    @Override
                    public void onError(ChatModelErrorContext errorContext) {
                        System.out.println("错误信息:" + errorContext.error());
                    }
                }))
                .logRequests(true)
                .logResponses(true)
                .build();

        // 获取监听器
        List<ChatModelListener> listeners = chatModel.listeners();
        System.out.println("监听器数量:" + listeners.size());

        // 调用chat方法
        ChatResponse response = chatModel.chat(List.of(SystemMessage.from("你是一个Java编程助手"),
                UserMessage.from("什么是ChatModel?"),
                AiMessage.from("ChatModel是聊天模型的抽象接口"),
                UserMessage.from("它的核心方法有哪些?")));
        System.out.println("回复内容:" + response.aiMessage().text());
    }

}

执行示例,输出如下:

监听器数量:1
请求内容:SystemMessage { text = "你是一个Java编程助手" }
请求内容:UserMessage { name = null, contents = [TextContent { text = "什么是ChatModel?" }], attributes = {} }
请求内容:AiMessage { text = "ChatModel是聊天模型的抽象接口", thinking = null, toolExecutionRequests = [], attributes = {} }
请求内容:UserMessage { name = null, contents = [TextContent { text = "它的核心方法有哪些?" }], attributes = {} }
16:23:25.213 [main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP request:
- method: POST
- url: https://api.xty.app/v1/chat/completions
- headers: [Authorization: Beare...00], [User-Agent: langchain4j-openai], [Content-Type: application/json]
- body: {
  "model" : "gpt-3.5-turbo",
  "messages" : [ {
    "role" : "system",
    "content" : "你是一个Java编程助手"
  }, {
    "role" : "user",
    "content" : "什么是ChatModel?"
  }, {
    "role" : "assistant",
    "content" : "ChatModel是聊天模型的抽象接口"
  }, {
    "role" : "user",
    "content" : "它的核心方法有哪些?"
  } ],
  "temperature" : 0.7,
  "stream" : false
}
....

provider()

该方法用来获取该 ChatModel 对应的模型提供商(如 OpenAI、Anthropic、Google 等)。

返回值 ModelProvider 是一个枚举类型,包含 OPENAI、ANTHROPIC、GOOGLE、LOCAL 等值。

使用场景:

  • 运行时判断当前使用的模型提供商;

  • 针对不同提供商做差异化逻辑处理。

supportedCapabilities()

该方法获取该 ChatModel 支持的能力集(Capability)。应用可在运行时判断模型能力,避免调用不支持的功能(如给不支持流式的模型调用 stream 方法)。

源码分析

看看 ChatModel 接口源码:

public interface ChatModel {

    // 其他非 ChatRequest 参数的 chat() 方法调用该方法实现其功能
    default ChatResponse chat(ChatRequest chatRequest) {
        ChatRequest finalChatRequest = ChatRequest.builder().messages(chatRequest.messages()).parameters(this.defaultRequestParameters().overrideWith(chatRequest.parameters())).build();
        List<ChatModelListener> listeners = this.listeners();
        Map<Object, Object> attributes = new ConcurrentHashMap();
        ChatModelListenerUtils.onRequest(finalChatRequest, this.provider(), attributes, listeners);

        try {
            ChatResponse chatResponse = this.doChat(finalChatRequest); // 调用 doChat() 方法实现聊天功能
            ChatModelListenerUtils.onResponse(chatResponse, finalChatRequest, this.provider(), attributes, listeners);
            return chatResponse;
        } catch (Exception var6) {
            ChatModelListenerUtils.onError(var6, finalChatRequest, this.provider(), attributes, listeners);
            throw var6;
        }
    }

    // 由子类去实现
    // 子类仅仅实现该方法就可以了,其他chat()类型的方法已经有默认实现
    default ChatResponse doChat(ChatRequest chatRequest) {
        throw new RuntimeException("Not implemented");
    }

    // 去除非 chat() 系列方法

    default String chat(String userMessage) {
        ChatRequest chatRequest = ChatRequest.builder().messages(new ChatMessage[]{UserMessage.from(userMessage)}).build();
        ChatResponse chatResponse = this.chat(chatRequest);
        return chatResponse.aiMessage().text();
    }

    default ChatResponse chat(ChatMessage... messages) {
        ChatRequest chatRequest = ChatRequest.builder().messages(messages).build();
        return this.chat(chatRequest);
    }

    default ChatResponse chat(List<ChatMessage> messages) {
        ChatRequest chatRequest = ChatRequest.builder().messages(messages).build();
        return this.chat(chatRequest);
    }

    // 去除非 chat() 系列方法
}

默认方法(也叫扩展方法)是 Java 8 引入的特性,允许在接口(Interface) 中定义带有方法体的方法,并用 default 关键字修饰。

在 Java 8 之前,接口只能定义抽象方法(无方法体),如果给接口新增一个方法,所有实现该接口的类都必须强制实现这个新方法,这会导致:

  • 对已有代码的侵入性极强(比如修改 JDK 核心接口时,所有第三方实现类都要改);

  • 接口无法向后兼容。

默认方法的出现,让接口可以“无痛扩展”—— 新增的默认方法有默认实现,实现类可以选择重写,也可以直接继承这个默认实现。


说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号