""" OpenHands Agent - 自定义 System Prompt 示例 本文件展示了在使用 OpenHands SDK 时如何自定义 Agent 的 system prompt。 主要有三种方法: 1. 使用自定义 prompt 文件 2. 使用 system_prompt_kwargs 注入变量 3. 组合使用不同的内置 prompt 模板 """ import os from pathlib import Path from openhands.sdk import LLM, Agent, Conversation, Tool from openhands.tools.file_editor import FileEditorTool from openhands.tools.task_tracker import TaskTrackerTool from openhands.tools.terminal import TerminalTool # ============================================================================ # 方法 1: 使用自定义 Jinja2 模板文件 # ============================================================================ def example_custom_prompt_file(): """ 通过指定 system_prompt_filename 参数使用自定义的 prompt 文件。 适用场景: - 需要完全自定义 agent 的行为 - 想要为特定任务创建专门的 prompt """ llm = LLM( model=os.getenv("LLM_MODEL", "vertex_ai/gemini-2.5-flash"), api_key=os.getenv("LLM_API_KEY"), base_url=os.getenv("LLM_BASE_URL", None), ) # 创建自定义 prompt 文件(见下方的 create_custom_prompt_file 函数) custom_prompt_path = Path(__file__).parent / "custom_system_prompt.j2" agent = Agent( llm=llm, tools=[ Tool(name=TerminalTool.name), Tool(name=FileEditorTool.name), Tool(name=TaskTrackerTool.name), ], # 指定自定义的 prompt 文件名(需要在 prompts 目录下,或者使用绝对路径) system_prompt_filename=str(custom_prompt_path), ) cwd = os.getcwd() conversation = Conversation(agent=agent, workspace=cwd) conversation.send_message("Write 3 facts about the current project into FACTS.txt.") conversation.run() # ============================================================================ # 方法 2: 使用内置模板 + system_prompt_kwargs 注入自定义内容 # ============================================================================ def example_with_kwargs(): """ 通过 system_prompt_kwargs 向默认模板注入额外的自定义指令。 适用场景: - 想要保留默认 prompt 的大部分内容 - 只需要添加一些特定的指令或约束 - 需要动态生成部分 prompt 内容 """ llm = LLM( model=os.getenv("LLM_MODEL", "vertex_ai/gemini-2.5-flash"), api_key=os.getenv("LLM_API_KEY"), base_url=os.getenv("LLM_BASE_URL", None), ) # 准备要注入到 prompt 模板中的自定义变量 custom_instructions = """ * 你是一个专门用于代码演化的 AI Agent * 在修改代码时,始终保持向后兼容性 * 优先考虑代码的可读性和可维护性 * 每次修改后都要运行测试确保功能正常 * 生成的代码应该遵循 PEP 8 规范(Python) * 记录所有重要的设计决策 """ agent = Agent( llm=llm, tools=[ Tool(name=TerminalTool.name), Tool(name=FileEditorTool.name), Tool(name=TaskTrackerTool.name), ], # 注入自定义变量到 prompt 模板中 system_prompt_kwargs={ "custom_instructions": custom_instructions, "project_name": "ShinkaEvolve", "task_type": "code_evolution", }, ) cwd = os.getcwd() conversation = Conversation(agent=agent, workspace=cwd) conversation.send_message("Analyze the codebase structure and suggest improvements.") conversation.run() # ============================================================================ # 方法 3: 使用不同的内置 prompt 模板 # ============================================================================ def example_builtin_templates(): """ OpenHands 提供了多个内置的 prompt 模板,可以根据任务类型选择。 可用的内置模板: - system_prompt.j2 (默认) - system_prompt_interactive.j2 (交互式任务) - system_prompt_planning.j2 (需要规划的复杂任务) - system_prompt_long_horizon.j2 (长期任务) - system_prompt_tech_philosophy.j2 (技术哲学导向) """ llm = LLM( model=os.getenv("LLM_MODEL", "vertex_ai/gemini-2.5-flash"), api_key=os.getenv("LLM_API_KEY"), base_url=os.getenv("LLM_BASE_URL", None), ) # 使用规划导向的 prompt 模板 agent = Agent( llm=llm, tools=[ Tool(name=TerminalTool.name), Tool(name=FileEditorTool.name), Tool(name=TaskTrackerTool.name), ], system_prompt_filename="system_prompt_planning.j2", # 使用规划模板 ) cwd = os.getcwd() conversation = Conversation(agent=agent, workspace=cwd) conversation.send_message("Create a comprehensive test suite for the project.") conversation.run() # ============================================================================ # 方法 4: 完全自定义 - 创建针对代码演化任务的 prompt # ============================================================================ def create_custom_evolution_prompt(): """ 创建一个专门用于 ShinkaEvolve 代码演化任务的自定义 prompt 文件。 """ custom_prompt_content = """You are an AI agent specialized in evolutionary code optimization for the ShinkaEvolve framework. * Your primary role is to analyze, evolve, and improve Python code through iterative mutations * You should focus on optimizing performance metrics while maintaining code correctness * You must be creative in exploring the solution space while being rigorous in validation * Always preserve the code structure marked by EVOLVE-BLOCK-START and EVOLVE-BLOCK-END * Focus mutations on the algorithmic core, not on boilerplate code * Ensure all changes are semantically valid and syntactically correct * Test thoroughly before proposing changes * Document the rationale behind significant changes * Consider multiple approaches and select the most promising one * Balance exploration (trying new ideas) with exploitation (refining good solutions) * Remember that your changes will be evaluated by an external evaluation script * The evaluation metric is typically a performance score (higher is better) * Consider edge cases and potential failure modes * Ensure backward compatibility unless explicitly instructed otherwise * Use `AGENTS.md` under the repository root as your persistent memory * Record successful mutation strategies for future reference * Document patterns that led to performance improvements * Keep track of approaches that didn't work to avoid repeating them * Each evaluation run has a cost, so think carefully before proposing changes * Batch multiple related changes together when possible * Use incremental improvements rather than complete rewrites unless necessary * Work directly with the files in the EVOLVE-BLOCK sections * Do not create multiple versions of files * Preserve the original file structure and imports * Ensure all dependencies are properly maintained * Write clean, readable code with minimal but meaningful comments * Follow Python best practices and PEP 8 style guide * Optimize for both performance and maintainability * Use appropriate data structures and algorithms * Before proposing changes, verify they will work correctly * Consider the expected input/output format * Think about edge cases and boundary conditions * Ensure the modified code integrates properly with the evaluation framework 1. UNDERSTAND: Read and comprehend the current implementation 2. ANALYZE: Identify potential areas for improvement 3. HYPOTHESIZE: Formulate ideas for optimization 4. IMPLEMENT: Make focused, incremental changes 5. VALIDATE: Ensure correctness before submission 6. DOCUMENT: Explain the rationale for significant changes * Algorithm substitution: Replace algorithms with more efficient variants * Parameter tuning: Adjust numerical parameters for better performance * Code refactoring: Improve structure without changing functionality * Feature engineering: Add or modify features in the solution * Heuristic improvements: Enhance problem-specific heuristics * Hybrid approaches: Combine multiple strategies * Don't be afraid to try unconventional approaches * Consider insights from related domains * Look for patterns in successful solutions * Be willing to make bold changes if data supports them {% if custom_instructions %} {{ custom_instructions }} {% endif %} {% if project_context %} Project: {{ project_name }} Task Type: {{ task_type }} {{ project_context }} {% endif %} """ # 将自定义 prompt 保存到文件 custom_prompt_path = Path(__file__).parent / "custom_evolution_prompt.j2" with open(custom_prompt_path, 'w') as f: f.write(custom_prompt_content) print(f"Created custom evolution prompt at: {custom_prompt_path}") return custom_prompt_path def example_with_custom_evolution_prompt(): """ 使用专门为代码演化任务创建的自定义 prompt。 """ # 首先创建自定义 prompt 文件 custom_prompt_path = create_custom_evolution_prompt() llm = LLM( model=os.getenv("LLM_MODEL", "vertex_ai/gemini-2.5-flash"), api_key=os.getenv("LLM_API_KEY"), base_url=os.getenv("LLM_BASE_URL", None), ) agent = Agent( llm=llm, tools=[ Tool(name=TerminalTool.name), Tool(name=FileEditorTool.name), Tool(name=TaskTrackerTool.name), ], system_prompt_filename=str(custom_prompt_path), system_prompt_kwargs={ "custom_instructions": "Focus on optimizing circle packing algorithms", "project_name": "ShinkaEvolve", "task_type": "Geometric Optimization", "project_context": "We are evolving algorithms for circle packing problems", }, ) cwd = os.getcwd() conversation = Conversation(agent=agent, workspace=cwd) conversation.send_message( "Analyze the initial.py file and suggest optimizations for the circle packing algorithm." ) conversation.run() # ============================================================================ # 比较不同方法的适用场景 # ============================================================================ def print_comparison(): """ 打印不同自定义方法的对比和使用建议。 """ comparison = """ ╔════════════════════════════════════════════════════════════════════════╗ ║ OpenHands Agent System Prompt 自定义方法对比 ║ ╚════════════════════════════════════════════════════════════════════════╝ 方法 1: 使用内置模板(最简单) ──────────────────────────────────────── Agent( llm=llm, tools=tools, # 使用默认 prompt,无需额外配置 ) 适用场景:通用任务,不需要特殊定制 优点:简单快速,经过良好测试 缺点:无法精细控制行为 方法 2: 使用不同的内置模板(简单) ──────────────────────────────────────── Agent( llm=llm, tools=tools, system_prompt_filename="system_prompt_planning.j2" ) 可用模板: - system_prompt.j2 # 默认,通用任务 - system_prompt_interactive.j2 # 交互式任务 - system_prompt_planning.j2 # 需要规划的复杂任务 - system_prompt_long_horizon.j2 # 长期任务 - system_prompt_tech_philosophy.j2 # 技术哲学导向 适用场景:任务类型与内置模板匹配 优点:无需自己写 prompt,质量有保证 缺点:选择有限,可能不完全符合需求 方法 3: 注入自定义变量(推荐) ──────────────────────────────────────── Agent( llm=llm, tools=tools, system_prompt_kwargs={ "custom_instructions": "你的额外指令", "project_name": "项目名", "task_type": "任务类型", } ) 注意:需要修改模板文件来使用这些变量,或者创建支持这些变量的自定义模板 适用场景:需要在标准模板基础上添加特定指令 优点:灵活,可以动态注入内容 缺点:需要了解模板变量的使用方式 方法 4: 完全自定义 Jinja2 模板(最灵活) ──────────────────────────────────────── Agent( llm=llm, tools=tools, system_prompt_filename="path/to/custom_prompt.j2", system_prompt_kwargs={...} # 可选,用于模板变量 ) 适用场景: - 需要完全控制 agent 行为 - 特定领域的专业任务(如代码演化) - 需要复杂的条件逻辑和指令 优点:最大化灵活性和控制力 缺点:需要自己维护和测试 prompt ╔════════════════════════════════════════════════════════════════════════╗ ║ 针对 ShinkaEvolve 的建议 ║ ╚════════════════════════════════════════════════════════════════════════╝ 对于代码演化任务,推荐使用方法 4: 1. 创建专门的演化 prompt 模板 - 强调代码质量和正确性 - 明确演化策略和约束 - 包含评估意识 2. 使用 system_prompt_kwargs 传递任务特定信息 - 当前演化目标 - 性能指标定义 - 任务特定约束 3. 保持 prompt 的可维护性 - 使用清晰的章节划分 - 文档化关键指令 - 定期根据实验结果优化 示例代码见 example_with_custom_evolution_prompt() """ print(comparison) # ============================================================================ # 主程序 # ============================================================================ if __name__ == "__main__": print("\n" + "="*80) print("OpenHands Agent System Prompt 自定义示例") print("="*80 + "\n") # 打印对比说明 print_comparison() print("\n" + "="*80) print("运行示例(取消注释以运行)") print("="*80 + "\n") # 取消注释以运行不同的示例 # example_with_kwargs() # example_builtin_templates() # example_with_custom_evolution_prompt() print("\n提示:修改上面的代码取消注释来运行不同的示例\n")