| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.smartor.common; |
| | | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.aliyuncs.CommonRequest; |
| | | import com.aliyuncs.CommonResponse; |
| | | import com.aliyuncs.DefaultAcsClient; |
| | | import com.aliyuncs.IAcsClient; |
| | | import com.aliyuncs.exceptions.ClientException; |
| | | import com.aliyuncs.exceptions.ServerException; |
| | | import com.aliyuncs.http.MethodType; |
| | | import com.aliyuncs.profile.DefaultProfile; |
| | | import com.aliyuncs.profile.IClientProfile; |
| | | import com.google.gson.Gson; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.junit.Test; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * é¿éäºèªç¶è¯è¨å¤çï¼NLPï¼å·¥å
፱ȋ |
| | | * <p> |
| | | * ææ¡£ï¼<a href="https://help.aliyun.com/zh/document_detail/181284.html">NLP èªå¦ä¹ å¹³å° / åºç¡ææ¬æå¡</a> |
| | | * <p> |
| | | * è°ç¨æ¹å¼åºäº {@code aliyun-java-sdk-alinlp} ç {@link CommonRequest}ï¼ |
| | | * ç»ä¸å {@code alinlp.cn-hangzhou.aliyuncs.com} åé POST 请æ±ï¼çæ¬å· 2020-06-29ï¼ |
| | | * éè¿ä¼ å
¥ä¸åç {@code Action} ä¸ {@code ServiceCode} è°ç¨å
·ä½è½åã |
| | | * <p> |
| | | * é
置项ï¼application.ymlï¼ï¼ |
| | | * <pre> |
| | | * aliyun: |
| | | * nlp: |
| | | * access-key-id: ${accessKeyId} # é»è®¤å¤ç¨ä¸»è´¦å· accessKeyId |
| | | * access-key-secret: ${accessKeySecret} |
| | | * region-id: cn-hangzhou |
| | | * domain: alinlp.cn-hangzhou.aliyuncs.com |
| | | * version: 2020-06-29 |
| | | * read-timeout: 5000 |
| | | * connect-timeout: 3000 |
| | | * </pre> |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class AliNlpUtil { |
| | | |
| | | /** é¿éäº AccessKey IDï¼é»è®¤å¤ç¨ä¸»è´¦å·é
ç½® */ |
| | | @Value("${aliyun.nlp.access-key-id:${accessKeyId:}}") |
| | | private String accessKeyId; |
| | | |
| | | /** é¿éäº AccessKey Secret */ |
| | | @Value("${aliyun.nlp.access-key-secret:${accessKeySecret:}}") |
| | | private String accessKeySecret; |
| | | |
| | | /** å°å IDï¼å
Œ
±äºåºå®ä¸º cn-hangzhou */ |
| | | @Value("${aliyun.nlp.region-id:cn-hangzhou}") |
| | | private String regionId; |
| | | |
| | | /** æ¥å
¥åå */ |
| | | @Value("${aliyun.nlp.domain:alinlp.cn-hangzhou.aliyuncs.com}") |
| | | private String domain = "alinlp.cn-hangzhou.aliyuncs.com"; |
| | | |
| | | /** API çæ¬å· */ |
| | | @Value("${aliyun.nlp.version:2020-06-29}") |
| | | private String version = "2020-06-29"; |
| | | |
| | | /** 读åè¶
æ¶ï¼æ¯«ç§ï¼ */ |
| | | @Value("${aliyun.nlp.read-timeout:5000}") |
| | | private int readTimeout = 5000; |
| | | |
| | | /** è¿æ¥è¶
æ¶ï¼æ¯«ç§ï¼ */ |
| | | @Value("${aliyun.nlp.connect-timeout:3000}") |
| | | private int connectTimeout = 3000; |
| | | |
| | | // NLPå°ååºå® cn-hangzhou |
| | | private static final String REGION_ID = "cn-hangzhou"; |
| | | private static final String PRODUCT = "nlp"; |
| | | private static final String VERSION = "2020-06-08"; |
| | | |
| | | private static final Gson gson = new Gson(); |
| | | |
| | | private IAcsClient client; |
| | | |
| | | @PostConstruct |
| | | private void init() { |
| | | // String accessKeyId = "LTAI5tPfc1VJzz7VuhzcBwug"; |
| | | // String accessKeySecret = "gG1srKxPFDBNWe2oHfqmK1qsSQkf1e"; |
| | | |
| | | String accessKeyId = "LTAI5t6GBf9nUXfX37CUDi4H"; |
| | | String accessKeySecret = "BtjYAES4yjvde5Lwg46sTqnZefPnOE"; |
| | | String regionId = "cn-hangzhou"; |
| | | if (StringUtils.isBlank(accessKeyId) || StringUtils.isBlank(accessKeySecret)) { |
| | | log.warn("é¿éäº NLP æªé
ç½® AccessKeyï¼AliNlpUtil å°ä¸å¯ç¨"); |
| | | return; |
| | | } |
| | | IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); |
| | | this.client = new DefaultAcsClient(profile); |
| | | } |
| | | |
| | | // ============================== åºç¡è°ç¨ ============================== |
| | | |
| | | /** |
| | | * éç¨è°ç¨å
¥å£ï¼ä¼ å
¥ Action ä¸ä¸å¡åæ°ï¼è¿åè§£æåç JSON 对象ã |
| | | * |
| | | * @param action API å¨ä½åï¼ä¾å¦ {@code GetWsChGeneral} |
| | | * @param params ä¸å¡åæ°ï¼è³å°éè¦å
å« {@code ServiceCode}ã{@code Text} ç |
| | | * @return æ¥å£è¿åç JSON 对象ï¼å¤±è´¥æ¶è¿å {@code null} |
| | | */ |
| | | public JSONObject invoke(String action, Map<String, String> params) { |
| | | if (client == null) { |
| | | log.error("é¿éäº NLP 客æ·ç«¯æªåå§åï¼æ æ³è°ç¨ action={}", action); |
| | | return null; |
| | | } |
| | | if (StringUtils.isBlank(action)) { |
| | | throw new IllegalArgumentException("action ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | CommonRequest request = new CommonRequest(); |
| | | request.setSysMethod(MethodType.POST); |
| | | request.setSysDomain(domain); |
| | | request.setSysVersion(version); |
| | | request.setSysAction(action); |
| | | request.setSysReadTimeout(readTimeout); |
| | | request.setSysConnectTimeout(connectTimeout); |
| | | if (params != null) { |
| | | for (Map.Entry<String, String> e : params.entrySet()) { |
| | | if (e.getValue() != null) { |
| | | request.putBodyParameter(e.getKey(), e.getValue()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | try { |
| | | CommonResponse response = client.getCommonResponse(request); |
| | | String data = response.getData(); |
| | | if (StringUtils.isBlank(data)) { |
| | | log.error("é¿éäº NLP è¿å为空ï¼action={}, params={}", action, params); |
| | | return null; |
| | | } |
| | | return JSONObject.parseObject(data); |
| | | } catch (ClientException e) { |
| | | log.error("é¿éäº NLP è°ç¨å¤±è´¥ action={}, params={}, errCode={}, errMsg={}", |
| | | action, params, e.getErrCode(), e.getErrMsg(), e); |
| | | return null; |
| | | } catch (Exception e) { |
| | | log.error("é¿éäº NLP è°ç¨å¼å¸¸ action={}, params={}", action, params, e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | // ============================== ä¾¿æ·æ¹æ³ ============================== |
| | | |
| | | /** |
| | | * 䏿åè¯ï¼éç¨é¢åï¼é«çº§çï¼ã |
| | | * å¯¹åº Actionï¼{@code GetWsChGeneral}ï¼ServiceCodeï¼{@code alinlp}ã |
| | | * |
| | | * @param text å¾
åè¯ææ¬ |
| | | * @param tokenizer åè¯ç²åº¦ï¼å¯ç©ºã常ç¨å¼ï¼{@code GENERAL_CHN}ï¼éç¨åºç¡ç²åº¦ï¼ |
| | | * @return åè¯ç»æå表ï¼è°ç¨å¤±è´¥è¿å空å表 |
| | | */ |
| | | public List<String> segmentChinese(String text, String tokenizer) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | Map<String, String> params = new LinkedHashMap<>(); |
| | | params.put("ServiceCode", "alinlp"); |
| | | params.put("Text", text); |
| | | if (StringUtils.isNotBlank(tokenizer)) { |
| | | params.put("TokenizerId", tokenizer); |
| | | } |
| | | JSONObject resp = invoke("GetWsChGeneral", params); |
| | | return parseWordsFromData(resp); |
| | | } |
| | | |
| | | /** 䏿åè¯ï¼ä½¿ç¨é»è®¤éç¨ç²åº¦ {@code GENERAL_CHN}ã */ |
| | | public List<String> segmentChinese(String text) { |
| | | return segmentChinese(text, "GENERAL_CHN"); |
| | | } |
| | | |
| | | /** |
| | | * æ
æåæï¼éç¨é¢åï¼åºç¡çï¼ã |
| | | * å¯¹åº Actionï¼{@code GetSaChGeneral}ã |
| | | * |
| | | * @param text å¾
åæææ¬ |
| | | * @return å½¢å¦ {@code {"sentiment":"positive","positive_prob":0.97,...}} ç对象ï¼å¤±è´¥è¿å {@code null} |
| | | */ |
| | | public JSONObject sentimentAnalysis(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | Map<String, String> params = new LinkedHashMap<>(); |
| | | params.put("ServiceCode", "alinlp"); |
| | | params.put("Text", text); |
| | | JSONObject resp = invoke("GetSaChGeneral", params); |
| | | return extractDataObject(resp); |
| | | } |
| | | |
| | | // æµè¯å
¥å£ |
| | | @Test |
| | | public void main() { |
| | | String text1 = "è¿å®¶å¥¶è¶è¶
级好åï¼ä¸æ¬¡è¿æ¥ï¼"; |
| | | String text2 = "å³éå¾å·®ï¼æå¡æåº¦ä¹ä¸å¥½ï¼ä¸æ¨è"; |
| | | String text3 = "ä»å¤©åºé¨ä¹°äºä¸ç¶ç¿æ³æ°´"; |
| | | |
| | | this.init(); |
| | | JSONObject res1 = sentimentAnalysis(text1); |
| | | JSONObject res2 = sentimentAnalysis(text2); |
| | | JSONObject res3 = sentimentAnalysis(text3); |
| | | |
| | | System.out.println("æ£é¢ææ¬ç»æï¼" + gson.toJson(res1)); |
| | | System.out.println("è´é¢ææ¬ç»æï¼" + gson.toJson(res2)); |
| | | System.out.println("䏿§ææ¬ç»æï¼" + gson.toJson(res3)); |
| | | } |
| | | |
| | | /** |
| | | * å½åå®ä½è¯å«ï¼éç¨é¢åï¼ã |
| | | * å¯¹åº Actionï¼{@code GetNerChGeneral}ã |
| | | * |
| | | * @param text å¾
è¯å«ææ¬ |
| | | * @return å®ä½åè¡¨ï¼æ¯ä¸ªå
ç´ å« wordãtagãstartIndex çåæ®µï¼ï¼å¤±è´¥è¿å空å表 |
| | | */ |
| | | public JSONArray namedEntityRecognition(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return new JSONArray(); |
| | | } |
| | | Map<String, String> params = new LinkedHashMap<>(); |
| | | params.put("ServiceCode", "alinlp"); |
| | | params.put("Text", text); |
| | | JSONObject resp = invoke("GetNerChGeneral", params); |
| | | JSONObject data = extractDataObject(resp); |
| | | if (data == null) { |
| | | return new JSONArray(); |
| | | } |
| | | JSONArray arr = data.getJSONArray("result"); |
| | | return arr == null ? new JSONArray() : arr; |
| | | } |
| | | |
| | | // ============================== ååºè§£æ ============================== |
| | | |
| | | /** |
| | | * è§£æé¿é NLP ç {@code Data} åæ®µï¼å符串åç JSONï¼ã |
| | | * é¡¶å±ååºå½¢å¦ï¼{@code {"Data":"{...}","RequestId":"..."}}ã |
| | | */ |
| | | private JSONObject extractDataObject(JSONObject resp) { |
| | | if (resp == null) { |
| | | return null; |
| | | } |
| | | String dataStr = resp.getString("Data"); |
| | | if (StringUtils.isBlank(dataStr)) { |
| | | log.warn("é¿éäº NLP ååºç¼ºå° Data åæ®µï¼resp={}", resp); |
| | | return null; |
| | | } |
| | | try { |
| | | return JSONObject.parseObject(dataStr); |
| | | } catch (Exception e) { |
| | | log.error("é¿éäº NLP Data åæ®µè§£æå¤±è´¥ï¼dataStr={}", dataStr, e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ä»åè¯ååºéæ½åè¯å表ãresult å½¢å¦ {@code [{"word":"ä»å¤©","tag":"t"},...]}ã |
| | | */ |
| | | private List<String> parseWordsFromData(JSONObject resp) { |
| | | JSONObject data = extractDataObject(resp); |
| | | if (data == null) { |
| | | return Collections.emptyList(); |
| | | } |
| | | JSONArray result = data.getJSONArray("result"); |
| | | if (result == null || result.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | String[] words = new String[result.size()]; |
| | | for (int i = 0; i < result.size(); i++) { |
| | | JSONObject item = result.getJSONObject(i); |
| | | words[i] = item == null ? "" : item.getString("word"); |
| | | } |
| | | return Arrays.asList(words); |
| | | } |
| | | |
| | | @Test |
| | | public void test() { |
| | | List <String> result = segmentChinese("é¿éå·´å·´éå¢çä½¿å½æ¯è®©å¤©ä¸æ²¡æé¾åççæã"); |
| | | log.info(result.toString()); |
| | | } |
| | | |
| | | @Test |
| | | public void testP() { |
| | | JSONObject result = sentimentAnalysis("æè§å¾ä½ å¯è½æ¯å¯¹ç"); |
| | | log.info(result.toString()); |
| | | } |
| | | } |