SmallCode架构全解:你按下回车之后,在模型生成第一个Token前发生的8件事
【免费下载链接】smallcodeAI coding agent optimized for small LLMs. 87% benchmark with 4B-active model.项目地址: https://gitcode.com/gh_mirrors/sm/smallcode
SmallCode 是一款专为 7B–20B 小型 LLM 优化的AI 编程代理(AI coding agent),它在消费级硬件上完全本地运行。很多人以为"输入 → 模型输出"之间只有网络请求,但实际上 SmallCode 在你按下回车的瞬间,会先完成一整套零成本的前置流水线——消息澄清检测、@文件展开、Git 上下文注入、确定性工具路由、计划锚点重注入……这些步骤不调用一次大模型,却决定了小模型能否稳定干活。本文带你逐条拆解这8 件事,全部对应真实源码路径,方便你跟着代码理解。
先搞懂:为什么小模型需要这些"前处理"
SmallCode 的核心假设与 Cursor 等工具正好相反:你的模型上下文可能只有 8–32k、工具调用 JSON 时有时无、三步之后就会忘记自己在干什么。于是架构上每一处"看起来多余"的前置步骤,都是在用小模型付不起的成本(正则、文件扫描)替代它付不起的能力(长上下文记忆)。
核心设计文档可参考 ARCHITECTURE.md,中文说明见 README_zh-CN.md。
前置流水线总览:8 件事一张表看懂
| 顺序 | 步骤 | 成本 | 关键源码 |
|---|---|---|---|
| 1 | 模糊消息检测 | 纯正则,0 token | clarify.js |
| 2 | 图片文件扫描 | 本地 IO | images.js |
| 3 | @文件引用展开 | 本地 IO | references.js |
| 4 | Git 变更上下文注入 | git diff | git_context.js |
| 5 | 项目自举探测(首轮) | 本地扫描 | bootstrap.js |
| 6 | 确定性工具路由 | 加权正则评分 | two_stage_router.js |
| 7 | 计划锚点重注入 | 内存读取 | plan_tracker.js |
| 8 | 上下文压缩 + 消息规范化 | 本地计算 | message_normalizer.js |
💡 注意:以上 8 步全部在本地完成,没有一步需要请求模型。这就是"小模型专用代理"与"通用代理"的本质区别。
第 1 件事:正则分类器检查你的话是不是"太模糊"
如果你只打了 "fix it" 这种没有上下文的话,模型大概率会瞎猜。SmallCode 的做法很聪明:不用 LLM 判断模糊性,用一个成本为零的正则分类器。
匹配到 "fix it / do this / make it better" 这类模式后,系统会向模型注入一条指令:先说出你的理解,问一个澄清问题,然后立刻基于最佳理解动手——不许干等确认。
// 触发澄清的典型模糊模式 /^(fix|do|make|change|update|improve)\s+(it|this|that|things?)$/i /^(help|please|can you|could you)$/i- 实现位置:clarify.js
- 细节:回复模型问题的 "yes / ok / go ahead" 被明确排除在外,不会误触发澄清。
第 2 件事:扫描你"顺手丢进对话"的图片
如果你在输入时附带了图片文件(比如报错截图),系统会先扫描消息中引用到的图片文件,确认其存在、可读、体积合规,再决定是否随请求发给模型。这一步是纯本地 IO,避免把不存在的图片路径丢给模型后白白浪费一轮调用。
- 实现位置:images.js
- 多模态内容在后续消息规范化时会被原样保留(见第 8 步)。
第 3 件事:把 @文件 引用展开成真实内容
你在输入框里敲@src/main.ts,模型并不能凭空读到它。SmallCode 会解析消息中所有@path引用,把文件内容直接注入对话:
- 单文件:读取内容,超 500 行截断并标注;
- 目录:列出前 50 个条目;
- 安全防护:拒绝
.ssh、.aws等敏感路径,内容注入前会脱敏(抹掉 API Key、Token),单文件上限 4000 字符、总量约 2000 token 封顶。
@src/main.ts → 注入该文件内容 @src/ → 注入目录列表- 实现位置:references.js
这一步等价于"替模型省掉了 2–3 次 read_file 工具调用"。
第 4 件事:自动注入最近的 Git 变更
当你说 "fix the failing test"、"what changed" 这类话时,系统会先跑一遍git diff --stat和git log,把未暂存变更(封顶 100 行)、已暂存变更和最后一次 commit 信息自动塞进上下文。
--- Recent git changes --- Unstaged changes: src/auth.js | 12 ++++++------ 1 file changed Last commit: a1b2c3d fix login timeout- 触发词匹配:git_context.js
- 小模型最擅长修"眼前刚改坏的东西",这一步让它不用自己
git status。
第 5 件事(首轮专属):项目自举探测,一句话告诉模型"这是什么项目"
首次对话时,SmallCode 会扫描工作区的package.json/pyproject.toml/Cargo.toml/go.mod等配置,生成一行项目摘要直接注入系统提示词,例如:
Project: Node 20 (npm) — Next.js app. Build: `npm run build`. Test: `npm test`. Entry: src/app.js没有这一步,小模型要浪费 3–5 次工具调用才能搞清楚"这是个 Node 项目、测试命令是 npm test"。支持 Node、Python、Rust、Go、.NET、Java、Ruby 七大技术栈识别,结果带缓存、可被SMALLCODE_BOOTSTRAP=false关闭。
- 实现位置:bootstrap.js
第 6 件事:确定性工具路由——8 个类别里"投票"选出该带哪些工具
这是 SmallCode 最核心的省 token 设计。每次调用前,先用加权正则对消息打分,在 read / write / search / run / plan / code-intelligence / web / respond 八个类别之间做"置信度投票",胜出类别决定哪些工具 schema 进入提示词:
- 判为
respond(纯聊天)→注入 0 个工具,省约 800 token; - 判为
write→ 只带 write 相关工具; - "Explain" 这类词会压低 write 分,"How does X work" 触发代码智能类路由。
平局时按优先级打破:write > run > code-intelligence > search > plan > read > web > respond——模糊的行动性消息默认偏向"动手"。
对于 16k 以下上下文的模型,还会切换为两阶段路由:第一次调用只让模型选类别(约 200 token),第二次才注入该类完整工具 schema,用一次额外往返换大幅 token 节省:
- 类别定义与模式切换:two_stage_router.js
- 完整路由评分设计说明:ARCHITECTURE.md
还有一个精妙的边界处理:任务中途你回复 "ok" 时,专门的"肯定词守卫"会保留上一次的类别,避免写文件工具被误剥离。
第 7 件事:把"计划锚点"重新钉回模型眼前
小模型最大的毛病是"到第 4 步忘了第 3 步"。SmallCode 对多步任务(长消息、refactor/migrate 关键词、多个祈使句)会要求模型先输出编号计划再调工具,并把它作为锚点在后续每一轮重新注入:
ACTIVE PLAN (step 3 of 5): ✓ 1. Read the existing auth module ✓ 2. Identify the JWT validation function → 3. Add the refresh token handler 4. Update the route middleware 5. Run tests模型永远知道自己在哪一步。这是多文件任务可靠性的最大单一提升。
- 启发式判断与锚点格式:plan_tracker.js
- 配套机制:计划步骤还会做纯代码依赖分析(同一文件的多步自动建立依赖),为并行执行打基础。
第 8 件事:上下文预算压缩 + 系统消息规范化,最后一道安检
真正发出请求前,还要过两道"安检":
① 消息规范化:Qwen3 等严格聊天模板要求 system 消息必须出现在数组第 0 位,否则直接返回 HTTP 400。SmallCode 会在对话中途注入澄清指令、计划锚点、路径警告等多种 system 消息,发送前统一把它们合并为一条居首的 system 消息,顺序保留、内容不丢:
- 实现位置:message_normalizer.js
② 上下文预算管理:实时估算 token 用量(约 4 字符 ≈ 1 token),大文件摘要为签名、旧消息按压力驱逐,保证任何一轮都不超出模型上下文窗口:
- Token 估算与成本追踪:tokens.js
✅ 到这里,一个"为这个小模型量身裁剪"的请求才终于发出——上下文更短、工具更少、目标更明确,这才是"87% benchmark with 4B-active model" 的真正来源。
如何验证这些机制:亲手试一遍
想亲眼看到这套流水线工作,最快的方式:
# 1. 全局安装(含 BoneScript 等全部依赖) npm install -g smallcode # 2. 在项目目录创建 .env SMALLCODE_MODEL=qwen3:8b SMALLCODE_BASE_URL=http://localhost:11434/v1 # 3. 启动 smallcode然后试试这些输入,观察系统提示词变化:
| 你的输入 | 触发的前置步骤 |
|---|---|
fix it | 第 1 步:澄清检测注入 |
@package.json 这个干嘛的 | 第 3 步:文件内容注入 |
为什么最近的改动让测试挂了 | 第 4 步:git diff 注入 |
纯闲聊:你好呀 | 第 6 步:判为 respond,0 工具 |
重构这个模块,要改多个文件并跑测试 | 第 7 步:计划锚点生成 |
总结:小模型的可靠性是用"确定性代码"换来的
回头看这 8 件事,你会发现一个共同点:所有 SmallCode 在小模型身上做的补偿,全部发生在模型生成第一个 Token 之前,而且几乎全部是零 token 成本的本地计算——正则分类、文件扫描、git 快照、预算压缩。它不是"更聪明的 Cursor",而是一套围绕"小模型会忘事、会写坏 JSON、上下文又短"这三个弱点长出来的架构。理解这 8 步,你就理解了 SmallCode 在 4B 激活参数模型上跑 87% benchmark 的全部秘密。
【免费下载链接】smallcodeAI coding agent optimized for small LLMs. 87% benchmark with 4B-active model.项目地址: https://gitcode.com/gh_mirrors/sm/smallcode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考