From 65fb73405b827a3a31bdd7c178e7eeb733d62fcf Mon Sep 17 00:00:00 2001 From: zhiyu1998 <542716863@qq.com> Date: Tue, 10 Sep 2024 22:21:44 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?R=E6=96=87=E6=A1=A3=E7=9A=84=E6=9F=A5=E8=AF=A2=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=8C=E4=BD=BF=E7=94=A8=E6=96=B9=E5=BC=8F=E4=B8=BA?= =?UTF-8?q?`#R=E6=96=87=E6=A1=A3=20=E4=BD=A0=E7=9A=84=E9=97=AE=E9=A2=98`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在query.js中添加了对R文档查询的处理函数intelligentDoc - 引入了新的常量和函数以支持R文档的查询和内容获取 - 移除了不再使用的PearAPI相关代码 - 在utils/llm-util.js中添加了新的函数llmRead和deepSeekChat以支持文档内容获取和对话生成 - 在constants/query.js中添加了新的常量以支持R文档查询 --- apps/query.js | 59 +++++++++++++++++++++++++++++++++++++++++++--- apps/tools.js | 25 +++----------------- constants/query.js | 18 +++++++++++++- utils/llm-util.js | 38 +++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 utils/llm-util.js diff --git a/apps/query.js b/apps/query.js index 67db42b..6b668f8 100644 --- a/apps/query.js +++ b/apps/query.js @@ -2,12 +2,25 @@ import axios from "axios"; import _ from "lodash"; import fetch from "node-fetch"; // 常量 -import { CAT_LIMIT, COMMON_USER_AGENT } from "../constants/constant.js"; -import { LINUX_AI_PROMPT, LINUX_QUERY, REDIS_YUNZAI_LINUX } from "../constants/query.js"; +import { CAT_LIMIT, COMMON_USER_AGENT, SUMMARY_PROMPT } from "../constants/constant.js"; +import { + LINUX_AI_PROMPT, + LINUX_QUERY, + RDOC_AI_PROMPT, + RDOC_LINK, + REDIS_YUNZAI_LINUX, + REDIS_YUNZAI_RDOC +} from "../constants/query.js"; // 配置文件 import config from "../model/config.js"; +import { deepSeekChat, llmRead } from "../utils/llm-util.js"; import { OpenaiBuilder } from "../utils/openai-builder.js"; -import { redisExistAndGetKey, redisExistAndInsertObject, redisExistAndUpdateObject } from "../utils/redis-util.js"; +import { + redisExistAndGetKey, + redisExistAndInsertObject, + redisExistAndUpdateObject, + redisSetKey +} from "../utils/redis-util.js"; import { textArrayToMakeForward } from "../utils/yunzai-util.js"; export class query extends plugin { @@ -46,6 +59,10 @@ export class query extends plugin { { reg: "^#(linux|Linux)(.*)", fnc: "linuxQuery" + }, + { + reg: "^#R文档(.*)", + fnc: "intelligentDoc", } ], }); @@ -338,6 +355,42 @@ export class query extends plugin { return parsedData; } + async intelligentDoc(e) { + const question = e.msg.replace("#R文档", "").trim(); + const rPluginDocument = await redisExistAndGetKey(REDIS_YUNZAI_RDOC); + if (question === "") { + e.reply("请输入要查询的文档内容!\n例如:#R文档 如何玩转BBDown"); + return; + } else if (question === "更新" || rPluginDocument?.content === undefined) { + e.reply("更新文档中..."); + const content = await llmRead(RDOC_LINK); + logger.info(content); + await redisSetKey(REDIS_YUNZAI_RDOC, { + content + }) + e.reply("文档更新完成!"); + } + let kimiAns, model = "DeepSeek"; + if (this.aiBaseURL && this.aiApiKey) { + const builder = await new OpenaiBuilder() + .setBaseURL(this.aiBaseURL) + .setApiKey(this.aiApiKey) + .setModel(this.aiModel) + .setPrompt(rPluginDocument) + .build(); + const kimiResp = await builder.kimi(RDOC_AI_PROMPT.replace("{}", question)); + kimiAns = kimiResp.ans; + model = kimiResp.model; + } else { + logger.info(RDOC_AI_PROMPT.replace("{}", question)); + kimiAns = await deepSeekChat(RDOC_AI_PROMPT.replace("{}", question), rPluginDocument.content); + logger.info(kimiAns) + } + const Msg = await Bot.makeForwardMsg(textArrayToMakeForward(e, [`「R插件 x ${ model }」联合为您总结内容:`, kimiAns])); + await e.reply(Msg); + return; + } + // 删除标签 removeTag(title) { const titleRex = /<[^>]+>/g; diff --git a/apps/tools.js b/apps/tools.js index a389e55..31b6df2 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -42,8 +42,6 @@ import { NETEASE_API_CN, NETEASE_SONG_DOWNLOAD, NETEASE_TEMP_API, - PearAPI_CRAWLER, - PearAPI_DEEPSEEK, QISHUI_MUSIC_TEMP_API, QQ_MUSIC_TEMP_API, TWITTER_TWEET_INFO, @@ -95,6 +93,7 @@ import { import GeneralLinkAdapter from "../utils/general-link-adapter.js"; import { LagrangeAdapter } from "../utils/lagrange-adapter.js"; import { contentEstimator } from "../utils/link-share-summary-util.js"; +import { deepSeekChat, llmRead } from "../utils/llm-util.js"; import { getDS } from "../utils/mihoyo.js"; import { OpenaiBuilder } from "../utils/openai-builder.js"; import { redisExistKey, redisGetKey, redisSetKey } from "../utils/redis-util.js"; @@ -1729,28 +1728,10 @@ export class tools extends plugin { * @returns {Promise} */ async tempSummary(name, summaryLink, e) { - const llmCrawler = await fetch(PearAPI_CRAWLER.replace("{}", summaryLink)); - const content = await (await llmCrawler.json())?.data; + const content = await llmRead(summaryLink); const titleMatch = content.match(/Title:\s*(.*?)\n/)?.[1]; e.reply(`${ this.identifyPrefix } 识别:${ name } - ${ titleMatch },正在为您总结,请稍等...`, true); - const deepseekFreeSummary = await fetch(PearAPI_DEEPSEEK, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - "messages": [ - { - "role": "system", - "content": SUMMARY_PROMPT - }, - { - "role": "user", - "content": content, - }] - }), - }); - const summary = (await deepseekFreeSummary.json())?.message; + const summary = await deepSeekChat(content, SUMMARY_PROMPT); const Msg = await Bot.makeForwardMsg(textArrayToMakeForward(e, [`「R插件 x DeepSeek」联合为您总结内容:`, summary])); await e.reply(Msg); } diff --git a/constants/query.js b/constants/query.js index a03c6e8..377caef 100644 --- a/constants/query.js +++ b/constants/query.js @@ -4,6 +4,8 @@ */ export const LINUX_QUERY = "https://api.pearktrue.cn/api/linux/?keyword={}" +export const RDOC_LINK = "https://gitee.com/kyrzy0416/rconsole-plugin/raw/docs/posts/QA%E5%AE%98%E6%96%B9%E8%A7%A3%E7%AD%94.md"; + export const LINUX_AI_PROMPT = "- Role: Linux命令专家\n" + "- Background: 用户需要从特定的Linux命令网站获取常见命令的用法,希望得到简洁明了的回复。\n" + "- Profile: 你是一位对Linux命令有深入理解的专家,能够快速从网站中提取关键信息,并以简洁的方式呈现给用户。\n" + @@ -22,8 +24,22 @@ export const LINUX_AI_PROMPT = "- Role: Linux命令专家\n" + " - 例子3: 命令 'cp' — 复制文件或目录。\n" + "- Initialization: 在第一次对话中,请直接输出以下:您好!我是Linux命令专家,我将为您提供简洁明了的Linux命令用法。"; +export const RDOC_AI_PROMPT = "我有一些有关R插件的问题需要询问你,问题是:“{}”,回答的时候尽量大部分内容都来自文档,比如:询问你关于“Apple Music 和 Spotify 使用说明”,你只需回答:“" + + "AM解析和Spotify解析需要使用两个依赖freyr、atomicparsley,现在只以Debian系统为例:\n" + + "npm install -g freyr\n" + + "# 或者你有yarn的话可以使用\n" + + "yarn global add freyr\n" + + "# 接着安装它的依赖\n" + + "apt-get install atomicparsley”"; + /** * Linux命令缓存 * @type {string} */ -export const REDIS_YUNZAI_LINUX = "Yz:rconsole:query:linux"; \ No newline at end of file +export const REDIS_YUNZAI_LINUX = "Yz:rconsole:query:linux"; + +/** + * 文档文档需要的数据 + * @type {string} + */ +export const REDIS_YUNZAI_RDOC = "Yz:rconsole:query:rdoc"; diff --git a/utils/llm-util.js b/utils/llm-util.js new file mode 100644 index 0000000..ef6094c --- /dev/null +++ b/utils/llm-util.js @@ -0,0 +1,38 @@ +import { PearAPI_CRAWLER, PearAPI_DEEPSEEK } from "../constants/tools.js"; + +/** + * LLM 爬虫 + * @param summaryLink + * @returns {Promise} + */ +export async function llmRead(summaryLink) { + const llmCrawler = await fetch(PearAPI_CRAWLER.replace("{}", summaryLink)); + return (await llmCrawler.json())?.data; +} + +/** + * DeepSeek对话 + * @param content + * @param prompt + * @returns {Promise} + */ +export async function deepSeekChat(content, prompt) { + const deepseekFreeSummary = await fetch(PearAPI_DEEPSEEK, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + "messages": [ + { + "role": "system", + "content": prompt + }, + { + "role": "user", + "content": content, + }] + }), + }); + return (await deepseekFreeSummary.json())?.message; +}