tepirale commited on
Commit
e2469f7
·
verified ·
1 Parent(s): 92f1751

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +743 -0
README.md CHANGED
@@ -11,6 +11,9 @@ tags:
11
  ---
12
  # Ornith-Agents-A1
13
 
 
 
 
14
  This is a merge of pre-trained language models created using [mergekit](https://github.com/cg123/mergekit).
15
 
16
  ## Merge Details
@@ -44,3 +47,743 @@ models:
44
  dtype: bfloat16
45
 
46
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  ---
12
  # Ornith-Agents-A1
13
 
14
+ ![image](https://cdn-uploads.huggingface.co/production/uploads/69fd0f92cd1d7acb7e880a3e/D2gaf1z7fgd4GvgT52hMu.png)
15
+
16
+
17
  This is a merge of pre-trained language models created using [mergekit](https://github.com/cg123/mergekit).
18
 
19
  ## Merge Details
 
47
  dtype: bfloat16
48
 
49
  ```
50
+
51
+
52
+
53
+ # install
54
+ ```
55
+ !python -m pip install --upgrade pip
56
+ !pip install -U uv
57
+
58
+
59
+ !uv pip install --system \
60
+ --reinstall-package vllm --reinstall-package torch \
61
+ --reinstall-package torchvision --reinstall-package torchaudio \
62
+ "vllm==0.24.0+cu129" \
63
+ --extra-index-url https://wheels.vllm.ai/0.24.0/cu129 \
64
+ --torch-backend=cu129 \
65
+ --index-strategy unsafe-best-match
66
+
67
+ !pip install -q "openai>=1.40.0" --root-user-action=ignore
68
+
69
+
70
+ # https://docs.vllm.ai/en/v0.24.0/configuration/engine_args/#multimodalconfig
71
+ ```
72
+
73
+ # !chmod +x serve_ornith_vllm.sh
74
+
75
+ ```sh
76
+ #!/usr/bin/env bash
77
+ # ---------------------------------------------------------------------------
78
+ # serve_ornith_vllm.sh (versión DETACHED)
79
+ # Levanta Ornith-1.0 con vLLM en segundo plano (OpenAI-compatible).
80
+ #
81
+ # Igual que el serve de Gemma 4: nohup + disown -> el servidor sobrevive aunque
82
+ # cierres la shell o termine este script. Guarda el PID y espera a que el
83
+ # endpoint /health responda antes de devolverte el control.
84
+ #
85
+ # Ornith es un modelo de razonamiento (<think>...</think>) con tool-calling
86
+ # estilo Qwen3, así que activamos --reasoning-parser qwen3 y --tool-call-parser
87
+ # qwen3_xml para obtener reasoning_content y tool_calls.
88
+ #
89
+ # Uso:
90
+ # chmod +x serve_ornith_vllm.sh stop_ornith.sh
91
+ # ./serve_ornith_vllm.sh # arranca en background y espera al health
92
+ # ./stop_ornith.sh # lo apaga
93
+ #
94
+ # El número de GPUs (tensor-parallel-size) se DETECTA AUTOMÁTICAMENTE.
95
+ #
96
+ # Variables de entorno configurables (con sus valores por defecto):
97
+ # MODEL deepreinforce-ai/Ornith-1.0-9B
98
+ # SERVED_NAME Ornith-1.0-9B
99
+ # TP_SIZE (auto-detectado) -> fuerza un valor para sobreescribir
100
+ # PORT 8000
101
+ # HOST 0.0.0.0
102
+ # MAX_LEN 262144 (bajalo si te quedas sin VRAM/KV cache, p.ej. 16384)
103
+ # GPU_UTIL 0.90
104
+ # API_KEY EMPTY (token que exigira el server; cliente debe enviarlo)
105
+ # LOG ornith_vllm.log
106
+ # PIDFILE ornith_server.pid
107
+ # SHOW_PROGRESS 1 (=1 muestra el log en vivo al cargar; =0 silencioso)
108
+ #
109
+ # Ejemplos:
110
+ # ./serve_ornith_vllm.sh # usa TODAS las GPUs visibles
111
+ # TP_SIZE=2 ./serve_ornith_vllm.sh # fuerza solo 2 GPUs
112
+ # MAX_LEN=16384 ./serve_ornith_vllm.sh # recorta contexto (recomendado en 1 GPU)
113
+ # SHOW_PROGRESS=0 ./serve_ornith_vllm.sh # arranque silencioso
114
+ # ---------------------------------------------------------------------------
115
+ set -euo pipefail
116
+
117
+ # ---------------------------------------------------------------------------
118
+ # Deteccion automatica de GPUs
119
+ # Prioridad: 1) TP_SIZE manual 2) CUDA_VISIBLE_DEVICES 3) nvidia-smi
120
+ # ---------------------------------------------------------------------------
121
+ detect_gpus() {
122
+ if [[ -n "${CUDA_VISIBLE_DEVICES:-}" ]]; then
123
+ echo "${CUDA_VISIBLE_DEVICES}" | tr ',' '\n' | grep -cE '^[0-9]+$' || echo 0
124
+ return
125
+ fi
126
+ if command -v nvidia-smi >/dev/null 2>&1; then
127
+ nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | grep -c . || echo 0
128
+ return
129
+ fi
130
+ echo 0
131
+ }
132
+
133
+ if [[ -n "${TP_SIZE:-}" ]]; then
134
+ echo "[info] TP_SIZE forzado manualmente: ${TP_SIZE}"
135
+ else
136
+ NUM_GPUS="$(detect_gpus)"
137
+ if [[ "${NUM_GPUS}" -lt 1 ]]; then
138
+ echo "[error] No se detecto ninguna GPU NVIDIA." >&2
139
+ echo " vLLM requiere GPU. Verifica los drivers con 'nvidia-smi'." >&2
140
+ echo " Si quieres forzar un valor de todos modos: TP_SIZE=1 ./serve_ornith_vllm.sh" >&2
141
+ exit 1
142
+ fi
143
+ TP_SIZE="${NUM_GPUS}"
144
+ echo "[info] GPUs detectadas: ${NUM_GPUS} -> tensor-parallel-size=${TP_SIZE}"
145
+
146
+ if (( TP_SIZE > 1 )) && (( (TP_SIZE & (TP_SIZE - 1)) != 0 )); then
147
+ echo "[warn] ${TP_SIZE} no es potencia de 2; si vLLM falla al cargar," >&2
148
+ echo " fuerza una potencia de 2 (p.ej. TP_SIZE=2 o TP_SIZE=4)." >&2
149
+ fi
150
+ fi
151
+
152
+ # ---------------------------------------------------------------------------
153
+ # Configuracion del modelo / servidor
154
+ # ---------------------------------------------------------------------------
155
+ # MODEL="${MODEL:-deepreinforce-ai/Ornith-1.0-9B}"
156
+ # SERVED_NAME="${SERVED_NAME:-Ornith-1.0-9B}"
157
+ MODEL="${MODEL:-tepirale/Ornith-Agents-A1-3.7-35B-A3B-dare_ties}"
158
+ SERVED_NAME="${SERVED_NAME:-Ornith-Agents-A1-3.7-35B-A3B-dare_ties}"
159
+ PORT="${PORT:-8000}"
160
+ HOST="${HOST:-0.0.0.0}"
161
+ MAX_LEN="${MAX_LEN:-50000}"
162
+ GPU_UTIL="${GPU_UTIL:-0.93}"
163
+ # GPU_UTIL="${GPU_UTIL:-0.90}"
164
+ API_KEY="${API_KEY:-EMPTY}"
165
+ LOG="${LOG:-ornith_vllm.log}"
166
+ PIDFILE="${PIDFILE:-ornith_server.pid}"
167
+ SHOW_PROGRESS="${SHOW_PROGRESS:-1}"
168
+
169
+ # Evita arrancar dos veces sobre el mismo PIDFILE
170
+ if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
171
+ echo "[error] Ya hay un servidor corriendo (PID $(cat "$PIDFILE"), $PIDFILE)." >&2
172
+ echo " Apagalo primero con ./stop_ornith.sh" >&2
173
+ exit 1
174
+ fi
175
+
176
+ echo "============================================================"
177
+ echo " Sirviendo: ${MODEL}"
178
+ echo " Nombre expuesto: ${SERVED_NAME}"
179
+ echo " GPUs (TP): ${TP_SIZE} | Contexto max: ${MAX_LEN}"
180
+ echo " Endpoint: http://${HOST}:${PORT}/v1 | Log: ${LOG}"
181
+ echo "============================================================"
182
+
183
+ export VLLM_API_KEY="${API_KEY}"
184
+
185
+ # ─── Chat template oficial de Ornith (dispara el modo <think>) ───
186
+ TEMPLATE="${TEMPLATE:-ornith_chat_template.jinja}"
187
+ # TEMPLATE_URL="${TEMPLATE_URL:-https://huggingface.co/deepreinforce-ai/Ornith-1.0-9B/resolve/main/chat_template.jinja}"
188
+ TEMPLATE_URL="${TEMPLATE_URL:-https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B/resolve/main/chat_template.jinja}"
189
+ if [ ! -f "$TEMPLATE" ]; then
190
+ echo "Descargando chat template de Ornith..."
191
+ curl -sfL -o "$TEMPLATE" "$TEMPLATE_URL" \
192
+ || { echo "ERROR: no se pudo descargar el template"; exit 1; }
193
+ fi
194
+ TEMPLATE_PATH="$(pwd)/$TEMPLATE"
195
+
196
+
197
+
198
+ # ---------------------------------------------------------------------------
199
+ # Arranque DETACHED (sobrevive al cierre de la shell)
200
+ # ---------------------------------------------------------------------------
201
+ nohup vllm serve "${MODEL}" \
202
+ --served-model-name "${SERVED_NAME}" \
203
+ --tensor-parallel-size "${TP_SIZE}" \
204
+ --host "${HOST}" --port "${PORT}" \
205
+ --max-model-len "${MAX_LEN}" \
206
+ --gpu-memory-utilization "${GPU_UTIL}" \
207
+ --enable-auto-tool-choice \
208
+ --tool-call-parser qwen3_xml \
209
+ --reasoning-parser qwen3 \
210
+ --chat-template "${TEMPLATE_PATH}" \
211
+ --default-chat-template-kwargs '{"enable_thinking": true}' \
212
+ --trust-remote-code \
213
+ --limit-mm-per-prompt '{"image":4,"video":0}' \
214
+ --max-num-seqs 4 \
215
+ --kv-cache-dtype bfloat16 \
216
+ --attention-backend FLASH_ATTN \
217
+ --max-num-batched-tokens 8192 \
218
+ --compilation-config '{"cudagraph_mode": "PIECEWISE"}' \
219
+ --api-key "${API_KEY}" \
220
+ > "${LOG}" 2>&1 &
221
+
222
+ SERVER_PID=$!
223
+ echo "${SERVER_PID}" > "${PIDFILE}"
224
+ disown
225
+ echo "Servidor lanzado (PID ${SERVER_PID}, guardado en ${PIDFILE}). Logs: ${LOG}"
226
+
227
+ # ---------------------------------------------------------------------------
228
+ # Progreso de carga en vivo (opcional). tqdm de vLLM escribe en el log.
229
+ # ---------------------------------------------------------------------------
230
+ TAIL_PID=""
231
+ if [ "$SHOW_PROGRESS" = "1" ]; then
232
+ echo "── Progreso de carga (SHOW_PROGRESS=1) ───────────────────────"
233
+ tail -f "$LOG" &
234
+ TAIL_PID=$!
235
+ fi
236
+ stop_tail() { [ -n "$TAIL_PID" ] && kill "$TAIL_PID" 2>/dev/null || true; TAIL_PID=""; }
237
+
238
+ # ---------------------------------------------------------------------------
239
+ # Espera a que cargue el modelo (/health no requiere API key)
240
+ # ---------------------------------------------------------------------------
241
+ [ "$SHOW_PROGRESS" = "1" ] || echo "Esperando a que el modelo cargue (puede tardar varios minutos)..."
242
+ until curl -sf "http://localhost:${PORT}/health" > /dev/null 2>&1; do
243
+ if ! kill -0 "$SERVER_PID" 2>/dev/null; then
244
+ stop_tail
245
+ echo "ERROR: el servidor murió durante el arranque. Últimas líneas:"
246
+ tail -n 40 "$LOG"
247
+ rm -f "$PIDFILE"
248
+ exit 1
249
+ fi
250
+ sleep 3
251
+ done
252
+
253
+ stop_tail
254
+ [ "$SHOW_PROGRESS" = "1" ] && echo "──────────────────────────────────────────────────────────────"
255
+
256
+ echo "OK: servidor listo en http://localhost:${PORT}/v1 (sigue corriendo en segundo plano)"
257
+ echo " Modelo expuesto: ${SERVED_NAME}"
258
+ echo " Apaga el servidor: ./stop_ornith.sh (o: kill \$(cat ${PIDFILE}))"
259
+
260
+
261
+ ```
262
+
263
+ # !chmod +x stop_ornith.sh
264
+
265
+ ```sh
266
+ #!/usr/bin/env bash
267
+ set -euo pipefail
268
+
269
+ # Apaga el servidor vLLM de Ornith lanzado por serve_ornith_vllm.sh.
270
+ # Usa el mismo PIDFILE por defecto; puedes sobreescribirlo con la variable PIDFILE.
271
+ PIDFILE="${PIDFILE:-ornith_server.pid}"
272
+
273
+ if [ ! -f "$PIDFILE" ]; then
274
+ echo "No encontré $PIDFILE."
275
+ echo "Busca el proceso a mano con: pgrep -af 'vllm serve'"
276
+ exit 0
277
+ fi
278
+
279
+ PID="$(cat "$PIDFILE")"
280
+
281
+ if ! kill -0 "$PID" 2>/dev/null; then
282
+ echo "El proceso $PID ya no estaba corriendo."
283
+ rm -f "$PIDFILE"
284
+ exit 0
285
+ fi
286
+
287
+ # 1) SIGTERM al proceso principal (vLLM cierra sus workers de engine al recibirlo).
288
+ echo "Enviando SIGTERM al servidor (PID $PID)..."
289
+ kill "$PID" 2>/dev/null || true
290
+
291
+ # 2) Espera hasta 15s a que muera limpio.
292
+ for _ in $(seq 1 15); do
293
+ kill -0 "$PID" 2>/dev/null || break
294
+ sleep 1
295
+ done
296
+
297
+ # 3) Si sigue vivo, mata también a sus hijos huérfanos y fuerza SIGKILL.
298
+ if kill -0 "$PID" 2>/dev/null; then
299
+ echo "No respondió a SIGTERM; forzando SIGKILL..."
300
+ pkill -9 -P "$PID" 2>/dev/null || true # workers/subprocesos del engine
301
+ kill -9 "$PID" 2>/dev/null || true
302
+ sleep 1
303
+ fi
304
+
305
+ if kill -0 "$PID" 2>/dev/null; then
306
+ echo "AVISO: el PID $PID sigue vivo. Revísalo con: pgrep -af 'vllm serve'"
307
+ else
308
+ echo "Servidor detenido (PID $PID)."
309
+ fi
310
+
311
+ rm -f "$PIDFILE"
312
+
313
+ ```
314
+
315
+
316
+
317
+ # Code Python
318
+
319
+ ```py
320
+ MODEL = "Ornith-Agents-A1-3.7-35B-A3B-dare_ties" # debe coincidir EXACTO con --served-model-name
321
+
322
+
323
+ import os
324
+ from openai import OpenAI
325
+
326
+ BASE_URL = os.getenv("OPENAI_BASE_URL", "http://localhost:8000/v1")
327
+ API_KEY = os.getenv("OPENAI_API_KEY", "EMPTY")
328
+
329
+ client = OpenAI(base_url=BASE_URL, api_key=API_KEY)
330
+
331
+ # Toma el primer modelo que exponga el server en vez de hardcodearlo
332
+ MODEL = client.models.list().data[0].id
333
+ print("Usando modelo:", MODEL)
334
+ ```
335
+
336
+
337
+
338
+ ```py
339
+ import base64, mimetypes, time
340
+ from pathlib import Path
341
+
342
+ def image_to_data_uri(path):
343
+ """Convierte una imagen local a data URI base64 para el endpoint OpenAI."""
344
+ path = Path(path)
345
+ mime = mimetypes.guess_type(path.name)[0] or "image/png"
346
+ b64 = base64.b64encode(path.read_bytes()).decode()
347
+ return f"data:{mime};base64,{b64}"
348
+
349
+
350
+ def chat_stream(prompt, image_path=None, system=None, thinking=True,
351
+ temperature=0.6, top_p=0.95, max_tokens=1024,
352
+ top_k=65, min_p=0.0):
353
+ """
354
+ Stream contra el server vLLM de Ornith.
355
+ Devuelve (reasoning, answer, stats) donde stats es un dict con métricas.
356
+ """
357
+ # ─── Construye el contenido del turno de usuario ──────────────────
358
+ if image_path:
359
+ user_content = [
360
+ {"type": "text", "text": prompt},
361
+ {"type": "image_url",
362
+ "image_url": {"url": image_to_data_uri(image_path)}},
363
+ ]
364
+ else:
365
+ user_content = prompt
366
+
367
+ messages = []
368
+ if system:
369
+ messages.append({"role": "system", "content": system})
370
+ messages.append({"role": "user", "content": user_content})
371
+
372
+ # ─── Lanza el stream ──────────────────────────────────────────────
373
+ t_start = time.perf_counter()
374
+ stream = client.chat.completions.create(
375
+ model=MODEL,
376
+ messages=messages,
377
+ temperature=temperature,
378
+ top_p=top_p,
379
+ max_tokens=max_tokens,
380
+ stream=True,
381
+ stream_options={"include_usage": True}, # ← asegura usage en el último chunk
382
+ extra_body={
383
+ "chat_template_kwargs": {"enable_thinking": thinking},
384
+ "top_k": top_k,
385
+ "min_p": min_p,
386
+ "do_sample":True
387
+
388
+ },
389
+ )
390
+
391
+ # ─── Consume los deltas ───────────────────────────────────────────
392
+ reasoning_parts, answer_parts = [], []
393
+ in_answer = False
394
+ t_first = None # time-to-first-token
395
+ usage = None # lo trae el chunk final
396
+ finish_reason = None # ← nuevo
397
+ for chunk in stream:
398
+ # El chunk final (con usage) trae choices vacío.
399
+ if getattr(chunk, "usage", None):
400
+ usage = chunk.usage
401
+ if not chunk.choices:
402
+ continue
403
+
404
+ choice = chunk.choices[0]
405
+ if choice.finish_reason is not None: # ← nuevo
406
+ finish_reason = choice.finish_reason
407
+ delta = chunk.choices[0].delta
408
+
409
+ # 1) cadena de pensamiento (mientras dura el bloque <think>)
410
+ rc = getattr(delta, "reasoning", None)
411
+ if rc:
412
+ if t_first is None:
413
+ t_first = time.perf_counter()
414
+ if not reasoning_parts:
415
+ print("===== RAZONAMIENTO (<think>) =====")
416
+ print(rc, end="", flush=True)
417
+ reasoning_parts.append(rc)
418
+
419
+ # 2) respuesta final (empieza cuando se cierra el razonamiento)
420
+ if delta.content:
421
+ if t_first is None:
422
+ t_first = time.perf_counter()
423
+ if not in_answer:
424
+ print("\n\n===== RESPUESTA =====")
425
+ in_answer = True
426
+ print(delta.content, end="", flush=True)
427
+ answer_parts.append(delta.content)
428
+
429
+ t_end = time.perf_counter()
430
+
431
+ # ─── Métricas ─────────────────────────────────────────────────────
432
+ total_time = t_end - t_start
433
+ ttft = (t_first - t_start) if t_first is not None else None
434
+ gen_time = (t_end - t_first) if t_first is not None else total_time
435
+
436
+ # tokens de salida: usa el usage real del server; si no llega, cae a un estimado
437
+ if usage is not None:
438
+ out_tokens = usage.completion_tokens
439
+ prompt_tokens = usage.prompt_tokens
440
+ else:
441
+ out_tokens = len(reasoning_parts) + len(answer_parts) # estimado grosero
442
+ prompt_tokens = None
443
+
444
+ # tok/s de decode (excluye el TTFT, que es el estándar para medir velocidad de generación)
445
+ tok_s = out_tokens / gen_time if gen_time > 0 else float("nan")
446
+
447
+ stats = {
448
+ "prompt_tokens": prompt_tokens,
449
+ "output_tokens": out_tokens,
450
+ "ttft_s": ttft,
451
+ "gen_time_s": gen_time,
452
+ "total_time_s": total_time,
453
+ "tokens_per_s": tok_s,
454
+ }
455
+
456
+ print(f"\n\n===== MÉTRICAS =====")
457
+ print(f"Tokens de salida : {out_tokens}")
458
+ if ttft is not None:
459
+ print(f"TTFT : {ttft:.3f} s")
460
+ print(f"Tiempo generación: {gen_time:.3f} s")
461
+ print(f"Tiempo total : {total_time:.3f} s")
462
+ print(f"Velocidad : {tok_s:.2f} tok/s")
463
+
464
+ stats["finish_reason"] = finish_reason
465
+ print(f"Finish reason : {finish_reason}")
466
+
467
+ return "".join(reasoning_parts), "".join(answer_parts), stats
468
+ ```
469
+
470
+
471
+ ```py
472
+ p="""dame todas tus funcionalidades de terminal"""
473
+ # Imagen con razonamiento (p.ej. "explica qué hace este diagrama")
474
+ reasoning, answer, stats = chat_stream(
475
+ p,
476
+ thinking=True,
477
+ max_tokens=45000,
478
+ temperature=0.1,
479
+ top_k=64
480
+ )
481
+
482
+ """
483
+ ===== RAZONAMIENTO (<think>) =====
484
+ The user is asking for all terminal functionalities in Spanish. I need to clarify that I'm an AI assistant and don't have a terminal myself, but I can help with terminal commands and concepts. I should provide a comprehensive overview of common terminal functionalities and commands that users typically need.
485
+
486
+ Let me organize this in a helpful way, covering:
487
+ 1. File operations
488
+ 2. Navigation
489
+ 3. System information
490
+ 4. Process management
491
+ 5. Text manipulation
492
+ 6. Network commands
493
+ 7. Permissions
494
+ 8. Package management
495
+ 9. And other common terminal tasks
496
+
497
+ I'll present this in Spanish since that's the language the user used.
498
+
499
+
500
+ ===== RESPUESTA =====
501
+
502
+
503
+ # Funcionalidades de Terminal (Linux/Unix/macOS)
504
+
505
+ Aunque soy un asistente de IA y no tengo una terminal propia, puedo ayudarte con **comandos y funcionalidades de terminal**. Aquí tienes un resumen completo:
506
+
507
+ ## 📁 Operaciones con Archivos y Directorios
508
+ | Comando | Descripción |
509
+ |---------|-------------|
510
+ | `ls` | Listar archivos |
511
+ | `cd [ruta]` | Cambiar directorio |
512
+ | `pwd` | Mostrar ruta actual |
513
+ | `mkdir [nombre]` | Crear directorio |
514
+ | `touch [archivo]` | Crear archivo vacío |
515
+ | `cp [origen] [destino]` | Copiar archivos |
516
+ | `mv [origen] [destino]` | Mover/renombrar |
517
+ | `rm [archivo]` | Eliminar archivo |
518
+ | `rm -r [carpeta]` | Eliminar directorio recursivo |
519
+ | `ln -s [origen] [destino]` | Crear enlace simbólico |
520
+
521
+ ## 🔍 Búsqueda y Filtrado
522
+ | Comando | Descripción |
523
+ |---------|-------------|
524
+ | `find [ruta] -name [patrón]` | Buscar archivos |
525
+ | `grep [patrón] [archivo]` | Buscar texto en archivos |
526
+ | `locate [nombre]` | Buscar archivos (base de datos) |
527
+ | `which [comando]` | Mostrar ruta de comando |
528
+
529
+ ## 🖥️ Información del Sistema
530
+ | Comando | Descripción |
531
+ |---------|-------------|
532
+ | `uname -a` | Información del sistema |
533
+ | `df -h` | Espacio en disco |
534
+ | `free -h` | Memoria RAM |
535
+ | `top` / `htop` | Proceso en tiempo real |
536
+ | `ps aux` | Procesos activos |
537
+ | `whoami` | Usuario actual |
538
+ | `date` | Fecha y hora |
539
+ | `uptime` | Tiempo de actividad |
540
+
541
+ ## 🌐 Red y Conectividad
542
+ | Comando | Descripción |
543
+ |---------|-------------|
544
+ | `ping [host]` | Probar conectividad |
545
+ | `curl [url]` | Transferencia de datos |
546
+ | `wget [url]` | Descargar archivos |
547
+ | `ssh [usuario@host]` | Conexión remota |
548
+ | `scp [origen] [destino]` | Copia segura remota |
549
+ | `netstat -tuln` | Puertos abiertos |
550
+ | `ifconfig` / `ip addr` | Información de red |
551
+ | `nslookup [dominio]` | Consultas DNS |
552
+
553
+ ## 🔐 Permisos y Usuarios
554
+ | Comando | Descripción |
555
+ |---------|-------------|
556
+ | `chmod [modos] [archivo]` | Cambiar permisos |
557
+ | `chown [usuario] [archivo]` | Cambiar propietario |
558
+ | `sudo [comando]` | Ejecutar como root |
559
+ | `su -` | Cambiar a usuario root |
560
+ | `passwd` | Cambiar contraseña |
561
+
562
+ ## 📦 Gestión de Paquetes
563
+ | Distribución | Comandos |
564
+ |--------------|----------|
565
+ | **Ubuntu/Debian** | `apt update`, `apt install [paquete]`, `apt remove [paquete]` |
566
+ | **CentOS/RHEL** | `yum install [paquete]`, `dnf install [paquete]` |
567
+ | **Arch Linux** | `pacman -S [paquete]`, `pacman -R [paquete]` |
568
+ | **macOS** | `brew install [paquete]` |
569
+
570
+ ## 📝 Manipulación de Texto
571
+ | Comando | Descripción |
572
+ |---------|-------------|
573
+ | `cat [archivo]` | Mostrar contenido |
574
+ | `less [archivo]` | Ver archivo página por página |
575
+ | `head [archivo]` | Primeras líneas |
576
+ | `tail [archivo]` | Últimas líneas |
577
+ | `wc [archivo]` | Contar líneas, palabras, caracteres |
578
+ | `sort [archivo]` | Ordenar líneas |
579
+ | `uniq [archivo]` | Eliminar duplicados |
580
+ | `cut [opciones]` | Extraer columnas |
581
+ | `sed [comando] [archivo]` | Edición de texto |
582
+ | `awk [comando] [archivo]` | Procesamiento de texto |
583
+
584
+ ## 🔄 Redirección y Pipes
585
+ | Símbolo | Descripción |
586
+ |---------|-------------|
587
+ | `>` | Redirigir salida (sobrescribir) |
588
+ | `>>` | Redirigir salida (apender) |
589
+ | `<` | Redirigir entrada |
590
+ | `\|` | Pipe (enviar salida a otro comando) |
591
+ | `2>&1` | Redirigir errores a stdout |
592
+ | `&` | Ejecutar en segundo plano |
593
+ | `&&` | Ejecutar si el anterior tiene éxito |
594
+ | `||` | Ejecutar si el anterior falla |
595
+
596
+ ## 🛠️ Utilidades Varias
597
+ | Comando | Descripción |
598
+ |---------|-------------|
599
+ | `history` | Historial de comandos |
600
+ | `alias [nombre]=[comando]` | Crear alias |
601
+ | `clear` | Limpiar pantalla |
602
+ | `man [comando]` | Manual de ayuda |
603
+ | `echo [texto]` | Mostrar texto |
604
+ | `export [variable]=[valor]` | Definir variable de entorno |
605
+ | `source ~/.bashrc` | Recargar configuración |
606
+ | `kill [PID]` | Terminar proceso |
607
+ | `killall [nombre]` | Terminar por nombre |
608
+ | `tar [opciones] [archivo]` | Comprimir/descomprimir |
609
+ | `zip` / `unzip` | Archivos ZIP |
610
+ | `rsync [origen] [destino]` | Sincronización remota |
611
+
612
+ ## 🎯 Comandos Avanzados
613
+ | Comando | Descripción |
614
+ |---------|-------------|
615
+ | `xargs` | Construir y ejecutar comandos |
616
+ | `tee` | Leer y escribir simultáneamente |
617
+ | `nc` (netcat) | Herramienta de red |
618
+ | `strace` | Rastrear llamadas al sistema |
619
+ | `lsof` | Listar archivos abiertos |
620
+ | `iotop` | Monitoreo de E/S de disco |
621
+ | `nethogs` | Tráfico de red por proceso |
622
+
623
+ ---
624
+
625
+ ## 💡 Consejos Útiles
626
+
627
+ 1. **Tabulador**: Autocompletar comandos y archivos
628
+ 2. **Ctrl+C**: Cancelar comando
629
+ 3. **Ctrl+Z**: Pausar comando
630
+ 4. **Ctrl+D**: Salir de terminal
631
+ 5. **Ctrl+L**: Limpiar pantalla
632
+ 6. **Ctrl+R**: Buscar en historial
633
+ 7. **!!**: Reejecutar último comando
634
+ 8. **!$**: Último argumento del comando anterior
635
+
636
+ ---
637
+
638
+ ¿Hay alguna funcionalidad específica que te interese o algún comando que quieras que te explique con más detalle? 🚀
639
+
640
+ ===== MÉTRICAS =====
641
+ Tokens de salida : 1698
642
+ TTFT : 0.058 s
643
+ Tiempo generación: 11.665 s
644
+ Tiempo total : 11.723 s
645
+ Velocidad : 145.56 tok/s
646
+ Finish reason : stop
647
+ """
648
+
649
+ ```
650
+
651
+
652
+ ```py
653
+ p="""hola, quien eres? explicame """
654
+ # Imagen con razonamiento (p.ej. "explica qué hace este diagrama")
655
+ reasoning, answer, stats = chat_stream(
656
+ p,
657
+ thinking=True,
658
+ max_tokens=45000,
659
+ temperature=0.1,
660
+ top_k=64
661
+ )
662
+
663
+ """
664
+ ===== RAZONAMIENTO (<think>) =====
665
+ Okay, the user is asking "hola, quien eres? explicame" which translates to "Hello, who are you? Explain to me." I need to respond in Spanish since the query is in Spanish.
666
+
667
+ First, I should introduce myself as Qwen3.5, the latest large language model developed by Tongyi Lab. I need to mention my capabilities briefly but clearly. The user might want a concise explanation without too much technical jargon.
668
+
669
+ I should list some key features like handling long contexts, multilingual support, advanced reasoning, code generation, etc. But keep it friendly and approachable. Maybe start with a greeting and then explain my purpose.
670
+
671
+ Wait, the user might not know what a language model is. So I should explain that I'm an AI assistant designed to help with various tasks like answering questions, creating text, coding, etc. Also, mention that I can process and generate text in many languages.
672
+
673
+ I need to make sure the response is in Spanish, natural and conversational. Avoid using too many technical terms. Maybe structure it as: greeting, who I am, what I can do, and offer help.
674
+
675
+ Check if there's any specific thing the user might need. Since they just asked who I am, keep it general but informative. Don't overload with too many details. Maybe mention my context window size, multilingual support, and some use cases.
676
+
677
+ Also, since I'm Qwen3.5, I should highlight improvements over previous versions if relevant, but maybe keep it simple. Focus on what I can do for the user.
678
+
679
+ Make sure the tone is friendly and helpful. End with an offer to assist them with something specific.
680
+
681
+
682
+ ===== RESPUESTA =====
683
+
684
+
685
+ ¡Hola! Soy Qwen3.5, el modelo de lenguaje a gran escala más reciente desarrollado por Tongyi Lab. Soy una inteligencia artificial diseñada para ayudarte en una amplia variedad de tareas, como responder preguntas, crear textos, escribir código, analizar documentos, traducir idiomas y mucho más.
686
+
687
+ Puedo procesar y generar texto en más de 100 idiomas, entender contextos largos (hasta 256,000 tokens) y resolver problemas complejos en áreas como matemáticas, ciencias o lógica. También tengo capacidades avanzadas en razonamiento, generación de código y análisis de imágenes.
688
+
689
+ ¿En qué te gustaría que te ayude hoy? 😊
690
+
691
+ ===== MÉTRICAS =====
692
+ Tokens de salida : 488
693
+ TTFT : 0.059 s
694
+ Tiempo generación: 3.328 s
695
+ Tiempo total : 3.387 s
696
+ Velocidad : 146.65 tok/s
697
+ Finish reason : stop
698
+ """
699
+ ```
700
+
701
+
702
+ ```py
703
+ p="""hola, quien eres? explicame, quiero que razones en español """
704
+ # Imagen con razonamiento (p.ej. "explica qué hace este diagrama")
705
+ reasoning, answer, stats = chat_stream(
706
+ p,
707
+ thinking=True,
708
+ max_tokens=45000,
709
+ temperature=0.1,
710
+ top_k=64
711
+ )
712
+
713
+ """
714
+ ===== RAZONAMIENTO (<think>) =====
715
+ Thinking Process:
716
+
717
+ 1. **Analyze the Request:**
718
+ * User: "hola, quien eres? explicame, quiero que razones en español" (Hello, who are you? Explain to me, I want you to reason in Spanish).
719
+ * Language: Spanish.
720
+ * Task: Introduce myself (who I am) and explain my capabilities/nature, reasoning in Spanish.
721
+ * Constraint: "quiero que razones en español" (I want you to reason in Spanish). This implies the internal thought process or the explanation should be in Spanish, or at least the output must be in Spanish. Since I'm an AI, I don't "reason" in the human sense, but I generate text based on patterns. The user likely means "respond in Spanish" or "think in Spanish". I will ensure my response is entirely in Spanish.
722
+
723
+ 2. **Identify My Identity:**
724
+ * I am an AI assistant, a large language model trained by Google.
725
+ * I am not a human.
726
+ * I can process text, answer questions, create content, translate, etc.
727
+
728
+ 3. **Draft the Response (Internal Monologue/Drafting in Spanish):**
729
+ * *Greeting:* Hola.
730
+ * *Identity:* Soy un modelo de lenguaje grande, una inteligencia artificial.
731
+ * *Creator:* Fui creado por Google.
732
+ * *Function:* Ayudo con tareas, respondo preguntas, escribo, traduzco, etc.
733
+ * *Reasoning:* No pienso como un humano, pero proceso información para generar respuestas.
734
+ * *Tone:* Amable, claro, directo.
735
+
736
+ 4. **Refine the Response:**
737
+ * Make it engaging.
738
+ * Ensure the "reasoning in Spanish" constraint is met (the output itself is the reasoning/explanation).
739
+ * Clarify that I don't have consciousness or feelings.
740
+
741
+ 5. **Final Polish (Spanish):**
742
+ * "¡Hola! Soy una inteligencia artificial, específicamente un modelo de lenguaje grande."
743
+ * "Fui desarrollado por Google."
744
+ * "Mi función principal es ayudarte con información, tareas creativas, análisis, etc."
745
+ * "Aunque no tengo conciencia ni sentimientos, puedo procesar y generar texto en español y muchos otros idiomas."
746
+ * "¿En qué puedo ayudarte hoy?"
747
+
748
+ 6. **Check Constraints:**
749
+ * Language: Spanish? Yes.
750
+ * Identity explained? Yes.
751
+ * Reasoning in Spanish? Yes (the output is the explanation).
752
+
753
+ 7. **Final Output Generation:** (Matches the drafted polish).
754
+ * Add a bit more detail about how I work (processing patterns) to satisfy "explain to me".
755
+
756
+ *Draft:*
757
+ ¡Hola! Soy una inteligencia artificial, un modelo de lenguaje avanzado desarrollado por Google. No soy un ser humano, por lo que no tengo cuerpo, sentimientos ni conciencia propia.
758
+
759
+ Mi "razonamiento" consiste en procesar la información que me das, buscar patrones en el vasto conjunto de datos con el que fui entrenado y generar una respuesta coherente y útil. Puedo ayudarte a escribir, traducir, resolver problemas, explicar conceptos, programar y mucho más.
760
+
761
+ En resumen, soy una herramienta diseñada para asistirte en tus tareas y responder tus dudas. ¿Hay algo específico en lo que te gustaría que te ayude hoy?
762
+
763
+ 8. **Final Review:** Looks good. Adheres to all instructions.cw
764
+
765
+
766
+ ===== RESPUESTA =====
767
+
768
+
769
+ ¡Hola! Soy una inteligencia artificial, específicamente un modelo de lenguaje grande desarrollado por Google.
770
+
771
+ Para explicarte mejor quién soy:
772
+
773
+ 1. **No soy un ser humano:** No tengo cuerpo, sentimientos, conciencia ni experiencias personales.
774
+ 2. **Soy un programa de software:** Funciono procesando texto y patrones de información. Cuando me haces una pregunta, analizo tu solicitud, busco en mi base de conocimientos (entrenada con una gran cantidad de texto) y genero una respuesta que tenga sentido en español.
775
+ 3. **Mi propósito:** Estoy diseñado para ayudarte. Puedo escribir textos, traducir idiomas, resolver problemas lógicos, explicar conceptos complejos, ayudarte a programar o simplemente conversar.
776
+
777
+ En resumen, soy una herramienta digital creada para asistirte en tus tareas y responder tus dudas de la manera más precisa posible.
778
+
779
+ ¿En qué te gustaría que te ayude hoy?
780
+
781
+ ===== MÉTRICAS =====
782
+ Tokens de salida : 957
783
+ TTFT : 0.057 s
784
+ Tiempo generación: 6.551 s
785
+ Tiempo total : 6.608 s
786
+ Velocidad : 146.08 tok/s
787
+ Finish reason : stop
788
+ """
789
+ ```