luanpoppe commited on
Commit
dc376b6
·
1 Parent(s): 9ef64c5

feat: refatorações e melhorias gerais

Browse files
_utils/LLMs/LLM_class.py CHANGED
@@ -1,6 +1,4 @@
1
- # from langchain_openai import OpenAI
2
  from typing import cast
3
- from openai import OpenAI
4
  from pydantic import SecretStr
5
  from setup.environment import default_model
6
  from setup.easy_imports import ChatOpenAI, ChatGoogleGenerativeAI
@@ -17,17 +15,17 @@ class LLM:
17
  # def create_GPT_model(self, model=default_model):
18
  # return ChatOpen()
19
 
20
- def deepseek(self):
21
  return ChatOpenAI(
22
  api_key=SecretStr(deepseek_api_key),
23
  base_url="https://api.deepseek.com/v1",
24
- model="deepseek-chat",
25
  )
26
 
27
- def googleGemini(self):
28
  return ChatGoogleGenerativeAI(
29
  api_key=SecretStr(google_api_key),
30
- model="gemini-1.5-flash",
31
  temperature=0,
32
  max_tokens=None,
33
  timeout=None,
 
 
1
  from typing import cast
 
2
  from pydantic import SecretStr
3
  from setup.environment import default_model
4
  from setup.easy_imports import ChatOpenAI, ChatGoogleGenerativeAI
 
15
  # def create_GPT_model(self, model=default_model):
16
  # return ChatOpen()
17
 
18
+ def deepseek(self, model="deepseek-chat"):
19
  return ChatOpenAI(
20
  api_key=SecretStr(deepseek_api_key),
21
  base_url="https://api.deepseek.com/v1",
22
+ model=model,
23
  )
24
 
25
+ def google_gemini(self, model="gemini-1.5-flash"):
26
  return ChatGoogleGenerativeAI(
27
  api_key=SecretStr(google_api_key),
28
+ model=model,
29
  temperature=0,
30
  max_tokens=None,
31
  timeout=None,
_utils/gerar_relatorio_modelo_usuario/{EnhancedDocumentSummarizer.py → GerarDocumento.py} RENAMED
@@ -10,23 +10,23 @@ from setup.easy_imports import (
10
  PromptTemplate,
11
  BM25Okapi,
12
  Response,
 
13
  )
14
  import logging
15
- import requests
16
  from _utils.gerar_relatorio_modelo_usuario.DocumentSummarizer_simples import (
17
  DocumentSummarizer,
18
  )
19
  from _utils.models.gerar_relatorio import (
20
  RetrievalConfig,
21
  )
22
- from modelos_usuarios.serializer import ModeloUsuarioSerializer
23
- from setup.environment import api_url
24
 
25
- from asgiref.sync import sync_to_async
26
 
27
-
28
- class EnhancedDocumentSummarizer(DocumentSummarizer):
29
  openai_api_key = os.environ.get("OPENAI_API_KEY", "")
 
 
30
 
31
  def __init__(
32
  self,
@@ -43,15 +43,6 @@ class EnhancedDocumentSummarizer(DocumentSummarizer):
43
  prompt_gerar_documento,
44
  reciprocal_rank_fusion,
45
  ):
46
- super().__init__(
47
- self.openai_api_key,
48
- os.environ.get("COHERE_API_KEY", ""),
49
- embedding_model,
50
- chunk_size,
51
- chunk_overlap,
52
- num_k_rerank,
53
- model_cohere_rerank,
54
- )
55
  self.config = config
56
  self.logger = logging.getLogger(__name__)
57
  self.prompt_auxiliar = prompt_auxiliar
@@ -59,7 +50,13 @@ class EnhancedDocumentSummarizer(DocumentSummarizer):
59
  self.gpt_temperature = gpt_temperature
60
  self.prompt_gerar_documento = prompt_gerar_documento
61
  self.reciprocal_rank_fusion = reciprocal_rank_fusion
62
- self.resumo_gerado = ""
 
 
 
 
 
 
63
 
64
  self.vector_store = VectorStore(embedding_model)
65
 
@@ -114,56 +111,73 @@ class EnhancedDocumentSummarizer(DocumentSummarizer):
114
  self.logger.error(f"Error in rank fusion retrieval: {str(e)}")
115
  raise
116
 
117
- async def generate_enhanced_summary(
118
  self,
119
  vector_store: Chroma,
120
  bm25: BM25Okapi,
121
  chunk_ids: List[str],
122
- llm_ultimas_requests: str,
123
  query: str = "Summarize the main points of this document",
124
- ) -> List[Dict]:
125
- """Generate enhanced summary using both vector and BM25 retrieval"""
126
- try:
127
- # Get combined results using rank fusion
128
- ranked_results = self.retrieve_with_rank_fusion(
129
- vector_store, bm25, chunk_ids, query
 
 
 
 
 
 
 
 
130
  )
131
 
132
- # Prepare context and track sources
133
- contexts = []
134
- sources = []
135
 
136
- # Get full documents for top results
137
- for chunk_id, score in ranked_results[: self.config.num_chunks]:
138
- results = vector_store.get(
139
- where={"chunk_id": chunk_id}, include=["documents", "metadatas"]
 
 
 
 
 
140
  )
141
 
142
- if results["documents"]:
143
- context = results["documents"][0]
144
- metadata = results["metadatas"][0]
145
-
146
- contexts.append(context)
147
- sources.append(
148
- {
149
- "content": context,
150
- "page": metadata["page"],
151
- "chunk_id": chunk_id,
152
- "relevance_score": score,
153
- "context": metadata.get("context", ""),
154
- }
155
- )
156
 
157
- if llm_ultimas_requests == "gpt-4o-mini":
158
- llm = ChatOpenAI(
159
- temperature=self.gpt_temperature,
160
- model=self.gpt_model,
161
- api_key=SecretStr(self.openai_api_key),
162
- )
163
- elif llm_ultimas_requests == "deepseek-chat":
164
- llm_instance = LLM()
165
- llm = llm_instance.deepseek()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
 
167
  prompt_auxiliar = PromptTemplate(
168
  template=self.prompt_auxiliar, input_variables=["context"]
169
  )
@@ -176,21 +190,23 @@ class EnhancedDocumentSummarizer(DocumentSummarizer):
176
 
177
  prompt_gerar_documento = PromptTemplate(
178
  template=self.prompt_gerar_documento,
179
- input_variables=["context"],
180
  )
181
 
182
- documento_gerado = cast(
183
  str,
184
  llm.invoke(
185
  prompt_gerar_documento.format(
186
- context=self.resumo_gerado,
187
- # modelo_usuario=serializer.data["modelo"],
188
  )
189
  ).content,
190
  )
191
 
192
  # Split the response into paragraphs
193
- summaries = [p.strip() for p in documento_gerado.split("\n\n") if p.strip()]
 
 
194
 
195
  # Create structured output
196
  structured_output = []
 
10
  PromptTemplate,
11
  BM25Okapi,
12
  Response,
13
+ HuggingFaceEmbeddings,
14
  )
15
  import logging
 
16
  from _utils.gerar_relatorio_modelo_usuario.DocumentSummarizer_simples import (
17
  DocumentSummarizer,
18
  )
19
  from _utils.models.gerar_relatorio import (
20
  RetrievalConfig,
21
  )
22
+ from cohere import Client
23
+ from _utils.splitters.Splitter_class import Splitter
24
 
 
25
 
26
+ class GerarDocumento:
 
27
  openai_api_key = os.environ.get("OPENAI_API_KEY", "")
28
+ cohere_api_key = os.environ.get("COHERE_API_KEY", "")
29
+ resumo_gerado = ""
30
 
31
  def __init__(
32
  self,
 
43
  prompt_gerar_documento,
44
  reciprocal_rank_fusion,
45
  ):
 
 
 
 
 
 
 
 
 
46
  self.config = config
47
  self.logger = logging.getLogger(__name__)
48
  self.prompt_auxiliar = prompt_auxiliar
 
50
  self.gpt_temperature = gpt_temperature
51
  self.prompt_gerar_documento = prompt_gerar_documento
52
  self.reciprocal_rank_fusion = reciprocal_rank_fusion
53
+
54
+ self.openai_api_key = self.openai_api_key
55
+ self.cohere_client = Client(self.cohere_api_key)
56
+ self.embeddings = HuggingFaceEmbeddings(model_name=embedding_model)
57
+ self.num_k_rerank = num_k_rerank
58
+ self.model_cohere_rerank = model_cohere_rerank
59
+ self.splitter = Splitter(chunk_size, chunk_overlap)
60
 
61
  self.vector_store = VectorStore(embedding_model)
62
 
 
111
  self.logger.error(f"Error in rank fusion retrieval: {str(e)}")
112
  raise
113
 
114
+ def rank_fusion_get_top_results(
115
  self,
116
  vector_store: Chroma,
117
  bm25: BM25Okapi,
118
  chunk_ids: List[str],
 
119
  query: str = "Summarize the main points of this document",
120
+ ):
121
+ # Get combined results using rank fusion
122
+ ranked_results = self.retrieve_with_rank_fusion(
123
+ vector_store, bm25, chunk_ids, query
124
+ )
125
+
126
+ # Prepare context and track sources
127
+ contexts = []
128
+ sources = []
129
+
130
+ # Get full documents for top results
131
+ for chunk_id, score in ranked_results[: self.config.num_chunks]:
132
+ results = vector_store.get(
133
+ where={"chunk_id": chunk_id}, include=["documents", "metadatas"]
134
  )
135
 
136
+ if results["documents"]:
137
+ context = results["documents"][0]
138
+ metadata = results["metadatas"][0]
139
 
140
+ contexts.append(context)
141
+ sources.append(
142
+ {
143
+ "content": context,
144
+ "page": metadata["page"],
145
+ "chunk_id": chunk_id,
146
+ "relevance_score": score,
147
+ "context": metadata.get("context", ""),
148
+ }
149
  )
150
 
151
+ return sources, contexts
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
+ def select_model_for_last_requests(self, llm_ultimas_requests: str):
154
+ llm_instance = LLM()
155
+ if llm_ultimas_requests == "gpt-4o-mini":
156
+ llm = ChatOpenAI(
157
+ temperature=self.gpt_temperature,
158
+ model=self.gpt_model,
159
+ api_key=SecretStr(self.openai_api_key),
160
+ )
161
+ elif llm_ultimas_requests == "deepseek-chat":
162
+ llm = llm_instance.deepseek()
163
+ elif llm_ultimas_requests == "gemini-2.0-flash":
164
+ llm = llm_instance.google_gemini("gemini-2.0-flash")
165
+ return llm
166
+
167
+ async def gerar_documento_final(
168
+ self,
169
+ vector_store: Chroma,
170
+ bm25: BM25Okapi,
171
+ chunk_ids: List[str],
172
+ llm_ultimas_requests: str,
173
+ query: str = "Summarize the main points of this document",
174
+ ) -> List[Dict]:
175
+ try:
176
+ sources, contexts = self.rank_fusion_get_top_results(
177
+ vector_store, bm25, chunk_ids, query
178
+ )
179
 
180
+ llm = self.select_model_for_last_requests(llm_ultimas_requests)
181
  prompt_auxiliar = PromptTemplate(
182
  template=self.prompt_auxiliar, input_variables=["context"]
183
  )
 
190
 
191
  prompt_gerar_documento = PromptTemplate(
192
  template=self.prompt_gerar_documento,
193
+ input_variables=["documento_gerado", "context"],
194
  )
195
 
196
+ documento_gerado_final = cast(
197
  str,
198
  llm.invoke(
199
  prompt_gerar_documento.format(
200
+ documento_gerado=self.resumo_gerado,
201
+ context="\n\n".join(contexts),
202
  )
203
  ).content,
204
  )
205
 
206
  # Split the response into paragraphs
207
+ summaries = [
208
+ p.strip() for p in documento_gerado_final.split("\n\n") if p.strip()
209
+ ]
210
 
211
  # Create structured output
212
  structured_output = []
_utils/gerar_relatorio_modelo_usuario/utils.py CHANGED
@@ -82,7 +82,7 @@ async def get_response_from_auxiliar_contextual_prompt(full_text_as_array: List[
82
  # )
83
 
84
  llms = LLM()
85
- response_auxiliar_summary = await llms.googleGemini().ainvoke(
86
  [HumanMessage(content=prompt_auxiliar_summary)]
87
  )
88
 
 
82
  # )
83
 
84
  llms = LLM()
85
+ response_auxiliar_summary = await llms.google_gemini().ainvoke(
86
  [HumanMessage(content=prompt_auxiliar_summary)]
87
  )
88
 
_utils/ragas.py CHANGED
@@ -1,6 +1,6 @@
1
  import os
2
  from langchain_community.document_loaders import PyPDFLoader
3
- from _utils.resumo_completo_cursor import EnhancedDocumentSummarizer, RetrievalConfig
4
  from rest_framework.response import Response
5
  from ragas import evaluate
6
 
@@ -13,7 +13,7 @@ from langchain.memory import SimpleMemory
13
 
14
  def test_ragas(serializer, listaPDFs):
15
 
16
- # Step 2: Setup RetrievalConfig and EnhancedDocumentSummarizer
17
  config = RetrievalConfig(
18
  num_chunks=serializer["num_chunks_retrieval"],
19
  embedding_weight=serializer["embedding_weight"],
@@ -22,7 +22,7 @@ def test_ragas(serializer, listaPDFs):
22
  chunk_overlap=serializer["chunk_overlap"],
23
  )
24
 
25
- summarizer = EnhancedDocumentSummarizer(
26
  openai_api_key=os.environ.get("OPENAI_API_KEY"),
27
  claude_api_key=os.environ.get("CLAUDE_API_KEY"),
28
  config=config,
@@ -74,7 +74,7 @@ def test_ragas(serializer, listaPDFs):
74
 
75
  def generate_summary(vector_store, bm25, chunk_ids, query, summarizer):
76
  """Generates an enhanced summary using the vector store and BM25 index."""
77
- structured_summaries = summarizer.generate_enhanced_summary(
78
  vector_store, bm25, chunk_ids, query
79
  )
80
  return {"structured_summaries": structured_summaries}
 
1
  import os
2
  from langchain_community.document_loaders import PyPDFLoader
3
+ from _utils.resumo_completo_cursor import GerarDocumento, RetrievalConfig
4
  from rest_framework.response import Response
5
  from ragas import evaluate
6
 
 
13
 
14
  def test_ragas(serializer, listaPDFs):
15
 
16
+ # Step 2: Setup RetrievalConfig and GerarDocumento
17
  config = RetrievalConfig(
18
  num_chunks=serializer["num_chunks_retrieval"],
19
  embedding_weight=serializer["embedding_weight"],
 
22
  chunk_overlap=serializer["chunk_overlap"],
23
  )
24
 
25
+ summarizer = GerarDocumento(
26
  openai_api_key=os.environ.get("OPENAI_API_KEY"),
27
  claude_api_key=os.environ.get("CLAUDE_API_KEY"),
28
  config=config,
 
74
 
75
  def generate_summary(vector_store, bm25, chunk_ids, query, summarizer):
76
  """Generates an enhanced summary using the vector store and BM25 index."""
77
+ structured_summaries = summarizer.gerar_documento_final(
78
  vector_store, bm25, chunk_ids, query
79
  )
80
  return {"structured_summaries": structured_summaries}
_utils/resumo_completo_cursor.py CHANGED
@@ -1,7 +1,7 @@
1
  import os
2
  from _utils.gerar_relatorio_modelo_usuario.prompts import prompt_auxiliar_SEM_CONTEXT
3
- from _utils.gerar_relatorio_modelo_usuario.EnhancedDocumentSummarizer import (
4
- EnhancedDocumentSummarizer,
5
  )
6
  from _utils.gerar_relatorio_modelo_usuario.contextual_retriever import (
7
  ContextualRetriever,
@@ -59,7 +59,7 @@ async def get_llm_summary_answer_by_cursor_complete(
59
  )
60
 
61
  # Initialize enhanced summarizer
62
- summarizer = EnhancedDocumentSummarizer(
63
  config=config,
64
  embedding_model=serializer["hf_embedding"],
65
  chunk_overlap=serializer["chunk_overlap"],
@@ -100,7 +100,7 @@ async def get_llm_summary_answer_by_cursor_complete(
100
 
101
  llm_ultimas_requests = serializer["llm_ultimas_requests"]
102
  # Generate enhanced summary
103
- structured_summaries = await summarizer.generate_enhanced_summary(
104
  vector_store, bm25, chunk_ids, llm_ultimas_requests, prompt_auxiliar_SEM_CONTEXT
105
  )
106
 
 
1
  import os
2
  from _utils.gerar_relatorio_modelo_usuario.prompts import prompt_auxiliar_SEM_CONTEXT
3
+ from _utils.gerar_relatorio_modelo_usuario.GerarDocumento import (
4
+ GerarDocumento,
5
  )
6
  from _utils.gerar_relatorio_modelo_usuario.contextual_retriever import (
7
  ContextualRetriever,
 
59
  )
60
 
61
  # Initialize enhanced summarizer
62
+ summarizer = GerarDocumento(
63
  config=config,
64
  embedding_model=serializer["hf_embedding"],
65
  chunk_overlap=serializer["chunk_overlap"],
 
100
 
101
  llm_ultimas_requests = serializer["llm_ultimas_requests"]
102
  # Generate enhanced summary
103
+ structured_summaries = await summarizer.gerar_documento_final(
104
  vector_store, bm25, chunk_ids, llm_ultimas_requests, prompt_auxiliar_SEM_CONTEXT
105
  )
106
 
gerar_documento/serializer.py CHANGED
@@ -46,7 +46,9 @@ class GerarDocumentoSerializer(ResumoCursorSerializer):
46
  id_modelo_do_usuario = serializers.IntegerField(required=False)
47
  should_have_contextual_chunks = serializers.BooleanField(default=False) # type: ignore
48
  should_use_llama_parse = serializers.BooleanField(required=False, default=False) # type: ignore
49
- llm_ultimas_requests = serializers.CharField(required=False, default="gpt-4o-mini")
 
 
50
 
51
 
52
  class GerarDocumentoComPDFProprioSerializer(ResumoCursorSerializer):
 
46
  id_modelo_do_usuario = serializers.IntegerField(required=False)
47
  should_have_contextual_chunks = serializers.BooleanField(default=False) # type: ignore
48
  should_use_llama_parse = serializers.BooleanField(required=False, default=False) # type: ignore
49
+ llm_ultimas_requests = serializers.CharField(
50
+ required=False, default="gemini-2.0-flash"
51
+ )
52
 
53
 
54
  class GerarDocumentoComPDFProprioSerializer(ResumoCursorSerializer):
tests/LLMs/test_LLM_class.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ import os
3
+ from _utils.LLMs.LLM_class import LLM
4
+ from _utils.splitters.Splitter_class import Splitter
5
+ from _utils.models.gerar_relatorio import (
6
+ DocumentChunk,
7
+ )
8
+
9
+
10
+ class TestSplitters:
11
+ llm = LLM()
12
+
13
+ @pytest.mark.asyncio
14
+ async def test_google_gemini_modelo_padrao(self, monkeypatch):
15
+ gemini = self.llm.google_gemini()
16
+ result = gemini.invoke("Qual a capital do Brasil?").content
17
+
18
+ assert isinstance(result, str)
19
+ assert len(result) > 0
20
+
21
+ @pytest.mark.asyncio
22
+ async def test_google_gemini_modelo_flash_2(self, monkeypatch):
23
+ gemini = self.llm.google_gemini("gemini-2.0-flash")
24
+ result = gemini.invoke("Qual a capital do Brasil?").content
25
+
26
+ assert isinstance(result, str)
27
+ assert len(result) > 0
28
+
29
+ @pytest.mark.asyncio
30
+ async def test_deepseek_modelo_padrao(self, monkeypatch):
31
+ deepseek = self.llm.deepseek()
32
+ result = deepseek.invoke("Qual a capital do Brasil?").content
33
+
34
+ assert isinstance(result, str)
35
+ assert len(result) > 0