ウィキペディアを検索し、収集した情報に基づいて質問に答えることができる AI エージェントを作成します。
この ReAct (推論とアクション) エージェントは、Google Generative AI API を使用してクエリを処理し、応答を生成します。
当社のエージェントは次のことができます:
ReAct Agent は、Reflection-Action サイクルに従う特定のタイプのエージェントです。入手可能な情報と実行可能なアクションに基づいて現在のタスクを反映し、実行するアクション、またはタスクを完了するかどうかを決定します。
ReAct Agent には 3 つの主な状態があります:
思考状態とは、ReactAgent が収集した情報を反映し、次のステップをどうすべきかを決定する瞬間です。
async thought() { // ... }
アクション状態では、エージェントは前の思考に基づいて利用可能な機能の 1 つを実行します。
アクション (実行) と決定 (どのアクション) があることに注意してください。
async action() { // chama a decisão // executa a ação e retorna um ActionResult } async decideAction() { // Chama o LLM com base no Pensamento (reflexão) para formatar e adequar a chamada de função. // Procure por um modo de função-ferramenta na [documentação da API do Google](https://ai.google.dev/gemini-api/docs/function-calling) }
各状態を強調表示しながら、ReAct Agent を段階的に構築してみましょう。
まず、プロジェクトを構成し、依存関係をインストールします。
mkdir projeto-agente-react cd projeto-agente-react npm init -y npm install axios dotenv @google/generative-ai
プロジェクトのルートに .env ファイルを作成します:
GOOGLE_AI_API_KEY=sua_chave_api_aqui
無料 API キーはこちら
このファイルは、Node.js が Wikipedia への API 呼び出しを実行するために使用する JavaScript ファイルです。
このファイルの内容は FunctionDescription で説明します。
次の内容を含む Tools.js を作成します:
const axios = require("axios"); class Tools { static async wikipedia(q) { try { const response = await axios.get("https://pt.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://pt.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://pt.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://pt.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;
次の内容で 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: 1.8, }); } async run() { this.pushHistory(`**Tarefa: ${this.query} **`); try { return await this.step(); } catch (e) { console.error("Erro durante a execução:", e); return "Desculpe, não consegui processar sua solicitação."; } } 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": return await this.thought(); break; case "ACTION": return await this.action(); break; case "ANSWER": return await this.answer(); } } async thought() { const funcoesDisponiveis = JSON.stringify(Array.from(this.functions)); const contextoHistorico = this.history.join("\n"); const prompt = `Sua Tarefa é ${this.consulta} O Contexto posui todas as reflexões que você fez até agora e os ResultadoAção que coletou. AçõesDisponíveis são funções que você pode chamar sempre que precisar de mais dados. Contexto: "${contextoHistorico}" << AçõesDisponíveis: "${funcoesDisponiveis}" << Tarefa: "${this.consulta}" << Reflita sobre Sua Tarefa usando o Contexto, ResultadoAção e AçõesDisponíveis para encontrar seu próximo_passo. Imprima seu próximo_passo com um Pensamento ou Finalize Cumprindo Sua Tarefa caso tenha as informações disponíveis`; const thought = await this.promptModel(prompt); this.pushHistory(`\n **${thought.trim()}**`); if ( thought.toLowerCase().includes("cumprida") || thought.toLowerCase().includes("cumpra") || thought.toLowerCase().includes("cumprindo") || thought.toLowerCase().includes("finalizar") || thought.toLowerCase().includes("finalizando") || thought.toLowerCase().includes("finalize") || thought.toLowerCase().includes("concluída") ) { this.state = "ANSWER"; } else { this.state = "ACTION"; } return this.step(); } async action() { const action = await this.decideAction(); this.pushHistory(`** Ação: ${action} **`); const result = await this.executeFunctionCall(action); this.pushHistory(`** ResultadoAção: ${result} **`); this.state = "THOUGHT"; return this.step(); } async decideAction() { const availableFunctions = JSON.stringify(Array.from(this.functions)); const historyContext = this.history; const prompt = `Reflita sobre o Pensamento, Consulta e Ações Disponíveis ${historyContext[historyContext.length - 2]} Pensamento <<< ${historyContext[historyContext.length - 1]} Consulta: "${this.query}" Ações Disponíveis: ${availableFunctions} Retorne apenas a função,parâmetros separados por vírgula. Exemplo: "wikipedia,ronaldinho gaucho,1450"`; const decision = await this.promptModel(prompt); return decision.replace(/`/g, "").trim(); } async answer() { const historyContext = this.history.join("\n"); const prompt = `Com base no seguinte contexto, forneça uma resposta completa e detalhada para a tarefa: ${this.query}. Contexto: ${historyContext} Tarefa: "${this.query}"`; const finalAnswer = await this.promptModel(prompt); return finalAnswer; } async promptModel(prompt) { const result = await this.model.generateContent(prompt); const response = await result.response; return response.text(); } async executeFunctionCall(functionCall) { const [functionName, ...args] = functionCall.split(","); const func = Tools[functionName.trim()]; if (func) { return await func.call(null, ...args); } throw new Error(`Função ${functionName} não encontrada`); } pushHistory(value) { this._history.push(value); } get history() { return this._history; } } module.exports = ReactAgent;
次の内容でindex.jsを作成します:
const ReactAgent = require("./ReactAgentPTBR.js"); async function main() { const query = "Que clubes ronaldinho gaúcho jogou para?"; // const query = "Quais os bairros de Joinville?"; // const query = "Qual a capital da frança?"; const functions = [ [ "wikipedia", "params: query", "Busca semântica na Wikipedia API por pageId e sectionIds >> \n ex: Pontos turísticos de são paulo \n São Paulo é uma cidade com muitos pontos turísticos, pageId, sections : []", ], [ "wikipedia_with_pageId", "params: pageId, sectionId", "Busca na Wikipedia API usando pageId e sectionIndex como parametros. \n ex: 1500,1234 \n Informações sobre a seção blablalbal", ], ]; const agent = new ReactAgent(query, functions); const result = await agent.run(); console.log("Resultado do Agente:", result); } main().catch(console.error);
新しいツールや機能を追加する場合は、必ずそれをよく説明してください。
この例では、これはすでに行われており、新しいインスタンスを呼び出すときに ReActAgent クラスに追加されています。
const functions = [ [ "google", // nomeDaFuncao "params: query", // NomeDoParâmetroLocal "Pesquisa semântica na API da Wikipedia por snippets, pageIds e sectionIds >> \n ex: Quando o Brasil foi colonizado? \n O Brasil foi colonizado em 1500, pageId, sections : []", // breve explicação e exemplo (isso será encaminhado para o LLM) ] ];
Wikipedia との対話は 2 つの主な手順で行われます:
初期検索 (wikipedia 機能):
詳細検索 (wikipedia_with_pageId 関数):
このプロセスにより、エージェントはまずクエリに関連するトピックの概要を取得し、必要に応じて特定のセクションにドリルダウンできます。
以上がNode.js を使用した ReAct AI エージェントの作成 (Wikipedia 検索)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。