shinka-backup / eval_agent /design_draft /openhands_custom_prompt_examples.py
JustinTX's picture
Add files using upload-large-folder tool
3f6526a verified
"""
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 = """
<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),
],
# 注入自定义变量到 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.
<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 %}
"""
# 将自定义 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")