koishi-plugin-sus-chat
Version:
超简单超棒的AI聊天, 启动!
163 lines (162 loc) • 6.46 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.apply = exports.logger = exports.usage = exports.Config = exports.name = void 0;
const koishi_1 = require("koishi");
const chat_1 = require("./chat");
const js_yaml_1 = __importDefault(require("js-yaml"));
const he_1 = __importDefault(require("he"));
exports.name = "sus-chat";
var config_1 = require("./config");
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
exports.usage = `
# 使用方法可查看: [**文档**](https://beradq.github.io/sus-chat-doc)
`;
class Collected {
collected = {};
max_length;
constructor(max_length) {
this.max_length = max_length;
}
get(cid) {
this.collected[cid]?.shift();
return this.collected[cid] ?? [];
}
add(cid, content) {
this.collected[cid] = [...(this.collected[cid] ?? []), content];
while (this.collected[cid].length > this.max_length) {
this.collected[cid].shift();
}
}
clean(cid) {
this.collected[cid] = [];
}
}
exports.logger = new koishi_1.Logger("sus-chat");
function apply(ctx, config) {
const collected = new Collected(config.functionality.extension_count);
const current_prompt = new CurrentPropmptName(config);
const server = new chat_1.ChatServer(config, config.prompt.pro_prompt
? new chat_1.Prompts(ctx, config.prompt.prompt_directory, config)
: config.prompt.prompt_str);
server.persistence = config.functionality.persistence;
if (config.functionality.persistence)
server.load_recollect(ctx);
async function chat(session, content) {
const liquid = server.prompts?.get_liquid?.(ctx, session);
const prompt_real = await server.get_prompt(current_prompt.get(session.cid), ctx, session);
const my_content = prompt_real.postprocessing({
role: "user",
content,
});
const message = {
role: "user",
content: [...collected.get(session.cid), my_content.content].join("\n"),
};
collected.clean(session.cid);
const result = await server.chat(message, current_prompt.get(session.cid), ctx, session);
return result?.content;
}
ctx.command("sus <content:text>", "与Ai聊天").action(async (s, content) => {
return chat(s.session, content);
});
if (config.prompt.pro_prompt) {
ctx
.command("sus.prom", "提示词相关指令,直接输入可查看提示词列表")
.action(async (_s) => {
return server.prompts.names
.filter((v) => !v.startsWith("."))
.join("\n");
});
ctx
.command("sus.prom.set <name:string>", "设置提示词")
.action(async (s, name) => {
if (!Object.keys(server.prompts.prompts_map).includes(name))
return "提示词不存在";
current_prompt.set(s.session.cid, name);
return "设置成功";
});
ctx
.command("sus.prom.exec <name:string>", "求值提示词")
.action(async (s, name) => {
const result = server.prompts.get(name, ctx, s.session);
return js_yaml_1.default.dump(result.prompts);
});
ctx.command("sus.prom.current", "查看当前提示词").action((s) => {
return current_prompt.get(s.session.cid);
});
ctx.command("sus.reload", "重新载入所有提示词").action(() => {
server.prompts?.reload(ctx, config.prompt.prompt_directory);
return "重载成功";
});
}
ctx
.command("sus.eval <content:text>", "求值 liquid")
.action(async (s, content) => {
const result = await server.evaluate(ctx, s.session, content);
return result;
});
ctx.command("sus.history", "查看聊天记录").action((s) => {
return js_yaml_1.default.dump(server.get_recollect(s.session, current_prompt.get(s.session.cid)));
});
ctx.command("sus.history.clean", "清空聊天记录").action((s) => {
server.update_recollect(ctx, s.session, current_prompt.get(s.session.cid), (_) => []);
collected.clean(s.session.cid);
return "清空成功";
});
// 随机回复与关键词触发与私聊触发
ctx.middleware(async (session, next) => {
const content = he_1.default.decode(session.content);
if (!content)
return next();
let for_key = false;
let k1 = server.prompts?.get_keywords(current_prompt.get(session.cid));
let k2 = config.functionality.tiggering.keywords?.keywords_for_triggering;
if (!(k1 instanceof Array))
k1 = [];
if (!(k2 instanceof Array))
k2 = [];
const keywords = [...k1, ...k2];
for (const key of keywords) {
if (content.includes(key)) {
for_key = true;
break;
}
}
const for_random = config.functionality.tiggering?.random_reply?.enable &&
Math.random() < config.functionality.tiggering?.random_reply?.probability;
const for_direct = config.functionality.tiggering?.when_direct_reply && session?.isDirect;
if (!(for_key || for_random || for_direct))
return next();
const result = await chat?.(session, content);
return result ?? next();
});
if (config.functionality.extension_count >= 1) {
ctx.middleware(async (session, next) => {
const postprocessing = (await server?.get_prompt(current_prompt?.get(session.cid), ctx, session))?.postprocessing;
const message = {
role: "user",
content: session.content,
};
const result = postprocessing(message);
collected?.add(session.cid, result?.content);
return next();
});
}
}
exports.apply = apply;
class CurrentPropmptName {
current_name = {};
config;
constructor(config) {
this.config = config;
}
get(id) {
return this.current_name[id] ?? this.config.prompt.default_prompt ?? "";
}
set(id, name) {
this.current_name[id] = name;
}
}