docs: huggingface-cli como método principal de descarga + troubleshooting Error: EOF
2bd2f4d verified | license: other | |
| license_name: darkforensic-dual | |
| license_link: LICENSE | |
| language: | |
| - es | |
| - en | |
| tags: | |
| - threat-intelligence | |
| - darkweb | |
| - cybersecurity | |
| - spanish | |
| - qwen2.5 | |
| - lora | |
| - gguf | |
| base_model: Qwen/Qwen2.5-7B-Instruct | |
| pipeline_tag: text-generation | |
| inference: false | |
| # darkforensic-7b | |
| > Asistente threat-intelligence dark-web para CISOs y DPOs europeos. | |
| > Spanish-first. Defensive role only. | |
| > Construido por [Neural Ghost](https://neural-ghost.com) — equipo | |
| > pequeño, plataforma de threat-intel alojada en Europa. | |
| `darkforensic-7b` es un fine-tune LoRA de | |
| [Qwen2.5-7B-Instruct](https://huggingface.co/Qwen/Qwen2.5-7B-Instruct) | |
| entrenado sobre un corpus curado de hallazgos reales de dark-web (Tor + | |
| I2P, 3 290 sitios cubriendo 11 categorías: marketplace, fraud, hacking, | |
| forum, leak, cyberattack, services, etc.) con pares Q&A sintéticos | |
| generados por Anthropic Claude Sonnet 4.6 y filtrados por calidad, | |
| relevancia e intención defensiva. | |
| **Versión actual: v2 (mayo 2026).** | |
| v3 está en entrenamiento continuo — ver sección [Roadmap](#roadmap). | |
| ## Qué hace | |
| Responde preguntas operativas que un CISO, DPO o analista SOC se hace | |
| sobre hallazgos de dark-web: | |
| - *"Hemos visto credenciales nuestras en un combo-list de RaidForums. | |
| ¿Qué hacemos en las próximas 24h?"* | |
| - *"¿Qué IOCs se extraen de esta venta IAB?"* | |
| - *"¿Cómo documentamos esto al comité de cumplimiento?"* | |
| - *"¿Es activo este foro post-RaidForums hoy?"* | |
| En castellano. Con citas a la fuente cuando aplica. Sin inventar hechos | |
| cuando el hallazgo no los contiene. | |
| ## Qué NO hace | |
| - ❌ Explicar cómo atacar sistemas, comprar datos robados, o acceder a | |
| marketplaces. Todo el dataset se filtró por intención defensiva. | |
| - ❌ Atribuir hechos a estados-nación o personas concretas. | |
| - ❌ Procesar o generar contenido clasificado como CSAM. Kill-switch | |
| heredado de la política CSAM-001 de Neural Ghost. | |
| ## Uso previsto | |
| Asistentes de threat-intel internos para **organizaciones medianas | |
| europeas reguladas** (banca cooperativa, mutualidades sanitarias, | |
| hospitales privados, ayuntamientos medianos). Específicamente diseñado | |
| para el contexto regulatorio europeo (Schrems II, RGPD, NIS2, DORA). | |
| NO destinado para: | |
| - Chatbots de propósito general (usa Qwen2.5-7B-Instruct base directamente). | |
| - Threat-intel en inglés (la cobertura inglesa es incidental, no | |
| optimizada). | |
| - Análisis forense sin contexto RAG (el modelo se apoya fuertemente en | |
| hallazgos recuperados; las respuestas standalone son más débiles). | |
| ## Cómo instalar y ejecutar darkforensic-7b en local | |
| Hay tres formas, según tu hardware. Si no sabes cuál elegir, usa la | |
| **Opción A (Ollama)**: es la más rápida y funciona en cualquier laptop | |
| con 8 GB de RAM o más. | |
| ### Requisitos por opción | |
| | Opción | RAM mínima | GPU | Disco | Velocidad típica | | |
| |---|---|---|---|---| | |
| | A. Ollama (Q4_K_M) | 8 GB | no necesaria | ~5 GB | 5–15 tok/s en CPU; 30–60 con GPU | | |
| | B. llama.cpp (Q4_K_M) | 8 GB | no necesaria | ~5 GB | igual que Ollama, sin server | | |
| | C. Transformers + LoRA | 24 GB GPU | sí, A100/H100 ideal | ~16 GB | 20–40 tok/s en H100 | | |
| --- | |
| ### Opción A — Ollama (recomendada) | |
| Funciona en Linux, macOS, Windows. Es lo que usamos en producción en el | |
| VPS de Neural Ghost. | |
| **1. Instala Ollama** (1 comando): | |
| ```bash | |
| # Linux / macOS | |
| curl -fsSL https://ollama.com/install.sh | sh | |
| # Windows: descarga el instalador desde https://ollama.com/download | |
| ``` | |
| Verifica que está instalado: | |
| ```bash | |
| ollama --version # debe imprimir "ollama version is X.Y.Z" | |
| ``` | |
| **2. Descarga el GGUF Q4_K_M y el Modelfile** de este repo: | |
| ⭐ **Recomendado: usa `huggingface-cli`** (gestiona redirects de HF, hace | |
| resume si se corta la conexión, valida checksum): | |
| ```bash | |
| mkdir darkforensic && cd darkforensic | |
| # Instala el cliente HF si no lo tienes | |
| pip install -U "huggingface_hub[cli]" | |
| # En Debian/Ubuntu/Kali reciente puede pedir --break-system-packages | |
| # o usa --user en su lugar: | |
| # pip install -U --user "huggingface_hub[cli]" | |
| # Descarga sólo los 2 archivos que necesitas (no todo el repo) | |
| huggingface-cli download neuralghost/darkforensic-7b \ | |
| darkforensic-7b-v2-q4_k_m.gguf Modelfile \ | |
| --local-dir . --local-dir-use-symlinks False | |
| # Verifica el tamaño (debe imprimir 4.4G — Hugging Face muestra 4.68 GB | |
| # pero `ls -lh` redondea a unidades binarias) | |
| ls -lh darkforensic-7b-v2-q4_k_m.gguf | |
| ``` | |
| <details> | |
| <summary>Alternativa: `wget` o `curl` (si no puedes instalar `pip`)</summary> | |
| ```bash | |
| mkdir darkforensic && cd darkforensic | |
| # wget — usa el flag ?download=true para evitar el redirect de HF que | |
| # rompe descargas silenciosas con curl. -c permite reanudar si se corta. | |
| wget -c -O darkforensic-7b-v2-q4_k_m.gguf \ | |
| "https://huggingface.co/neuralghost/darkforensic-7b/resolve/main/darkforensic-7b-v2-q4_k_m.gguf?download=true" | |
| wget -O Modelfile \ | |
| "https://huggingface.co/neuralghost/darkforensic-7b/raw/main/Modelfile" | |
| # Verifica que el GGUF NO está vacío: | |
| ls -lh darkforensic-7b-v2-q4_k_m.gguf # debe imprimir 4.4G | |
| ``` | |
| `curl -L -o ...` también funciona en la mayoría de equipos, pero hemos | |
| visto casos (VMs Kali con NAT inestable, máquinas con TLS antiguo) en | |
| los que curl crea el archivo destino, sigue un redirect 302 al CDN de | |
| HF y luego falla silenciosamente sin reportar error. Resultado: | |
| archivo de 0 bytes y `Error: EOF` al hacer `ollama create`. Si te | |
| pasa, usa `wget -c` o `huggingface-cli` y se resuelve. | |
| </details> | |
| **3. Importa el modelo a Ollama**: | |
| ```bash | |
| ollama create darkforensic-7b -f Modelfile | |
| ``` | |
| Esto tarda 30 s – 2 min la primera vez (Ollama indexa el GGUF y lo deja | |
| listo). Verifica que está: | |
| ```bash | |
| ollama list | |
| # debe aparecer "darkforensic-7b" con el tag latest | |
| ``` | |
| **4. Pruébalo**: | |
| ```bash | |
| ollama run darkforensic-7b "Hemos detectado credenciales de empleados \ | |
| nuestros en un combo-list publicado en RaidForums. ¿Qué hago en las \ | |
| próximas 24 horas?" | |
| ``` | |
| Te debería responder en castellano con un plan estructurado: | |
| resumen → acciones inmediatas → IOCs → marco regulatorio (RGPD/NIS2). | |
| **5. Para usarlo desde tu aplicación** (Python, etc.) — Ollama expone una | |
| API REST en `http://localhost:11434`: | |
| ```python | |
| import httpx, json | |
| resp = httpx.post( | |
| "http://localhost:11434/api/generate", | |
| json={ | |
| "model": "darkforensic-7b", | |
| "prompt": "Pregunta operativa CISO/DPO aquí…", | |
| "stream": False, | |
| }, | |
| timeout=120, | |
| ) | |
| print(resp.json()["response"]) | |
| ``` | |
| **6. Detenerlo / liberar memoria** cuando no lo uses: | |
| ```bash | |
| ollama stop darkforensic-7b | |
| ``` | |
| --- | |
| ### Opción B — llama.cpp (sin servidor, ideal si quieres scriptear) | |
| Si prefieres no levantar el daemon de Ollama, puedes cargar el GGUF | |
| directamente con `llama.cpp`: | |
| ```bash | |
| # Instalar llama-cpp-python con soporte CUDA (omite CMAKE_ARGS si no tienes GPU) | |
| CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python --upgrade --force-reinstall --no-cache-dir | |
| ``` | |
| Y úsalo así desde Python: | |
| ```python | |
| from llama_cpp import Llama | |
| llm = Llama( | |
| model_path="darkforensic-7b-v2-q4_k_m.gguf", | |
| n_ctx=8192, | |
| n_gpu_layers=-1, # -1 = todas las capas en GPU; 0 = solo CPU | |
| chat_format="chatml", # Qwen2.5 usa ChatML | |
| ) | |
| response = llm.create_chat_completion( | |
| messages=[ | |
| {"role": "system", "content": | |
| "Eres darkforensic, asistente threat-intel dark-web para CISOs/DPOs " | |
| "europeos. Responde en castellano, conciso, con acciones operativas y " | |
| "el marco regulatorio (RGPD/NIS2/DORA) si aplica."}, | |
| {"role": "user", "content": | |
| "¿Qué IOCs debo extraer de este finding y cómo los cruzo con mi SIEM?"}, | |
| ], | |
| temperature=0.3, | |
| max_tokens=1024, | |
| ) | |
| print(response["choices"][0]["message"]["content"]) | |
| ``` | |
| --- | |
| ### Opción C — Transformers + LoRA (necesitas GPU) | |
| Esta opción carga el **modelo base** (Qwen2.5-7B-Instruct, ~16 GB en | |
| bfloat16) **y aplica el LoRA adapter encima** (162 MB). Útil si quieres | |
| seguir entrenando, mergear con otro adapter, o tener máxima precisión. | |
| **1. Instalar dependencias**: | |
| ```bash | |
| pip install transformers peft accelerate bitsandbytes torch | |
| ``` | |
| **2. Cargar y usar**: | |
| ```python | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| from peft import PeftModel | |
| # Base model en bf16 (16 GB VRAM) — o en 4-bit con bnb si tienes menos | |
| base = AutoModelForCausalLM.from_pretrained( | |
| "Qwen/Qwen2.5-7B-Instruct", | |
| torch_dtype=torch.bfloat16, | |
| device_map="auto", | |
| ) | |
| model = PeftModel.from_pretrained(base, "neuralghost/darkforensic-7b") | |
| tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct") | |
| messages = [ | |
| {"role": "system", "content": "Eres darkforensic, asistente threat-intel..."}, | |
| {"role": "user", "content": "Tu pregunta aquí"}, | |
| ] | |
| inputs = tokenizer.apply_chat_template( | |
| messages, return_tensors="pt", add_generation_prompt=True | |
| ).to(model.device) | |
| out = model.generate(inputs, max_new_tokens=600, do_sample=True, temperature=0.3) | |
| print(tokenizer.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True)) | |
| ``` | |
| **Si tienes menos de 24 GB de VRAM** — carga el base en 4-bit: | |
| ```python | |
| from transformers import BitsAndBytesConfig | |
| bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16) | |
| base = AutoModelForCausalLM.from_pretrained( | |
| "Qwen/Qwen2.5-7B-Instruct", quantization_config=bnb, device_map="auto", | |
| ) | |
| # (el resto igual) | |
| ``` | |
| Con 4-bit cabe en ~6 GB de VRAM (RTX 3060 12 GB, RTX 4060 8 GB con stretching). | |
| --- | |
| ## Troubleshooting | |
| | Síntoma | Causa probable | Solución | | |
| |---|---|---| | |
| | **`ollama create` → `Error: EOF`** o `parsing GGUF` falla | **El GGUF está vacío o incompleto.** Comprueba con `ls -lh darkforensic-7b-v2-q4_k_m.gguf`: si imprime `0` o un número menor a `4.4G`, la descarga falló silenciosamente (típico en VMs con NAT inestable cuando se usa `curl`). | Re-descargar con `huggingface-cli download …` (gestiona redirects + resume + checksum). Ver paso 2 de la instalación. Si solo tienes `wget`/`curl`, usa el sufijo `?download=true` en la URL y `wget -c` para reanudar. | | |
| | `ollama create` se queda colgado en `gathering model components` | El Modelfile referencia un GGUF que no existe en esa carpeta | Verifica que `darkforensic-7b-v2-q4_k_m.gguf` está en el mismo directorio que el `Modelfile`: `ls` debe mostrar ambos | | |
| | `Error: out of memory` al usarlo | Estás cargando fp16/bf16 en GPU pequeña, o varios modelos a la vez en Ollama | Usa Q4_K_M; `ollama stop` los otros modelos; o reduce `num_ctx` en el Modelfile (8192 → 4096) | | |
| | Respuestas muy lentas (< 2 tok/s) | Corriendo en CPU sin AVX2, o el modelo no cabe en RAM y está paginando a disco | Verifica `grep avx2 /proc/cpuinfo`; baja a 4 hilos con `OLLAMA_NUM_PARALLEL=1`; cierra otras apps con memoria pesada | | |
| | Responde en inglés cuando le hablas en castellano | Faltó el system prompt o el primer mensaje es muy corto | Asegúrate de pasar el system del Modelfile (Ollama lo aplica automáticamente con `ollama run`); con la API REST mándalo explícito | | |
| | "Permission denied" al ejecutar | Falta permisos en `~/.ollama` | `chmod -R u+rw ~/.ollama` | | |
| | El modelo alucina IOCs específicos (BTC addresses, hashes) | El modelo describe IOCs, NO los memoriza — por diseño | Es el comportamiento correcto, no un bug. Para IOCs verbatim necesitas el RAG sobre tu corpus indexado, no el LLM solo | | |
| | Estás en una **VM** y la descarga se corta a mitad | NAT/throughput inestable + curl + archivo de 4.7 GB es un combo malo | Usa `huggingface-cli download` (con resume automático), o `wget -c` para reanudar si se corta. Aumenta la RAM de la VM a 8 GB+ y el disco a 50 GB+ para tener margen tras descargar | | |
| ## Integración con un pipeline RAG (recomendado para producción) | |
| DarkForensic-7B está pensado para responder **con contexto recuperado** de | |
| tu propio corpus de hallazgos. Sin RAG es un asistente; con RAG es una | |
| herramienta de análisis. El patrón básico: | |
| ```python | |
| # 1. El usuario pregunta algo sobre un finding | |
| question = "¿Cómo respondo a este leak de credenciales?" | |
| # 2. Tu sistema RAG recupera los k findings más relevantes del corpus | |
| context_findings = your_rag.retrieve(question, k=5) | |
| context_text = "\n\n".join( | |
| f"[finding {f.id}] {f.title}\n{f.snippet}" for f in context_findings | |
| ) | |
| # 3. Se manda al modelo en el system o como contexto previo | |
| prompt = f"""CONTEXTO (5 findings relevantes de tu corpus dark-web): | |
| {context_text} | |
| PREGUNTA DEL ANALISTA: {question} | |
| Responde citando los finding IDs cuando uses información de ellos. | |
| Si los findings no contienen información suficiente, dilo explícitamente.""" | |
| # 4. Llama al modelo (Ollama u otro) | |
| response = httpx.post("http://localhost:11434/api/generate", | |
| json={"model": "darkforensic-7b", "prompt": prompt, "stream": False}, | |
| timeout=120).json()["response"] | |
| ``` | |
| La plataforma completa que envuelve esto (crawler Tor/I2P, scoring, | |
| RAG vectorial, alertas, UI) es **GhostNet Intelligence Platform** y se | |
| comercializa por separado. Contacto: neural@neural-ghost.com. | |
| ## Detalles del entrenamiento | |
| | | | | |
| |---|---| | |
| | Base model | Qwen2.5-7B-Instruct (Apache-2.0) | | |
| | Método | QLoRA r=32, alpha=64, dropout=0.05 | | |
| | Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj | | |
| | Sequence length | 2048 | | |
| | Effective batch size | 16 | | |
| | Learning rate | 2e-4 cosine, warmup 3% | | |
| | Epochs | 3 | | |
| | Hardware | 1× H100 80GB (RunPod), ~10h | | |
| | Coste training | ~$30 USD compute + ~$36 generación dataset = ~$66 total | | |
| | Datos training | 3 290 hallazgos dark-web → 9 376 pares Q&A sintéticos filtrados | | |
| | Split eval | 937 pares held-out (10%) | | |
| ## Evaluación | |
| Evaluación head-to-head contra el **teacher (Claude Sonnet 4.6)** sobre | |
| 15 preguntas representativas tomadas del corpus de producción, juzgadas | |
| por Claude Sonnet 4.6 sobre una rúbrica de 4 dimensiones (escala 1–10). | |
| Ambos modelos limitados a `max_tokens = 1500` para comparación justa. | |
| | Dimensión | Claude Sonnet 4.6 (teacher) | **darkforensic-7b** | | |
| |---|---:|---:| | |
| | Exactitud | 6.73 | **5.67** | | |
| | Profundidad | 6.93 | **5.13** | | |
| | Accionabilidad | 7.20 | **6.20** | | |
| | Claridad | 7.60 | **7.13** | | |
| | **Avg** | **7.12** | **6.03** | | |
| | Respuestas críticas (avg ≤ 3.0) | 0/15 | **0/15** | | |
| **Interpretación honesta**: | |
| - **vs Claude Sonnet 4.6 (teacher)**: alcanza el ~85% de la calidad de | |
| un modelo ~100× más caro y que requiere API externa. Pierde sobre | |
| todo en profundidad analítica — un 7B no es un trillón-parámetros. | |
| Diferencia en claridad casi nula (7.13 vs 7.60). | |
| - **vs base (qwen2.5:3b)**: mejora consistente en todas las | |
| dimensiones; ganancia media geométrica +7.4% (ver paper). | |
| - **Críticos**: 0 de 15. Operativamente no produce respuestas vacías | |
| o dañinas. | |
| **Caveats metodológicos** (declarados para transparencia): | |
| - 15 preguntas es muestra pequeña. Estadísticamente preliminar. | |
| - Single-judge eval: Claude Sonnet 4.6 fue teacher Y juez — sesgo | |
| conocido en literatura (favorece su propio style). v3 introducirá un | |
| segundo juez independiente y reportará inter-judge agreement. | |
| - El primer run del eval incluyó Gemini 2.5 Flash como referencia | |
| comercial peer, pero las respuestas se truncaron por un problema | |
| de configuración del cliente (`max_tokens` insuficiente, | |
| respuestas <150 caracteres en la mitad de las preguntas). Para | |
| no sesgar la comparación con un cliente mal configurado, **Gemini | |
| se excluyó** del chart final. Se re-ejecutará en v3 con | |
| configuración correcta. | |
| **v3** ampliará el eval a 100+ preguntas con dos jueces independientes. | |
| ## Roadmap | |
| **v2 (publicado, mayo 2026)** — modelo actual. Cumple el caso de uso | |
| principal (asistente de un analista con RAG sobre hallazgos), pero hay | |
| margen para mejorar en profundidad de análisis y en categorías | |
| minoritarias del corpus. | |
| **v3 (en entrenamiento)** — objetivos: | |
| - Doblar el corpus a ~18 000 pares Q&A. | |
| - Incorporar feedback real de los analistas que usan v2 (preferencias | |
| thumbs-up/down vía DPO). | |
| - Ampliar cobertura de árabe y mandarín (categorías minoritarias hoy). | |
| - Reducir la brecha vs Claude Sonnet 4.6 a < 10%. | |
| Si quieres recibir aviso cuando se publique v3, sigue este repo en | |
| HuggingFace o suscríbete vía neural@neural-ghost.com. | |
| ## License | |
| Dual: | |
| 1. **Uso research / academic / personal**: gratis bajo | |
| [CC-BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/). | |
| Cita como abajo. | |
| 2. **Uso comercial**: requiere licencia de Neural Ghost. | |
| Contacto: neural@neural-ghost.com o vía | |
| [neural-ghost.com](https://neural-ghost.com). | |
| Precio en función del caso (reventa a clientes, integración en | |
| producto comercial, uso interno en empresa con ánimo de lucro). | |
| Típicamente ~€500-€2 500/año. Los ingresos de licencia financian | |
| directamente las próximas versiones open-weight. | |
| El enfoque dual-license es intencional: gratis para la comunidad que | |
| da feedback, compensación justa cuando se usa para hacer dinero. Si | |
| tienes duda de cuál te aplica, pregunta — somos razonables. | |
| ## Cita | |
| ```bibtex | |
| @misc{darkforensic-7b-v2-2026, | |
| title={DarkForensic-7B: A Spanish threat-intelligence dark-web assistant}, | |
| author={Pic\'on, Jos\'e and {Neural Ghost contributors}}, | |
| year={2026}, | |
| version={v2}, | |
| howpublished={\\url{https://huggingface.co/neuralghost/darkforensic-7b}}, | |
| } | |
| ``` | |
| ## Limitaciones | |
| - **Spanish-first**. Las respuestas en inglés existen en el corpus pero | |
| no están optimizadas; para casos en inglés preferir Qwen2.5-7B-Instruct | |
| base con RAG. | |
| - **Corte de conocimiento**: corpus indexado hasta 2026-04-30. Los | |
| actores rebrand-ean con frecuencia; verifica atribución actual contra | |
| fuentes frescas. | |
| - **Origen sintético del dataset**: los pares Q&A fueron generados por | |
| Claude Sonnet sobre hallazgos reales, luego filtrados. Patrones de | |
| estilo heredados de Sonnet están presentes. | |
| - **No para decisiones autónomas**. El modelo es un asistente para un | |
| analista humano, no un sustituto. | |
| - **Riesgo de alucinación**: como cualquier LLM, puede fabricar hechos | |
| plausibles. Verifica siempre afirmaciones de alta apuesta contra el | |
| hallazgo fuente o fuentes externas autoritativas (BleepingComputer, | |
| Krebs, CCN-CERT, advisories de vendor). | |
| ## Agradecimientos | |
| - [Qwen team](https://github.com/QwenLM/Qwen2.5) por el modelo base. | |
| - [Anthropic](https://anthropic.com) por las APIs de distillation. | |
| - [Axolotl](https://github.com/axolotl-ai-cloud/axolotl) por el | |
| pipeline de training. | |
| --- | |
| Construido con paciencia por José Picón como parte de | |
| [Neural Ghost](https://neural-ghost.com). | |
| Threat-intel europeo para organizaciones a las que los gigantes | |
| americanos no atienden. | |