| """ |
| 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 |
|
|
|
|
| |
| |
| |
| 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), |
| ) |
| |
| |
| 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), |
| ], |
| |
| 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() |
|
|
|
|
| |
| |
| |
| 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), |
| ) |
| |
| |
| custom_instructions = """ |
| <CUSTOM_INSTRUCTIONS> |
| * 你是一个专门用于代码演化的 AI Agent |
| * 在修改代码时,始终保持向后兼容性 |
| * 优先考虑代码的可读性和可维护性 |
| * 每次修改后都要运行测试确保功能正常 |
| * 生成的代码应该遵循 PEP 8 规范(Python) |
| * 记录所有重要的设计决策 |
| </CUSTOM_INSTRUCTIONS> |
| """ |
| |
| agent = Agent( |
| llm=llm, |
| tools=[ |
| Tool(name=TerminalTool.name), |
| Tool(name=FileEditorTool.name), |
| Tool(name=TaskTrackerTool.name), |
| ], |
| |
| 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() |
|
|
|
|
| |
| |
| |
| 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), |
| ) |
| |
| |
| 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() |
|
|
|
|
| |
| |
| |
| def create_custom_evolution_prompt(): |
| """ |
| 创建一个专门用于 ShinkaEvolve 代码演化任务的自定义 prompt 文件。 |
| """ |
| custom_prompt_content = """You are an AI agent specialized in evolutionary code optimization for the ShinkaEvolve framework. |
| |
| <ROLE> |
| * 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 |
| </ROLE> |
| |
| <CODE_EVOLUTION_PRINCIPLES> |
| * 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) |
| </CODE_EVOLUTION_PRINCIPLES> |
| |
| <EVALUATION_AWARENESS> |
| * 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 |
| </EVALUATION_AWARENESS> |
| |
| <MEMORY> |
| * 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 |
| </MEMORY> |
| |
| <EFFICIENCY> |
| * 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 |
| </EFFICIENCY> |
| |
| <FILE_SYSTEM_GUIDELINES> |
| * 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 |
| </FILE_SYSTEM_GUIDELINES> |
| |
| <CODE_QUALITY> |
| * 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 |
| </CODE_QUALITY> |
| |
| <TESTING_AND_VALIDATION> |
| * 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 |
| </TESTING_AND_VALIDATION> |
| |
| <PROBLEM_SOLVING_WORKFLOW> |
| 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 |
| </PROBLEM_SOLVING_WORKFLOW> |
| |
| <MUTATION_STRATEGIES> |
| * 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 |
| </MUTATION_STRATEGIES> |
| |
| <CREATIVITY_AND_EXPLORATION> |
| * 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 |
| </CREATIVITY_AND_EXPLORATION> |
| |
| {% if custom_instructions %} |
| <ADDITIONAL_CUSTOM_INSTRUCTIONS> |
| {{ custom_instructions }} |
| </ADDITIONAL_CUSTOM_INSTRUCTIONS> |
| {% endif %} |
| |
| {% if project_context %} |
| <PROJECT_CONTEXT> |
| Project: {{ project_name }} |
| Task Type: {{ task_type }} |
| {{ project_context }} |
| </PROJECT_CONTEXT> |
| {% endif %} |
| """ |
| |
| |
| 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。 |
| """ |
| |
| 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") |
| |
| |
| |
| |
| |
| |
| print("\n提示:修改上面的代码取消注释来运行不同的示例\n") |
|
|