From e5b65ed56085745ce1876cc25942c327dfb3f9eb Mon Sep 17 00:00:00 2001 From: XianSen Zheng Date: Mon, 18 Dec 2023 23:50:26 +0800 Subject: [PATCH] release 0.1.0 (#5) --- README.md | 14 ++++-- demo/help.ts | 39 +++++++++++++++ demo/index.ts | 34 +++++++++++++ demo/llm/multi-llms.ts | 7 +++ package.json | 41 ++++++++-------- src/commands/index.ts | 8 +-- src/core/createAssistant.ts | 16 +++--- src/core/createConversationContext.ts | 3 ++ src/core/keywords.ts | 8 +++ src/core/printHelp.ts | 29 +++++++++++ src/core/processTextMessage.ts | 70 +++++++++++++++------------ src/core/resolveAssistantOptions.ts | 3 ++ src/index.ts | 1 + src/interfaces/assistant.ts | 13 ++++- src/interfaces/context.ts | 12 +++++ src/interfaces/index.ts | 8 +-- src/interfaces/keywords.ts | 6 +++ src/interfaces/llm.ts | 10 ++++ src/interfaces/options.ts | 7 +++ src/llmapi/qwen-api.ts | 1 - src/llms/erniebot.ts | 16 ++---- src/llms/multi.ts | 31 +++++++----- tsconfig.node.json | 2 +- vite.config.ts => vite.config.mts | 0 24 files changed, 281 insertions(+), 98 deletions(-) create mode 100644 demo/help.ts create mode 100644 demo/index.ts create mode 100644 src/core/keywords.ts create mode 100644 src/core/printHelp.ts create mode 100644 src/interfaces/keywords.ts rename vite.config.ts => vite.config.mts (100%) diff --git a/README.md b/README.md index f27b34f..6423be1 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,10 @@ $ pnpm install @zhengxs/wechaty-plugin-assistant 在这里获取你的 [accessToken](https://aistudio.baidu.com/index/accessToken) 值。 ```ts -import { ChatERNIEBot, createAssistant } from '@zhengxs/wechaty-plugin-assistant'; +import { + ChatERNIEBot, + createAssistant, +} from '@zhengxs/wechaty-plugin-assistant'; import { WechatyBuilder } from 'wechaty'; import { QRCodeTerminal } from 'wechaty-plugin-contrib'; @@ -121,7 +124,12 @@ bot.start(); 同时接入多个大模型。 ```ts -import { ChatERNIEBot, ChatQWen, createAssistant, MultiChatModelSwitch } from '@zhengxs/wechaty-plugin-assistant'; +import { + ChatERNIEBot, + ChatQWen, + createAssistant, + MultiChatModelSwitch, +} from '@zhengxs/wechaty-plugin-assistant'; const assistant = createAssistant({ llm: new MultiChatModelSwitch([ @@ -151,7 +159,7 @@ const assistant = createAssistant({ ### 指令 > [!NOTE] -> 后续将去除内置指令,改为按需手动注册。 +> 不再内置指令,改为按需手动注册。 | 名称 | 描述 | 状态 | | -------- | ----------------------------------------------------------------------------------------------------------------------------- | ----- | diff --git a/demo/help.ts b/demo/help.ts new file mode 100644 index 0000000..a954f44 --- /dev/null +++ b/demo/help.ts @@ -0,0 +1,39 @@ +import { + kfc, + ChatType, + createAssistant, + createMockTextMessage, + MultiChatModelSwitch, +} from '../src'; + +const assistant = createAssistant({ + llm: new MultiChatModelSwitch([ + { + name: 'yiyan', + human_name: '文心一言', + input_type: [ChatType.Text], + summary: '文心一言 [百度]', + call(ctx) { + console.log('[文心一言] 收到', ctx.message.text()); + }, + }, + { + name: 'xinghuo', + human_name: '星火认知 [讯飞]', + input_type: [ChatType.Text], + call(ctx) { + console.log('[讯飞星火] 收到', ctx.message.text()); + }, + }, + ]), +}); + +assistant.command.addCommand(kfc) + +async function main() { + assistant.run(); + + await assistant.handler(createMockTextMessage('帮助')); +} + +main(); diff --git a/demo/index.ts b/demo/index.ts new file mode 100644 index 0000000..7a8a443 --- /dev/null +++ b/demo/index.ts @@ -0,0 +1,34 @@ +import { + ChatERNIEBot, + ChatQWen, + MultiChatModelSwitch, + createAssistant, +} from '../src'; +import { WechatyBuilder } from 'wechaty'; +import { EventLogger, QRCodeTerminal } from 'wechaty-plugin-contrib'; + +const ernie = new ChatERNIEBot({ + token: process.env.EB_ACCESS_TOKEN, // 飞桨平台的 token +}); + +const qwen = new ChatQWen({ + apiKey: process.env.QWEN_API_KEY, +}) + +const assistant = createAssistant({ + llm: new MultiChatModelSwitch([ernie, qwen]) +}); + +const bot = WechatyBuilder.build({ + name: 'demo', + puppet: 'wechaty-puppet-wechat4u', + puppetOptions: { uos: true }, +}); + +bot.use(QRCodeTerminal({ small: true })); +bot.use(EventLogger(['login', 'logout', 'error', 'friendship', 'room-invite'])); + +// 作为插件使用 +bot.use(assistant.callback()); + +bot.start(); diff --git a/demo/llm/multi-llms.ts b/demo/llm/multi-llms.ts index ca7aace..c3d8330 100644 --- a/demo/llm/multi-llms.ts +++ b/demo/llm/multi-llms.ts @@ -1,3 +1,4 @@ +import { codeBlock } from 'common-tags'; import { ChatType, createAssistant, @@ -19,6 +20,12 @@ const assistant = createAssistant({ name: 'xinghuo', human_name: '讯飞星火', input_type: [ChatType.Text], + greeting: codeBlock` + 您好,我是讯飞星火认知大模型! + + 能够学习和理解人类的语言,进行多轮对话。 + + 回答问题,高效便捷地帮助人们获取信息、知识和灵感。`, call(ctx) { console.log('[讯飞星火] 收到', ctx.message.text()); }, diff --git a/package.json b/package.json index bb9d676..2a4a784 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zhengxs/wechaty-plugin-assistant", - "version": "0.1.0-alpha.27", + "version": "0.1.0", "main": "./dist/index.cjs", "module": "./dist/index.mjs", "description": "基于 wechaty 的聊天助手插件", @@ -41,10 +41,11 @@ ], "scripts": { "prepare": "husky install", - "dev": "pnpm task --watch ./demo/multi-llms.ts", + "preinstall": "npx only-allow pnpm", + "dev": "pnpm task ./demo/index.ts", "task": "node --no-warnings -r tsconfig-paths/register -r dotenv/config -r jiti/register", "inspect": "node --no-warnings --inspect -r tsconfig-paths/register -r dotenv/config -r jiti/register", - "build": "trash dist dist-types && tsc --noEmit && pnpm lint && vite build", + "build": "trash dist dist-types && pnpm lint && vite build", "lint": "eslint . --ext .ts,.cjs", "lint:fix": "eslint . --ext .ts,.cjs --fix --fix-type [problem,suggestion]", "fmt": "prettier --write \"**/*.{ts,json,,md}\" --log-level warn" @@ -54,7 +55,7 @@ "wechaty": ">=1" }, "dependencies": { - "@zhengxs/ai": "0.1.0-alpha.7", + "@zhengxs/ai": "0.5.0", "@zhengxs/erniebot": "0.1.0-alpha.5", "common-tags": "^1.8.2", "eventemitter3": "^5.0.1", @@ -64,35 +65,35 @@ "keyv": "^4.5.4", "languagedetect": "^2.0.0", "minimist": "^1.2.8", - "openai": "^4.20.1" + "openai": "^4.23.0" }, "devDependencies": { - "@microsoft/api-extractor": "^7.38.3", - "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@microsoft/api-extractor": "^7.38.5", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/common-tags": "^1.8.4", "@types/minimist": "^1.2.5", - "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^6.10.0", - "@typescript-eslint/parser": "^6.10.0", + "@types/node": "^20.10.5", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "dotenv": "^16.3.1", - "eslint": "^8.53.0", - "eslint-config-prettier": "^9.0.0", - "eslint-define-config": "^1.24.1", - "eslint-plugin-import": "^2.29.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-define-config": "^2.0.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-tsdoc": "^0.2.17", "husky": "^8.0.3", "jiti": "^1.21.0", - "lint-staged": "^15.0.2", + "lint-staged": "^15.2.0", "mkdirp": "^3.0.1", - "prettier": "^3.0.3", + "prettier": "^3.1.1", "trash-cli": "^5.0.0", "tsconfig-paths": "^4.2.0", - "typescript": "~5.0.4", - "vite": "^4.5.0", + "typescript": "~5.3.3", + "vite": "^5.0.10", "vite-plugin-checker": "^0.6.2", - "vite-plugin-dts": "^3.6.3", - "vite-plugin-externalize-deps": "^0.7.0", + "vite-plugin-dts": "^3.6.4", + "vite-plugin-externalize-deps": "^0.8.0", "wechaty": "^1.20.2", "wechaty-plugin-contrib": "^1.12.1" }, diff --git a/src/commands/index.ts b/src/commands/index.ts index 94f737d..270a4b3 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -4,10 +4,4 @@ import hot from './hot'; import kfc from './kfc'; import moyu from './moyu'; -export default { - moyu, - hot, - dict, - kfc, - deepl, -}; +export { moyu, hot, dict, kfc, deepl }; diff --git a/src/core/createAssistant.ts b/src/core/createAssistant.ts index 81e1634..46a6561 100644 --- a/src/core/createAssistant.ts +++ b/src/core/createAssistant.ts @@ -1,7 +1,7 @@ import { codeBlock } from 'common-tags'; -import commands from '../commands'; import { Command } from '../integrations/commander'; +import { deepl } from '../commands' import { type Assistant, type AssistantConfig } from '../interfaces'; import { createAssistantHooks } from './createAssistantHooks'; import { createAssistantMonitor } from './createAssistantMonitor'; @@ -10,6 +10,8 @@ import { setupConfigAndLLM } from './setupConfigAndLLM'; import { wechatyMessageHandler } from './wechatyMessageHandler'; import { wechatyPluginCallback } from './wechatyPluginCallback'; +import { keywords } from './keywords' + export function createAssistant(config: AssistantConfig) { const options = resolveAssistantOptions(config); @@ -27,6 +29,8 @@ export function createAssistant(config: AssistantConfig) { chatbotUser: null, wechaty: null, command: program, + keywords, + llm, handler: message => wechatyMessageHandler(assistant, message), callback: () => { return bot => void wechatyPluginCallback(assistant, bot); @@ -38,7 +42,9 @@ export function createAssistant(config: AssistantConfig) { ctx.reply(codeBlock` ⊶ 系统提示 ﹊ - ${llm.human_name} 暂不支持处理此类消息!`); + ${llm.human_name} 暂不支持处理此类消息! + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } }, run() { @@ -50,11 +56,7 @@ export function createAssistant(config: AssistantConfig) { }, }; - program.addCommand(commands.deepl); - program.addCommand(commands.dict); - program.addCommand(commands.hot); - program.addCommand(commands.moyu); - program.addCommand(commands.kfc); + program.addCommand(deepl) setupConfigAndLLM(options, assistant); diff --git a/src/core/createConversationContext.ts b/src/core/createConversationContext.ts index 129240a..0d5d1de 100644 --- a/src/core/createConversationContext.ts +++ b/src/core/createConversationContext.ts @@ -27,6 +27,7 @@ export async function createConversationContext( const { monitor, + llm, options: { debug, maintainers, cache }, } = assistant; @@ -127,6 +128,8 @@ export async function createConversationContext( } const ctx: ConversationContext = { + assistant, + llm: llm, conversationId, conversationTitle, talkerId, diff --git a/src/core/keywords.ts b/src/core/keywords.ts new file mode 100644 index 0000000..5f887e2 --- /dev/null +++ b/src/core/keywords.ts @@ -0,0 +1,8 @@ +import { Keywords } from '../interfaces' + +export const keywords: Keywords = { + newConversation: ['新对话', '新聊天', '重新开始', '重新对话', '重新聊天', '重新对话', '重新开始对话', '重新开始聊天', '重新开始对话'], + stopConversation: ['停', '停止', '停止回复'], + help: ['帮助', '获取帮助'], + sourceCode: ['获取源码', '查看源码'], +} diff --git a/src/core/printHelp.ts b/src/core/printHelp.ts new file mode 100644 index 0000000..16b7261 --- /dev/null +++ b/src/core/printHelp.ts @@ -0,0 +1,29 @@ +import { html } from 'common-tags'; +import { MultiChatModelSwitch } from '../llms' +import { type ConversationContext } from '../interfaces'; + +export function printHelp(ctx: ConversationContext) { + const { llm } = ctx + const llms = llm instanceof MultiChatModelSwitch ? llm.llms : [llm]; + + const commands = Array.from(ctx.assistant.command.commands.values()); + + return ctx.reply(html` + ⊶ 帮助信息 + ﹊ + 口令 + ☛ 重新开始 + ☛ 停止 + ☛ 查看模型 + ☛ 切换 <模型名称> + ☛ 帮助 + ☛ 查看源码 + + 指令 + ${commands.map(cmd => ` ☛ ${cmd.name}`)} + + 模型列表 + ${llms.map(m => ` ☛ ${m.summary || m.human_name}`)} + + 如恶意使用,将拉入黑名单,敬请谅解。`); +} diff --git a/src/core/processTextMessage.ts b/src/core/processTextMessage.ts index db819f7..83248d5 100644 --- a/src/core/processTextMessage.ts +++ b/src/core/processTextMessage.ts @@ -5,10 +5,6 @@ import { toSingleQuotes } from '../vendors'; const REF_MSG_SEP = '- - - - - - - - - - - - - - -'; -const stopWords = ['停', '停止', '停止回复']; - -const newWords = ['新对话', '新聊天', '重新开始', '重置']; - /** * 清理用户消息 * @@ -24,25 +20,14 @@ export async function processTextMessage( assistant: Assistant, ctx: ConversationContext, ) { - const { message, reply } = ctx; + const { message } = ctx; - // 拒绝空内容 - let text = message.text().trim(); - if (!text) { - controller.abort(); - - return reply(codeBlock` - ⊶ 系统提示 - ﹊ - 👀 你想要说什么?`); - } - - const { monitor } = assistant; + const { monitor, keywords } = assistant; // Note: 需要先清理,否则命令无法匹配 // 如果是群聊,清除自身的 @ 信息 if (ctx.conversationTitle) { - message.payload!.text = text = text + message.payload!.text = message.text() // 清理 @机器人 的信息 .replaceAll(`@${ctx.chatbotUserName}`, '') // 去除 @ 符合,但保留 @ 后的内容 @@ -50,29 +35,53 @@ export async function processTextMessage( .trim(); } + // 拒绝空内容 + const text = message.text(); + if (!text) { + return ctx.reply(codeBlock` + ⊶ 系统提示 + ﹊ + 👀 你想要说什么?`); + } + // Note: 如果以斜线开头当作指令处理 // 并且指令允许重复触发 if (text.startsWith('/')) { monitor.stats.command += 1; + return assistant.command.parse(ctx, text.split(' ')) + } + + // 显示帮助 + if (keywords.help.includes(text)) { + return assistant.options.help(ctx) + } + + // 显示源码 + if (keywords.sourceCode.includes(text)) { + return ctx.reply(codeBlock` + 项目地址: - await assistant.command.parse(ctx, text.split(' ')); - return; + https://github.com/zhengxs2018/wechaty-plugin-assistant + + 欢迎 Star 和 Fork。`); } - if (stopWords.includes(text)) { + // 重新开始 + if (keywords.stopConversation.includes(text)) { if (ctx.isLocked) { monitor.stats.skipped += 1; ctx.abort(); } - return reply(codeBlock` + return ctx.reply(codeBlock` ⊶ 系统提示 ﹊ 好的,我将不再回复。如果你有其他问题或需要帮助,请随时告诉我,我将竭诚为您服务。`); } // 允许用户主动终止对话 - if (newWords.includes(text)) { + if (keywords.newConversation.includes(text)) { + // 强制清理上下文 ctx.session.clear(); if (ctx.isLocked) { @@ -81,12 +90,12 @@ export async function processTextMessage( monitor.stats.skipped += 1; } - return reply(codeBlock` - ⊶ 系统提示 - ﹊ - 好的,新的对话从现在开始,期待与您的交流。 + return ctx.reply(codeBlock` + ⊶ 系统提示 + ﹊ + 好的,新的对话从现在开始,期待与您的交流。 - 如有任何问题或需要帮助,请随时提出.`); + 如有任何问题或需要帮助,请随时提出.`); } // Note: 可以解决提升多模型切换命令的优先级 @@ -100,7 +109,7 @@ export async function processTextMessage( // 防止重复提问 if (ctx.isLocked) { - return reply(codeBlock` + return ctx.reply(codeBlock` ⊶ 系统提示 ﹊ 稍等一下,还在思考中...`); @@ -126,8 +135,7 @@ export async function processTextMessage( 我会发送一个被引用消息和一个问题; 你需要根据我引用的消息,来回答我发送的问题; 你应该仅返回和我引用消息和问题相关的内容; - - 被引用的消息: """ ${cleanUserMessage(question)} """; + 被引用的消息: """ ${cleanUserMessage(question)}; """; 这是我的问题: """ ${cleanUserMessage(input)}; """ `; } diff --git a/src/core/resolveAssistantOptions.ts b/src/core/resolveAssistantOptions.ts index 375fa10..e014c76 100644 --- a/src/core/resolveAssistantOptions.ts +++ b/src/core/resolveAssistantOptions.ts @@ -1,16 +1,19 @@ import { type AssistantConfig, type AssistantOptions } from '../interfaces'; import { createMemoryCache } from './createMemoryCache'; +import { printHelp } from './printHelp' export const resolveAssistantOptions = ({ debug = false, testing = false, cache = createMemoryCache(), maintainers = [], + help = printHelp, ...rest }: AssistantConfig): AssistantOptions => ({ ...rest, debug, testing, cache, + help, maintainers, }); diff --git a/src/index.ts b/src/index.ts index b33dead..7b4d808 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +export * from './commands'; export * from './core'; export * from './llms'; export * from './llmapi'; diff --git a/src/interfaces/assistant.ts b/src/interfaces/assistant.ts index d6cc912..e0b996d 100644 --- a/src/interfaces/assistant.ts +++ b/src/interfaces/assistant.ts @@ -1,11 +1,13 @@ import { type ContactSelf, - Message, + type Message, type Wechaty, type WechatyPlugin, } from 'wechaty'; -import { Command } from '../integrations'; +import { type Command } from '../integrations'; +import { type ChatModel } from './llm'; +import { type Keywords } from './keywords'; import { type ConversationContext } from './context'; import { type HookQueue, type HooksName } from './hooks'; import { type AssistantMonitor } from './monitor'; @@ -31,11 +33,18 @@ export interface Assistant { */ command: Command; + /** + * 关键词 + */ + keywords: Keywords; + /** * 助手的钩子 */ hooks: AssistantHooks; + llm: ChatModel + /** * 当前机器人登录的用户 */ diff --git a/src/interfaces/context.ts b/src/interfaces/context.ts index 1da6fb3..8036e53 100644 --- a/src/interfaces/context.ts +++ b/src/interfaces/context.ts @@ -1,8 +1,10 @@ import { type FileBoxInterface } from 'file-box'; import { type Message, type Sayable } from 'wechaty'; +import { type Assistant } from './assistant'; import { type State } from './cache'; import { type LockInfo } from './lock'; +import { type ChatModel } from './llm'; /** * 输入类型 @@ -17,6 +19,16 @@ export enum ChatType { } export type ConversationContext = { + /** + * 助手 + */ + assistant: Assistant; + + /** + * 大模型 + */ + llm: ChatModel; + /** * 对话ID */ diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 249c0ce..0f4e827 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,9 +1,11 @@ export * from './assistant'; export * from './cache'; export * from './context'; +export * from './hooks'; +export * from './keywords'; export * from './llm'; -export * from './options'; -export * from './monitor'; export * from './lock'; +export * from './monitor'; +export * from './options'; +export * from './plugin' export * from './typescript'; -export * from './hooks'; diff --git a/src/interfaces/keywords.ts b/src/interfaces/keywords.ts new file mode 100644 index 0000000..e501129 --- /dev/null +++ b/src/interfaces/keywords.ts @@ -0,0 +1,6 @@ +export interface Keywords { + newConversation: string[] + stopConversation: string[] + help: string[] + sourceCode: string[] +} diff --git a/src/interfaces/llm.ts b/src/interfaces/llm.ts index 49ee07b..fdb0491 100644 --- a/src/interfaces/llm.ts +++ b/src/interfaces/llm.ts @@ -22,6 +22,16 @@ export interface ChatModel extends PluginObject { */ input_type: ChatType[]; + /** + * 简单描述 + */ + summary?: string; + + /** + * 招呼语 + */ + greeting?: string; + /** * @param context - * @param assistant- diff --git a/src/interfaces/options.ts b/src/interfaces/options.ts index 4db842b..bb870d6 100644 --- a/src/interfaces/options.ts +++ b/src/interfaces/options.ts @@ -1,6 +1,8 @@ import { type MemoryCache } from './cache'; +import { ConversationContext } from './context'; import { type ChatModel } from './llm'; import type { PluginObject } from './plugin'; +import { MaybePromise } from './typescript'; type AssistantConfigBase = { /** @@ -23,6 +25,11 @@ type AssistantConfigBase = { */ cache?: MemoryCache; + /** + * 输出帮助信息 + */ + help?: (ctx: ConversationContext) => MaybePromise; + /** * 维护者列表 */ diff --git a/src/llmapi/qwen-api.ts b/src/llmapi/qwen-api.ts index 9f7beeb..77f9b99 100644 --- a/src/llmapi/qwen-api.ts +++ b/src/llmapi/qwen-api.ts @@ -37,7 +37,6 @@ export class QWenAPI extends ChatLLMAPI { chatParams: { model: 'qwen-max', temperature: 0.8, - top_p: 1.0, ...chatParams, }, maxModelTokens, diff --git a/src/llms/erniebot.ts b/src/llms/erniebot.ts index f7c2f85..5914d11 100644 --- a/src/llms/erniebot.ts +++ b/src/llms/erniebot.ts @@ -14,25 +14,17 @@ export interface ChatERNIEBotOptions extends EBApiOptions { } export class ChatERNIEBot implements ChatModel { - name: string; - human_name: string; + name: string ='ernie-bot' + human_name: string = '文心一言'; input_type = [ChatType.Text]; protected api: ERNIEBotAPI; protected limiter: PQueue; constructor(options: ChatERNIEBotOptions) { - const { token, concurrency = 3, interval = 1000, ...rest } = options; + const { concurrency = 3, interval = 1000, ...rest } = options; - if (token) { - this.name = 'qianfan'; - this.human_name = '文心千帆'; - } else { - this.name = 'aistudio'; - this.human_name = '文心飞浆'; - } - - this.api = new ERNIEBotAPI({ token, ...rest }); + this.api = new ERNIEBotAPI(rest); this.limiter = new PQueue({ concurrency, diff --git a/src/llms/multi.ts b/src/llms/multi.ts index 7ba5200..ebf21db 100644 --- a/src/llms/multi.ts +++ b/src/llms/multi.ts @@ -11,9 +11,8 @@ export class MultiChatModelSwitch implements ChatModel { name: string = 'multi-model'; human_name: string = '多模型管理'; input_type: ChatType[] = []; + llms: ChatModel[]; - // TODO 改成数组以支持不同模型的多个实例 - protected llms: ChatModel[]; protected llmMap: Map = new Map(); protected llm?: ChatModel; @@ -46,9 +45,8 @@ export class MultiChatModelSwitch implements ChatModel { .map(llm => ` - ${llm.human_name}`) .join(`\n`)} - 输入 “切换${ - llm?.human_name || '模型名称' - }”,可以切换至其他模型,模型名称支持模糊匹配。`); + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } if (text.startsWith('切换')) { @@ -70,7 +68,8 @@ export class MultiChatModelSwitch implements ChatModel { .map(llm => ` - ${llm.human_name}`) .join(`\n`)} - 提示:必须带 “切换” 关键字,但模型名称支持模糊匹配。`); + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } const found = this.find(searchName.toString()); @@ -78,6 +77,11 @@ export class MultiChatModelSwitch implements ChatModel { if (found) { userConfig.model = found.name; + // 输出招呼语 + if (found.greeting) { + return ctx.reply(found.greeting); + } + return ctx.reply(codeBlock` ⊶ 系统提示 ﹊ @@ -94,7 +98,8 @@ export class MultiChatModelSwitch implements ChatModel { .map(llm => ` - ${llm.human_name}`) .join(`\n`)} - 提示:必须带 “切换” 关键字,但模型名称支持模糊匹配。`); + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } } @@ -105,7 +110,9 @@ export class MultiChatModelSwitch implements ChatModel { return ctx.reply(codeBlock` ⊶ 系统提示 ﹊ - 暂无可用的 AI 模型!`); + 暂无可用的 AI 模型! + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } if (llm.input_type.includes(ctx.type) === false) { @@ -114,7 +121,9 @@ export class MultiChatModelSwitch implements ChatModel { ﹊ ${llm.human_name} 暂不支持处理此类消息! - 请切换至其他模型后再试。`); + 请切换至其他模型后再试。 + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } // 如果当前模型调用失败,尝试其他模型 @@ -149,8 +158,8 @@ export class MultiChatModelSwitch implements ChatModel { ⊶ 系统提示 ﹊ ${llm.human_name} 模型调用失败,可以试试其他模型。 - - 输入 “查看模型” 可以获取当前支持的模型列表。`); + ------------------- + 输入 "帮助" 获取更详细的使用说明。`); } } diff --git a/tsconfig.node.json b/tsconfig.node.json index 298f0aa..2c7f432 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -11,6 +11,6 @@ "allowSyntheticDefaultImports": true, "esModuleInterop": true }, - "include": ["vite.config.ts", "package.json"], + "include": ["vite.config.mts", "package.json"], "exclude": ["node_modules"] } diff --git a/vite.config.ts b/vite.config.mts similarity index 100% rename from vite.config.ts rename to vite.config.mts