Skip to content

Commit

Permalink
抽象AI响应服务,添加通义千问实现,日志改为slf4j-simple
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinDai committed May 21, 2024
1 parent 8f98eff commit 16afd06
Show file tree
Hide file tree
Showing 20 changed files with 322 additions and 235 deletions.
43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

## 项目介绍:

本项目是一个微信公众号项目,需配合微信公众号使用,在微信公众号配置本项目运行的服务器域名,用户关注公众号后,向公众号发送任意信息,公众号会根据用户发送的内容自动回复。
本项目是一个微信公众号项目,需配合微信公众号使用,在微信公众号配置本项目运行的服务器域名,用户关注公众号后,向公众号发送任意信息,公众号会根据用户发送的内容自动回复。

## 涉及框架及技术

Expand All @@ -25,20 +25,33 @@ _Tips:1.2版本开始使用Vert.x替换SpringBoot_
## 支持的功能

+ [x] 自定义关键字回复内容
+ [x] 调用ChatGPT接口回复内容(需配置启动参数或者环境变量:`OPENAI_API_KEY`
+ [x] 调用OPENAI规范的接口回复内容(需配置启动参数或者环境变量:`OPENAI_SERVER_URL`
+ [x] 调用图灵机器人(V2)接口回复内容(需配置启动参数或者环境变量:`TULING_API_KEY`

## 使用说明:

1. 使用之前需要有微信公众号的帐号,没有的请戳[微信公众号申请](https://mp.weixin.qq.com/cgi-bin/readtemplate?t=register/step1_tmpl&lang=zh_CN)
2. 如果需要使用图灵机器人的回复内容则需要[注册图灵机器人帐号](http://tuling123.com/register/email.jhtml)获取相应的ApiKey并配置在启动参数或者环境变量中
3. 如果需要使用ChatGPT的回复内容则需要[创建OpenAI的API Key](https://platform.openai.com/account/api-keys)并配置在启动参数或者环境变量中
4. 可以通过配置启动参数或者环境变量`OPENAI_SERVER_URL`指定访问OpenAI服务的baseUrl
5. 可以通过配置启动参数或者环境变量`OPENAI_BASE_DOMAIN`更换访问OpenAI的域名
6. 可以通过配置启动参数或者环境变量`OPENAI_PROXY`使用代理服务访问OpenAI
7. 内容响应来源的优先级`自定义关键 > ChatGPT > 图灵机器人`
8. 在微信公众号后台配置回调URL为<https://wechatrobot.doodl6.com/weChat/receiveMessage>,其中`wechatrobot.doodl6.com`是你自己的域名,token与`config.yml`里面配置的保持一致即可
+ [x] 调用OpenAI接口回复内容(配置启动参数或者环境变量:`OPENAI_API_KEY`
+ [x] 修改OpenAI的接口地址(配置启动参数或者环境变量:`OPENAI_SERVER_URL`
+ [x] 调用通义千问接口回复内容(配置启动参数或者环境变量:`DASHSCOPE_API_KEY`
+ [x] 调用图灵机器人(V2)接口回复内容(配置启动参数或者环境变量:`TULING_API_KEY`

## 使用说明

需要有微信公众号的帐号,没有的请戳[微信公众号申请](https://mp.weixin.qq.com/cgi-bin/readtemplate?t=register/step1_tmpl&lang=zh_CN)

内容响应来源的优先级`自定义关键 > OpenAI > 通义千问 > 图灵机器人`

在微信公众号后台配置回调URL为<https://wechatrobot.doodl6.com/weChat/receiveMessage>,其中`wechatrobot.doodl6.com`是你自己的域名,token与`config.yml`里面配置的保持一致即可

### OpenAI

1. 如果需要使用OpenAI的回复内容则需要[创建OpenAI的API Key](https://platform.openai.com/account/api-keys)并配置在启动参数或者环境变量中
2. 可以通过配置启动参数或者环境变量`OPENAI_SERVER_URL`指定访问OpenAI服务的baseUrl
3. 可以通过配置启动参数或者环境变量`OPENAI_BASE_DOMAIN`更换访问OpenAI的域名(优先级低于`OPENAI_SERVER_URL`)
4. 可以通过配置启动参数或者环境变量`OPENAI_PROXY`使用代理服务访问OpenAI

### 通义千问

如果需要使用通义千问的回复内容则需要[创建通义千问的API Key](https://bailian.console.aliyun.com/#/api_key)并配置在启动参数或者环境变量中

### 图灵机器人

如果需要使用图灵机器人的回复内容则需要[注册图灵机器人帐号](http://tuling123.com/register/email.jhtml)获取相应的ApiKey并配置在启动参数或者环境变量中

## 开发部署

Expand Down
23 changes: 21 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</modules>

<properties>
<revision>1.2</revision>
<revision>1.3</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
Expand All @@ -22,14 +22,15 @@

<commons.lang3.version>3.12.0</commons.lang3.version>
<commons.io.version>2.11.0</commons.io.version>
<dashscope.version>2.14.4</dashscope.version>
<guava.version>32.1.1-jre</guava.version>
<jackson.version>2.15.2</jackson.version>
<kotlin-stdlib.version>1.6.20</kotlin-stdlib.version>
<logback.version>1.3.8</logback.version>
<lombok.version>1.18.30</lombok.version>
<okhttp3.version>4.10.0</okhttp3.version>
<openai-gpt3-java.version>0.12.0</openai-gpt3-java.version>
<reactive-streams.version>1.0.3</reactive-streams.version>
<slf4j.version>1.7.21</slf4j.version>
<vertx.version>4.4.4</vertx.version>
</properties>

Expand All @@ -55,6 +56,17 @@
<version>${lombok.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
Expand Down Expand Up @@ -118,6 +130,13 @@
<version>${kotlin-stdlib.version}</version>
</dependency>

<!-- 通义千问SDK -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>${dashscope.version}</version>
</dependency>

</dependencies>
</dependencyManagement>

Expand Down
9 changes: 9 additions & 0 deletions robot-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@
<artifactId>guava</artifactId>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package com.doodl6.wechatrobot.util;

import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

import java.util.logging.Level;
import java.util.logging.Logger;

@Slf4j
public final class HttpUtil {

private static final Logger LOGGER = Logger.getLogger(HttpUtil.class.getName());

public static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");

private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();
Expand Down Expand Up @@ -43,7 +40,7 @@ private static String executeRequest(Request request) {
return responseBody.string();
}
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "api调用异常,url:" + request.url(), e);
log.error("api调用异常,url:{}", request.url(), e);
throw new RuntimeException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;

@Slf4j
public class JsonUtil {

private static final Logger LOGGER = Logger.getLogger(JsonUtil.class.getName());

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
Expand All @@ -37,7 +35,7 @@ public static <T> T jsonToObj(String jsonStr, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(jsonStr, clazz);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "json转对象异常", e);
log.error("json转对象异常", e);
throw new IllegalArgumentException(e.getMessage());
}
}
Expand All @@ -46,7 +44,7 @@ public static <T> T jsonToObj(InputStream inputStream, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(inputStream, clazz);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "json转对象异常", e);
log.error("json转对象异常", e);
throw new IllegalArgumentException(e.getMessage());
}
}
Expand All @@ -55,7 +53,7 @@ public static String objToJson(Object obj) {
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
LOGGER.log(Level.SEVERE, "对象转json异常", e);
log.error("对象转json异常", e);
throw new IllegalArgumentException(e.getMessage());
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
package com.doodl6.wechatrobot.util;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

@Slf4j
public class XmlUtil {

private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());

private static final XmlMapper XML_MAPPER = new XmlMapper();

public static <T> T xmlToObj(String xml, Class<T> clazz) {
try {
return XML_MAPPER.readValue(xml, clazz);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "xml转clazz异常", e);
log.error("xml转clazz异常", e);
throw new IllegalArgumentException(e.getMessage());
}
}
Expand All @@ -25,7 +23,7 @@ public static String objToXml(Object obj) {
try {
return XML_MAPPER.writeValueAsString(obj);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "obj转xml异常", e);
log.error("obj转xml异常", e);
throw new IllegalArgumentException(e.getMessage());
}
}
Expand Down
5 changes: 5 additions & 0 deletions robot-web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
<artifactId>service</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
</dependency>

</dependencies>

<profiles>
Expand Down
18 changes: 8 additions & 10 deletions robot-web/src/main/java/com/doodl6/wechatrobot/MainVerticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.StaticHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

@Slf4j
public class MainVerticle extends AbstractVerticle {

private static final Logger LOGGER = Logger.getLogger(MainVerticle.class.getName());

private static final String CONFIG_KEY = "config";

@Override
Expand All @@ -43,7 +41,7 @@ public void start() {
.requestHandler(router)
.listen(port, listen -> {
if (listen.succeeded()) {
LOGGER.log(Level.INFO,"HTTP server started on port " + port);
log.info("HTTP server started on port: {}", port);
} else {
listen.cause().printStackTrace();
System.exit(1);
Expand All @@ -60,10 +58,10 @@ public static void main(String[] args) {
configPath = "config.yml";
}

VertxOptions options = new VertxOptions();
// 设置事件循环线程的最大执行时间
options.setMaxEventLoopExecuteTime(TimeUnit.SECONDS.toNanos(10));
Vertx vertx = Vertx.vertx(options);
VertxOptions options = new VertxOptions();
// 设置事件循环线程的最大执行时间
options.setMaxEventLoopExecuteTime(TimeUnit.SECONDS.toNanos(10));
Vertx vertx = Vertx.vertx(options);
ConfigStoreOptions storeOptions = new ConfigStoreOptions()
.setType("file")
.setFormat("yaml")
Expand All @@ -74,7 +72,7 @@ public static void main(String[] args) {
ConfigRetriever retriever = ConfigRetriever.create(vertx, retrieverOptions);
retriever.getConfig()
.onSuccess(config -> {
System.out.println("load config success:" + config.toString());
log.info("load config success:{}", config.toString());
DeploymentOptions deploymentOptions = new DeploymentOptions().setConfig(config);
vertx.deployVerticle(new MainVerticle(), deploymentOptions);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.doodl6.wechatrobot.processor.EventMessageProcessor;
import com.doodl6.wechatrobot.processor.TextMessageProcessor;
import com.doodl6.wechatrobot.processor.WeChatMessageProcessor;
import com.doodl6.wechatrobot.service.KeywordService;
import com.doodl6.wechatrobot.service.WeChatService;
import com.doodl6.wechatrobot.util.XmlUtil;
import com.google.common.collect.Lists;
Expand All @@ -15,16 +14,14 @@
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

@Slf4j
public class MainHandler implements Handler<RoutingContext> {

private static final Logger LOGGER = Logger.getLogger(KeywordService.class.getName());

private final WeChatService weChatService;

public MainHandler(Vertx vertx, WechatConfig wechatConfig, KeywordConfig keywordConfig) {
Expand All @@ -50,17 +47,18 @@ public void handle(RoutingContext context) {
}
} else {
request.bodyHandler(body -> {
long start = System.currentTimeMillis();
String requestBody = body.toString();
Object result;
try {
result = weChatService.processReceived(requestBody);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "获取来自微信的消息异常", e);
log.error("获取来自微信的消息异常", e);
result = StringUtils.EMPTY;
}
this.responseXml(context, result);
log.info("响应耗时:{}ms", (System.currentTimeMillis() - start));
});

}
}

Expand Down
Loading

0 comments on commit 16afd06

Please sign in to comment.