《60天AI学习计划启动 | Day 13: AI Agent 开发 - 自主任务执行》

Day 13: AI Agent 开发 - 自主任务执行

学习目标


核心学习内容

1. AI Agent 概念

什么是 AI Agent?

  • 能感知环境、做出决策、执行行动
  • 自主完成任务
  • 使用工具扩展能力
  • 具备记忆和规划能力

Agent 组成:

感知(Perception)
  ↓
思考(Reasoning)
  ↓
行动(Action)
  ↓
反馈(Feedback)

Agent 类型:

  • ReAct Agent:推理+行动
  • Plan-and-Execute Agent:规划+执行
  • AutoGPT Agent:自主任务执行

2. Agent 架构

核心组件:

  1. LLM:决策大脑
  2. Tools:可用工具
  3. Memory:记忆系统
  4. Planner:任务规划
  5. Executor:执行器

3. 工具调用链

工作流程:

用户目标
  ↓
Agent 分析
  ↓
选择工具
  ↓
执行工具
  ↓
评估结果
  ↓
继续或完成

实践作业

作业1:实现基础 Agent

src/agents/base-agent.js:

import { ChatOpenAI } from '@langchain/openai';
import { DynamicTool } from '@langchain/core/tools';
import { logger } from '../utils/logger.js';

/**
 * 基础 Agent
 */
export class BaseAgent {
  constructor(options = {}) {
    this.llm = new ChatOpenAI({
      modelName: options.model || 'gpt-3.5-turbo',
      temperature: options.temperature || 0.7,
      openAIApiKey: process.env.OPENAI_API_KEY
    });

    this.tools = [];
    this.memory = [];
    this.maxIterations = options.maxIterations || 10;
    this.verbose = options.verbose || false;
  }

  /**
   * 添加工具
   */
  addTool(tool) {
    this.tools.push(tool);
  }

  /**
   * 执行任务
   */
  async execute(goal) {
    logger.info(`Agent 目标: ${goal}`);
    
    let iteration = 0;
    let currentGoal = goal;
    const executionPlan = [];

    while (iteration < this.maxIterations) {
      iteration++;
      
      if (this.verbose) {
        logger.info(`\n=== 迭代 ${iteration} ===`);
      }

      // 1. 分析当前状态
      const analysis = await this.analyze(currentGoal);
      
      if (this.verbose) {
        logger.info(`分析: ${analysis.reasoning}`);
      }

      // 2. 决定下一步行动
      const action = await this.decideAction(analysis, currentGoal);
      
      if (this.verbose) {
        logger.info(`行动: ${action.type} - ${action.description}`);
      }

      // 3. 执行行动
      const result = await this.executeAction(action);
      
      executionPlan.push({
        iteration,
        action,
        result
      });

      // 4. 评估结果
      const evaluation = await this.evaluate(result, currentGoal);
      
      if (this.verbose) {
        logger.info(`结果: ${result}`);
        logger.info(`评估: ${evaluation.status}`);
      }

      // 5. 检查是否完成
      if (evaluation.status === 'completed') {
        logger.info('任务完成!');
        return {
          success: true,
          goal: goal,
          executionPlan: executionPlan,
          finalResult: result
        };
      }

      // 6. 更新目标
      if (evaluation.status === 'in_progress') {
        currentGoal = evaluation.nextGoal || currentGoal;
      }
    }

    // 达到最大迭代次数
    return {
      success: false,
      goal: goal,
      executionPlan: executionPlan,
      reason: '达到最大迭代次数'
    };
  }

  /**
   * 分析当前状态
   */
  async analyze(goal) {
    const prompt = `分析以下目标,思考如何实现:

目标:${goal}

当前可用工具:
${this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

请分析:
1. 目标的关键步骤
2. 需要使用的工具
3. 可能遇到的问题

分析:`;

    const response = await this.llm.invoke(prompt);
    
    return {
      reasoning: response.content,
      tools: this.extractTools(response.content)
    };
  }

  /**
   * 决定行动
   */
  async decideAction(analysis, goal) {
    const prompt = `基于以下分析,决定下一步行动:

目标:${goal}
分析:${analysis.reasoning}

可用工具:
${this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

请决定:
1. 行动类型(tool_call 或 final_answer)
2. 如果使用工具,选择哪个工具
3. 工具参数

格式:JSON
{
  "type": "tool_call" | "final_answer",
  "tool": "工具名称",
  "parameters": {},
  "description": "行动描述"
}

决定:`;

    const response = await this.llm.invoke(prompt);
    const action = this.parseJSON(response.content);

    return {
      type: action.type || 'tool_call',
      tool: action.tool,
      parameters: action.parameters || {},
      description: action.description || ''
    };
  }

  /**
   * 执行行动
   */
  async executeAction(action) {
    if (action.type === 'final_answer') {
      return action.description;
    }

    // 查找工具
    const tool = this.tools.find(t => t.name === action.tool);
    if (!tool) {
      return `错误:工具 ${action.tool} 不存在`;
    }

    try {
      // 执行工具
      const result = await tool.func(action.parameters);
      return result;
    } catch (error) {
      return `错误:${error.message}`;
    }
  }

  /**
   * 评估结果
   */
  async evaluate(result, goal) {
    const prompt = `评估任务执行结果:

目标:${goal}
结果:${result}

请评估:
1. 任务状态(completed, in_progress, failed)
2. 如果未完成,下一步应该做什么

格式:JSON
{
  "status": "completed" | "in_progress" | "failed",
  "nextGoal": "下一步目标",
  "reason": "评估原因"
}

评估:`;

    const response = await this.llm.invoke(prompt);
    const evaluation = this.parseJSON(response.content);

    return {
      status: evaluation.status || 'in_progress',
      nextGoal: evaluation.nextGoal,
      reason: evaluation.reason
    };
  }

  /**
   * 提取工具
   */
  extractTools(text) {
    const toolNames = [];
    this.tools.forEach(tool => {
      if (text.toLowerCase().includes(tool.name.toLowerCase())) {
        toolNames.push(tool.name);
      }
    });
    return toolNames;
  }

  /**
   * 解析 JSON
   */
  parseJSON(text) {
    try {
      // 尝试提取 JSON
      const jsonMatch = text.match(/\{[\s\S]*\}/);
      if (jsonMatch) {
        return JSON.parse(jsonMatch[0]);
      }
      return {};
    } catch (error) {
      logger.error('JSON 解析失败:', error);
      return {};
    }
  }
}

作业2:实现工具集

src/agents/tools.js:

import { DynamicTool } from '@langchain/core/tools';
import axios from 'axios';
import fs from 'fs/promises';

/**
 * 工具集合
 */
export class ToolSet {
  /**
   * 创建所有工具
   */
  static createTools() {
    return [
      // 网络搜索工具
      new DynamicTool({
        name: 'web_search',
        description: '搜索网络信息。输入:搜索关键词',
        func: async (input) => {
          // 模拟搜索(实际可以集成真实搜索 API)
          return `关于"${input}"的搜索结果:
1. 相关结果1...
2. 相关结果2...
3. 相关结果3...`;
        }
      }),

      // 文件读写工具
      new DynamicTool({
        name: 'read_file',
        description: '读取文件内容。输入:文件路径',
        func: async (input) => {
          try {
            const content = await fs.readFile(input, 'utf-8');
            return `文件内容:\n${content}`;
          } catch (error) {
            return `错误:无法读取文件 ${input}`;
          }
        }
      }),

      new DynamicTool({
        name: 'write_file',
        description: '写入文件。输入:JSON格式 {"path": "文件路径", "content": "内容"}',
        func: async (input) => {
          try {
            const params = JSON.parse(input);
            await fs.writeFile(params.path, params.content, 'utf-8');
            return `文件已写入:${params.path}`;
          } catch (error) {
            return `错误:${error.message}`;
          }
        }
      }),

      // 计算工具
      new DynamicTool({
        name: 'calculate',
        description: '执行数学计算。输入:数学表达式',
        func: async (input) => {
          try {
            const result = Function(`"use strict"; return (${input})`)();
            return `计算结果:${result}`;
          } catch (error) {
            return `计算错误:${error.message}`;
          }
        }
      }),

      // HTTP 请求工具
      new DynamicTool({
        name: 'http_request',
        description: '发送 HTTP 请求。输入:JSON格式 {"url": "URL", "method": "GET|POST", "data": {}}',
        func: async (input) => {
          try {
            const params = JSON.parse(input);
            const response = await axios({
              method: params.method || 'GET',
              url: params.url,
              data: params.data,
              timeout: 10000
            });
            return `响应:${JSON.stringify(response.data)}`;
          } catch (error) {
            return `请求错误:${error.message}`;
          }
        }
      }),

      // 代码执行工具(安全限制)
      new DynamicTool({
        name: 'execute_code',
        description: '执行 JavaScript 代码。输入:代码字符串(仅限安全操作)',
        func: async (input) => {
          try {
            // 安全检查:禁止危险操作
            const dangerous = ['require', 'process', 'fs', 'eval', 'Function'];
            if (dangerous.some(keyword => input.includes(keyword))) {
              return '错误:代码包含不安全操作';
            }

            // 执行代码(实际应该使用沙箱)
            const result = eval(input);
            return `执行结果:${result}`;
          } catch (error) {
            return `执行错误:${error.message}`;
          }
        }
      }),

      // 数据库查询工具(模拟)
      new DynamicTool({
        name: 'query_database',
        description: '查询数据库。输入:SQL 查询语句',
        func: async (input) => {
          // 模拟数据库查询
          return `查询结果:
ID | Name | Value
1  | Item1| 100
2  | Item2| 200`;
        }
      })
    ];
  }
}

作业3:实现 ReAct Agent

src/agents/react-agent.js:

import { BaseAgent } from './base-agent.js';
import { ToolSet } from './tools.js';
import { logger } from '../utils/logger.js';

/**
 * ReAct Agent:推理+行动
 */
export class ReActAgent extends BaseAgent {
  constructor(options = {}) {
    super(options);
    
    // 添加默认工具
    const tools = ToolSet.createTools();
    tools.forEach(tool => this.addTool(tool));
  }

  /**
   * ReAct 循环
   */
  async reactLoop(goal) {
    let thought = '';
    let action = '';
    let observation = '';
    let iteration = 0;

    const history = [];

    while (iteration < this.maxIterations) {
      iteration++;

      // Thought: 思考下一步
      thought = await this.think(goal, history);
      logger.info(`思考: ${thought}`);

      // Action: 决定行动
      action = await this.planAction(thought, history);
      logger.info(`行动: ${action}`);

      // 检查是否完成
      if (action.type === 'final') {
        return {
          success: true,
          answer: action.answer,
          history: history
        };
      }

      // Observation: 执行并观察结果
      observation = await this.executeAction(action);
      logger.info(`观察: ${observation}`);

      // 记录历史
      history.push({
        thought,
        action,
        observation
      });
    }

    return {
      success: false,
      reason: '达到最大迭代次数',
      history: history
    };
  }

  /**
   * 思考
   */
  async think(goal, history) {
    const historyText = history.map(h => 
      `思考: ${h.thought}\n行动: ${h.action.description}\n观察: ${h.observation}`
    ).join('\n\n');

    const prompt = `目标:${goal}

执行历史:
${historyText || '无'}

可用工具:
${this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

请思考下一步应该做什么:`;

    const response = await this.llm.invoke(prompt);
    return response.content;
  }

  /**
   * 规划行动
   */
  async planAction(thought, history) {
    const prompt = `基于以下思考,决定具体行动:

思考:${thought}

可用工具:
${this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

请决定:
1. 如果目标已完成,返回最终答案
2. 否则,选择工具并执行

格式:JSON
{
  "type": "tool" | "final",
  "tool": "工具名称",
  "input": "工具输入",
  "answer": "最终答案(如果type为final)"
}

决定:`;

    const response = await this.llm.invoke(prompt);
    const action = this.parseJSON(response.content);

    if (action.type === 'final') {
      return {
        type: 'final',
        answer: action.answer
      };
    }

    return {
      type: 'tool',
      tool: action.tool,
      input: action.input,
      description: `使用 ${action.tool} 处理: ${action.input}`
    };
  }
}

作业4:实现任务规划 Agent

src/agents/planner-agent.js:

import { BaseAgent } from './base-agent.js';
import { ToolSet } from './tools.js';
import { logger } from '../utils/logger.js';

/**
 * 规划执行 Agent
 */
export class PlannerAgent extends BaseAgent {
  constructor(options = {}) {
    super(options);
    
    const tools = ToolSet.createTools();
    tools.forEach(tool => this.addTool(tool));
  }

  /**
   * 执行任务(规划+执行)
   */
  async execute(goal) {
    // 1. 规划阶段
    logger.info('=== 规划阶段 ===');
    const plan = await this.plan(goal);
    logger.info(`规划完成,共 ${plan.steps.length} 步`);

    // 2. 执行阶段
    logger.info('=== 执行阶段 ===');
    const results = [];
    
    for (let i = 0; i < plan.steps.length; i++) {
      const step = plan.steps[i];
      logger.info(`执行步骤 ${i + 1}/${plan.steps.length}: ${step.description}`);
      
      const result = await this.executeStep(step);
      results.push({
        step: step,
        result: result
      });

      // 检查是否需要调整计划
      if (result.needsReplan) {
        logger.info('需要重新规划');
        const newPlan = await this.replan(goal, results);
        plan.steps = newPlan.steps;
      }
    }

    return {
      success: true,
      goal: goal,
      plan: plan,
      results: results
    };
  }

  /**
   * 规划任务
   */
  async plan(goal) {
    const prompt = `将以下目标分解为具体步骤:

目标:${goal}

可用工具:
${this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}

请规划执行步骤,每个步骤应该:
1. 明确描述要做什么
2. 指定使用的工具
3. 说明预期结果

格式:JSON
{
  "steps": [
    {
      "step": 1,
      "description": "步骤描述",
      "tool": "工具名称",
      "input": "工具输入",
      "expected": "预期结果"
    }
  ]
}

规划:`;

    const response = await this.llm.invoke(prompt);
    const plan = this.parseJSON(response.content);

    return {
      steps: plan.steps || []
    };
  }

  /**
   * 执行步骤
   */
  async executeStep(step) {
    try {
      const tool = this.tools.find(t => t.name === step.tool);
      if (!tool) {
        return {
          success: false,
          error: `工具 ${step.tool} 不存在`,
          needsReplan: true
        };
      }

      const result = await tool.func(step.input);
      
      // 验证结果
      const validation = await this.validateResult(step, result);
      
      return {
        success: validation.valid,
        result: result,
        needsReplan: !validation.valid
      };
    } catch (error) {
      return {
        success: false,
        error: error.message,
        needsReplan: true
      };
    }
  }

  /**
   * 验证结果
   */
  async validateResult(step, result) {
    const prompt = `验证步骤执行结果:

步骤:${step.description}
预期:${step.expected}
实际:${result}

结果是否满足预期?返回 JSON:
{
  "valid": true/false,
  "reason": "原因"
}

验证:`;

    const response = await this.llm.invoke(prompt);
    return this.parseJSON(response.content);
  }

  /**
   * 重新规划
   */
  async replan(goal, results) {
    const resultsText = results.map(r => 
      `步骤: ${r.step.description}\n结果: ${r.result.result || r.result.error}`
    ).join('\n\n');

    const prompt = `目标:${goal}

已执行结果:
${resultsText}

请重新规划剩余步骤:`;

    const response = await this.llm.invoke(prompt);
    const newPlan = this.parseJSON(response.content);

    return {
      steps: newPlan.steps || []
    };
  }
}

作业5:创建 Agent API

src/routes/agent.js:

import express from 'express';
import { ReActAgent } from '../agents/react-agent.js';
import { PlannerAgent } from '../agents/planner-agent.js';
import { logger } from '../utils/logger.js';

export const agentRouter = express.Router();

// POST /api/agent/react - ReAct Agent
agentRouter.post('/react', async (req, res) => {
  try {
    const { goal, maxIterations = 10 } = req.body;

    if (!goal) {
      return res.status(400).json({
        success: false,
        error: '目标不能为空'
      });
    }

    const agent = new ReActAgent({
      maxIterations: maxIterations,
      verbose: true
    });

    const result = await agent.reactLoop(goal);

    res.json({
      success: result.success,
      data: result
    });
  } catch (error) {
    logger.error('ReAct Agent 错误:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// POST /api/agent/planner - Planner Agent
agentRouter.post('/planner', async (req, res) => {
  try {
    const { goal } = req.body;

    if (!goal) {
      return res.status(400).json({
        success: false,
        error: '目标不能为空'
      });
    }

    const agent = new PlannerAgent({
      verbose: true
    });

    const result = await agent.execute(goal);

    res.json({
      success: true,
      data: result
    });
  } catch (error) {
    logger.error('Planner Agent 错误:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

作业6:测试 Agent

test/agent-test.js:

import { ReActAgent } from '../src/agents/react-agent.js';
import { PlannerAgent } from '../src/agents/planner-agent.js';

async function testReActAgent() {
  console.log('=== 测试 ReAct Agent ===\n');
  
  const agent = new ReActAgent({
    maxIterations: 5,
    verbose: true
  });

  const result = await agent.reactLoop(
    '计算 123 * 456,然后将结果写入文件 result.txt'
  );

  console.log('\n结果:', result);
}

async function testPlannerAgent() {
  console.log('\n=== 测试 Planner Agent ===\n');
  
  const agent = new PlannerAgent({
    verbose: true
  });

  const result = await agent.execute(
    '搜索"前端开发最佳实践",总结要点,保存到文件 best-practices.txt'
  );

  console.log('\n结果:', result);
}

async function runTests() {
  await testReActAgent();
  await testPlannerAgent();
}

runTests().catch(console.error);

遇到的问题

问题1:Agent 陷入循环

解决方案:

// 限制最大迭代次数
this.maxIterations = 10;

// 检测重复操作
const recentActions = history.slice(-3);
if (this.isRepeating(recentActions)) {
  return { success: false, reason: '检测到重复操作' };
}

问题2:工具执行失败

解决方案:

// 错误处理和重试
try {
  const result = await tool.func(input);
  return result;
} catch (error) {
  // 记录错误,让 Agent 重新规划
  return { error: error.message, needsReplan: true };
}

学习总结

今日收获

  1. ✅ 理解 AI Agent 概念
  2. ✅ 实现自主任务执行
  3. ✅ 构建工具调用链
  4. ✅ 实现状态管理
  5. ✅ 创建智能 Agent 系统

关键知识点

  • Agent 自主执行,无需人工干预
  • 工具扩展能力,调用外部功能
  • 规划+执行,分步骤完成任务
  • 状态管理,保持上下文

Agent 优势

  • ✅ 自动化任务
  • ✅ 智能决策
  • ✅ 工具集成
  • ✅ 复杂任务处理

明日计划

明天将学习:

期待明天的学习! 🚀


参考资源


代码仓库

项目已更新:

  • ✅ 基础 Agent
  • ✅ ReAct Agent
  • ✅ Planner Agent
  • ✅ 工具集
  • ✅ API 接口

GitHub 提交: Day 13 - AI Agent 开发


标签: #AI学习 #AI Agent #自主执行 #工具调用 #学习笔记


写在最后

今天学习了 AI Agent 开发,这是 AI 应用的高级功能。
通过 Agent,可以让 AI 自主执行复杂任务,大大扩展了应用能力。
明天将学习应用优化,提升用户体验!

继续加油! 💪


快速检查清单

完成这些,第十三天就达标了!

posted @ 2025-12-16 16:17  XiaoZhengTou  阅读(3)  评论(0)    收藏  举报