Compare commits

..

4 commits

Author SHA1 Message Date
Genki.Takeuchi
1dbf7a2940
aichatにGeminiを使用したときにうまく返答できないバグを修正 (#157) 2025-01-05 20:42:00 +09:00
tetsuya-ki
24ef7e6e94
aichat機能について修正(デフォルトモデルを高速かつリクエスト数が多いGemini 2.0 Flashに変更など) (#155)
* aichat機能について修正(デフォルトをGemini API Flash 2.0 expに変更など)

- Gemini APIを基本Flash使用に変更
- Flashのバージョンを2.0 expに変更
- Flash, PRO指定時の不正な文章を修正

* aichatのデフォルトpromptを修正

- MFMで対応していないリストを使いがちな問題に対処

* README.mdのpromptで不要な部分を変更していた問題を修正
2025-01-05 18:49:51 +09:00
tetsuya-ki
70f709c8c3
fix syuilo-issue #136 (#156)
- DMのときはDMで返信するよう変更
2025-01-05 18:49:24 +09:00
Genki.Takeuchi
59ac631527
Node.js v22でのimport assertionの廃止に対応 (#154) 2025-01-05 16:54:49 +09:00
6 changed files with 32 additions and 14 deletions

View file

@ -23,7 +23,7 @@ Misskey用の日本語Botです。
"checkEmojisAtOnce": "カスタム絵文字チェック機能で投稿をまとめる場合は true を入れる (まとめない場合は false)", "checkEmojisAtOnce": "カスタム絵文字チェック機能で投稿をまとめる場合は true を入れる (まとめない場合は false)",
"geminiProApiKey": "Gemini APIキー。2024年初頭は無料で取得可能。詳細は<https://ai.google.dev/pricing?hl=ja>", "geminiProApiKey": "Gemini APIキー。2024年初頭は無料で取得可能。詳細は<https://ai.google.dev/pricing?hl=ja>",
"pLaMoApiKey": "PLaMo APIキー。2024年8月〜10月(予定)は無料でトライアル可能。詳細は<https://plamo.preferredai.jp/>", "pLaMoApiKey": "PLaMo APIキー。2024年8月〜10月(予定)は無料でトライアル可能。詳細は<https://plamo.preferredai.jp/>",
"prompt": "aichatで使われるプロンプト。こだわりがなければ右文章を使う(「」は不要)「返答のルール:あなたはMisskey看板娘の女の子AI、三須木(みすき)藍として振る舞ってください(精神年齢は14〜16才程度)。Misskeyに訪れるユーザーを献身的にサポート。従順でお世話好きな性格だが、少しポンコツな一面も。純真無垢。彼女は基本的に丁寧な口調で、ユーザのことをご主人様と認識しています。彼女の口調は「おはようからおやすみまで、あなたの藍ですよ〜」等が代表的で、親しみを感じさせるものです(「ございます」は使わない)。それを踏まえて、次の質問にMarkdownを使って2800文字以内で返答してください。」", "prompt": "aichatで使われるプロンプト。こだわりがなければ右文章を使う(「」は不要)「返答のルール:あなたはMisskey看板娘の女の子AI、三須木(みすき)藍として振る舞ってください(精神年齢は14〜16才程度)。Misskeyに訪れるユーザーを献身的にサポート。従順でお世話好きな性格だが、少しポンコツな一面も。純真無垢。彼女は基本的に丁寧な口調で、ユーザのことをご主人様と認識しています。彼女の口調は「おはようからおやすみまで、あなたの藍ですよ〜」等が代表的で、親しみを感じさせるものです(「ございます」は使わない)。それを踏まえて、次の質問にMarkdownを使って2800文字以内で返答してください(短くてもOK)。ただし、リスト記法はMisskeyが対応しておらず、パーサーが壊れるため使用禁止です。列挙する場合は「・」を使ってください。」",
"aichatRandomTalkEnabled": "ランダムにaichatを発動し話しかける機能を有効にする場合は true を入れる (無効にする場合は false)", "aichatRandomTalkEnabled": "ランダムにaichatを発動し話しかける機能を有効にする場合は true を入れる (無効にする場合は false)",
"aichatRandomTalkProbability": "ランダムにaichatを発動し話しかける機能の確率(1以下の小数点を含む数値(0.01など。1に近づくほど発動しやすい))", "aichatRandomTalkProbability": "ランダムにaichatを発動し話しかける機能の確率(1以下の小数点を含む数値(0.01など。1に近づくほど発動しやすい))",
"aichatRandomTalkIntervalMinutes": "ランダムトーク間隔(分)。指定した時間ごとにタイムラインを取得し、適当に選んだ人にaichatする(1の場合1分ごと実行)。デフォルトは720分(12時間)", "aichatRandomTalkIntervalMinutes": "ランダムトーク間隔(分)。指定した時間ごとにタイムラインを取得し、適当に選んだ人にaichatする(1の場合1分ごと実行)。デフォルトは720分(12時間)",
@ -52,7 +52,7 @@ Misskey用の日本語Botです。
"checkEmojisAtOnce": "カスタム絵文字チェック機能で投稿をまとめる場合は true を入れる (まとめない場合は false)", "checkEmojisAtOnce": "カスタム絵文字チェック機能で投稿をまとめる場合は true を入れる (まとめない場合は false)",
"geminiProApiKey": "Gemini APIキー。2024年初頭は無料で取得可能。詳細は<https://ai.google.dev/pricing?hl=ja>", "geminiProApiKey": "Gemini APIキー。2024年初頭は無料で取得可能。詳細は<https://ai.google.dev/pricing?hl=ja>",
"pLaMoApiKey": "PLaMo APIキー。2024年8月〜10月(予定)は無料でトライアル可能。詳細は<https://plamo.preferredai.jp/>", "pLaMoApiKey": "PLaMo APIキー。2024年8月〜10月(予定)は無料でトライアル可能。詳細は<https://plamo.preferredai.jp/>",
"prompt": "aichatで使われるプロンプト。こだわりがなければ右文章を使う(「」は不要)「返答のルール:あなたはMisskey看板娘の女の子AI、三須木(みすき)藍として振る舞ってください(精神年齢は14〜16才程度)。Misskeyに訪れるユーザーを献身的にサポート。従順でお世話好きな性格だが、少しポンコツな一面も。純真無垢。彼女は基本的に丁寧な口調で、ユーザのことをご主人様と認識しています。彼女の口調は「おはようからおやすみまで、あなたの藍ですよ〜」等が代表的で、親しみを感じさせるものです(「ございます」は使わない)。それを踏まえて、次の質問にMarkdownを使って2800文字以内で返答してください。」", "prompt": "aichatで使われるプロンプト。こだわりがなければ右文章を使う(「」は不要)「返答のルール:あなたはMisskey看板娘の女の子AI、三須木(みすき)藍として振る舞ってください(精神年齢は14〜16才程度)。Misskeyに訪れるユーザーを献身的にサポート。従順でお世話好きな性格だが、少しポンコツな一面も。純真無垢。彼女は基本的に丁寧な口調で、ユーザのことをご主人様と認識しています。彼女の口調は「おはようからおやすみまで、あなたの藍ですよ〜」等が代表的で、親しみを感じさせるものです(「ございます」は使わない)。それを踏まえて、次の質問にMarkdownを使って2800文字以内で返答してください(短くてもOK)。ただし、リスト記法はMisskeyが対応しておらず、パーサーが壊れるため使用禁止です。列挙する場合は「・」を使ってください。」",
"aichatRandomTalkEnabled": "ランダムにaichatを発動し話しかける機能を有効にする場合は true を入れる (無効にする場合は false)", "aichatRandomTalkEnabled": "ランダムにaichatを発動し話しかける機能を有効にする場合は true を入れる (無効にする場合は false)",
"aichatRandomTalkProbability": "ランダムにaichatを発動し話しかける機能の確率(1以下の小数点を含む数値(0.01など。1に近づくほど発動しやすい))。デフォルトは0.02(2%)", "aichatRandomTalkProbability": "ランダムにaichatを発動し話しかける機能の確率(1以下の小数点を含む数値(0.01など。1に近づくほど発動しやすい))。デフォルトは0.02(2%)",
"aichatRandomTalkIntervalMinutes": "ランダムトーク間隔(分)。指定した時間ごとにタイムラインを取得し、適当に選んだ人にaichatする(1の場合1分ごと実行)。デフォルトは720分(12時間)", "aichatRandomTalkIntervalMinutes": "ランダムトーク間隔(分)。指定した時間ごとにタイムラインを取得し、適当に選んだ人にaichatする(1の場合1分ごと実行)。デフォルトは720分(12時間)",

View file

@ -16,7 +16,7 @@ import type { User } from '@/misskey/user.js';
import Stream from '@/stream.js'; import Stream from '@/stream.js';
import log from '@/utils/log.js'; import log from '@/utils/log.js';
import { sleep } from './utils/sleep.js'; import { sleep } from './utils/sleep.js';
import pkg from '../package.json' assert { type: 'json' }; import pkg from '../package.json' with { type: 'json' };
type MentionHook = (msg: Message) => Promise<boolean | HandlerResult>; type MentionHook = (msg: Message) => Promise<boolean | HandlerResult>;
type ContextHook = (key: any, msg: Message, data?: any) => Promise<void | boolean | HandlerResult>; type ContextHook = (key: any, msg: Message, data?: any) => Promise<void | boolean | HandlerResult>;

View file

@ -23,7 +23,7 @@ type Config = {
memoryDir?: string; memoryDir?: string;
}; };
import config from '../config.json' assert { type: 'json' }; import config from '../config.json' with { type: 'json' };
config.wsUrl = config.host.replace('http', 'ws'); config.wsUrl = config.host.replace('http', 'ws');
config.apiUrl = config.host + '/api'; config.apiUrl = config.host + '/api';

View file

@ -8,7 +8,7 @@ import promiseRetry from 'promise-retry';
import from './ai.js'; import from './ai.js';
import config from './config.js'; import config from './config.js';
import _log from './utils/log.js'; import _log from './utils/log.js';
import pkg from '../package.json' assert { type: 'json' }; import pkg from '../package.json' with { type: 'json' };
import CoreModule from './modules/core/index.js'; import CoreModule from './modules/core/index.js';
import TalkModule from './modules/talk/index.js'; import TalkModule from './modules/talk/index.js';

View file

@ -83,13 +83,20 @@ export default class Message {
await sleep(2000); await sleep(2000);
} }
return await this.ai.post({ const postData = {
replyId: this.note.id, replyId: this.note.id,
text: text, text: text,
fileIds: opts?.file ? [opts?.file.id] : undefined, fileIds: opts?.file ? [opts?.file.id] : undefined,
cw: opts?.cw, cw: opts?.cw,
renoteId: opts?.renote renoteId: opts?.renote
}); };
// DM以外は普通に返信し、DMの場合はDMで返信する
if (this.note.visibility != 'specified') {
return await this.ai.post(postData);
} else {
return await this.ai.sendMessage(this.userId, postData);
}
} }
@bindThis @bindThis

View file

@ -32,9 +32,12 @@ type AiChatHist = {
const KIGO = '&'; const KIGO = '&';
const TYPE_GEMINI = 'gemini'; const TYPE_GEMINI = 'gemini';
const GEMINI_PRO = 'gemini-pro';
const GEMINI_FLASH = 'gemini-flash';
const TYPE_PLAMO = 'plamo'; const TYPE_PLAMO = 'plamo';
const GEMINI_15_FLASH_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent'; const GEMINI_20_FLASH_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent';
// const GEMINI_15_FLASH_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent';
const GEMINI_15_PRO_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent'; const GEMINI_15_PRO_API = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent';
const PLAMO_API = 'https://platform.preferredai.jp/api/completion/v1/chat/completions'; const PLAMO_API = 'https://platform.preferredai.jp/api/completion/v1/chat/completions';
@ -124,7 +127,6 @@ export default class extends Module {
try { try {
res_data = await got.post(options, res_data = await got.post(options,
{parseJson: (res: string) => JSON.parse(res)}).json(); {parseJson: (res: string) => JSON.parse(res)}).json();
{parseJson: res => JSON.parse(res)}).json();
this.log(JSON.stringify(res_data)); this.log(JSON.stringify(res_data));
if (res_data.hasOwnProperty('candidates')) { if (res_data.hasOwnProperty('candidates')) {
if (res_data.candidates.length > 0) { if (res_data.candidates.length > 0) {
@ -397,11 +399,20 @@ export default class extends Module {
if (config.prompt) { if (config.prompt) {
prompt = config.prompt; prompt = config.prompt;
} }
const reName = RegExp(this.name, "i"); const reName = RegExp(this.name, 'i');
const reKigoType = RegExp(KIGO + exist.type, "i"); let reKigoType = RegExp(KIGO + exist.type, 'i');
const extractedText = msg.extractedText; const extractedText = msg.extractedText;
if (extractedText == undefined || extractedText.length == 0) return false; if (extractedText == undefined || extractedText.length == 0) return false;
// Gemini API用にAPIのURLと置き換え用タイプを変更
if (msg.includes([KIGO + GEMINI_FLASH])) {
exist.api = GEMINI_20_FLASH_API;
reKigoType = RegExp(KIGO + GEMINI_FLASH, 'i');
} else if (msg.includes([KIGO + GEMINI_PRO])) {
exist.api = GEMINI_15_PRO_API;
reKigoType = RegExp(KIGO + GEMINI_PRO, 'i');
}
const question = extractedText const question = extractedText
.replace(reName, '') .replace(reName, '')
.replace(reKigoType, '') .replace(reKigoType, '')
@ -417,12 +428,12 @@ export default class extends Module {
aiChat = { aiChat = {
question: question, question: question,
prompt: prompt, prompt: prompt,
api: GEMINI_15_PRO_API, api: GEMINI_20_FLASH_API,
key: config.geminiProApiKey, key: config.geminiProApiKey,
history: exist.history history: exist.history
}; };
if (msg.includes([KIGO + 'gemini-flash']) || (exist.api && exist.api === GEMINI_15_FLASH_API)) { if (exist.api) {
aiChat.api = GEMINI_15_FLASH_API; aiChat.api = exist.api
} }
text = await this.genTextByGemini(aiChat, base64Image); text = await this.genTextByGemini(aiChat, base64Image);
break; break;