《60天AI学习计划启动 | Day 17: LangChain Agents 深入 - 多 Agent 协作》

Day 17: LangChain Agents 深入 - 多 Agent 协作

学习目标


核心学习内容

1. LangChain Agents 类型

Agent 类型:

  • Zero-shot ReAct:零样本推理+行动
  • ReAct Docstore:文档检索
  • Self-ask with Search:自问自答+搜索
  • Conversational ReAct:对话式 ReAct
  • Plan-and-Execute:规划执行

2. 多 Agent 协作

协作模式:

  • 主从模式:主 Agent 协调子 Agent
  • 对等模式:多个 Agent 平等协作
  • 流水线模式:Agent 依次处理
  • 竞争模式:多个 Agent 竞争执行

3. 工具链优化

优化策略:

  • 工具选择优化
  • 执行顺序优化
  • 结果缓存
  • 错误恢复

实践作业

作业1:实现多 Agent 系统

src/agents/multi-agent-system.js:

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

/**
 * 多 Agent 系统
 */
export class MultiAgentSystem {
  constructor() {
    this.llm = new ChatOpenAI({
      temperature: 0.7,
      openAIApiKey: process.env.OPENAI_API_KEY
    });

    this.agents = new Map();
    this.coordinator = null;
    this.initializeAgents();
  }

  /**
   * 初始化 Agent
   */
  initializeAgents() {
    // 代码专家 Agent
    this.agents.set('code_expert', {
      name: '代码专家',
      description: '擅长代码审查、优化、调试',
      tools: this.createCodeTools()
    });

    // 文档专家 Agent
    this.agents.set('doc_expert', {
      name: '文档专家',
      description: '擅长文档编写、整理、分析',
      tools: this.createDocTools()
    });

    // 数据分析 Agent
    this.agents.set('data_analyst', {
      name: '数据分析师',
      description: '擅长数据分析、统计、可视化',
      tools: this.createDataTools()
    });

    // 协调者 Agent
    this.coordinator = this.createCoordinator();
  }

  /**
   * 创建代码工具
   */
  createCodeTools() {
    return [
      new DynamicTool({
        name: 'code_review',
        description: '审查代码质量',
        func: async (input) => {
          return `代码审查结果:${input}`;
        }
      }),
      new DynamicTool({
        name: 'code_optimize',
        description: '优化代码性能',
        func: async (input) => {
          return `优化建议:${input}`;
        }
      })
    ];
  }

  /**
   * 创建文档工具
   */
  createDocTools() {
    return [
      new DynamicTool({
        name: 'doc_generate',
        description: '生成文档',
        func: async (input) => {
          return `文档生成:${input}`;
        }
      }),
      new DynamicTool({
        name: 'doc_analyze',
        description: '分析文档',
        func: async (input) => {
          return `文档分析:${input}`;
        }
      })
    ];
  }

  /**
   * 创建数据工具
   */
  createDataTools() {
    return [
      new DynamicTool({
        name: 'data_analyze',
        description: '分析数据',
        func: async (input) => {
          return `数据分析:${input}`;
        }
      }),
      new DynamicTool({
        name: 'data_visualize',
        description: '数据可视化',
        func: async (input) => {
          return `可视化结果:${input}`;
        }
      })
    ];
  }

  /**
   * 创建协调者
   */
  createCoordinator() {
    const coordinatorTools = [
      new DynamicTool({
        name: 'delegate_to_agent',
        description: '委托任务给特定 Agent。输入:JSON格式 {"agent": "agent_name", "task": "任务描述"}',
        func: async (input) => {
          try {
            const { agent, task } = JSON.parse(input);
            return await this.delegateTask(agent, task);
          } catch (error) {
            return `委托失败:${error.message}`;
          }
        }
      })
    ];

    return {
      tools: coordinatorTools,
      llm: this.llm
    };
  }

  /**
   * 委托任务
   */
  async delegateTask(agentName, task) {
    const agent = this.agents.get(agentName);
    if (!agent) {
      return `Agent ${agentName} 不存在`;
    }

    logger.info(`委托任务给 ${agent.name}: ${task}`);

    // 创建 Agent Executor
    const executor = await initializeAgentExecutorWithOptions(
      agent.tools,
      this.llm,
      {
        agentType: 'zero-shot-react-description',
        verbose: true
      }
    );

    const result = await executor.invoke({ input: task });
    return result.output;
  }

  /**
   * 协调执行复杂任务
   */
  async coordinateTask(goal) {
    logger.info(`协调执行任务: ${goal}`);

    // 1. 分析任务,分解为子任务
    const subTasks = await this.analyzeTask(goal);

    // 2. 为每个子任务分配合适的 Agent
    const assignments = await this.assignAgents(subTasks);

    // 3. 并行或顺序执行
    const results = [];
    for (const assignment of assignments) {
      const result = await this.delegateTask(
        assignment.agent,
        assignment.task
      );
      results.push({
        agent: assignment.agent,
        task: assignment.task,
        result: result
      });
    }

    // 4. 整合结果
    const finalResult = await this.integrateResults(goal, results);

    return {
      goal: goal,
      subTasks: subTasks,
      assignments: assignments,
      results: results,
      finalResult: finalResult
    };
  }

  /**
   * 分析任务
   */
  async analyzeTask(goal) {
    const prompt = `将以下任务分解为子任务:

任务:${goal}

可用 Agent:
${Array.from(this.agents.values()).map(a => 
  `- ${a.name}: ${a.description}`
).join('\n')}

请返回 JSON 数组:
[
  {"task": "子任务1", "agent": "推荐的agent名称"},
  {"task": "子任务2", "agent": "推荐的agent名称"}
]

分解:`;

    const response = await this.llm.invoke(prompt);
    
    try {
      const jsonMatch = response.content.match(/\[[\s\S]*\]/);
      if (jsonMatch) {
        return JSON.parse(jsonMatch[0]);
      }
    } catch (e) {
      logger.error('解析任务失败:', e);
    }

    // 默认分解
    return [{ task: goal, agent: 'code_expert' }];
  }

  /**
   * 分配 Agent
   */
  async assignAgents(subTasks) {
    return subTasks.map(st => ({
      task: st.task,
      agent: st.agent || this.selectBestAgent(st.task)
    }));
  }

  /**
   * 选择最佳 Agent
   */
  selectBestAgent(task) {
    const taskLower = task.toLowerCase();
    
    if (taskLower.includes('代码') || taskLower.includes('code')) {
      return 'code_expert';
    } else if (taskLower.includes('文档') || taskLower.includes('doc')) {
      return 'doc_expert';
    } else if (taskLower.includes('数据') || taskLower.includes('data')) {
      return 'data_analyst';
    }
    
    return 'code_expert'; // 默认
  }

  /**
   * 整合结果
   */
  async integrateResults(goal, results) {
    const resultsText = results.map(r => 
      `${r.agent}: ${r.result}`
    ).join('\n\n');

    const prompt = `基于以下执行结果,生成最终答案:

原始任务:${goal}

执行结果:
${resultsText}

请整合所有结果,生成完整的答案:`;

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

作业2:实现流水线 Agent

src/agents/pipeline-agent.js:

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

/**
 * 流水线 Agent:依次处理任务
 */
export class PipelineAgent {
  constructor() {
    this.llm = new ChatOpenAI({
      temperature: 0.7,
      openAIApiKey: process.env.OPENAI_API_KEY
    });

    this.stages = [];
  }

  /**
   * 添加处理阶段
   */
  addStage(name, tools, description) {
    this.stages.push({
      name,
      tools,
      description
    });
  }

  /**
   * 执行流水线
   */
  async execute(input) {
    logger.info(`开始流水线处理: ${input}`);

    let currentInput = input;
    const stageResults = [];

    for (let i = 0; i < this.stages.length; i++) {
      const stage = this.stages[i];
      logger.info(`执行阶段 ${i + 1}/${this.stages.length}: ${stage.name}`);

      // 创建 Agent
      const executor = await initializeAgentExecutorWithOptions(
        stage.tools,
        this.llm,
        {
          agentType: 'zero-shot-react-description',
          verbose: true
        }
      );

      // 执行阶段
      const task = `${stage.description}\n\n输入:${currentInput}`;
      const result = await executor.invoke({ input: task });

      stageResults.push({
        stage: stage.name,
        input: currentInput,
        output: result.output
      });

      // 下一阶段的输入
      currentInput = result.output;
    }

    return {
      finalOutput: currentInput,
      stages: stageResults
    };
  }
}

/**
 * 代码处理流水线示例
 */
export function createCodePipeline() {
  const pipeline = new PipelineAgent();

  // 阶段1:代码审查
  pipeline.addStage(
    '代码审查',
    [
      new DynamicTool({
        name: 'review_code',
        description: '审查代码',
        func: async (input) => {
          return `审查完成:发现3个问题`;
        }
      })
    ],
    '审查代码质量'
  );

  // 阶段2:代码优化
  pipeline.addStage(
    '代码优化',
    [
      new DynamicTool({
        name: 'optimize_code',
        description: '优化代码',
        func: async (input) => {
          return `优化完成:性能提升20%`;
        }
      })
    ],
    '优化代码性能'
  );

  // 阶段3:生成文档
  pipeline.addStage(
    '生成文档',
    [
      new DynamicTool({
        name: 'generate_doc',
        description: '生成文档',
        func: async (input) => {
          return `文档生成完成`;
        }
      })
    ],
    '为代码生成文档'
  );

  return pipeline;
}

作业3:实现竞争 Agent

src/agents/competitive-agent.js:

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

/**
 * 竞争 Agent:多个 Agent 竞争执行,选择最佳结果
 */
export class CompetitiveAgent {
  constructor() {
    this.llm = new ChatOpenAI({
      temperature: 0.7,
      openAIApiKey: process.env.OPENAI_API_KEY
    });

    this.agents = [];
  }

  /**
   * 添加竞争 Agent
   */
  addAgent(name, tools, strategy) {
    this.agents.push({
      name,
      tools,
      strategy
    });
  }

  /**
   * 竞争执行
   */
  async compete(task) {
    logger.info(`开始竞争执行: ${task}`);

    // 并行执行所有 Agent
    const promises = this.agents.map(agent => 
      this.executeAgent(agent, task)
    );

    const results = await Promise.allSettled(promises);

    // 评估结果
    const evaluated = await this.evaluateResults(task, results);

    // 选择最佳结果
    const winner = evaluated.sort((a, b) => b.score - a.score)[0];

    return {
      task: task,
      results: evaluated,
      winner: winner,
      bestResult: winner.result
    };
  }

  /**
   * 执行单个 Agent
   */
  async executeAgent(agent, task) {
    try {
      const executor = await initializeAgentExecutorWithOptions(
        agent.tools,
        this.llm,
        {
          agentType: 'zero-shot-react-description',
          verbose: false
        }
      );

      const result = await executor.invoke({ input: task });
      return {
        agent: agent.name,
        result: result.output,
        success: true
      };
    } catch (error) {
      logger.error(`Agent ${agent.name} 执行失败:`, error);
      return {
        agent: agent.name,
        result: null,
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 评估结果
   */
  async evaluateResults(task, results) {
    const prompt = `评估以下执行结果,为每个结果评分(1-10):

任务:${task}

结果:
${results.map((r, i) => 
  `${i + 1}. Agent: ${r.value?.agent || 'Unknown'}\n   结果: ${r.value?.result || '失败'}`
).join('\n\n')}

请返回 JSON 数组:
[
  {"index": 1, "score": 分数, "reason": "评分理由"},
  ...
]

评估:`;

    const response = await this.llm.invoke(prompt);
    
    try {
      const jsonMatch = response.content.match(/\[[\s\S]*\]/);
      if (jsonMatch) {
        const evaluations = JSON.parse(jsonMatch[0]);
        return results.map((r, i) => {
          const eval = evaluations.find(e => e.index === i + 1);
          return {
            agent: r.value?.agent,
            result: r.value?.result,
            score: eval?.score || 5,
            reason: eval?.reason || '默认评分'
          };
        });
      }
    } catch (e) {
      logger.error('评估失败:', e);
    }

    // 默认评分
    return results.map(r => ({
      agent: r.value?.agent,
      result: r.value?.result,
      score: r.status === 'fulfilled' ? 7 : 3,
      reason: r.status === 'fulfilled' ? '执行成功' : '执行失败'
    }));
  }
}

作业4:优化工具链

src/agents/tool-optimizer.js:

import { logger } from '../utils/logger.js';

/**
 * 工具链优化器
 */
export class ToolOptimizer {
  constructor() {
    this.toolCache = new Map();
    this.toolStats = new Map();
  }

  /**
   * 优化工具选择
   */
  optimizeToolSelection(tools, task) {
    // 1. 根据任务描述匹配工具
    const taskLower = task.toLowerCase();
    const matched = tools.filter(tool => {
      const nameMatch = taskLower.includes(tool.name.toLowerCase());
      const descMatch = tool.description.toLowerCase()
        .split(' ')
        .some(word => taskLower.includes(word));
      return nameMatch || descMatch;
    });

    // 2. 根据历史使用统计排序
    const scored = matched.map(tool => {
      const stats = this.toolStats.get(tool.name) || {
        uses: 0,
        successes: 0,
        avgTime: 0
      };
      
      const successRate = stats.uses > 0 
        ? stats.successes / stats.uses 
        : 0.5;
      
      const score = successRate * 0.7 + (1 - stats.avgTime / 1000) * 0.3;
      
      return {
        tool,
        score
      };
    });

    scored.sort((a, b) => b.score - a.score);

    return scored.map(s => s.tool);
  }

  /**
   * 记录工具使用
   */
  recordToolUse(toolName, success, duration) {
    const stats = this.toolStats.get(toolName) || {
      uses: 0,
      successes: 0,
      avgTime: 0
    };

    stats.uses++;
    if (success) {
      stats.successes++;
    }
    stats.avgTime = (stats.avgTime * (stats.uses - 1) + duration) / stats.uses;

    this.toolStats.set(toolName, stats);
  }

  /**
   * 工具结果缓存
   */
  getCachedResult(toolName, input) {
    const key = `${toolName}_${JSON.stringify(input)}`;
    return this.toolCache.get(key);
  }

  /**
   * 缓存工具结果
   */
  cacheResult(toolName, input, result) {
    const key = `${toolName}_${JSON.stringify(input)}`;
    this.toolCache.set(key, {
      result,
      timestamp: Date.now()
    });

    // 限制缓存大小
    if (this.toolCache.size > 1000) {
      const firstKey = this.toolCache.keys().next().value;
      this.toolCache.delete(firstKey);
    }
  }

  /**
   * 获取工具统计
   */
  getToolStats() {
    return Array.from(this.toolStats.entries()).map(([name, stats]) => ({
      name,
      uses: stats.uses,
      successRate: stats.uses > 0 
        ? (stats.successes / stats.uses * 100).toFixed(2) + '%'
        : '0%',
      avgTime: stats.avgTime.toFixed(2) + 'ms'
    }));
  }
}

export const toolOptimizer = new ToolOptimizer();

作业5:创建多 Agent API

src/routes/multi-agent.js:

import express from 'express';
import { MultiAgentSystem } from '../agents/multi-agent-system.js';
import { createCodePipeline } from '../agents/pipeline-agent.js';
import { CompetitiveAgent } from '../agents/competitive-agent.js';
import { logger } from '../utils/logger.js';

export const multiAgentRouter = express.Router();

// 初始化系统
const multiAgentSystem = new MultiAgentSystem();

// POST /api/multi-agent/coordinate - 协调执行
multiAgentRouter.post('/coordinate', async (req, res) => {
  try {
    const { goal } = req.body;

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

    const result = await multiAgentSystem.coordinateTask(goal);

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

// POST /api/multi-agent/pipeline - 流水线执行
multiAgentRouter.post('/pipeline', async (req, res) => {
  try {
    const { input, pipelineType = 'code' } = req.body;

    if (!input) {
      return res.status(400).json({
        success: false,
        error: '输入不能为空'
      });
    }

    let pipeline;
    if (pipelineType === 'code') {
      pipeline = createCodePipeline();
    } else {
      return res.status(400).json({
        success: false,
        error: '未知的流水线类型'
      });
    }

    const result = await pipeline.execute(input);

    res.json({
      success: true,
      data: result
    });
  } catch (error) {
    logger.error('流水线执行错误:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// POST /api/multi-agent/compete - 竞争执行
multiAgentRouter.post('/compete', async (req, res) => {
  try {
    const { task } = req.body;

    if (!task) {
      return res.status(400).json({
        success: false,
        error: '任务不能为空'
      });
    }

    // 创建竞争 Agent(示例)
    const competitiveAgent = new CompetitiveAgent();
    
    // 添加多个 Agent
    competitiveAgent.addAgent('agent1', [
      // 工具列表
    ], '策略1');

    competitiveAgent.addAgent('agent2', [
      // 工具列表
    ], '策略2');

    const result = await competitiveAgent.compete(task);

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

作业6:测试多 Agent 系统

test/multi-agent-test.js:

import { MultiAgentSystem } from '../src/agents/multi-agent-system.js';
import { createCodePipeline } from '../src/agents/pipeline-agent.js';

async function testMultiAgent() {
  console.log('=== 测试多 Agent 系统 ===\n');

  const system = new MultiAgentSystem();

  const result = await system.coordinateTask(
    '审查这段代码,优化性能,然后生成文档'
  );

  console.log('协调结果:', result);
}

async function testPipeline() {
  console.log('\n=== 测试流水线 Agent ===\n');

  const pipeline = createCodePipeline();

  const result = await pipeline.execute(
    'function add(a, b) { return a + b; }'
  );

  console.log('流水线结果:', result);
}

async function runTests() {
  await testMultiAgent();
  await testPipeline();
}

runTests().catch(console.error);

遇到的问题

问题1:Agent 执行冲突

解决方案:

// 使用锁机制
const locks = new Map();

async function executeWithLock(agentId, task) {
  if (locks.has(agentId)) {
    await locks.get(agentId);
  }
  
  const lock = new Promise(resolve => {
    locks.set(agentId, resolve);
  });
  
  try {
    return await executeTask(task);
  } finally {
    locks.delete(agentId);
  }
}

问题2:结果整合困难

解决方案:

// 使用 LLM 整合结果
async function integrateResults(goal, results) {
  const prompt = `整合以下结果:\n${results.join('\n\n')}`;
  const response = await llm.invoke(prompt);
  return response.content;
}

学习总结

今日收获

  1. ✅ 深入理解 LangChain Agents
  2. ✅ 实现多 Agent 协作
  3. ✅ 优化工具链
  4. ✅ 实现复杂 Agent 系统
  5. ✅ 掌握实际应用场景

关键知识点

  • 多 Agent 协作,处理复杂任务
  • 流水线模式,顺序处理
  • 竞争模式,选择最佳结果
  • 工具优化,提高效率

Agent 协作模式对比

主从模式:适合有明确分工的任务
对等模式:适合需要多角度分析的任务
流水线:适合步骤化处理
竞争模式:适合需要最佳方案的任务

明日计划

明天将学习:

期待明天的学习! 🚀


参考资源


代码仓库

项目已更新:

  • ✅ 多 Agent 系统
  • ✅ 流水线 Agent
  • ✅ 竞争 Agent
  • ✅ 工具优化器
  • ✅ API 接口

GitHub 提交: Day 17 - LangChain Agents 深入


标签: #AI学习 #LangChain #多Agent #Agent协作 #学习笔记


写在最后

今天深入学习了 LangChain Agents 的多 Agent 协作,这是处理复杂任务的重要技术。
通过多 Agent 协作,可以让 AI 系统更加强大和智能。明天将继续学习实际应用场景!

继续加油! 💪


快速检查清单

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

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