Refactor
This commit is contained in:
45
index.ts
45
index.ts
@@ -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;
|
||||||
|
|||||||
10
lib/llm.ts
10
lib/llm.ts
@@ -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",
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
Reference in New Issue
Block a user