java接入gpt开发

2023-12-14 05:54:24

前情提要

本次文章使用编译器为IDEA2020

使用GPT模型为百度旗下的千帆大模型

如果是个人用或者不流传出去,可以无脑入,因为会免费送20块钱(够用上万次)

代金卷查看

正式教程:

百度智能云控制台 (baidu.com)

按照步骤创建什么都不要担心

获取AccessToken?
无论是实现调用免费的接口还是付费接口,都要先获取AccessToken,目的是鉴权。

查看对应文档获取access_token 获取access_token - 千帆大模型平台 | 百度智能云文档 (baidu.com)

根据文档我们知道我们向接口发起一个POST请求。一个请求头以及三个Query参数。

首先我们在pom文件中导入了如下jar包

    <dependencies>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.8.1</version>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.19</version>
        </dependency>
 
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.36</version>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>

编写测试获取AccessToken的方法?

@Slf4j
public class Chat {
    private final String ACCESS_TOKEN_URI = "https://aip.baidubce.com/oauth/2.0/token";
 
    private String apiKey = "yourApikey";
    private String secretKey = "yourSecetkey";
    private String accessToken;
 
    private OkHttpClient client = new OkHttpClient();
 
    public boolean getAccessToken(){
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        //创建一个请求
        Request request = new Request.Builder()
                .url(ACCESS_TOKEN_URI+"?client_id=" + apiKey + "&client_secret=" + secretKey + "&grant_type=client_credentials")
                .method("POST",body)
                .addHeader("Content-Type", "application/json")
                .build();
        try {
            //使用浏览器对象发起请求
            Response response = client.newCall(request).execute();
            //只能执行一次response.body().string()。下次再执行会抛出流关闭异常,因此需要一个对象存储返回结果
            String responseMessage = response.body().string();
            log.debug("获取accessToken成功");
            JSONObject jsonObject = JSON.parseObject(responseMessage);
            accessToken = (String) jsonObject.get("access_token");
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

我们将调用的获取AccessToken接口获取到的信息转为JSON格式后,获取access_token属性值,复制给类属性。?

测试

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Chat chat = new Chat();
        boolean result = chat.getAccessToken();
        System.out.println(result);
    }
}

19:46:13,387 DEBUG Chat:48 - 获取accessToken成功
true

实现Prompt模板接口调用

Prompt模板 - 千帆大模型平台 | 百度智能云文档 (baidu.com)查看对应文档Prompt模板 - 千帆大模型平台 | 百度智能云文档 (baidu.com)

要想调用该接口,我们需要事先创建好Promet模板。创建模板过程如下

创建好模板后,我们后续需要调用模板ID。

具体实现代码如下

    /**
     * 调用Prompt接口
     * @param param
     */
    public void getPrompt(int id,String param){
        Request request = new Request.Builder()
//        https://aip.baidubce.com/rest/2.0/wenxinworkshop/api/v1/template/info?access_token=xxx&id=7964&name=value
                .url(CHAT_URI + "?access_token="+accessToken+"&id="+id+"&name="+param)
                .addHeader("Content-Type", "application/json")
                .method("GET",null)
                .build();
        try {
            Response responseMessage = client.newCall(request).execute();
            JSONObject jsonObject = JSON.parseObject(responseMessage.body().string());
            log.debug(jsonObject.toString());
            Object result = jsonObject.get("result");
            log.debug("{}",result.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

测试

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Chat chat = new Chat();
        boolean result = chat.getAccessToken();
        if (result){
            chat.getPrompt(7964,"zmbwcx");
        }
    }
}

19:48:04,906 DEBUG Chat:48 - 获取accessToken成功
19:48:05,144 DEBUG Chat:99 - {"result":{"templateName":"测试接口调用","templateContent":"文章内容:{name}测试接口调用成功","templateId":7964,"content":"文章内容:zmbwcx测试接口调用成功","templateVariables":"name"},"log_id":"0hkyy9izb4azvsgp","success":true,"status":200}
19:48:05,145 DEBUG Chat:101 - {"templateName":"测试接口调用","templateContent":"文章内容:{name}测试接口调用成功","templateId":7964,"content":"文章内容:zmbwcx测试接口调用成功","templateVariables":"name"}

实现对话接口调用

同样是观察文档,不过实现对话接口调用比实现调用Prompt接口稍微复杂一些。需要创建一些类来设置我们的参数。

创建请求参数类

@Data
public class RequestMessage {
    /**
     * 聊天上下文
     */
    List<Message> messages = new ArrayList<>();
 
    /**
     * 范围(0~1.0]
     * 较高的数值会使输出更加随机
     */
    float temperature = Float.parseFloat("0.95");
 
    /**
     * 影响文本的多样性,取值越大生成的文本多样性越强
     * 建议该参数与temperature只设置一个。建议top_p和temperature不要同时更改
     */
    float top_p = Float.parseFloat("0.8");
 
    /**
     * 通过对已生成的token增加惩罚,减少重复生成的现象
     * 值越大,惩罚越大
     * 取值范围[1,2]
     */
    float penalty_score = Float.parseFloat("1.0");
 
    /**
     * 是否以流式接口形式返回数据
     */
    boolean stream = false;
 
    /**
     * 模型人设
     */
    String system = null;
 
    /**
     * 表示用户唯一标识符,用于监测和检测滥用行为。防止接口恶意调用。
     */
    String user_id = "";
 
    public void addMessage(Message message){
        this.messages.add(message);
    }
}

创建Message类?

@Data
public class Message {
    /**
     * 用户角色
     * 目前支持:
     * user 用户
     * assistant 对话助手
     */
    String role;
 
    /**
     * 对话内容。
     */
    String content;
 
    public Message(String role, String content) {
        this.role = role;
        this.content = content;
    }
}

设置接收响应信息类

@Data
public class ResponseMessage {
    //本轮对话id
    String id;
 
    //回包类型。 chat.completion:多轮对话返回
    String object;
 
    //时间戳
    int created;
 
    //表示当前子句的序号。只有在流式接口模式下才会返回该字段
    int sentence_id;
 
    //表示当前子句是否是最后一句。只有在流式接口模式下会返回该字段。
    boolean is_end;
 
    //对话返回结果。
    String result;
 
    /**
     * 表示用户输入是否存在安全,是否关闭当前会话,清理历史回话信息。
     * true:是,表示用户输入存在安全风险,建议关闭当前会话,清理历史会话信息。
     * false:否,表示用户输入无安全风险。
     */
    boolean need_clear_history;
 
    //token统计信息,token数 = 汉字数+单词数*1.3 (仅为估算逻辑)。
    Usage usage;
}

?设置Usage类

public class Usage {
    //问题token数
    int prompt_tokens;
    //回答token数
    int completion_tokens;
    //token总数
    int total_tokens;
}

?如果看文档不太清楚的话,我们可以通过在线调试平台观察一下请求所需要的必须参数与响应过来的参数结构。

接下来我们编写Chat类?

@Slf4j
public class Chat {
    private final String ACCESS_TOKEN_URI = "https://aip.baidubce.com/oauth/2.0/token";
    private final String CHAT_URI = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant";
 
    private String apiKey = "yourApikey";
    private String secretKey = "yourSecretkey";
    private String accessToken = "";
 
    private OkHttpClient client ;
 
    //请求参数
    private RequestMessage requestBody = new RequestMessage();
    //响应超时时间
    private int responseTimeOut = 5000;
 
    public Chat(){
        this.client = new OkHttpClient.Builder().readTimeout(responseTimeOut,TimeUnit.SECONDS).build();
    }
 
    public Chat(int responseTimeOut){
        this.client = new OkHttpClient.Builder().readTimeout(responseTimeOut,TimeUnit.SECONDS).build();
    }
 
     public boolean getAccessToken(){
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        //创建一个请求
        Request request = new Request.Builder()
                .url(ACCESS_TOKEN_URI+"?client_id=" + apiKey + "&client_secret=" + secretKey + "&grant_type=client_credentials")
                .method("POST",body)
                .addHeader("Content-Type", "application/json")
                .build();
        try {
            //使用浏览器对象发起请求
            Response response = client.newCall(request).execute();
            //只能执行一次response.body().string()。下次再执行会抛出流关闭异常,因此需要一个对象存储返回结果
            String responseMessage = response.body().string();
            log.debug("获取accessToken成功");
            JSONObject jsonObject = JSON.parseObject(responseMessage);
            accessToken = (String) jsonObject.get("access_token");
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
 
    /**
     *
     * 获取问题参数,返回答案
     * @param question
     */
    public void getAnswer(String question){
        //通过参数获取一个Message
        Message message = new Message("user",question);
        //将新的问题添加到消息上下文
        requestBody.addMessage(message);
        String jsonStr = JSON.toJSONString(requestBody);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, jsonStr);
        Request request = new Request.Builder()
                .url(CHAT_URI + "?access_token="+accessToken)
                .addHeader("Content-Type", "application/json")
                .method("POST",body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            log.debug("发送一次请求,询问问题:{}",question);
            String responseJsonStr = response.body().string();
            ResponseMessage responseMessage = JSON.parseObject(responseJsonStr, ResponseMessage.class);
            System.out.println("返回的响应结果为:"+responseJsonStr);
            String result = responseMessage.getResult();
            String answer = result.replaceAll("\n+", "\n");
            log.debug("{}",answer);
            Message assistant = new Message("assistant", answer);
            requestBody.addMessage(assistant);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    public void getRequestBody(){
        System.out.println(JSON.toJSONString(requestBody));
    }    
}

测试

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Chat chat = new Chat();
        boolean result = chat.getAccessToken();
        if (result){
            Scanner scanner = new Scanner(System.in);
            String question = scanner.nextLine();
            while(!"q".equals(question)){
                chat.getAnswer(question);
                chat.getRequestBody();
                question = scanner.nextLine();
            }
        }
    }
}

注意!!

以上信息均为使用Java调用千帆大模型接口-CSDN博客大佬教程(此处抄袭仅为整合自用)

但是我需要的是可以提供阅读背景式的调用,接下来以我的web作业为例:

我需要gpt扮演我的网站客服为用户回答问题:实现场景如下

ok,进入正题:

根据要求配置插件后在插件详情页面有

我们来看一下开发文档域内知识搜索增强插件API调用说明 - 千帆大模型平台 | 百度智能云文档 (baidu.com)

注意请求体发生了改变!!!

我一直以为一样结果在这里被坑惨了

java代码简单修改一下

 /**
     *
     * 获取问题参数,返回答案
     * @param question
     */
    public String getAnswer(String question) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();

        Map<String, Object> payload = new HashMap<>();
        payload.put("query", question);
        payload.put("verbose", true);
        String jsonString = mapper.writeValueAsString(payload);
        
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, jsonString);
        Request request = new Request.Builder()
                .url(CHAT_URI + "?access_token="+accessToken)
                .addHeader("Content-Type", "application/json")
                .method("POST",body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            log.debug("发送一次请求,询问问题:{}",question);
            String responseJsonStr = response.body().string();
            ResponseMessage responseMessage = JSON.parseObject(responseJsonStr, ResponseMessage.class);
            System.out.println("返回的响应结果为:"+responseJsonStr);
            String result = responseMessage.getResult();

            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

Controller层代码:

 @PostMapping
    public String ai(@RequestBody String text) throws JsonProcessingException {
        log.info("沟通文本为:{}",text);

        //ai接口
        Chat chat = new Chat();
        boolean result = chat.getAccessToken();
        if(result) {
            String ai = chat.getAnswer(text);
            return  "美女客服:"+ai;
        }
        return  "客服忙去了~";
    }

ok,完美解决

最后总结!

遇到一个新东西,不要想当然的操作,还是要去看一下开发者文档!!!!

文章来源:https://blog.csdn.net/weixin_61034310/article/details/134915865
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。