使用 nodeJS 从头开始​​创建 ReAct Agent(维基百科搜索)

使用 nodejs 从头开始​​创建 react agent(维基百科搜索)

介绍

我们将创建一个能够搜索维基百科并根据找到的信息回答问题的人工智能代理。该 react(理性与行动)代理使用 google generative ai api 来处理查询并生成响应。我们的代理将能够:

搜索维基百科获取相关信息。从维基百科页面中提取特定部分。对收集到的信息进行推理并制定答案。

[2] 什么是react代理?

react agent 是一种遵循反射-操作循环的特定类型的代理。它根据可用信息和它可以执行的操作反映当前任务,然后决定采取哪个操作或是否结束任务。

[3] 规划代理

3.1 所需工具

node.js用于 http 请求的 axios 库google 生成式 ai api (gemini-1.5-flash)维基百科 api

3.2 代理结构

我们的 react agent 将具有三个主要状态:

思想(反思)行动(执行)答案(回复)

[4] 实现代理

让我们逐步构建 react agent,突出显示每个状态。

4.1 初始设置

首先,设置项目并安装依赖项:

mkdir react-agent-projectcd react-agent-projectnpm init -ynpm install axios dotenv @google/generative-ai

在项目根目录创建一个 .env 文件:

google_ai_api_key=your_api_key_here

4.2 创建tools.js文件

使用以下内容创建 tools.js:

const axios = require("axios");class tools {  static async wikipedia(q) {    try {      const response = await axios.get("https://en.wikipedia.org/w/api.php", {        params: {          action: "query",          list: "search",          srsearch: q,          srwhat: "text",          format: "json",          srlimit: 4,        },      });      const results = await promise.all(        response.data.query.search.map(async (searchresult) => {          const sectionresponse = await axios.get(            "https://en.wikipedia.org/w/api.php",            {              params: {                action: "parse",                pageid: searchresult.pageid,                prop: "sections",                format: "json",              },            },          );          const sections = object.values(            sectionresponse.data.parse.sections,          ).map((section) => `${section.index}, ${section.line}`);          return {            pagetitle: searchresult.title,            snippet: searchresult.snippet,            pageid: searchresult.pageid,            sections: sections,          };        }),      );      return results        .map(          (result) =>            `snippet: ${result.snippet}npageid: ${result.pageid}nsections: ${json.stringify(result.sections)}`,        )        .join("nn");    } catch (error) {      console.error("error fetching from wikipedia:", error);      return "error fetching data from wikipedia";    }  }  static async wikipedia_with_pageid(pageid, sectionid) {    if (sectionid) {      const response = await axios.get("https://en.wikipedia.org/w/api.php", {        params: {          action: "parse",          format: "json",          pageid: parseint(pageid),          prop: "wikitext",          section: parseint(sectionid),          disabletoc: 1,        },      });      return object.values(response.data.parse?.wikitext ?? {})[0]?.substring(        0,        25000,      );    } else {      const response = await axios.get("https://en.wikipedia.org/w/api.php", {        params: {          action: "query",          pageids: parseint(pageid),          prop: "extracts",          exintro: true,          explaintext: true,          format: "json",        },      });      return object.values(response.data?.query.pages)[0]?.extract;    }  }}module.exports = tools;

4.3 创建reactagent.js文件

使用以下内容创建 reactagent.js:

require("dotenv").config();const { googlegenerativeai } = require("@google/generative-ai");const tools = require("./tools");const genai = new googlegenerativeai(process.env.google_ai_api_key);class reactagent {  constructor(query, functions) {    this.query = query;    this.functions = new set(functions);    this.state = "thought";    this._history = [];    this.model = genai.getgenerativemodel({      model: "gemini-1.5-flash",      temperature: 2,    });  }  get history() {    return this._history;  }  pushhistory(value) {    this._history.push(`n ${value}`);  }  async run() {    this.pushhistory(`**task: ${this.query} **`);    try {      return await this.step();    } catch (e) {      if (e.message.includes("exhausted")) {        return "sorry, i'm exhausted, i can't process your request anymore. ><";    }  }  async step() {    const colors = {      reset: "x1b[0m",      yellow: "x1b[33m",      red: "x1b[31m",      cyan: "x1b[36m",    };    console.log("====================================");    console.log(      `next movement: ${        this.state === "thought"          ? colors.yellow          : this.state === "action"            ? colors.red            : this.state === "answer"              ? colors.cyan              : colors.reset      }${this.state}${colors.reset}`,    );    console.log(`last movement: ${this.history[this.history.length - 1]}`);    console.log("====================================");    switch (this.state) {      case "thought":        await this.thought();        break;      case "action":        await this.action();        break;      case "answer":        await this.answer();        break;    }  }  async promptmodel(prompt) {    const result = await this.model.generatecontent(prompt);    const response = await result.response;    return response.text();  }  async thought() {    const availablefunctions = json.stringify(array.from(this.functions));    const historycontext = this.history.join("n");    const prompt = `your task to fullfill ${this.query}.context contains all the reflection you made so far and the actionresult you collected.availableactions are functions you can call whenever you need more data.context: "${historycontext}" <<availableactions: "${availablefunctions}" <<task: "${this.query}" <<reflect uppon your task using context, actionresult and availableactions to find your next_step.print your next_step with a thought or fullfill your task `;    const thought = await this.promptmodel(prompt);    this.pushhistory(`n **${thought.trim()}**`);    if (      thought.tolowercase().includes("fullfill") ||      thought.tolowercase().includes("fulfill")    ) {      this.state = "answer";      return await this.step();    }    this.state = "action";    return await this.step();  }  async action() {    const action = await this.decideaction();    this.pushhistory(`** action: ${action} **`);    const result = await this.executefunctioncall(action);    this.pushhistory(`** actionresult: ${result} **`);    this.state = "thought";    return await this.step();  }  async decideaction() {    const availablefunctions = json.stringify(array.from(this.functions));    const historycontext = this.history;    const prompt = `reflect uppon the thought, query and availableactions    ${historycontext[historycontext.length - 2]}    thought <<>>>>>>", finalanswer);    return finalanswer;  }}module.exports = reactagent;

4.4 运行代理(index.js)

使用以下内容创建index.js:

const ReActAgent = require("./ReactAgent.js");async function main() {  const query = "What does England border with?";  const functions = [    [      "wikipedia",      "params: query",      "Semantic Search Wikipedia API for snippets, pageIds and sectionIds >> n ex: Date brazil has been colonized? n Brazil was colonized at 1500, pageId, sections : []",    ],    [      "wikipedia_with_pageId",      "params : pageId, sectionId",      "Search Wikipedia API for data using a pageId and a sectionIndex as params.  n ex: 1500, 1234 n Section information about blablalbal",    ],  ];  const agent = new ReActAgent(query, functions);  try {    const result = await agent.run();    console.log("THE AGENT RETURN THE FOLLOWING >>>", result);  } catch (e) {    console.log("FAILED TO RUN T.T", e);  }}main().catch(console.error);

[5] 维基百科部分如何运作

与维基百科的交互主要分为两个步骤:

初始搜索(维基百科功能):

向维基百科搜索 api 发出请求。最多返回 4 个相关的查询结果。对于每个结果,它都会获取页面的各个部分。

详细搜索(wikipedia_with_pageid函数):

使用页面 id 和部分 id 来获取特定内容。返回请求部分的文本。

此过程允许代理首先获得与查询相关的主题的概述,然后根据需要深入研究特定部分。

[6] 执行流程示例

用户提出问题。智能体进入思考状态并反思问题。它决定搜索维基百科并进入 action 状态。执行wikipedia函数并获取结果。返回thought状态反思结果。可能决定搜索更多详细信息或不同的方法。根据需要重复思想和行动循环。当它有足够的信息时,它进入answer状态。根据收集到的所有信息生成最终答案。只要维基百科没有可收集的数据,就会进入无限循环。用计时器修复它=p

[7] 最后的考虑

模块化结构可以轻松添加新工具或 api。实施错误处理和时间/迭代限制非常重要,以避免无限循环或过度资源使用。使用温度:99999 哈哈

以上就是使用 nodeJS 从头开始​​创建 ReAct Agent(维基百科搜索)的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1491757.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月19日 14:14:15
下一篇 2025年12月19日 14:14:32

相关推荐

  • React 中高效实现数据过滤与排序的教程

    本教程旨在解决React应用中同时进行数据过滤和排序的常见挑战。通过避免useEffect中的无限循环、正确管理状态以及利用派生状态,我们将展示如何将数据获取、过滤和排序逻辑清晰地分离,从而实现高性能且可维护的数据处理流程。 在react应用中,当我们需要从后端获取数据,并根据用户交互(如筛选条件和…

    2025年12月20日
    000
  • JavaScript条件逻辑与函数返回值:修复“石头剪刀布”游戏中的常见错误

    本教程旨在解决JavaScript“石头剪刀布”游戏中常见的逻辑错误,特别是函数未返回预期值导致的问题,以及if-else语句中else条件分支的错误使用。通过纠正getPlayerChoice函数的返回值和优化条件判断结构,我们将确保游戏逻辑的正确执行,避免意外结果,并提升代码的健壮性与可读性。 …

    2025年12月20日
    000
  • JavaScript游戏开发:解决if/else逻辑与函数返回值陷阱

    本文将深入探讨JavaScript编程中常见的两个问题:函数返回值缺失和if/else语句的错误使用,并以一个剪刀石头布游戏为例,详细展示如何识别、理解并纠正这些逻辑缺陷。通过本文,读者将掌握如何确保函数正确返回期望值,以及如何规范地构建条件判断逻辑,从而编写出更健壮、可预测的JavaScript代…

    2025年12月20日
    000
  • 调试JavaScript条件逻辑:修复剪刀石头布游戏中的if/else语句错误

    本文深入探讨了JavaScript中if/else语句和函数返回值的常见错误,以一个剪刀石头布游戏为例,详细解析了getPlayerChoice函数缺少return语句导致变量undefined的问题,以及else语句语法不正确导致逻辑失效的现象。通过具体代码示例,教程将指导开发者如何正确编写函数返…

    2025年12月20日
    000
  • JavaScript剪刀石头布游戏中的条件逻辑与函数返回值陷阱解析

    本文深入探讨了在JavaScript开发剪刀石头布游戏时常见的两个逻辑错误:函数未返回预期值导致变量undefined,以及else语句中误加条件表达式。通过分析这些问题及其解决方案,教程旨在帮助开发者理解if-else条件链的正确用法和函数返回值的必要性,从而避免类似错误,提升代码的健壮性和可读性…

    2025年12月20日
    000
  • React-Redux组件状态访问与常见错误排查指南

    本文旨在解决React-Redux应用中常见的“Cannot read properties of undefined”和“state not found”错误。核心问题在于组件未正确连接到Redux store,导致无法访问全局状态,以及reducer中可能存在的拼写错误。通过示例代码,我们将详细…

    2025年12月20日
    000
  • Lingui.js 在 React 中 t 宏不生效的解决方案

    在使用 Lingui.js 进行 React 应用国际化时,t 宏有时无法直接在非订阅组件中进行翻译,而 组件则工作正常。核心原因在于 t 宏需要组件能够访问 Lingui 的 i18n 上下文。本文将详细介绍如何通过 useLingui 钩子或 msg(defineMessage)宏结合 i18n…

    2025年12月20日 好文分享
    000
  • 解决 LinguiJS t 宏在 React 应用中不生效的问题

    中的 t 宏却未能生效。这背后的核心原因在于 t 宏(或 msg 宏)的运行时行为与 React 组件的生命周期及上下文管理机制。 当您在 JSX 中直接使用 组件时,@lingui/react 包内部会处理语言上下文的订阅,确保组件在语言变化时重新渲染并显示正确的翻译。然而,t 宏在编译时会将模板…

    2025年12月20日
    000
  • LinguiJS t 宏在 React 组件中不生效的解决方案与最佳实践

    在 LinguiJS 中,t 宏在 React 组件中直接使用作为属性时可能无法正确翻译。这是因为 t 宏返回的是一个消息描述符(MessageDescriptor),而非立即翻译的字符串。要实现动态翻译,需要利用 useLingui 钩子获取 i18n 实例,并通过 i18n._() 方法将消息描…

    好文分享 2025年12月20日
    000
  • JavaScript 条件语句挑战:根据国家和时间问候

    本文旨在帮助开发者理解和解决一个常见的 JavaScript 条件语句挑战:根据国家和时间设置不同的问候语。通过分析问题代码中的逻辑错误,并提供两种修正后的代码示例,帮助读者掌握如何正确使用条件语句处理多重条件判断,从而编写出更健壮、可维护的代码。 问题分析 原始代码存在两个主要问题: 逻辑结构错误…

    2025年12月20日
    000
  • JavaScript 条件语句优化:打造健壮的基于国家和时间的问候语逻辑

    本文深入探讨了JavaScript中条件语句的常见陷阱与优化策略,通过一个基于国家和时间生成问候语的编程挑战,详细解析了逻辑或运算符的优先级问题和条件分支覆盖的错误。文章提供了两种结构清晰、易于维护的解决方案:嵌套的if-else if结构和switch语句,旨在帮助开发者编写更准确、更具可读性的条…

    2025年12月20日
    000
  • JavaScript条件逻辑精解:多维判断与常见陷阱规避

    本文深入探讨JavaScript中处理复杂多重条件判断的技巧,特别是在根据国家和时间生成不同问候语的场景中。文章分析了常见的逻辑错误,如操作符优先级误解和条件语句覆盖问题,并提供了嵌套if-else和switch语句的两种健壮解决方案,旨在帮助开发者编写更清晰、更可靠的条件逻辑代码。 复杂条件判断的…

    2025年12月20日
    000
  • JavaScript条件语句深度解析:避免常见陷阱与优化实践

    本文深入探讨JavaScript条件语句中常见的逻辑错误,特别是操作符优先级和不当的if-else结构如何导致意想不到的结果。通过分析实际案例,文章提供了两种有效的解决方案:优化嵌套if-else结构和利用switch语句,旨在帮助开发者编写更健壮、清晰且易于维护的条件逻辑代码。 在javascri…

    2025年12月20日
    000
  • JavaScript实现点击图片切换效果:专业教程

    本文将介绍如何使用JavaScript实现点击图片切换的效果。核心思路是利用HTML5的data-*属性存储备用图片路径,并通过JavaScript监听点击事件,动态切换src属性,从而实现图片切换。本文将提供详细的代码示例和解释,帮助你理解和掌握这种常用的交互效果。 HTML结构 首先,我们需要在…

    2025年12月20日
    000
  • JavaScript实现点击图片切换效果

    本文将详细介绍如何使用JavaScript实现点击图片切换的效果。通过利用HTML5的data-*属性存储备用图片路径,并结合JavaScript的事件监听和属性修改,可以轻松实现图片的动态切换。本文将提供完整的代码示例和详细的步骤说明,帮助开发者快速掌握该技巧。 实现原理 实现图片点击切换的核心在…

    2025年12月20日
    000
  • JavaScript实现点击图片切换:专业教程

    JavaScript实现点击图片切换:专业教程 本文旨在提供一个清晰易懂的JavaScript教程,讲解如何实现点击图片后切换图片的功能。我们将使用data-src属性来存储第二张图片的路径,并通过JavaScript代码实现图片的动态切换。本文包含完整的HTML和JavaScript代码示例,以及…

    2025年12月20日
    000
  • JavaScript字符串的智能空白符与换行符处理:实现精确的代码压缩

    本教程深入探讨如何在JavaScript字符串中精确控制空白符和换行符的替换。我们将介绍如何使用String.prototype.replace()方法结合回调函数,实现有条件的空白符移除和换行符转换为分号,以达到类似代码压缩的效果,同时避免破坏代码语法。这种方法比简单的全局替换更智能,能有效处理特…

    2025年12月20日
    000
  • JavaScript代码字符串格式化:智能替换空格与换行符的实践

    本文探讨在JavaScript中如何智能地替换代码字符串中的空格和换行符,以实现代码的紧凑化,同时避免破坏语法或可读性。通过一个自定义函数,结合正则表达式和回调函数,实现对换行符的条件性转换为分号,并保留关键字后的必要空格,从而生成一个既紧凑又功能正确的代码字符串。 引言:为何简单的替换不足以应对?…

    2025年12月20日
    000
  • JavaScript代码字符串的精细化处理:智能替换空格、换行与添加分号

    本教程探讨如何在JavaScript中对代码字符串进行智能格式化与压缩。针对移除不必要的空格和换行符,并根据上下文自动插入或保留分号与空格的需求,文章提供了一种基于正则表达式和上下文判断的解决方案。通过示例代码,详细演示了如何实现代码的精细化处理,使其在保持功能完整性的同时,达到更紧凑的输出效果。 …

    2025年12月20日
    000
  • JavaScript代码字符串的智能格式化与自定义压缩:处理空白符和换行符

    本教程探讨如何在JavaScript代码字符串中智能地处理空白符和换行符,以实现自定义的格式化或轻量级压缩。通过结合正则表达式和回调函数,我们将学习如何有选择地移除不必要的空格、将换行符转换为分号,并保留关键字间的必要空格,从而生成更紧凑但功能完整的代码字符串,避免简单全局替换导致的语法错误。 在j…

    2025年12月20日
    000

发表回复

登录后才能评论
关注微信