rag.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /**
  2. * Módulo RAG (Retrieval-Augmented Generation)
  3. *
  4. * Este módulo integra a busca por documentos similares com a geração de respostas
  5. * Ele importa as funções da pasta rag e as adapta para uso na API
  6. */
  7. // URL da nova API de embeddings
  8. const EMBEDDINGS_API_URL = process.env.EMBEDDINGS_API_URL || 'http://localhost:3402/api/embeddings';
  9. console.log(`[API::rag.ts]Usando EMBEDDINGS_API_URL: ${EMBEDDINGS_API_URL}`);
  10. /**
  11. * Interface para os resultados da busca
  12. */
  13. interface ResultadoBusca {
  14. nome: string;
  15. conteudo: string;
  16. similaridade: number;
  17. }
  18. /**
  19. * Interface para o resultado da busca com contexto
  20. */
  21. interface ResultadoBuscaComContexto {
  22. contexto: string;
  23. resultados: ResultadoBusca[];
  24. }
  25. /**
  26. * Interface para a resposta da API de embeddings
  27. */
  28. interface ApiEmbeddingsResponse {
  29. contexto: string;
  30. resultados: Array<{
  31. documento: {
  32. nome: string;
  33. caminho: string;
  34. conteudo: string;
  35. tamanho: number;
  36. embedding: number[];
  37. };
  38. similaridade: number;
  39. }>;
  40. }
  41. /**
  42. * Interface para a requisição da API de embeddings
  43. */
  44. interface ApiEmbeddingsRequest {
  45. prompt: string;
  46. topK: number;
  47. limiarSimilaridade: number;
  48. }
  49. /**
  50. * Chama a API de embeddings para buscar documentos similares
  51. */
  52. async function chamarApiEmbeddings(
  53. prompt: string,
  54. topK: number = 2,
  55. limiarSimilaridade: number = 0.3
  56. ): Promise<ApiEmbeddingsResponse> {
  57. console.log('Chamando API de embeddings...');
  58. try {
  59. const requestBody: ApiEmbeddingsRequest = {
  60. prompt,
  61. topK,
  62. limiarSimilaridade
  63. };
  64. const response = await fetch(EMBEDDINGS_API_URL, {
  65. method: 'POST',
  66. headers: {
  67. 'Content-Type': 'application/json',
  68. },
  69. body: JSON.stringify(requestBody)
  70. });
  71. if (!response.ok) {
  72. throw new Error(`API de embeddings retornou status ${response.status}`);
  73. }
  74. const data = await response.json() as ApiEmbeddingsResponse;
  75. return data;
  76. } catch (erro) {
  77. console.error('Erro ao chamar API de embeddings:', erro);
  78. throw new Error('Falha na comunicação com a API de embeddings');
  79. }
  80. }
  81. /**
  82. * Busca documentos similares no banco de dados
  83. *
  84. * Esta função é otimizada para uso na API:
  85. * - Logs menos verbosos (para produção)
  86. * - Retorna dados simplificados
  87. * - Usa a nova API de embeddings
  88. *
  89. * @param pergunta - A pergunta do usuário
  90. * @param topK - Quantos documentos retornar (padrão: 2)
  91. * @param limiarSimilaridade - Similaridade mínima (padrão: 0.3)
  92. * @returns Objeto com contexto formatado e array com os documentos mais similares
  93. */
  94. async function buscarContexto(
  95. pergunta: string,
  96. topK: number = 2,
  97. limiarSimilaridade: number = 0.3
  98. ): Promise<ResultadoBuscaComContexto> {
  99. try {
  100. // Chama a API de embeddings
  101. const respostaApi = await chamarApiEmbeddings(pergunta, topK, limiarSimilaridade);
  102. // Mapeia os resultados para o formato esperado
  103. const resultados: ResultadoBusca[] = respostaApi.resultados.map(resultado => ({
  104. nome: resultado.documento.nome,
  105. conteudo: resultado.documento.conteudo,
  106. similaridade: resultado.similaridade
  107. }));
  108. return {
  109. contexto: respostaApi.contexto,
  110. resultados
  111. };
  112. } catch (erro) {
  113. console.error('Erro ao buscar contexto:', erro);
  114. // Em caso de erro, retorna objeto vazio
  115. return {
  116. contexto: '',
  117. resultados: []
  118. };
  119. }
  120. }
  121. /**
  122. * Monta um prompt enriquecido com contexto RAG
  123. *
  124. * Esta é a função principal que integra tudo:
  125. * 1. Busca documentos relevantes usando a nova API
  126. * 2. Retorna o contexto formatado da API
  127. *
  128. * Por que usar a API?
  129. * - Centraliza a lógica de busca e formatação
  130. * - Reduz código duplicado
  131. * - Melhora a manutenibilidade
  132. *
  133. * @param pergunta - A pergunta do usuário
  134. * @param topK - Quantos documentos usar (padrão: 2)
  135. * @param limiarSimilaridade - Similaridade mínima (padrão: 0.3)
  136. * @returns Prompt formatado com contexto
  137. */
  138. async function montarPromptComRAG(
  139. pergunta: string,
  140. topK: number = 2,
  141. limiarSimilaridade: number = 0.3
  142. ): Promise<string> {
  143. try {
  144. // Chama a API de embeddings
  145. const respostaApi = await chamarApiEmbeddings(pergunta, topK, limiarSimilaridade);
  146. // Retorna o contexto formatado diretamente da API
  147. return respostaApi.contexto;
  148. } catch (erro) {
  149. console.error('Erro ao montar prompt com RAG:', erro);
  150. // Em caso de erro, retorna apenas a pergunta
  151. return pergunta;
  152. }
  153. }
  154. // Exporta as funções para serem usadas na API
  155. export {
  156. buscarContexto,
  157. montarPromptComRAG,
  158. type ResultadoBusca,
  159. type ResultadoBuscaComContexto
  160. };