Interpretable Language Models
Reverse-engineering the circuits and representations inside transformers — turning black boxes into systems we can inspect, edit, and trust.
可解释语言模型
逆向工程 Transformer 内部的电路与表征——把黑盒变成可检查、可编辑、可信赖的系统。
个人技术站点 · 非商用 · 持续折腾中
I build large language model systems that are interpretable and honestly reliable in the open world.
围绕 LLM Agent 与空间信息的个人实验室——业余写各类代码实验、记技术笔记,偶尔读书、偶尔造轮子。所有内容仅作个人学习演示。
作品集
Reverse-engineering the circuits and representations inside transformers — turning black boxes into systems we can inspect, edit, and trust.
逆向工程 Transformer 内部的电路与表征——把黑盒变成可检查、可编辑、可信赖的系统。
Making language models reliable under distribution shift, with calibrated uncertainty and guarantees that survive contact with the real world.
让语言模型在分布偏移下依然可靠——给出校准的不确定性,以及经得起真实世界考验的保证。
Long-context attention and sparse computation — cutting the cost of foundation models without cutting corners on quality.
长上下文注意力与稀疏计算——在不牺牲质量的前提下,削减基础模型的推理成本。
kbpi-theory 是 Pi 0.84.1 的理论对齐副本,核心动作是把上游的"自由工具循环"改成受治理运行时:默认 CLI 走严格受控路径,原自由模式降级为显式 --legacy。差异集中在三件事——授权、状态与失败的表示。
授权是任务级 TaskContract:操作数、模型请求数、绝对 deadline、输出限制、验收预留全部写进契约,且验收消耗计入 maxOperations。审批分两层:任务级 /approve 出契约摘要,逐操作 /allow <id> <argsHash> 用 canonicalHash 对最终 JSON 算参数摘要——裸批准、错摘要、旧 nonce、重复回复一律无效,未消费的批准不跨会话。
有界 Option 是另一个亮点:宿主预注册 {steps, preconditions, invariants, postconditions},上限 16 定义 × 32 步 × 32 条检查,契约体量限 64 KiB——"可扩展"必须先"可预算"。严格本地 RPC(NDJSON v1)在 busy 时对第二个业务请求立即拒绝而非排队,SDK 拿不出可信的 onApprovalRequest 回调就连账本都不许建。
最值得抄的观念转变:unknown 不是异常而是一等状态,执行与验收分离账本、显式限制重试。
kbpi-theory 的 RSI(受治理自改进)可行性文档里,最工程化的部分是组件三权分立:CampaignController 管预算、谱系与停止规则;Evaluator 独立评分并出收据;PromotionController 只接受版本匹配且过门禁的证据——不确定就不提升。
门禁分软硬:安全、版本完整性、证据完整性是硬门禁,不与平均成功率加权抵消;过关也不自动发布,predict 支持 {action, policyId} 一步回滚。改进算子 I_g 只负责提出并筛选开发阶段的候选,运行时权力被锁死。
六阶段退出门禁(0-5)给出了自改进系统的成熟度标尺:0 冻结问题边界 → 1 离线单代机制闭环(重启不洗预算)→ 2 策略预测进真实动作链 → 3 固定改进器业务收益(此时才配称"受治理自动自改进闭环")→ 4 开放有限算子演化 → 5 有限真实使用。
配套的 DeepSeek Harness 启示录里有两句我抄进了备忘录:不让候选代码获得修改审批/预算/账本的能力;区分五种回执——消息已收、代码已跑、任务已结算、进程已静止、验收通过。
背景:文档入库后要走一条 CDC 增量链路——PostgreSQL 逻辑复制捕获变更,再交给 LLM 抽取实体关系写入 Neo4j。链路本身能跑,但一到真实数据量就全面告急。
三个问题层层叠加:其一,抽取端硬编码 60 秒超时,而大模型在长文本上经常要跑两三分钟,任务被成片掐死;其二,worker 串行消费,一条变更十几秒,积压越滚越大;其三,复制槽没人消费时 WAL 只增不减,磁盘肉眼可见地往下掉。
对应三刀:把超时在运行时补到 300 秒(改不了上游代码就 monkey-patch);切换到仓库自带的并发构建脚本,四路并发吞吐翻了一个量级;积压过深时果断丢弃重建复制槽,跳过历史 backlog 只追增量。
结果:40 篇文档全量图谱约半小时构建完成,增量延迟回落到分钟级。遗留问题:健康检查接口因脚本与 systemd 单元名不一致,永远报 CRITICAL——管道本身是健康的,属于"仪表盘说谎"类问题,留待后续治理。
把 pi 的精读路线走完之后,最大的收获是一张完整的调用链地图:cli.ts → main.ts(972 行)→ agent-session-runtime → services → sdk.ts:169 → AgentSession(3351 行,在 :396 处订阅)。想快速追踪行为,print-mode.ts 是干扰最小的入口。
会话构造是自底向上注入服务:SessionManager → TUI → ExtensionRunner → Agent,_handleAgentEvent 把 agent 的事件接到持久化挂钩上。事件侧一共 18 种 AgentSessionEvent union 分发给 SDK 监听者;SessionManager.appendMessage 把每条消息追加写入 session JSONL,工具结果以 SDKFunctionCallResult 事件回流落盘。
上下文是两层模型:L1 systemPrompt(core/system-prompt.ts 融合 custom sections、AGENTS.md 上下文、tool snippets)、L2 messages + tools。这个分离让 agent loop 彻底不用回头查 systemPrompt。坑:两个包里各有一个 buildContext,职责完全不同,读源码时极易张冠李戴。
compaction 的入口在 agent-session.ts:2051 shouldCompact → :2444 compact(),顺着这两个函数就能把上下文回收的完整时序串起来。
空间数据的图谱化,第一步就卡在哲学问题上:什么算实体?一条道路是一个节点,还是每个路口之间的一段?一个行政区的边界,是属性、节点还是一条"围合关系"?三种建模各有适用场景,没有银弹。
我最终采用的折中:要素本身做节点,要素间的拓扑关系(相交、邻接、包含)做边,坐标串压缩后放属性。好处是图查询语义清晰——"与某地块邻接的所有地块"就是一度邻居查询。
意外收获是格网索引:把要素按固定格网分桶后建二级索引节点,空间范围查询先过格网再过滤,比在图上直接做属性扫描快一个数量级。老 GIS 人的智慧在图数据库里依然成立。
教训:别急着把所有几何细节搬进图——图谱负责关系,几何留给 PostGIS,各司其职。
tau 是受 Pi 启发的 Python 终端 coding agent,README 明言兼顾"可运行"与"可阅读"。骨架上是干净的三层单向依赖:tau_coding → tau_agent → tau_ai,AgentHarness 是可复用大脑、CodingSession 是编码环境、TUI 只是消费事件流的前端之一——核心代码不 import Textual/Rich。
主循环在 tau_agent/loop.py:44 run_agent_loop,双层 while 的 async generator:外层管 turn,内层顺序执行一次响应里的多个 tool_call 并支持 steering 注入。一次 prompt + 一轮工具往返大约 yield 12–15 个 AgentEvent。事件流分两层:下层 ProviderEvent 7 类是 provider 私有,上层 AssistantMessageEvent 12 类 provider 中立,靠 canonicalize_provider_stream() 桥接;类型系统用 pydantic Annotated[Union, Field(discriminator="type")]。
工具也是两层:AgentTool(119 行,loop 直接用)与 ToolDefinition(1060 行,多 prompt_snippet/guidelines),经 to_agent_tool() 下转。四个内置工具按 read/write/edit/bash 注册,同路径的读写共享 per-path 锁,bash 走信号协作取消——细节都长在正确的地方。
Session 管理把 pi 的大类拆成两半:索引归 session_manager.py,entry 持久化独立在 tau_agent/session/jsonl.py;索引用 split("\n") 规避 U+2028 这种"看起来是换行其实不是"的字符坑。
pi 的上下文压缩有个容易踩的坑:双轨实现。实际生效的是 packages/coding-agent/src/core/compaction/(compaction.ts 845 行 + branch-summarization.ts 355 行),而 packages/agent/src/harness/compaction/ 那份 grep 实测没有被 coding-agent 引用——读源码不看引用关系,笔记就会写错对象。
触发条件是 tokens > contextWindow - reserveTokens,reserve 默认 16384、keepRecent 20000。压缩结果作为独立的 CompactionEntry 落盘,不混进消息流;扩展可以经 session_before_compact / session_before_tree 两个钩子拦截。
分支摘要靠 parentId 构成的会话树:找两条分支的 commonAncestor,把分叉后的历史交给 LLM 总结;FileOperations 每路径截 2000 字符,防止 diff 把上下文撑爆。
方法论教训:我曾在笔记里写"pi 与 tau 的 prompt 一字不差",后来复核降级为[待验证]——从此所有论断都标注 [实测]/[源码引用]/[推理]/[待验证] 四级证据。
把 pi(TypeScript)和 tau(Python)放在一起读会发现:三层分包、L1/L2 上下文、同形调用链,骨架几乎镜像;但细节层面全面不兼容,这正是双实现对照的价值所在。
典型 diff:事件名相同而 usage schema 不同——pi 是 {input, output, cacheRead, total},tau 多出 cacheWrite/totalTokens 和嵌套 cost;错误表示 pi 用 stopReason:"error",tau 用 diagnostics[] 数组;扩展接口 pi 是 camelCase 的 customPrompt/promptGuidelines,tau 是 snake_case 的 custom_prompt/extra_guidelines。
最有趣的是 Skill 装载策略:pi 只存 filePath,运行时靠 read 工具现读;tau 直接把 content 持进内存。前者省内存多一次 IO,后者快但吃上下文——同一种功能的两种性格。tau 还对资源格式从严:必须目录式 SKILL.md,裸 .md 会报迁移诊断。
对照读法的好处:任何一边出现的设计决策,都能立刻在另一边找到"它为什么没这么做"的反证。
,
,
,
,
, , ,
面向公开讯息流的安全事件识别与演化追踪——多语言理解、风险分级与传播链路还原。
用 LLM 在椭圆曲线参数空间做启发式搜索,权衡安全强度与计算开销,并做形式化安全验证。
时空轨迹的脱敏与可用性权衡——k-匿名与差分隐私在真实城市路网上的实证。
多因子智能推荐——模型自适应学习口味、价格、距离与排队时长的偏好权重,生成选购排序与门店导航。
Say hello
打个招呼
The fastest way to reach me is email — I usually reply within 72 hours. Always happy to chat about research, internships, or collaboration.
最快的联系方式是邮件——我通常会在 72 小时内回复。随时欢迎聊聊研究、实习或合作。