diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/QanythingService.java b/kbqa-graph/src/main/java/com/supervision/qanything/QanythingService.java new file mode 100644 index 0000000..8dd228b --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/QanythingService.java @@ -0,0 +1,23 @@ +package com.supervision.qanything; + +import com.supervision.qanything.dto.ChatResult; +import com.supervision.qanything.dto.ResultWrapper; + +import java.security.NoSuchAlgorithmException; +import java.util.List; + +/** + * Qanything 接口服务 + */ +public interface QanythingService { + + + /** + * 聊天接口 + * @param question 问题 + * @param kbIds 知识库ID + * @return + * @throws NoSuchAlgorithmException + */ + ResultWrapper chat(String question,List kbIds) throws NoSuchAlgorithmException; +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/BaseParam.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/BaseParam.java new file mode 100644 index 0000000..1d7afab --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/BaseParam.java @@ -0,0 +1,38 @@ +package com.supervision.qanything.dto; + +import lombok.Data; + +@Data +public class BaseParam { + + /** + * 应用标识(应用 ID) + */ + private String appKey; + + /** + * 时间戳(秒) + */ + private String curtime; + + /** + * 随机字符串 建议使用UUID + */ + private String salt; + + /** + * 签名信息:sha256(应用ID+input+salt+curtime+应用密钥) + */ + private String sign; + + /** + * 签名类型 v3 + */ + private String signType; + + private String q; + + private String[] img; + + +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatParam.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatParam.java new file mode 100644 index 0000000..f7be84a --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatParam.java @@ -0,0 +1,21 @@ +package com.supervision.qanything.dto; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +public class ChatParam extends BaseParam{ + + /** + * json数组类型,多知识库问答 + */ + private List kbIds; + + /** + * json数组类型,最多支持两轮对话历史消息 + */ + private List history; +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatResult.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatResult.java new file mode 100644 index 0000000..2848a83 --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ChatResult.java @@ -0,0 +1,30 @@ +package com.supervision.qanything.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class ChatResult { + + /** + * 本轮提问 + */ + private String question; + + /** + * 本轮回答 + */ + private String response; + + /** + * 历史问答 + */ + private List history; + + /** + * 文档出处 + */ + private List source; + +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/HistoryDTO.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/HistoryDTO.java new file mode 100644 index 0000000..99116ee --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/HistoryDTO.java @@ -0,0 +1,19 @@ +package com.supervision.qanything.dto; + +import lombok.Data; + +/** + * 历史问答 + */ +@Data +public class HistoryDTO { + /** + * 历史提问 + */ + private String question; + + /** + * 历史回答 + */ + private String response; +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/ResultWrapper.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ResultWrapper.java new file mode 100644 index 0000000..f4c4ca0 --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/ResultWrapper.java @@ -0,0 +1,24 @@ +package com.supervision.qanything.dto; + +import lombok.Data; + +@Data +public class ResultWrapper { + + /** + * 错误码 + */ + private String errorCode; + + /** + * 描述 + */ + private String msg; + + /** + * 请求id + */ + private String requestId; + + private T result; +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/dto/SourceDTO.java b/kbqa-graph/src/main/java/com/supervision/qanything/dto/SourceDTO.java new file mode 100644 index 0000000..ecc6a43 --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/dto/SourceDTO.java @@ -0,0 +1,30 @@ +package com.supervision.qanything.dto; + + +import lombok.Data; + +/** + * 文档出处 + */ +@Data +public class SourceDTO { + /** + * 文档id + */ + private String fileId; + + /** + * 文档名称 + */ + private String fileName; + + /** + * 原文内容 + */ + private String content; + + /** + * 可信度 + */ + private String source; +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/impl/QanythingServiceImpl.java b/kbqa-graph/src/main/java/com/supervision/qanything/impl/QanythingServiceImpl.java new file mode 100644 index 0000000..645ecd3 --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/impl/QanythingServiceImpl.java @@ -0,0 +1,37 @@ +package com.supervision.qanything.impl; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONUtil; +import com.supervision.qanything.QanythingService; +import com.supervision.qanything.dto.ChatParam; +import com.supervision.qanything.dto.ChatResult; +import com.supervision.qanything.dto.ResultWrapper; +import com.supervision.qanything.util.AuthV3Util; +import lombok.extern.slf4j.Slf4j; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +@Slf4j +public class QanythingServiceImpl implements QanythingService { + + private static final String APP_KEY = "071053d9bc4b544c"; // 您的应用ID + private static final String APP_SECRET = "nObcggsh0li2eGtyII6XOGtSCo6nFgdD"; // 您的应用密钥 + + private String baseUrl = "https://openapi.youdao.com"; + @Override + public ResultWrapper chat(String question, List kbIds) throws NoSuchAlgorithmException { + ChatParam chatParam = new ChatParam(); + chatParam.setQ(question); + chatParam.setKbIds(kbIds); + // 添加鉴权相关参数 + AuthV3Util.addAuthParams(APP_KEY, APP_SECRET, chatParam); + HttpRequest request = HttpRequest.post(baseUrl + "/q_anything/paas/chat") + .body(JSONUtil.toJsonStr(chatParam)); + try (HttpResponse response = request.execute()){ + return JSONUtil.toBean(response.body(), ResultWrapper.class); + } + } + + +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV3Util.java b/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV3Util.java new file mode 100644 index 0000000..512494f --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV3Util.java @@ -0,0 +1,119 @@ +package com.supervision.qanything.util; + +import com.supervision.qanything.dto.BaseParam; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + +public class AuthV3Util { + + + /** + * 添加鉴权相关参数 - + * appKey : 应用ID + * salt : 随机值 + * curtime : 当前时间戳(秒) + * signType : 签名版本 + * sign : 请求签名 + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param baseParam 请求参数表 + */ + public static void addAuthParams(String appKey, String appSecret, BaseParam baseParam) + throws NoSuchAlgorithmException { + /* String[] qArray = baseParam.getQ(); + if (qArray == null) { + qArray = baseParam.getImg(); + } + StringBuilder q = new StringBuilder(); + for (String item : qArray) { + q.append(item); + }*/ + String salt = UUID.randomUUID().toString(); + String curtime = String.valueOf(System.currentTimeMillis() / 1000); + String sign = calculateSign(appKey, appSecret, baseParam.getQ().toString(), salt, curtime); + baseParam.setAppKey(appKey); + baseParam.setSalt(salt); + baseParam.setCurtime(curtime); + baseParam.setSignType("v3"); + baseParam.setSign(sign); + } + + + /** + * 添加鉴权相关参数 - + * + * @param appKey + * @param appSecret + * @param q 用于生成签名的字段 + * @return + * @throws NoSuchAlgorithmException + */ + public static BaseParam addAuthParams(String appKey, String appSecret, String q) throws NoSuchAlgorithmException { + String salt = UUID.randomUUID().toString(); + String curtime = String.valueOf(System.currentTimeMillis() / 1000); + String sign = calculateSign(appKey, appSecret, q, salt, curtime); + + BaseParam baseParam = new BaseParam(); + baseParam.setAppKey(appKey); + baseParam.setSalt(salt); + baseParam.setCurtime(curtime); + baseParam.setSignType("v3"); + baseParam.setSign(sign); + + return baseParam; + + + } + + /** + * 计算鉴权签名 - + * 计算方式 : sign = sha256(appKey + input(q) + salt + curtime + appSecret) + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param q 请求内容 + * @param salt 随机值 + * @param curtime 当前时间戳(秒) + * @return 鉴权签名sign + */ + public static String calculateSign(String appKey, String appSecret, String q, String salt, String curtime) + throws NoSuchAlgorithmException { + String strSrc = appKey + getInput(q) + salt + curtime + appSecret; + return encrypt(strSrc); + } + + private static String encrypt(String strSrc) throws NoSuchAlgorithmException { + byte[] bt = strSrc.getBytes(); + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(bt); + byte[] bts = md.digest(); + StringBuilder des = new StringBuilder(); + for (byte b : bts) { + String tmp = (Integer.toHexString(b & 0xFF)); + if (tmp.length() == 1) { + des.append("0"); + } + des.append(tmp); + } + return des.toString(); + } + + private static String getInput(String input) { + if (input == null) { + return null; + } + String result; + int len = input.length(); + if (len <= 20) { + result = input; + } else { + String startStr = input.substring(0, 10); + String endStr = input.substring(len - 10, len); + result = startStr + len + endStr; + } + return result; + } +} diff --git a/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV4Util.java b/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV4Util.java new file mode 100644 index 0000000..2bed0de --- /dev/null +++ b/kbqa-graph/src/main/java/com/supervision/qanything/util/AuthV4Util.java @@ -0,0 +1,65 @@ +package com.supervision.qanything.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.UUID; + +public class AuthV4Util { + + /** + * 添加鉴权相关参数 - + * appKey : 应用ID + * salt : 随机值 + * curtime : 当前时间戳(秒) + * signType : 签名版本 + * sign : 请求签名 + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param paramsMap 请求参数表 + */ + public static void addAuthParams(String appKey, String appSecret, Map paramsMap) + throws NoSuchAlgorithmException { + String salt = UUID.randomUUID().toString(); + String curtime = String.valueOf(System.currentTimeMillis() / 1000); + String sign = calculateSign(appKey, appSecret, salt, curtime); + paramsMap.put("appKey", new String[]{appKey}); + paramsMap.put("salt", new String[]{salt}); + paramsMap.put("curtime", new String[]{curtime}); + paramsMap.put("signType", new String[]{"v4"}); + paramsMap.put("sign", new String[]{sign}); + } + + /** + * 计算鉴权签名 - + * 计算方式 : sign = sha256(appKey + salt + curtime + appSecret) + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param salt 随机值 + * @param curtime 当前时间戳(秒) + * @return 鉴权签名sign + */ + public static String calculateSign(String appKey, String appSecret, String salt, String curtime) + throws NoSuchAlgorithmException { + String strSrc = appKey + salt + curtime + appSecret; + return encrypt(strSrc); + } + + private static String encrypt(String strSrc) throws NoSuchAlgorithmException { + byte[] bt = strSrc.getBytes(); + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(bt); + byte[] bts = md.digest(); + StringBuilder des = new StringBuilder(); + for (byte b : bts) { + String tmp = (Integer.toHexString(b & 0xFF)); + if (tmp.length() == 1) { + des.append("0"); + } + des.append(tmp); + } + return des.toString(); + } +}