Skip to content

Commit afba62e

Browse files
Copilotbinarywang
authored andcommitted
🆕 #4042 增加智能对话 weixin-java-aispeech 模块,承接智能客服和知识助理的接口能力
1 parent 20ce58b commit afba62e

31 files changed

Lines changed: 1396 additions & 0 deletions

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
<module>weixin-java-miniapp</module>
125125
<module>weixin-java-open</module>
126126
<module>weixin-java-qidian</module>
127+
<module>weixin-java-aispeech</module>
127128
<module>weixin-java-channel</module>
128129
<module>spring-boot-starters</module>
129130
<module>solon-plugins</module>

weixin-java-aispeech/pom.xml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?xml version="1.0"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
4+
xmlns="http://maven.apache.org/POM/4.0.0">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.github.binarywang</groupId>
8+
<artifactId>wx-java</artifactId>
9+
<version>4.8.3.B</version>
10+
</parent>
11+
12+
<artifactId>weixin-java-aispeech</artifactId>
13+
<name>WxJava - Aispeech Java SDK</name>
14+
<description>微信智能对话 Java SDK</description>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>com.github.binarywang</groupId>
19+
<artifactId>weixin-java-common</artifactId>
20+
<version>${project.version}</version>
21+
</dependency>
22+
23+
<dependency>
24+
<groupId>org.apache.httpcomponents.client5</groupId>
25+
<artifactId>httpclient5</artifactId>
26+
</dependency>
27+
28+
<dependency>
29+
<groupId>org.testng</groupId>
30+
<artifactId>testng</artifactId>
31+
<scope>test</scope>
32+
</dependency>
33+
<dependency>
34+
<groupId>org.projectlombok</groupId>
35+
<artifactId>lombok</artifactId>
36+
</dependency>
37+
</dependencies>
38+
39+
<build>
40+
<plugins>
41+
<plugin>
42+
<groupId>org.apache.maven.plugins</groupId>
43+
<artifactId>maven-surefire-plugin</artifactId>
44+
<configuration>
45+
<suiteXmlFiles>
46+
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
47+
</suiteXmlFiles>
48+
</configuration>
49+
</plugin>
50+
</plugins>
51+
</build>
52+
53+
<profiles>
54+
<profile>
55+
<id>native-image</id>
56+
<activation>
57+
<activeByDefault>false</activeByDefault>
58+
</activation>
59+
60+
<build>
61+
<plugins>
62+
<plugin>
63+
<groupId>org.apache.maven.plugins</groupId>
64+
<artifactId>maven-compiler-plugin</artifactId>
65+
<version>3.5.1</version>
66+
<configuration>
67+
<annotationProcessors>
68+
com.github.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor
69+
</annotationProcessors>
70+
<annotationProcessorPaths>
71+
<path>
72+
<groupId>com.github.binarywang</groupId>
73+
<artifactId>weixin-graal</artifactId>
74+
<version>${project.version}</version>
75+
</path>
76+
</annotationProcessorPaths>
77+
</configuration>
78+
</plugin>
79+
</plugins>
80+
</build>
81+
</profile>
82+
</profiles>
83+
</project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package me.chanjar.weixin.aispeech.api;
2+
3+
import java.util.List;
4+
import me.chanjar.weixin.aispeech.bean.dialog.AsyncTaskResult;
5+
import me.chanjar.weixin.aispeech.bean.dialog.BotIntent;
6+
import me.chanjar.weixin.aispeech.bean.dialog.DialogQueryRequest;
7+
import me.chanjar.weixin.aispeech.bean.dialog.DialogResult;
8+
import me.chanjar.weixin.aispeech.bean.dialog.PublishProgress;
9+
import me.chanjar.weixin.common.error.WxErrorException;
10+
11+
public interface WxAispeechDialogService {
12+
String getAccessToken(String appid, String account) throws WxErrorException;
13+
14+
String importBotJson(int mode, List<BotIntent> data) throws WxErrorException;
15+
16+
String publishBot() throws WxErrorException;
17+
18+
PublishProgress getPublishProgress(String env) throws WxErrorException;
19+
20+
AsyncTaskResult queryAsyncTask(String taskId) throws WxErrorException;
21+
22+
DialogResult query(DialogQueryRequest request) throws WxErrorException;
23+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package me.chanjar.weixin.aispeech.api;
2+
3+
import java.io.File;
4+
import java.util.List;
5+
import java.util.Map;
6+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeInfo;
7+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeManualCreateRequest;
8+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeMoveProgress;
9+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeMoveRequest;
10+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeTagRequest;
11+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeUpdateRequest;
12+
import me.chanjar.weixin.aispeech.bean.knowledge.KnowledgeUrlCreateRequest;
13+
import me.chanjar.weixin.common.error.WxErrorException;
14+
15+
public interface WxAispeechKnowledgeService {
16+
KnowledgeInfo createKnowledgeByFile(String knowledgeBaseId, File file, String title, String description, String metadata)
17+
throws WxErrorException;
18+
19+
KnowledgeInfo createKnowledgeByUrl(String knowledgeBaseId, KnowledgeUrlCreateRequest request) throws WxErrorException;
20+
21+
KnowledgeInfo createKnowledgeByManual(String knowledgeBaseId, KnowledgeManualCreateRequest request) throws WxErrorException;
22+
23+
List<KnowledgeInfo> listKnowledge(String knowledgeBaseId, Integer page, Integer pageSize) throws WxErrorException;
24+
25+
List<KnowledgeInfo> listKnowledgeByIds(List<String> knowledgeIds) throws WxErrorException;
26+
27+
KnowledgeInfo getKnowledge(String knowledgeId) throws WxErrorException;
28+
29+
KnowledgeInfo updateKnowledge(String knowledgeId, KnowledgeUpdateRequest request) throws WxErrorException;
30+
31+
KnowledgeInfo updateManualKnowledge(String knowledgeId, KnowledgeManualCreateRequest request) throws WxErrorException;
32+
33+
boolean deleteKnowledge(String knowledgeId) throws WxErrorException;
34+
35+
boolean updateKnowledgeTags(List<String> knowledgeIds, Long tagId) throws WxErrorException;
36+
37+
List<KnowledgeInfo> searchKnowledge(String keyword, String knowledgeBaseId, Integer page, Integer pageSize)
38+
throws WxErrorException;
39+
40+
String moveKnowledge(KnowledgeMoveRequest request) throws WxErrorException;
41+
42+
KnowledgeMoveProgress getMoveProgress(String taskId) throws WxErrorException;
43+
44+
boolean createKnowledgeBaseTag(String knowledgeBaseId, KnowledgeTagRequest request) throws WxErrorException;
45+
46+
boolean updateKnowledgeBaseTag(String knowledgeBaseId, String tagId, KnowledgeTagRequest request) throws WxErrorException;
47+
48+
String postRaw(String path, Object requestBody) throws WxErrorException;
49+
50+
String getRaw(String path, Map<String, String> queryParams) throws WxErrorException;
51+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package me.chanjar.weixin.aispeech.api;
2+
3+
import me.chanjar.weixin.aispeech.config.WxAispeechConfigStorage;
4+
5+
public interface WxAispeechService {
6+
WxAispeechDialogService getDialogService();
7+
8+
WxAispeechKnowledgeService getKnowledgeService();
9+
10+
WxAispeechConfigStorage getConfigStorage();
11+
12+
void setConfigStorage(WxAispeechConfigStorage configStorage);
13+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package me.chanjar.weixin.aispeech.api.impl;
2+
3+
import com.google.gson.JsonElement;
4+
import com.google.gson.JsonObject;
5+
import com.google.gson.reflect.TypeToken;
6+
import java.lang.reflect.Type;
7+
import java.util.HashMap;
8+
import java.util.List;
9+
import java.util.Map;
10+
import me.chanjar.weixin.aispeech.api.WxAispeechDialogService;
11+
import me.chanjar.weixin.aispeech.bean.dialog.AispeechApiResponse;
12+
import me.chanjar.weixin.aispeech.bean.dialog.AsyncTaskResult;
13+
import me.chanjar.weixin.aispeech.bean.dialog.BotIntent;
14+
import me.chanjar.weixin.aispeech.bean.dialog.DialogQueryRequest;
15+
import me.chanjar.weixin.aispeech.bean.dialog.DialogResult;
16+
import me.chanjar.weixin.aispeech.bean.dialog.PublishProgress;
17+
import me.chanjar.weixin.aispeech.util.WxAispeechSignUtil;
18+
import me.chanjar.weixin.common.error.WxError;
19+
import me.chanjar.weixin.common.error.WxErrorException;
20+
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
21+
import org.apache.commons.lang3.StringUtils;
22+
23+
public class WxAispeechDialogServiceImpl implements WxAispeechDialogService {
24+
private final WxAispeechServiceImpl service;
25+
26+
public WxAispeechDialogServiceImpl(WxAispeechServiceImpl service) {
27+
this.service = service;
28+
}
29+
30+
@Override
31+
public String getAccessToken(String appid, String account) throws WxErrorException {
32+
Map<String, String> request = new HashMap<>();
33+
if (StringUtils.isNotBlank(account)) {
34+
request.put("account", account);
35+
}
36+
37+
String response = service.executeDialogPost("/v2/token", request, false, appid);
38+
Type type = new TypeToken<AispeechApiResponse<JsonObject>>() { } .getType();
39+
AispeechApiResponse<JsonObject> result = WxGsonBuilder.create().fromJson(response, type);
40+
ensureSuccess(result);
41+
String token = result.getData().get("access_token").getAsString();
42+
service.getConfigStorage().setOpenAiToken(token);
43+
return token;
44+
}
45+
46+
@Override
47+
public String importBotJson(int mode, List<BotIntent> data) throws WxErrorException {
48+
Map<String, Object> request = new HashMap<>();
49+
request.put("mode", mode);
50+
request.put("data", data);
51+
52+
String response = service.executeDialogPost("/v2/bot/import/json", request, true, null);
53+
Type type = new TypeToken<AispeechApiResponse<JsonObject>>() { } .getType();
54+
AispeechApiResponse<JsonObject> result = WxGsonBuilder.create().fromJson(response, type);
55+
ensureSuccess(result);
56+
return result.getData().get("task_id").getAsString();
57+
}
58+
59+
@Override
60+
public String publishBot() throws WxErrorException {
61+
String response = service.executeDialogPost("/v2/bot/publish", "{}", true, null);
62+
Type type = new TypeToken<AispeechApiResponse<JsonObject>>() { } .getType();
63+
AispeechApiResponse<JsonObject> result = WxGsonBuilder.create().fromJson(response, type);
64+
ensureSuccess(result);
65+
return result.getRequestId();
66+
}
67+
68+
@Override
69+
public PublishProgress getPublishProgress(String env) throws WxErrorException {
70+
Map<String, String> request = new HashMap<>();
71+
request.put("env", env);
72+
73+
String response = service.executeDialogPost("/v2/bot/effective_progress", request, true, null);
74+
Type type = new TypeToken<AispeechApiResponse<PublishProgress>>() { } .getType();
75+
AispeechApiResponse<PublishProgress> result = WxGsonBuilder.create().fromJson(response, type);
76+
ensureSuccess(result);
77+
return result.getData();
78+
}
79+
80+
@Override
81+
public AsyncTaskResult queryAsyncTask(String taskId) throws WxErrorException {
82+
Map<String, String> request = new HashMap<>();
83+
request.put("task_id", taskId);
84+
85+
String response = service.executeDialogPost("/v2/async/fetch", request, true, null);
86+
Type type = new TypeToken<AispeechApiResponse<AsyncTaskResult>>() { } .getType();
87+
AispeechApiResponse<AsyncTaskResult> result = WxGsonBuilder.create().fromJson(response, type);
88+
ensureSuccess(result);
89+
return result.getData();
90+
}
91+
92+
@Override
93+
public DialogResult query(DialogQueryRequest request) throws WxErrorException {
94+
String json = WxGsonBuilder.create().toJson(request);
95+
String encrypted = WxAispeechSignUtil.encryptAesCbcToBase64(json, service.getConfigStorage().getAesKey());
96+
String response = service.executeDialogPost("/v2/bot/query", encrypted, true, null);
97+
98+
String responseJson = response;
99+
if (!looksLikeJson(response)) {
100+
responseJson = WxAispeechSignUtil.decryptAesCbcFromBase64(response, service.getConfigStorage().getAesKey());
101+
}
102+
103+
Type type = new TypeToken<AispeechApiResponse<DialogResult>>() { } .getType();
104+
AispeechApiResponse<DialogResult> result = WxGsonBuilder.create().fromJson(responseJson, type);
105+
ensureSuccess(result);
106+
107+
DialogResult dialogResult = result.getData();
108+
if (dialogResult != null && looksLikeJson(dialogResult.getAnswer())) {
109+
dialogResult.setRawAnswer(WxGsonBuilder.create().fromJson(dialogResult.getAnswer(), JsonElement.class));
110+
}
111+
return dialogResult;
112+
}
113+
114+
private boolean looksLikeJson(String value) {
115+
return StringUtils.isNotBlank(value) && (value.startsWith("{") || value.startsWith("["));
116+
}
117+
118+
private void ensureSuccess(AispeechApiResponse<?> response) throws WxErrorException {
119+
if (response == null) {
120+
throw new WxErrorException("响应为空");
121+
}
122+
if (response.getCode() == null || response.getCode() != 0) {
123+
throw new WxErrorException(WxError.builder()
124+
.errorCode(response.getCode() == null ? -1 : response.getCode())
125+
.errorMsg(response.getMsg())
126+
.build());
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)