# openai-sdk-java **Repository Path**: longlongqin/openai-sdk-java ## Basic Information - **Project Name**: openai-sdk-java - **Description**: 小傅哥的开源项目:https://gitcode.net/KnowledgePlanet/open-hub/openai-sdk-java - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-03-06 - **Last Updated**: 2024-03-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # openai-sdk-java —— 统一大模型对接 SDK 设计实现 星球开源共建项目 **《OpenAI SDK》** 统一大模型标准化对接的技术组件项目,此项目以解决实际市面上的场景为诉求,将 OpenAI、Claude、PalM、文心一言、通义千问、讯飞星火、智谱 ChatGLM、腾讯混元等这些大模型做一个统一的 SDK 对接组件。 ## 一、发布记录 - 1.2 支持 ChatGPT、ChatGLM、讯飞星火 - 1.3 阿里通义千问 [@Vanffer](https://gitcode.net/weixin_60954617) ## 二、安装使用 ```pom cn.bugstack openai-sdk-java 1.3 ``` - [https://central.sonatype.com/artifact/cn.bugstack/openai-sdk-java](https://central.sonatype.com/artifact/cn.bugstack/openai-sdk-java) - 在系统中引入 POM 并入 ApiTest 创建使用。 ### 1. 单元测试 #### 1.1 阿里通义千问 ```java @Slf4j public class AliYunTest { private OpenAiSession openAiSession; @Before public void test_OpenAiSessionFactory() throws IOException { // 0. 注意;将 resources 包下的 .env修改为 .env.local 并添加各项配置 Properties prop = new Properties(); prop.load(ApiTest.class.getClassLoader().getResourceAsStream(".env.local")); AliModelConfig aliModelConfig = new AliModelConfig(); aliModelConfig.setApiHost(prop.getProperty("ali.config.alihost")); aliModelConfig.setApiKey(prop.getProperty("ali.config.apikey")); // 2. 配置文件 Configuration configuration = new Configuration(); configuration.setLevel(HttpLoggingInterceptor.Level.HEADERS); configuration.setAliModelConfig(aliModelConfig); // 3. 会话工厂 OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration); // 4. 开启会话 this.openAiSession = factory.openSession(); } /** * 文本 & 流式对话;选择不同的模型测试 GPT_3_5_TURBO、GPT_3_5_TURBO_1106、GPT_3_5_TURBO_16K、GPT_4、CHATGLM_TURBO */ @Test public void test_completions() throws Exception { // 1. 创建参数 CompletionRequest request = CompletionRequest.builder() .stream(true) .messages(Collections.singletonList(Message.builder().role(CompletionRequest.Role.USER).content("1+1").build())) .model(CompletionRequest.Model.QWEN_TURBO.getCode()) .build(); // 2. 请求等待 CountDownLatch countDownLatch = new CountDownLatch(1); // 3. 应答请求 EventSource eventSource = openAiSession.completions(request, new EventSourceListener() { @Override public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) { if ("[DONE]".equalsIgnoreCase(data)) { log.info("OpenAI 应答完成"); return; } CompletionResponse chatCompletionResponse = JSON.parseObject(data, CompletionResponse.class); List choices = chatCompletionResponse.getChoices(); for (ChatChoice chatChoice : choices) { Message delta = chatChoice.getDelta(); if (CompletionRequest.Role.ASSISTANT.getCode().equals(delta.getRole())) continue; // 应答完成 String finishReason = chatChoice.getFinishReason(); if (StringUtils.isNoneBlank(finishReason) && "stop".equalsIgnoreCase(finishReason)) { return; } log.info("测试结果:{}", delta.getContent()); } } @Override public void onClosed(EventSource eventSource) { log.info("对话完成"); countDownLatch.countDown(); } @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { log.info("对话异常"); countDownLatch.countDown(); } }); countDownLatch.await(); } } ``` #### 1.2 ChatGLM ```java @Slf4j public class ChatGLMTest { private OpenAiSession openAiSession; @Before public void test_OpenAiSessionFactory() throws IOException { // 0. 注意;将 resources 包下的 .env修改为 .env.local 并添加各项配置 Properties prop = new Properties(); prop.load(ApiTest.class.getClassLoader().getResourceAsStream(".env.local")); ChatGLMConfig chatGLMConfig = new ChatGLMConfig(); chatGLMConfig.setApiHost(prop.getProperty("chatglm.config.apihost")); chatGLMConfig.setApiSecretKey(prop.getProperty("chatglm.config.apisecretkey")); // 2. 配置文件 Configuration configuration = new Configuration(); configuration.setLevel(HttpLoggingInterceptor.Level.HEADERS); configuration.setChatGLMConfig(chatGLMConfig); // 3. 会话工厂 OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration); // 4. 开启会话 this.openAiSession = factory.openSession(); } /** * 文本 & 流式对话;选择不同的模型测试 GPT_3_5_TURBO、GPT_3_5_TURBO_1106、GPT_3_5_TURBO_16K、GPT_4、CHATGLM_TURBO */ @Test public void test_completions() throws Exception { // 1. 创建参数 CompletionRequest request = CompletionRequest.builder() .stream(true) .messages(Collections.singletonList(Message.builder().role(CompletionRequest.Role.USER).content("1+1").build())) .model(CompletionRequest.Model.CHATGLM_TURBO.getCode()) .build(); // 2. 请求等待 CountDownLatch countDownLatch = new CountDownLatch(1); // 3. 应答请求 EventSource eventSource = openAiSession.completions(request, new EventSourceListener() { @Override public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) { if ("[DONE]".equalsIgnoreCase(data)) { log.info("OpenAI 应答完成"); return; } CompletionResponse chatCompletionResponse = JSON.parseObject(data, CompletionResponse.class); List choices = chatCompletionResponse.getChoices(); for (ChatChoice chatChoice : choices) { Message delta = chatChoice.getDelta(); if (CompletionRequest.Role.ASSISTANT.getCode().equals(delta.getRole())) continue; // 应答完成 String finishReason = chatChoice.getFinishReason(); if (StringUtils.isNoneBlank(finishReason) && "stop".equalsIgnoreCase(finishReason)) { return; } log.info("测试结果:{}", delta.getContent()); } } @Override public void onClosed(EventSource eventSource) { log.info("对话完成"); countDownLatch.countDown(); } @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { log.info("对话异常"); countDownLatch.countDown(); } }); countDownLatch.await(); } } ``` #### 1.3 ChatGPT ```java @Slf4j public class ChatGPTTest { private OpenAiSession openAiSession; @Before public void test_OpenAiSessionFactory() throws IOException { // 0. 注意;将 resources 包下的 .env修改为 .env.local 并添加各项配置 Properties prop = new Properties(); prop.load(ApiTest.class.getClassLoader().getResourceAsStream(".env.local")); ChatGPTConfig chatGPTConfig = new ChatGPTConfig(); chatGPTConfig.setApiHost(prop.getProperty("chatgpt.config.apihost")); chatGPTConfig.setApiKey(prop.getProperty("chatgpt.config.apikey")); // 2. 配置文件 Configuration configuration = new Configuration(); configuration.setLevel(HttpLoggingInterceptor.Level.HEADERS); configuration.setChatGPTConfig(chatGPTConfig); // 3. 会话工厂 OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration); // 4. 开启会话 this.openAiSession = factory.openSession(); } /** * 文本 & 流式对话;选择不同的模型测试 GPT_3_5_TURBO、GPT_3_5_TURBO_1106、GPT_3_5_TURBO_16K、GPT_4、CHATGLM_TURBO */ @Test public void test_completions() throws Exception { // 1. 创建参数 CompletionRequest request = CompletionRequest.builder() .stream(true) .messages(Collections.singletonList(Message.builder().role(CompletionRequest.Role.USER).content("1+1").build())) .model(CompletionRequest.Model.GPT_3_5_TURBO_1106.getCode()) .build(); // 2. 请求等待 CountDownLatch countDownLatch = new CountDownLatch(1); // 3. 应答请求 EventSource eventSource = openAiSession.completions(request, new EventSourceListener() { @Override public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) { if ("[DONE]".equalsIgnoreCase(data)) { log.info("OpenAI 应答完成"); return; } CompletionResponse chatCompletionResponse = JSON.parseObject(data, CompletionResponse.class); List choices = chatCompletionResponse.getChoices(); for (ChatChoice chatChoice : choices) { Message delta = chatChoice.getDelta(); if (CompletionRequest.Role.ASSISTANT.getCode().equals(delta.getRole())) continue; // 应答完成 String finishReason = chatChoice.getFinishReason(); if (StringUtils.isNoneBlank(finishReason) && "stop".equalsIgnoreCase(finishReason)) { return; } log.info("测试结果:{}", delta.getContent()); } } @Override public void onClosed(EventSource eventSource) { log.info("对话完成"); countDownLatch.countDown(); } @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { log.info("对话异常"); countDownLatch.countDown(); } }); countDownLatch.await(); } } ``` #### 1.4 讯飞星火 ```java @Slf4j public class XunFeiTest { private OpenAiSession openAiSession; @Before public void test_OpenAiSessionFactory() throws IOException { // 0. 注意;将 resources 包下的 .env修改为 .env.local 并添加各项配置 Properties prop = new Properties(); prop.load(ApiTest.class.getClassLoader().getResourceAsStream(".env.local")); XunFeiConfig xunFeiConfig = new XunFeiConfig(); xunFeiConfig.setApiHost(prop.getProperty("xunfei.config.apihost")); xunFeiConfig.setAppid(prop.getProperty("xunfei.config.apiappid")); xunFeiConfig.setApiKey(prop.getProperty("xunfei.config.apiapikey")); xunFeiConfig.setApiSecret(prop.getProperty("xunfei.config.apiapisecret")); // 2. 配置文件 Configuration configuration = new Configuration(); configuration.setLevel(HttpLoggingInterceptor.Level.HEADERS); configuration.setXunFeiConfig(xunFeiConfig); // 3. 会话工厂 OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration); // 4. 开启会话 this.openAiSession = factory.openSession(); } /** * 文本 & 流式对话;选择不同的模型测试 GPT_3_5_TURBO、GPT_3_5_TURBO_1106、GPT_3_5_TURBO_16K、GPT_4、CHATGLM_TURBO */ @Test public void test_completions() throws Exception { // 1. 创建参数 CompletionRequest request = CompletionRequest.builder() .stream(true) .messages(Collections.singletonList(Message.builder().role(CompletionRequest.Role.USER).content("1+1").build())) .model(CompletionRequest.Model.XUNFEI.getCode()) .build(); // 2. 请求等待 CountDownLatch countDownLatch = new CountDownLatch(1); // 3. 应答请求 EventSource eventSource = openAiSession.completions(request, new EventSourceListener() { @Override public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) { if ("[DONE]".equalsIgnoreCase(data)) { log.info("OpenAI 应答完成"); return; } CompletionResponse chatCompletionResponse = JSON.parseObject(data, CompletionResponse.class); List choices = chatCompletionResponse.getChoices(); for (ChatChoice chatChoice : choices) { Message delta = chatChoice.getDelta(); if (CompletionRequest.Role.ASSISTANT.getCode().equals(delta.getRole())) continue; // 应答完成 String finishReason = chatChoice.getFinishReason(); if (StringUtils.isNoneBlank(finishReason) && "stop".equalsIgnoreCase(finishReason)) { return; } log.info("测试结果:{}", delta.getContent()); } } @Override public void onClosed(EventSource eventSource) { log.info("对话完成"); countDownLatch.countDown(); } @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { log.info("对话异常"); countDownLatch.countDown(); } }); countDownLatch.await(); } } ``` ### 2. 应用接入 ## 3. 程序接入 yml 配置 ```pom # OpenAi 配置;ChatGPT、ChatGLM... openai: sdk: config: chatglm: # 状态;true = 开启、false 关闭 enabled: false # 官网地址 api-host: https://open.bigmodel.cn/ # 官网申请 https://open.bigmodel.cn/usercenter/apikeys api-secret-key: 4e087e4135306ef4a676f0cce3cee560.sgP2DUs***** ``` SpringBoot 配置类 ```java @Configuration @EnableConfigurationProperties(OpenAISDKConfigProperties.class) public class OpenAISDKConfig { @Bean @ConditionalOnProperty(value = "openai.sdk.config.enabled", havingValue = "true", matchIfMissing = false) public OpenAiSession openAiSession(OpenAISDKConfigProperties properties) { // 1. 配置文件 Configuration configuration = new Configuration(); // 添加配置 // 2. 会话工厂 OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration); // 3. 开启会话 return factory.openSession(); } } @Data @ConfigurationProperties(prefix = "openai.sdk.config", ignoreInvalidFields = true) public class ChatGLMSDKConfigProperties { /** 添加 ChatGPT、ChatGLM 等 */ private ChatGPTConfig chatGPTConfig; private ChatGLMConfig chatGLMConfig; } ``` ```java @Autowired(required = false) private OpenAiSession openAiSession; ``` ## 三、对接计划 - [x] [OpenAI ChatGPT 系列模型](https://platform.openai.com/) - [x] [阿里通义千问系列模型](https://help.aliyun.com/document_detail/2400395.html) - [x] [讯飞星火认知大模型](https://www.xfyun.cn/doc/spark/Web.html) - [x] [智谱 ChatGLM 系列模型](https://bigmodel.cn/) - [ ] [Anthropic Claude 系列模型](https://www.anthropic.com/) - [ ] [Google PaLM2 系列模型](https://developers.generativeai.google/) - [ ] [百度文心一言系列模型](https://cloud.baidu.com/doc/WENXINWORKSHOP/index.html) - [ ] [360 智脑](https://ai.360.cn/) - [ ] [腾讯混元大模型](https://cloud.tencent.com/document/product/1729) ## 四、开发规范 1. 打开地址 [openai-sdk-java](https://gitcode.net/KnowledgePlanet/open-hub/openai-sdk-java) Fork 代码到自己的仓库 2. 熟悉工程模型和代码,并调试运行理解整个框架的设计实现。之后开始承接需求并提交代码到自己的仓库。对于自己已经完成运行的调试的代码,可以提交 PR 代码。小傅哥在评审后,会合并你的提交。这样你就成为一个贡献者了,并记录在文档。 3. 修改 .env 为 .env.local 并配置相关的信息,就可以在 ApiTest 中调试了。 ```java # 主要type feat: 增加新功能 fix: 修复bug # 特殊type docs: 只改动了文档相关的内容 style: 不影响代码含义的改动,例如去掉空格、改变缩进、增删分号 build: 构造工具的或者外部依赖的改动,例如webpack,npm refactor: 代码重构时使用 revert: 执行git revert打印的message # 暂不使用type test: 添加测试或者修改现有测试 perf: 提高性能的改动 ci: 与CI(持续集成服务)有关的改动 chore: 不修改src或者test的其余修改,例如构建过程或辅助工具的变动 ``` ## 五、需求开发 1. 【简单】工程中有标记 `TODO` 标签待开发点,此类的功能比如在A模型中实现了,B、C 模型未实现,可以参考代码开发。 2. 【中等】阅读模型API文档,补全功能。这部分会从会话的调用,一直到执行器包下对应的实现,开发具体实现。 3. 【复杂】对未实现对接的模型,阅读API文档,添加对接。 --- 以上开发内容,小傅哥会陆续的提交代码,你可以赶在我的前面实现,这样可以很好和我的开发进行对比,学习设计思想和落地实现。 ## 六、其他资料 - https://gpgtools.org/ - brew install gpg - https://issues.sonatype.org/browse/OSSRH-97151 - https://central.sonatype.org/publish/publish-maven/#javadoc-and-sources-attachments