前情提要
本次文章使用編譯器為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 {//本輪對話idString 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){//通過參數獲取一個MessageMessage 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層代碼:
@PostMappingpublic 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,完美解決