让大模型生成可维护代码:约束式 Prompt 工程的设计与验证
一、代码生成的隐性成本
用 LLM 写代码很快,改起来也很快。
生成的代码往往"能跑",但经不起维护。
变量名随意、缺少异常处理、逻辑全挤在一个函数里。
这类代码上线后,技术债以惊人的速度累积。
生成十分钟的代码,可能要花一小时理解和重构。
问题不在模型能力,而在我们如何"提要求"。
本文探讨用约束式 Prompt,把可维护性写进生成契约里。
让模型从第一步就产出接近生产标准的代码。
二、约束式 Prompt 的作用机制
普通 Prompt 只描述"做什么"。
约束式 Prompt 额外描述"怎么写"与"不做什么"。
模型在生成时,会把约束当作硬条件逐条满足。
约束越结构化,输出越稳定可复现。
这本质是把团队规范编译成模型能理解的指令。
下面是约束注入与校验的闭环:
flowchart TD A[需求描述] --> B[拼接约束模板] B --> C[大模型生成代码] C --> D[静态检查器校验] D --> E{全部通过?} E -->|否| F[返回违规项作反馈] F --> C E -->|是| G[输出合规代码] style B fill:#e1f5fe style D fill:#fff3e0 style G fill:#e8f5e9关键在"反馈环":校验不通过时,把具体违规回灌给模型。
这比一次性要求更有效,因为模型能针对错误修正。
三、生产级 Prompt 与校验实现
下面是一段可复用的约束模板。
你是一名资深后端工程师,请实现以下需求: {requirement} 硬性约束(必须全部满足): 1. 单函数不超过 50 行,超过则拆分。 2. 所有网络与 IO 调用必须设置超时。 3. 禁止裸 except,必须记录上下文日志。 4. 使用参数化查询,禁止字符串拼接 SQL。 5. 公开函数提供类型注解与 docstring。 6. 先写单元测试再写实现(TDD 顺序)。 仅输出代码与必要注释,不要解释。光有 Prompt 不够,需用检查器兜底。
下面用 AST 统计函数行数,拦截超长函数:
import ast from pathlib import Path def check_function_length(path: Path, limit: int = 50) -> list[str]: """用 AST 扫描超长函数,作为生成代码的守门员""" violations: list[str] = [] tree = ast.parse(path.read_text(encoding="utf-8")) for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): start = node.lineno end = getattr(node, "end_lineno", start) length = end - start + 1 if length > limit: violations.append(f"{node.name} 行数 {length} 超过 {limit}") return violations if __name__ == "__main__": bad = check_function_length(Path("generated.py")) if bad: # 将违规列表回灌模型,触发二次生成 print("需重构:", bad)把违规项拼回 Prompt 的"反馈"段,模型通常能一次修好。
这形成了"生成—校验—修复"的自动闭环。
四、边界分析与架构权衡
约束式 Prompt 有收益,也有代价。
约束越多,遵循率越低。超过 8 条硬约束后,模型容易顾此失彼。
建议只保留"有后果"的约束,风格类交给 formatter。
校验器必须可机器判定。模糊约束如"代码要优雅"无法自动检查。
可量化的约束(行数、类型注解、SQL 参数化)才能落地。
反馈环的轮次成本。每轮校验加生成都消耗 token 与延迟。
建议最多两轮修正,仍不通过则交由人工,避免无限循环。
领域知识依赖。复杂业务需要把领域规则写进约束。
这要求维护一套"约束知识库",随项目演进更新。
约束模板的维护成本需要正视。随着项目演进,规范会变,模板也要同步更新,否则模型依据过时约束生成代码。建议把约束模板纳入版本库,和规范文档同源管理,变更时一起评审。另一个常见误区是盲目追求零人工:对于核心模块,模型生成的代码仍应由人做最终架构确认,约束只解决"格式与基础安全",解决不了"设计对错"。此外,约束模板应定期用历史缺陷回测,删掉从未命中过的条目,保持简洁。模板越精炼,模型遵循率越高,反馈环也越干净。
五、总结
让 LLM 生成可维护代码,关键在把规范变成可执行的约束。
机制上用结构化 Prompt 描述"怎么写",用 AST 校验兜底。
工程上形成"生成—校验—反馈"的闭环。
落地路线:抽取高优先级硬约束成模板;接 AST/linters 做机器校验;把违规回灌模型二次生成;最后把约束库纳入版本管理。代码生成的价值,不在快,而在可维护。