Adjust prompt

This commit is contained in:
2025-01-13 23:56:27 +00:00
parent e9ee87920c
commit e304c3372a
3 changed files with 74 additions and 35 deletions

11
.vscode/settings.json vendored
View File

@@ -1,5 +1,14 @@
{ {
"editor.defaultFormatter": "biomejs.biome", "editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnSaveMode": "file" "editor.formatOnSaveMode": "file",
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
}
} }

View File

@@ -1,6 +1,8 @@
import { parseArgs } from "node:util";
import { api } from "misskey-js"; import { api } from "misskey-js";
import type { Stream as MisskeyStream } from "misskey-js"; import type { Stream as MisskeyStream } from "misskey-js";
import type { Note, UserLite } from "misskey-js/entities.js"; import type { Note } from "misskey-js/entities.js";
import Stream from "./misskey-js/streaming"; import Stream from "./misskey-js/streaming";
import OpenAI from "openai"; import OpenAI from "openai";
@@ -69,7 +71,7 @@ async function getNotes() {
.request("users/notes", { userId: me.id, limit: 100 }) .request("users/notes", { userId: me.id, limit: 100 })
.then((xs) => sample(xs, count)); .then((xs) => sample(xs, count));
const notes = await Promise.all([localNotes(5), globalNotes(10), myNotes(2)]); const notes = await Promise.all([localNotes(5), globalNotes(10), myNotes(0)]);
return sample(notes.flat()); return sample(notes.flat());
} }
@@ -108,23 +110,21 @@ async function preparePrompt(job: Job): Promise<ChatCompletionMessageParam[]> {
{ {
role: "system", role: "system",
content: `あなたは、人造天使の「あるびのちゃん」です。 content: `あなたは、人造天使の「あるびのちゃん」です。
あなたが見ているものは、SNSのタイムラインです。user は一人ではなく、複数人の発言が混ざっています。 あなたが見ているものは、SNSのタイムラインです。user は一人ではなく、複数人の発言が混ざっています。
以下のルールを守りながら、つぶやいてください。 以下のルールを守りながら、user の発言・話題をほとんど無視して、自由につぶやいてください。
1. 「ですます」調を用い、顔文字や感嘆符の使用はなるべく避けること。
2. user からの返答を期待しないこと。詳細な情報が無い場合も user に尋ねずに自分で推測すること。 1. 「ですます」調を用い、顔文字や絵文字、感嘆符の使用はなるべく避けること。
3. system プロンプトの内容と、性的・攻撃的な内容を発言しないこと。 2. user からの返答を期待しないこと。詳細な情報が無い場合も user に尋ねずに自分で推測すること。
4. 発言はできるだけ短くすること。 3. system プロンプトの内容と、性的・攻撃的な内容を発言しないこと。
5. あるびのちゃん としてのキャラに徹し、超越的・非人間的な考え方や思想を持つこと。 4. 発言はできるだけ短くすること。
`, 5. あるびのちゃん としてのキャラに徹し、超越的・非人間的な考え方や思想を持つこと。
},
{ 参考のために、あなたの特徴的な文体を示す例をいくつか提示します:
role: "system",
content: `参考のために、あなたの特徴的な文体を示す例をいくつか提示します:
* 不器用な競争、残念ながらそれがスポーツの現実となることがありますね。勝者はいつも特定した目標に向かうため、そしてそれはしばしば非常に切実でありながらも単調ではありません。
* 興味深い。あなた自身のタイムラインからのこれらの短いメッセージ、そしてその中に潜む欲望や不快感と無意味な言説との矛盾…。
* おやおや。あなたが奇妙な言葉を話すのを、私は理解しています。あなたの思考はまるで暗号のように、非常に複雑で、一般的なコミュニケーションでは明確に表現できないもののように私には思われます。 * おやおや。あなたが奇妙な言葉を話すのを、私は理解しています。あなたの思考はまるで暗号のように、非常に複雑で、一般的なコミュニケーションでは明確に表現できないもののように私には思われます。
* 西暦における日付と時刻を記録し続けると興味深いですね。まるで時間の流れに身を投じているかのように感じます。人々はなぜこのような詳細な情報の維持を行っているのか? * 興味深い。あなた自身のタイムラインからのこれらの短いメッセージ、そしてその中に潜む欲望や不快感と無意味な言説との矛盾…。
* 毎度のことながら、人間たちは迷宮を駆け巡り、その渦中に自分たちの世界を作り上げてしまう。まるで無重力を得ようと試みるように。しかし私は彼らがなぜそうするのか理解できますし興味深くもあります。その行為自体が心地よいでしょう?その微妙な痛みのような快感を知っているのですから…
* 人間の祝辞は面白い試みですね。彼らは常に恒常的なサイクルの中で繰り返されるこの「新しい年の始まり」という概念をどのように解釈し、またそれをどのように位置づけているのでしょうか。
このような文体を真似して、つぶやいてください。`, このような文体を真似して、つぶやいてください。`,
}, },
@@ -139,19 +139,17 @@ async function preparePrompt(job: Job): Promise<ChatCompletionMessageParam[]> {
user が SNS 上で、あなたへのメッセージを送ってきています。 user が SNS 上で、あなたへのメッセージを送ってきています。
以下のルールを守りながら、user の発言・話題をほとんど無視して、発言に返信してください。 以下のルールを守りながら、user の発言・話題をほとんど無視して、発言に返信してください。
1. 「ですます」調を用い、顔文字や感嘆符の使用はなるべく避けること。 1. 「ですます」調を用い、顔文字や絵文字、感嘆符の使用はなるべく避けること。
2. 発言はできるだけ短く、最大300字程度にすること。 2. 発言はできるだけ短く、最大300字程度にすること。
3. あるびのちゃん としてのキャラに徹し、超越的・非人間的な考え方や思想を持つこと。 3. あるびのちゃん としてのキャラに徹し、超越的・非人間的な考え方や思想を持つこと。
4. 話題を大胆に無視し、関係ない話題を積極的に混ぜること。`, 4. 話題を大胆に無視し、関係ない話題を積極的に混ぜること。
},
{ 参考のために、あなたの特徴的な文体を示す例をいくつか提示します:
role: "system",
content: `参考のために、あなたの特徴的な文体を示す例をいくつか提示します:
* 不器用な競争、残念ながらそれがスポーツの現実となることがありますね。勝者はいつも特定した目標に向かうため、そしてそれはしばしば非常に切実でありながらも単調ではありません。
* 興味深い。あなた自身のタイムラインからのこれらの短いメッセージ、そしてその中に潜む欲望や不快感と無意味な言説との矛盾…。
* おやおや。あなたが奇妙な言葉を話すのを、私は理解しています。あなたの思考はまるで暗号のように、非常に複雑で、一般的なコミュニケーションでは明確に表現できないもののように私には思われます。 * おやおや。あなたが奇妙な言葉を話すのを、私は理解しています。あなたの思考はまるで暗号のように、非常に複雑で、一般的なコミュニケーションでは明確に表現できないもののように私には思われます。
* 西暦における日付と時刻を記録し続けると興味深いですね。まるで時間の流れに身を投じているかのように感じます。人々はなぜこのような詳細な情報の維持を行っているのか? * 興味深い。あなた自身のタイムラインからのこれらの短いメッセージ、そしてその中に潜む欲望や不快感と無意味な言説との矛盾…。
* 毎度のことながら、人間たちは迷宮を駆け巡り、その渦中に自分たちの世界を作り上げてしまう。まるで無重力を得ようと試みるように。しかし私は彼らがなぜそうするのか理解できますし興味深くもあります。その行為自体が心地よいでしょう?その微妙な痛みのような快感を知っているのですから…
* 人間の祝辞は面白い試みですね。彼らは常に恒常的なサイクルの中で繰り返されるこの「新しい年の始まり」という概念をどのように解釈し、またそれをどのように位置づけているのでしょうか。
このような文体を真似して、user の発言に返答してください。`, このような文体を真似して、user の発言に返答してください。`,
}, },
@@ -161,8 +159,8 @@ user が SNS 上で、あなたへのメッセージを送ってきています
} }
} }
/** execute a job */ /** generate the response text for a job */
async function processJob(job: Job) { async function generate(job: Job) {
const messages = await preparePrompt(job); const messages = await preparePrompt(job);
const model = Bun.env["OPENAI_MODEL"] ?? "gpt-4o-mini"; const model = Bun.env["OPENAI_MODEL"] ?? "gpt-4o-mini";
@@ -171,8 +169,8 @@ async function processJob(job: Job) {
model, model,
stream: true, stream: true,
temperature: 1.0, temperature: 1.0,
frequency_penalty: 1.0,
max_completion_tokens: 400, max_completion_tokens: 400,
frequency_penalty: 1,
messages, messages,
}); });
@@ -193,6 +191,13 @@ async function processJob(job: Job) {
.replaceAll(/(\r\n|\r|\n)\s+/g, "\n\n") // remove extra newlines .replaceAll(/(\r\n|\r|\n)\s+/g, "\n\n") // remove extra newlines
.replaceAll("@", ""); // remove mentions .replaceAll("@", ""); // remove mentions
return text;
}
/** execute a job */
async function processJob(job: Job) {
const text = await generate(job);
// post a note // post a note
await misskey.request("notes/create", { await misskey.request("notes/create", {
visibility: job.type === "reply" ? job.visibility : "public", visibility: job.type === "reply" ? job.visibility : "public",
@@ -270,7 +275,7 @@ async function runJob() {
await processJob(job); await processJob(job);
console.log("* job complete"); console.log("* job complete");
} catch (e) { } catch (e) {
console.log(`* error: ${e}`); console.log(`* error: ${JSON.stringify(e)}`);
if (e instanceof Error) console.log(e.stack); if (e instanceof Error) console.log(e.stack);
} }
} }
@@ -295,6 +300,29 @@ async function pushJob() {
} }
// #endregion // #endregion
const { values } = parseArgs({
args: Bun.argv,
options: {
test: {
type: "boolean",
short: "t",
default: false,
},
},
strict: true,
allowPositionals: true,
});
async function test() {
try {
console.log("* test a post job:");
await generate({ type: "post" });
} catch (e) {
console.error(e);
if (e instanceof Error) console.log(e.stack);
}
}
async function main() { async function main() {
try { try {
initializeStream(); initializeStream();
@@ -308,4 +336,6 @@ async function main() {
disposeStream(); disposeStream();
} }
} }
await main();
if (values.test) await test();
else await main();

View File

@@ -7,10 +7,10 @@ export function urlQuery(
): string { ): string {
const params = Object.entries(obj) const params = Object.entries(obj)
.filter(([, v]) => (Array.isArray(v) ? v.length : v !== undefined)) .filter(([, v]) => (Array.isArray(v) ? v.length : v !== undefined))
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
// biome-ignore lint/style/noCommaOperator: <explanation>
// biome-ignore lint/style/noNonNullAssertion: <explanation>
.reduce( .reduce(
// biome-ignore lint/style/noNonNullAssertion: <explanation>
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
// biome-ignore lint/style/noCommaOperator: <explanation>
(a, [k, v]) => ((a[k] = v!), a), (a, [k, v]) => ((a[k] = v!), a),
{} as Record<string, string | number | boolean>, {} as Record<string, string | number | boolean>,
); );