joinfv commited on
Commit
f143bb0
·
1 Parent(s): 5d56898
Files changed (3) hide show
  1. app.py +137 -0
  2. requeriments.txt +4 -0
  3. src/add_your_files_here +0 -0
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import spaces
3
+ import subprocess
4
+ import os
5
+ import shutil
6
+ import string
7
+ import random
8
+ import glob
9
+ from pypdf import PdfReader
10
+ from sentence_transformers import SentenceTransformer
11
+
12
+ model_name = os.environ.get("MODEL", "Snowflake/snowflake-arctic-embed-m")
13
+ chunk_size = int(os.environ.get("CHUNK_SIZE", 128))
14
+ default_max_characters = int(os.environ.get("DEFAULT_MAX_CHARACTERS", 258))
15
+
16
+ model = SentenceTransformer(model_name)
17
+ # model.to(device="cuda")
18
+
19
+ @spaces.GPU
20
+ def embed(queries, chunks) -> dict[str, list[tuple[str, float]]]:
21
+ query_embeddings = model.encode(queries, prompt_name="query")
22
+ document_embeddings = model.encode(chunks)
23
+
24
+ scores = query_embeddings @ document_embeddings.T
25
+ results = {}
26
+ for query, query_scores in zip(queries, scores):
27
+ chunk_idxs = [i for i in range(len(chunks))]
28
+ # Obtenha uma estrutura como {query: [(chunk_idx, score), (chunk_idx, score), ...]}
29
+ results[query] = list(zip(chunk_idxs, query_scores))
30
+
31
+ return results
32
+
33
+
34
+ def extract_text_from_pdf(reader):
35
+ full_text = ""
36
+ for idx, page in enumerate(reader.pages):
37
+ text = page.extract_text()
38
+ if len(text) > 0:
39
+ full_text += f"---- Página {idx} ----\n" + page.extract_text() + "\n\n"
40
+
41
+ return full_text.strip()
42
+
43
+ def convert(filename) -> str:
44
+ plain_text_filetypes = [
45
+ ".txt",
46
+ ".csv",
47
+ ".tsv",
48
+ ".md",
49
+ ".yaml",
50
+ ".toml",
51
+ ".json",
52
+ ".json5",
53
+ ".jsonc",
54
+ ]
55
+ # Já é um arquivo de texto simples que não se beneficiaria com o pandoc, então retorne o conteúdo
56
+ if any(filename.endswith(ft) for ft in plain_text_filetypes):
57
+ with open(filename, "r") as f:
58
+ return f.read()
59
+
60
+ if filename.endswith(".pdf"):
61
+ return extract_text_from_pdf(PdfReader(filename))
62
+
63
+ raise ValueError(f"Tipo de arquivo não suportado: {filename}")
64
+
65
+
66
+ def chunk_to_length(text, max_length=512):
67
+ chunks = []
68
+ while len(text) > max_length:
69
+ chunks.append(text[:max_length])
70
+ text = text[max_length:]
71
+ chunks.append(text)
72
+ return chunks
73
+
74
+ @spaces.GPU
75
+ def predict(query, max_characters) -> str:
76
+ #Incorpore a consulta
77
+ query_embedding = model.encode(query, prompt_name="query")
78
+
79
+ # Inicialize uma lista para armazenar todos os pedaços e suas semelhanças em todos os documentos
80
+ all_chunks = []
81
+
82
+ # Iterar por todos os documentos
83
+ for filename, doc in docs.items():
84
+ # Calcular produto escalar entre consultas e incorporações de documentos
85
+ similarities = doc["embeddings"] @ query_embedding.T
86
+
87
+ # Adicione pedaços e semelhanças à lista all_chunks
88
+ all_chunks.extend([(filename, chunk, sim) for chunk, sim in zip(doc["chunks"], similarities)])
89
+
90
+ # Classifica todos os pedaços por similaridade
91
+ all_chunks.sort(key=lambda x: x[2], reverse=True)
92
+
93
+ # Inicialize um dicionário para armazenar partes relevantes para cada documento
94
+ relevant_chunks = {}
95
+
96
+ # Adicione os pedaços mais relevantes até que max_characters seja alcançado
97
+ total_chars = 0
98
+ for filename, chunk, _ in all_chunks:
99
+ if total_chars + len(chunk) <= max_characters:
100
+ if filename not in relevant_chunks:
101
+ relevant_chunks[filename] = []
102
+ relevant_chunks[filename].append(chunk)
103
+ total_chars += len(chunk)
104
+ else:
105
+ break
106
+
107
+ return relevant_chunks
108
+
109
+
110
+
111
+ docs = {}
112
+
113
+ for filename in glob.glob("src/*"):
114
+ if filename.endswith("add_your_files_here"):
115
+ continue
116
+
117
+ converted_doc = convert(filename)
118
+
119
+ chunks = chunk_to_length(converted_doc, chunk_size)
120
+ embeddings = model.encode(chunks)
121
+
122
+ docs[filename] = {
123
+ "chunks": chunks,
124
+ "embeddings": embeddings,
125
+ }
126
+
127
+
128
+ gr.Interface(
129
+ predict,
130
+ inputs=[
131
+ gr.Textbox(label="Consulta feita sobre os documentos"),
132
+ gr.Number(label="Máximo de caracteres de saída", value=default_max_characters),
133
+ ],
134
+ outputs=[gr.JSON(label="Pedaços relevantes")],
135
+ title="Demonstração do modelo de ferramenta da comunidade RAG",
136
+ description="Esta é uma demonstração do modelo de ferramenta comunitária RAG. Para usar o RAG no HuggingChat com seus próprios documentos, comece clonando este espaço, adicione seus documentos à pasta `sources` e então crie uma ferramenta comunitária com este espaço!",
137
+ ).launch()
requeriments.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ pypdf==4.2.0
2
+ sentence-transformers==3.0.0
3
+ gradio
4
+ spaces
src/add_your_files_here ADDED
File without changes