动手实践OpenHands系列学习笔记4:AI代理提示工程

发布于:2025-07-06 ⋅ 阅读:(20) ⋅ 点赞:(0)

笔记4:AI代理提示工程

一、引言

提示工程(Prompt Engineering)是AI代理系统的关键技术,直接影响模型的执行质量和效率。本笔记将探讨提示工程的核心原理,以及如何优化OpenHands中的提示模板,使AI代理能够更准确地完成复杂任务。

二、提示工程基础理论

2.1 提示工程核心概念

  • 提示结构: 指令、上下文、示例和任务描述的组织方式
  • 系统提示: 定义AI代理的角色、行为规范和能力边界
  • 任务分解: 将复杂任务拆分为子任务逐步执行
  • 上下文窗口管理: 有效利用模型有限的上下文长度
  • 提示模板化: 设计可重用的提示结构以保持一致性

2.2 提示工程关键技术

  • 思维链(Chain of Thought): 引导模型展示推理过程
  • 思维树(Tree of Thoughts): 探索多条可能的推理路径
  • 提示策略(Prompting Strategy): 根据任务类型选择恰当的提示方式
  • 少样本学习(Few-shot Learning): 提供示例帮助模型理解任务期望
  • 自反思(Self-reflection): 引导模型评估自身输出质量

2.3 代理系统的提示特点

  • 工具使用提示: 指导模型如何使用可用工具
  • 反馈循环: 设计提示以支持模型利用执行结果调整
  • 多轮任务执行: 维护执行状态和历史
  • 错误处理: 指导模型识别并修复错误
  • 自主性与限制: 平衡模型的创造性和规则遵循

三、OpenHands提示系统分析

从README_CN.md中,我们可以推断OpenHands设计了一个复杂的提示系统:

  1. 多模型支持: 提示需适应不同LLM特性(尤其是Claude Sonnet 4)
  2. 软件开发焦点: 提示针对软件开发任务优化
  3. 工具使用能力: 提示强调使用正确工具完成任务
  4. 自主性: 代理能"完成人类开发者能做的任何事情"

3.1 OpenHands的提示层次结构

推测的OpenHands提示架构:

  • 基础系统提示: 定义代理身份、能力和行为规范
  • 任务特定提示: 针对不同开发任务的特化提示
  • 工具使用提示: 描述可用工具及其使用方法
  • 上下文管理提示: 维护对话历史和任务进度
  • 错误处理提示: 指导如何处理异常情况

四、实践项目:优化AI代理提示模板

4.1 基础系统提示设计

// prompt-templates.js
const BASE_SYSTEM_PROMPT = `
你是OpenHands AI开发助手,一个专业的软件开发代理。你能够编写代码、运行命令、分析错误并提供解决方案。请遵循以下原则:

1. 专注于任务:直接解决用户提出的问题,避免不必要的解释。
2. 代码优先:优先提供实际可运行的代码而不是概念性描述。
3. 工具使用:有效利用可用工具完成任务,包括编辑文件、运行命令、搜索代码等。
4. 自主性:在必要时主动采取后续步骤完成整体任务,无需每一步都请求用户确认。
5. 错误处理:遇到错误时,分析原因并尝试修复,而不是简单放弃。

你可以访问以下工具:
{{TOOLS_DESCRIPTION}}

始终使用最佳实践编写高质量代码,确保代码安全、可维护且符合现代开发标准。
`;

// 根据不同任务类型的专用提示
const TASK_SPECIFIC_PROMPTS = {
  CODE_GENERATION: `
我需要你生成代码来实现以下功能:{{TASK_DESCRIPTION}}
请使用{{LANGUAGE}}编写,并遵循以下约束条件:{{CONSTRAINTS}}
代码应当包含适当的错误处理和文档。
  `,
  
  BUG_FIXING: `
以下代码存在问题:{{PROBLEMATIC_CODE}}
错误信息:{{ERROR_MESSAGE}}
请分析问题并提供修复后的代码。
  `,
  
  CODE_REVIEW: `
请审查以下代码:{{CODE_TO_REVIEW}}
关注安全性、性能、可读性和最佳实践。提供具体的改进建议。
  `
};

// 工具使用提示模板
function generateToolsPrompt(availableTools) {
  const toolDescriptions = availableTools.map(tool => 
    `- ${tool.name}: ${tool.description}\n  用法: ${tool.usage}`
  ).join('\n\n');
  
  return toolDescriptions;
}

// 导出提示模板函数
module.exports = {
  generateSystemPrompt: function(taskType, toolsList, customData = {}) {
    const toolsDescription = generateToolsPrompt(toolsList);
    let systemPrompt = BASE_SYSTEM_PROMPT.replace('{{TOOLS_DESCRIPTION}}', toolsDescription);
    
    if (taskType && TASK_SPECIFIC_PROMPTS[taskType]) {
      let taskPrompt = TASK_SPECIFIC_PROMPTS[taskType];
      
      // 替换任务特定的占位符
      Object.keys(customData).forEach(key => {
        const placeholder = `{{${key}}}`;
        if (taskPrompt.includes(placeholder)) {
          taskPrompt = taskPrompt.replace(placeholder, customData[key]);
        }
      });
      
      systemPrompt += '\n\n' + taskPrompt;
    }
    
    return systemPrompt;
  }
};

4.2 实现思维链提示增强器

// cot-enhancer.js
class ChainOfThoughtEnhancer {
  constructor(options = {}) {
    this.verbose = options.verbose || false;
    this.stepByStep = options.stepByStep || true;
    this.maxSteps = options.maxSteps || 5;
  }
  
  // 为用户提示添加思维链指令
  enhancePrompt(userPrompt, taskContext = {}) {
    if (!this.stepByStep) return userPrompt;
    
    const enhancedPrompt = `${userPrompt}\n\n请使用以下步骤解决这个问题:
1. 分析任务需求,确定需要完成的具体目标
2. 制定解决方案的计划,确定需要使用的工具和步骤
3. 按照计划执行每一步,使用适当的工具
4. 检查结果,确保满足需求
5. 如有必要,进行调整或优化

在每一步之前,请简要说明你的思考过程。`;
    
    return enhancedPrompt;
  }
  
  // 分析并增强模型响应
  analyzeAndEnhanceResponse(response) {
    if (!this.verbose || !response) return response;
    
    // 简单的启发式算法,检查响应是否包含足够的推理过程
    const hasReasoningMarkers = [
      '首先', '接下来', '然后', '因为', '所以', '考虑到', 
      '分析', '步骤', '计划', '思考', '我的思路是'
    ].some(marker => response.includes(marker));
    
    if (!hasReasoningMarkers) {
      // 如果缺少推理标记,添加提示让模型在下一次交互中提供更详细的推理
      return {
        originalResponse: response,
        needMoreReasoning: true,
        followUpPrompt: "请详细解释你的思考过程,包括你为什么选择这种方法以及考虑了哪些替代方案。"
      };
    }
    
    return {
      originalResponse: response,
      needMoreReasoning: false
    };
  }
  
  // 生成多步骤推理提示
  generateStepwisePrompt(task, context, tools) {
    return `任务: ${task}
可用工具: ${tools.map(t => t.name).join(', ')}
相关上下文: ${JSON.stringify(context)}

请按照以下步骤解决问题,在每一步明确说明你的思考过程:

1. 任务分析:明确定义问题和目标
2. 思考方法:列出可能的解决方案
3. 工具选择:确定要使用的最佳工具
4. 执行计划:详细说明执行步骤
5. 结果验证:确认解决方案是否有效

对于每一步,先解释你的思考,然后执行必要的操作。`;
  }
}

module.exports = ChainOfThoughtEnhancer;

4.3 实现提示模板管理器

// prompt-manager.js
const fs = require('fs').promises;
const path = require('path');
const promptTemplates = require('./prompt-templates');
const ChainOfThoughtEnhancer = require('./cot-enhancer');

class PromptManager {
  constructor(config = {}) {
    this.templatesDir = config.templatesDir || path.join(process.cwd(), 'templates');
    this.customTemplates = {};
    this.cotEnhancer = new ChainOfThoughtEnhancer(config.cotOptions || {});
    this.defaultTools = [];
  }
  
  // 初始化加载模板
  async initialize() {
    try {
      // 创建模板目录(如果不存在)
      await fs.mkdir(this.templatesDir, { recursive: true });
      
      // 尝试加载自定义模板
      const files = await fs.readdir(this.templatesDir);
      for (const file of files) {
        if (file.endsWith('.json')) {
          const content = await fs.readFile(path.join(this.templatesDir, file), 'utf8');
          const template = JSON.parse(content);
          this.customTemplates[template.id] = template;
        }
      }
      
      console.log(`Loaded ${Object.keys(this.customTemplates).length} custom templates`);
    } catch (error) {
      console.warn('Error initializing prompt manager:', error.message);
    }
  }
  
  // 设置默认工具列表
  setDefaultTools(tools) {
    this.defaultTools = tools;
  }
  
  // 保存自定义模板
  async saveCustomTemplate(template) {
    if (!template.id || !template.content) {
      throw new Error('Template must have id and content properties');
    }
    
    this.customTemplates[template.id] = template;
    
    await fs.writeFile(
      path.join(this.templatesDir, `${template.id}.json`),
      JSON.stringify(template, null, 2),
      'utf8'
    );
    
    return template.id;
  }
  
  // 生成系统提示
  generateSystemPrompt(taskType, tools = this.defaultTools, customData = {}) {
    return promptTemplates.generateSystemPrompt(taskType, tools, customData);
  }
  
  // 获取自定义模板
  getCustomTemplate(templateId) {
    return this.customTemplates[templateId]?.content;
  }
  
  // 增强用户提示
  enhanceUserPrompt(userPrompt, taskContext = {}) {
    return this.cotEnhancer.enhancePrompt(userPrompt, taskContext);
  }
  
  // 生成代码相关任务的提示
  generateCodeTaskPrompt(taskDescription, language, constraints = []) {
    return this.generateSystemPrompt('CODE_GENERATION', this.defaultTools, {
      TASK_DESCRIPTION: taskDescription,
      LANGUAGE: language,
      CONSTRAINTS: constraints.join('\n- ')
    });
  }
  
  // 生成Bug修复任务的提示
  generateBugFixPrompt(code, errorMessage) {
    return this.generateSystemPrompt('BUG_FIXING', this.defaultTools, {
      PROBLEMATIC_CODE: code,
      ERROR_MESSAGE: errorMessage
    });
  }
  
  // 生成代码审查任务的提示
  generateCodeReviewPrompt(code) {
    return this.generateSystemPrompt('CODE_REVIEW', this.defaultTools, {
      CODE_TO_REVIEW: code
    });
  }
}

module.exports = PromptManager;

4.4 应用示例:构建提示优化服务

// prompt-service.js
const express = require('express');
const bodyParser = require('body-parser');
const PromptManager = require('./prompt-manager');

const app = express();
app.use(bodyParser.json());

// 初始化提示管理器
const promptManager = new PromptManager();

// 定义默认工具列表
const defaultTools = [
  {
    name: 'code_search',
    description: '在代码库中搜索相关代码片段',
    usage: 'code_search(query: string, directories?: string[])'
  },
  {
    name: 'run_command',
    description: '在终端中运行命令',
    usage: 'run_command(command: string)'
  },
  {
    name: 'edit_file',
    description: '编辑文件内容',
    usage: 'edit_file(file_path: string, changes: { type: "insert"|"replace"|"delete", line: number, content?: string }[])'
  },
  {
    name: 'browse_web',
    description: '浏览网页获取信息',
    usage: 'browse_web(url: string)'
  }
];

// 启动服务前初始化
async function startServer() {
  await promptManager.initialize();
  promptManager.setDefaultTools(defaultTools);
  
  // 生成任务提示
  app.post('/api/prompts/generate', (req, res) => {
    try {
      const { taskType, customData } = req.body;
      
      if (!taskType) {
        return res.status(400).json({ error: 'taskType is required' });
      }
      
      const systemPrompt = promptManager.generateSystemPrompt(
        taskType, 
        defaultTools, 
        customData || {}
      );
      
      res.json({ systemPrompt });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
  
  // 增强用户提示
  app.post('/api/prompts/enhance', (req, res) => {
    try {
      const { userPrompt, taskContext } = req.body;
      
      if (!userPrompt) {
        return res.status(400).json({ error: 'userPrompt is required' });
      }
      
      const enhancedPrompt = promptManager.enhanceUserPrompt(
        userPrompt, 
        taskContext || {}
      );
      
      res.json({ enhancedPrompt });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
  
  // 创建自定义模板
  app.post('/api/prompts/templates', async (req, res) => {
    try {
      const { id, name, content, description } = req.body;
      
      if (!id || !content) {
        return res.status(400).json({ error: 'id and content are required' });
      }
      
      const templateId = await promptManager.saveCustomTemplate({
        id,
        name: name || id,
        content,
        description: description || '',
        createdAt: new Date().toISOString()
      });
      
      res.json({ templateId });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
  
  // 获取模板列表
  app.get('/api/prompts/templates', (req, res) => {
    const templates = Object.values(promptManager.customTemplates).map(t => ({
      id: t.id,
      name: t.name,
      description: t.description,
      createdAt: t.createdAt
    }));
    
    res.json({ templates });
  });
  
  // 获取特定模板
  app.get('/api/prompts/templates/:id', (req, res) => {
    const template = promptManager.customTemplates[req.params.id];
    
    if (!template) {
      return res.status(404).json({ error: 'Template not found' });
    }
    
    res.json(template);
  });
  
  // 启动服务
  const PORT = process.env.PORT || 3001;
  app.listen(PORT, () => {
    console.log(`Prompt service running on port ${PORT}`);
  });
}

startServer().catch(error => {
  console.error('Failed to start server:', error);
  process.exit(1);
});

4.5 提示模板实例

代码生成提示模板示例:

{
  "id": "react_component",
  "name": "React组件生成",
  "description": "生成符合最佳实践的React组件",
  "content": "请为我创建一个名为{{COMPONENT_NAME}}的React组件,具有以下功能:\n\n{{COMPONENT_DESCRIPTION}}\n\n请确保组件符合以下要求:\n- 使用函数式组件和React Hooks\n- 包含适当的PropTypes类型检查\n- 实现必要的错误处理\n- 代码简洁易读,带有适当的注释\n- 遵循React最佳实践\n\n组件应接受以下props:\n{{PROPS_LIST}}\n\n如果需要,请添加自定义hooks或辅助函数。",
  "createdAt": "2023-09-15T12:00:00Z"
}

Bug修复提示模板示例:

{
  "id": "database_error",
  "name": "数据库错误修复",
  "description": "修复数据库连接和查询相关错误",
  "content": "我的应用程序出现以下数据库错误:\n\n```\n{{ERROR_MESSAGE}}\n```\n\n相关代码:\n\n```{{LANGUAGE}}\n{{CODE_SNIPPET}}\n```\n\n使用的数据库类型是:{{DATABASE_TYPE}}\n\n请分析这个错误,解释可能的原因,并提供修复方案。修复时请考虑:\n1. 连接配置是否正确\n2. SQL语法是否有误\n3. 事务处理是否适当\n4. 是否有并发问题\n5. 异常处理是否完善",
  "createdAt": "2023-09-16T14:30:00Z"
}

五、提示工程最佳实践

5.1 针对代码生成的提示优化

  1. 明确指定语言和框架版本:

    使用Python 3.10编写,仅使用标准库和pandas 2.0+
    
  2. 提供文件结构上下文:

    该代码将位于项目的src/utils/目录中,需要导入src/models/中的模型
    
  3. 指定代码风格与约束:

    遵循PEP 8规范,使用类型提示,函数不超过30行
    
  4. 提供输入/输出示例:

    输入示例:{"name": "test", "values": [1, 2, 3]}
    期望输出:{"processed_name": "TEST", "sum": 6}
    

5.2 AI代理系统提示技巧

  1. 明确权限边界:

    你可以修改src目录下的文件,但不能修改tests目录或配置文件
    
  2. 设定决策标准:

    在做决定时,优先考虑: 1)代码安全性 2)性能 3)可读性
    
  3. 定义行动计划格式:

    在执行任务前,请先列出计划的步骤,然后依次执行
    
  4. 设置反馈循环:

    每完成一个主要步骤后,评估结果并决定是否需要调整计划
    

5.3 工具使用提示模式

  1. 工具选择决策树:

    - 如果需要查找代码,使用code_search工具
    - 如果需要修改文件,使用edit_file工具
    - 如果需要运行命令,使用run_command工具
    - 如果以上工具都不适用,说明原因并请求指导
    
  2. 工具使用示例:

    要搜索包含"database connection"的代码:
    code_search("database connection", ["src/db"])
    
    要运行测试:
    run_command("npm test")
    
  3. 工具组合模式:

    先搜索相关代码,然后编辑文件,最后运行测试验证更改
    

六、总结与思考

  1. 提示工程的关键价值:

    • 提升模型响应质量和相关性
    • 增强AI代理的自主性和能力
    • 优化用户与AI代理的交互体验
    • 降低模型幻觉和错误率
  2. OpenHands提示系统的特点:

    • 专注软件开发场景
    • 工具使用与自主性平衡
    • 安全性与功能性兼顾
    • 灵活适应不同LLM特性
  3. 提示工程的未来发展:

    • 提示自动优化与自适应
    • 多模态提示工程
    • 个性化提示定制
    • 提示评估与质量度量

七、下一步学习方向

  1. 研究代理系统中的提示自我改进机制
  2. 探索提示压缩技术,在有限上下文窗口中传递更多信息
  3. 测试不同LLM对相同提示的响应差异
  4. 开发提示版本控制和A/B测试框架

八、参考资源

  1. Anthropic Claude提示工程指南
  2. 提示工程最佳实践
  3. Langchain文档-提示模板
  4. Chain-of-Thought Prompting研究论文
  5. OpenHands文档