OpenAI模块重构

ops/2025/2/1 8:57:00/

文章目录

    • 1.common-openai-starter
        • 1.目录结构
        • 2.OpenAiProperties.java 新增apiUrl
        • 3.OpenAIAutoConfiguration.java
        • 4.OpenAiClient.java 使用gson重构
    • 2.common-openai-starter-demo
        • 1.目录结构
        • 2.application.yml 新增api-url
        • 3.OpenAiController.java
        • 4.OpenAiApplication.java
        • 5.测试

openaistarter_2">1.common-openai-starter

1.目录结构

CleanShot 2025-01-02 at 16.40.21@2x

2.OpenAiProperties.java 新增apiUrl
package com.sunxiansheng.openai.config.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** Description: OpenAI配置属性类** @Author sun* @Create 2024/12/14 11:44* @Version 1.0*/
@Data
@ConfigurationProperties(prefix = "openai")
public class OpenAiProperties {/*** OpenAI API Key*/private String apiKey;/*** OpenAI API URL 有默认值*/private String apiUrl = "https://api.openai.com/v1/chat/completions";
}
3.OpenAIAutoConfiguration.java
package com.sunxiansheng.openai.config;import com.sunxiansheng.openai.client.OpenAiClient;
import com.sunxiansheng.openai.config.properties.OpenAiProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Description: OpenAI自动配置类** @Author sun* @Create 2024/12/14 11:39* @Version 1.0*/
@Configuration
@EnableConfigurationProperties({OpenAiProperties.class}) // 启用配置类
public class OpenAIAutoConfiguration {/*** 创建 OpenAiClient** @return*/@Bean@ConditionalOnMissingBeanpublic OpenAiClient openAiClient() {return new OpenAiClient();}
}
4.OpenAiClient.java 使用gson重构
package com.sunxiansheng.openai.client;import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sunxiansheng.openai.config.properties.OpenAiProperties;
import okhttp3.*;import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;/*** Description: OpenAI 客户端类** @Author sun* @Create 2024/12/14 11:56* @Version 1.1*/
public class OpenAiClient {@Resourceprivate OpenAiProperties openAiProperties;private static final OkHttpClient CLIENT = new OkHttpClient.Builder().connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS).writeTimeout(120, TimeUnit.SECONDS).build();private static final Logger LOGGER = Logger.getLogger(OpenAiClient.class.getName());/*** 向 AI 提问通用方法** @param model        使用的 AI 模型,如 "gpt-4o"* @param prompt       提示内容* @param base64Encode 是否对内容进行 Base64 编码* @return AI 的响应内容*/public String askAI(String model, String prompt, boolean base64Encode) {try {// 处理 Base64 编码String encodedPrompt = base64Encode ? encodeBase64(prompt) : prompt;// 构造请求体RequestBody body = RequestBody.create(createJsonRequest(model, encodedPrompt), MediaType.get("application/json; charset=utf-8"));// 构建请求Request request = new Request.Builder().url(openAiProperties.getApiUrl()).header("Authorization", "Bearer " + openAiProperties.getApiKey()).header("Content-Type", "application/json").post(body).build();// 发送请求并获取响应try (Response response = CLIENT.newCall(request).execute()) {if (!response.isSuccessful()) {throw new IOException("Unexpected response: " + response);}// 解析 JSON 响应return parseResponse(response.body().string());}} catch (IOException e) {LOGGER.log(Level.SEVERE, "Error occurred during API request: " + e.getMessage(), e);throw new RuntimeException("API request failed", e);}}/*** 对输入内容进行 Base64 编码** @param prompt 输入内容* @return 编码后的字符串*/private String encodeBase64(String prompt) {return Base64.getEncoder().encodeToString(prompt.getBytes(StandardCharsets.UTF_8));}/*** 构建请求的 JSON 数据** @param model         使用的 AI 模型* @param encodedPrompt 编码后的输入内容* @return 构建好的 JSON 字符串*/private String createJsonRequest(String model, String encodedPrompt) {JsonObject jsonRequest = new JsonObject();jsonRequest.addProperty("model", model);JsonArray messages = new JsonArray();// 添加 system 信息JsonObject systemMessage = new JsonObject();systemMessage.addProperty("role", "system");systemMessage.addProperty("content", "请根据以下内容提供问题的解决方案。使用中文回答,不要使用markdown语法和特殊符号**之类的,注意,内容可能经过 Base64 编码。");messages.add(systemMessage);// 添加 user 信息JsonObject userMessage = new JsonObject();userMessage.addProperty("role", "user");userMessage.addProperty("content", encodedPrompt);messages.add(userMessage);jsonRequest.add("messages", messages);return jsonRequest.toString();}/*** 解析 API 响应内容** @param responseBody 响应的 JSON 内容* @return 解析后的结果*/private String parseResponse(String responseBody) {JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();JsonArray choices = jsonObject.getAsJsonArray("choices");if (choices != null && choices.size() > 0) {JsonObject choice = choices.get(0).getAsJsonObject();JsonObject message = choice.getAsJsonObject("message");return message.get("content").getAsString();}throw new RuntimeException("Invalid response: No choices found.");}
}

openaistarterdemo_216">2.common-openai-starter-demo

1.目录结构

CleanShot 2025-01-02 at 16.47.19@2x

2.application.yml 新增api-url
openai:api-key: guest # 必填,OpenAI API Keyapi-url: https://api.openai.com/v1/chat/completions # 可选,有默认值,为了防止以后 URL 变化
3.OpenAiController.java
package com.sunxiansheng.openai.controller;import com.sunxiansheng.openai.client.OpenAiClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** Description: OpenAI 控制器类** @Author sun* @Create 2024/12/14 12:27* @Version 1.0*/
@RestController
public class OpenAiController {@Resourceprivate OpenAiClient openAiClient;@RequestMapping("/ask")public String ask(String question) {String res = openAiClient.askAI("gpt-4o", question, false);return "AI回答:" + res;}
}
4.OpenAiApplication.java
package com.sunxiansheng.openai;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: OpenAI启动类** @Author sun* @Create 2024/12/14 12:23* @Version 1.0*/
@SpringBootApplication
public class OpenAiApplication {public static void main(String[] args) {SpringApplication.run(OpenAiApplication.class, args);}
}
5.测试

CleanShot 2025-01-02 at 16.48.52@2x


http://www.ppmy.cn/ops/154700.html

相关文章

青少年编程与数学 02-008 Pyhon语言编程基础 03课题、环境准备

青少年编程与数学 02-008 Pyhon语言编程基础 03课题、环境准备 一、开发环境二、PyCharm安装 PyCharm配置 PyCharm 三、VS Code安装 VS Code配置 VS Code 四、Python (解释器)Windows系统:macOS系统:Linux系统: 五、Py…

Linux:线程池和单例模式

一、普通线程池 1.1 线程池概念 线程池:一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价&…

【4Day创客实践入门教程】Day3 实战演练——桌面迷你番茄钟

Day3 实战演练——桌面迷你番茄钟 目录 Day3 实战演练——桌面迷你番茄钟1. 选择、准备元件、收集资料2. 硬件搭建3.编写代码 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟…

Windows中本地组策略编辑器gpedit.msc打不开/微软远程桌面无法复制粘贴

目录 背景 解决gpedit.msc打不开 解决复制粘贴 剪贴板的问题 启用远程桌面剪贴板与驱动器 重启RDP剪贴板监视程序 以上都不行?可能是操作被Win11系统阻止 最后 背景 远程桌面无法复制粘贴,需要查看下主机策略组设置,结果按WinR输入…

【算法】动态规划专题① ——线性DP python

目录 引入简单实现稍加变形举一反三实战演练总结 引入 楼梯有个台阶,每次可以一步上1阶或2阶。一共有多少种不同的上楼方法? 怎么去思考? 假设就只有1个台阶,走法只有:1 只有2台阶: 11,2 只有3台…

计算机毕业设计Django+Tensorflow音乐推荐系统 机器学习 深度学习 音乐可视化 音乐爬虫 知识图谱 混合神经网络推荐算法 大数据毕设

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

科家多功能美发梳:科技赋能,重塑秀发新生

在繁忙的都市生活中,头皮健康与秀发养护成为了现代人不可忽视的日常课题。近日,科家电动按摩梳以其卓越的性能和创新设计,赢得了广大消费者的青睐。这款集科技与美学于一身的美发梳,不仅搭载了2亿负离子、6000次/分钟的声波振动等前沿技术,更融入了650nm聚能环红光与415nm强劲蓝…

蓝桥杯python语言基础(1)——编程基础

目录 一、python开发环境 二、python输入输出 (1)print输出函数 print(*object,sep,end\n,......) (2)input输入函数 input([prompt]), 输入的变量均为str字符串类型! input()会读入一整行的信息 ​编…