Spring Boot后端调用文心一言响应式问答

1.获取文心服务

要在我们的后端服务中接入文心一言,就要获取文心的服务,首先我们要进入百度智能云中注册一个账号: https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application 然后点击应用接入,再创建一个应用: 这里的API Key和Sercet Key都是比较重要的,需要把他们保存下来,不过比较好的是,这里的Key都可以多次访问。

紧接着再点击左侧的在线服务选择其中一个开通,这里我使用ERNIE-3.5K:

2.配置相关信息

我们要携带API Key和Sercet Key访问获取获取access_token的接口,再携带access_token和提问访问文心服务器获取回答,大致流程如下: 所以我们要在application.yml配置类中配置一些信息: 这里要替换成自己的,第一步中开通的服务不同,access_token的接口也不同

gaomengsuanjia:

wenxin:

#client_id

api-key: 3Q4deLxxxxxxxxxxHOUWmP

#client_secret

secret-key: mefNTexxxxxxxxxxxxxxxnnN097Tn

#access_token接口

token-url: https://aip.baidubce.com/oauth/2.0/token

#文心服务器接口

chat_url: https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions

再创建Properties配置类:WenXinProperties

@Component

@ConfigurationProperties(prefix = "gaomengsuanjia.wenxin")

@Data

public class WenXinProperties {

private String apiKey;

private String secretKey;

private String tokenUrl;

private String chatUrl;

}

3.编写Http请求工具类

本次示例我们需要使用HttpClient向两个接口发送http请求,在我们的完整项目中,可能需要多次发送不同的http请求,因此编写一个工具类HttpClientUtil十分有必要:

/**

* Http工具类

*/

public class HttpClientUtil {

static final int TIMEOUT_MSEC = 20 * 1000;

/**

* 发送GET方式请求

* @param url

* @param paramMap

* @return

*/

public static String doGet(String url,Map paramMap){

// 创建Httpclient对象

CloseableHttpClient httpClient = HttpClients.createDefault();

String result = "";

CloseableHttpResponse response = null;

try{

URIBuilder builder = new URIBuilder(url);

if(paramMap != null){

for (String key : paramMap.keySet()) {

builder.addParameter(key,paramMap.get(key));

}

}

URI uri = builder.build();

//创建GET请求

HttpGet httpGet = new HttpGet(uri);

//发送请求

response = httpClient.execute(httpGet);

//判断响应状态

if(response.getStatusLine().getStatusCode() == 200){

result = EntityUtils.toString(response.getEntity(),"UTF-8");

}

}catch (Exception e){

e.printStackTrace();

}finally {

try {

response.close();

httpClient.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return result;

}

/**

* 发送POST方式请求

* @param url

* @param paramMap

* @return

* @throws IOException

*/

public static String doPost(String url, Map paramMap) throws IOException {

// 创建Httpclient对象

CloseableHttpClient httpClient = HttpClients.createDefault();

CloseableHttpResponse response = null;

String resultString = "";

try {

// 创建Http Post请求

HttpPost httpPost = new HttpPost(url);

// 创建参数列表

if (paramMap != null) {

List paramList = new ArrayList();

for (Map.Entry param : paramMap.entrySet()) {

paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));

}

// 模拟表单

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);

httpPost.setEntity(entity);

}

httpPost.setConfig(builderRequestConfig());

// 执行http请求

response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");

} catch (Exception e) {

throw e;

} finally {

try {

response.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return resultString;

}

/**

* 发送POST方式请求

* @param url

* @param paramMap

* @return

* @throws IOException

*/

public static String doPost4Json(String url, Map paramMap) throws IOException {

// 创建Httpclient对象

CloseableHttpClient httpClient = HttpClients.createDefault();

CloseableHttpResponse response = null;

String resultString = "";

try {

// 创建Http Post请求

HttpPost httpPost = new HttpPost(url);

if (paramMap != null) {

//构造json格式数据

JSONObject jsonObject = new JSONObject();

for (Map.Entry param : paramMap.entrySet()) {

jsonObject.put(param.getKey(),param.getValue());

}

StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");

//设置请求编码

entity.setContentEncoding("utf-8");

//设置数据类型

entity.setContentType("application/json");

httpPost.setEntity(entity);

}

httpPost.setConfig(builderRequestConfig());

// 执行http请求

response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");

} catch (Exception e) {

throw e;

} finally {

try {

response.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return resultString;

}

private static RequestConfig builderRequestConfig() {

return RequestConfig.custom()

.setConnectTimeout(TIMEOUT_MSEC)

.setConnectionRequestTimeout(TIMEOUT_MSEC)

.setSocketTimeout(TIMEOUT_MSEC).build();

}

/**

* 发送POST方式请求,带有JSON格式的请求体

* @param url 请求地址

* @param jsonBody JSON格式的请求体

* @return 响应内容

* @throws IOException

*/

public static String doPostWithJson(String url, String jsonBody) throws IOException {

// 创建Httpclient对象

CloseableHttpClient httpClient = HttpClients.createDefault();

CloseableHttpResponse response = null;

String resultString = "";

try {

// 创建Http Post请求

HttpPost httpPost = new HttpPost(url);

// 设置请求体为JSON格式

StringEntity entity = new StringEntity(jsonBody, "UTF-8");

entity.setContentType("application/json");

httpPost.setEntity(entity);

// 设置请求配置

httpPost.setConfig(builderRequestConfig());

// 执行HTTP请求

response = httpClient.execute(httpPost);

// 解析响应内容

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");

} catch (Exception e) {

throw e;

} finally {

try {

if (response != null) {

response.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

return resultString;

}

}

这里我们只使用了doPost()和doPostWithJson()方法

4.编写主程序

假设前端把question放在请求体中传到我们后端,我们也需要把文心的回答响应回去:

@RestController

@RequestMapping("/gaomengsuanjia")

public class WenXinController {

@Autowired

private WenXinService wenXinService;

@PostMapping("/test")

public String wenXinTest(@RequestBody String question){

String answers = wenXinService.wenXinTest(question);

return answers;

}

}

在Service层中请求access_token,并且携带访问文心一言服务器,获取回答:

public interface WenXinService {

/**

* 向文心一言提问

* @param question

* @return

*/

String wenXinTest(String question);

}

@Service

public class WenXinServiceImpl implements WenXinService {

@Autowired

private WenXinProperties wenXinProperties;

/**

* 向文心一言提问

* @param question

* @return

*/

@Override

public String wenXinTest(String question) {

Map paramMap = new HashMap<>();

//拼接请求路径,要把key放在路径参数中

String url = wenXinProperties.getTokenUrl()+"?client_id="+wenXinProperties.getApiKey()+"&client_secret="+wenXinProperties.getSecretKey()+"&grant_type=client_credentials";

//向access_token接口发送POST请求,获取响应结果

String response = null;

try {

response = HttpClientUtil.doPost(url, paramMap);

} catch (IOException e) {

e.printStackTrace();

}

//将响应结果中的access_token获取出来

JSONObject jsonObject = JSON.parseObject(response);

String token = jsonObject.getString("access_token");

//下面携带access_token请求文心服务器

//编写请求体,把前端传进来的问题拼入

String paramJson = String.format("{\"messages\": [{\"role\": \"user\", \"content\": \"%s\"}]}", question);

String request = null;

//发送POST请求,获取请求结果字符串

try {

request = HttpClientUtil.doPostWithJson("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + token, paramJson);

} catch (IOException e) {

e.printStackTrace();

}

//截取请求结果中文心一言的回答部分

JSONObject jsonResponse = JSON.parseObject(request);

String result = jsonResponse.getString("result");

//打印输出

System.out.println("输出结果:" + result);

//返回结果

return result;

}

}

5.进行问答测试

使用postman进行测试,把问题放在请求体中: 点击发送请求,就会看到文心的回答了:

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: