笔记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设计了一个复杂的提示系统:
- 多模型支持: 提示需适应不同LLM特性(尤其是Claude Sonnet 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 针对代码生成的提示优化
明确指定语言和框架版本:
使用Python 3.10编写,仅使用标准库和pandas 2.0+
提供文件结构上下文:
该代码将位于项目的src/utils/目录中,需要导入src/models/中的模型
指定代码风格与约束:
遵循PEP 8规范,使用类型提示,函数不超过30行
提供输入/输出示例:
输入示例:{"name": "test", "values": [1, 2, 3]} 期望输出:{"processed_name": "TEST", "sum": 6}
5.2 AI代理系统提示技巧
明确权限边界:
你可以修改src目录下的文件,但不能修改tests目录或配置文件
设定决策标准:
在做决定时,优先考虑: 1)代码安全性 2)性能 3)可读性
定义行动计划格式:
在执行任务前,请先列出计划的步骤,然后依次执行
设置反馈循环:
每完成一个主要步骤后,评估结果并决定是否需要调整计划
5.3 工具使用提示模式
工具选择决策树:
- 如果需要查找代码,使用code_search工具 - 如果需要修改文件,使用edit_file工具 - 如果需要运行命令,使用run_command工具 - 如果以上工具都不适用,说明原因并请求指导
工具使用示例:
要搜索包含"database connection"的代码: code_search("database connection", ["src/db"]) 要运行测试: run_command("npm test")
工具组合模式:
先搜索相关代码,然后编辑文件,最后运行测试验证更改
六、总结与思考
提示工程的关键价值:
- 提升模型响应质量和相关性
- 增强AI代理的自主性和能力
- 优化用户与AI代理的交互体验
- 降低模型幻觉和错误率
OpenHands提示系统的特点:
- 专注软件开发场景
- 工具使用与自主性平衡
- 安全性与功能性兼顾
- 灵活适应不同LLM特性
提示工程的未来发展:
- 提示自动优化与自适应
- 多模态提示工程
- 个性化提示定制
- 提示评估与质量度量
七、下一步学习方向
- 研究代理系统中的提示自我改进机制
- 探索提示压缩技术,在有限上下文窗口中传递更多信息
- 测试不同LLM对相同提示的响应差异
- 开发提示版本控制和A/B测试框架