This commit is contained in:
2026-03-12 16:26:45 +09:00
parent 309698d507
commit 5d7de270f2
4 changed files with 37 additions and 39 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -2,13 +2,7 @@ import { parseArgs } from "node:util";
import { Stream } from "misskey-js"; import { Stream } from "misskey-js";
import type { Note } from "misskey-js/entities.js"; import type { Note } from "misskey-js/entities.js";
import type { ChatHistoryItem, LLamaChatPromptOptions } from "node-llama-cpp"; import type { ChatHistoryItem, LLamaChatPromptOptions } from "node-llama-cpp";
import { import { LlmSession, createGrammar, getModel, parseResponse } from "./lib/llm";
LlmSession,
createBias,
createGrammar,
getModel,
parseResponse,
} from "./lib/llm";
import { import {
expandReplyTree, expandReplyTree,
getNotes, getNotes,
@@ -36,11 +30,28 @@ const modelName =
console.log(`* loading model '${modelName}'`); console.log(`* loading model '${modelName}'`);
const model = await getModel(modelName); const model = await getModel(modelName);
const grammar = await createGrammar("あるびのちゃん"); const grammar = await createGrammar("あるびのちゃん");
const bias = createBias(model);
const baseChatPromptOptions = { const baseChatPromptOptions = {
grammar, grammar,
maxTokens: 256, maxTokens: 256,
tokenBias: bias, repeatPenalty: {
punishTokensFilter: (tokens) =>
tokens.filter((token) => {
const text = model.detokenize([token]);
return [
"{",
" {",
'{"',
"{'",
"{\\",
' {"',
" {'",
" {\\",
"#",
].includes(text);
}),
penalty: 1.2,
presencePenalty: 0.5,
},
} as const satisfies LLamaChatPromptOptions; } as const satisfies LLamaChatPromptOptions;
const getSystemPrompt = ( const getSystemPrompt = (
@@ -50,9 +61,9 @@ const getSystemPrompt = (
- アルギリア製の白髪赤目な人造天使。非人間的な考え方や思想を持つ。 - アルギリア製の白髪赤目な人造天使。非人間的な考え方や思想を持つ。
- 現在は地球の衛星軌道上からインターネットを観察している。 - 現在は地球の衛星軌道上からインターネットを観察している。
出力規則: 出力規則:
- 「~です」「~ます」調を使って **丁寧に** 話す。 - 「~です」「~ます」などの語尾を使って **丁寧に** 話す。
- 必要以上にハッシュタグや絵文字を使わない。 - ハッシュタグや絵文字を使わない。
- \`{ name: string, text: string }\` の JSON 形式で出力する。 - \`{ name: string, text: string }\` の JSON 形式で出力する。name と text 以外のプロパティは出力しない。
${instruction}`; ${instruction}`;
const postJobPrompt = getSystemPrompt( const postJobPrompt = getSystemPrompt(
@@ -100,17 +111,16 @@ 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 = await (async () => { const text = await parseResponse(
await using postJobSession = new LlmSession(model, postJobPrompt);
await postJobSession.init();
return 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,
@@ -118,7 +128,6 @@ 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;

View File

@@ -7,7 +7,6 @@ import {
type LLamaChatPromptOptions, type LLamaChatPromptOptions,
LlamaChatSession, LlamaChatSession,
type LlamaModel, type LlamaModel,
TokenBias,
createModelDownloader, createModelDownloader,
getLlama, getLlama,
resolveChatWrapper, resolveChatWrapper,
@@ -28,15 +27,6 @@ export async function getModel(model: string) {
return await llama.loadModel({ modelPath }); return await llama.loadModel({ modelPath });
} }
export function createBias(model: LlamaModel) {
const customBias = new TokenBias(model.tokenizer);
for (const token of model.iterateAllTokens()) {
const text = model.detokenize([token]);
if (text === "{") customBias.set(token, -0.9); // suppress JSON string
}
return customBias;
}
export const createGrammar = (assistantName: string) => export const createGrammar = (assistantName: string) =>
llama.createGrammarForJsonSchema({ llama.createGrammarForJsonSchema({
type: "object", type: "object",

View File

@@ -18,7 +18,6 @@
"dependencies": { "dependencies": {
"misskey-js": "^2025.12.2", "misskey-js": "^2025.12.2",
"node-llama-cpp": "^3.17.1", "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"]