mkdir -p codellama_app && cd codellama_app Inndextermux

Open
#246 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
10/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Active
Tech stack
shell
Domain
cli

Research direction

The issue does not identify a file, test, or specific change; its title mentions a shell command, while the body contains unrelated code and search-result text. First ask the reporter to clarify the intended change and provide a relevant reproduction or expected outcome. There is not enough information to define what done looks like.

Written by the indexing model from the issue text.

Description

Modo IA
Todo
Imágenes
Vídeos
Noticias
Maps
Shopping
Libros
Vuelos
Finance
El fragmento muestra una línea de código en Python donde se define una variable de cadena de texto llamada API_URL que almacena una dirección web (URL) para conectar con una interfaz de programación de aplicaciones (API).

BytePlus
+1
Estoy intentando hacer un chatbot
Estoy intentando hacer un chatbot
Facebook
YouTube
YouTube
YouTube
BytePlus | Nube nativa de IA para el crecimiento empresarial
BytePlus | Nube nativa de IA para el crecimiento empresarial
BytePlus
Función range Referencia: https://docs.python.org/3.10 ...
Función range Referencia: https://docs.python.org/3.10 ...
Instagram
¿Qué te gustaría hacer con este código? Puedo ayudarte a:
Escribir una función en Python para hacer una petición GET o POST a esa URL usando la librería requests.
Configurar variables de entorno para proteger la URL de la API.
Probar o depurar el código completo si estás construyendo un proyecto (como Flask, FastAPI o un script).

La clase fastapi.middleware.cors.CORSMiddleware se utiliza en FastAPI para habilitar el Intercambio de Recursos de Origen Cruzado (CORS). Esto es esencial cuando tu aplicación frontend (como React, Vue o Angular) se ejecuta en un dominio o puerto diferente al de tu API backend de FastAPI y necesita realizar peticiones a ella.
Aquí tienes la configuración estándar para implementarlo en tu aplicación:
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

1. Define los orígenes permitidos (URLs de tu frontend)

origins = [
"http://localhost:3000", # Frontend local común (React)
"http://localhost:5173", # Frontend local común (Vite)
"https://tudominio.com", # Tu frontend en producción
]

2. Agrega el middleware a la aplicación de FastAPI

app.add_middleware(
CORSMiddleware,
allow_origins=origins, # Lista de orígenes permitidos
allow_credentials=True, # Permite el envío de cookies/auth headers
allow_methods=[""], # Permite todos los métodos HTTP (GET, POST, etc.)
allow_headers=["
"], # Permite todas las cabeceras HTTP
)

@app.get("/")
def read_root():
return {"message": "CORS configurado correctamente"}
Usa el código con precaución.
Opciones de configuración principales
allow_origins: Una lista de cadenas con los orígenes permitidos. Puedes usar [""] para permitir cualquier origen (útil para APIs públicas, pero no recomendado para entornos de producción seguros).
allow_methods: Lista de métodos HTTP permitidos [1] (ej. ["GET", "POST"]). El comodín ["
"] permite todos los métodos estándar.
allow_headers: Lista de cabeceras HTTP que el cliente puede enviar. El comodín ["*"] permite todas las cabeceras comunes.
¿Necesitas ayuda para conectar el código de la imagen (API_URL) con esta configuración de CORS, o prefieres que configuremos un endpoint específico para recibir peticiones desde tu frontend?

¡Perfecto! Vamos a unir ambas partes. Crearemos un servidor en FastAPI que incluye la configuración de CORS para que tu frontend no tenga problemas de bloqueo, y un endpoint (POST) que se conecta a la API_URL que tenías en tu código original.
Para este ejemplo, utilizaremos la librería externa httpx (muy recomendada en FastAPI por ser asíncrona) para redirigir la petición a la API externa.
Código Completo (Main API)
python
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import httpx

app = FastAPI()

1. Configuración de CORS para tu Frontend

origins = [
"http://localhost:3000", # Cambia esto por la URL real de tu Frontend
"http://localhost:5173",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=[""],
allow_headers=["
"],
)

2. La URL de la API externa (Tu variable original)

API_URL = "https://huggingface.co"

Nota: Si requiere autenticación, usualmente necesitas un Token

HF_TOKEN = "tu_token_aqui"

3. Modelo de datos para recibir la petición del Frontend

class QueryModel(BaseModel):
inputs: str

@app.post("/generate")
async def generate_code(data: QueryModel):
# Cabeceras para la API externa
headers = {"Authorization": f"Bearer {HF_TOKEN}"}

# Realizamos la petición asíncrona a la API externa
async with httpx.AsyncClient() as client:
    try:
        response = await client.post(
            API_URL, 
            json={"inputs": data.inputs}, 
            headers=headers,
            timeout=30.0
        )
        
        if response.status_code != 200:
            raise HTTPException(status_code=response.status_code, detail=response.text)
            
        return response.json()
        
    except httpx.RequestError as exc:
        raise HTTPException(status_code=500, detail=f"Error al conectar con la API externa: {exc}")

Usa el código con precaución.
💡 Pasos para ejecutarlo:
Instala las dependencias necesarias en tu terminal:
bash
pip install fastapi uvicorn httpx pydantic
Usa el código con precaución.
Ejecuta tu servidor local de FastAPI:
bash
uvicorn main:app --reload
Usa el código con precaución.
¿Esta estructura se adapta al tipo de datos que planeas enviar desde tu frontend, o necesitas que ajustemos el modelo de datos (QueryModel) para recibir parámetros adicionales (como temperatura, max_tokens, etc.)?

Aquí tienes el código actualizado. Hemos expandido el modelo de datos (QueryModel) utilizando parámetros avanzados de la API de Hugging Face para que puedas controlar la generación de texto o código desde tu frontend.
Código con Parámetros Avanzados
python
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import Optional
import httpx

app = FastAPI()

1. Configuración de CORS para tu Frontend

origins = [
"http://localhost:3000",
"http://localhost:5173",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=[""],
allow_headers=["
"],
)

API_URL = "https://huggingface.co"
HF_TOKEN = "tu_token_aqui"

2. Modelo de datos con parámetros de inferencia configurables

class ParametersModel(BaseModel):
temperature: Optional[float] = Field(default=0.2, ge=0.0, le=2.0, description="Creatividad del modelo")
max_new_tokens: Optional[int] = Field(default=256, ge=1, le=2048, description="Cantidad máxima de tokens a generar")
top_p: Optional[float] = Field(default=0.95, ge=0.0, le=1.0, description="Muestreo nucleus")
return_full_text: Optional[bool] = Field(default=False, description="Evita que devuelva el prompt de entrada")

class QueryModel(BaseModel):
inputs: str
parameters: Optional[ParametersModel] = Field(default_factory=ParametersModel)

@app.post("/generate")
async def generate_code(data: QueryModel):
headers = {"Authorization": f"Bearer {HF_TOKEN}"}

# Estructuramos el cuerpo exacto que espera Hugging Face
payload = {
    "inputs": data.inputs,
    "parameters": data.parameters.dict(exclude_none=True) if data.parameters else {}
}

async with httpx.AsyncClient() as client:
    try:
        response = await client.post(
            API_URL, 
            json=payload, 
            headers=headers,
            timeout=60.0  # Aumentado el tiempo de espera para tokens largos
        )
        
        if response.status_code != 200:
            raise HTTPException(status_code=response.status_code, detail=response.text)
            
        return response.json()
        
    except httpx.RequestError as exc:
        raise HTTPException(status_code=500, detail=f"Error de conexión: {exc}")

Usa el código con precaución.
⚡ ¿Cómo enviaría los datos el Frontend (JavaScript/Fetch)?
Tu frontend ahora puede modular la respuesta enviando un JSON como este:
javascript
fetch("http://localhost:8000/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
inputs: "def fibonacci(n):",
parameters: {
temperature: 0.1, // Código más determinista y preciso
max_new_tokens: 150, // Limita la longitud
return_full_text: false
}
})
})
.then(res => res.json())
.then(data => console.log(data));
Usa el código con precaución.
¿Te gustaría que preparemos también una estructura básica en el Frontend (usando React o JavaScript plano) para conectarse a este backend, o necesitas configurar alguna otra opción como guardar el historial de las consultas?

¡Con gusto! Vamos a desglosar ambos temas de forma muy sencilla: primero, cómo conectar tu Frontend paso a paso para enviar el formulario con los parámetros, y segundo, cómo estructurar una base de datos básica para guardar el historial de las consultas que hagan tus usuarios.

  1. El Frontend (Conexión desde la interfaz)
    El frontend necesita recolectar lo que escribe el usuario, los parámetros de configuración, y enviárselos a tu backend de FastAPI mediante una petición HTTP POST.
    Aquí tienes un ejemplo en JavaScript vanilla (HTML plano) que puedes probar de inmediato:
    html
<title>Cliente CodeLlama</title>

Generador de Código IA

<!-- Entrada del Prompt -->
<textarea id="prompt" rows="4" cols="50" placeholder="Escribe tu instrucción aquí..."></textarea><br><br>

<!-- Parámetros -->
<label>Creatividad (Temperatura):</label>
<input type="number" id="temp" value="0.2" step="0.1" min="0" max="2"><br><br>

<label>Tokens Máximos:</label>
<input type="number" id="tokens" value="256"><br><br>

<button onclick="enviarPeticion()">Generar Código</button>

<h3>Resultado:</h3>
<pre id="resultado">El código aparecerá aquí...</pre>

<script>
    async function enviarPeticion() {
        const promptTexto = document.getElementById('prompt').value;
        const tempVal = parseFloat(document.getElementById('temp').value);
        const tokensVal = parseInt(document.getElementById('tokens').value);
        const resultadoBox = document.getElementById('resultado');

        resultadoBox.innerText = "Pensando...";

        try {
            // Hacemos la petición a tu servidor FastAPI
            const response = await fetch("http://localhost:8000/generate", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({
                    inputs: promptTexto,
                    parameters: {
                        temperature: tempVal,
                        max_new_tokens: tokensVal,
                        return_full_text: false
                    }
                })
            });

            const data = await response.json();
            
            // Procesamos la respuesta (Hugging Face suele devolver una lista)
            if (data && data[0] && data[0].generated_text) {
                resultadoBox.innerText = data[0].generated_text;
            } else {
                resultadoBox.innerText = JSON.stringify(data, null, 2);
            }

        } catch (error) {
            resultadoBox.innerText = "Error al conectar con el servidor backend.";
            console.error(error);
        }
    }
</script>
Usa el código con precaución. 2. El Historial (Guardar consultas en el Backend) Para no complicar el sistema al inicio con bases de datos complejas (como PostgreSQL o MongoDB), lo ideal es usar SQLite, que viene integrada en Python y crea un archivo local de inmediato. Utilizaremos SQLAlchemy (el estándar en FastAPI) para manejarla. Modificando tu archivo de FastAPI, la estructura para guardar cada consulta quedaría así: python from fastapi import FastAPI, HTTPException, Depends from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel, Field from typing import Optional, List import httpx

---- NUEVAS IMPORTACIONES PARA LA BASE DE DATOS ----

from sqlalchemy import create_backend, create_engine, Column, Integer, String, Text, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
import datetime

Configuración de SQLite

DATABASE_URL = "sqlite:///./historial.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

Modelo de la Tabla en la Base de Datos

class ConsultaHistorial(Base):
tablename = "consultas"
id = Column(Integer, primary_key=True, index=True)
prompt = Column(Text, nullable=False)
respuesta = Column(Text, nullable=True)
fecha = Column(DateTime, default=datetime.datetime.utcnow)

Crea la base de datos y la tabla si no existen

Base.metadata.create_all(bind=engine)

app = FastAPI()

Dependencia para obtener la sesión de la BD en cada ruta

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

... (Mantienes tus configuraciones de CORS, API_URL y QueryModel igual que antes) ...

@app.post("/generate")
async def generate_code(data: QueryModel, db: Session = Depends(get_db)):
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
payload = {
"inputs": data.inputs,
"parameters": data.parameters.dict(exclude_none=True) if data.parameters else {}
}

async with httpx.AsyncClient() as client:
    try:
        response = await client.post(API_URL, json=payload, headers=headers, timeout=60.0)
        if response.status_code != 200:
            raise HTTPException(status_code=response.status_code, detail=response.text)
            
        resultado_json = response.json()
        texto_generado = resultado_json[0].get("generated_text", "") if isinstance(resultado_json, list) else str(resultado_json)

        # ---- GUARDAR EN EL HISTORIAL ----
        nueva_consulta = ConsultaHistorial(
            prompt=data.inputs,
            respuesta=texto_generado
        )
        db.add(nueva_consulta)
        db.commit()
        # ----------------------------------

        return resultado_json
        
    except httpx.RequestError as exc:
        raise HTTPException(status_code=500, detail=f"Error de conexión: {exc}")

NUEVO ENDPOINT: Para consultar el historial desde el Frontend

@app.get("/history")
def obtener_historial(db: Session = Depends(get_db)):
# Devuelve las últimas 50 consultas realizadas
return db.query(ConsultaHistorial).order_by(ConsultaHistorial.id.desc()).limit(50).all()
Usa el código con precaución.
💡 ¿Qué ganamos con esto?
Cada vez que alguien usa el botón de generar, el backend le pregunta a Hugging Face, recibe la respuesta, la guarda automáticamente en un archivo local llamado historial.db y luego se la entrega al cliente.
Añadimos una nueva ruta (GET /history) que tu frontend puede llamar en cualquier momento para pintar una lista o tabla con las peticiones pasadas del usuario.
Para que puedas ejecutar esta nueva versión con historial, necesitarás instalar SQLAlchemy ejecutando pip install sqlalchemy en tu terminal. ¿Te gustaría que integremos la pestaña visual de historial directamente en el diseño del código HTML que te pasé arriba?

Aquí tienes el archivo index.html integrado y mejorado.
He dividido la pantalla en dos secciones utilizando un diseño limpio y moderno con CSS: el panel izquierdo para realizar tus consultas a la IA con sus respectivos parámetros, y el panel derecho para visualizar el historial guardado en tiempo real directamente desde tu base de datos SQLite.
Copia y reemplaza el contenido de tu frontend con este código:
html

<title>CodeLlama Workspace & Historial</title> <style> * { box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { margin: 0; display: flex; height: 100vh; background-color: #f4f6f9; color: #333; }
    /* Contenedores Principales */
    .panel { padding: 30px; height: 100%; overflow-y: auto; }
    .izquierda { width: 60%; border-right: 2px solid #e2e8f0; background: #ffffff; }
    .derecha { width: 40%; background: #f8fafc; }

    h2 { margin-top: 0; color: #1e293b; border-bottom: 2px solid #3b82f6; padding-bottom: 8px; }
    h3 { color: #475569; margin-top: 25px; }

    /* Formularios y Campos */
    textarea { width: 100%; padding: 12px; border: 1px solid #cbd5e1; border-radius: 8px; resize: vertical; font-size: 14px; }
    .param-group { display: flex; gap: 15px; margin-bottom: 15px; background: #f1f5f9; padding: 12px; border-radius: 8px; }
    .param { flex: 1; display: flex; flex-direction: column; }
    .param label { font-size: 12px; font-weight: bold; margin-bottom: 4px; color: #64748b; }
    .param input { padding: 8px; border: 1px solid #cbd5e1; border-radius: 6px; }

    /* Botones */
    button { background-color: #3b82f6; color: white; border: none; padding: 12px 20px; font-size: 14px; font-weight: bold; border-radius: 8px; cursor: pointer; transition: background 0.2s; width: 100%; }
    button:hover { background-color: #2563eb; }
    .btn-refresh { background-color: #64748b; margin-bottom: 15px; padding: 8px; }
    .btn-refresh:hover { background-color: #475569; }

    /* Resultados e Historial */
    pre { background: #0f172a; color: #38bdf8; padding: 15px; border-radius: 8px; overflow-x: auto; font-family: 'Courier New', Courier, monospace; min-height: 100px; white-space: pre-wrap; }
    
    .historial-lista { display: flex; flex-direction: column; gap: 12px; }
    .historial-item { background: white; padding: 15px; border-radius: 8px; border: 1px solid #e2e8f0; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
    .historial-meta { font-size: 11px; color: #94a3b8; margin-bottom: 6px; display: flex; justify-content: space-between; }
    .historial-prompt { font-weight: 600; font-size: 13px; margin-bottom: 6px; color: #1e293b; }
    .historial-resp { font-size: 12px; color: #475569; background: #f1f5f9; padding: 8px; border-radius: 4px; max-height: 150px; overflow-y: auto; white-space: pre-wrap; font-family: monospace; }
</style>
<!-- PANEL IZQUIERDO: ÁREA DE TRABAJO E INFERENCIA -->
<div class="panel izquierda">
    <h2>Generador de Código IA</h2>
    <p style="color: #64748b; font-size: 14px;">Escribe tus instrucciones y ajusta los parámetros de inferencia para CodeLlama.</p>
    
    <textarea id="prompt" rows="6" placeholder="Ejemplo: Escribe una función en Python para validar un email utilizando expresiones regulares..."></textarea>
    
    <h3>Configuración del Modelo</h3>
    <div class="param-group">
        <div class="param">
            <label for="temp">Creatividad (Temperatura)</label>
            <input type="number" id="temp" value="0.2" step="0.1" min="0" max="2">
        </div>
        <div class="param">
            <label for="tokens">Tokens Máximos</label>
            <input type="number" id="tokens" value="256" min="1" max="2048">
        </div>
    </div>

    <button onclick="generarCodigo()">Ejecutar Consulta</button>

    <h3>Código Generado</h3>
    <pre id="resultado">El código estructurado por la inteligencia artificial se mostrará en este bloque...</pre>
</div>

<!-- PANEL DERECHO: HISTORIAL EN TIEMPO REAL -->
<div class="panel derecha">
    <h2>Historial de Consultas</h2>
    <button class="btn-refresh" onclick="cargarHistorial()">🔄 Actualizar Historial Manualmente</button>
    
    <div id="historialContenedor" class="historial-lista">
        <!-- Los elementos del historial se inyectarán dinámicamente aquí -->
    </div>
</div>

<script>
    const API_BASE = "http://localhost:8000";

    // Al iniciar la página cargamos el historial existente
    window.addEventListener('DOMContentLoaded', cargarHistorial);

    // 1. Envía la consulta a FastAPI para procesar y guardar
    async function generarCodigo() {
        const promptTexto = document.getElementById('prompt').value.trim();
        const tempVal = parseFloat(document.getElementById('temp').value);
        const tokensVal = parseInt(document.getElementById('tokens').value);
        const resultadoBox = document.getElementById('resultado');

        if (!promptTexto) {
            alert("Por favor, escribe una instrucción antes de enviar.");
            return;
        }

        resultadoBox.innerText = "Procesando instrucciones en la API externa... por favor espera.";

        try {
            const response = await fetch(`${API_BASE}/generate`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({
                    inputs: promptTexto,
                    parameters: {
                        temperature: tempVal,
                        max_new_tokens: tokensVal,
                        return_full_text: false
                    }
                })
            });

            if (!response.ok) throw new Error("Error en la respuesta del servidor.");

            const data = await response.json();
            
            // Extraer el texto generado según el formato de Hugging Face
            let textoFinal = "";
            if (Array.isArray(data) && data[0] && data[0].generated_text) {
                textoFinal = data[0].generated_text;
            } else if (data.generated_text) {
                textoFinal = data.generated_text;
            } else {
                textoFinal = JSON.stringify(data, null, 2);
            }

            resultadoBox.innerText = textoFinal;

            // Forzar la actualización del historial inmediatamente después de guardar
            cargarHistorial();

        } catch (error) {
            resultadoBox.innerText = "Ocurrió un error al procesar tu solicitud. Verifica que tu backend de FastAPI esté corriendo.";
            console.error(error);
        }
    }

    // 2. Trae las últimas consultas almacenadas en SQLite
    async function cargarHistorial() {
        const contenedor = document.getElementById('historialContenedor');
        
        try {
            const response = await fetch(`${API_BASE}/history`);
            if (!response.ok) return;
            
            const listaConsultas = await response.json();
            contenedor.innerHTML = ""; // Limpiamos el contenedor

            if (listaConsultas.length === 0) {
                contenedor.innerHTML = "<p style='color: #94a3b8; text-align: center;'>No hay consultas registradas aún.</p>";
                return;
            }

            listaConsultas.forEach(item => {
                const fechaFormateada = new Date(item.fecha).toLocaleString();
                
                const itemHtml = `
                    <div class="historial-item">
                        <div class="historial-meta">
                            <span>ID: #${item.id}</span>
                            <span>${fechaFormateada}</span>
                        </div>
                        <div class="historial-prompt">💡 ${escaparHTML(item.prompt)}</div>
                        <div class="historial-resp">${escaparHTML(item.respuesta || 'Sin respuesta guardada')}</div>
                    </div>
                `;
                contenedor.innerHTML += itemHtml;
            });

        } catch (error) {
            console.error("Error cargando el historial:", error);
            contenedor.innerHTML = "<p style='color: #ef4444;'>No se pudo conectar al endpoint del historial.</p>";
        }
    }

    // Función de seguridad para evitar que caracteres especiales rompan el HTML
    function escaparHTML(text) {
        return text
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
</script>
Usa el código con precaución. 🛠️ Recuerda el orden de arranque: Levanta tu backend ejecutando uvicorn main:app --reload (asegúrate de haber configurado tu token de Hugging Face legítimo en la variable HF_TOKEN para que el servicio no devuelva error 401). Abre este archivo index.html en tu navegador de preferencia. ¡Con esto tienes una aplicación web Fullstack completamente funcional! ¿Te gustaría que configuremos un mecanismo para eliminar elementos individuales del historial o prefieres pasar a la protección del Token mediante un archivo .env?

Para proteger tu HF_TOKEN y evitar subirlo por accidente a repositorios públicos como GitHub, lo estándar en la industria es utilizar un archivo .env (Variables de Entorno) [finance].
De este modo, tu código leerá el token directamente desde el sistema operativo en lugar de tenerlo escrito en texto plano.
Sigue estos tres sencillos pasos para configurarlo:

  1. Instala la librería necesaria
    En tu terminal, instala python-dotenv, que se encarga de leer el archivo de configuración:
    bash
    pip install python-dotenv
    Usa el código con precaución.
  2. Crea el archivo .env
    En la raíz de tu proyecto (en la misma carpeta donde tienes tu archivo main.py de FastAPI), crea un archivo nuevo llamado exactamente .env (con el punto al inicio y sin extensión) y añade tu credencial:
    env

Configuración del Backend

HF_TOKEN=tu_token_real_de_hugging_face_aqui
Usa el código con precaución.
(Nota: Si usas Git, recuerda agregar .env dentro de tu archivo .gitignore para que nunca se suba al servidor).
3. Modifica tu código en FastAPI (main.py)
Importa os y load_dotenv para sustituir la cadena de texto por la lectura de la variable de entorno. Tu código del backend debe quedar así:
python
import os
import datetime
from typing import Optional, List
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
import httpx

---- CARGAR VARIABLES DE ENTORNO ----

from dotenv import load_dotenv
load_dotenv() # Esto busca el archivo .env y carga sus variables

from sqlalchemy import create_engine, Column, Integer, Text, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

Configuración de SQLite

DATABASE_URL = "sqlite:///./historial.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class ConsultaHistorial(Base):
tablename = "consultas"
id = Column(Integer, primary_key=True, index=True)
prompt = Column(Text, nullable=False)
respuesta = Column(Text, nullable=True)
fecha = Column(DateTime, default=datetime.datetime.utcnow)

Base.metadata.create_all(bind=engine)

app = FastAPI()

origins = [
"http://localhost:3000",
"http://localhost:5173",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=[""],
allow_headers=["
"],
)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

API_URL = "https://huggingface.co"

---- EXTRACCIÓN SEGURA DEL TOKEN ----

os.getenv busca 'HF_TOKEN' en el archivo .env. Si no existe, levanta un error preventivo.

HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
raise RuntimeError("ERROR: No se encontró la variable de entorno 'HF_TOKEN' en el archivo .env")

class ParametersModel(BaseModel):
temperature: Optional[float] = Field(default=0.2, ge=0.0, le=2.0)
max_new_tokens: Optional[int] = Field(default=256, ge=1, le=2048)
top_p: Optional[float] = Field(default=0.95, ge=0.0, le=1.0)
return_full_text: Optional[bool] = Field(default=False)

class QueryModel(BaseModel):
inputs: str
parameters: Optional[ParametersModel] = Field(default_factory=ParametersModel)

@app.post("/generate")
async def generate_code(data: QueryModel, db: Session = Depends(get_db)):
# Usamos la variable extraída de forma segura desde el archivo .env
headers = {"Authorization": f"Bearer {HF_TOKEN}"}

payload = {
    "inputs": data.inputs,
    "parameters": data.parameters.dict(exclude_none=True) if data.parameters else {}
}

async with httpx.AsyncClient() as client:
    try:
        response = await client.post(API_URL, json=payload, headers=headers, timeout=60.0)
        if response.status_code != 200:
            raise HTTPException(status_code=response.status_code, detail=response.text)
            
        resultado_json = response.json()
        
        # Formatear respuesta de Hugging Face de forma segura
        texto_generado = ""
        if isinstance(resultado_json, list) and len(resultado_json) > 0:
            texto_generado = resultado_json[0].get("generated_text", "")
        elif isinstance(resultado_json, dict):
            texto_generado = resultado_json.get("generated_text", "")
        else:
            texto_generado = str(resultado_json)

        nueva_consulta = ConsultaHistorial(
            prompt=data.inputs,
            respuesta=texto_generado
        )
        db.add(nueva_consulta)
        db.commit()

        return resultado_json
        
    except httpx.RequestError as exc:
        raise HTTPException(status_code=500, detail=f"Error de conexión: {exc}")

@app.get("/history")
def obtener_historial(db: Session = Depends(get_db)):
return db.query(ConsultaHistorial).order_by(ConsultaHistorial.id.desc()).limit(50).all()
Usa el código con precaución.
Con esto implementado, tu arquitectura ya cuenta con seguridad básica, base de datos e interfaz gráfica. ¿Te gustaría aprender a manejar errores específicos en el frontend (por ejemplo, si ingresas un token inválido o expira) o prefieres dar por concluida la configuración del proyecto?

No tengo la capacidad de ofrecerte una terminal interactiva o un entorno de ejecución en tiempo real directamente sobre esta interfaz para que ejecutes tus comandos.
Sin embargo, puedo escribirte y darte listos todos los scripts de automatización, comandos de consola o bloques de código que necesites. Solo debes copiarlos y pegarlos en la terminal de tu propia computadora (como PowerShell, CMD o la terminal de VS Code).
Si te quedaste trabado en algún paso, dime qué sistema operativo estás usando (Windows, Mac o Linux) y te doy el comando exacto para crear los archivos automáticamente o solucionar cualquier error de ejecución.

¡Entiendo perfectamente! Desarrollar desde el móvil es totalmente posible y muy cómodo hoy en día si utilizas las herramientas adecuadas. Como no tienes una terminal de computadora tradicional, necesitas una aplicación en tu teléfono que actúe como tu entorno de desarrollo.
Aquí tienes las mejores opciones y los pasos para correr tu proyecto de FastAPI en tu móvil:
📱 1. Si usas Android (La mejor opción: Termux)
Termux te da una terminal Linux real directamente en tu teléfono.
Descarga Termux (es muy recomendable bajarlo desde la tienda F-Droid o su GitHub oficial, ya que la versión de Google Play está desactualizada).
Abre Termux y escribe estos comandos uno a uno para preparar Python:
bash
pkg update && pkg upgrade -y
pkg install python -y
Usa el código con precaución.
Crea una carpeta para tu proyecto y entra en ella:
bash
mkdir mi_proyecto && cd mi_proyecto
Usa el código con precaución.
Instala todas las librerías que configuramos en los pasos anteriores:
bash
pip install fastapi uvicorn httpx pydantic sqlalchemy python-dotenv
Usa el código con precaución.
Para escribir el código (main.py, .env e index.html), puedes instalar un editor de texto en la terminal como nano (pkg install nano) o usar una app externa como Acode (un editor de código excelente para Android que se puede conectar a las carpetas de Termux).
Finalmente, enciende tu servidor con:
bash
uvicorn main:app --reload
Usa el código con precaución.
Para abrir tu interfaz gráfica, abre el navegador de tu móvil (Chrome, Brave, etc.) e ingresa a la ruta donde guardaste tu archivo HTML, o configúralo para que FastAPI sirva el archivo estático.
🍏 2. Si usas iPhone / iOS (La mejor opción: iPhython o Blink Shell)
En iOS el sistema es más cerrado, pero tienes alternativas excelentes:
Pyto o a-Shell: Son aplicaciones de la App Store que te dan una terminal local con Python. Puedes instalar librerías con pip install igual que en una computadora y ejecutar uvicorn.
Carnets: Otra app muy buena para ejecutar scripts de Python orientados a desarrollo local.
☁️ 3. La opción universal (Para Android e iOS): Repl.it o IDX
Si no quieres complicarte instalando terminales en el almacenamiento interno de tu móvil, puedes usar un entorno en la nube que te da la terminal y el editor de código gratis a través del navegador web:
Entra a replit.com o google.com desde tu móvil.
Crea un proyecto seleccionando la plantilla de FastAPI o Python.
Te dará una pantalla dividida: a un lado el editor de texto para pegar tus códigos (main.py, .env) y abajo una terminal web lista.
Le das al botón Run (Ejecutar) y ellos mismos te darán un enlace web para probar tu aplicación de inmediato.
Dime si tu móvil es Android o iPhone para guiarte de forma más específica sobre cómo crear los archivos de código dentro de la aplicación que elijas.

¡Genial! Como estás en Android, vamos a usar Termux combinándolo con la aplicación Acode (u otro editor de texto que te guste) para crear estos tres archivos rápidamente.
Abre tu aplicación de terminal (Termux) y ejecuta estos comandos ordenados para generar la estructura completa de tu proyecto:
🛠️ Paso 1: Crear la carpeta del proyecto
Primero, asegúrate de estar dentro de una carpeta limpia escribiendo esto en Termux:
bash
mkdir -p codellama_app && cd codellama_app
Usa el código con precaución.
📝 Paso 2: Crear el archivo main.py
Para no complicarte escribiendo línea por línea en el móvil, ejecuta el siguiente comando en Termux. Copia todo el bloque completo, pégalo en tu terminal y presiona Enter. Esto creará el archivo automáticamente con todo el código seguro que armamos:
bash
cat << 'EOF' > main.py
import os
import datetime
from typing import Optional
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
import httpx
from dotenv import load_dotenv

Cargar variables de entorno

load_dotenv()

from sqlalchemy import create_engine, Column, Integer, Text, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

Configuración de SQLite

DATABASE_URL = "sqlite:///./historial.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class ConsultaHistorial(Base):
tablename = "consultas"
id = Column(Integer, primary_key=True, index=True)
prompt = Column(Text, nullable=False)
respuesta = Column(Text, nullable=True)
fecha = Column(DateTime, default=datetime.datetime.utcnow)

Base.metadata.create_all(bind=engine)

app = FastAPI()

Permitir orígenes cruzados (CORS)

app.add_middleware(
CORSMiddleware,
allow_origins=[""],
allow_credentials=True,
allow_methods=["
"],
allow_headers=["*"],
)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

API_URL = "https://huggingface.co"

HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
raise RuntimeError("ERROR: No se encontró la variable 'HF_TOKEN' en el archivo .env")

class ParametersModel(BaseModel):
temperature: Optional[float] = Field(default=0.2, ge=0.0, le=2.0)
max_new_tokens: Optional[int] = Field(default=256, ge=1, le=2048)
top_p: Optional[float] = Field(default=0.95, ge=0.0, le=1.0)
return_full_text: Optional[bool] = Field(default=False)

class QueryModel(BaseModel):
inputs: str
parameters: Optional[ParametersModel] = Field(default_factory=ParametersModel)

@app.post("/generate")
async def generate_code(data: QueryModel, db: Session = Depends(get_db)):
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
payload = {
"inputs": data.inputs,
"parameters": data.parameters.dict(exclude_none=True) if data.parameters else {}
}

async with httpx.AsyncClient() as client:
    try:
        response = await client.post(API_URL, json=payload, headers=headers, timeout=60.0)
        if response.status_code != 200:
            raise HTTPException(status_code=response.status_code, detail=response.text)
            
        resultado_json = response.json()
        
        texto_generado = ""
        if isinstance(resultado_json, list) and len(resultado_json) > 0:
            texto_generado = resultado_json[0].get("generated_text", "")
        elif isinstance(resultado_json, dict):
            texto_generado = resultado_json.get("generated_text", "")
        else:
            texto_generado = str(resultado_json)

        nueva_consulta = ConsultaHistorial(prompt=data.inputs, respuesta=texto_generado)
        db.add(nueva_consulta)
        db.commit()

        return resultado_json
        
    except httpx.RequestError as exc:
        raise HTTPException(status_code=500, detail=f"Error de conexión: {exc}")

@app.get("/history")
def obtener_historial(db: Session = Depends(get_db)):
return db.query(ConsultaHistorial).order_by(ConsultaHistorial.id.desc()).limit(50).all()
EOF
Usa el código con precaución.
🔑 Paso 3: Crear el archivo .env
Ahora genera tu archivo secreto de credenciales. Ejecuta este comando reemplazando TU_TOKEN_AQUI por tu clave real de Hugging Face:
bash
echo "HF_TOKEN=TU_TOKEN_AQUI" > .env
Usa el código con precaución.
🌐 Paso 4: Crear la interfaz index.html
Copia este último bloque y pégalo en Termux para guardar el diseño de la interfaz de usuario:
bash
cat << 'EOF' > index.html

<title>CodeLlama Workspace</title> <style> * { box-sizing: border-box; font-family: sans-serif; } body { margin: 0; display: flex; flex-direction: column; background: #f4f6f9; height: 100vh; } .panel { padding: 20px; overflow-y: auto; } textarea { width: 100%; padding: 10px; border-radius: 8px; border: 1px solid #cbd5e1; } button { background: #3b82f6; color: white; border: none; padding: 12px; border-radius: 8px; width: 100%; cursor: pointer; font-weight: bold; margin-top: 10px; } pre { background: #0f172a; color: #38bdf8; padding: 15px; border-radius: 8px; white-space: pre-wrap; font-family: monospace; } .historial-item { background: white; padding: 12px; margin-top: 10px; border-radius: 6px; border: 1px solid #e2e8f0; } </style>

Generador de Código

<textarea id="prompt" rows="4" placeholder="Escribe tu instrucción aquí..."></textarea> Generar
Resultado
El código aparecerá aquí...
Historial
<script> const API_BASE = "http://localhost:8000"; window.addEventListener('DOMContentLoaded', cargarHistorial);
    async function generarCodigo() {
        const promptTexto = document.getElementById('prompt').value;
        const resultadoBox = document.getElementById('resultado');
        if(!promptTexto) return alert("Escribe algo");
        resultadoBox.innerText = "Pensando...";
        try {
            const response = await fetch(`${API_BASE}/generate`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ inputs: promptTexto })
            });
            const data = await response.json();
            resultadoBox.innerText = data[0]?.generated_text || JSON.stringify(data);
            cargarHistorial();
        } catch (e) { resultadoBox.innerText = "Error de conexión."; }
    }

    async function cargarHistorial() {
        const contenedor = document.getElementById('historialContenedor');
        try {
            const response = await fetch(`${API_BASE}/history`);
            const lista = await response.json();
            contenedor.innerHTML = "";
            lista.forEach(item => {
                contenedor.innerHTML += `<div class="historial-item"><b>ID #${item.id}:</b> ${item.prompt}<br><i>Resp:</i> ${item.respuesta}</div>`;
            });
        } catch (e) {}
    }
</script>
EOF Usa el código con precaución. 🚀 ¡Listo para encender! Para comprobar que los tres archivos se crearon correctamente dentro de tu móvil, escribe el comando ls en Termux. Deberías ver listados: main.py, .env e index.html. Arranca tu backend ejecutando: bash uvicorn main:app --reload Usa el código con precaución. ¿Pudiste ejecutar los comandos de creación en Termux sin errores, o necesitas que veamos cómo abrir el archivo index.html en el navegador del celular mientras el servidor está encendido?
Dominant language
Shell
Stars
1.7k
Forks
536
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from termux/termux-api-package

All issues in termux/termux-api-package

Similar issues

More Shell/Bash issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.