简介
本章节主要介绍 java-openai(GitHub:litongjava/java-openai)库的核心能力、目录结构与统一调用方式,并展示如何将第三方大模型 API(OpenAI / Google / Anthropic / OpenRouter 等)以一致的请求与响应模型接入业务系统。
java-openai 的设计目标不是“只对接某一家模型厂商”,而是提供一套统一的抽象层:
- 业务侧只需要组装
UniChatRequest - 统一通过
UniChatClient发起调用 - 得到统一结构的
UniChatResponse - 底层根据平台与模型自动完成协议转换与返回结构归一化
- 同时支持非流式与流式文本输出,便于在 Web、SSE、WebSocket 等场景使用
快速入门
1. 添加依赖
<java.java-openai>1.2.6</java.java-openai>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>java-openai</artifactId>
<version>${java.java-openai}</version>
</dependency>
2. 最小可运行示例
下面示例使用 OpenRouter 平台 + 指定模型,通过统一接口请求并返回内容。
package com.litongjava.tio.web.hello.handler;
import java.util.ArrayList;
import java.util.List;
import com.litongjava.chat.PlatformInput;
import com.litongjava.chat.UniChatClient;
import com.litongjava.chat.UniChatMessage;
import com.litongjava.chat.UniChatRequest;
import com.litongjava.chat.UniChatResponse;
import com.litongjava.consts.ModelPlatformName;
import com.litongjava.openrouter.OpenRouterModels;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.handler.HttpRequestHandler;
public class PredictHandler implements HttpRequestHandler {
@Override
public HttpResponse handle(HttpRequest httpRequest) throws Exception {
PlatformInput platform = new PlatformInput(
ModelPlatformName.OPENROUTER,
OpenRouterModels.XIAOMI_MIMO_V2_FLASH_FREE
);
List<UniChatMessage> messges = new ArrayList<>();
messges.add(UniChatMessage.buildUser("just say hi"));
UniChatRequest uniChatRequest = new UniChatRequest(platform);
uniChatRequest.setMessages(messges);
UniChatResponse uniChatResponse = UniChatClient.generate(uniChatRequest);
String content = uniChatResponse.getMessage().getContent();
HttpResponse response = TioRequestContext.getResponse();
return response.setBody(content);
}
}
调用:
curl http://localhost/predict
可能输出:
Hi! I'm MiMo, Xiaomi's AI assistant. How can I help you today?
注意
{"error": {"code": 404, "message": "The free MiMo-V2-Flash period has ended. To continue using this model, please migrate to the paid slug: xiaomi/mimo-v2-flash"}, "user_id": "user_2whnYnpxFSlsBXAVMkR8Qc6XOUC"}
工程目录结构与模块说明
java-openai 按“平台/能力域”组织代码,每个目录大体代表一个厂商平台、一个能力模块或一个业务通用层。你给出的目录如下(节选说明):
chat统一聊天抽象层所在位置。通常包含:UniChatRequest / UniChatResponse等统一 DTOUniChatClient统一入口- 消息结构、流式 delta、usage 归一化等
openai/claude/gemini/google对应不同厂商协议与实现细节:- OpenAI 风格的 Chat/Responses
- Anthropic/Claude 风格的 messages / content blocks
- Google/Gemini 风格的 contents / parts 这些模块对上层隐藏协议差异,供
UniChatClient做自动转换与路由。
openrouter/groq/deepseek/moonshot/minimax/tencent/volcengine/byteplus/siliconflow/cerebras… 代表不同聚合平台或模型服务商的适配层,通常包含:- 模型常量(如
xxxModels) - API 地址与鉴权适配
- 请求/响应结构映射
- 模型常量(如
consts/exception/utils/vo/model基础设施与通用能力:- 常量与枚举(平台名、模型名等)
- 异常封装与错误处理
- 工具类(序列化、HTTP、签名、字符串等)
- 通用 VO 与数据模型
image/tts/fishaudio/textin多模态或特定能力域扩展:图像生成、语音合成、音频能力、OCR/文档等。search/searchapi/searxng/tavily/supadata与搜索/数据检索相关的能力与第三方服务整合,常用于:- 开启检索增强(RAG)
- 外部搜索工具调用
- 结果引用(citations)等
proxy/linux/libreoffice偏工程化、运行环境与系统工具集成的模块:- 代理与网络访问
- 服务器环境工具封装
- 文档转换等
promptPrompt 模板与提示词组织方式,通常用于统一系统提示词、模板复用与版本管理。mcp一般用于“工具协议/工具调用”的扩展模块(若你这里指的是 Model Context Protocol 或类似思想),用来把外部能力以统一方式暴露给模型或业务。
整体上可以理解为两层:
- 业务统一层:
chat(统一输入输出、统一调用方式) - 平台适配层:
openai/claude/gemini/openrouter/...(负责协议差异与细节)
UniChatRequest:统一请求结构
UniChatRequest 是业务侧与 UniChatClient 之间的统一契约。你可以把它当作“跨平台 Chat 请求 DTO”。
你给出的字段如下(节选):
public class UniChatRequest {
private String domain;
private Long groupId;
private String groupName;
private Long taskId;
private String taskName;
private String apiPrefixUrl;
private boolean useSystemPrompt = true;
private String apiKey;
private String platform;
private String model;
private String systemPrompt;;
private boolean cacheSystemPrompt;
private Boolean stream;
private List<UniChatMessage> messages;
private Float temperature;
private String cachedId;
private Integer max_tokens;
private Boolean enable_thinking;
private UniThinkingConfig thinkingConfig;
private String responseFormat;
private UniResponseSchema responseSchema;
private ChatProvider provider;
private List<String> responseModalities;
private Boolean enable_search;
}
1. 业务标识字段(不会发送给大模型)
以下字段仅用于业务表达与链路追踪,不会进入最终发给模型的 payload:
domaingroupIdgroupNametaskIdtaskName
典型用途包括:
- 多租户/多业务域隔离:按
domain做配置路由或日志分桶 - 分组维度统计:按
groupId/groupName汇总调用量、成本、成功率 - 任务维度管理:按
taskId/taskName关联某条业务流程(比如“客服质检”“合同摘要”“代码审查”) - 日志与审计:在不污染模型上下文的前提下,保留业务语义
2. 平台与鉴权
platform:平台标识(如 OpenAI / Google / Anthropic / OpenRouter 等)model:模型名或模型常量apiKey:平台 API KeyapiPrefixUrl:可选,自定义 API 前缀(私有化网关、代理、内网镜像等)provider:可选,某些平台下用于进一步指定提供方(例如聚合平台路由到具体供应商)
3. Prompt 与消息
useSystemPrompt:是否启用系统提示词systemPrompt:系统提示词内容cacheSystemPrompt:是否缓存系统提示词(用于减少重复传输或复用同一系统提示词配置)messages:对话消息列表(UniChatMessage),业务侧统一用它来表达 user/assistant/system/tool 等角色内容
4. 生成参数
temperature:随机性/发散程度max_tokens:最大输出 token 限制(不同平台命名不同,此处归一)responseFormat:响应格式类型(例如 text/json 等,按你内部枚举ChatResponseFormatType组织)responseSchema:当需要结构化输出时,可提供 schema(用于 JSON Schema 或类似约束)
5. 思考与推理控制(可选)
enable_thinkingthinkingConfig
用于对接支持“思考/推理配置”的平台或模型能力。即便底层不同平台字段不同,上层也仍然用统一开关与配置表达意图。
6. 流式与多模态/搜索(可选)
stream:是否流式输出 为true时,期望底层以 SSE/Chunked 等方式输出增量内容,并映射到统一的 delta 结构。responseModalities:期望的输出模态(例如仅文本,或文本+其他)enable_search:是否开启搜索能力(对接支持检索增强的供应商或你的search/*模块)
7. 缓存/复用(可选)
cachedId:用于复用某次缓存结果或上下文(具体语义由你的实现定义,比如命中缓存直接返回、或复用某个会话上下文)
UniChatResponse:统一响应结构
UniChatResponse 是 UniChatClient 的统一输出,屏蔽不同平台返回字段差异。
你给出的结构:
public class UniChatResponse {
private transient String rawData;
private String model;
private ChatResponseMessage message;
private ChatResponseDelta delta;
private ChatResponseUsage usage;
private List<String> citations;
}
逐字段说明:
rawData(transient) 原始响应字符串或原始数据快照,用于:- 调试与问题定位(查看平台原始返回)
- 线上故障回溯(但一般不参与序列化持久化)
model实际响应所使用的模型(部分平台可能会返回最终命中的模型名)message归一后的“完整消息结果”。非流式场景通常读取:uniChatResponse.getMessage().getContent()
delta用于流式场景的增量内容承载(一次 chunk/一次增量)。 在 SSE/WebSocket 场景中,你通常会不断拿到 delta 并拼接成完整文本。usagetoken 使用情况(输入/输出/总计等),用于成本统计、限额控制、计费等。citations引用列表,常见于:- 带搜索或检索增强的返回(RAG)
- 平台返回引用链接/来源片段 业务可以直接展示“参考来源”,或用于审计与可追溯性。
UniChatClient:统一入口与协议自动转换
UniChatClient 的核心价值是:业务只关心统一 DTO,不需要分别学习 OpenAI/Google/Anthropic 的协议细节。
它的行为可以概括为:
以
UniChatRequest作为唯一输入根据
platform + model (+ provider)做路由内部自动完成协议转换:
- 将
UniChatRequest/messages/systemPrompt/...映射为目标平台请求格式 - 调用对应平台 API
- 将目标平台响应映射回
UniChatResponse(message/delta/usage/citations 等统一结构)
- 将
支持的协议家族
按你要求,这里强调三类主协议:
- OpenAI 协议(OpenAI 风格 Chat/Responses)
- Google 协议(Gemini/Google 风格)
- Anthropic 协议(Claude 风格)
无论底层字段如何变化,业务侧都以 UniChatRequest 描述意图。
文本流式响应
除普通一次性返回外,UniChatClient 也支持文本的流式输出能力。典型用途:
- Web 前端逐字输出提升体验
- 长文本生成时尽早得到结果
- 降低超时风险并改善“首 token 延迟”
实现层面通常表现为:
uniChatRequest.setStream(true)- 服务端使用 SSE/Chunked/WebSocket 将 delta 持续推送给客户端
- 业务侧使用
UniChatResponse.delta拼接渲染,并在结束时读取 usage 等信息(具体以你的实现为准)
推荐使用方式与实践建议
- 业务侧统一只依赖
chat抽象层(UniChatRequest/Response/Client/Message),把平台差异留在java-openai内部。 - 为不同业务域设置
domain/groupId/taskId等标识,配合日志与用量统计做治理,但不要把这些字段塞进提示词。 - 对需要“稳定结构化输出”的场景(如抽取字段、生成 JSON、生成表格数据),优先使用
responseFormat/responseSchema,减少靠 prompt 约束带来的不确定性。 - 对交互型产品(聊天、写作助手、客服)优先考虑流式输出,显著提升体验。
