代码参考:
千帆API流式调用:PHP、JS、Nodejs、Python、Java、C# 、Go流式示例代码 - 百度智能云千帆社区本文旨在提供一个全面的指南,涵盖了在PHP、JS、Nodejs、Python、Java、C# 中流式调用千帆API的关键技巧和最佳实践。不论您是初学者还是有经验的开发者,相信这里的内容都能帮助您提升https://cloud.baidu.com/qianfandev/topic/268202
效果演示:
API服务:
接口地址:
V1版本:https://apis.ydxiaoshuai.cn/xai/rest/llm/baidu/qianfan/chat?accessToken=ACCESSTOKEN&prompt=PROMPT
V2版本使用WebFlux:https://apis.ydxiaoshuai.cn/xai/rest/llm/baidu/qianfan/v2/chat?accessToken=ACCESSTOKEN&prompt=PROMPT
请求方式:GET
参数替换:
替换ACCESSTOKEN为自己的
替换PROMPT为自己要提问的问题
注意:服务器带宽有限,请不要恶意攻击
Java-Controller代码:
/*** 发送问题** @param apiKey - 用于获取token的apiKey* @param secretKey - 用于获取token的secretKey* @param accessToken - 接口token* @param prompt - 用于权限验证,从服务接口认证信息中获取* @return 百度千帆的回答*/@GetMapping(value = "/baidu/qianfan/chat")public void baiduQianfanChat(@RequestParam(value ="apiKey",required = false) String apiKey,@RequestParam(value ="secretKey",required = false) String secretKey,@RequestParam(value ="accessToken",required = false) String accessToken,@RequestParam(value ="prompt",required = false) String prompt,HttpServletResponse res) throws Exception {LiteLLMResult bean = new LiteLLMResult();QianFanResponseDTO responseDTO = new QianFanResponseDTO();log.info("【百度千帆-prompt内容】:{}", prompt);// 响应流res.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_EVENT_STREAM_VALUE);res.setCharacterEncoding("UTF-8");res.setHeader(HttpHeaders.PRAGMA, "no-cache");ServletOutputStream out = null;String REQ_URL = null;try {out = res.getOutputStream();if (StrUtil.isEmpty(prompt)) {bean.fail("无效问题,请重新输入",500);out.write(JSON.toJSONString(bean).getBytes());return;}okhttp3.MediaType mediaType = okhttp3.MediaType.parse(MediaType.APPLICATION_JSON_VALUE);QianFanChatBean requestBean = QianFanUtil.getRequestData(prompt);requestBean.setStream(true);RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(requestBean));boolean flag = StrUtil.isEmpty(apiKey)||StrUtil.isEmpty(secretKey);if(flag && StrUtil.isNotEmpty(accessToken)){REQ_URL = QianFanUtil.API_URL.replace("ACCESS_TOKEN",accessToken);}else if(StrUtil.isNotEmpty(apiKey)&&StrUtil.isNotEmpty(secretKey)){REQ_URL = QianFanUtil.API_URL.replace("ACCESS_TOKEN",QianFanUtil.getAccessToken(apiKey,secretKey));}else{bean.fail("apiKey|secretKey|accessToken参数为空,请检查",500);out.write(JSON.toJSONString(bean).getBytes());return;}Request request = new Request.Builder().url(REQ_URL).method(Method.POST.toString(), body).addHeader(Header.CONTENT_TYPE.getValue(), MediaType.APPLICATION_JSON_VALUE).build();Response response = QianFanUtil.HTTP_CLIENT.newCall(request).execute();try (ResponseBody responseBody = response.body()) {if (responseBody != null) {try (BufferedReader reader = new BufferedReader(responseBody.charStream())) {String line;while ((line = reader.readLine()) != null) {String result = line.replace("data: ", "");if(StrUtil.isNotEmpty(result)){QianFanResponseBean qianFanResponseBean = JSON.parseObject(result,QianFanResponseBean.class);responseDTO.setContent(qianFanResponseBean.getResult());bean.success("执行成功",responseDTO);out.write(JSON.toJSONString(bean).getBytes());out.flush();//防止返回内容重复或错误。暂停一下Thread.sleep(100);}}}finally {responseBody.close();response.close();QianFanUtil.HTTP_CLIENT.connectionPool().evictAll();QianFanUtil.HTTP_CLIENT.dispatcher().executorService().shutdown();QianFanUtil.HTTP_CLIENT.newCall(request).cancel();}}}} catch (Exception e) {bean.fail("系统内部错误,请联系管理员",500);out.write(JSON.toJSONString(bean).getBytes());return;} finally {try {if (out != null) {out.close();}} catch (IOException e) {bean.fail("系统内部错误,请联系管理员",500);out.write(JSON.toJSONString(bean).getBytes());return;}}}
LiteLLMResult
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class LiteLLMResult extends BaseResponseBean {/*** 具体参数**/private XingHuoResponseDTO data;public LiteLLMResult success(String message, XingHuoResponseDTO data) {this.message = message;this.code = CommonConstant.SC_OK_200;this.data = data;return this;}public LiteLLMResult fail(String message, Integer code) {this.message = message;this.code = code;return this;}public LiteLLMResult error(String message) {this.message = message;this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;return this;}
}
BaseResponseBean
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BaseResponseBean implements Serializable {private static final long serialVersionUID = 1L;private static final long timestamps = System.currentTimeMillis();/*** 返回处理消息*/public String log_id = timestamps+"-"+IdUtil.fastSimpleUUID();/*** 返回处理消息*/public String message = "ok";/*** 返回处理消息*/public String message_zh = "操作成功!";/*** 返回代码*/public Integer code = 200;/*** 时间戳*/public long timestamp = timestamps;/*** 作者*/public String author = "小帅丶";}
QianFanResponseDTO
@Data
public class QianFanResponseDTO{private String uId;private String content;private String chatId;
}
Nginx配置SSE
在自己域名反向代理的location下面配置即可
proxy_buffering off;proxy_cache off;proxy_set_header Connection '';chunked_transfer_encoding off; # 开启分块传输编码tcp_nopush on; # 开启TCP NOPUSH选项,禁止Nagle算法tcp_nodelay on; # 开启TCP NODELAY选项,禁止延迟ACK算法# SSE事件流add_header Content-Type text/event-stream;add_header Cache-Control no-cache;