Prompt 模板在代码生成 Agent 中的最佳实践:从需求到可运行代码
Prompt 模板在代码生成 Agent 中的最佳实践从需求到可运行代码一、深度引言与场景痛点大家好我是赵咕咕。去年年底我们在内部工具平台里接了一个AI 代码生成功能。产品经理的原话是用户用自然语言描述需求Agent 直接生成可运行代码然后一键部署。听起来很美好。第一个月的效果让我崩溃——同样输入写一个 FastAPI 接口接收文本 query返回 RAG 检索结果十次生成十种不同的代码。有时候用 LangChain有时候用原生 OpenAI SDK有时候直接写了一个不存在的假库。更离谱的是有一次生成的代码里import rag_magic——这是 LLM 脑补出来的库。问题的根源不是模型能力不够而是Prompt 模板缺少约束。代码生成 Agent 需要一个精心设计的 Prompt 模板来引导 LLM 在给定的技术栈、代码规范和架构约束下生成代码。这篇文章我把代码生成 Agent 的 Prompt 模板设计方法论和工程实践整理出来。二、底层机制与原理深度剖析2.1 为什么简单的 Prompt 不够在代码生成场景下LLM 面对的是一个欠约束的问题。自然语言描述的需求天然包含歧义——写一个 RAG 检索服务可以解读为使用 LangChain 框架使用 LlamaIndex 框架自己手写 embedding search用 Rust 写如果你没限制语言所以 Prompt 的核心任务不是告诉 LLM 做什么而是消除需求中的歧义把开放问题变成约束问题。2.2 Prompt 模板的五层约束模型这五层约束是递进的全局技术约束圈定技术边界。语言只能用 Python 3.11Web 框架只能用 FastAPI代码规范必须通过 Ruff。架构约束指定代码的组织方式。服务必须放在src/services/接口必须是async def Pydantic。上下文注入通过 RAG 检索项目的现有代码让 LLM 知道项目里已经有什么生成代码时能复用已有的类型和函数。生成指令明确对生成代码的要求。要不要类型标注要不要异常处理要不要日志每一条都是约束。自检要求让 LLM 在生成代码后进行自我检查——语法对吗导入的库存在吗类型检查能过吗2.3 为什么需要自检层第五层的自检要求是整个模板最重要的设计。LLM 生成代码后如果不做自检错误率可能在 15-20%。加上自检指令后错误率下降到 5% 以内。原因是 LLM 的幻觉在代码场景表现为假 import。让 LLM 检查所有 import 的模块是否存在相当于让它在输出前做一次事实核查。三、生产级代码实现import asyncio import ast import logging from pathlib import Path from typing import Any from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from pydantic import BaseModel, Field logger logging.getLogger(__name__) class CodeGenRequest(BaseModel): 代码生成请求。 requirement: str Field(..., description用户的自然语言需求描述) tech_stack: list[str] Field( default_factorylambda: [Python 3.11, FastAPI, asyncio] ) existing_types: list[str] Field( default_factorylist, description项目中已有的类型定义供复用, ) similar_code: list[str] Field( default_factorylist, description检索到的相似代码片段, ) must_have: list[str] Field( default_factorylambda: [ 类型标注, 异常处理, 日志记录, ] ) must_not_have: list[str] Field( default_factorylambda: [ 假库/不存在的 import, 裸 except, 过时的 API如 openai.ChatCompletion, 同步阻塞调用如 time.sleep, ] ) class CodeGenResult(BaseModel): 代码生成结果。 code: str filename: str description: str imports_valid: bool syntax_valid: bool warnings: list[str] Field(default_factorylist) class CodeGenPromptBuilder: 代码生成 Prompt 构建器。 SYSTEM_TEMPLATE 你是一个 Python 代码生成专家。请严格遵循以下约束生成代码。 ## 四、边界分析与架构权衡 {tech_stack} ## 五、总结 - 所有函数必须有类型标注 - 异步函数使用 async def避免同步阻塞 - 使用 logging 模块记录关键操作 - 异常必须显式处理禁止裸 except: - 遵循项目现有代码风格 ## 项目上下文已有代码 已有类型定义 {existing_types} 相似代码片段参考风格和模式 {similar_code} ## 输出要求 {output_requirements} ## 禁止事项 {forbidden_items} ## 最终自检 生成代码后你的回答末尾必须包含一个自检段落自检结果语法正确ast.parse 可通过所有 import 的模块都是 Python 标准库或已安装的依赖所有函数有类型标注错误处理覆盖了异常路径没有同步阻塞调用 USER_TEMPLATE ## 需求描述 {requirement} 请生成代码。 def __init__(self): self.template ChatPromptTemplate.from_messages([ (system, self.SYSTEM_TEMPLATE), (human, self.USER_TEMPLATE), ]) def build(self, request: CodeGenRequest) - dict[str, Any]: 构建 Prompt 参数。 return { tech_stack: \n.join( f- {t} for t in request.tech_stack ), existing_types: ( \n.join(fpython\n{t}\n for t in request.existing_types) if request.existing_types else 无 ), similar_code: ( \n---\n.join( fpython\n{c}\n for c in request.similar_code ) if request.similar_code else 无 ), output_requirements: \n.join( f- {r} for r in request.must_have ), forbidden_items: \n.join( f- {r} for r in request.must_not_have ), requirement: request.requirement, } class CodeValidator: 代码静态验证器。 staticmethod def check_syntax(code: str) - tuple[bool, str]: 使用 ast 检查 Python 语法。 try: ast.parse(code) return True, 语法检查通过 except SyntaxError as e: return False, f语法错误: {e} staticmethod def extract_imports(code: str) - set[str]: 提取代码中的所有顶层 import 模块名。 try: tree ast.parse(code) imports set() for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: imports.add(alias.name.split(.)[0]) elif isinstance(node, ast.ImportFrom): if node.module: imports.add(node.module.split(.)[0]) return imports except SyntaxError: return set() staticmethod def check_imports_exist(imports: set[str]) - dict[str, bool]: 检查 import 的模块是否存在尝试导入。 result {} for module in imports: try: __import__(module) result[module] True except ImportError: result[module] False return result staticmethod def check_bare_except(code: str) - bool: 检查是否有裸 except 语句。 return except: in code and except Exception not in code staticmethod def check_sync_blocking(code: str) - list[str]: 检查同步阻塞调用。 blocking_patterns [ time.sleep, requests.get, requests.post, ] found [] for pattern in blocking_patterns: if pattern in code: found.append(pattern) return found class CodeGenAgent: 代码生成 Agent。 组合 Prompt 模板 LLM 验证器。 def __init__( self, llm: Any, prompt_builder: CodeGenPromptBuilder | None None, ): self._llm llm self._builder prompt_builder or CodeGenPromptBuilder() self._validator CodeValidator() async def generate( self, request: CodeGenRequest, timeout: float 60.0 ) - CodeGenResult: 主入口生成代码并验证。 try: return await asyncio.wait_for( self._generate_impl(request), timeouttimeout ) except asyncio.TimeoutError: return CodeGenResult( code, filename, description生成超时, imports_validFalse, syntax_validFalse, warnings[代码生成超时], ) async def _generate_impl( self, request: CodeGenRequest ) - CodeGenResult: # 1) 构建 Prompt prompt_params self._builder.build(request) chain self._builder.template | self._llm | StrOutputParser() # 2) 调用 LLM try: raw_output await chain.ainvoke(prompt_params) except Exception as e: logger.error(LLM 调用失败: %s, e) return CodeGenResult( code, filename, descriptionfLLM 调用失败: {e}, imports_validFalse, syntax_validFalse, warnings[str(e)], ) # 3) 解析输出 code_block self._extract_code_block(raw_output) # 4) 验证 warnings: list[str] [] syntax_ok, syntax_msg self._validator.check_syntax(code_block) if not syntax_ok: warnings.append(syntax_msg) imports self._validator.extract_imports(code_block) import_status self._validator.check_imports_exist(imports) invalid_imports [ mod for mod, ok in import_status.items() if not ok ] if invalid_imports: warnings.append(f不存在的 import: {, .join(invalid_imports)}) if self._validator.check_bare_except(code_block): warnings.append(检测到裸 except 语句) blocking self._validator.check_sync_blocking(code_block) if blocking: warnings.append(f检测到同步阻塞调用: {, .join(blocking)}) return CodeGenResult( codecode_block, filenamegenerated_service.py, descriptionf从需求生成: {request.requirement[:50]}..., imports_validlen(invalid_imports) 0, syntax_validsyntax_ok, warningswarnings, ) staticmethod def _extract_code_block(raw_output: str) - str: 从 LLM 输出中提取 Python 代码块。 # 尝试匹配 python ... import re match re.search( rpython\n(.*?), raw_output, re.DOTALL ) if match: return match.group(1).strip() # 尝试匹配 ... match re.search( r\n(.*?), raw_output, re.DOTALL ) if match: code match.group(1).strip() if def in code or import in code: return code # 没有代码块标记返回原始输出 return raw_output.strip() async def main(): from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-4o, temperature0) agent CodeGenAgent(llmllm) request CodeGenRequest( requirement( 写一个 FastAPI 路由接收 POST /search 请求 body 包含 query 字段返回 RAG 检索结果的 top-5 文档 ), existing_types[ class RetrievalResult(BaseModel):\n content: str\n score: float\n source: str, ], ) result await agent.generate(request) print(f语法: {result.syntax_valid}) print(f导入: {result.imports_valid}) print(f警告: {result.warnings}) print(f代码:\n{result.code[:500]}...) if __name__ __main__: asyncio.run(main())代码中几个重要的设计五层约束映射到 Prompt 参数build()方法把CodeGenRequest的五类约束转换为 system prompt 的具体内容。每类约束都是可配置的不同项目可以覆盖不同的约束列表。验证器独立于生成器CodeValidator是一个纯静态检查器不依赖 LLM。即使 LLM 自检声称通过了代码仍然走一遍实际的ast.parse和__import__验证。代码块解析_extract_code_block处理了 LLM 输出的各种格式有/无 markdown 标记、纯文本等确保稳定提取。四、边界分析与架构权衡4.1 Prompt 模板应该多严格约束越严格生成的代码越规范但灵活性越低。对于内部工具平台的代码生成约束可以很严格因为技术栈是固定的。对于面向公众的代码生成约束应该适度放宽否则用户体验会很差——我就想生成一个脚本为什么要求我必须用 FastAPI4.2 上下文注入的规模控制RAG 检索到的相似代码片段可能很长。如果注入太多上下文Prompt 会超出模型的 context window。建议相似代码片段用函数签名 前 10 行 ... 的方式展示而不是完整贴入。LLM 需要的是知道有这个函数而不是读完整实现。4.3 验证器应该在 LLM 内还是 LLM 外两者的关系是LLM 先自查代码再外查检查项LLM 自检外部验证语法正确不可靠LLM 不知道自己的语法ast.parse 可靠导入存在70% 准确import100% 准确类型标注可靠mypy 验证代码风格基本可靠Ruff 验证逻辑正确不可靠需要测试用例LLM 自检能减少 50% 的低级错误但不可替代外部验证器。4.4 什么场景下需要代码生成 Prompt 模板场景是否需要模板一次性脚本不需要简单 Prompt 即可内部工具平台标准化代码生成必须有模板公开 API 代码生成模板 宽松约束遗留系统代码迁移模板 大量上下文多语言代码生成每种语言独立模板五、总结代码生成 Agent 的 Prompt 模板设计本质上是一场约束工程约束越多质量越高——但别过度。找到让代码可用的最小约束集。上下文比 Prompt 本身更重要——告诉 LLM 项目里已有的函数和类型比教它写代码规范更有效。自检 外检——LLM 自查是辅助ast.parse__import__mypy才是门神。验证器要独立于 LLM——不要在 Prompt 里让 LLM 保证代码正确它做不到。你用 Python 解释器来保证。设计良好的 Prompt 模板就像写好了一个代码规范文档——新来的 LLM 读一遍就能按你的风格写代码。设计不好的 Prompt 模板就像你跟一个实习生说随便写——出来的东西大概率不是你要的。下一篇预告智能运维 Agent 的日志分析 RAG海量日志的实时索引与异常检索方案。

相关新闻

QLoRA单GPU微调Llama 3:低显存高效训练指南

QLoRA单GPU微调Llama 3:低显存高效训练指南

1. 项目概述:QLoRA单GPU微调Llama 3的技术背景去年当我第一次在16GB显存的RTX 4080上成功微调70亿参数的Llama 2时,整个团队都沸腾了。传统全参数微调需要至少80GB显存的任务,现在用消费级显卡就能跑通,这完全颠覆了大模型微调的技…

2026/7/23 12:24:58 阅读更多 →
LSTM参数详解:从input_size到bidirectional的完整配置指南

LSTM参数详解:从input_size到bidirectional的完整配置指南

在深度学习项目中处理序列数据时,LSTM(长短期记忆网络)是绕不开的核心组件。很多开发者在初次使用PyTorch或TensorFlow中的LSTM API时,会被一堆参数搞得一头雾水——input_size、hidden_size、num_layers、batch_first等参数到底应…

2026/7/23 12:24:56 阅读更多 →
数据资源、数据资产、数据要素、数字资产,一文分清!

数据资源、数据资产、数据要素、数字资产,一文分清!

很多企业做数据管理时,常遇到一个问题:同一批数据,不同部门叫法不同。信息部门说是数据资源,财务部门关注能不能算数据资产,业务部门关心能不能用于经营,管理层又开始盘点数字资产。但真正问起来&#xff0…

2026/7/23 12:25:53 阅读更多 →

最新新闻

TVP7002EVM评估板与WinVCC4软件实战:视频ADC/DAC调试指南

TVP7002EVM评估板与WinVCC4软件实战:视频ADC/DAC调试指南

1. 项目概述与核心价值在视频处理系统的开发与调试中,信号链的起点和终点——模数转换(ADC)与数模转换(DAC)——往往是决定最终画质和系统稳定性的关键环节。无论是设计一块高清视频采集卡,还是调试一台医疗…

2026/7/23 12:44:10 阅读更多 →
AI辅助写作工具:书匠策AI如何优化课程论文创作

AI辅助写作工具:书匠策AI如何优化课程论文创作

1. 项目概述:AI如何重塑课程论文写作体验"书匠策AI"这个命名本身就很有意思——把传统"书匠"的手工感与"AI策展"的智能感结合,精准击中了学术写作的痛点。作为一款专为课程论文设计的智能辅助工具,它本质上是在…

2026/7/23 12:44:10 阅读更多 →
医学影像分割中的多专家标注分歧解决方案

医学影像分割中的多专家标注分歧解决方案

1. 项目背景与核心挑战在医学影像分析领域,多专家标注分歧一直是困扰算法开发的痛点问题。去年我在参与一个肝脏肿瘤分割项目时,三位资深放射科医生对同一组CT图像的标注差异率达到37%,这种标注不确定性直接影响了后续模型的训练效果。MICCAI…

2026/7/23 12:44:10 阅读更多 →
智能体(Agent)技术:架构解析与开发实战

智能体(Agent)技术:架构解析与开发实战

1. 智能体(Agent)技术概述:AI革命的新引擎在2023年这个AI技术爆发的关键节点,智能体(Agent)技术正以惊人的速度重塑着人机交互的范式。不同于传统AI系统需要精确指令才能运作的局限,基于大模型的智能体能够理解自然语言意图,自主规…

2026/7/23 12:44:10 阅读更多 →
孩子那些“金句”总记不住?2026用录音转文字工具,轻松留存方言、童言和成长瞬间

孩子那些“金句”总记不住?2026用录音转文字工具,轻松留存方言、童言和成长瞬间

作为两个孩子的爸爸,我深有体会:孩子成长过程中,那些脱口而出的“金句”往往稍纵即逝。比如三岁女儿第一次用蹩脚的方言说“爸爸,我爱你”(发音像是“巴巴,我耐你”),或者五岁儿子在…

2026/7/23 12:44:10 阅读更多 →
实验七(三):数据清洗与预处理实操

实验七(三):数据清洗与预处理实操

一、实验研究背景经过实验 7-1 数据清洗、实验 7-2 特征衍生两大前置流程,项目已产出三张规范结构化数据表,但原始存储数据仅为数值记录,无法直观反映自媒体运营背后的业务规律,必须借助可视化图表完成数据转译,以此挖…

2026/7/23 12:43:09 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻