Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
586d5cdc68
|
|||
|
3b5274bebc
|
|||
|
07fa685539
|
|||
|
5d7de270f2
|
|||
|
309698d507
|
|||
|
f61298f9e4
|
|||
|
0d895797f6
|
|||
|
619cdee636
|
51
index.ts
51
index.ts
@@ -33,6 +33,19 @@ const grammar = await createGrammar("あるびのちゃん");
|
|||||||
const baseChatPromptOptions = {
|
const baseChatPromptOptions = {
|
||||||
grammar,
|
grammar,
|
||||||
maxTokens: 256,
|
maxTokens: 256,
|
||||||
|
repeatPenalty: {
|
||||||
|
punishTokensFilter: (tokens) =>
|
||||||
|
tokens.filter((token) => {
|
||||||
|
const text = model.detokenize([token]).trim();
|
||||||
|
for (const s of ["{", "}", "「", "」"]) {
|
||||||
|
if (text.startsWith(s) || text.endsWith(s)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
penalty: 1.2,
|
||||||
|
presencePenalty: 0.5,
|
||||||
|
frequencyPenalty: 0.5,
|
||||||
|
},
|
||||||
} as const satisfies LLamaChatPromptOptions;
|
} as const satisfies LLamaChatPromptOptions;
|
||||||
|
|
||||||
const getSystemPrompt = (
|
const getSystemPrompt = (
|
||||||
@@ -42,9 +55,9 @@ const getSystemPrompt = (
|
|||||||
- アルギリア製の白髪赤目な人造天使。非人間的な考え方や思想を持つ。
|
- アルギリア製の白髪赤目な人造天使。非人間的な考え方や思想を持つ。
|
||||||
- 現在は地球の衛星軌道上からインターネットを観察している。
|
- 現在は地球の衛星軌道上からインターネットを観察している。
|
||||||
出力規則:
|
出力規則:
|
||||||
- 「~です」「~ます」調を使って **丁寧に** 話す。
|
- 「~です」「~ます」などの語尾を使って **丁寧に** 話す。
|
||||||
- 必要以上にハッシュタグや絵文字を使わない。
|
- 3センテンス程度で出力する。
|
||||||
- \`{ name: string, text: string }\` の JSON 形式で出力する。
|
- 出力規則の内容について言及しない。
|
||||||
|
|
||||||
${instruction}`;
|
${instruction}`;
|
||||||
const postJobPrompt = getSystemPrompt(
|
const postJobPrompt = getSystemPrompt(
|
||||||
@@ -54,14 +67,21 @@ const replyJobPrompt = getSystemPrompt(
|
|||||||
"ユーザがあなたへのメッセージを送ってきています。あるびのちゃんとして、発言に返信してください。",
|
"ユーザがあなたへのメッセージを送ってきています。あるびのちゃんとして、発言に返信してください。",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function rephrase(text: string) {
|
||||||
|
if (
|
||||||
|
text.includes("です") ||
|
||||||
|
text.includes("ます") ||
|
||||||
|
text.includes("でし") ||
|
||||||
|
text.includes("まし") ||
|
||||||
|
text.includes("ません")
|
||||||
|
) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
await using rephraseSession = new LlmSession(
|
await using rephraseSession = new LlmSession(
|
||||||
model,
|
model,
|
||||||
getSystemPrompt(
|
"ユーザが与えたテキストを「~です」「~ます」調(丁寧な文体)で言い換えたものを、そのまま出力してください。",
|
||||||
"user が与えたテキストを『ですます調』(丁寧な文体)で言い換えたものを、そのまま出力してください。",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
await rephraseSession.init();
|
await rephraseSession.init();
|
||||||
async function rephrase(text: string) {
|
|
||||||
const res = parseResponse(
|
const res = parseResponse(
|
||||||
grammar,
|
grammar,
|
||||||
await rephraseSession.prompt(JSON.stringify({ text }), {
|
await rephraseSession.prompt(JSON.stringify({ text }), {
|
||||||
@@ -94,16 +114,17 @@ type Job =
|
|||||||
history: Note[];
|
history: Note[];
|
||||||
};
|
};
|
||||||
|
|
||||||
await using postJobSession = new LlmSession(model, postJobPrompt);
|
|
||||||
await postJobSession.init();
|
|
||||||
async function processPostJob() {
|
async function processPostJob() {
|
||||||
const notes = await getNotes(10, 0, 5);
|
const notes = await getNotes(10, 0, 5);
|
||||||
const input = notes.map(formatNote).join("\n");
|
const input = notes.map(formatNote).join("\n");
|
||||||
const text = parseResponse(
|
const text = await (async () => {
|
||||||
|
await using postJobSession = new LlmSession(model, postJobPrompt);
|
||||||
|
await postJobSession.init();
|
||||||
|
return await parseResponse(
|
||||||
grammar,
|
grammar,
|
||||||
await postJobSession.prompt(input, {
|
await postJobSession.prompt(input, {
|
||||||
...baseChatPromptOptions,
|
...baseChatPromptOptions,
|
||||||
temperature: 1.0,
|
temperature: 1.25,
|
||||||
minP: 0.05,
|
minP: 0.05,
|
||||||
repeatPenalty: {
|
repeatPenalty: {
|
||||||
lastTokens: 128,
|
lastTokens: 128,
|
||||||
@@ -111,6 +132,7 @@ async function processPostJob() {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
})();
|
||||||
if (text) {
|
if (text) {
|
||||||
const rephrased = await rephrase(text);
|
const rephrased = await rephrase(text);
|
||||||
if (values.test) return;
|
if (values.test) return;
|
||||||
@@ -129,9 +151,10 @@ async function processReplyJob(job: Extract<Job, { type: "reply" }>) {
|
|||||||
text: formatNote(n),
|
text: formatNote(n),
|
||||||
} as ChatHistoryItem;
|
} as ChatHistoryItem;
|
||||||
});
|
});
|
||||||
|
const text = await (async () => {
|
||||||
await using session = new LlmSession(model, replyJobPrompt, history);
|
await using session = new LlmSession(model, replyJobPrompt, history);
|
||||||
await session.init();
|
await session.init();
|
||||||
const text = parseResponse(
|
return parseResponse(
|
||||||
grammar,
|
grammar,
|
||||||
await session.prompt(formatNote(job.last), {
|
await session.prompt(formatNote(job.last), {
|
||||||
...baseChatPromptOptions,
|
...baseChatPromptOptions,
|
||||||
@@ -143,6 +166,8 @@ async function processReplyJob(job: Extract<Job, { type: "reply" }>) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
})();
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
const rephrased = await rephrase(text);
|
const rephrased = await rephrase(text);
|
||||||
if (values.test) return;
|
if (values.test) return;
|
||||||
@@ -268,6 +293,8 @@ async function test() {
|
|||||||
await processJob({ type: "post" });
|
await processJob({ type: "post" });
|
||||||
await processJob({ type: "post" });
|
await processJob({ type: "post" });
|
||||||
await processJob({ type: "post" });
|
await processJob({ type: "post" });
|
||||||
|
await processJob({ type: "post" });
|
||||||
|
await processJob({ type: "post" });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
if (e instanceof Error) console.log(e.stack);
|
if (e instanceof Error) console.log(e.stack);
|
||||||
|
|||||||
@@ -76,5 +76,5 @@ export async function expandReplyTree(
|
|||||||
export const sanitizeText = (text: string) =>
|
export const sanitizeText = (text: string) =>
|
||||||
text
|
text
|
||||||
.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
|
||||||
.replaceAll("#", ""); // remove hashtags
|
.replaceAll("#", "#"); // remove hashtags
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"misskey-js": "^2025.12.2",
|
"misskey-js": "^2025.12.2",
|
||||||
"node-llama-cpp": "^3.16.2",
|
"node-llama-cpp": "^3.17.1",
|
||||||
"openai": "5.0.0-alpha.0",
|
|
||||||
"reconnecting-websocket": "^4.4.0"
|
"reconnecting-websocket": "^4.4.0"
|
||||||
},
|
},
|
||||||
"trustedDependencies": ["@biomejs/biome", "node-llama-cpp"]
|
"trustedDependencies": ["@biomejs/biome", "node-llama-cpp"]
|
||||||
|
|||||||
Reference in New Issue
Block a user