dsh-live2dwaifu 1.2.2 → 1.3.0
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/README.md +8 -1
- package/assets/viewer.js +40 -1
- package/lib/index.js +38 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -231,7 +231,7 @@ python tools/export-dsh-meme.py
|
|
|
231
231
|
| 自动播放动作 | 本机 | 开 | 模型带动作文件时,隔一会儿播一个 |
|
|
232
232
|
| 说话带电子音 | 本机 | 开 | 每个字一声短音 |
|
|
233
233
|
| 复述聊天内容 | 本机 | 开 | 聊天窗口出现新回复时,由她念出来 |
|
|
234
|
-
|
|
|
234
|
+
| 闲置主动说话的间隔 | 服务端 | 30 分钟 | 关闭 / 30 分钟 / 1 小时 / 2 小时 / 4 小时 |
|
|
235
235
|
| 回复附带选项按钮 | 服务端 | 开 | 她觉得需要选择时,气泡上方出现可点按钮 |
|
|
236
236
|
| 记住聊过的内容 | 服务端 | 开 | 关掉就不带记忆、不压缩 |
|
|
237
237
|
| 表情包(四档) | 服务端 | 不使用 | 测试功能,见上面那节 |
|
|
@@ -380,6 +380,13 @@ curl -X POST http://127.0.0.1:<端口>/dsh-live2d/api/push \
|
|
|
380
380
|
|
|
381
381
|
版本号怎么走:动了功能和结构就抬第二位(1.2.0),只补洞和小修就抬第三位(1.2.1)。
|
|
382
382
|
|
|
383
|
+
### 1.3.0
|
|
384
|
+
|
|
385
|
+
- 主动说话的间隔可以调了:⚙ 里一根滑轴,关闭 / 30 分钟 / 1 小时 / 2 小时 / 4 小时。默认从原来的十几分钟放宽到 30 分钟。
|
|
386
|
+
- 提示词改了顺序和说法:当前这句话和规则挪到最后,语料样例挪到前面并注明「只参考语气,别拿去回答」。之前她容易跟着样例跑,答非所问。
|
|
387
|
+
- 规则里加了硬要求:先接住这句话,别答非所问;接不住就说短的,不要编。
|
|
388
|
+
- 语料取样从「最多 3 组问答 + 4 句台词」收到「2 + 2」,少喂点无关内容。
|
|
389
|
+
|
|
383
390
|
### 1.2.2
|
|
384
391
|
|
|
385
392
|
- 人设卡、音色、语料三个页面的按钮和说明改成通用说法:保存/追加保存/覆盖保存/放弃修改/选择文件/播放/关掉。
|
package/assets/viewer.js
CHANGED
|
@@ -44345,10 +44345,11 @@ void main(void)\r
|
|
|
44345
44345
|
["follow", "\u590D\u8FF0\u804A\u5929\u5185\u5BB9"]
|
|
44346
44346
|
];
|
|
44347
44347
|
var SERVER_OPTS = [
|
|
44348
|
-
["proactive", "\u95F2\u7F6E\u65F6\u4E3B\u52A8\u8BF4\u8BDD"],
|
|
44349
44348
|
["choices", "\u56DE\u590D\u9644\u5E26\u9009\u9879\u6309\u94AE"],
|
|
44350
44349
|
["memory", "\u8BB0\u4F4F\u804A\u8FC7\u7684\u5185\u5BB9"]
|
|
44351
44350
|
];
|
|
44351
|
+
var GAP_LABELS = ["\u5173\u95ED", "30 \u5206\u949F", "1 \u5C0F\u65F6", "2 \u5C0F\u65F6", "4 \u5C0F\u65F6"];
|
|
44352
|
+
var GAP_VALUES = [0, 30, 60, 120, 240];
|
|
44352
44353
|
var LOCAL_HINT = {
|
|
44353
44354
|
gaze: "\u89D2\u8272\u7684\u773C\u775B\u548C\u5934\u4F1A\u8DDF\u7740\u9F20\u6807\u79FB\u52A8",
|
|
44354
44355
|
poke: "\u70B9\u89D2\u8272\u7684\u4E0D\u540C\u90E8\u4F4D\u4F1A\u6709\u4E0D\u540C\u53CD\u5E94",
|
|
@@ -44406,6 +44407,44 @@ void main(void)\r
|
|
|
44406
44407
|
row.appendChild(document.createTextNode(label));
|
|
44407
44408
|
box.appendChild(row);
|
|
44408
44409
|
}
|
|
44410
|
+
const hg = document.createElement("h3");
|
|
44411
|
+
hg.textContent = "\u95F2\u7F6E\u4E3B\u52A8\u8BF4\u8BDD\u7684\u95F4\u9694";
|
|
44412
|
+
box.appendChild(hg);
|
|
44413
|
+
const gapWrap = document.createElement("div");
|
|
44414
|
+
gapWrap.className = "opt-col";
|
|
44415
|
+
const gapSlider = document.createElement("input");
|
|
44416
|
+
gapSlider.type = "range";
|
|
44417
|
+
gapSlider.min = "0";
|
|
44418
|
+
gapSlider.max = String(GAP_VALUES.length - 1);
|
|
44419
|
+
gapSlider.step = "1";
|
|
44420
|
+
const curGap = Math.max(
|
|
44421
|
+
0,
|
|
44422
|
+
GAP_VALUES.indexOf(Number(serverSettings.proactiveInterval ?? 30))
|
|
44423
|
+
);
|
|
44424
|
+
gapSlider.value = String(curGap);
|
|
44425
|
+
const gapLab = document.createElement("div");
|
|
44426
|
+
gapLab.className = "opt-lab";
|
|
44427
|
+
gapLab.textContent = GAP_LABELS[curGap];
|
|
44428
|
+
gapSlider.oninput = () => {
|
|
44429
|
+
gapLab.textContent = GAP_LABELS[Number(gapSlider.value)];
|
|
44430
|
+
};
|
|
44431
|
+
gapSlider.onchange = () => {
|
|
44432
|
+
const v2 = GAP_VALUES[Number(gapSlider.value)];
|
|
44433
|
+
serverSettings.proactiveInterval = v2;
|
|
44434
|
+
fetch(BASE + "/api/settings", {
|
|
44435
|
+
method: "POST",
|
|
44436
|
+
headers: { "content-type": "application/json" },
|
|
44437
|
+
body: JSON.stringify({ settings: { proactiveInterval: v2 } })
|
|
44438
|
+
}).catch(() => {
|
|
44439
|
+
});
|
|
44440
|
+
};
|
|
44441
|
+
const gapNote = document.createElement("div");
|
|
44442
|
+
gapNote.className = "opt-note";
|
|
44443
|
+
gapNote.textContent = "\u591A\u4E45\u6CA1\u6709\u5BF9\u8BDD\u4E4B\u540E\uFF0C\u89D2\u8272\u4E3B\u52A8\u8BF4\u4E00\u53E5\u3002\u9009\u300C\u5173\u95ED\u300D\u5C31\u4E0D\u4F1A\u81EA\u5DF1\u5F00\u53E3\u3002";
|
|
44444
|
+
gapWrap.appendChild(gapSlider);
|
|
44445
|
+
gapWrap.appendChild(gapLab);
|
|
44446
|
+
gapWrap.appendChild(gapNote);
|
|
44447
|
+
box.appendChild(gapWrap);
|
|
44409
44448
|
const h3 = document.createElement("h3");
|
|
44410
44449
|
h3.textContent = "\u8868\u60C5\u5305\uFF08\u6D4B\u8BD5\u529F\u80FD\uFF09";
|
|
44411
44450
|
box.appendChild(h3);
|
package/lib/index.js
CHANGED
|
@@ -25,6 +25,8 @@ const MEME_TAGS = {
|
|
|
25
25
|
|
|
26
26
|
const DEFAULT_SETTINGS = {
|
|
27
27
|
proactive: true,
|
|
28
|
+
/** 多久没人说话才自己开口,单位分钟;0 = 关闭 */
|
|
29
|
+
proactiveInterval: 30,
|
|
28
30
|
/** off | own | both | external —— 测试功能,默认关 */
|
|
29
31
|
memesMode: 'off',
|
|
30
32
|
choices: true,
|
|
@@ -202,7 +204,7 @@ function writeCorpus(id, corpus) {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
/** 从语料里挑几条最贴当前对话的,拼成样例 */
|
|
205
|
-
function pickCorpusSamples(corpus, text, toneN =
|
|
207
|
+
function pickCorpusSamples(corpus, text, toneN = 2) {
|
|
206
208
|
const out = [];
|
|
207
209
|
const chars = new Set(String(text || ''));
|
|
208
210
|
const scored = (corpus.pairs || [])
|
|
@@ -212,7 +214,7 @@ function pickCorpusSamples(corpus, text, toneN = 4) {
|
|
|
212
214
|
return { p, hit };
|
|
213
215
|
})
|
|
214
216
|
.sort((a, b) => b.hit - a.hit);
|
|
215
|
-
for (const s of scored.slice(0,
|
|
217
|
+
for (const s of scored.slice(0, 2)) {
|
|
216
218
|
if (s.p.user) out.push('他:' + s.p.user + ' —— 你:' + s.p.assistant);
|
|
217
219
|
else out.push('你:' + s.p.assistant);
|
|
218
220
|
}
|
|
@@ -403,10 +405,13 @@ let lastAutoAt = 0;
|
|
|
403
405
|
|
|
404
406
|
async function maybeTalk(ctx) {
|
|
405
407
|
const cfg = readConfig();
|
|
406
|
-
|
|
408
|
+
const st = settingsOf(cfg);
|
|
409
|
+
const mins = Number(st.proactiveInterval ?? 30);
|
|
410
|
+
if (!(mins > 0)) return;
|
|
411
|
+
const gap = mins * 60 * 1000;
|
|
407
412
|
const now = Date.now();
|
|
408
|
-
if (now - LAST_ACTIVE.at <
|
|
409
|
-
if (now - lastAutoAt <
|
|
413
|
+
if (now - LAST_ACTIVE.at < gap) return;
|
|
414
|
+
if (now - lastAutoAt < gap) return;
|
|
410
415
|
const id = String(cfg.selected || '');
|
|
411
416
|
const meta = id ? readMeta(id) : null;
|
|
412
417
|
if (!meta) return;
|
|
@@ -644,32 +649,31 @@ async function handle(req, res, ctx) {
|
|
|
644
649
|
.slice(-8)
|
|
645
650
|
.map((m) => (m.role === 'user' ? '他:' : '你:') + String(m.text ?? ''))
|
|
646
651
|
.join('\n');
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
.join('\n\n');
|
|
652
|
+
const prompt = [
|
|
653
|
+
personaOf(meta),
|
|
654
|
+
meta.isolation === false ? '' : ISOLATION,
|
|
655
|
+
'现在是 ' + nowText() + '。',
|
|
656
|
+
store.summary ? '之前聊过的,你还记得:\n' + store.summary : '',
|
|
657
|
+
facts.length ? '关于他,你记得这些:\n' + facts.map((f) => '- ' + f).join('\n') : '',
|
|
658
|
+
samples.length ? '这个人平时这么说话,只参考语气,别照抄,也别拿这些去回答:\n' + samples.join('\n') : '',
|
|
659
|
+
lines ? '刚才的对话:\n' + lines : '',
|
|
660
|
+
'他现在说:' + text,
|
|
661
|
+
'先接住他这句话:同意、拒绝、反问、解释、或者提一件和他这句有关的事。别答非所问,别自顾自说别的。',
|
|
662
|
+
'一到两句,四十字以内。不总结他,不讲道理,不说“我理解你”“希望帮到你”“还需要什么”;他没问就别建议。接不住就说短的,不要编。',
|
|
663
|
+
'只输出这句话本身:不要引号,不要旁白,不要括号里的动作。',
|
|
664
|
+
'说话密度参考(别照抄内容):\n' + TALK_SAMPLES,
|
|
665
|
+
st.choices ? '需要他挑的话,最后另起一行写 ||选项一|选项二,最多三项。' : '',
|
|
666
|
+
st.memesMode === 'own' || st.memesMode === 'both'
|
|
667
|
+
? '想附一张贴图,就在最后另起一行写 ||图:名字。能挑的:' +
|
|
668
|
+
readOwnMemes()
|
|
669
|
+
.map((it) => it.label)
|
|
670
|
+
.filter(Boolean)
|
|
671
|
+
.join('、') +
|
|
672
|
+
'。不想配就别写。'
|
|
673
|
+
: '',
|
|
674
|
+
]
|
|
675
|
+
.filter(Boolean)
|
|
676
|
+
.join('\n\n');
|
|
673
677
|
|
|
674
678
|
let reply = '';
|
|
675
679
|
try {
|
|
@@ -738,6 +742,9 @@ async function handle(req, res, ctx) {
|
|
|
738
742
|
for (const k of Object.keys(DEFAULT_SETTINGS)) {
|
|
739
743
|
if (typeof patch?.[k] === 'boolean') next[k] = patch[k];
|
|
740
744
|
}
|
|
745
|
+
if (typeof patch?.proactiveInterval === 'number' && Number.isFinite(patch.proactiveInterval)) {
|
|
746
|
+
next.proactiveInterval = Math.max(0, Math.min(720, Math.round(patch.proactiveInterval)));
|
|
747
|
+
}
|
|
741
748
|
if (typeof patch?.memesMode === 'string' && MEMES_MODES.includes(patch.memesMode)) {
|
|
742
749
|
next.memesMode = patch.memesMode;
|
|
743
750
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-live2dwaifu",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "给 DSH 网页右下角请一个 Live2D 角色:会眨眼、会呼吸、视线跟着鼠标、点她有反应、说话时嘴动、心情变了眉毛跟着动。模型不用内置——谁装谁放自己的文件夹;支持自定义 .exp3.json 表情和 .motion3.json 动作,卡片能拖能缩,背景可换。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|