使用 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-project cd react-agent-project npm init -y npm 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("\n\n"); } 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. ><"; } return "Unable to process your request, please try again? ><"; } } 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 <<< ${historyContext[historyContext.length - 1]} Query: "${this.query}" AvailableActions: ${availableFunctions} output only the function,parametervalues separated by a comma. For example: "wikipedia,ronaldinho gaucho, 1450"`; const decision = await this.promptModel(prompt); return `${decision.replace(/`/g, "").trim()}`; } async executeFunctionCall(functionCall) { const [functionName, ...args] = functionCall.split(","); const func = Tools[functionName.trim()]; if (func) { return await func.call(null, ...args); } throw new Error(`Function ${functionName} not found`); } async answer() { const historyContext = this.history; const prompt = `Based on the following context, provide a complete, detailed and descriptive formated answer for the Following Task: ${this.query} . Context: ${historyContext} Task: "${this.query}"`; const finalAnswer = await this.promptModel(prompt); this.history.push(`Answer: ${this.finalAnswer}`); console.log("WE WILL ANSWER >>>>>>>", 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(維基百科搜尋)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。
