我们将创建一个能够搜索维基百科并根据收集到的信息回答问题的人工智能代理。
该 ReAct(推理和行动)代理使用 Google Generative AI API 来处理查询并生成响应。
我们的代理将能够:
ReAct Agent 是一种遵循反射-操作循环的特定类型的代理。它根据可用信息和可以采取的操作来反映当前任务,然后决定采取什么操作或是否完成任务。
我们的 ReAct Agent 将具有三个主要状态:
思考状态是ReactAgent对收集到的信息进行反思并决定下一步应该做什么的时刻。
async thought() { // ... }
在动作状态下,代理根据先前的想法执行可用功能之一。
请注意,有行动(执行)和决定(哪个行动)。
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 将用来执行对维基百科的 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_with_pageId函数):
此过程允许代理首先获得与查询相关的主题的概述,然后根据需要深入到特定部分。
以上是使用 Node.js 创建 ReAct AI 代理(维基百科搜索)en的详细内容。更多信息请关注PHP中文网其他相关文章!