跳到主要内容

个性化设置应当属于 Dotfile,而非向量数据库

· 阅读需 14 分钟
Tian Pan
Software Engineer

当产品团队第一次需要针对每个用户的智能体(agent)行为时,通常会有人说“我们应该进行微调”或“让我们接入持久化内存”。一周后,他们拥有了向量数据库、反馈循环流水线,以及监控学习状态漂移的路线图项。他们构建了一个机器学习系统来解决一个在十有八九的情况下其实只是配置文件的问题。

看看用户真正想要的是什么:更简洁的回答、要点列表而非散文、免责声明中包含我的公司名称、默认使用我偏好的模型、100 美元以下不要转接到人工、这是我本周正在处理的项目、永远不要使用表情符号。这些都不需要模型去学习任何东西。它需要的是设置(settings)。Dotfile 模式——一个版本化的、声明式的、针对每个用户的配置库——在四十年前就为 shell、编辑器和 CLI 解决了这个问题,而这正是 2026 年 AI 智能体的正确形态。

团队跳过它的原因部分是出于地位考虑——微调听起来像是真正的机器学习工作,而设置听起来像是平淡的周二日常——部分是由于大语言模型时代早期的习惯,当时一切都是系统提示词(system prompt),且系统提示词是庞大且单一的(monolith)。现在这两者都错了。智能体是软件。为它们提供针对每个用户的行为的最廉价、最易调试、最尊重用户的方式是交付给它们一个 Dotfile。

大多数“个性化”只是伪装的配置

调研一下任何智能体产品的待办事项中的个性化需求。列表看起来大概是这样的:语气(简洁、正式、随意、生硬)、输出格式(Markdown、纯文本、JSON)、默认模型层级、默认启用的工具、转接阈值、语言、时区、默认项目或工作空间、禁止操作列表(不要运行 shell 命令、未经确认不要发送 Slack 消息)、偏好的引用样式、面向客户的智能体的人格叠加。

列表中的每一项都是用户明确选择的值。它们不是模型应该从交互历史中推断出的模式。它们是具有清晰模式(schema)、默认值和一小组有效值的偏好。用户修改一次后,行为应该立即且可预测地发生变化——而不是在三个会话之后,当嵌入(embedding)模型终于跟上时。

一个有用的心理测试:如果用户可以用一句话清晰地表达偏好(“永远不要使用表情符号”),那就是配置。如果他们不能(“写得更像我们的资深工程师”),那就是嵌入、示例或微调发挥作用的地方。界限比人们假装的要清晰得多,而配置这一侧的需求是巨大的。

Dotfile 模式到底能带给你什么

将这个类比简化到其原语,有四个属性至关重要:

  • 声明式(Declarative)。 文件陈述期望的状态,而不是实现该状态的步骤。“tone: terse” 而不是 “在每次回答后,检查之前的风格并进行调整”。
  • 版本化(Versioned)。 每次更改都是一个带有作者和时间戳的 diff,可恢复、可审查且可回滚。
  • 可组合(Composable)。 层层覆盖——系统默认、组织、团队、用户、项目、会话——最具体的获胜。
  • 可检查(Inspectable)。 用户可以阅读文件,确切地知道是什么在塑造智能体的行为。支持人员、合规部门和下一任工程师也可以做到这一点。

这些正是 GitOps 为基础设施带来的属性——声明式状态、版本控制、自动协调、可追溯。SRE 团队通过惨痛教训学到的是,命令式配置和学习状态都会以难以观察、更难以回滚的方式发生漂移。相比之下,声明式状态允许你对比今天和昨天的差异,并清晰地说明发生了什么变化。

基于学习的个性化技术栈不具备这些属性。用户的偏好存在于向量或模型权重中。没有人能阅读它。没有人能对比它。回归测试看起来就像是“智能体这周感觉不一样了”,而答案是重新训练,而不是回滚。审计人员并不喜欢这种对话。

一个模式(Schema),而非自由格式的提示词

破坏 Dotfile 模式最快的方法是将文件变成自由格式的内容——一个用户在其中输入的单一 Markdown 文档。这会让你落入两难境地:智能体端解析困难,用户端没有验证、没有自动补全、没有默认值,也没有契约。

真正的针对每个用户的智能体配置有一个模式。在最近的智能体框架(VS Code 自定义智能体、OpenCode、Continue、Microsoft 365 的声明式智能体、Google 的 Agent Development Kit、Claude Code 的 CLAUDE.mdsettings.json 组合)中出现的形态是以下内容的某种组合:

  • 身份块(名称、人格、受众)。
  • 能力块(哪些工具、具有哪些权限范围、针对哪些类型的任务)。
  • 约束块(禁止操作规则、转接阈值、司法管辖标志)。
  • 上下文块(项目、工作空间、相关文档)。
  • 组合块(包含哪些提示词片段,按什么顺序)。
  • 模型和路由块(默认层级、备选方案、延迟预算)。

这种结构并非随意的。它映射到了已经成为最佳实践的四层系统提示词架构:身份、能力、约束、上下文。在配置中保持每一层独立意味着你可以修改其中一层而无需重新读取其他层,并且你可以独立测试每一层。

模式还启用了一个单一体提示词(monolithic prompt)无法提供的属性:显式的默认值和覆盖。系统提供合理的默认值;组织覆盖一些;团队再覆盖一些;用户覆盖一小部分;当前项目覆盖一两个。智能体在请求时解析这一叠配置并序列化最终状态。你作为用户可以问“你为什么做 X”,答案是一个带有获胜者的配置路径——而不是“模型感觉是这样”。

Prompt 片段:Dotfile 连接模型的桥梁

从结构化的配置文件到实际的大模型(LLM)调用的桥梁就是 Prompt 片段。Agent 并不是通过字符串拼接来组装一个巨大的系统 Prompt,而是维护一个小型、命名的片段库——每个片段都是一两段专注于特定指令的内容——配置文件按定义顺序通过名称引用它们。

以语气设置为例。Agent 代码中不需要包含带有五个 if tone == "terse" then prepend "be terse..." 分支的 switch 语句,系统只需将 fragments/tone-terse.md 文件提交到代码仓库。用户的配置显示 tone: terse,解析器在请求时加载相应的片段。添加新语气就是添加一个片段。审计用户看到的内容就是阅读他们引用的片段。对新约束进行 A/B 测试只需发布一个新片段,并在配置层路由一小部分流量,无需更改代码。

这种方法还解决了单体式巨型 Prompt 导致的 Token 成本问题。一个包含 50 个片段的库只加载用户配置实际引用的片段,在实践中通常只有几个——往往是 5,000 到 10,000 个 Token 的专注指令,而不是没人能从头读到尾的 50,000 个 Token 的全量 Prompt。撇开价格不谈,当指令精简、有序且相关时,模型的表现会更好。

这种模式与 Prompt 缓存(Prompt Caching)完美契合。稳定层(系统身份、组织默认设置、团队配置)位于 Prompt 顶部,每次请求都能命中缓存。动态层(当前项目、会话范围的覆盖)位于底部。缓存层级与覆盖层级相镜像,这种巧合在生产环境中带来了巨大的收益。

无需重训,即时加载

Agent dotfile 与任何基于机器学习(ML)的个性化方案的一个显著区别在于其重载语义。当用户切换偏好时,下一个请求就会看到新行为——就是这么简单。没有训练运行,没有评估周期,没有嵌入(embedding)刷新,不需要“给它一周时间学习”。

构建这一点并不难。Agent 在每次请求时从已知路径读取配置,或者通过文件监控器(file watcher)观察它,或者从具有短 TTL(生存时间)的键值存储中获取。Claude Code 的 CLAUDE.md 文件监控器就是这一理念的公开实践:在会话中途编辑文件,下一个响应就会使用新指令,无需重启。同样的模式也适用于托管的多租户 Agent 产品——用户的配置是数据库中的一行,请求路径在读取时通过每请求缓存(per-request cache)并在写入时失效。

这对用户体验的影响是巨大的。如果用户修改了一个设置,并看到 Agent 在下一条消息中改变了行为,他们就会建立起一种信任,这种信任与他们对任何其他可配置软件的信任是一致的。而如果用户修改了设置,却还要等待观察模型是否“学会了”,那么他就是在与一个黑盒打交道。第一种用户会提交连贯的 Bug 报告;第二种用户则会提交基于“感觉”的投诉,从而演变成长达数周的调查。

解决的问题与保留的领域

Dotfile 模式消除了一长串学习型个性化方法固有的问题:

  • 无声退化(Silent regression)。 当学习到的状态发生偏移时,行为也会发生偏移,而你只能从用户报告中发现这一点。当配置不变时,行为就不会改变。
  • 不透明性(Opacity)。 “Agent 为什么那样做?”可以通过配置差异(config diff)来回答。而对于学习到的状态,这得变成一个研究项目。
  • 无法干净导出。 当个性化是一个用户可以下载的文件时,GDPR 式的可移植性或“删除我的数据”就变得非常简单。对于权重(weights)和嵌入,这则是一个合规性难题。
  • 评估歧义(Eval ambiguity)。 配置与输出的契约是可测试的:给定配置 C 和输入 I,输出 O 应该通过这些检查。而学习型个性化的评估必须跨越会话、控制偏移并考虑重训频率。

它并没有抹杀微调(fine-tuning)和长期记忆的正当用途。领域特定术语、对过去对话的回溯、真正从交互历史中显现的行为——所有这些仍然需要它们自己的机制。关键点在于,它们应该位于声明式配置层之上,而不是取代它。Dotfile 处理 70% 属于偏好的个性化;机器学习处理另外 30% 真正属于涌现的部分。

值得捍卫的边界是:任何用户原则上可以写下的偏好都属于配置,而任何用户无法写下的内容都是学习状态的候选。大多数团队模糊了这条界线,最终使用机器学习来解决配置问题,这既昂贵、不透明,又难以支持。

如何测试配置驱动的行为

一旦个性化变成声明式的,评估就不再是会话回放的噩梦,而是变成了契约测试(contract tests)。这种形式就像 QA 团队过去三十年里编写的那种枯燥测试:给定配置 C 和输入 I,输出 O 必须满足断言 A。

用户行为变成了一个矩阵——配置维度在一个轴上,输入场景在另一个轴上——你可以在每次提交代码时运行。对默认 tone-terse.md 片段的修改会触发所有引用它的配置的回归测试;对约束片段的修改会触发所有启用该约束的用户的回归测试。更改的影响范围正是引用了该更改片段的配置集,这可以从配置文件中计算出来。对于学习型个性化技术栈,你无法做到这一点,除非有一套没人愿意运行的、既慢又嘈杂的全量评估套件。

这还让你能以发布代码同样的工程严谨性来发布用户行为:特性标志(feature-flag)化的片段、配置层的灰度发布(canary rollouts)、通过组合两个版本的片段库并切换指针来实现蓝绿部署。你组织中现有的用于安全代码部署的基础设施都是可以复用的——因为,Agent 本质上也是软件。

这对组织架构意味着什么

一旦你接受了个性化路线图中有一半的最廉价答案是声明式配置,工作重点就会发生转移。负责“智能体个性化”的团队不再是一个机器学习团队,而是一个配置管理团队——其职能更接近平台工程,而非应用研究。他们负责维护模式(schema)、片段库(fragment library)、解析器(resolver)、文件监控器(file watcher)以及评估矩阵(eval matrix)。他们发布契约,供产品团队基于此进行配置。

产品端的迭代循环会变得更快。添加一个新的画像(persona)只需编辑一个 YAML 文件并发布一个片段,而不是训练一个模型。为客户移除某项功能只需在他们的配置中切换一个开关(flag),而不是重新追溯微调数据集。合规性检查变成了“给我看该用户在周二 14:32 的配置以及它所引用的片段”,这是一个查询操作,而不是一场司法取证式的排查。

除此之外,还有一个关键的长期岗位:需要有人像对待文档站点一样对待片段库,制定编辑标准、命名规范、弃用政策和评审流程。片段库是智能体的公共表面;如果任其随意增长,它就会变成增加了额外步骤的新版“巨型提示词(mega-prompt)”。如果将其视为精心维护的资产,它就是系统中杠杆率最高的代码。

先选最廉价的方案

在个性化问题上本能地诉诸机器学习,其动机与在单体架构问题上本能地诉诸微服务如出一辙:追逐潮流、追求地位,以及不愿反思更简单的工具是否已经能解决问题。在这种情况下,更简单的工具就是配置文件。它是版本化的、声明式的、分层的、可组合的且可检查的。那些赋予 SRE 团队可运维基础设施的原始语料,同样将赋予智能体团队可运维的个性化能力。

从 dotfile 开始。只有当 dotfile 显而易见地无法支撑时,再考虑向量数据库。这个顺序至关重要,因为 dotfile 是可逆的——你始终可以在声明式状态之上叠加载机器学习,但习得的个性化(learned personalization)却不可逆。你无法追溯性地让嵌入(embeddings)变得可审计,也无法为模型权重补全版本历史。但对于一个由配置驱动的系统,你随时可以对其进行升级,在机器学习确实能产生实际效益的场景中使用它。

领悟到这一点的团队在周二就能上线个性化功能;而没领悟到的团队到周五还在为训练数据争论不休。

References:Let's stay in touch and Follow me for more thoughts and updates