Skip to content

函数执行脑:thinknext 展开的可执行搜索树([stackid,stackorder] / stackmem) #69

Description

@miaobyte

函数执行脑(function execution brain)

前身:本 issue 原描述为「vthread 栈暂停 + dump 给 LLM 补充函数/指令,边补充边执行」。
本方案把它推广:暂停与补充不是异常补救,而是每个节点的常态展开算子(thinknext)。

一句话

推理 = 在 kvspace 里跑一棵可执行搜索树:帧是节点,节点坐标是 [stackid, stackorder]
函数调用是边,thinknext 是节点展开。栈即搜索路径,函数子树即搜索树本身——不另建树结构。

流程

  1. 空闲:进程起来后停在等待外部消息(input),不预先生成任何东西。
  2. 生成:收到消息 → LLM 产出 {函数名, 函数体},函数体内恰好 1 条 thinknext
  3. 入库:layout 该函数进 /lib(vet 闸门不通过即 error,不入库)。
  4. 执行:调用该函数名,入口帧坐标 [0,0]
  5. 展开:函数体内的子函数序列逐层执行;因函数体内只有 1 条 thinknext,
    每个节点恰好一步决策——函数体 = 一个决策点。
  6. 收束:退出函数栈后总结整个函数栈(不是单个函数),写
    /vthread/{vid}/[stackid,stackorder].stackmem

节点坐标 [stackid, stackorder]

把原先单一维度的 fid 二维化:一维管身份,一维管位置

  • stackid —— 身份轴:全局单调递增,只增不减、退出不回收。每次「创建并进入子函数」
    分配一个新 stackid。同一节点在整个执行期内只有一个 stackid,永不复用。
  • stackorder —— 位置轴:保持当前。它是该帧在当前调用栈中的序位(等价原 fid 的语义:
    调用 +1,退出 -1),随弹栈回退。
  • 写法与 kvlang 指令坐标 [s0,s1](行、列)同构:第一维定位是谁,第二维定位在哪
  • 节点路径:/vthread/{vid}/[stackid,stackorder]/[stackid,stackorder]/…,逐段即调用链。
  • 回溯目标 [target_stackid, target_stackorder]:身份轴锁定「哪一个」,位置轴确认「它在栈上哪一层」。

为什么这样切分

  • 身份与位置分离后,「同一深度互相覆盖」的问题消失:stackmem 路径因 stackid 唯一而各写各的,
    兄弟子树不再互踩。
  • 同一位置被多次访问时:stackorder 相同、stackid 不同 ⇒ 审计上能区分「同一层的第几次访问」。
  • 动作 3(改写)落在身份轴上 ⇒ 改写历史可以按 stackid 记账、可回溯到具体那一次。

thinknext:唯一的展开算子

# 动作 语义 树搜索术语
1 继续 推进本帧 PC /vthread/{vid}/[stackid,stackorder]/[+1,0] continue(单步推进)
2 下钻 创建新子函数并进入:分配新 stackidstackorder +1 expand(生成子节点)
3 改写 修改当前帧的下一条指令 node revision(在线改节点)
4 回溯 改写已执行过的函数,回到 /vthread/{vid}/[target_stackid,target_stackorder] backtrack + backup

用树的搜索术语看

映射表

搜索概念 本方案
状态 state /vthread/{vid}/[stackid,stackorder](帧内 PC + 局部槽 = 局面)
节点 node 一次函数调用 = 一个帧
节点身份 stackid(单调递增,永不回收)
深度 depth stackorder(调用栈内序位)
根 root 入口帧 [0,0]
边 edge / operator 进入子函数
分支因子 b thinknext 可选动作数(动作 2 可现场造任意函数 → b 无上界)
展开 expansion thinknext 调 LLM 生成下一步
搜索策略 目前是纯 DFS(下钻 + 回溯),无启发式
前沿 frontier 未完成的帧链(就是当前栈)
回溯 backtracking 动作 4
值回传 backup 退出函数栈写 stackmem
目标测试 goal test thinknext 判定任务达成
转置表 transposition stackmem 若按状态指纹索引,可复用同一子问题的结论
闭环检测 cycle check 同一状态重复出现即闭环(图搜索而非树搜索)
AND-OR 树 函数体内的「子函数序列」= AND(全做);thinknext 多选一 = OR
分层任务网络 HTN 函数 = 复合任务,thinknext = 选方法,子函数 = 子任务分解
options / SMDP 子函数 = macro-action(有启动、内部策略、终止),stackmem = option 结果

这套方案的位置:最贴近 Tree-of-Thoughts(把 thought 换成可执行帧)与 HTN(LLM
现场造方法)。与 LATS / RAP 这类 MCTS + LLM 的差别是:现在只有单条 DFS 轨迹 + 事后总结
没有 value(节点价值)、visits(访问计数)、rollout(多次试跑)——即还谈不上 best-first。

相对 ToT 的结构优势:树不需要额外的数据结构。kvspace 里帧路径本身就是调用链,
kvlanglayout·dump 能把 /lib 子树逆向成可运行 kvlang 源码并标注每条指令的 [s0,s1] 槽位——
搜索树天生可寻址、可持久、可 dump、可审计。

二维化之后新增的两条要求

  1. 坐标所指的节点必须还在树上。 kvlang 的 return 是「弹出当前帧、删其子树」:被弹掉的历史帧
    连同它的 [stackid,stackorder] 坐标一起消失。动作 4 想「回到 targetfid 改一条指令」时,
    坐标还在记录里、节点却已不在树里。所以需要一份不随弹帧消失的节点账本 / 搜索树副本
    (落在帧子树之外,如 /byteseek/tree/{vid}/…),或者改弹帧语义。这是二维化的直接代价:
    坐标稳定了,坐标指向的东西必须同样稳定。
  2. 闭环检测不能靠 stackid 每次调用都分配新 stackid,所以「回到同一个状态」在坐标上
    看是新节点。转置表 / 重复检测必须另用状态指纹(帧的 ‥lib + 局部槽摘要)。
    身份轴解决的是冲突,不是去重——两件事。

落地前还必须定清楚的几处

  1. 动作 3/4 破坏「节点不可变」。 搜索的回溯要求被回访的节点可复现;原地改写会让同一
    坐标在不同时刻语义不同。要么节点版本化(坐标 + 版本号),要么改写前存旧值(undo log)。
  2. stackmem 写在帧路径下会被删。 与上一条同源:/vthread/{vid}/[stackid,stackorder].stackmem
    随弹帧消失。要留存必须落在帧子树之外,或改弹帧语义。
  3. 「回溯」不是 goto。 kvlang 的 goto 是帧内跳转(只改 PC 的行号,帧不变);跨帧回到
    目标坐标 = 弹掉中间帧 + 在该帧改写下一条指令(动作 4 = backtrack + 动作 3 的组合)。
    命名与实现都要按 kvlang 语义来。
  4. 动作 1「继续」需要精确定义。 函数体只有 1 条指令时 [+1,0] 已越出函数体:「继续」到底
    是结束本帧(return),还是执行父帧的下一个子函数?帧内序列长度 = 1 时,动作 1 与 return
    重合——必须选定其一。
  5. 终止性。 缺 goal test 的树不是搜索,是无限生成。需要 stackorder 深度上限、节点预算、
    LLM 调用预算,以及状态指纹级的重复检测。
  6. thinknext 必须落在 runtime 侧。 它要读全栈、调 LLM,再改 PC / 建子帧 / 改写指令——
    本质是控制流 rwir(call / goto / return 的合体)。kv rwfunc 改不了调用者的帧与 PC。
    LLM 调用可直接复用现成的 llm·raw(sys,user) -> text
  7. 每节点一次 LLM 调用 = 成本 O(节点数)。 要做 beam / 多候选,得让 thinknext 一次生成
    多个候选(b > 1),并在 stackmem 里存 value / visits 才谈得上 best-first。
  8. 命名对齐。 身份轴 stackid 符合主流惯例(全局唯一 id);位置轴 stackorder 在五大语言
    里更常见的对应词是 depth / index,沿用需在文档里写明它就是调用栈内序位,避免被读成
    「兄弟序号」。

完成定义

  • 收到消息 → 生成首函数 → layout → 执行 → 逐层 thinknext → 退栈总结 stackmem,全程无人工干预。
  • 四种动作各自可观测:节点坐标、动作类型、stackmem 落在确定的 KV 路径上,且 stackid 可唯一定位。
  • 有界:stackorder 深度 / 节点数 / LLM 调用三重预算,超限停机并留现场(PC 与状态留在 kvspace)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions