feat: 删除冷门识图 & 增加微信文章分享总结

1. 识图用户较少直接删除
2. 增加可能热门的微信文章分享总结
This commit is contained in:
zhiyu 2024-05-23 12:13:47 +08:00
parent 6753bba89c
commit 786e2476b6
5 changed files with 73 additions and 105 deletions

View File

@ -198,23 +198,27 @@ git clone -b 1.6.7-lts https://gitee.com/kyrzy0416/rconsole-plugin.git
<img src="./img/lagrange.webp" width="30%" height="30%">
### 🤖 关于识图 [beta功能]
### 微信文章总结 (完全免费总结)
R 插件集成了我的新作品`gpt2txt`https://github.com/zhiyu1998/gpt2txt
官方Kimi API 暂时没有看到可以联网搜索的选项,所以选用开源的[kimi-free-api](https://github.com/LLM-Red-Team/kimi-free-api)
1. 部署 kimi-free-api
```shell
docker run -it -d --init --name kimi-free-api -p 8000:8000 -e TZ=Asia/Shanghai vinlic/kimi-free-api:latest
```
2. 更改下面两个选项,自行修改 `tools.yaml` 或者锅巴:
使用需要在锅巴 or tools.yaml修改以下内容
```yaml
aiBaseURL: '' # 用于识图的接口kimi默认接口为https://api.moonshot.cn其他服务商自己填写
aiApiKey: '' # 用于识图的api keykimi接口申请https://platform.moonshot.cn/console/api-keys
aiModel: 'claude-3-haiku-20240307' # 模型使用kimi不用填写其他要填写
```
`Kimi`用户只需填写`aiBaseURL``aiApiKey`,其他用户都需要填写!效果展示如下:
- aiBaseURL你服务器的地址
- aiApiKeykimi 的 `refresh_token` F12 -> 应用Application -> Local Storage -> `https://kimi.moonshot.cn` -> 找到)
![imageRecognition.webp](./img/imageRecognition.webp)
- [Kimi开放平台](https://platform.moonshot.cn/console/info)
- [OpenAI](https://platform.openai.com/api-keys)
3. 开始游玩
## 🤺 R插件交流群
扫码不行就575663150
@ -272,6 +276,7 @@ aiModel: 'claude-3-haiku-20240307' # 模型使用kimi不用填写其他要
🌸 感谢以下框架的开源:
- [yt-dlp:A youtube-dl fork with additional features and fixes](https://github.com/yt-dlp/yt-dlp)
- [freyr-js](https://github.com/miraclx/freyr-js)
- [kimi-free-api](https://github.com/LLM-Red-Team/kimi-free-api)
## ☕ 请我喝一杯瑞幸咖啡
如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力!

View File

@ -4,19 +4,14 @@ import fetch from "node-fetch";
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
// http库
import axios from "axios";
// url库
import url from 'url';
// 常量
import { CAT_LIMIT, OCR_PROMPT } from "../constants/constant.js";
import { CAT_LIMIT } from "../constants/constant.js";
// 配置文件
import config from "../model/index.js";
// 书库
import { getYiBook, getZBook, getZHelper } from "../utils/books.js";
// 工具类
import TokenBucket from '../utils/token-bucket.js'
import { downloadImg } from "../utils/common.js";
import { checkAndRemoveFile, toBase64 } from "../utils/file.js";
import { OpenaiBuilder } from "../utils/openai-builder.js";
export class query extends plugin {
/**
@ -63,10 +58,6 @@ export class query extends plugin {
{
reg: "^#(wiki|百科)(.*)$",
fnc: "wiki",
},
{
reg: "^识图",
fnc: "openAiOCR"
}
],
});
@ -74,12 +65,6 @@ export class query extends plugin {
this.toolsConfig = config.getConfig("tools");
// 视频保存路径
this.defaultPath = this.toolsConfig.defaultPath;
// ai接口
this.aiBaseURL = this.toolsConfig.aiBaseURL;
// ai api key
this.aiApiKey = this.toolsConfig.aiApiKey;
// ai模型
this.aiModel = this.toolsConfig.aiModel;
}
async doctor(e) {
@ -338,69 +323,6 @@ export class query extends plugin {
return true;
}
// 识图
async openAiOCR(e) {
if (e.source) {
let reply;
if (e.isGroup) {
reply = (await e.group.getChatHistory(this.e.source.seq, 1)).pop()?.message;
} else {
reply = (await e.friend.getChatHistory(this.e.source.time, 1)).pop()?.message;
}
if (reply) {
for (let val of reply) {
if (val.type == "image") {
e.img = [val.url];
break;
}
}
}
}
if (!e.img) {
this.setContext('openAiProcess');
await e.reply("「R插件 x 月之暗面 Kimi」联合识别提醒你请发送图片", false, { at: true });
} else {
this.openAiProcess();
}
}
/**
* AI引擎提供图像识别能力
* @return {Promise<boolean>}
*/
async openAiProcess() {
if (!this.e.img) {
e.reply("「R插件 x 月之暗面 Kimi」联合识别提醒你无法找到图片")
return true;
}
const img = this.e.img.find(item => item.startsWith("http"));
const parsedUrl = url.parse(img);
const pathArray = parsedUrl.pathname.split('/');
const filenameWithExtension = pathArray[pathArray.length - 1];
const path = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`
// 下载图片
const imgPath = await downloadImg(img, path, filenameWithExtension);
// 构造OpenAI引擎
try {
const { model, ans } = await new OpenaiBuilder()
.setBaseURL(this.aiBaseURL)
.setApiKey(this.aiApiKey)
.setModel(this.aiModel)
.setPrompt(OCR_PROMPT)
.setPath(imgPath)
.build();
const ocrAns = ans.split("▲");
logger.info(ocrAns)
this.e.reply(`「R插件 x ${ model }」联合识别:\n描述:${ ocrAns[1] } \nOCR识别结果${ ocrAns[2] }`);
await checkAndRemoveFile(filenameWithExtension);
} catch (err) {
this.e.reply("「R插件 x 月之暗面 Kimi」联合识别提醒你无法找到图片路径")
logger.error(err);
}
return true;
}
/**
* 限制用户调用默认1分钟1次
* @param e

View File

@ -27,6 +27,7 @@ import {
douyinTypeMap,
REDIS_YUNZAI_ISOVERSEA,
REDIS_YUNZAI_LAGRANGE,
SUMMARY_PROMPT,
transMap,
TWITTER_BEARER_TOKEN,
XHS_NO_WATERMARK_HEADER,
@ -68,6 +69,7 @@ import GeneralLinkAdapter from "../utils/general-link-adapter.js";
import { mid2id } from "../utils/weibo.js";
import { LagrangeAdapter } from "../utils/lagrange-adapter.js";
import path from "path";
import { OpenaiBuilder } from "../utils/openai-builder.js";
export class tools extends plugin {
/**
@ -171,6 +173,10 @@ export class tools extends plugin {
{
reg: "(music.apple.com|open.spotify.com)",
fnc: "freyr"
},
{
reg: "mp.weixin",
fnc: "weixin"
}
],
});
@ -198,6 +204,12 @@ export class tools extends plugin {
this.queue = new PQueue({ concurrency: Number(this.toolsConfig.queueConcurrency) });
// 视频下载的并发数量
this.videoDownloadConcurrency = this.toolsConfig.videoDownloadConcurrency;
// ai接口
this.aiBaseURL = this.toolsConfig.aiBaseURL;
// ai api key
this.aiApiKey = this.toolsConfig.aiApiKey;
// ai模型
this.aiModel = this.toolsConfig.aiModel;
}
// 翻译插件
@ -1446,7 +1458,7 @@ export class tools extends plugin {
logger.info(result.toString());
// 获取信息
const { title, album, artist } = await this.parseFreyrLog(result.toString());
e.reply(`识别:${freyrName}${ title }--${ artist }\n${ album }`);
e.reply(`识别:${ freyrName }${ title }--${ artist }\n${ album }`);
// 判断是否是海外服务器
const isOversea = await this.isOverseasServer();
// 国内服务器解决方案
@ -1481,7 +1493,7 @@ export class tools extends plugin {
// 读取目录中的所有文件和文件夹
fs.readdir(musicPath, (err, files) => {
if (err) {
e.reply(`${freyrName}解析出错,请查看日志!`)
e.reply(`${ freyrName }解析出错,请查看日志!`)
logger.error('读取目录时出错:', err);
return;
}
@ -1496,11 +1508,11 @@ export class tools extends plugin {
});
});
} else {
e.reply(`下载失败!没有找到${freyrName}下载下来文件!`);
e.reply(`下载失败!没有找到${ freyrName }下载下来文件!`);
}
// 计数
tools.#amCount += 1;
logger.info(`当前${freyrName}已经下载了:${ tools.#amCount }`);
logger.info(`当前${ freyrName }已经下载了:${ tools.#amCount }`);
// 定时清理
if (tools.#amCount >= 5) {
await deleteFolderRecursive(currentWorkingDirectory + "/am");
@ -1528,6 +1540,21 @@ export class tools extends plugin {
return { title, album, artist };
}
async weixin(e) {
const urlReg = /(?:https?:\/\/)?mp\.weixin\.qq\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
const wxUrl = urlReg.exec(e.msg)?.[0];
const builder = await new OpenaiBuilder()
.setBaseURL(this.aiBaseURL)
.setApiKey(this.aiApiKey)
.setModel(this.aiModel)
.setPrompt(SUMMARY_PROMPT)
.build();
e.reply(`识别:微信文章,正在为您总结,请稍等...`);
const { ans: kimiAns, model } = await builder.kimi(wxUrl);
e.reply(`「R插件 x ${ model }」联合为您总结内容:\n${ kimiAns }`)
return true;
}
/**
* 哔哩哔哩下载
* @param title

View File

@ -90,3 +90,5 @@ export const OCR_PROMPT = `
图片中提取的文本在适当的地方使用换行符如果文本被某物遮挡请使其不受阻隔以便阅读如果图像中没有文本只需回复描述不要包含任何其他信息
示例 文本编辑器中的代码行 const x = 5; const y = 10; const z = x + y; console.log(z);
`
export const SUMMARY_PROMPT = `请返回您仔细阅读正文后精心写成的详尽笔记`

View File

@ -39,31 +39,43 @@ export class OpenaiBuilder {
}
async build() {
if (this.path === '') {
throw Error("无法获取到文件路径");
return null;
}
// logger.info(this.baseURL, this.apiKey)
// 创建客户端
this.client = new OpenAI({
baseURL: this.baseURL,
apiKey: this.apiKey
});
// 构建
if (this.baseURL.includes("api.moonshot.cn")) {
return await this.kimi(this.path);
} else {
return await this.openai(this.path);
return this;
}
async kimi(query) {
// 请求Kimi
const completion = await this.client.chat.completions.create({
model: "moonshot-v1-8k",
messages: [
{
"role": "system",
"content": this.prompt,
},
{
role: "user",
content: query
},
],
});
return {
"model": "月之暗面 Kimi",
"ans": completion.choices[0].message.content
}
}
async kimi(path) {
async kimi_pic(path) {
let file_object = await this.client.files.create({
file: fs.createReadStream(path),
purpose: "file-extract"
})
let file_content = await (await this.client.files.content(file_object.id)).text()
// 请求OpenAI
// 请求Kimi
const completion = await this.client.chat.completions.create({
model: "moonshot-v1-8k",
messages: [
@ -84,7 +96,7 @@ export class OpenaiBuilder {
}
}
async openai(path) {
async openai_pic(path) {
// 转换base64
const pic = await toBase64(path);
const completion = await this.client.chat.completions.create({