Node.js로 ReAct AI 에이전트 생성(Wikipedia 검색)
Sep 25, 2024 am 06:22 AM소개
수집된 정보를 바탕으로 위키피디아를 검색하고 질문에 답할 수 있는 AI 에이전트를 만들어 보겠습니다.
이 ReAct(추론 및 행동) 에이전트는 Google Generative AI API를 사용하여 쿼리를 처리하고 응답을 생성합니다.
저희 에이전트는 다음을 수행할 수 있습니다.
- 위키피디아에서 관련 정보를 검색해 보세요.
- Wikipedia 페이지에서 특정 섹션을 추출합니다.
- 정보 수집 이유 및 답변 작성
[2] ReAct Agent란 무엇인가요?
ReAct Agent는 Reflection-Action 주기를 따르는 특정 유형의 에이전트입니다. 사용 가능한 정보와 수행할 수 있는 작업을 기반으로 현재 작업을 반영한 다음 수행할 작업이나 작업 완료 여부를 결정합니다.
[3] 에이전트 계획
3.1 필수 도구
- Node.js
- HTTP 요청용 Axios 라이브러리
- Google Generative AI API(gemini-1.5-flash)
- 위키피디아 API
3.2 에이전트 구조
ReAct 에이전트에는 세 가지 주요 상태가 있습니다.
- 생각(반성)
- ACTION(실행)
- ANSWER(답글)
3.3 생각의 상태
사고 상태는 ReactAgent가 수집된 정보를 반영하고 다음 단계가 무엇인지 결정하는 순간입니다.
async thought() { // ... }
3.4 액션 상태(ACTION)
액션 상태에서 에이전트는 이전 생각을 바탕으로 사용 가능한 기능 중 하나를 수행합니다.
행동(실행)과 결정(어느 행동)이 있는지 주목하세요.
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) }
[4] 에이전트 구현
각 상태를 강조하면서 ReAct Agent를 단계별로 구축해 보겠습니다.
4.1 초기 구성
먼저 프로젝트를 구성하고 종속성을 설치합니다.
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 키는 여기
4.2 역할 설명
이 파일은 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;
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: 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;
4.4 에이전트 실행 및 사용 가능한 도구 설명(index.js)
다음 콘텐츠로 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) ] ];
[5] Wikipedia 부분의 작동 방식
Wikipedia와의 상호작용은 두 가지 주요 단계로 이루어집니다.
-
초기 검색(위키피디아 기능):
- Wikipedia 검색 API에 요청합니다.
- 검색어와 관련된 최대 4개의 결과를 반환합니다.
- 각 결과에 대해 페이지 섹션을 검색하세요.
-
상세 검색(wikipedia_with_pageId 기능):
- 페이지 ID와 섹션 ID를 사용하여 특정 콘텐츠를 검색합니다.
- 요청된 섹션의 텍스트를 반환합니다.
이 프로세스를 통해 상담원은 먼저 검색어와 관련된 주제의 개요를 확인한 다음 필요에 따라 특정 섹션으로 드릴다운할 수 있습니다.
[6] 실행 흐름 예시
- 사용자가 질문을 합니다.
- 에이전트가 THOUGHT 상태로 들어가 질문에 대해 반성합니다.
- 위키피디아를 검색하기로 하고 ACTION 상태로 들어갑니다.
- 위키피디아 기능을 실행하고 결과를 얻습니다.
- 결과를 반영하기 위해 THOUGHT 상태로 돌아갑니다.
- 더 자세한 내용을 찾아보거나 다른 접근 방식을 찾아볼 수도 있습니다.
- 필요에 따라 생각과 행동 주기를 반복하세요.
- 충분한 정보가 있으면 ANSWER 상태로 들어갑니다.
- 수집된 모든 정보를 바탕으로 최종 응답을 생성합니다.
- Wikipedia에 수집할 데이터가 없을 때마다 무한 루프에 들어갑니다. 타이머 =P로 이 문제를 해결하세요
[7] 최종 고려 사항
- 모듈형 구조를 통해 새로운 도구나 API를 쉽게 추가할 수 있습니다.
- 무한 루프나 과도한 리소스 사용을 방지하려면 오류 처리 및 시간/반복 제한을 구현하는 것이 중요합니다.
- 이 예에서는 온도 2를 사용합니다. 온도가 낮을수록 반복 중에 에이전트의 창의성이 떨어집니다. 온도가 LLM에 미치는 영향을 이해하기 위한 실험입니다.
위 내용은 Node.js로 ReAct AI 에이전트 생성(Wikipedia 검색)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

인기 기사

인기 기사

뜨거운 기사 태그

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









