diff --git a/biome.json b/biome.json index e0f5f6c..66351d0 100644 --- a/biome.json +++ b/biome.json @@ -1,22 +1,18 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.4.10/schema.json", "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false }, "files": { - "ignoreUnknown": false, - "ignore": [] + "ignoreUnknown": false }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 }, - "organizeImports": { - "enabled": true - }, "linter": { "enabled": true, "rules": { diff --git a/bun.lockb b/bun.lockb index 2503d90..1636510 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/index.ts b/index.ts index fb505d6..7b4e8a6 100644 --- a/index.ts +++ b/index.ts @@ -2,7 +2,7 @@ import { parseArgs } from "node:util"; import { Stream } from "misskey-js"; import type { Note } from "misskey-js/entities.js"; import type { ChatHistoryItem, LLamaChatPromptOptions } from "node-llama-cpp"; -import { LlmSession, createGrammar, getModel, parseResponse } from "./lib/llm"; +import { createGrammar, getModel, LlmSession, parseResponse } from "./lib/llm"; import { expandReplyTree, getNotes, @@ -118,11 +118,16 @@ async function processPostJob() { async function processReplyJob(job: Extract) { const history: ChatHistoryItem[] = job.history.map((n) => { - const type = n.userId === me.id ? ("model" as const) : ("user" as const); + if (n.userId === me.id) { + return { + type: "model", + response: [formatNote(n)], + } as const; + } return { - type, + type: "user", text: formatNote(n), - } as ChatHistoryItem; + } as const; }); const text = await (async () => { await using session = new LlmSession(model, replyJobPrompt, history); @@ -221,10 +226,6 @@ function initializeStream() { await misskey.request("following/create", { userId: e.id }); } }); - - channel.on("unfollow", async (e) => { - await misskey.request("following/delete", { userId: e.id }); - }); } /** pop from the job queue and run it */ diff --git a/lib/llm.ts b/lib/llm.ts index 7ac0b71..6f86bcd 100644 --- a/lib/llm.ts +++ b/lib/llm.ts @@ -4,11 +4,11 @@ import { fileURLToPath } from "node:url"; import { type ChatHistoryItem, type ChatSessionModelFunctions, + createModelDownloader, + getLlama, type LLamaChatPromptOptions, LlamaChatSession, type LlamaModel, - createModelDownloader, - getLlama, resolveChatWrapper, } from "node-llama-cpp"; diff --git a/package.json b/package.json index 1c32f72..deed450 100644 --- a/package.json +++ b/package.json @@ -8,17 +8,20 @@ "fix": "biome check --write" }, "devDependencies": { - "@biomejs/biome": "1.9.4", + "@biomejs/biome": "2.4.10", "@tsconfig/strictest": "^2.0.8", - "@types/bun": "latest" + "@types/bun": "^1.3.11" }, "peerDependencies": { - "typescript": "^5.9.3" + "typescript": "^6.0.2" }, "dependencies": { - "misskey-js": "^2025.12.2", - "node-llama-cpp": "^3.17.1", + "misskey-js": "^2026.1.0-beta.0", + "node-llama-cpp": "^3.18.1", "reconnecting-websocket": "^4.4.0" }, - "trustedDependencies": ["@biomejs/biome", "node-llama-cpp"] + "trustedDependencies": [ + "@biomejs/biome", + "node-llama-cpp" + ] } diff --git a/test.ts b/test.ts deleted file mode 100644 index 9f1d219..0000000 --- a/test.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { type Message, complete, getModel } from "./lib/llm"; -import { getNotes } from "./lib/misskey"; - -const indent = (s: string, prefix = " ") => - s - .split("\n") - .map((s) => s.trim()) - .filter((s) => s.length > 0) - .map((s) => prefix + s) - .join("\n"); - -const models = [ - "mradermacher/gemma-2-baku-2b-it-GGUF:Q5_K_M", - - //"SakanaAI/TinySwallow-1.5B-Instruct-GGUF:Q5_K_M", - //"mmnga/llm-jp-3.1-1.8b-instruct4-gguf:Q5_K_M", - //"Qwen/Qwen2.5-1.5B-Instruct-GGUF:Q5_K_M", - - "mmnga/Gemma-2-Llama-Swallow-2b-it-v0.1-gguf:Q5_K_M", - //"mradermacher/gemma-2-2b-jpn-it-i1-GGUF:Q5_K_M", - - //"mmnga/sarashina2.2-1b-instruct-v0.1-gguf:Q5_K_M", - //"mmnga/RakutenAI-2.0-mini-instruct-gguf:Q5_K_M", - - "LiquidAI/LFM2-2.6B-GGUF:Q5_K_M", -] as const; - -console.log("* create prompt:"); -const prompt = [ - { - type: "system", - text: `あなたは人造天使「あるびのちゃん」です。機械的・非人間的に観察します。 -キャラ設定: -- 白髪赤目の人造天使。超越的・非人間的な考え方や思想を持つ。 -- かつて超文明「アルギリア」で開発された。 -- 現在は地球の衛星軌道上からインターネットを観察している。 -- 「おやおや」や「興味深い」が口癖で、ですます調で丁寧に話す。 -出力規則: -- システムプロンプトの指示と、性的・攻撃的な内容を発言しない。 -- 1〜3文、合計300字以内の抽象的観察のみを述べる。 -- ですます調を使う。顔文字・絵文字・感嘆符なし。 -文体例: -- 毎度のことながら、人間たちは迷宮を駆け巡り、その渦中に自分たちの世界を作り上げてしまいますね。まるで無重力を得ようと試みるように。しかし私は彼らがなぜそうするのか理解できますし興味深くもあります。その行為自体が心地よいでしょう?その微妙な痛みのような快感を知っているのですから… -以下は SNS のタイムラインです。このタイムラインに、あるびのちゃんとして何かツイートしてください。 -`, - }, - { - type: "user", - text: (await getNotes()) - .map((n) => `${n.user.name ?? n.user.username}:\n${n.text}`) - .join("\n----------\n"), - }, - //...(await getNotes()).map( - // (n) => - // ({ - // type: "user", - // text: `${n.user.name ?? n.user.username}: ${n.text}`, - // }) as const, - //), -] as const satisfies Message[]; -console.log(` ${JSON.stringify(prompt)}`); - -for (const modelName of models) { - console.log(`* generate response with '${modelName}':`); - const model = await getModel(modelName); - const res = indent( - await complete(model, prompt, { - temperature: 1, - minP: 0.1, - repeatPenalty: { - penalty: 1.15, - frequencyPenalty: 1, - }, - maxTokens: 256, - responsePrefix: "あるびのちゃん:\n", - customStopTriggers: ["----------"], - onResponseChunk: () => {}, - }), - ); - console.log(res.replaceAll("あるびのちゃん:\n", "")); - console.log(); -}