danielramos commited on
Commit
bf59288
·
1 Parent(s): 2769fa1

feat: hybrid engine with real CUDA GPU acceleration and streaming on Hugging Face ZeroGPU

Browse files
Files changed (2) hide show
  1. app.py +103 -27
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,46 +1,122 @@
 
 
1
  import gradio as gr
2
- import spaces
 
 
3
  from main import (
 
4
  graph_app,
5
  HumanMessage,
6
  AIMessage,
7
  SystemMessage,
8
- DEFAULT_SYSTEM_PROMPT,
9
- app as fastapi_app
10
  )
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  @spaces.GPU
13
  def chat_fn(message, history):
14
- messages = [SystemMessage(content=DEFAULT_SYSTEM_PROMPT)]
15
- if history:
16
- for turn in history:
17
- if isinstance(turn, dict):
18
- role = turn.get("role", "user")
19
- content = turn.get("content", "")
20
- if role == "assistant":
21
- messages.append(AIMessage(content=content))
22
- else:
23
- messages.append(HumanMessage(content=content))
24
- elif isinstance(turn, (list, tuple)) and len(turn) == 2:
25
- user_msg, bot_msg = turn
26
- if user_msg:
27
- messages.append(HumanMessage(content=str(user_msg)))
28
- if bot_msg:
29
- messages.append(AIMessage(content=str(bot_msg)))
30
-
31
- messages.append(HumanMessage(content=message))
32
- output = graph_app.invoke({"messages": messages})
33
- return output["messages"][-1].content
34
-
35
- # Interfaz interactiva de Chat de Gradio
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  demo = gr.ChatInterface(
37
  fn=chat_fn,
38
  title="⚡ Qwen 2.5 (0.5B) • Intelecto Conciso",
39
- description="Chatbot superinteligente, hiperpreciso y conciso en español. Orquestado con LangGraph y llama-cpp-python en Hugging Face Spaces (ZeroGPU).",
40
  examples=["¿Qué es la entropía?", "¿Por qué el cielo es azul?", "¿Qué es la vida?"],
41
  )
42
 
43
- # Integrar las rutas de FastAPI (/chat, /healthz, /docs) en la misma app
44
  demo.app.include_router(fastapi_app.router)
45
 
46
  if __name__ == "__main__":
 
1
+ import os
2
+ import threading
3
  import gradio as gr
4
+ from typing import List, Dict, Any
5
+
6
+ # Importar configuración y lógica existente de main.py
7
  from main import (
8
+ app as fastapi_app,
9
  graph_app,
10
  HumanMessage,
11
  AIMessage,
12
  SystemMessage,
13
+ DEFAULT_SYSTEM_PROMPT
 
14
  )
15
 
16
+ # Detección del motor GPU (Hugging Face ZeroGPU)
17
+ USE_CUDA_ENGINE = False
18
+
19
+ try:
20
+ import spaces
21
+ import torch
22
+ from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
23
+
24
+ # En Hugging Face ZeroGPU siempre está disponible torch y spaces
25
+ MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
26
+ print(f"[INFO] Inicializando motor Transformers en GPU para {MODEL_ID}...")
27
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
28
+ model = AutoModelForCausalLM.from_pretrained(
29
+ MODEL_ID,
30
+ torch_dtype="auto",
31
+ device_map="auto"
32
+ )
33
+ USE_CUDA_ENGINE = True
34
+ print("[INFO] Motor Transformers GPU cargado exitosamente en tarjeta gráfica.")
35
+ except Exception as e:
36
+ print(f"[INFO] Modo local/CPU detectado ({e}). Utilizando motor local LangGraph / llama-cpp-python.")
37
+ USE_CUDA_ENGINE = False
38
+
39
+ # Stub para spaces.GPU en desarrollo local
40
+ try:
41
+ import spaces
42
+ except ImportError:
43
+ class spaces:
44
+ @staticmethod
45
+ def GPU(func=None, duration=None):
46
+ if func is not None:
47
+ return func
48
+ def decorator(f):
49
+ return f
50
+ return decorator
51
+
52
+
53
+ # Función de generación con soporte de Streaming y aceleración por GPU
54
  @spaces.GPU
55
  def chat_fn(message, history):
56
+ if USE_CUDA_ENGINE:
57
+ # 1. Modo HF ZeroGPU (Aceleración real A100 con Streaming en tiempo real)
58
+ messages = [{"role": "system", "content": DEFAULT_SYSTEM_PROMPT}]
59
+ if history:
60
+ for turn in history:
61
+ if isinstance(turn, dict):
62
+ messages.append(turn)
63
+ elif isinstance(turn, (list, tuple)) and len(turn) == 2:
64
+ if turn[0]:
65
+ messages.append({"role": "user", "content": str(turn[0])})
66
+ if turn[1]:
67
+ messages.append({"role": "assistant", "content": str(turn[1])})
68
+ messages.append({"role": "user", "content": message})
69
+
70
+ text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
71
+ model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
72
+
73
+ streamer = TextIteratorStreamer(tokenizer, timeout=20.0, skip_prompt=True, skip_special_tokens=True)
74
+ generate_kwargs = dict(
75
+ model_inputs,
76
+ streamer=streamer,
77
+ max_new_tokens=120,
78
+ temperature=0.3,
79
+ repetition_penalty=1.15
80
+ )
81
+ t = threading.Thread(target=model.generate, kwargs=generate_kwargs)
82
+ t.start()
83
+
84
+ partial_text = ""
85
+ for new_token in streamer:
86
+ partial_text += new_token
87
+ yield partial_text
88
+ else:
89
+ # 2. Modo Local (LangGraph + llama-cpp-python)
90
+ messages = [SystemMessage(content=DEFAULT_SYSTEM_PROMPT)]
91
+ if history:
92
+ for turn in history:
93
+ if isinstance(turn, dict):
94
+ role = turn.get("role", "user")
95
+ content = turn.get("content", "")
96
+ if role == "assistant":
97
+ messages.append(AIMessage(content=content))
98
+ else:
99
+ messages.append(HumanMessage(content=content))
100
+ elif isinstance(turn, (list, tuple)) and len(turn) == 2:
101
+ if turn[0]:
102
+ messages.append(HumanMessage(content=str(turn[0])))
103
+ if turn[1]:
104
+ messages.append(AIMessage(content=str(turn[1])))
105
+
106
+ messages.append(HumanMessage(content=message))
107
+ output = graph_app.invoke({"messages": messages})
108
+ yield output["messages"][-1].content
109
+
110
+
111
+ # Interfaz Gradio con Streaming en tiempo real
112
  demo = gr.ChatInterface(
113
  fn=chat_fn,
114
  title="⚡ Qwen 2.5 (0.5B) • Intelecto Conciso",
115
+ description="Chatbot superinteligente, hiperpreciso y conciso en español. Acelerado con GPU en Hugging Face Spaces (Streaming en vivo).",
116
  examples=["¿Qué es la entropía?", "¿Por qué el cielo es azul?", "¿Qué es la vida?"],
117
  )
118
 
119
+ # Integrar las rutas de FastAPI (/chat, /healthz, /docs) en la misma aplicación
120
  demo.app.include_router(fastapi_app.router)
121
 
122
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -6,3 +6,5 @@ langgraph>=0.2.0
6
  langchain-core>=0.3.0
7
  huggingface_hub
8
  gradio
 
 
 
6
  langchain-core>=0.3.0
7
  huggingface_hub
8
  gradio
9
+ transformers>=4.44.0
10
+ accelerate>=0.33.0