技术教程 · 阅读约 8 分钟

让 AI 写出「三个月后还能看懂」的代码——一个可落地的提示词工程实战

让 AI 写出「三个月后还能看懂」的代码——一个可落地的提示词工程实战

你有没有遇到过这种情况:打开三个月前让 AI 帮你写的一段代码,完全不知道它在干什么。变量叫 res2,函数叫 handleStuff,注释一行没有,逻辑全靠猜。

这不是 AI 的问题,是你没告诉它你要什么。

今天这篇文章,我们用一个可以直接跑的 Python 脚本,系统性地解决这个问题——让 AI 生成的代码,从第一行就对人类友好。


问题根源:AI 默认生成「能跑」而不是「能读」

大多数人给 AI 的 prompt 是这样的:

"帮我写一个解析 JWT 的函数"

AI 给出的结果能跑,但:

  • 没有类型注解
  • 没有边界情况说明
  • 异常处理是 except Exception as e: pass
  • 函数名叫 parse,参数叫 t

三个月后你回来看,等于看天书。

解法不是换模型,是换提示词策略。


核心思路:给 AI 一个「代码风格宪法」

我们要做的是在每次请求前,注入一段系统级的编码规范,让模型知道你的期望不只是「能跑」,而是「可维护」。


完整可运行代码

下面这个脚本封装了一个 CodeGen 类,你可以直接集成到自己的工作流里。


# codegen.py

# 依赖: pip install openai



from openai import OpenAI



client = OpenAI(

    api_key="你的API密钥",

    base_url="https://api2everything.xyz/v1"  # 国内直连,无需代理

)



# ===== 核心:代码风格宪法 =====

CODE_CONSTITUTION = """

你是一位注重可维护性的高级工程师。生成代码时必须遵守以下规则:



1. **命名规范**

   - 变量/函数名必须是自解释的,禁止使用 res, data, tmp, stuff 等模糊名

   - 布尔变量以 is_/has_/can_ 开头

   - 常量全大写加下划线



2. **类型注解**(Python)

   - 所有函数参数和返回值必须有类型注解

   - 复杂类型用 TypedDict 或 dataclass 定义



3. **注释规范**

   - 每个函数必须有 docstring,说明:做什么、参数含义、返回值、可能抛出的异常

   - 非直觉逻辑必须有行内注释,解释「为什么」而不是「做什么」



4. **错误处理**

   - 禁止裸 except,必须捕获具体异常类型

   - 错误信息必须包含上下文,方便调试



5. **边界情况**

   - 函数开头必须校验关键参数

   - 说明函数对 None、空列表、空字符串的处理方式



生成完代码后,附上一段「三个月后的你需要知道的事」,用 2-3 句话解释这段代码最容易踩的坑。

"""



def generate_maintainable_code(

    task_description: str,

    language: str = "Python",

    model: str = "claude-sonnet-4-5"

) -> str:

    """

    根据任务描述生成可维护的代码。



    Args:

        task_description: 自然语言描述的编程任务

        language: 目标编程语言,默认 Python

        model: 使用的模型,支持 Claude / GPT / Gemini 等 300+ 模型



    Returns:

        包含代码和维护说明的完整响应字符串



    Raises:

        openai.APIError: API 调用失败时抛出

    """

    response = client.chat.completions.create(

        model=model,

        messages=[

            {

                "role": "system",

                "content": CODE_CONSTITUTION

            },

            {

                "role": "user",

                "content": f"语言:{language}\n\n任务:{task_description}"

            }

        ],

        temperature=0.2,  # 降低随机性,代码生成用低温度更稳定

    )



    return response.choices[0].message.content





# ===== 批量生成模式:一次性生成整个模块 =====

def generate_module(tasks: list[str], module_name: str) -> None:

    """

    批量生成一个模块的多个函数,统一风格。



    Args:

        tasks: 任务描述列表,每项对应一个函数

        module_name: 输出文件名(不含 .py)

    """

    print(f"开始生成模块 {module_name},共 {len(tasks)} 个函数...\n")



    all_code_parts: list[str] = []



    for i, task in enumerate(tasks, start=1):

        print(f"[{i}/{len(tasks)}] 生成中:{task[:50]}...")

        code = generate_maintainable_code(task)

        all_code_parts.append(f"# === 函数 {i}:{task[:30]} ===\n{code}\n")



    output_path = f"{module_name}.py"

    with open(output_path, "w", encoding="utf-8") as f:

        f.write("\n\n".join(all_code_parts))



    print(f"\n✅ 已写入 {output_path}")





if __name__ == "__main__":

    # 单个函数示例

    result = generate_maintainable_code(

        task_description="解析 JWT token,提取 payload,验证过期时间",

        language="Python"

    )

    print(result)


关键细节解释

为什么用 temperature=0.2

代码生成不需要创意,需要确定性。低温度让模型更倾向于标准写法,减少「聪明但奇怪」的实现。

「三个月后需要知道的事」这个技巧从哪来?

这是逼迫模型做元认知的方式——它生成代码的同时,必须思考这段代码的脆弱点在哪。实践下来,这部分内容往往比注释本身更有价值。

为什么用这个 base_url?

我用的是无量 API,国内直连,不需要代理,支持 Claude、GPT-4o、Gemini、DeepSeek 等 300+ 模型,而且价格比官方便宜 60% 以上。claude-sonnet-4-5 这类需要付费订阅才能用的模型,在这里按 token 付费,日常学习和小项目非常划算。注册还送 ¥1 余额,可以先试试效果。


实际效果对比

同样的任务「解析 JWT」,普通 prompt 给出的结果:


def parse(t):

    parts = t.split('.')

    return json.loads(base64.decode(parts[1]))

用上面这套 prompt 工程之后:


def decode_jwt_payload(token: str) -> dict[str, Any]:

    """

    解码 JWT token 的 payload 部分,不做签名验证。



    Args:

        token: 标准格式的 JWT 字符串(header.payload.signature)



    Returns:

        解码后的 payload 字典



    Raises:

        ValueError: token 格式不正确(不含两个 '.')

        jwt.ExpiredSignatureError: token 已过期

    """

    ...

差距一目了然。三个月后你回来,第一个你看不懂;第二个你直接知道该怎么用、会出什么问题。


延伸:把这套规范加到你的编辑器里

如果你用 Cursor 或 VS Code + Continue,可以把 CODE_CONSTITUTION 的内容直接放进项目根目录的 .cursorrulesAGENTS.md 文件。这样所有 AI 辅助写代码的场景都会自动应用这套规范,不用每次手动注入。


代码已经给到了,逻辑也说清楚了。如果你在实际运行中遇到问题,或者想聊某个具体场景下的 prompt 策略,评论区见。

觉得有用的话点个赞,下次更新「如何让 AI 给遗留代码自动补文档」。


🔗 文中用到的 API 服务无量 API — 国内直连 300+ 模型,注册送 ¥1,余额永久有效