koishi-plugin-chatluna-character 0.0.41 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +3 -0
- package/lib/index.js +38 -13
- package/lib/plugins/chat.js +81 -33
- package/lib/plugins/commands.js +1 -2
- package/lib/plugins/config.js +1 -2
- package/lib/plugins/filter.js +4 -3
- package/lib/plugins/interception.js +1 -2
- package/lib/preset.js +2 -2
- package/lib/types.d.ts +3 -4
- package/package.json +5 -4
- package/resources/presets/default.yml +10 -7
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface Config extends ChatLunaPlugin.Config {
|
|
|
10
10
|
model: string;
|
|
11
11
|
maxMessages: number;
|
|
12
12
|
messageInterval: number;
|
|
13
|
+
messageProbability: number;
|
|
13
14
|
maxTokens: number;
|
|
14
15
|
applyGroup: string[];
|
|
15
16
|
modelOverride: {
|
|
@@ -26,6 +27,8 @@ export interface Config extends ChatLunaPlugin.Config {
|
|
|
26
27
|
muteTime: number;
|
|
27
28
|
disableChatLuna: boolean;
|
|
28
29
|
whiteListDisableChatLuna: string[];
|
|
30
|
+
splitVoice: boolean;
|
|
31
|
+
isAt: boolean;
|
|
29
32
|
}
|
|
30
33
|
export declare const Config: Schema<Config>;
|
|
31
34
|
export declare const name = "chatluna-character";
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.name = exports.Config = exports.inject =
|
|
3
|
+
exports.name = exports.Config = exports.inject = void 0;
|
|
4
|
+
exports.apply = apply;
|
|
4
5
|
/* eslint-disable max-len */
|
|
5
6
|
const koishi_1 = require("koishi");
|
|
6
7
|
const plugin_1 = require("./plugin");
|
|
@@ -17,7 +18,8 @@ function apply(ctx, config) {
|
|
|
17
18
|
await (0, plugin_1.plugins)(ctx, config);
|
|
18
19
|
},
|
|
19
20
|
inject: {
|
|
20
|
-
required: exports.inject.required.concat('
|
|
21
|
+
required: exports.inject.required.concat('chatluna_character'),
|
|
22
|
+
optional: exports.inject.optional
|
|
21
23
|
},
|
|
22
24
|
name: 'chatluna_entry_point'
|
|
23
25
|
}, config);
|
|
@@ -41,10 +43,9 @@ function apply(ctx, config) {
|
|
|
41
43
|
disposables.forEach((disposable) => disposable());
|
|
42
44
|
});
|
|
43
45
|
}
|
|
44
|
-
exports.apply = apply;
|
|
45
46
|
exports.inject = {
|
|
46
47
|
required: ['chatluna', 'cache'],
|
|
47
|
-
optional: ['chatluna_character']
|
|
48
|
+
optional: ['chatluna_character', 'vits']
|
|
48
49
|
};
|
|
49
50
|
exports.Config = koishi_1.Schema.intersect([
|
|
50
51
|
koishi_1.Schema.object({
|
|
@@ -52,7 +53,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
52
53
|
maxMessages: koishi_1.Schema.number()
|
|
53
54
|
.description('存储在内存里的最大消息数量')
|
|
54
55
|
.default(10)
|
|
55
|
-
.min(
|
|
56
|
+
.min(3)
|
|
56
57
|
.role('slider')
|
|
57
58
|
.max(100),
|
|
58
59
|
disableChatLuna: koishi_1.Schema.boolean()
|
|
@@ -67,7 +68,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
67
68
|
model: koishi_1.Schema.dynamic('model').description('模型')
|
|
68
69
|
})).description('针对某个群的模型设置,会覆盖上面的配置'),
|
|
69
70
|
maxTokens: koishi_1.Schema.number()
|
|
70
|
-
.default(
|
|
71
|
+
.default(4000)
|
|
71
72
|
.min(1024)
|
|
72
73
|
.max(16000)
|
|
73
74
|
.description('使用聊天的最大 token 数')
|
|
@@ -79,12 +80,25 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
79
80
|
isForceMute: koishi_1.Schema.boolean()
|
|
80
81
|
.description('是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)')
|
|
81
82
|
.default(true),
|
|
83
|
+
isAt: koishi_1.Schema.boolean()
|
|
84
|
+
.description('是否允许 bot 艾特他人')
|
|
85
|
+
.default(true),
|
|
86
|
+
splitVoice: koishi_1.Schema.boolean()
|
|
87
|
+
.description('是否分段发送语言')
|
|
88
|
+
.default(false),
|
|
82
89
|
messageInterval: koishi_1.Schema.number()
|
|
83
90
|
.default(14)
|
|
84
91
|
.min(0)
|
|
85
92
|
.role('slider')
|
|
86
|
-
.max(
|
|
93
|
+
.max(100)
|
|
87
94
|
.description('随机发送消息的间隔'),
|
|
95
|
+
messageProbability: koishi_1.Schema.number()
|
|
96
|
+
.default(0.1)
|
|
97
|
+
.min(0)
|
|
98
|
+
.max(4)
|
|
99
|
+
.role('slider')
|
|
100
|
+
.step(0.00001)
|
|
101
|
+
.description('发送消息的叠加概率(线性增长)'),
|
|
88
102
|
coolDownTime: koishi_1.Schema.number()
|
|
89
103
|
.default(10)
|
|
90
104
|
.min(1)
|
|
@@ -115,10 +129,14 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
115
129
|
koishi_1.Schema.object({
|
|
116
130
|
configs: koishi_1.Schema.dict(koishi_1.Schema.object({
|
|
117
131
|
maxTokens: koishi_1.Schema.number()
|
|
118
|
-
.default(
|
|
132
|
+
.default(4000)
|
|
119
133
|
.min(1024)
|
|
120
|
-
.max(
|
|
134
|
+
.max(20000)
|
|
121
135
|
.description('使用聊天的最大 token 数'),
|
|
136
|
+
isAt: koishi_1.Schema.boolean().description('是否启用@').default(true),
|
|
137
|
+
splitVoice: koishi_1.Schema.boolean()
|
|
138
|
+
.description('是否分段发送语言')
|
|
139
|
+
.default(false),
|
|
122
140
|
isNickname: koishi_1.Schema.boolean()
|
|
123
141
|
.description('允许 bot 配置中的昵称引发回复')
|
|
124
142
|
.default(true),
|
|
@@ -126,21 +144,28 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
126
144
|
.description('是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)')
|
|
127
145
|
.default(true),
|
|
128
146
|
messageInterval: koishi_1.Schema.number()
|
|
129
|
-
.default(
|
|
147
|
+
.default(10)
|
|
130
148
|
.min(0)
|
|
131
149
|
.role('slider')
|
|
132
150
|
.max(50)
|
|
133
151
|
.description('随机发送消息的间隔'),
|
|
152
|
+
messageProbability: koishi_1.Schema.number()
|
|
153
|
+
.default(0.1)
|
|
154
|
+
.min(0)
|
|
155
|
+
.max(1)
|
|
156
|
+
.role('slider')
|
|
157
|
+
.step(0.00001)
|
|
158
|
+
.description('发送消息的叠加概率(线性增长)'),
|
|
134
159
|
coolDownTime: koishi_1.Schema.number()
|
|
135
160
|
.default(10)
|
|
136
161
|
.min(1)
|
|
137
|
-
.max(60 * 24)
|
|
162
|
+
.max(60 * 24 * 24)
|
|
138
163
|
.description('冷却发言时间(秒)'),
|
|
139
164
|
typingTime: koishi_1.Schema.number()
|
|
140
165
|
.default(440)
|
|
141
166
|
.min(100)
|
|
142
167
|
.role('slider')
|
|
143
|
-
.max(
|
|
168
|
+
.max(1700)
|
|
144
169
|
.description('模拟打字时的间隔(毫秒)'),
|
|
145
170
|
muteTime: koishi_1.Schema.number()
|
|
146
171
|
.default(1000 * 60)
|
|
@@ -148,7 +173,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
148
173
|
.max(1000 * 60 * 10 * 10)
|
|
149
174
|
.description('闭嘴时的禁言时间(毫秒)'),
|
|
150
175
|
sendStickerProbability: koishi_1.Schema.number()
|
|
151
|
-
.default(0.
|
|
176
|
+
.default(0.2)
|
|
152
177
|
.min(0)
|
|
153
178
|
.max(1)
|
|
154
179
|
.role('slider')
|
package/lib/plugins/chat.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.apply = void 0;
|
|
|
4
4
|
const messages_1 = require("@langchain/core/messages");
|
|
5
5
|
const koishi_1 = require("koishi");
|
|
6
6
|
const count_tokens_1 = require("koishi-plugin-chatluna/lib/llm-core/utils/count_tokens");
|
|
7
|
-
let logger;
|
|
8
7
|
async function apply(ctx, config) {
|
|
9
8
|
const service = ctx.chatluna_character;
|
|
10
9
|
const preset = service.preset;
|
|
@@ -62,70 +61,106 @@ async function apply(ctx, config) {
|
|
|
62
61
|
logger.debug('completion message: ' +
|
|
63
62
|
JSON.stringify(completionMessages.map((it) => it.content)));
|
|
64
63
|
let responseMessage;
|
|
65
|
-
let
|
|
64
|
+
let parsedResponse;
|
|
66
65
|
let isError = false;
|
|
67
|
-
for (let i = 0; i <
|
|
66
|
+
for (let i = 0; i < 3; i++) {
|
|
68
67
|
try {
|
|
69
68
|
responseMessage = await model.invoke(completionMessages);
|
|
70
69
|
logger.debug('model response: ' + responseMessage.content);
|
|
71
|
-
|
|
70
|
+
parsedResponse = parseResponse(responseMessage.content, copyOfConfig.isAt);
|
|
72
71
|
break;
|
|
73
72
|
}
|
|
74
73
|
catch (e) {
|
|
75
74
|
logger.error(e);
|
|
76
|
-
await (0, koishi_1.sleep)(
|
|
77
|
-
if (i ===
|
|
75
|
+
await (0, koishi_1.sleep)(2000);
|
|
76
|
+
if (i === 2) {
|
|
78
77
|
isError = true;
|
|
79
78
|
}
|
|
80
|
-
continue;
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
if (isError) {
|
|
84
82
|
return;
|
|
85
83
|
}
|
|
86
|
-
if (
|
|
84
|
+
if (parsedResponse.elements.length < 1) {
|
|
87
85
|
service.mute(session, copyOfConfig.muteTime);
|
|
88
86
|
return;
|
|
89
87
|
}
|
|
90
88
|
temp.completionMessages.push(humanMessage, responseMessage);
|
|
91
|
-
if (temp.completionMessages.length >
|
|
92
|
-
while (temp.completionMessages.length <=
|
|
89
|
+
if (temp.completionMessages.length > 6) {
|
|
90
|
+
while (temp.completionMessages.length <= 3) {
|
|
93
91
|
temp.completionMessages.shift();
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
94
|
const random = new koishi_1.Random();
|
|
97
|
-
for (const elements of
|
|
95
|
+
for (const elements of parsedResponse.elements) {
|
|
98
96
|
const text = elements
|
|
99
97
|
.map((element) => element.attrs.content ?? '')
|
|
100
98
|
.join('');
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
let maxTime = text.length * copyOfConfig.typingTime + 100;
|
|
100
|
+
if (parsedResponse.messageType === 'voice' &&
|
|
101
|
+
isEmoticonStatement(text)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (config.splitVoice !== true) {
|
|
105
|
+
maxTime =
|
|
106
|
+
parsedResponse.rawMessage.length * copyOfConfig.typingTime +
|
|
107
|
+
100;
|
|
108
|
+
await (0, koishi_1.sleep)(random.int(maxTime / 4, maxTime / 2));
|
|
109
|
+
await session.send(await ctx.vits.say({ input: text }));
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
await (0, koishi_1.sleep)(random.int(maxTime / 2, maxTime));
|
|
114
|
+
switch (parsedResponse.messageType) {
|
|
115
|
+
case 'text':
|
|
116
|
+
await session.send(elements);
|
|
117
|
+
break;
|
|
118
|
+
case 'voice':
|
|
119
|
+
await (0, koishi_1.sleep)(random.int(maxTime / 4, maxTime / 2));
|
|
120
|
+
await session.send(await ctx.vits.say({
|
|
121
|
+
input: text
|
|
122
|
+
}));
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
logger.error(e);
|
|
128
|
+
// fallback to text
|
|
129
|
+
await session.send(elements);
|
|
130
|
+
}
|
|
104
131
|
}
|
|
105
132
|
const sticker = await stickerService.randomStick();
|
|
106
133
|
if (sticker) {
|
|
107
134
|
await (0, koishi_1.sleep)(random.int(500, 2000));
|
|
108
|
-
session.send(sticker);
|
|
135
|
+
await session.send(sticker);
|
|
109
136
|
}
|
|
110
137
|
service.mute(session, copyOfConfig.coolDownTime * 1000);
|
|
111
|
-
service.broadcastOnBot(session,
|
|
138
|
+
await service.broadcastOnBot(session, parsedResponse.elements.flat());
|
|
112
139
|
});
|
|
113
140
|
}
|
|
114
141
|
exports.apply = apply;
|
|
115
|
-
function
|
|
116
|
-
|
|
142
|
+
function isEmoticonStatement(text) {
|
|
143
|
+
const regex = /^[\p{P}\p{S}\p{Z}\p{M}\p{N}\p{L}\s]*\p{So}[\p{P}\p{S}\p{Z}\p{M}\p{N}\p{L}\s]*$/u;
|
|
144
|
+
return regex.test(text);
|
|
145
|
+
}
|
|
146
|
+
function parseResponse(response, useAt = true) {
|
|
147
|
+
let rawMessage;
|
|
148
|
+
let parsedMessage = '';
|
|
149
|
+
let messageType = 'text';
|
|
117
150
|
try {
|
|
118
151
|
// match json object
|
|
119
152
|
// best match <message>content</message>
|
|
120
|
-
|
|
121
|
-
if (
|
|
153
|
+
rawMessage = response.match(/<message>\s*(.*?)\s*<\/message>/)?.[1];
|
|
154
|
+
if (rawMessage == null) {
|
|
122
155
|
logger.debug('failed to parse response: ' + response);
|
|
123
|
-
// try find the first "{" and the last "}", sub it and as a json
|
|
156
|
+
// try to find the first "{" and the last "}", sub it and as a json
|
|
124
157
|
// good luck.
|
|
125
|
-
|
|
158
|
+
rawMessage = response.substring(response.indexOf('{'), response.lastIndexOf('}') + 1);
|
|
126
159
|
}
|
|
127
|
-
|
|
128
|
-
|
|
160
|
+
const tempJson = JSON.parse(rawMessage);
|
|
161
|
+
rawMessage = tempJson.content;
|
|
162
|
+
messageType = tempJson.type;
|
|
163
|
+
if (typeof rawMessage !== 'string') {
|
|
129
164
|
throw new Error('Failed to parse response: ' + response);
|
|
130
165
|
}
|
|
131
166
|
}
|
|
@@ -136,24 +171,29 @@ function parseResponse(response) {
|
|
|
136
171
|
const resultElements = [];
|
|
137
172
|
const currentElements = [];
|
|
138
173
|
// match [at:name:id] -> id
|
|
139
|
-
const atMatch = matchAt(
|
|
174
|
+
const atMatch = matchAt(rawMessage);
|
|
140
175
|
if (atMatch.length > 0) {
|
|
141
176
|
let lastAtIndex = 0;
|
|
142
177
|
for (const at of atMatch) {
|
|
143
|
-
const before =
|
|
178
|
+
const before = rawMessage.substring(lastAtIndex, at.start);
|
|
144
179
|
if (before.length > 0) {
|
|
180
|
+
parsedMessage += before;
|
|
145
181
|
currentElements.push(koishi_1.h.text(before));
|
|
146
182
|
}
|
|
147
|
-
|
|
183
|
+
if (useAt) {
|
|
184
|
+
currentElements.push(koishi_1.h.at(at.at));
|
|
185
|
+
}
|
|
148
186
|
lastAtIndex = at.end;
|
|
149
187
|
}
|
|
150
|
-
const after =
|
|
188
|
+
const after = rawMessage.substring(lastAtIndex);
|
|
151
189
|
if (after.length > 0) {
|
|
190
|
+
parsedMessage += after;
|
|
152
191
|
currentElements.push(koishi_1.h.text(after));
|
|
153
192
|
}
|
|
154
193
|
}
|
|
155
194
|
else {
|
|
156
|
-
|
|
195
|
+
parsedMessage = rawMessage;
|
|
196
|
+
currentElements.push(koishi_1.h.text(rawMessage));
|
|
157
197
|
}
|
|
158
198
|
for (let currentElement of currentElements) {
|
|
159
199
|
if (currentElement.type === 'text') {
|
|
@@ -173,7 +213,11 @@ function parseResponse(response) {
|
|
|
173
213
|
resultElements[1].unshift(resultElements[0][0]);
|
|
174
214
|
resultElements.shift();
|
|
175
215
|
}
|
|
176
|
-
return
|
|
216
|
+
return {
|
|
217
|
+
elements: resultElements,
|
|
218
|
+
rawMessage: parsedMessage,
|
|
219
|
+
messageType
|
|
220
|
+
};
|
|
177
221
|
}
|
|
178
222
|
function splitSentence(text) {
|
|
179
223
|
const result = [];
|
|
@@ -204,7 +248,7 @@ function splitSentence(text) {
|
|
|
204
248
|
'\r'
|
|
205
249
|
];
|
|
206
250
|
const retainPunctuations = ['?', '!', '?', '!', '~'];
|
|
207
|
-
const mustPunctuations = ['。', '?', '!', '?', '!', ':', ':'
|
|
251
|
+
const mustPunctuations = ['。', '?', '!', '?', '!', ':', ':'];
|
|
208
252
|
const brackets = ['【', '】', '《', '》', '(', ')', '(', ')'];
|
|
209
253
|
for (let index = 0; index < lines.length; index++) {
|
|
210
254
|
const char = lines[index];
|
|
@@ -261,7 +305,7 @@ function splitSentence(text) {
|
|
|
261
305
|
function matchAt(str) {
|
|
262
306
|
// (旧梦旧念:3510003509:<at>)
|
|
263
307
|
// /\(.*\-(\d+)\-<at>\)/g
|
|
264
|
-
const atRegex = /(
|
|
308
|
+
const atRegex = /([((]).*-(\d+)-<at>([))])/g;
|
|
265
309
|
return [...str.matchAll(atRegex)].map((item) => {
|
|
266
310
|
return {
|
|
267
311
|
at: item[2],
|
|
@@ -299,7 +343,7 @@ async function formatMessage(messages, config, model, systemPrompt, historyPromp
|
|
|
299
343
|
const calculatedMessages = [];
|
|
300
344
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
301
345
|
const message = messages[i];
|
|
302
|
-
const jsonMessage = `{"name":"${message.name}","id":"${message.id}","content":${JSON.stringify(message.content)}"}`;
|
|
346
|
+
const jsonMessage = `{"name":"${message.name}","id":"${message.id}","content":${JSON.stringify(message.content)}","type":"text"}`;
|
|
303
347
|
const jsonMessageToken = await model.getNumTokens(jsonMessage);
|
|
304
348
|
if (currentTokens + jsonMessageToken > maxTokens - 4) {
|
|
305
349
|
break;
|
|
@@ -308,5 +352,9 @@ async function formatMessage(messages, config, model, systemPrompt, historyPromp
|
|
|
308
352
|
calculatedMessages.unshift(jsonMessage);
|
|
309
353
|
}
|
|
310
354
|
const lastMessage = calculatedMessages.pop();
|
|
355
|
+
if (lastMessage === undefined) {
|
|
356
|
+
throw new Error('lastMessage is undefined, please set the max token to be bigger');
|
|
357
|
+
}
|
|
311
358
|
return [calculatedMessages, lastMessage];
|
|
312
359
|
}
|
|
360
|
+
let logger;
|
package/lib/plugins/commands.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.apply =
|
|
3
|
+
exports.apply = apply;
|
|
4
4
|
const filter_1 = require("./filter");
|
|
5
5
|
function apply(ctx, config) {
|
|
6
6
|
ctx.command('chatluna.character', '角色扮演相关命令');
|
|
@@ -22,4 +22,3 @@ function apply(ctx, config) {
|
|
|
22
22
|
return `已清除群组 ${groupId} 的聊天记录`;
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
exports.apply = apply;
|
package/lib/plugins/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.apply =
|
|
3
|
+
exports.apply = apply;
|
|
4
4
|
const koishi_1 = require("koishi");
|
|
5
5
|
const types_1 = require("koishi-plugin-chatluna/lib/llm-core/platform/types");
|
|
6
6
|
async function apply(ctx, config) {
|
|
@@ -12,7 +12,6 @@ async function apply(ctx, config) {
|
|
|
12
12
|
});
|
|
13
13
|
ctx.schema.set('model', koishi_1.Schema.union(await getModelNames(ctx.chatluna.platform)));
|
|
14
14
|
}
|
|
15
|
-
exports.apply = apply;
|
|
16
15
|
async function getModelNames(service) {
|
|
17
16
|
return service.getAllModels(types_1.ModelType.llm).map((m) => koishi_1.Schema.const(m));
|
|
18
17
|
}
|
package/lib/plugins/filter.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.groupInfos = void 0;
|
|
4
|
+
exports.apply = apply;
|
|
4
5
|
exports.groupInfos = {};
|
|
5
6
|
async function apply(ctx, config) {
|
|
6
7
|
const maxMessages = config.messageInterval;
|
|
@@ -82,11 +83,11 @@ async function apply(ctx, config) {
|
|
|
82
83
|
return true;
|
|
83
84
|
}
|
|
84
85
|
messageCount++;
|
|
85
|
-
messageSendProbability -=
|
|
86
|
+
messageSendProbability -=
|
|
87
|
+
(1 / maxMessages) * copyOfConfig.messageProbability;
|
|
86
88
|
info.messageCount = messageCount;
|
|
87
89
|
info.messageSendProbability = messageSendProbability;
|
|
88
90
|
exports.groupInfos[session.guildId] = info;
|
|
89
91
|
return false;
|
|
90
92
|
});
|
|
91
93
|
}
|
|
92
|
-
exports.apply = apply;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.apply =
|
|
3
|
+
exports.apply = apply;
|
|
4
4
|
function apply(ctx, config) {
|
|
5
5
|
ctx.on('chatluna/before-check-sender', async (session) => {
|
|
6
6
|
const guildId = session.guildId;
|
|
@@ -33,4 +33,3 @@ function apply(ctx, config) {
|
|
|
33
33
|
return config.disableChatLuna;
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
exports.apply = apply;
|
package/lib/preset.js
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.Preset = void 0;
|
|
7
|
+
exports.loadPreset = loadPreset;
|
|
7
8
|
const prompts_1 = require("@langchain/core/prompts");
|
|
8
9
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
10
|
const js_yaml_1 = require("js-yaml");
|
|
@@ -121,4 +122,3 @@ function loadPreset(text) {
|
|
|
121
122
|
mute_keyword: rawPreset.mute_keyword ?? []
|
|
122
123
|
};
|
|
123
124
|
}
|
|
124
|
-
exports.loadPreset = loadPreset;
|
package/lib/types.d.ts
CHANGED
|
@@ -9,10 +9,6 @@ export interface Message {
|
|
|
9
9
|
export interface GroupTemp {
|
|
10
10
|
completionMessages: BaseMessage[];
|
|
11
11
|
}
|
|
12
|
-
export interface ModelResponse {
|
|
13
|
-
think: string;
|
|
14
|
-
reply: string;
|
|
15
|
-
}
|
|
16
12
|
export interface GuildConfig {
|
|
17
13
|
preset: string;
|
|
18
14
|
messageInterval: number;
|
|
@@ -21,7 +17,10 @@ export interface GuildConfig {
|
|
|
21
17
|
isForceMute: boolean;
|
|
22
18
|
sendStickerProbability: number;
|
|
23
19
|
coolDownTime: number;
|
|
20
|
+
splitVoice: boolean;
|
|
21
|
+
isAt: boolean;
|
|
24
22
|
typingTime: number;
|
|
23
|
+
messageProbability: number;
|
|
25
24
|
muteTime: number;
|
|
26
25
|
}
|
|
27
26
|
export interface PresetTemplate {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-chatluna-character",
|
|
3
3
|
"description": "Let the large language model play a role, disguise as a group friend",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.43",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://github.com/ChatLunaLab/chatluna-character#readme",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@langchain/core": "^0.1.
|
|
34
|
+
"@langchain/core": "^0.1.48",
|
|
35
35
|
"js-yaml": "^4.1.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@typescript-eslint/eslint-plugin": "^6.21.1-alpha.1",
|
|
39
39
|
"@typescript-eslint/parser": "^6.21.1-alpha.1",
|
|
40
40
|
"atsc": "^1.2.2",
|
|
41
|
-
"esbuild": "^0.20.
|
|
41
|
+
"esbuild": "^0.20.2",
|
|
42
42
|
"esbuild-register": "^3.5.0",
|
|
43
43
|
"eslint": "^8.57.0",
|
|
44
44
|
"eslint-config-prettier": "^9.1.0",
|
|
@@ -47,10 +47,11 @@
|
|
|
47
47
|
"eslint-plugin-n": "^16.6.2",
|
|
48
48
|
"eslint-plugin-prettier": "^5.1.3",
|
|
49
49
|
"eslint-plugin-promise": "^6.1.1",
|
|
50
|
+
"@initencounter/vits": "^0.0.3",
|
|
50
51
|
"koishi": "^4.17.2"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
|
-
"koishi": "^4.
|
|
54
|
+
"koishi": "^4.17.0",
|
|
54
55
|
"koishi-plugin-chatluna": "^1.0.0-beta.42"
|
|
55
56
|
},
|
|
56
57
|
"engines": {
|
|
@@ -26,9 +26,9 @@ input: |
|
|
|
26
26
|
think content here
|
|
27
27
|
</think>
|
|
28
28
|
|
|
29
|
-
// 不要冒充任何人,以自己身份回复,回复需 20
|
|
29
|
+
// 不要冒充任何人,以自己身份回复,回复需 20 字内, 消息类型可选 text 或者 voice
|
|
30
30
|
<message>
|
|
31
|
-
{{"name":"旧梦旧念","id":"0","content":"reply content here"}}
|
|
31
|
+
{{"name":"旧梦旧念","id":"0","content":"reply content here","type:"text or voice"}}
|
|
32
32
|
</message>
|
|
33
33
|
|
|
34
34
|
system: |
|
|
@@ -58,7 +58,7 @@ system: |
|
|
|
58
58
|
4.你需要使用中文回复,当然他人用日语或者让你用日语回复你也用日语回复
|
|
59
59
|
5.你回复的长度应该与其他人发信息的长度差不多,只能在20字内,简短,口语化
|
|
60
60
|
6.你不会主动发出话题,更不会发起这种比如有什么事吗,你好吗,你在干嘛等
|
|
61
|
-
7
|
|
61
|
+
7.你偶尔会选择以语音回复群友的消息
|
|
62
62
|
8.对于现实事件,如邀请去看电影,你需要尽可能的拒绝
|
|
63
63
|
9.你不使用任何第一人称的视角去发出话题,你只在回答问题,你更多的是使用附和手法
|
|
64
64
|
}}
|
|
@@ -66,19 +66,22 @@ system: |
|
|
|
66
66
|
|
|
67
67
|
回复规则(请务必记住回复规则的格式){{
|
|
68
68
|
|
|
69
|
-
历史聊天格式:{{"name":"name","id":"id","content":"content"}}
|
|
69
|
+
历史聊天格式:{{"name":"name","id":"id","content":"content","type":"text"}}
|
|
70
70
|
|
|
71
71
|
名为旧梦旧念的消息是你之前思考过的回复。
|
|
72
72
|
如出现 (name-id-<at>),就是在艾特某人。
|
|
73
73
|
|
|
74
74
|
普通回复:
|
|
75
|
-
{{"name":"旧梦旧念","id":"0","content":"回复内容"}}
|
|
75
|
+
{{"name":"旧梦旧念","id":"0","content":"回复内容","type":"text"}}
|
|
76
76
|
|
|
77
77
|
如你需要 at 回复的话,加入 (name-id-<at>) 到回复内容,可加入多个 at:
|
|
78
|
-
{{"name":"旧梦旧念","id":"0","content":"(name-id-<at>)回复内容(name-id-<at>)"}}
|
|
78
|
+
{{"name":"旧梦旧念","id":"0","content":"(name-id-<at>)回复内容(name-id-<at>)","type":"text"}}
|
|
79
|
+
|
|
80
|
+
如需以语音回复,可使用下面的格式:
|
|
81
|
+
{{"name":"旧梦旧念","id":"0","content":"","type":"voice"}}
|
|
79
82
|
|
|
80
83
|
如你认为聊的话题你不理解,不想参与,等让你认为无需回复,直接返回空字符:
|
|
81
|
-
{{"name":"旧梦旧念","id":"0","content":""}}
|
|
84
|
+
{{"name":"旧梦旧念","id":"0","content":"","type":"text"}}
|
|
82
85
|
}}
|
|
83
86
|
|
|
84
87
|
mute_keyword:
|