站点图标 Liao's blog

使用Nginx转发代理ChatGpt接口,Java调用实现多轮对话

一、理论概述

ChatGpt接口目前只能在国外互联网环境中使用,国内想要使用相关服务的话可以寻求代理,在这里使用的是一台国外服务器安装Nginx服务进行相关代理。

二、环境要求

以上就是所有需要用到的环境,请注意,如要使用接口还需要充值API额度。除此之外还需要将你的域名解析到公网IP上。完成准备工作后进行以下操作。

三、Nginx转发

  1. 在服务器中安装nginx,这里使用的是docker服务,根据以往博文中可自行安装Docker服务。
#服务器中新建一个nginx目录,下级目录新建conf.d、logs、ssl三个目录
mkdir -p nginx/conf.d
mkdir -p nginx/logs
mkdir -p nginx/ssl

#在nginx目录中新建start.sh脚本
vim start.sh

docker stop nginx
docker rm nginx
docker run  -p 80:80  -p 443:443 --name nginx --net=host  --restart=always  --privileged=true \
    -v `pwd`/conf.d/:/etc/nginx/conf.d \
    -v `pwd`/logs/:/var/log/nginx  \
    -v `pwd`/ssl/:/var/ssl \
    -e TZ="Asia/Shanghai" \
    nginx:latest

#输入 :wq 保存后授权并执行即可
chmod a+x start.sh
./start.sh
  1. 将域名ssl证书放置在ssl目录下后,编辑nginx转发代理,执行start.sh脚本重启nginx服务。
vim conf.d/gpt.conf

#填入域名信息
server {
        listen       443 ssl;
        server_name  域名;
        ssl_certificate /var/ssl/域名.crt;     #配置证书位置
        ssl_certificate_key /var/ssl/域名.key; #配置秘钥位置】

        ssl_session_timeout 5m;
        ssl_protocols SSLv2 SSLv3 TLSv1.2;
        ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ssl_prefer_server_ciphers on;

        underscores_in_headers on;
        charset utf-8;

        location /v1/ {
             proxy_ssl_server_name on;
             proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
             proxy_pass https://api.openai.com;
        }
}

以上便完成了针对chatgpt接口地址 api.openai.com 的转发工作,转发后的地址既是你的域名。

四、Java实例调用实现多轮对话

  1. 新建Maven项目ChatGPTClient,在pom.xml中添加后续用到的依赖,重构后拉取。
<dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
</dependency>
<dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.9</version> <!-- 使用最新的可用版本 -->
</dependency>
  1. java代码
import okhttp3.*;
import com.google.gson.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ChatGPTClient {
    private final String apiKey;
    private final OkHttpClient client;
    private final List<Message> messages;
    private final Gson gson;
    private int tokenCount = 0;
    private int inputTokenCount = 0;
    private int outputTokenCount = 0;

    public ChatGPTClient(String apiKey) {
        this.apiKey = apiKey;
        this.client = new OkHttpClient();
        this.messages = new ArrayList<>();
        this.gson = new Gson();
    }

    public String sendMessage(String message) throws IOException {
        updateTokenCount(message, true);

        messages.add(new Message("system", "user", message));
//model模型选择可以有gpt-3.5-turbo、gpt-4、gpt-4-turbo价格以此类推
        RequestBody body = RequestBody.create(
                MediaType.get("application/json; charset=utf-8"),
                "{\"model\": \"gpt-3.5-turbo\", \"messages\": " + gson.toJson(messages) + "}"
        );

        Request request = new Request.Builder()
                .url("https://你的域名地址/v1/chat/completions")
                .addHeader("Authorization", "Bearer " + this.apiKey)
                .addHeader("Content-Type", "application/json")
                .post(body)
                .build();

        try (Response response = client.newCall(request).execute()) {
            JsonObject respJson = JsonParser.parseString(response.body().string()).getAsJsonObject();
            JsonArray choices = respJson.getAsJsonArray("choices");
            if (choices != null && choices.size() > 0) {
                JsonObject firstChoice = choices.get(0).getAsJsonObject();
                String aiResponse = firstChoice.getAsJsonObject("message").get("content").getAsString();

                updateTokenCount(aiResponse, false);

                messages.add(new Message("system", "assistant", aiResponse));

                System.out.println("输入的 Token 数: " + inputTokenCount);
                System.out.println("输出的 Token 数: " + outputTokenCount);
                System.out.println("总使用的 Token 数: " + tokenCount);

                return aiResponse;
            }
        }
        return "无法获取响应。";
    }

    private void updateTokenCount(String text, boolean isInput) {
        int count = 0;
        for (char c : text.toCharArray()) {
            count += (String.valueOf(c).matches("[\\u0000-\\u00ff]") ? 1 : 4);
        }
        int tokens = (int) Math.ceil(count / 4.0);
        tokenCount += tokens;
        if (isInput) {
            inputTokenCount += tokens;
        } else {
            outputTokenCount += tokens;
        }
    }

    private static class Message {
        String role;
        String content;

        public Message(String type, String role, String content) {
            this.role = role;
            this.content = content;
        }
    }

    public static void main(String[] args) throws IOException {
        ChatGPTClient client = new ChatGPTClient("YOUR-API-KEY");

        Scanner scanner = new Scanner(System.in, "UTF-8");
        String input;
        while (true) {
            System.out.print("输入消息(输入 'bye' 结束对话): ");
            input = scanner.nextLine();
            if ("bye".equalsIgnoreCase(input)) {
                break;
            }
            String response = client.sendMessage(input);
            System.out.println("ChatGPT 回应: " + response);
        }
    }
}

在以上代码中,增加了每次对话后所使用的token值,以便查询核对接口使用费。可在官网查询相关定价。

五、运行结果

退出移动版