Maximofn commited on
Commit
43c2b09
·
1 Parent(s): 7ad5856

Añade funciones para manejar imágenes y normalizar contenido de usuario en `app.py`. Se implementan las funciones `_build_image_parts` y `_value_to_user_content` para procesar imágenes y generar contenido de usuario adecuado. Además, se mejora la función `_value_preview` para ofrecer una vista previa segura de los mensajes, incluyendo el conteo de imágenes. Se actualiza la función `respond` para utilizar estas nuevas funciones, optimizando el manejo de contenido y mejorando la legibilidad del código.

Browse files
Files changed (1) hide show
  1. app.py +53 -27
app.py CHANGED
@@ -92,6 +92,53 @@ def _extract_text_and_files(message):
92
  return text_combined, files
93
 
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  def _preview_text(text: str | None, limit: int = 600) -> str:
96
  if not text:
97
  return ""
@@ -107,9 +154,9 @@ def _history_preview(history: list[tuple[str, str]] | None, max_turns: int = 3,
107
  parts: list[str] = []
108
  for user_turn, assistant_turn in tail:
109
  if user_turn:
110
- parts.append(f"U: {_preview_text(user_turn, 300)}")
111
  if assistant_turn:
112
- parts.append(f"A: {_preview_text(assistant_turn, 300)}")
113
  joined = "\n".join(parts)
114
  return _preview_text(joined, max_chars)
115
 
@@ -138,36 +185,15 @@ def respond(message, history: list[tuple[str, str]]):
138
  ]
139
  for user_turn, assistant_turn in history or []:
140
  if user_turn:
141
- messages.append({"role": "user", "content": user_turn})
142
  if assistant_turn:
143
  messages.append({"role": "assistant", "content": assistant_turn})
144
 
145
  # Build user content with optional inline images (data URLs)
146
  final_user_text = (user_text or "").strip() or "Describe el contenido de la(s) imagen(es)."
147
 
148
- # Collect image parts
149
- image_parts = []
150
- for f in files or []:
151
- path = None
152
- if isinstance(f, str):
153
- path = f
154
- elif isinstance(f, dict):
155
- path = f.get("path") or f.get("name")
156
- if not path or not os.path.exists(path):
157
- continue
158
- mime, _ = mimetypes.guess_type(path)
159
- if not mime or not mime.startswith("image/"):
160
- continue
161
- try:
162
- with open(path, "rb") as fp:
163
- b64 = base64.b64encode(fp.read()).decode("utf-8")
164
- data_url = f"data:{mime};base64,{b64}"
165
- image_parts.append({
166
- "type": "image_url",
167
- "image_url": {"url": data_url},
168
- })
169
- except Exception:
170
- continue
171
 
172
  if image_parts:
173
  user_content = [{"type": "text", "text": final_user_text}] + image_parts
@@ -187,7 +213,7 @@ def respond(message, history: list[tuple[str, str]]):
187
  name="Chat Session",
188
  run_type="chain",
189
  inputs={
190
- "user_text": _preview_text(user_text, 600),
191
  "has_images": bool(image_parts),
192
  "history_preview": _history_preview(history),
193
  },
 
92
  return text_combined, files
93
 
94
 
95
+ def _build_image_parts(files):
96
+ image_parts = []
97
+ for f in files or []:
98
+ path = None
99
+ if isinstance(f, str):
100
+ path = f
101
+ elif isinstance(f, dict):
102
+ path = f.get("path") or f.get("name")
103
+ if not path or not os.path.exists(path):
104
+ continue
105
+ mime, _ = mimetypes.guess_type(path)
106
+ if not mime or not mime.startswith("image/"):
107
+ continue
108
+ try:
109
+ with open(path, "rb") as fp:
110
+ b64 = base64.b64encode(fp.read()).decode("utf-8")
111
+ data_url = f"data:{mime};base64,{b64}"
112
+ image_parts.append({
113
+ "type": "image_url",
114
+ "image_url": {"url": data_url},
115
+ })
116
+ except Exception:
117
+ continue
118
+ return image_parts
119
+
120
+
121
+ def _value_to_user_content(value):
122
+ """Normalize any gradio message value to OpenAI user 'content'."""
123
+ text, files = _extract_text_and_files(value)
124
+ final_user_text = (text or "").strip() or "Describe el contenido de la(s) imagen(es)."
125
+ image_parts = _build_image_parts(files)
126
+ if image_parts:
127
+ return [{"type": "text", "text": final_user_text}] + image_parts
128
+ return final_user_text
129
+
130
+
131
+ def _value_preview(value, limit: int = 600) -> str:
132
+ """Safe preview string for any kind of message value."""
133
+ if isinstance(value, str):
134
+ return _preview_text(value, limit)
135
+ text, files = _extract_text_and_files(value)
136
+ suffix = ""
137
+ if files:
138
+ suffix = f" [images:{len(files)}]"
139
+ return _preview_text((text or "").strip() + suffix, limit)
140
+
141
+
142
  def _preview_text(text: str | None, limit: int = 600) -> str:
143
  if not text:
144
  return ""
 
154
  parts: list[str] = []
155
  for user_turn, assistant_turn in tail:
156
  if user_turn:
157
+ parts.append(f"User 👤: {_preview_text(user_turn, 300)}")
158
  if assistant_turn:
159
+ parts.append(f"Assistant 🤖: {_preview_text(assistant_turn, 300)}")
160
  joined = "\n".join(parts)
161
  return _preview_text(joined, max_chars)
162
 
 
185
  ]
186
  for user_turn, assistant_turn in history or []:
187
  if user_turn:
188
+ messages.append({"role": "user", "content": _value_to_user_content(user_turn)})
189
  if assistant_turn:
190
  messages.append({"role": "assistant", "content": assistant_turn})
191
 
192
  # Build user content with optional inline images (data URLs)
193
  final_user_text = (user_text or "").strip() or "Describe el contenido de la(s) imagen(es)."
194
 
195
+ # Collect image parts using helper
196
+ image_parts = _build_image_parts(files)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  if image_parts:
199
  user_content = [{"type": "text", "text": final_user_text}] + image_parts
 
213
  name="Chat Session",
214
  run_type="chain",
215
  inputs={
216
+ "user_text": _value_preview(message, 600),
217
  "has_images": bool(image_parts),
218
  "history_preview": _history_preview(history),
219
  },