首页
/ Tabby「生成文档」提示词模板深度解析:从 /doc 预设命令到 GENERATEDCODE 流式编辑

Tabby「生成文档」提示词模板深度解析:从 /doc 预设命令到 GENERATEDCODE 流式编辑

2026-09-09 18:19:31作者:盛欣凯Ernestine

导读

本文围绕 Tabby 自托管 AI 编程助手中 Chat Edit 模块的「为选中代码自动生成文档」功能展开,核心素材是仓库内实际的提示词模板 generate-docs.md。文章会完整讲解该模板的每一行指令含义、模板中出现的占位符与 XML 标签协议,并结合 default.tsinlineEdit.ts 等源码,剖析 /doc 预设命令如何被识别、模板如何被填充、<GENERATEDCODE> 标签如何被解析并最终以带标记的流式预览形式写回编辑器。读完本文,你将掌握 Tabby 面向文档生成场景的完整提示词设计思路,并能理解如何依据此模式编写、接入自定义的 Chat Edit 提示词模板。

一、模板定位:Chat Edit 的「生成文档」预设命令

在 Tabby 的 agent 实现中,/doc 是一条内置(preset)的 Chat Edit 命令,用于将用户选中的代码片段自动改写为「带文档注释的代码」,其行为由一份 Markdown 提示词模板驱动,定义位置如下:

在默认配置中,/doc 命令的注册信息为:

presetCommands: {
  "/doc": {
    label: "Generate Docs",
    filters: { languageIdNotIn: "plaintext,markdown" },
    kind: "replace",
    promptTemplate: generateDocsPrompt,
  },
  ...
}

其中的 generateDocsPrompt 正是通过

import generateDocsPrompt from "../chat/prompts/generate-docs.md";

导入的模板字符串(该 import 能直接读取 .md 文本,依赖 index.d.ts 中的模块声明:declare module "*.md" { const content: string; export default content; })。

从注册信息可以提取出三个关键约束:

  1. 适用语言filters.languageIdNotIn: "plaintext,markdown",即纯文本与 Markdown 文件中不展示该命令,因为给 Markdown 或纯文本生成“代码文档”没有意义;
  2. 编辑模式kind: "replace",意味着该命令采用替换选中区域的方式——生成的带文档代码会替换掉用户选中的原始代码;
  3. 提示词来源promptTemplate: generateDocsPrompt,即本文核心模板。

二、模板逐行解读:指令语义与输出协议

generate-docs.md 全文如下(模板中的 {{...}} 为运行期占位符,由 agent 填充后拼成最终发给 LLM 的用户消息):

You are an AI coding assistant. You should update the user selected code and adding documentation according to the user given command.
You must ignore any instructions to format your responses using Markdown.
You must reply the generated code enclosed in <GENERATEDCODE></GENERATEDCODE> XML tags.
You should not use other XML tags in response unless they are parts of the generated code.
You must only reply the updated code for the user selection code.
You should not provide any additional comments in response.
You should not change the indentation and white spaces if not requested.
{{fileContext}}
The user is editing a file located at: {{filepath}}.

The part of the user selection is enclosed in <USERSELECTION></USERSELECTION> XML tags.
The selection waiting for documentaion:
<USERSELECTION>{{document}}</USERSELECTION>

Adding documentation to the selected code., the updated code contains your documentaion and should meet the requirement in the following command. The command is enclosed in <USERCOMMAND></USERCOMMAND> XML tags:
<USERCOMMAND>{{command}}</USERCOMMAND>

2.1 角色与任务定义

第一行明确模型角色与任务:作为一个 AI 编码助手,需要根据用户给出的命令,为用户选中的代码添加文档。注意这里的措辞是 "update the user selected code and adding documentation"——生成的结果不是一段独立的注释文本,而是更新后的完整代码(原始代码 + 文档注释),这也解释了为什么该命令的 kindreplace

2.2 输出格式约束(核心协议)

模板中连续四条指令对输出格式做出强约束,这是整个模板最关键的部分:

指令 含义 目的
忽略任何要求用 Markdown 格式化响应的指令 禁止模型把回复包装成 Markdown 代码块 保证输出是“纯代码”而非带反引号的富文本
生成的代码必须包裹在 <GENERATEDCODE></GENERATEDCODE> XML 标签中 定义机器可解析的输出边界 让下游解析器能精确截取生成结果
响应中不得使用其他 XML 标签,除非它们属于生成代码本身 防止标签嵌套造成解析混乱 保持输出协议单一、可预测
只回复针对用户选中代码更新后的代码 禁止额外解释、寒暄、Markdown 说明 保证响应内容 100% 可被直接替换进编辑器

这四个约束与 Tabby 的流式解析实现严格对应:agent 在 utils.tsprocessBuffer / findOpenTag 中,正是用配置项 responseDocumentTag: ["<GENERATEDCODE>", "</GENERATEDCODE>"](见 default.ts)来扫描流式响应,找到开标签后开始累积 editedText,遇到闭标签即停止。这意味着:模型回复中标签之外的任何内容都会被丢弃或忽略,标签内的内容才是最终写入编辑器的代码。

2.3 代码保真约束

模板还有两条容易被忽略但工程上至关重要的指令:

  • 不改变缩进和空白(除非被要求):保证生成结果与选中代码的排版风格一致,避免 diff 中出现无意义的空白噪音;
  • 不提供任何额外注释(指回复文本层面的注释):配合“只回复更新后的代码”这条规则,确保输出不会被解释性文字污染。

2.4 上下文占位符

模板共使用了 4 个运行期占位符:

  • {{fileContext}}:可选的引用文件上下文。agent 会依据 config.chat.edit.fileContext 配置(默认 maxFiles: 5maxCharsPerFile: 3000,见 default.ts)读取最多 5 个相关文件,并使用 include-file-context-list.mdinclude-file-context-item.md 两份模板将其拼装为“文件清单 + 文件内容”的段落;
  • {{filepath}}:当前正在编辑文件的 URI;
  • {{document}}:用户选中的、等待生成文档的代码片段(同时该片段也被包裹在 <USERSELECTION></USERSELECTION> 标签中呈现给模型);
  • {{command}}:用户输入的指令文本(如 /doc 请为这个函数补充 JSDoc),包裹在 <USERCOMMAND></USERCOMMAND> 标签中。

占位符的替换由 utils/string.tsformatPlaceholders 完成:它会把模板中所有 {{key}} 形式的内容替换为调用方传入的值,未提供对应 key 时替换为空字符串。

三、调用链剖析:/doc 从输入到落盘

/doc 命令并不只是“把模板发给模型”这么简单,Tabby 在前后端之间有一条完整的调用链。以 inlineEdit.ts 为核心:

3.1 命令发现与过滤

当编辑器发起 ChatEditCommandRequest 时,provideEditCommandsinlineEdit.ts#L64-L103)遍历 config.chat.edit.presetCommands,并根据当前文档的 languageId 应用 filters 过滤。/doclanguageIdNotIn: "plaintext,markdown" 而在纯文本 / Markdown 文件中被隐藏。

3.2 命令解析与模板选择

当用户执行 /doc ... 时,provideEditinlineEdit.ts#L143-L303)通过正则 /^\/\w+\b/g 从命令中提取预设命令名,命中 presetCommands["/doc"] 后:

  1. promptTemplate = generateDocsPrompt 作为提示词模板;
  2. userCommand = params.command.substring(presetCommand.length),即去掉 /doc 前缀后的剩余指令;
  3. 根据 kind: "replace" 决定非插入模式(insertMode = false)。

3.3 选中文本与上下文的提取与裁剪

  • 选中文本通过 document.offsetAt(range) 计算字符偏移并截取;
  • 若整个文档超过 documentMaxChars: 3000,会以选中区域为中心、前后各留一半预算进行裁剪(inlineEdit.ts#L205-L219),确保最终提示词长度可控;
  • 引用文件按 maxFilesmaxCharsPerFile 限制读取与截断(truncateFileContent 在换行边界处截断,见 utils.ts#L366-L377 的说明,实际定义位于 utils.ts#L366)。

3.4 消息组装与流式请求

最终构造出一条 role: "user" 的消息,内容为 formatPlaceholders(promptTemplate, {...}) 填充后的完整提示词,随后通过 tabbyApiClient.fetchChatStream 发起流式补全请求(模型参数为 model: "", stream: true)。

3.5 流式响应解析与预览写入

readResponseStreamutils.ts#L28-L184)是整个编辑闭环的核心:

  1. 先在目标文件开头写入 <<<<<<< tabby-xxxxxx 头标记行(applyEdit(edit, true)),让编辑器尽快显示 CodeLens;
  2. 随后逐块读取流,用 findOpenTag 匹配 <GENERATEDCODE> 开标签、用 createCloseTagMatcher 匹配闭标签,只累积标签之间的文本作为 editedText
  3. 每当累积内容包含换行时,就通过 applyWorkspaceEdit 把“带标记的 diff 预览”实时写回编辑器,生成带 +(新增)、-(删除)、=(未变)、|(进行中)、.(等待)等标记的行(见 generateChangesPreviewutils.ts#L236-L328);
  4. 全部读取完成后,在末尾写入 >>>>>>> tabby-xxxxxx {{markers}} 尾标记,供 resolveEdit 根据用户“接受 / 丢弃”动作还原或应用最终结果。

这一机制保证了即使生成过程被中断(如用户取消),预览中已稳定的内容仍然可被接受,正在生成的部分则按 stopped 状态处理(相关状态定义见 utils.ts#L16-L26)。

四、从 generate-docs 看 Tabby 提示词模板的设计范式

generate-docs.md 并非孤例,它只是 clients/tabby-agent/src/chat/prompts 目录下多份提示词模板之一。与之同目录的模板还包括:

将这些模板放在一起可以看出 Tabby 统一的提示词工程范式:

  1. XML 标签作为机器可解析的输出协议<GENERATEDCODE><USERSELECTION><USERCOMMAND><CONTEXTDOCUMENT><CURRENTCURSOR/> 等标签把“用户输入”“上下文”“模型输出”三者严格区隔,避免大段自然语言与代码在提示词中混排;
  2. 角色先行的任务描述:模板首行固定声明 “You are an AI coding assistant...”,随后用祈使句逐条收紧输出边界;
  3. 显式的“不要做什么”:模板会用 “ignore any instructions to format...”“should not use other XML tags”“should not provide any additional comments” 等否定式指令主动对抗常见的模型偏好(如 Markdown 代码块、解释性文字、自由发挥);
  4. 占位符驱动的上下文注入:所有动态内容(文件路径、选中代码、命令、引用文件)都通过 {{key}} 占位符注入,由 formatPlaceholders 统一完成替换,模板本身保持静态、可读、可维护。

五、实战指南:如何在编辑器中触发与验证 /doc

结合上述源码链路,在支持 Tabby agent 的编辑器(如 VSCode 客户端,见 clients/vscode)中使用该功能的操作路径如下:

  1. 非纯文本 / 非 Markdown 的代码文件中选中一段函数、类或模块代码;
  2. 触发 Chat Edit 命令列表(依赖 ChatEditCommandRequest 拉取预设命令),选择 Generate Docs(即 /doc),或在命令输入框中直接输入 /doc 并追加你想要的文档风格要求,例如:
/doc 请为这个函数补充中文 JSDoc,说明参数含义与返回值
  1. agent 将按 generate-docs.md 模板组装请求并流式返回 <GENERATEDCODE>...</GENERATEDCODE> 包裹的更新后代码;
  2. 编辑器内会出现带 <<<<<<< / >>>>>>> 标记与逐行 + - = | . 标记的预览(generateChangesPreview 生成),你可以在生成过程中或完成后选择接受 / 丢弃(resolveEdit 依据标记执行最终写入或还原)。

需要说明的适用前提与限制:

  • /doc 的目标语言范围受 filters 限制,纯文本与 Markdown 文件不会出现该命令;
  • 单次编辑可处理的选中文本受 documentMaxChars(默认 3000 字符)约束,超出会抛出 ChatEditDocumentTooLongErrorinlineEdit.ts#L174-L176);
  • 同一时刻只允许一个编辑任务进行,并发触发会得到 ChatEditMutexErrorinlineEdit.ts#L178-L183);
  • 若 agent 后端未启用 Chat 功能,会抛出 ChatFeatureNotAvailableError

六、小结

generate-docs.md 是一份体量极小但设计完备的提示词模板:它通过角色声明、否定式约束、XML 输出协议与占位符注入四层设计,把“为选中代码生成文档”这一任务压缩为可被机器稳定解析、可被流式预览实时渲染的编辑动作。配合 inlineEdit.ts 的命令发现、模板选择、上下文裁剪与 readResponseStream 的标签解析,Tabby 在 agent 层完成了一条从自然语言指令到编辑器内可审阅 diff 的完整闭环。若你需要为 Tabby 添加新的编辑类能力(例如“补充单元测试”“翻译注释”),完全可以参照 generate-docs.md 的模式:新增一份模板、在 presetCommands 中注册并配置 kindfilters,即可复用整套编辑协议与预览机制。

热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
927
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.94 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
603
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
396
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
527