AI Agent范式

207 阅读3分钟

说明:LangChain 官方现在更推荐用 LangGraph 构建 Agent(可与 LangChain.js 无缝搭配),ReAct/Plan&Execute 在 LangChain 里仍可用,但建议在新项目里考虑上图式编排(LangGraph)以获得更强的可控性与状态持久化。


1) ReAct(Reason + Act)

目标:让模型“思考—调用工具—再思考—再调用”。

LangChain.js 快速用法:createReactAgent({ llm, tools, prompt })。

// pnpm add langchain @langchain/openai zod
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import { createReactAgent } from "langchain/agents";
import { tool, StructuredTool } from "@langchain/core/tools";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

/** 1) 用 tool() 快速定义一个简单工具(推荐) */
const webSearch = tool({
  name: "web_search",
  description: "Search the web and return a short result overview.",
  schema: z.object({ query: z.string() }),
  async func({ query }) {
    // 这里替换成你自己的检索逻辑(公司内SaaS/ES/自建API等)
    return `Pretend we searched the web for: ${query}`;
  },
});

/** 2) 用 StructuredTool 定义带复杂Schema的工具(进阶) */
class SumTool extends StructuredTool<typeof schema> {
  name = "sum_numbers";
  description = "Sum two numbers.";
  constructor() { super(); }
  static schema = z.object({ a: z.number(), b: z.number() });
  schema = SumTool.schema;
  async _call({ a, b }) { return String(a + b); }
}

const agent = await createReactAgent({
  llm,
  tools: [webSearch, new SumTool()],
  // 可选:自定义提示词;不传则用默认 ReAct 提示
});

const res = await agent.invoke({
  input: "先用web_search搜索'2024年新能源销量Top3',再把1+2相加告诉我。",
});
console.log(res);
  • 工具创建与选择:官方建议优先使用 tool();复杂输入可用 StructuredTool。

2) Plan-and-Execute(先规划,再执行)

目标:先产出全局计划,再逐步执行各步骤,可在长任务中更稳定。

在 LangChain.js:可用 PlanAndExecuteAgentExecutor(实验模块),或直接采用 LangGraph 的 Plan&Execute 教程。

// pnpm add langchain @langchain/openai zod
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import { tool } from "@langchain/core/tools";
import {
  PlanAndExecuteAgentExecutor,
  LLMPlanner,
  PlanOutputParser,
} from "langchain/experimental/plan_and_execute";
import { LLMChain } from "langchain/chains/llm_chain";
import { ChatPromptTemplate } from "@langchain/core/prompts";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const fetchRepoStats = tool({
  name: "fetch_repo_stats",
  description: "Get stars and forks of a GitHub repo like owner/name.",
  schema: z.object({ repo: z.string() }),
  async func({ repo }) {
    // 演示:替换为真实 GitHub API
    return { repo, stars: 27500, forks: 3000 };
  },
});

// 自定义“规划阶段”提示:务必输出编号步骤(1. 2. 3. ...),以匹配 PlanOutputParser 的解析规则
const plannerPrompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    "你是项目规划助手。请将用户任务拆分为最多5个明确、可执行的步骤。" +
      "严格输出编号列表(每步以“1.”、“2.”开头),必要时在最后添加 <END_OF_PLAN> 标记。",
  ],
  ["human", "任务:{input}"],
]);

// 用你自定义的提示创建 LLMChain -> LLMPlanner -> PlanOutputParser
const plannerChain = new LLMChain({ llm, prompt: plannerPrompt });
const planner = new LLMPlanner(plannerChain, new PlanOutputParser());

// 使用默认的步骤执行器(也可自定义)。如果需要自定义执行阶段的人类消息模板,可传 humanMessageTemplate。
const stepExecutor = PlanAndExecuteAgentExecutor.getDefaultStepExecutor({
  llm,
  tools: [fetchRepoStats],
  // humanMessageTemplate: "基于已有步骤与工具,执行当前步骤:{current_step}\n历史:{previous_steps}\nScratchpad: {agent_scratchpad}",
});

// 组装 Plan-and-Execute 执行器
const executor = new PlanAndExecuteAgentExecutor({
  planner,
  stepExecutor,
});

const result = await executor.invoke({
  input: "比较 langchain-ai/react-agent-js 的人气与它的替代项目,并给出结论。",
});
console.log(result.output);

  • 进一步参考:
    • LangGraph 的 Plan&Execute 教程(推荐新项目用图式编排)。
    • LangChain 团队的规划 Agent 文章。

3) Reflex Agent(规则/映射式)

目标:输入→输出的轻量“反射型”策略,无外部推理树。

实现:直接用 LLMChain/RunnableSequence 即可(不需要 Agent 组件),示例:

// pnpm add langchain @langchain/openai
import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { RunnableSequence } from "@langchain/core/runnables";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const prompt = PromptTemplate.fromTemplate(
  "你是FAQ机器人,只能从下列知识里回答:{kb}\n用户:{q}\n回答:"
);

const chain = RunnableSequence.from([prompt, llm]);
const out = await chain.invoke({
  kb: "退改签规则:……\n客服电话:400-xxx-xxx",
  q: "怎么人工转客服?",
});
console.log(out);

4) 推理范式(CoT / ToT / GoT)

4.1 Chain-of-Thought(CoT)

import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { RunnableSequence } from "@langchain/core/runnables";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const prompt = PromptTemplate.fromTemplate(
  "请逐步思考并求解:{question}\n请给出“推理过程”和“最终答案”。"
);

const cot = RunnableSequence.from([prompt, llm]);
console.log(await cot.invoke({ question: "一辆车每小时行60km,2.5小时走多远?" }));

在 ReAct 或 Plan&Execute 里,同样可以通过提示工程把 CoT 融进去。

4.2 Tree-of-Thoughts / Graph-of-Thoughts

在 JS 侧最实用的做法是用 LangGraph.js 把“分支推理/回溯”的过程画成状态图节点(分支评估→选择→继续/回溯)。官方 ReAct 模板与教程也都基于 LangGraph Studio。


5) 学习范式(Self-Reflection / Self-Consistency)

做法:多采样→打分→自我反思→重写。

用 RunnableWithFallbacks / map/aggregate 等可快速拼装:

import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";

const llm = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0.7 });

const q = "比较 Vite 和 Webpack 的冷启动差异,并给出实验设计。";

// 多次采样
const drafts = await Promise.all(
  Array.from({ length: 3 }).map(() =>
    llm.invoke(`草拟答案(保证不同视角):${q}`)
                               )
);

// 自评&挑选(可以再用 llm 评审器打分)
const judge = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });
const scored = await Promise.all(
  drafts.map((d, i) =>
    judge.invoke(`对下面的答案打分(0-10)并解释:\n答案${i + 1}${d.content}`)
            )
);

// 反思重写
const bestIdx = 0; // 简化:也可以解析 judge 的评分选择最高分
const final = await judge.invoke(
  `参考答案${bestIdx + 1}的优点,针对不足之处重写更强版本:\n${drafts[bestIdx].content}`
);
console.log(final);

6) 多 Agent(Society / Role-Playing / Swarm)

建议实现:用 LangGraph 把多个 Agent 节点(例如“产品经理👩‍💼/架构师🧑‍💻/测试🧪”)连成图,角色消息通过边传递。官方 ReAct 模板可扩展为多 Agent。开源多 Agent 社区如 CAMEL 也提供丰富示例与角色提示。

最小多 Agent(2 角色轮询) (演示型,未用图式,仅 LangChain.js):

import { ChatOpenAI } from "@langchain/openai";

const pm = new ChatOpenAI({ model: "gpt-4o-mini" });
const dev = new ChatOpenAI({ model: "gpt-4o-mini" });

let msg = "目标:做一个车票比价H5,先给出里程碑。";
for (let i = 0; i < 4; i++) {
  const pmPlan = await pm.invoke(`你是产品经理,仅输出明确需求/里程碑:\n${msg}`);
  const devReply = await dev.invoke(
    `你是前端架构师,基于需求给出技术实现与风险清单:\n${pmPlan.content}`
  );
  msg = String(devReply.content);
}
console.log("最终输出:", msg);

7) 工具增强(Tool-augmented Agent)

核心:把企业内 API / RAG / 搜索 / 报表 等封装成 Tool,挂到 Agent 或直接让模型进行 原生 tool calling

  • JS 文档:工具概念、如何自定义工具。
  • 常用内置工具(文件、HTTP等)可复用或参考实现。
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import { tool } from "@langchain/core/tools";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const getOrder = tool({
  name: "get_order_by_id",
  description: "根据订单ID查询订单详情",
  schema: z.object({ orderId: z.string() }),
  async func({ orderId }) {
    // 调内部BFF/GraphQL/REST
    return { orderId, status: "PAID", driver: "Li Lei" };
  },
});

// 直接用“模型原生工具调用”而非老式 Agent 也可以:
const withTools = llm.bindTools([getOrder]); // 某些版本也叫 toolChoice/bind()
const out = await withTools.invoke("查询订单 20240926-001 的最新状态,并总结给用户。");
console.log(out);

8) 记忆增强(Memory-augmented Agent)

目标:保存对话长期/短期信息(如用户偏好、上下文摘要)。

  • JS 侧 ConversationSummaryBufferMemory 提供“摘要+最近窗口”的策略;新版文档里也给了迁移与对比。
// pnpm add langchain @langchain/openai
import { ChatOpenAI } from "@langchain/openai";
import { ConversationSummaryBufferMemory } from "langchain/memory";
import { ChatMessageHistory } from "langchain/stores/message/in_memory";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const memory = new ConversationSummaryBufferMemory({
  llm,            // 用于生成摘要
  maxTokenLimit: 800,
  memoryKey: "history",
  chatHistory: new ChatMessageHistory(),
});

await memory.saveContext(
  { input: "我喜欢用暗色主题,报表默认要按城市维度。" },
  { output: "已记录你的偏好。" }
);

const { history } = await memory.loadMemoryVariables({});
const reply = await llm.invoke(
  `结合历史偏好生成个性化欢迎语。\n历史:${history}`
);
console.log(reply);

9) Workflow / Orchestrator(工作流编排)

生产中推荐用 LangGraph 把“计划—执行—工具—回退—人工介入”画成 DAG/状态机;稳定、可测试、可持久化(官方鼓励从传统 Agent 迁移)。可直接参考 ReAct 模板与 Plan&Execute 教程。


小结 & 选型建议

  • 新项目:优先 LangGraph(JS)+ LangChain 工具与存储;ReAct/Plan&Execute 当作“策略”,用图把它们固化在节点里。
  • 工具层:tool() 足够用,复杂场景再上 StructuredTool,注意 Zod→JSON Schema 的复杂度(有兼容坑)。
  • 记忆层:面向会话用 ConversationSummaryBufferMemory;面向知识用 RAG(向量库)+ 工具调用。