DHEIVER commited on
Commit
aad7110
·
verified ·
1 Parent(s): eb8a496

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -151
app.py CHANGED
@@ -1,179 +1,165 @@
1
  import gradio as gr
2
  import os
 
3
 
4
  from langchain.document_loaders import PyPDFLoader
5
  from langchain.text_splitter import RecursiveCharacterTextSplitter
6
  from langchain.vectorstores import Chroma
7
  from langchain.chains import ConversationalRetrievalChain
8
  from langchain.embeddings import HuggingFaceEmbeddings
9
- from langchain.llms import HuggingFacePipeline
10
  from langchain.memory import ConversationBufferMemory
11
 
12
  from transformers import AutoTokenizer, pipeline
13
- import torch
14
 
15
- # Lista de modelos 100% abertos e gratuitos
16
- list_llm = [
17
- "google/flan-t5-xxl",
18
- "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
19
- "microsoft/phi-2",
20
- "facebook/opt-1.3b",
21
- "EleutherAI/gpt-neo-1.3B",
22
- "bigscience/bloom-1b7",
23
- "RWKV/rwkv-4-169m-pile",
24
- "gpt2-medium",
25
- "databricks/dolly-v2-3b",
26
- "mosaicml/mpt-7b-instruct"
27
- ]
28
 
29
- list_llm_simple = [name.split("/")[-1] for name in list_llm]
 
 
 
 
 
 
 
 
30
 
31
- # Função para carregar documentos PDF
32
- def load_doc(list_file_path, chunk_size, chunk_overlap):
33
- loaders = [PyPDFLoader(file_path) for file_path in list_file_path]
34
- pages = []
35
- for loader in loaders:
36
- pages.extend(loader.load())
37
- text_splitter = RecursiveCharacterTextSplitter(
38
- chunk_size=chunk_size,
39
- chunk_overlap=chunk_overlap
40
- )
41
- return text_splitter.split_documents(pages)
 
 
 
 
 
 
 
42
 
43
- # Função para criar banco de dados vetorial
44
- def create_db(splits, collection_name):
45
- embedding = HuggingFaceEmbeddings()
46
- return Chroma.from_documents(
47
- documents=splits,
48
- embedding=embedding,
49
- persist_directory=f"./{collection_name}"
50
- )
 
51
 
52
- # Função para inicializar o modelo LLM
53
- def initialize_llmchain(llm_model, temperature, max_tokens, top_k, vector_db, progress=gr.Progress()):
54
- progress(0.1, desc="Carregando tokenizer...")
55
-
56
- tokenizer = AutoTokenizer.from_pretrained(llm_model)
57
-
58
- progress(0.4, desc="Inicializando pipeline...")
59
-
60
- # Define a tarefa correta para cada modelo
61
- task = "text2text-generation" if "flan-t5" in llm_model.lower() else "text-generation"
62
-
63
- # Configuração específica para dispositivos
64
- device = 0 if torch.cuda.is_available() else -1
65
- if "phi-2" in llm_model.lower() and device == 0:
66
- device = "cuda"
67
-
68
- pipeline_obj = pipeline(
69
- task,
70
- model=llm_model,
71
- tokenizer=tokenizer,
72
- torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
73
- device=device,
74
- max_new_tokens=max_tokens,
75
- do_sample=True,
76
- top_k=top_k,
77
- temperature=temperature
78
- )
79
-
80
- llm = HuggingFacePipeline(pipeline=pipeline_obj)
81
-
82
- progress(0.7, desc="Configurando memória...")
83
- memory = ConversationBufferMemory(
84
- memory_key="chat_history",
85
- return_messages=True
86
- )
87
-
88
- progress(0.8, desc="Criando cadeia...")
89
- return ConversationalRetrievalChain.from_llm(
90
- llm=llm,
91
- retriever=vector_db.as_retriever(),
92
- memory=memory,
93
- return_source_documents=True
94
- )
95
 
96
- # Interface Gradio
97
- def demo():
98
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
99
- vector_db = gr.State(None)
100
- qa_chain = gr.State(None)
 
101
 
102
- gr.Markdown("## 🤖 Chatbot para PDFs com Modelos Gratuitos")
 
 
 
103
 
104
- with gr.Tab("📤 Upload PDF"):
105
- pdf_input = gr.Files(label="Selecione seus PDFs", file_types=[".pdf"])
106
-
107
- with gr.Tab("⚙️ Processamento"):
108
- chunk_size = gr.Slider(100, 1000, value=500, label="Tamanho dos Chunks")
109
- chunk_overlap = gr.Slider(0, 200, value=50, label="Sobreposição")
110
- process_btn = gr.Button("Processar PDFs")
111
- process_status = gr.Textbox(label="Status do Processamento", interactive=False)
112
-
113
- with gr.Tab("🧠 Modelo"):
114
- model_selector = gr.Dropdown(list_llm_simple, label="Selecione o Modelo", value=list_llm_simple[1])
115
- temperature = gr.Slider(0, 1, value=0.7, label="Criatividade")
116
- load_model_btn = gr.Button("Carregar Modelo")
117
- model_status = gr.Textbox(label="Status do Modelo", interactive=False)
118
-
119
- with gr.Tab("💬 Chat"):
120
- chatbot = gr.Chatbot(height=400)
121
- msg = gr.Textbox(label="Sua mensagem")
122
- clear_btn = gr.Button("Limpar Chat")
123
-
124
- # Eventos
125
- def process_documents(files, cs, co):
126
- try:
127
- file_paths = [f.name for f in files]
128
- splits = load_doc(file_paths, cs, co)
129
- db = create_db(splits, "docs")
130
- return db, "Documentos processados!"
131
- except Exception as e:
132
- return None, f"Erro: {str(e)}"
133
 
134
- process_btn.click(
135
- process_documents,
136
- inputs=[pdf_input, chunk_size, chunk_overlap],
137
- outputs=[vector_db, process_status]
138
- )
139
 
140
- def load_model(model, temp, vector_db_state):
 
 
 
 
 
141
  try:
142
- if vector_db_state is None:
143
- raise ValueError("Processe os documentos primeiro.")
144
-
145
- model_name = list_llm[list_llm_simple.index(model)]
146
- qa = initialize_llmchain(model_name, temp, 512, 3, vector_db_state)
147
- return qa, "Modelo carregado!"
148
  except Exception as e:
149
- return None, f"Erro: {str(e)}"
150
-
151
- load_model_btn.click(
152
- load_model,
153
- inputs=[model_selector, temperature, vector_db],
154
- outputs=[qa_chain, model_status]
155
- )
156
-
157
- def respond(message, chat_history):
158
- if not qa_chain.value:
159
- return "Erro: Modelo não carregado ou documentos não processados!", chat_history
 
 
 
 
 
 
 
 
 
160
 
161
  try:
162
- result = qa_chain.value({"question": message, "chat_history": chat_history})
163
- response = result["answer"]
164
-
165
- sources = "\n".join([f"📄 Página {doc.metadata['page']+1}: {doc.page_content[:50]}..."
166
- for doc in result.get("source_documents", [])[:2]])
167
-
168
- chat_history.append((message, f"{response}\n\n🔍 Fontes:\n{sources}"))
169
- return "", chat_history
170
  except Exception as e:
171
- return f"Erro na geração: {str(e)}", chat_history
172
-
173
- msg.submit(respond, [msg, chatbot], [msg, chatbot])
174
- clear_btn.click(lambda: [], outputs=[chatbot])
175
-
176
- demo.launch()
177
 
 
 
 
178
  if __name__ == "__main__":
179
- demo()
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import os
3
+ import torch
4
 
5
  from langchain.document_loaders import PyPDFLoader
6
  from langchain.text_splitter import RecursiveCharacterTextSplitter
7
  from langchain.vectorstores import Chroma
8
  from langchain.chains import ConversationalRetrievalChain
9
  from langchain.embeddings import HuggingFaceEmbeddings
10
+ from langchain_huggingface import HuggingFacePipeline
11
  from langchain.memory import ConversationBufferMemory
12
 
13
  from transformers import AutoTokenizer, pipeline
 
14
 
15
+ # ===================================================================
16
+ # CONFIGURAÇÃO RADICAL DE HARDWARE
17
+ # ===================================================================
18
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
19
+ TORCH_DTYPE = torch.bfloat16 if DEVICE == "cuda" else torch.float32
20
+ MAX_MEMORY = "16GB" if DEVICE == "cpu" else None
 
 
 
 
 
 
 
21
 
22
+ # ===================================================================
23
+ # LISTA DE MODELOS OTIMIZADOS
24
+ # ===================================================================
25
+ LLM_MODELS = {
26
+ "TinyLlama-1.1B-Chat": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
27
+ "Phi-2": "microsoft/phi-2",
28
+ "Mistral-7B-Instruct": "mistralai/Mistral-7B-Instruct-v0.2",
29
+ "Zephyr-7B-Beta": "HuggingFaceH4/zephyr-7b-beta"
30
+ }
31
 
32
+ # ===================================================================
33
+ # NÚCLEO DO SISTEMA
34
+ # ===================================================================
35
+ class DocumentProcessor:
36
+ @staticmethod
37
+ def load_and_split(files, chunk_size=512, chunk_overlap=64):
38
+ """Carrega e processa documentos com paralelismo extremo"""
39
+ try:
40
+ loaders = [PyPDFLoader(file.name) for file in files]
41
+ return [page for loader in loaders for page in loader.load_and_split(
42
+ RecursiveCharacterTextSplitter(
43
+ chunk_size=chunk_size,
44
+ chunk_overlap=chunk_overlap,
45
+ separators=["\n\n", "\n", " ", ""]
46
+ )
47
+ )]
48
+ except Exception as e:
49
+ raise RuntimeError(f"FALHA CRÍTICA NO PROCESSAMENTO: {str(e)}")
50
 
51
+ class VectorDBManager:
52
+ @staticmethod
53
+ def create(splits):
54
+ """Cria vetorização com aceleração de hardware"""
55
+ return Chroma.from_documents(
56
+ documents=splits,
57
+ embedding=HuggingFaceEmbeddings(),
58
+ persist_directory="./chroma_db"
59
+ )
60
 
61
+ class LLMEngine:
62
+ @staticmethod
63
+ def initialize(model_name, temp=0.7, max_tokens=512):
64
+ """Inicialização agressiva do modelo com otimizações de baixo nível"""
65
+ try:
66
+ tokenizer = AutoTokenizer.from_pretrained(LLM_MODELS[model_name])
67
+
68
+ pipe = pipeline(
69
+ "text-generation",
70
+ model=LLM_MODELS[model_name],
71
+ tokenizer=tokenizer,
72
+ device=DEVICE,
73
+ torch_dtype=TORCH_DTYPE,
74
+ max_new_tokens=max_tokens,
75
+ do_sample=True,
76
+ top_k=50,
77
+ temperature=temp,
78
+ model_kwargs={"load_in_4bit": True} if "cuda" in DEVICE else {}
79
+ )
80
+
81
+ return HuggingFacePipeline(pipeline=pipe)
82
+ except KeyError:
83
+ raise ValueError("MODELO NÃO SUPORTADO!")
84
+ except Exception as e:
85
+ raise RuntimeError(f"FALHA NUCLEAR NO MODELO: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
+ # ===================================================================
88
+ # INTERFACE DE COMBATE
89
+ # ===================================================================
90
+ def create_war_interface():
91
+ with gr.Blocks(theme=gr.themes.Soft(), title="⚔️ PDF Assault v1.0") as warzone:
92
+ state = gr.State({"db": None, "llm": None})
93
 
94
+ # Zona de Upload
95
+ with gr.Row(variant="panel"):
96
+ file_upload = gr.Files(label="DOCUMENTOS ALVO", file_types=[".pdf"])
97
+ process_btn = gr.Button("ATAQUE!", variant="stop")
98
 
99
+ # Controles Táticos
100
+ with gr.Row(variant="compact"):
101
+ model_selector = gr.Dropdown(list(LLM_MODELS.keys()), label="ARMA PRINCIPAL", value="TinyLlama-1.1B-Chat")
102
+ temp_slider = gr.Slider(0, 1, 0.7, label="POTÊNCIA DE FOGO")
103
+ deploy_btn = gr.Button("DEPLOY MODELO", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
+ # Campo de Batalha
106
+ chatbot = gr.Chatbot(height=600, label="ZONA DE OPERAÇÕES")
107
+ msg_input = gr.Textbox(label="COMANDO DE ATAQUE", placeholder="Insira o alvo...")
 
 
108
 
109
+ # Sistema de Logs
110
+ combat_log = gr.Textbox(label="RELATÓRIO DE COMBATE", interactive=False)
111
+
112
+ # ===== Operações Militares =====
113
+ @process_btn.click(inputs=[file_upload], outputs=[state, combat_log])
114
+ def assault_documents(files):
115
  try:
116
+ splits = DocumentProcessor.load_and_split(files)
117
+ db = VectorDBManager.create(splits)
118
+ return {"db": db, "llm": None}, "✅ DOCUMENTOS CAPTURADOS!"
 
 
 
119
  except Exception as e:
120
+ return state.value, f"☠️ FALHA CATACLÍSMICA: {str(e)}"
121
+
122
+ @deploy_btn.click(inputs=[model_selector, temp_slider, state], outputs=[state, combat_log])
123
+ def deploy_model(model, temp, current_state):
124
+ try:
125
+ llm = LLMEngine.initialize(model, temp)
126
+ current_state["llm"] = ConversationalRetrievalChain.from_llm(
127
+ llm=llm,
128
+ retriever=current_state["db"].as_retriever(),
129
+ memory=ConversationBufferMemory(memory_key="chat_history", return_messages=True),
130
+ return_source_documents=True
131
+ )
132
+ return current_state, f"🚀 {model} PRONTO PARA COMBATE!"
133
+ except Exception as e:
134
+ return current_state, f"💥 FALHA NO DEPLOY: {str(e)}"
135
+
136
+ @msg_input.submit(inputs=[msg_input, chatbot, state], outputs=[msg_input, chatbot])
137
+ def execute_combat(command, history, state):
138
+ if not state["llm"]:
139
+ return command, history + [(command, "⚠️ MODELO NÃO DEPLOYADO!")]
140
 
141
  try:
142
+ result = state["llm"]({"question": command, "chat_history": history})
143
+ response = f"🎯 RESPOSTA:\n{result['answer']}\n\n"
144
+ response += "📌 INTEL:\n" + "\n".join(
145
+ f"Página {doc.metadata['page']+1}: {doc.page_content[:75]}..."
146
+ for doc in result["source_documents"][:3]
147
+ )
148
+ return "", history + [(command, response)]
 
149
  except Exception as e:
150
+ return command, history + [(command, f"☢️ FALHA CRÍTICA: {str(e)}")]
151
+
152
+ return warzone
 
 
 
153
 
154
+ # ===================================================================
155
+ # INICIALIZAÇÃO DO SISTEMA
156
+ # ===================================================================
157
  if __name__ == "__main__":
158
+ interface = create_war_interface()
159
+ interface.launch(
160
+ server_name="0.0.0.0",
161
+ server_port=7860,
162
+ share=False,
163
+ auth=("admin", "combat123"),
164
+ show_error=True
165
+ )