From 0650373e2707ebd988ed60a5fb7c853b8dd1e701 Mon Sep 17 00:00:00 2001 From: "peng.li24" <734991033@qq.com> Date: Fri, 11 Sep 2026 21:08:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20byteseek=20=E8=AE=B0=E5=BF=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=A2=9E=E5=BC=BA=E2=80=94=E2=80=94LLM=20=E8=A3=B8?= =?UTF-8?q?=E8=B0=83=E7=94=A8/=E8=83=BD=E5=8A=9B=E8=AE=B0=E5=BF=86?= =?UTF-8?q?=E7=94=9F=E6=88=90/=E6=B6=88=E6=81=AF=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - llm·raw:裸 LLM 调用返回纯文本,供 memgen 等元能力复用 - memgen:递归概括 /lib 各目录能力写入 .mem(幂等,已有即跳过) - memory:新增 classify(LLM 分类)+ ensure_category,recall 跳过 cat 子树 - main:mainbrain 启动 build 能力记忆,对话按类别归档并注入 prompt Co-Authored-By: Claude Opus 4.8 --- lib/byteseek/llm.kv | 30 +++++++++++++++++++++ lib/byteseek/main.kv | 7 +++-- lib/byteseek/memgen.kv | 58 +++++++++++++++++++++++++++++++++++++++ lib/byteseek/memory.kv | 61 +++++++++++++++++++++++++++++------------- 4 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 lib/byteseek/memgen.kv diff --git a/lib/byteseek/llm.kv b/lib/byteseek/llm.kv index 76650a6..a2a702b 100644 --- a/lib/byteseek/llm.kv +++ b/lib/byteseek/llm.kv @@ -70,4 +70,34 @@ lib llm { "byteseek/session/" + name + "·init" -> entry if (print != "0") { println("[llm] 入口:", entry) } } + + // llm·raw(sys, user) -> text:裸 LLM 调用,返回 assistant 文本(不生成/不执行 kv 代码)。 + // 供 memgen 等需要「LLM 直接产出一段文本」的元能力复用。 + rwfunc raw(sys:[]char/utf32, user:[]char/utf32) -> (text:[]char/utf32) { + kv·get("/byteseek/llm.key") -> key + if (key == "") { + "error: 未设置 DEEPSEEK_API_KEY" -> text + return + } + kv·get("/byteseek/llm.api") -> url + sys -> /tmp/esc·sys + json·to(/tmp/esc·sys) -> sys_j + user -> /tmp/esc·user + json·to(/tmp/esc·user) -> user_j + "{\"model\":\"deepseek-v4-flash\",\"messages\":[{\"role\":\"system\",\"content\":" + sys_j + "},{\"role\":\"user\",\"content\":" + user_j + "}],\"temperature\":0.2,\"top_p\":1.0,\"max_tokens\":1024,\"stream\":false}" -> body + "Content-Type: application/json\nAuthorization: Bearer " + key -> header + http·call("POST", header, url, body) -> resp + string·find(resp, "choices") -> has_choices + if (has_choices < 0) { + "error: LLM 响应异常: " + resp -> text + return + } + json·from(resp) -> /tmp/llmresp + kv·get("/tmp/llmresp·choices·[0]·message·content") -> content + if (content == "") { + "error: LLM 响应无内容: " + resp -> text + return + } + content -> text + } } diff --git a/lib/byteseek/main.kv b/lib/byteseek/main.kv index 6c9006c..19355a7 100644 --- a/lib/byteseek/main.kv +++ b/lib/byteseek/main.kv @@ -8,6 +8,7 @@ lib byteseek { } rwfunc mainbrain() -> () { + byteseek/memgen·build() running = 1 while (running == 1) { input("byteseek> ") -> userinput @@ -15,11 +16,13 @@ lib byteseek { if (q == 0) { running = 0 } else { + byteseek/memory·classify(userinput) -> cat + byteseek/memory·ensure_category(cat) byteseek/memory·recall(userinput) -> mem if (mem == "") { - userinput -> prompt + userinput + "\n\n[类别] " + cat -> prompt } else { - userinput + "\n\n[相关记忆]\n" + mem -> prompt + userinput + "\n\n[类别] " + cat + "\n\n[相关记忆]\n" + mem -> prompt } llm·call(prompt) -> entry byteseek·run(entry) diff --git a/lib/byteseek/memgen.kv b/lib/byteseek/memgen.kv new file mode 100644 index 0000000..2247595 --- /dev/null +++ b/lib/byteseek/memgen.kv @@ -0,0 +1,58 @@ +// byteseek 能力记忆生成器(全 kvlang):把 /lib 下各目录的能力浓缩成一条 ·mem 记忆 key。 +// 后缀约定:目录 /lib/ 的能力记忆存在 key /lib/.mem。 +// fnlist(name) —— 枚举 /lib/· 下的函数/常量名(.src 条目去后缀,目录条目跳过)。 +// summarize(name) —— 若 /lib/·mem 不存在,用 LLM 生成中文能力记忆并写入该 key。 +// build() —— 对 kvlang stdlib 的目录递归概括一次(幂等:已有 ·mem 即跳过)。 +lib byteseek { + lib memgen { + rwfunc fnlist(name:[]char/utf32) -> (listing:[]char/utf32) { + "" -> listing + "/lib/" + name + "·" -> mdir + kv·listlen(mdir) -> n + i = 0 + while (i < n) { + kv·listn(mdir, i) -> entry + char/utf32(entry) -> entry + string·len(entry) -> elen + string·find(entry, ".src") -> p + if (p >= 0) { + elen - 4 -> cut + string·slice(entry, 0, cut) -> fn + if (listing == "") { fn -> listing } else { listing + ", " + fn -> listing } + } else { + elen - 1 -> last + string·char(entry, last) -> tail + if (tail != "/") { + if (listing == "") { entry -> listing } else { listing + ", " + entry -> listing } + } + } + i + 1 -> i + } + } + + rwfunc summarize(name:[]char/utf32) -> () { + kv·has("/lib/" + name + ".mem") -> exists + if (exists == true) { return } + fnlist(name) -> listing + "你是 kvlang 能力记忆生成器。kvspace 目录 /lib/" + name + " 提供以下能力:" + listing + "。请用中文写一段不超过 200 字的紧凑能力记忆:用 · 分隔,每个能力名后跟一句话用途。只输出记忆文本本身,不要代码、不要解释、不要 markdown。" -> user + llm·raw("你是 kvlang 能力记忆生成器。只输出简洁的中文记忆文本。", user) -> text + string·find(text, "error") -> iserr + if (iserr == 0) { + println("[memgen] 概括失败:", name, text) + return + } + kv·set("/lib/" + name + ".mem", text) + println("[memgen] 已生成:", "/lib/" + name + ".mem") + } + + rwfunc build() -> () { + byteseek/memgen·summarize("math") + byteseek/memgen·summarize("string") + byteseek/memgen·summarize("kv") + byteseek/memgen·summarize("xv") + byteseek/memgen·summarize("http") + byteseek/memgen·summarize("time") + byteseek/memgen·summarize("time/duration") + } + } +} diff --git a/lib/byteseek/memory.kv b/lib/byteseek/memory.kv index 6943e1e..7a13ae7 100644 --- a/lib/byteseek/memory.kv +++ b/lib/byteseek/memory.kv @@ -1,7 +1,9 @@ -// byteseek 记忆库(全 kvlang):记忆都活在 /byteseek/memory/ 的 kvspace 树里。 +// byteseek 记忆库(全 kvlang):记忆都活在 /byteseek/memory/ 的 kvspace 树里。 // remember(key, value) —— 写一条记忆到 /byteseek/memory/。 // recall(query) —— 记忆检查:扫描 /byteseek/memory/ 子树,自动滤出与 query 相关的关键树路径, // 返回多行 "key = value",供 mainbrain 注入 LLM 上下文。 +// classify(msg) —— 用 LLM 把消息归入一个简短类别。 +// ensure_category(cat) —— 若类别不存在,则在 /byteseek/memory/cat/ 新建。 // 匹配规则:query 与 key 互相包含,或 query 与 value 互相包含(子串匹配,大小写敏感)。 lib byteseek { lib memory { @@ -17,28 +19,49 @@ lib byteseek { while (i < n) { kv·listn("/byteseek/memory/", i) -> key char/utf32(key) -> key - "/byteseek/memory/" + key -> path - kv·get(path) -> value - hit = 0 - string·find(query, key) -> a - if (a != -1) { hit = 1 } - string·find(key, query) -> b - if (b != -1) { hit = 1 } - if (value != "") { - string·find(value, query) -> c - if (c != -1) { hit = 1 } - string·find(query, value) -> d - if (d != -1) { hit = 1 } - } - if (hit == 1) { - if (ctx == "") { - key + " = " + value -> ctx - } else { - ctx + "\n" + key + " = " + value -> ctx + if (key != "cat") { + "/byteseek/memory/" + key -> path + kv·get(path) -> value + hit = 0 + string·find(query, key) -> a + if (a != -1) { hit = 1 } + string·find(key, query) -> b + if (b != -1) { hit = 1 } + if (value != "") { + string·find(value, query) -> c + if (c != -1) { hit = 1 } + string·find(query, value) -> d + if (d != -1) { hit = 1 } + } + if (hit == 1) { + if (ctx == "") { + key + " = " + value -> ctx + } else { + ctx + "\n" + key + " = " + value -> ctx + } } } i + 1 -> i } } + + rwfunc classify(msg:[]char/utf32) -> (cat:[]char/utf32) { + "请把下面这条用户消息归入一个简短中文类别(2-6字,如:编程、文件、shell、数学、闲聊)。只输出类别名本身,不要任何空格、换行、标点或解释。\n\n消息:" + msg -> user + llm·raw("你是消息分类器。只输出一个简短中文类别名。", user) -> cat + string·find(cat, "error") -> e + if (e == 0) { + "未分类" -> cat + } + } + + rwfunc ensure_category(cat:[]char/utf32) -> () { + if (cat == "") { return } + "/byteseek/memory/cat/" + cat -> path + kv·has(path) -> exists + if (exists == false) { + kv·set(path, "1") + println("[memory] 新类别:", cat) + } + } } }