JMAA00 commited on
Commit
87fd43c
·
1 Parent(s): 4ce0a7a
Files changed (1) hide show
  1. app.py +67 -79
app.py CHANGED
@@ -4,17 +4,18 @@ import requests
4
  from huggingface_hub import InferenceClient
5
 
6
  """
7
- Para más info sobre huggingface_hub e InferenceClient:
 
8
  https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
9
  """
10
 
11
  # ============================
12
- # CONFIGURACIÓN DE SERPER
13
  # ============================
14
  SERPER_API_KEY = os.getenv("SERPER_API_KEY")
15
 
16
  def do_websearch(query: str) -> str:
17
- """ Llama a serper.dev y retorna el texto con los resultados. """
18
  if not SERPER_API_KEY:
19
  return "(SERPER_API_KEY no está configurado)"
20
 
@@ -34,13 +35,12 @@ def do_websearch(query: str) -> str:
34
  if not results:
35
  return "No hay resultados relevantes."
36
 
37
- text = []
38
  for i, item in enumerate(results, start=1):
39
  title = item.get("title", "Sin título")
40
  link = item.get("link", "Sin enlace")
41
- text.append(f"{i}. {title}\n {link}")
42
-
43
- return "\n".join(text)
44
 
45
 
46
  # ============================
@@ -53,56 +53,59 @@ client = InferenceClient(
53
  )
54
 
55
  # ============================
56
- # LÓGICA DE RESPUESTA
57
  # ============================
58
- def respond(
59
- message: str,
60
- history: list[tuple[str, str]],
61
- system_message: str,
62
- max_tokens: int,
63
- temperature: float,
64
- top_p: float,
65
- use_search: bool
66
- ):
67
  """
68
- - 'message': Mensaje del usuario.
69
- - 'use_search': si está activo, se llama a do_websearch() y se concatena el resultado al message.
70
- - 'history': historial en forma de (usuario, asistente).
71
- - 'system_message': texto del rol system.
72
- Generamos la respuesta en streaming con chat_completion(stream=True).
 
 
73
  """
74
- if use_search:
75
- web_info = do_websearch(message)
76
- message = f"{message}\nInformación de la web:\n{web_info}"
77
 
78
- # Construimos la conversación
79
- messages = [{"role": "system", "content": system_message}]
80
- for (user_msg, assistant_msg) in history:
81
- messages.append({"role": "user", "content": user_msg})
82
- messages.append({"role": "assistant", "content": assistant_msg})
 
 
 
 
83
 
84
- messages.append({"role": "user", "content": message})
 
85
 
86
- # Llamamos a la API con streaming
87
- response_text = ""
88
- for chunk in client.chat_completion(
89
- messages=messages,
90
  max_tokens=max_tokens,
91
  temperature=temperature,
92
  top_p=top_p,
93
- stream=True
94
- ):
95
- token = chunk.choices[0].delta.get("content", "")
96
- response_text += token
97
- yield response_text
 
 
 
 
 
98
 
99
  # ============================
100
- # CSS (SIN gr.Box)
101
  # ============================
102
  css_code = """
103
  #input_container {
104
  position: relative;
105
  margin-top: 1rem;
 
 
 
106
  }
107
  #search_toggle {
108
  position: absolute;
@@ -115,36 +118,34 @@ css_code = """
115
  font-size: 0.9rem;
116
  color: #333;
117
  cursor: pointer;
 
 
118
  }
 
119
  #search_toggle input[type="checkbox"]:checked + label {
120
- background-color: #0272f5; /* color gradio */
121
  color: white;
122
  border: none;
123
  }
124
  """
125
 
126
- # ============================
127
- # INTERFAZ GRADIO
128
- # ============================
129
  with gr.Blocks(css=css_code) as demo:
130
- gr.Markdown("# Chat con toggle websearch (sin gr.Box)")
131
 
132
- # Historial
133
- # Nota: si queremos evitar la advertencia "tuples are deprecated",
134
- # usamos type="messages" y cambiamos la forma de 'history'.
135
- # Aquí mantenemos la forma (usuario, asistente).
136
  chatbot = gr.Chatbot(
137
  label="Conversación",
138
  value=[],
139
- type="tuples" # ignora la advertencia, o cambia a type="messages".
140
  )
141
 
142
- # Para guardar (usuario, asistente)
143
- state_history = gr.State([])
144
 
 
145
  system_box = gr.Textbox(
146
  label="Mensaje del sistema",
147
- value="Eres Juan, un asistente en español con mucha paciencia y empatía."
148
  )
149
  max_tokens_slider = gr.Slider(1, 2048, 512, step=1, label="Máxima cantidad de tokens")
150
  temp_slider = gr.Slider(0.1, 4.0, 0.7, step=0.1, label="Temperatura")
@@ -153,42 +154,29 @@ with gr.Blocks(css=css_code) as demo:
153
  with gr.Column():
154
  with gr.Row(elem_id="input_container"):
155
  user_input = gr.Textbox(
 
156
  placeholder="Escribe tu mensaje...",
157
- lines=3,
158
- show_label=False
159
  )
160
- # Checkbox "websearch" en la parte inferior izq
161
- # usaremos un simple Row/Column en lugar de gr.Box
162
  with gr.Row(elem_id="search_toggle"):
163
- search_checkbox = gr.Checkbox(value=False, interactive=True)
164
  gr.Label("🌐 Búsqueda")
165
 
166
  send_btn = gr.Button("Enviar")
167
 
168
- def update_chatbot(history):
169
- # Retornamos la misma lista de tuplas para que aparezca en el chatbot
 
170
  return history
171
 
172
  send_btn.click(
173
- fn=respond,
174
- inputs=[
175
- user_input,
176
- state_history,
177
- system_box,
178
- max_tokens_slider,
179
- temp_slider,
180
- top_p_slider,
181
- search_checkbox
182
- ],
183
- outputs=None # streaming
184
- ).then(
185
- # Tomamos la salida (stream final) y la ponemos en chatbot
186
- fn=lambda text, msg, hist: hist + [(msg, text)],
187
- inputs=[gr.Button.stream_output, user_input, state_history],
188
- outputs=state_history
189
  ).then(
190
- fn=update_chatbot,
191
- inputs=state_history,
192
  outputs=chatbot
193
  ).then(
194
  fn=lambda: "",
 
4
  from huggingface_hub import InferenceClient
5
 
6
  """
7
+ For more information on `huggingface_hub` Inference API support,
8
+ please check the docs:
9
  https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
10
  """
11
 
12
  # ============================
13
+ # CONFIGURACIÓN SERPER
14
  # ============================
15
  SERPER_API_KEY = os.getenv("SERPER_API_KEY")
16
 
17
  def do_websearch(query: str) -> str:
18
+ """ Llama a serper.dev y retorna los resultados. """
19
  if not SERPER_API_KEY:
20
  return "(SERPER_API_KEY no está configurado)"
21
 
 
35
  if not results:
36
  return "No hay resultados relevantes."
37
 
38
+ lines = []
39
  for i, item in enumerate(results, start=1):
40
  title = item.get("title", "Sin título")
41
  link = item.get("link", "Sin enlace")
42
+ lines.append(f"{i}. {title}\n {link}")
43
+ return "\n".join(lines)
 
44
 
45
 
46
  # ============================
 
53
  )
54
 
55
  # ============================
56
+ # FUNCIÓN PRINCIPAL (sin streaming)
57
  # ============================
58
+ def chat_fn(user_msg, chat_history, system_msg, max_tokens, temperature, top_p, use_search):
 
 
 
 
 
 
 
 
59
  """
60
+ Llamado al pulsar "Enviar".
61
+ - user_msg: mensaje de usuario
62
+ - use_search: bool, si se hace la búsqueda
63
+ - chat_history: lista de dicts con formato messages
64
+ e.g. [{"role": "user", "content": ...}, {"role": "assistant", "content": ...}, ...]
65
+ - system_msg: se agrega como primer mensaje de rol system (si no está ya)
66
+ Retorna la nueva historia (formato 'messages'), con el nuevo assistant message.
67
  """
 
 
 
68
 
69
+ # 1) Revisamos si en el chat_history ya está el system. Si no, lo añadimos al principio.
70
+ if not chat_history or chat_history[0]["role"] != "system":
71
+ chat_history.insert(0, {"role": "system", "content": system_msg})
72
+
73
+ # 2) Mezclamos el user_msg + websearch (si use_search=True)
74
+ merged_prompt = user_msg
75
+ if use_search:
76
+ web_info = do_websearch(user_msg)
77
+ merged_prompt = f"{user_msg}\nInformación de la web:\n{web_info}"
78
 
79
+ # 3) Añadimos nuevo rol user
80
+ chat_history.append({"role": "user", "content": merged_prompt})
81
 
82
+ # 4) Llamada a la API (sin streaming)
83
+ response = client.chat_completion(
84
+ messages=chat_history,
 
85
  max_tokens=max_tokens,
86
  temperature=temperature,
87
  top_p=top_p,
88
+ stream=False
89
+ )
90
+ # Obtenemos el texto
91
+ assistant_reply = response.choices[0].message["content"]
92
+
93
+ # 5) Añadimos la respuesta del assistant
94
+ chat_history.append({"role": "assistant", "content": assistant_reply})
95
+
96
+ return chat_history
97
+
98
 
99
  # ============================
100
+ # CSS y DISEÑO
101
  # ============================
102
  css_code = """
103
  #input_container {
104
  position: relative;
105
  margin-top: 1rem;
106
+ display: flex;
107
+ align-items: flex-start;
108
+ gap: 0.5rem;
109
  }
110
  #search_toggle {
111
  position: absolute;
 
118
  font-size: 0.9rem;
119
  color: #333;
120
  cursor: pointer;
121
+ display: flex;
122
+ align-items: center;
123
  }
124
+
125
  #search_toggle input[type="checkbox"]:checked + label {
126
+ background-color: #0272f5; /* color principal de gradio */
127
  color: white;
128
  border: none;
129
  }
130
  """
131
 
 
 
 
132
  with gr.Blocks(css=css_code) as demo:
133
+ gr.Markdown("## Chat con WebSearch (Gradio 5.0.1) - Sin streaming, sin gr.Box")
134
 
135
+ # Chatbot en formato 'messages' para evitar el warning sobre 'tuples'.
 
 
 
136
  chatbot = gr.Chatbot(
137
  label="Conversación",
138
  value=[],
139
+ type="messages" # Evitamos la advertencia de tuplas deprecadas
140
  )
141
 
142
+ # Historial "messages" en un gr.State
143
+ chat_history = gr.State([])
144
 
145
+ # Config
146
  system_box = gr.Textbox(
147
  label="Mensaje del sistema",
148
+ value="Eres Juan, un asistente virtual en español. Ayuda con amabilidad."
149
  )
150
  max_tokens_slider = gr.Slider(1, 2048, 512, step=1, label="Máxima cantidad de tokens")
151
  temp_slider = gr.Slider(0.1, 4.0, 0.7, step=0.1, label="Temperatura")
 
154
  with gr.Column():
155
  with gr.Row(elem_id="input_container"):
156
  user_input = gr.Textbox(
157
+ show_label=False,
158
  placeholder="Escribe tu mensaje...",
159
+ lines=3
 
160
  )
161
+ # Checkbox en la parte inferior izq
 
162
  with gr.Row(elem_id="search_toggle"):
163
+ search_checkbox = gr.Checkbox(value=False)
164
  gr.Label("🌐 Búsqueda")
165
 
166
  send_btn = gr.Button("Enviar")
167
 
168
+ # Lógica: 1) chat_fn => 2) actualizamos Chatbot
169
+ def update_chat_display(history):
170
+ # El Chatbot 'messages' recibe [{"role": "...", "content": "..."}]
171
  return history
172
 
173
  send_btn.click(
174
+ fn=chat_fn,
175
+ inputs=[user_input, chat_history, system_box, max_tokens_slider, temp_slider, top_p_slider, search_checkbox],
176
+ outputs=chat_history
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  ).then(
178
+ fn=update_chat_display,
179
+ inputs=chat_history,
180
  outputs=chatbot
181
  ).then(
182
  fn=lambda: "",