OpenAI模块重构

文章目录

1.common-openai-starter

1.目录结构
2.OpenAiProperties.java 新增apiUrl
java 复制代码
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
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
    @ConditionalOnMissingBean
    public OpenAiClient openAiClient() {
        return new OpenAiClient();
    }
}
4.OpenAiClient.java 使用gson重构
java 复制代码
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 {

    @Resource
    private 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.");
    }
}

2.common-openai-starter-demo

1.目录结构
2.application.yml 新增api-url
yaml 复制代码
openai:
  api-key: guest # 必填,OpenAI API Key
  api-url: https://api.openai.com/v1/chat/completions # 可选,有默认值,为了防止以后 URL 变化
3.OpenAiController.java
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 {

    @Resource
    private OpenAiClient openAiClient;

    @RequestMapping("/ask")
    public String ask(String question) {
        String res = openAiClient.askAI("gpt-4o", question, false);
        return "AI回答:" + res;
    }
}
4.OpenAiApplication.java
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.测试
相关推荐
IU宝23 分钟前
vector的使用,以及部分功能的模拟实现(C++)
开发语言·c++
小熊科研路(同名GZH)40 分钟前
【Matlab高端绘图SCI绘图模板】第05期 绘制高阶折线图
开发语言·matlab·信息可视化
&白帝&44 分钟前
JAVA JDK7时间相关类
java·开发语言·python
geovindu1 小时前
Qt Designer and Python: Build Your GUI
开发语言·qt
Xiao Xiangζั͡ޓއއ1 小时前
程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<1>
c语言·开发语言·程序人生·学习方法·改行学it
狄加山6751 小时前
系统编程(线程互斥)
java·开发语言
Hunter_pcx1 小时前
[C++技能提升]插件模式
开发语言·c++
杰九1 小时前
【全栈】SprintBoot+vue3迷你商城(10)
开发语言·前端·javascript·vue.js·spring boot
左手の明天2 小时前
【C/C++】C++中使用vector存储并遍历数据
c语言·开发语言·c++
关关钧2 小时前
【R语言】函数
开发语言·r语言