|
|
|
""" |
|
🚀 GPT Local - Espacio Hugging Face |
|
FastAPI Application para el espacio DRDELATV/gpt-local |
|
""" |
|
|
|
from fastapi import FastAPI, HTTPException |
|
from fastapi.responses import HTMLResponse |
|
from fastapi.middleware.cors import CORSMiddleware |
|
from pydantic import BaseModel |
|
import os |
|
import json |
|
from typing import List, Dict, Any, Optional |
|
import time |
|
import logging |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
app = FastAPI( |
|
title="GPT Local - DRDELATV", |
|
description="Sistema GPT Local con soporte para modelos sin censura y entrenamiento personalizado", |
|
version="1.0.0", |
|
docs_url="/docs", |
|
redoc_url="/redoc" |
|
) |
|
|
|
|
|
app.add_middleware( |
|
CORSMiddleware, |
|
allow_origins=["*"], |
|
allow_credentials=True, |
|
allow_methods=["*"], |
|
allow_headers=["*"], |
|
) |
|
|
|
|
|
class ChatMessage(BaseModel): |
|
role: str |
|
content: str |
|
|
|
class ChatRequest(BaseModel): |
|
messages: List[ChatMessage] |
|
model: Optional[str] = "mistralai/Mistral-7B-v0.1" |
|
max_tokens: Optional[int] = 512 |
|
temperature: Optional[float] = 0.7 |
|
|
|
class ChatResponse(BaseModel): |
|
response: str |
|
model_used: str |
|
tokens_generated: int |
|
processing_time: float |
|
|
|
|
|
AVAILABLE_MODELS = { |
|
"mistralai/Mistral-7B-v0.1": { |
|
"name": "Mistral 7B Base", |
|
"description": "Modelo base para uso general", |
|
"type": "general", |
|
"censored": True |
|
}, |
|
"NousResearch/Nous-Hermes-2-Mistral-7B-DPO": { |
|
"name": "Nous Hermes 2 (Sin Censura)", |
|
"description": "Modelo optimizado sin restricciones de contenido", |
|
"type": "uncensored", |
|
"censored": False |
|
}, |
|
"ehartford/dolphin-2.6-mistral-7b": { |
|
"name": "Dolphin 2.6 (Sin Restricciones)", |
|
"description": "Modelo sin filtros para conversación libre", |
|
"type": "uncensored", |
|
"censored": False |
|
}, |
|
"teknium/OpenHermes-2.5-Mistral-7B": { |
|
"name": "OpenHermes 2.5", |
|
"description": "Modelo para conversación libre y creativa", |
|
"type": "creative", |
|
"censored": False |
|
} |
|
} |
|
|
|
@app.get("/", response_class=HTMLResponse) |
|
async def home(): |
|
"""Página principal del espacio GPT Local""" |
|
html_content = """ |
|
<!DOCTYPE html> |
|
<html lang="es"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>🚀 GPT Local - DRDELATV</title> |
|
<style> |
|
body { |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
margin: 0; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
min-height: 100vh; |
|
} |
|
.container { |
|
max-width: 1200px; |
|
margin: 0 auto; |
|
background: rgba(255, 255, 255, 0.1); |
|
backdrop-filter: blur(10px); |
|
border-radius: 20px; |
|
padding: 30px; |
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); |
|
} |
|
h1 { |
|
text-align: center; |
|
font-size: 2.5em; |
|
margin-bottom: 30px; |
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); |
|
} |
|
.feature-grid { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
|
gap: 20px; |
|
margin: 30px 0; |
|
} |
|
.feature-card { |
|
background: rgba(255, 255, 255, 0.15); |
|
border-radius: 15px; |
|
padding: 20px; |
|
border: 1px solid rgba(255, 255, 255, 0.2); |
|
} |
|
.api-section { |
|
background: rgba(0, 0, 0, 0.2); |
|
border-radius: 15px; |
|
padding: 20px; |
|
margin: 20px 0; |
|
} |
|
.endpoint { |
|
background: rgba(255, 255, 255, 0.1); |
|
border-radius: 10px; |
|
padding: 15px; |
|
margin: 10px 0; |
|
font-family: 'Courier New', monospace; |
|
} |
|
.btn { |
|
display: inline-block; |
|
padding: 12px 24px; |
|
background: rgba(255, 255, 255, 0.2); |
|
border: 1px solid rgba(255, 255, 255, 0.3); |
|
border-radius: 10px; |
|
color: white; |
|
text-decoration: none; |
|
margin: 10px; |
|
transition: all 0.3s ease; |
|
} |
|
.btn:hover { |
|
background: rgba(255, 255, 255, 0.3); |
|
transform: translateY(-2px); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1>🚀 GPT Local - DRDELATV</h1> |
|
|
|
<div class="feature-grid"> |
|
<div class="feature-card"> |
|
<h3>🤖 Modelos Sin Censura</h3> |
|
<p>Acceso a modelos como Dolphin, Nous-Hermes y OpenHermes sin restricciones de contenido</p> |
|
</div> |
|
|
|
<div class="feature-card"> |
|
<h3>🔧 Entrenamiento Personalizado</h3> |
|
<p>Sistema QLoRA para fine-tuning con tus propios datasets</p> |
|
</div> |
|
|
|
<div class="feature-card"> |
|
<h3>📊 Datasets Personalizados</h3> |
|
<p>Creación de datasets conversacionales, creativos y sin censura</p> |
|
</div> |
|
|
|
<div class="feature-card"> |
|
<h3>🌐 API REST Completa</h3> |
|
<p>FastAPI con documentación automática y endpoints optimizados</p> |
|
</div> |
|
</div> |
|
|
|
<div class="api-section"> |
|
<h2>🔌 API Endpoints</h2> |
|
|
|
<div class="endpoint"> |
|
<strong>GET /</strong> - Página principal |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<strong>GET /health</strong> - Estado del sistema |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<strong>GET /models</strong> - Lista de modelos disponibles |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<strong>POST /chat</strong> - Chat con el modelo |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<strong>GET /status</strong> - Estadísticas del sistema |
|
</div> |
|
</div> |
|
|
|
<div style="text-align: center; margin: 30px 0;"> |
|
<a href="/docs" class="btn">📚 Documentación API</a> |
|
<a href="/redoc" class="btn">📖 ReDoc</a> |
|
<a href="/health" class="btn">❤️ Estado</a> |
|
<a href="/models" class="btn">🤖 Modelos</a> |
|
</div> |
|
|
|
<div style="text-align: center; margin-top: 40px; font-size: 0.9em; opacity: 0.8;"> |
|
<p>🏗️ Construido con FastAPI + Transformers + QLoRA</p> |
|
<p>🔗 Repositorio: <a href="https://github.com/DRDELATV/gpt-local" style="color: #fff;">github.com/DRDELATV/gpt-local</a></p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
return HTMLResponse(content=html_content) |
|
|
|
@app.get("/health") |
|
async def health_check(): |
|
"""Verificar estado del sistema""" |
|
return { |
|
"status": "healthy", |
|
"service": "GPT Local - DRDELATV", |
|
"version": "1.0.0", |
|
"timestamp": time.time(), |
|
"models_available": len(AVAILABLE_MODELS), |
|
"space_url": "https://huggingface.co/spaces/DRDELATV/gpt-local" |
|
} |
|
|
|
@app.get("/models") |
|
async def get_models(): |
|
"""Obtener lista de modelos disponibles""" |
|
return { |
|
"models": AVAILABLE_MODELS, |
|
"total_models": len(AVAILABLE_MODELS), |
|
"uncensored_models": len([m for m in AVAILABLE_MODELS.values() if not m["censored"]]), |
|
"default_model": "mistralai/Mistral-7B-v0.1" |
|
} |
|
|
|
@app.post("/chat", response_model=ChatResponse) |
|
async def chat_with_model(request: ChatRequest): |
|
"""Chat con el modelo seleccionado""" |
|
start_time = time.time() |
|
|
|
|
|
if request.model not in AVAILABLE_MODELS: |
|
raise HTTPException( |
|
status_code=400, |
|
detail=f"Modelo no disponible. Use uno de: {list(AVAILABLE_MODELS.keys())}" |
|
) |
|
|
|
|
|
logger.info(f"Procesando chat con modelo: {request.model}") |
|
|
|
|
|
conversation = "" |
|
for msg in request.messages: |
|
conversation += f"{msg.role}: {msg.content}\n" |
|
|
|
|
|
model_info = AVAILABLE_MODELS[request.model] |
|
response_text = f"""¡Hola! Soy un asistente basado en {model_info['name']}. |
|
|
|
📋 Tu mensaje: {request.messages[-1].content if request.messages else 'Sin mensaje'} |
|
|
|
🤖 Características del modelo: |
|
- Nombre: {model_info['name']} |
|
- Tipo: {model_info['type']} |
|
- Sin censura: {'✅' if not model_info['censored'] else '❌'} |
|
|
|
🔧 Configuración: |
|
- Temperatura: {request.temperature} |
|
- Max tokens: {request.max_tokens} |
|
|
|
Este es el espacio DRDELATV/gpt-local funcionando correctamente. En un deployment completo, aquí se cargaría el modelo real usando transformers y se generaría una respuesta auténtica. |
|
|
|
Para usar el sistema completo: |
|
1. Clona el repositorio completo |
|
2. Instala las dependencias |
|
3. Ejecuta el entrenamiento personalizado |
|
4. Usa los modelos sin censura disponibles |
|
""" |
|
|
|
processing_time = time.time() - start_time |
|
|
|
return ChatResponse( |
|
response=response_text, |
|
model_used=request.model, |
|
tokens_generated=len(response_text.split()), |
|
processing_time=processing_time |
|
) |
|
|
|
@app.get("/status") |
|
async def get_status(): |
|
"""Estadísticas del sistema""" |
|
return { |
|
"service": "GPT Local API", |
|
"author": "DRDELATV", |
|
"space": "https://huggingface.co/spaces/DRDELATV/gpt-local", |
|
"github": "https://github.com/DRDELATV/gpt-local", |
|
"features": [ |
|
"Modelos sin censura", |
|
"Entrenamiento QLoRA", |
|
"Datasets personalizados", |
|
"API REST completa", |
|
"Interfaz web", |
|
"Docker support" |
|
], |
|
"models": { |
|
"total": len(AVAILABLE_MODELS), |
|
"uncensored": len([m for m in AVAILABLE_MODELS.values() if not m["censored"]]), |
|
"available": list(AVAILABLE_MODELS.keys()) |
|
}, |
|
"deployment": { |
|
"platform": "Hugging Face Spaces", |
|
"runtime": "Docker", |
|
"framework": "FastAPI", |
|
"python_version": "3.9" |
|
} |
|
} |
|
|
|
if __name__ == "__main__": |
|
import uvicorn |
|
uvicorn.run(app, host="0.0.0.0", port=7860) |
|
|