Skip to content

Commit 7ea8f1c

Browse files
authored
新增: DeepSeek多角色智能体@ck
1 parent 515fc05 commit 7ea8f1c

File tree

2 files changed

+261
-0
lines changed

2 files changed

+261
-0
lines changed

docs/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,8 @@ features:
9393
- title: Http主动发送@CK
9494
details: 通过 http 请求主动发送消息 `curl -X POST 'http://0.0.0.0:13333' --data '{"ids":["wxid1","wxid2"],"msg":"HelloWorld"}' --location`
9595
link: https://github.com/HdShare/WAuxiliary_Plugin/tree/main/plugins/CK/HttpSend
96+
97+
- title: DeepSeek多角色智能体@CK
98+
details: "监听收到消息时通过DeepSeek AI自动聊天(需修改密钥),不同的群和好友可设置不同的角色。选定对应对话框输入“角色设定: 你是一个逗逼”(不含引号),长按发送按钮即可设定,重复设定可更新角色"
99+
link: https://github.com/HdShare/WAuxiliary_Plugin/tree/main/plugins/CK/DeepSeek
96100
---

plugins/CK/DeepSeek/DeepSeek.java

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
// 此版本对所有私聊生效,群聊只有艾特你时才会生效
2+
import org.json.JSONArray;
3+
import org.json.JSONObject;
4+
5+
import java.util.ArrayList;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
import me.hd.wauxv.plugin.api.callback.PluginCallBack;
11+
12+
// 按用户ID存储对话历史
13+
Map msgListMap = new HashMap();
14+
// DeepSeek API密钥
15+
String deepseekApiKey = "sk-你的密钥";
16+
// 私聊触发关键词(可留空,空数组时允许所有私聊)
17+
String[] privateTriggerWords = {}; // 关键词触发,如不填则无限制{"你好","在吗"}
18+
// **新增:来源ID排除列表(精确匹配,支持私聊/群聊用户ID)**
19+
String[] excludedIds = {}; // 填写需要排除的用户ID
20+
// 违禁词列表(不区分大小写,包含即拦截)
21+
String[] forbiddenWords = {}; // 可自定义违禁词
22+
23+
final String MODEL_REASONER = "deepseek-reasoner"; // 推理模型
24+
final String MODEL_CHAT = "deepseek-chat"; // 聊天模型
25+
String currentModel = MODEL_CHAT; // 默认聊天模型
26+
// 可配置最大对话记录数
27+
int MAX_HISTORY_LENGTH = 100;
28+
29+
// 添加系统角色消息到历史记录(替换旧系统消息)
30+
void addSystemMsg(String talkerId, String content) {
31+
List userMsgList = msgListMap.get(talkerId);
32+
if (userMsgList == null) {
33+
userMsgList = new ArrayList();
34+
msgListMap.put(talkerId, userMsgList);
35+
}
36+
37+
boolean systemMsgFound = false;
38+
for (int i = 0; i < userMsgList.size(); i++) {
39+
Map msg = userMsgList.get(i);
40+
if ("system".equals(msg.get("role"))) {
41+
// 替换已有的系统消息
42+
msg.put("content", content);
43+
log("更新了角色设定" + talkerId);
44+
systemMsgFound = true;
45+
break;
46+
}
47+
}
48+
49+
if (!systemMsgFound) {
50+
// 不存在系统消息,添加新的
51+
Map systemMsg = new HashMap();
52+
systemMsg.put("role", "system");
53+
systemMsg.put("content", content);
54+
userMsgList.add(systemMsg);
55+
log("初始化角色设定: " + talkerId);
56+
}
57+
}
58+
59+
void checkMsgListLimit(String talkerId) {
60+
List userMsgList = msgListMap.get(talkerId);
61+
if (userMsgList == null) return;
62+
63+
if (userMsgList.size() > MAX_HISTORY_LENGTH) {
64+
// 移除最早的消息(保留系统消息)
65+
userMsgList.remove(1);
66+
}
67+
}
68+
69+
// 添加用户消息到历史记录
70+
void addUserMsg(String talkerId, String content) {
71+
List userMsgList = msgListMap.get(talkerId);
72+
if (userMsgList == null) return;
73+
74+
Map msgMap = new HashMap();
75+
msgMap.put("role", "user");
76+
msgMap.put("content", content);
77+
userMsgList.add(msgMap);
78+
79+
checkMsgListLimit(talkerId);
80+
}
81+
82+
// 添加助手消息
83+
void addAssistantMsg(String talkerId, String content) {
84+
List userMsgList = msgListMap.get(talkerId);
85+
if (userMsgList == null) return;
86+
87+
Map msgMap = new HashMap();
88+
msgMap.put("role", "assistant");
89+
msgMap.put("content", content);
90+
userMsgList.add(msgMap);
91+
92+
checkMsgListLimit(talkerId);
93+
}
94+
95+
// 构建DeepSeek API请求参数
96+
Map getDeepSeekParam(String talkerId, String content) {
97+
List userMsgList = msgListMap.get(talkerId);
98+
Map paramMap = new HashMap();
99+
paramMap.put("model", currentModel); // 指定模型
100+
addUserMsg(talkerId, content); // 将用户输入加入历史
101+
paramMap.put("messages", userMsgList); // 完整对话历史
102+
paramMap.put("temperature", 0.7); // 响应随机性控制
103+
paramMap.put("max_tokens", 2000); // 最大返回token数
104+
return paramMap;
105+
}
106+
107+
// 构建API请求头
108+
Map getDeepSeekHeader() {
109+
Map headerMap = new HashMap();
110+
headerMap.put("Content-Type", "application/json"); // JSON格式
111+
headerMap.put("Authorization", "Bearer " + deepseekApiKey); // API认证
112+
return headerMap;
113+
}
114+
115+
// 发送请求到DeepSeek API并处理响应
116+
void sendDeepSeekResp(String talker, String content) {
117+
// 发起POST请求
118+
post("https://api.deepseek.com/v1/chat/completions", // API地址
119+
getDeepSeekParam(talker, content), // 请求参数
120+
getDeepSeekHeader(), // 请求头
121+
new PluginCallBack.HttpCallback() {
122+
// 成功回调
123+
public void onSuccess(int code, String respContent) {
124+
try {
125+
JSONObject jsonObj = new JSONObject(respContent);
126+
JSONArray choices = jsonObj.getJSONArray("choices");
127+
if (choices.length() > 0) {
128+
JSONObject firstChoice = choices.getJSONObject(0);
129+
JSONObject message = firstChoice.getJSONObject("message");
130+
String msgContent = message.getString("content");
131+
132+
// 将AI回复加入对话历史
133+
addAssistantMsg(talker, msgContent);
134+
135+
// 发送回复给用户
136+
sendText(talker, msgContent);
137+
}
138+
} catch (Exception e) {
139+
// 错误处理:解析失败
140+
sendText(talker, "[DeepSeek] 解析响应失败: " + e.getMessage());
141+
}
142+
}
143+
144+
// 失败回调
145+
public void onError(Exception e) {
146+
// 错误处理:请求异常
147+
sendText(talker, "[DeepSeek] 请求异常: " + e.getMessage());
148+
}
149+
}
150+
);
151+
}
152+
153+
// 清空当前对话
154+
void cleanupInactiveSessions(String talkerId) {
155+
msgListMap.remove(talkerId);
156+
}
157+
158+
boolean onLongClickSendBtn(String text) {
159+
String talkerId = getTargetTalker();
160+
if (text.equals("切换模型")) {
161+
currentModel = (currentModel.equals(MODEL_REASONER)) ? MODEL_CHAT : MODEL_REASONER;
162+
return true; // 消耗事件,确保模型切换生效
163+
}
164+
165+
if (text.equals("当前模型")) {
166+
sendText(talkerId, currentModel);
167+
return true;
168+
}
169+
170+
if (text.startsWith("角色设定: ")) {
171+
addSystemMsg(talkerId, text.replace("角色设定: ", ""));
172+
return true;
173+
}
174+
175+
if (text.equals("重置")) {
176+
cleanupInactiveSessions(talkerId);
177+
return true;
178+
}
179+
180+
return false;
181+
}
182+
183+
// 消息处理主入口
184+
void onHandleMsg(Object msgInfoBean) {
185+
// **新增:来源ID排除判断(优先级最高,所有消息先过滤)**
186+
String talkerId = msgInfoBean.getTalker(); // 获取消息来源ID(需根据框架实际API调整,此处假设talker为用户ID)
187+
188+
// 未设定角色直接跳过
189+
if (msgListMap.get(talkerId) == null) {
190+
return;
191+
}
192+
193+
// 忽略自己发送的消息
194+
if (msgInfoBean.isSend()) {
195+
return;
196+
}
197+
198+
String content = msgInfoBean.getContent();
199+
200+
// 群聊消息处理
201+
if (msgInfoBean.isGroupChat()) {
202+
if (!msgInfoBean.isAtMe()) {
203+
return;
204+
}
205+
206+
String talker = msgInfoBean.getTalker(); // 群聊中talker为群成员ID
207+
208+
// 使用通用正则表达式移除所有 @提及
209+
String processedContent = content
210+
.replaceAll("(^|\\s+)@[^\\s\\u2005]+", "") // 匹配并移除 @+任意非空字符
211+
.replaceAll("^\\s+|\\s+$", "") // 去除首尾空格
212+
.replaceAll("\\s+", " "); // 合并中间多个空格为一个
213+
214+
sendDeepSeekResp(talker, processedContent);
215+
}
216+
// 私聊消息处理(含违禁词+关键词判断)
217+
else {
218+
if (msgInfoBean.isText()) {
219+
String userContent = content.trim().toLowerCase(); // 转小写统一校验
220+
String talker = msgInfoBean.getTalker(); // 私聊中talker为对方用户ID
221+
222+
// 第一步:违禁词判断
223+
if (hasForbiddenWord(userContent)) {
224+
return;
225+
}
226+
227+
// 第二步:关键词触发逻辑
228+
boolean containsTrigger = false;
229+
if (privateTriggerWords.length == 0) {
230+
containsTrigger = true;
231+
} else {
232+
for (String word : privateTriggerWords) {
233+
if (userContent.contains(word.toLowerCase())) {
234+
containsTrigger = true;
235+
break;
236+
}
237+
}
238+
}
239+
240+
if (!containsTrigger) {
241+
return;
242+
}
243+
244+
sendDeepSeekResp(talker, userContent);
245+
}
246+
}
247+
}
248+
249+
// **新增:判断消息是否包含违禁词(复用原有逻辑,封装为方法)**
250+
boolean hasForbiddenWord(String content) {
251+
for (String word : forbiddenWords) {
252+
if (content.contains(word)) {
253+
return true;
254+
}
255+
}
256+
return false;
257+
}

0 commit comments

Comments
 (0)