最近在用自己开发的编程智能体 cli_coder(基于 Qwen3-Max)开发一个 Rust 后端项目时,我再次深刻体会到一件事:即使在强类型语言中,数据模型的设计质量,依然直接决定了 AI 协同编程的上限

这并非新发现——在之前的《分形生成实验(三):Rust 强类型驱动的后端分步实现与编译时契约》中,我就已强调过类型系统作为“人与机器契约”的价值。而这次实践,更像是对这一理念在 AI 协作场景下的一次再确认与深化

模型演进:从“可用”到“精准表达语义”

这个项目从一开始就采用 Rust 的强类型系统进行建模,并未依赖纯自然语言描述来生成初始结构。然而,在早期版本中,我对 AnalysisRequest 的建模仍显粗糙:

#[derive(Default, Debug, Clone, Deserialize)]
pub struct AnalysisRequest {
    pub jd: String,
    pub resume: String,
    pub additional_info: Option<String>,
    pub answers: Option<Vec<Answer>>,
}

虽然类型安全,但业务语义被隐式地藏在字段组合的逻辑中。例如,“初始分析”和“后续问答”两种请求共用同一结构,导致处理逻辑需要通过字段是否为 None 来判断意图——这不仅易错,也难以让 AI 准确把握上下文。

当我意识到这一点后,将其重构为带标签的枚举:

#[derive(Debug, Clone, Deserialize)]
#[serde(tag = "request_type", rename_all = "snake_case")]
pub enum AnalysisRequest {
    InitialAnalysis { jd: String, resume: String },
    FollowUpAnswers {
        answers: Vec<Answer>,
        additional_info: Option<String>,
    },
}

这一次,当我将新模型提供给 cli_coder 并提示“请基于此更新相关逻辑”时,它迅速生成了正确的模式匹配、错误处理和序列化代码。不是因为它更聪明了,而是因为模型本身已显式编码了业务状态的区分

数据模型即契约

这再次印证了我此前的观点:类型系统是人与系统之间的契约。而在 AI 协同编程中,这份契约的另一方变成了大模型。

当我们用 enum 表达状态机、用 struct 定义资源关系,我们实际上是在为大模型构建一个结构化的语义锚点。它不再需要从模糊的文本中推断“用户可能想做什么”,而是直接依据你定义的类型分支来生成对应行为。

另一个例子是 UserState 的演进。我在原有字段基础上增加了 messages: Vec<TraceMessage>,以显式建立用户状态与交互消息的关联。这一变更虽小,却让后续所有涉及会话恢复、日志追踪、状态持久化的代码生成变得连贯一致——因为“状态包含消息历史”这一关系已被模型固化。

这是 “Vibe Coding” 吗?

社区常提的 “vibe coding” 强调通过自然语言与 AI 共创代码。我认为,以精准数据建模为基础的协作,正是 vibe coding 的一种更稳健的实践形式

它保留了高阶抽象的灵活性,但通过显式模型避免了纯文本提示常见的歧义与逻辑断裂。你可以把它看作 “有骨架的 vibe”:骨架由你设计,血肉由 AI 填充。

需要说明的是,目前 cli_coder 并未自动解析模型或强制执行这种范式。这一切依赖于我在与大模型交互时,主动提供清晰、演进中的数据定义。但这恰恰说明:工具可以辅助,但建模的思考仍需开发者主导

结语:建模先行,协作更稳

AI 编程不是要取代设计,而是让设计的价值更加凸显。
当你花时间把 models/ 目录里的结构打磨到能精准表达业务语义,你其实是在为大模型绘制一张高精度地图。它走得越稳,你越敢放手。

这条路还在探索中,但我相信:在人与 AI 的协作中,清晰的数据模型,是最值得信赖的共同语言

注:cli_coder 是我正在迭代的编程智能体项目,欢迎关注其后续是否能将“模型即契约”的理念进一步自动化。

相关文章:

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐