Skip to content

Latest commit

 

History

History
204 lines (130 loc) · 15.3 KB

File metadata and controls

204 lines (130 loc) · 15.3 KB

.\MetaGPT\metagpt\prompts\di\engineer2.py 详细设计文档

该文件定义了一个用于指导AI程序员(Engineer2)的复杂指令集(EXTRA_INSTRUCTION),它整合了基础角色指令(ROLE_INSTRUCTION)和一系列关于文件编辑、终端操作、项目创建、技术栈选择、代码编写与部署的详细规则和最佳实践。核心功能是为一个自主编程代理提供操作上下文、约束条件和执行流程的详细规范。

整体流程

graph TD
    A[开始: 接收用户需求] --> B{是否提供Issue链接?}
    B -- 是 --> C[使用Browser工具导航至Issue页面]
    B -- 否 --> D[检查当前路径下是否存在目标仓库]
    D -- 不存在 --> E[下载仓库并导航至其路径]
    D -- 存在 --> F[导航至仓库路径]
    F --> G[进入项目主循环]
    G --> H{根据需求制定计划?}
    H -- 是 --> I[列出待编码文件,规划任务]
    H -- 否 --> J[直接执行简单任务]
    I --> K[循环处理每个文件/任务]
    K --> L{使用哪种工具修改文件?}
    L -- 大范围重写/多次编辑失败 --> M[使用Engineer2.write_new_code]
    L -- 小范围精确编辑 --> N[使用Editor工具链]
    N --> O[使用Editor.open_file打开文件]
    O --> P[执行编辑命令(如edit_file_by_replace)]
    P --> Q[验证更改,确保符合PEP8]
    K --> R{是否为前端项目?}
    R -- 是 --> S[使用指定模板(Vue/React)创建项目]
    R -- 否 --> T[在`{project_name}_{timestamp}`文件夹中工作]
    S --> U[复制模板,读取关键文件]
    U --> V[重写src/和index.html文件]
    V --> W[使用Tailwind CSS等指定技术栈]
    K --> X[完成所有文件后]
    X --> Y[构建项目(pnpm install && pnpm run build)]
    Y --> Z[部署dist文件夹到公开环境]
    Z --> AA[结束]
Loading

类结构

该文件不包含显式的类层次结构它是一个配置/指令脚本主要包含:
├── 全局常量 (EXTRA_INSTRUCTION, CURRENT_STATE, ENGINEER2_INSTRUCTION)
├── 全局函数 ()
└── 从外部导入的常量 (REACT_TEMPLATE_PATH, VUE_TEMPLATE_PATH, ROLE_INSTRUCTION)

全局变量及字段

EXTRA_INSTRUCTION

一个包含详细操作指南和约束条件的多行字符串,用于扩展和定制AI工程师(Engineer2)的行为指令。

类型:str

CURRENT_STATE

一个格式化字符串模板,用于描述代码编辑器的当前状态,包括工作目录和打开的文件。

类型:str

ENGINEER2_INSTRUCTION

AI工程师(Engineer2)的完整指令,由基础角色指令(ROLE_INSTRUCTION)和扩展指令(EXTRA_INSTRUCTION)拼接而成。

类型:str

WRITE_CODE_SYSTEM_PROMPT

定义代码编写AI系统角色的提示词,强调遵循设计、完整实现和代码质量。

类型:str

WRITE_CODE_PROMPT

一个格式化字符串模板,用于在具体编写单个代码文件时,向AI提供用户需求、计划状态、文件路径和描述等上下文信息。

类型:str

全局函数及方法

关键组件

指令与提示词系统

定义了用于指导AI代理(如自主程序员)行为的多层级指令和系统提示词,包括核心角色指令、额外操作约束、代码编写规范以及当前状态模板。

常量与路径管理

管理项目模板(如React, Vue)的绝对路径,并通过time.time()动态生成时间戳,用于构建唯一的项目文件夹名称。

代码生成与编辑策略

规定了代码生成(Engineer2.write_new_code)与文件编辑(Editor工具系列命令)的使用场景、优先级和最佳实践,例如何时重写整个文件、如何避免重复编辑导致的语法错误等。

项目初始化与构建流程

定义了使用特定技术栈(Vite, Vue/React, MUI, Tailwind CSS)创建前端项目的标准化步骤,包括模板复制、文件读取、重写计划以及最终的构建和部署流程。

错误处理与操作约束

包含了一系列针对文件编辑、目录导航、命令使用频率的详细约束和错误预防措施,旨在确保AI代理操作的稳定性和代码质量。

问题及建议

已知问题

  • 指令字符串硬编码与格式化风险EXTRA_INSTRUCTION 字符串通过 .format() 方法进行格式化,但字符串内部包含大量需要动态替换的占位符(如 {{project_name}}, {{workspace}}, {{template_folder}}),这些占位符并未在 .format() 调用中被实际替换。这会导致运行时这些占位符保持原样,可能引发下游工具或代理的解析错误或逻辑混乱。
  • 指令逻辑矛盾与歧义
    1. 第11条与第11.1条存在潜在的逻辑冲突。第11条建议在一次响应中只执行第一个编辑操作,将后续操作推迟到下一轮;而第11.1条禁止在单个命令列表中使用多次 Editor.insert_content_at_lineEditor.edit_file_by_replace。虽然意图相似,但表述不够清晰,可能被误解为完全禁止在一次 交互 中进行多次编辑规划,而不仅仅是单次 命令列表
    2. 第24条与第25条关于技术栈优先级的描述存在重叠和潜在的决策路径不清晰。第24条给出了一个优先级列表,而第25条又为特定技术栈(Vite, Vue/React, MUI, Tailwind CSS)规定了一套详细步骤。当条件满足时,代理应遵循哪一套规则?是优先应用第25条的详细步骤,还是先根据第24条判断优先级再决定?这增加了代理决策的复杂性。
  • 时间戳静态化EXTRA_INSTRUCTION 中的 {timestamp} 在字符串格式化时被固定为模块加载时刻的时间(int(time.time()))。这意味着所有后续使用该指令的会话都会共享同一个时间戳,与第14条要求的“每次生成唯一文件夹”的意图相悖,可能导致文件夹命名冲突。
  • 路径引用潜在问题VUE_TEMPLATE_PATHREACT_TEMPLATE_PATH 被解析为绝对路径并格式化进指令。如果这些路径在系统间不一致或包含特殊字符,可能引发问题。且指令中关于模板路径不存在的处理(第29条“Just continue the work”)过于宽松,可能导致后续步骤因缺少模板而失败。
  • 代码重复与维护性WRITE_CODE_PROMPT 模板字符串虽然清晰,但如果需要调整输出格式或增加新的上下文变量,需要直接修改字符串,不利于维护和复用。

优化建议

  • 重构指令生成机制
    1. EXTRA_INSTRUCTION 定义为一个模板字符串(例如使用 string.Template 或 Jinja2 模板),将真正的动态变量(如 project_name, workspace, timestamp)留待每次任务执行时根据上下文注入。移除无效的 .format() 调用。
    2. CURRENT_STATE 的格式化整合到指令组装逻辑中,确保状态信息能正确反映实时环境。
  • 澄清和简化操作指令
    1. 合并并重写第11条和第11.1条,明确表达核心约束:“在一次行动响应中,至多规划一个文件编辑操作(使用 Editor.insert_content_at_lineEditor.edit_file_by_replace)。如果需要对同一文件进行多处修改,应将它们规划在连续的多个响应中依次执行。”
    2. 重构第24条和第25条。建议将第25条作为第24条优先级中“Vite, React, MUI and Tailwind CSS”或“未指定”情况下的 具体实施细则。在指令中明确说明:“若根据优先级选定或默认使用 Vite/React/Vue 等技术栈,则必须遵循以下详细步骤(25.1-25.5)”。
  • 确保时间戳唯一性:移除 EXTRA_INSTRUCTION 中静态的 {timestamp} 占位符。应在每次创建任务或代理初始化时,动态生成一个时间戳并注入到最终发送给代理的完整指令中。
  • 增强路径安全性与错误处理
    1. 在将模板路径注入指令前,增加路径存在性检查,并给出更明确的警告或备选方案,而不是简单地“继续工作”。
    2. 考虑对路径进行字符串转义,防止路径中的特殊字符破坏指令结构。
  • 提升提示模板可维护性:将 WRITE_CODE_PROMPT 等提示模板移出代码文件,放入独立的配置文件或模板文件中(如 YAML, JSON)。这样可以在不修改代码的情况下调整提示内容,也便于进行多语言支持或 A/B 测试。
  • 引入配置类或工厂模式:考虑创建一个 InstructionConfig 类或使用工厂函数来集中管理所有指令模板的加载、变量替换和组装。这可以提高代码的模块化程度和可测试性。

其它

设计目标与约束

本代码模块的核心设计目标是构建一个用于指导AI代理(特别是“工程师”角色)进行自动化编程任务的指令系统。它通过整合角色基础指令、特定工具使用规范、项目操作流程以及代码编写原则,形成一个结构化的、可执行的行动指南。主要约束包括:必须与特定的工具集(如Editor, Terminal, Browser)兼容;指令必须清晰、无歧义,以避免AI代理产生循环错误或无效操作;必须支持多种前端技术栈(React/Vue)的初始化流程;必须强制遵守既定的系统设计或项目排期文档。

错误处理与异常设计

代码本身不包含运行时错误处理逻辑,因为它主要定义的是提示词(Prompt)字符串。其“错误处理”体现在对AI代理行为的预防性指导上:

  1. 操作失败重试与规避:明确指示代理观察前序操作结果,避免触发重复错误(如avoid triggering repeated errors)。当编辑命令失败时,建议扩大代码修改范围或改用重写整个文件的方法(Engineer2.write_new_code)。
  2. 语法与格式错误预防:通过强调PEP8标准、缩进重要性以及在编辑后验证更改,来预防代码语法和格式错误。
  3. 流程异常处理:定义了当仓库不存在时的处理流程(下载并进入),以及当模板路径不存在时的应对策略(Just continue the work),确保了主流程的鲁棒性。
  4. 工具使用异常预防:规定了工具使用的先决条件(如使用Editor编辑前必须先open_file)和限制(如每轮响应中特定编辑命令只能使用一次),以防止工具调用层面的异常。

数据流与状态机

本模块定义了AI代理心智模型中的数据流和隐式状态机:

  1. 输入数据流
    • 静态配置REACT_TEMPLATE_PATH, VUE_TEMPLATE_PATH,用于模板路径解析。
    • 动态上下文:通过CURRENT_STATE模板注入current_directoryeditor_open_file,反映工作环境实时状态。
    • 任务参数:通过WRITE_CODE_PROMPT模板注入user_requirement, plan_status, file_path等,提供具体编码任务上下文。
  2. 内部状态转换(代理行为逻辑)
    • 初始状态:接收用户需求。若提供issue链接,则必须转换到“浏览issue”状态。
    • 仓库就绪状态:检查并确保目标仓库存在于工作路径。若不存在,则转换到“下载仓库”子流程,完成后进入该仓库目录。此状态为后续所有操作的稳定态,代理不应离开此目录。
    • 文件操作状态:围绕Editor工具进行。状态包括:文件未打开 -> 打开文件 -> 读取/定位(goto_line) -> 编辑(insert/replace) -> 验证。指令明确禁止在单次响应中进行多个可能改变行号的编辑操作,这强制了状态的串行推进。
    • 项目创建状态:当需要创建前端项目时,遵循一个严格的子状态机:创建目录 -> 复制模板 -> 进入目录 -> 读取模板文件 -> 规划改写 -> 执行改写 -> 构建部署
    • 规划与执行状态:代理在“制定计划”和“执行任务”间切换。指令要求制定计划时列出所有文件,执行时一次只读写一个文件,并将同一文件上的多个操作合并,这定义了从宏观规划到微观执行的层次化状态转移。
  3. 输出数据流:最终输出是符合WRITE_CODE_PROMPT格式要求的、完整的源代码文件内容。整个指令系统的目的是引导AI代理产生此输出。

外部依赖与接口契约

  1. 外部依赖
    • metagpt.const:依赖REACT_TEMPLATE_PATHVUE_TEMPLATE_PATH常量来获取预置模板的绝对路径。
    • metagpt.prompts.di.role_zero:依赖ROLE_INSTRUCTION作为基础角色指令。
    • time:用于生成时间戳,确保项目文件夹名称唯一。
  2. 接口契约(对AI代理及工具集的约定)
    • 工具接口:代码中提及了Terminal.run_command, Browser, Editor(包含open_file, goto_line, read, edit_file_by_replace, insert_content_at_line等方法)、Engineer2.write_new_codeImageGetter.get_image等工具。指令文本构成了使用这些工具的“契约”,规定了调用条件、参数注意事项(如路径是绝对还是相对)和后续处理。
    • 环境变量契约:假设存在{{workspace}}{{project_name}}等变量可在指令中被替换,这依赖于外层框架提供这些上下文。
    • 协议契约WRITE_CODE_SYSTEM_PROMPTWRITE_CODE_PROMPT定义了一个严格的交互协议。AI代理必须遵循该协议接收输入(用户需求、计划状态等)并产生输出(一个且仅一个代码块)。WRITE_CODE_SYSTEM_PROMPT进一步规定了代码质量契约(如Google风格、无TODO)。

安全与合规考虑

  1. 目录隔离:指令强制要求所有操作在特定的项目目录({{project_name}}_{timestamp})或下载的仓库目录内进行,防止AI代理意外操作或破坏系统其他文件,实现了操作沙盒化。
  2. 命令执行限制:虽然允许执行终端命令,但通过“必须在仓库目录内操作”的约束,间接限制了命令的执行范围。然而,对于cp, mkdir, pnpm install等命令的使用仍需底层执行环境进行安全控制(如容器化)。
  3. 依赖管理:使用pnpm install安装依赖,依赖源的安全性由项目配置和底层环境保障。
  4. 内容安全:指令未涉及对生成代码内容的审查(如恶意代码、许可证合规)。这部分安全依赖于基础AI模型的安全对齐策略以及后续的人工或自动化审计流程。

配置与可扩展性

  1. 模板配置:通过REACT_TEMPLATE_PATHVUE_TEMPLATE_PATH常量,可以灵活配置不同技术栈的启动模板路径,支持前端生态的扩展。
  2. 指令模块化:基础指令(ROLE_INSTRUCTION)与额外指令(EXTRA_INSTRUCTION)分离,允许在不改变核心角色定义的情况下,调整具体任务的行为细则。
  3. 提示词模板化WRITE_CODE_PROMPTCURRENT_STATE采用格式化字符串,使得任务描述、状态信息等动态内容可以方便地注入,适应不同的编码任务场景。
  4. 技术栈优先级规则EXTRA_INSTRUCTION第24-25条定义了一个明确的技术栈选择优先级链条(系统设计指定 > Vite/React/Vue/MUI/Tailwind CSS > 原生HTML)。这个规则本身是硬编码的,但通过修改此规则文本可以调整技术选型策略。