mrj-crom commited on
Commit
78d0c91
·
verified ·
1 Parent(s): 7fe95f8

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +345 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import ast
4
+ import operator as op
5
+ import re
6
+ import math
7
+ import torch
8
+ import gradio as gr
9
+ from transformers import AutoModelForCausalLM, AutoTokenizer
10
+ from peft import PeftModel
11
+
12
+ # ============================================================
13
+ # 1. INTERPRETADOR DA THINK-VETOR DSL (TV-DSL)
14
+ # ============================================================
15
+ class TVDSLInterpreter:
16
+ SAFE_OPERATORS = {
17
+ ast.Add: op.add,
18
+ ast.Sub: op.sub,
19
+ ast.Mult: op.mul,
20
+ ast.Div: op.truediv,
21
+ ast.Pow: op.pow,
22
+ ast.USub: op.neg,
23
+ ast.UAdd: op.pos
24
+ }
25
+
26
+ def __init__(self):
27
+ self.functions = {
28
+ "add": lambda a, b: a + b,
29
+ "sub": lambda a, b: a - b,
30
+ "subtract": lambda a, b: a - b,
31
+ "mul": lambda a, b: a * b,
32
+ "multiply": lambda a, b: a * b,
33
+ "div": lambda a, b: a / b if b != 0 else "Error: Division by zero",
34
+ "divide": lambda a, b: a / b if b != 0 else "Error: Division by zero",
35
+ "pow": lambda a, b: a ** b,
36
+ "power": lambda a, b: a ** b,
37
+ "sqrt": lambda a: math.sqrt(a) if a >= 0 else "Error: Square root of negative number",
38
+ "abs": lambda a: abs(a)
39
+ }
40
+
41
+ def safe_eval(self, expr_str: str):
42
+ expr_str = expr_str.strip()
43
+ expr_str = expr_str.replace('^', '**')
44
+ try:
45
+ tree = ast.parse(expr_str, mode='eval')
46
+ return self._eval_node(tree.body)
47
+ except Exception as e:
48
+ return f"Error: Expression parse failure ({str(e)})"
49
+
50
+ def _eval_node(self, node):
51
+ if isinstance(node, ast.Num):
52
+ return node.n
53
+ elif isinstance(node, ast.Constant):
54
+ return node.value
55
+ elif isinstance(node, ast.BinOp):
56
+ left = self._eval_node(node.left)
57
+ right = self._eval_node(node.right)
58
+ if isinstance(left, str) or isinstance(right, str):
59
+ return "Error: Invalid operand in binary operation"
60
+ op_type = type(node.op)
61
+ if op_type in self.SAFE_OPERATORS:
62
+ try:
63
+ return self.SAFE_OPERATORS[op_type](left, right)
64
+ except ZeroDivisionError:
65
+ return "Error: Division by zero"
66
+ return f"Error: Unsupported binary operator '{op_type.__name__}'"
67
+ elif isinstance(node, ast.UnaryOp):
68
+ operand = self._eval_node(node.operand)
69
+ if isinstance(operand, str):
70
+ return operand
71
+ op_type = type(node.op)
72
+ if op_type in self.SAFE_OPERATORS:
73
+ return self.SAFE_OPERATORS[op_type](operand)
74
+ return f"Error: Unsupported unary operator '{op_type.__name__}'"
75
+ elif isinstance(node, ast.Call):
76
+ func_name = node.func.id if isinstance(node.func, ast.Name) else None
77
+ if func_name in self.functions:
78
+ args = [self._eval_node(arg) for arg in node.args]
79
+ for arg in args:
80
+ if isinstance(arg, str) and arg.startswith("Error"):
81
+ return arg
82
+ try:
83
+ return self.functions[func_name](*args)
84
+ except TypeError:
85
+ return f"Error: Incorrect argument count"
86
+ return f"Error: Function '{func_name}' is not registered"
87
+ return "Error: AST node blocked"
88
+
89
+ def process_text_stream(self, text: str) -> tuple[str, bool]:
90
+ pattern = r"\[TV-DSL:\s*(.*?)\]"
91
+ matches = list(re.finditer(pattern, text))
92
+ if not matches:
93
+ return text, False
94
+ processed_text = text
95
+ offset = 0
96
+ for match in matches:
97
+ expr = match.group(1)
98
+ start, end = match.start() + offset, match.end() + offset
99
+ val = self.safe_eval(expr)
100
+ result_str = f"[TV-DSL: {expr}] -> [RESULT: {val}]"
101
+ processed_text = processed_text[:start] + result_str + processed_text[end:]
102
+ offset += len(result_str) - (end - start)
103
+ return processed_text, True
104
+
105
+ # ============================================================
106
+ # 2. CARREGAMENTO E CONFIGURAÇÃO DO MODELO
107
+ # ============================================================
108
+ print("[INFO] Carregando pesos do modelo e adaptadores da CromIA no Space...")
109
+ base_model_id = "Qwen/Qwen2.5-0.5B-Instruct"
110
+ adapter_id = "CromIA/think-vetor-0.5b-lora"
111
+
112
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
113
+ # CPU Basic do Hugging Face Spaces roda incrivelmente rápido e com vetorização AVX em Float32!
114
+ dtype = torch.float32
115
+
116
+ tokenizer = AutoTokenizer.from_pretrained(adapter_id, trust_remote_code=True)
117
+ model = AutoModelForCausalLM.from_pretrained(
118
+ base_model_id,
119
+ torch_dtype=dtype,
120
+ device_map=None,
121
+ trust_remote_code=True
122
+ ).to(device)
123
+ model = PeftModel.from_pretrained(model, adapter_id)
124
+ model.eval()
125
+
126
+ interpreter = TVDSLInterpreter()
127
+
128
+ # ============================================================
129
+ # 3. ROTINA DE INFERÊNCIA INTERATIVA TV-DSL
130
+ # ============================================================
131
+ def run_think_vetor_inference(prompt):
132
+ start_time = time.time()
133
+
134
+ messages = [
135
+ {
136
+ "role": "system",
137
+ "content": "Você é o Think-Vetor 1.5B, um assistente cognitivo híbrido dotado de cadeias de raciocínio de alta fidelidade e raciocínio lógico-matemático."
138
+ },
139
+ {
140
+ "role": "user",
141
+ "content": prompt
142
+ }
143
+ ]
144
+
145
+ formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
146
+ current_prompt = formatted_prompt
147
+
148
+ usou_dsl = False
149
+ full_generation = ""
150
+ max_new_tokens = 256
151
+
152
+ # Suporte a loops iterativos se a DSL for disparada
153
+ for iteration in range(3):
154
+ inputs = tokenizer(current_prompt, return_tensors="pt").to(device)
155
+
156
+ with torch.no_grad():
157
+ outputs = model.generate(
158
+ **inputs,
159
+ max_new_tokens=max_new_tokens,
160
+ temperature=0.1,
161
+ do_sample=False,
162
+ pad_token_id=tokenizer.pad_token_id
163
+ )
164
+
165
+ input_len = inputs["input_ids"].shape[1]
166
+ generated_tokens = outputs[0][input_len:]
167
+ generated_text = tokenizer.decode(generated_tokens, skip_special_tokens=True).strip()
168
+
169
+ processed_text, modified = interpreter.process_text_stream(generated_text)
170
+
171
+ if modified:
172
+ usou_dsl = True
173
+ current_prompt = formatted_prompt + processed_text + "\n"
174
+ max_new_tokens = max(10, max_new_tokens - len(generated_tokens))
175
+ full_generation = processed_text
176
+ continue
177
+ else:
178
+ full_generation = generated_text
179
+ break
180
+
181
+ latency = time.time() - start_time
182
+
183
+ # Separar o thought da resposta final
184
+ thought_content = ""
185
+ final_response = full_generation
186
+
187
+ if "<thought>" in full_generation and "</thought>" in full_generation:
188
+ try:
189
+ parts = full_generation.split("</thought>")
190
+ thought_content = parts[0].replace("<thought>", "").strip()
191
+ final_response = parts[1].strip()
192
+ except Exception:
193
+ pass
194
+ elif "<thought>" in full_generation:
195
+ parts = full_generation.split("<thought>")
196
+ final_response = parts[0].strip()
197
+ thought_content = parts[1].strip()
198
+
199
+ return thought_content, final_response, latency, usou_dsl
200
+
201
+ # ============================================================
202
+ # 4. INTERFACE GRÁFICA GRADIO PREMIUM (WOW-FACTOR)
203
+ # ============================================================
204
+ theme = gr.themes.Default(
205
+ primary_hue="emerald",
206
+ secondary_hue="cyan",
207
+ neutral_hue="slate",
208
+ font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"]
209
+ ).set(
210
+ body_background_fill="*neutral_950",
211
+ block_background_fill="*neutral_900",
212
+ block_border_color="*neutral_800",
213
+ block_title_text_color="*primary_400",
214
+ input_background_fill="*neutral_900",
215
+ button_primary_background_fill="linear-gradient(90deg, *primary_600, *secondary_600)",
216
+ button_primary_text_color="*white"
217
+ )
218
+
219
+ css = """
220
+ .cognitive-card {
221
+ background: rgba(30, 41, 59, 0.4) !important;
222
+ border: 1px solid rgba(16, 185, 129, 0.2) !important;
223
+ border-radius: 12px !important;
224
+ padding: 15px !important;
225
+ box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1) !important;
226
+ backdrop-filter: blur(5px) !important;
227
+ }
228
+ .latent-title {
229
+ color: #10b981 !important;
230
+ font-weight: bold !important;
231
+ font-size: 1.1em !important;
232
+ display: flex !important;
233
+ align-items: center !important;
234
+ gap: 8px !important;
235
+ }
236
+ .chat-window {
237
+ border: 1px solid rgba(6, 182, 212, 0.2) !important;
238
+ border-radius: 12px !important;
239
+ }
240
+ """
241
+
242
+ with gr.Blocks(theme=theme, css=css, title="Think-Vetor Chat - CromIA") as demo:
243
+ gr.HTML(
244
+ """
245
+ <div style="text-align: center; margin-bottom: 25px;">
246
+ <h1 style="font-size: 2.2em; font-weight: bold; background: linear-gradient(90deg, #10b981, #06b6d4); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
247
+ 🧠 Think-Vetor 0.5B: Playground Cognitivo
248
+ </h1>
249
+ <p style="color: #94a3b8; font-size: 1.1em; margin-top: 5px;">
250
+ Fusão de Raciocínio Contínuo e Computação Determinística de Altíssima Fidelidade (TV-DSL)
251
+ </p>
252
+ <div style="display: flex; justify-content: center; gap: 15px; margin-top: 10px;">
253
+ <span style="background: rgba(16, 185, 129, 0.1); color: #10b981; padding: 4px 10px; border-radius: 20px; font-size: 0.85em; border: 1px solid rgba(16, 185, 129, 0.2);">
254
+ Organization: CromIA
255
+ </span>
256
+ <span style="background: rgba(6, 182, 212, 0.1); color: #06b6d4; padding: 4px 10px; border-radius: 20px; font-size: 0.85em; border: 1px solid rgba(6, 182, 212, 0.2);">
257
+ Model Scale: 0.5B LoRA
258
+ </span>
259
+ </div>
260
+ </div>
261
+ """
262
+ )
263
+
264
+ with gr.Row():
265
+ # PAINEL ESQUERDO: Trajetória Cognitiva Latente e TV-DSL
266
+ with gr.Column(scale=1, variant="panel", elem_classes=["cognitive-card"]):
267
+ gr.HTML(
268
+ """
269
+ <div class="latent-title">
270
+ <span>🧠</span> TRAJETÓRIA COGNITIVA LATENTE (SCRATCHPAD)
271
+ </div>
272
+ """
273
+ )
274
+ thought_output = gr.Markdown(
275
+ "*Aguardando prompt do usuário para refletir no espaço latente...*",
276
+ label="Processamento do Pensamento"
277
+ )
278
+ gr.HTML("<hr style='border: 0; border-top: 1px solid #334155; margin: 15px 0;'>")
279
+
280
+ # Painel de Telemetria
281
+ gr.HTML("<div style='color: #06b6d4; font-weight: bold; font-size: 0.9em; margin-bottom: 5px;'>📟 TELEMETRIA FÍSICA</div>")
282
+ with gr.Row():
283
+ latency_box = gr.Textbox(label="Latência Total", placeholder="0.00s", interactive=False)
284
+ dsl_status_box = gr.Textbox(label="Status da TV-DSL", placeholder="Inativo", interactive=False)
285
+
286
+ # PAINEL DIREITO: Chat com o Assistente
287
+ with gr.Column(scale=2):
288
+ chatbot = gr.Chatbot(
289
+ label="Think-Vetor Chatbot Window",
290
+ elem_classes=["chat-window"],
291
+ bubble_full_width=False,
292
+ height=450
293
+ )
294
+
295
+ with gr.Row():
296
+ txt_input = gr.Textbox(
297
+ show_label=False,
298
+ placeholder="Digite seu prompt de lógica, matemática ou conversação aqui...",
299
+ scale=4,
300
+ container=False
301
+ )
302
+ btn_send = gr.Button("Enviar", variant="primary", scale=1)
303
+
304
+ # Sugestões de Prompt para Teste Rápido
305
+ gr.Examples(
306
+ examples=[
307
+ ["quanto é 432 vezes 78?"],
308
+ ["calcule (150 + 250) * 5"],
309
+ ["Alice is taller than Bob. Bob is taller than Charlie. Who is taller, Alice or Charlie?"],
310
+ ["quem é você?"]
311
+ ],
312
+ inputs=txt_input
313
+ )
314
+
315
+ # Evento de envio
316
+ def chat_action(user_message, history):
317
+ if not user_message.strip():
318
+ return "", history, "", "", ""
319
+
320
+ # Executar inferência cognitiva
321
+ thought, response, latency, usou_dsl = run_think_vetor_inference(user_message)
322
+
323
+ # Formatar a exibição do thought de forma visualmente rica
324
+ formatted_thought = ""
325
+ if thought:
326
+ formatted_thought = f"### 🧠 Pensamento Estruturado:\n"
327
+ for line in thought.split("\n"):
328
+ formatted_thought += f"> **|** {line}\n"
329
+ else:
330
+ formatted_thought = "*Esta resposta foi gerada diretamente sem a necessidade de múltiplos passos de relaxamento de atrator.*"
331
+
332
+ latency_str = f"{latency:.2f} segundos"
333
+ dsl_str = "🔥 Ativo (Cálculo Determinístico Executado)" if usou_dsl else "Inativo"
334
+
335
+ # Atualizar histórico do chat
336
+ history.append((user_message, response))
337
+
338
+ return "", history, formatted_thought, latency_str, dsl_str
339
+
340
+ # Conectar botões e envios
341
+ txt_input.submit(chat_action, [txt_input, chatbot], [txt_input, chatbot, thought_output, latency_box, dsl_status_box])
342
+ btn_send.click(chat_action, [txt_input, chatbot], [txt_input, chatbot, thought_output, latency_box, dsl_status_box])
343
+
344
+ if __name__ == "__main__":
345
+ demo.queue().launch()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ transformers>=4.40.0
2
+ peft>=0.10.0
3
+ accelerate>=0.28.0
4
+ safetensors>=0.4.0
5
+ torch>=2.2.0
6
+ gradio>=4.0.0
7
+ jinja2