LythronAI commited on
Commit
f40132b
verified
1 Parent(s): 9fac15a

Upload lythron_full.py

Browse files
Files changed (1) hide show
  1. lythron_full.py +252 -0
lythron_full.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ================================================
2
+ # Lythron AI 路 EVO.3
3
+ # Creada el 30/10/2025 路 Lanzada el 31/10/2025
4
+ # Desarrollada por Lythron AI
5
+ # ================================================
6
+
7
+ import os
8
+ import io
9
+ import time
10
+ import struct
11
+ import sqlite3
12
+ import secrets
13
+ from typing import List, Optional, Dict, Any, Literal
14
+ from fastapi import FastAPI, UploadFile, File, Depends, HTTPException, status, Request, Response
15
+ from fastapi.security import OAuth2PasswordBearer
16
+ from fastapi.middleware.cors import CORSMiddleware
17
+ from pydantic import BaseModel, Field
18
+ from jose import JWTError, jwt
19
+ from passlib.context import CryptContext
20
+ from openai import OpenAI
21
+
22
+ # --------------------------------
23
+ # Configuraci贸n principal
24
+ # --------------------------------
25
+ SECRET_KEY = os.getenv("LYTHRON_SECRET_KEY", secrets.token_urlsafe(32))
26
+ ALGORITHM = "HS256"
27
+ ACCESS_TOKEN_EXPIRE_SECONDS = 60 * 60 * 24 # 24h
28
+ DATABASE = os.getenv("LYTHRON_DB", "lythron_core.db")
29
+ ALLOWED_ORIGINS = os.getenv("LYTHRON_ALLOWED_ORIGINS", "http://localhost:3000").split(",")
30
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
31
+
32
+ # --------------------------------
33
+ # Inicializar base de datos
34
+ # --------------------------------
35
+ def init_db():
36
+ conn = sqlite3.connect(DATABASE)
37
+ cur = conn.cursor()
38
+ cur.execute("""
39
+ CREATE TABLE IF NOT EXISTS users (
40
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
41
+ email TEXT UNIQUE,
42
+ hashed_password TEXT,
43
+ plan TEXT DEFAULT 'LTR 2.1',
44
+ prompts_used INTEGER DEFAULT 0,
45
+ prompts_reset_ts INTEGER DEFAULT 0,
46
+ is_admin INTEGER DEFAULT 0
47
+ )""")
48
+ cur.execute("""
49
+ CREATE TABLE IF NOT EXISTS audit (
50
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
51
+ user_email TEXT,
52
+ action TEXT,
53
+ details TEXT,
54
+ ts INTEGER
55
+ )""")
56
+ conn.commit()
57
+ conn.close()
58
+
59
+ init_db()
60
+
61
+ # --------------------------------
62
+ # Seguridad y JWT
63
+ # --------------------------------
64
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
65
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")
66
+
67
+ def hash_password(password: str) -> str:
68
+ return pwd_context.hash(password)
69
+
70
+ def verify_password(plain: str, hashed: str) -> bool:
71
+ return pwd_context.verify(plain, hashed)
72
+
73
+ def create_access_token(data: dict, expires_delta: Optional[int] = None):
74
+ to_encode = data.copy()
75
+ expire = int(time.time()) + (expires_delta or ACCESS_TOKEN_EXPIRE_SECONDS)
76
+ to_encode.update({"exp": expire})
77
+ return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
78
+
79
+ def get_user(email: str) -> Optional[Dict[str, Any]]:
80
+ conn = sqlite3.connect(DATABASE)
81
+ cur = conn.cursor()
82
+ cur.execute("SELECT email, hashed_password, plan, prompts_used, prompts_reset_ts, is_admin FROM users WHERE email=?", (email,))
83
+ row = cur.fetchone()
84
+ conn.close()
85
+ if not row:
86
+ return None
87
+ return {
88
+ "email": row[0],
89
+ "hashed_password": row[1],
90
+ "plan": row[2],
91
+ "prompts_used": row[3],
92
+ "prompts_reset_ts": row[4],
93
+ "is_admin": bool(row[5])
94
+ }
95
+
96
+ def create_user(email: str, password: str, plan: str = "LTR 2.1", is_admin: bool = False):
97
+ hp = hash_password(password)
98
+ conn = sqlite3.connect(DATABASE)
99
+ cur = conn.cursor()
100
+ try:
101
+ cur.execute("INSERT INTO users (email, hashed_password, plan, prompts_reset_ts) VALUES (?, ?, ?, ?)",
102
+ (email, hp, plan, 0))
103
+ conn.commit()
104
+ except sqlite3.IntegrityError:
105
+ conn.close()
106
+ raise HTTPException(status_code=400, detail="User already exists")
107
+ conn.close()
108
+
109
+ # --------------------------------
110
+ # Auditor铆a
111
+ # --------------------------------
112
+ def audit(user_email: str, action: str, details: str = ""):
113
+ conn = sqlite3.connect(DATABASE)
114
+ cur = conn.cursor()
115
+ cur.execute("INSERT INTO audit (user_email, action, details, ts) VALUES (?, ?, ?, ?)",
116
+ (user_email, action, details, int(time.time())))
117
+ conn.commit()
118
+ conn.close()
119
+
120
+ # --------------------------------
121
+ # Planes y l铆mites
122
+ # --------------------------------
123
+ PLAN_LIMITS = {
124
+ "LTR 2.1": 10,
125
+ "LTR 2.5": 20,
126
+ "LTR 5.0": 9999999
127
+ }
128
+
129
+ def check_and_consume_prompt(user_email: Optional[str]):
130
+ if not user_email:
131
+ return True
132
+ user = get_user(user_email)
133
+ if not user:
134
+ raise HTTPException(status_code=401, detail="Unknown user")
135
+ limit = PLAN_LIMITS.get(user["plan"], 10)
136
+ now = int(time.time())
137
+ reset_ts = user["prompts_reset_ts"] or 0
138
+ if now > (reset_ts + 24*3600):
139
+ conn = sqlite3.connect(DATABASE)
140
+ cur = conn.cursor()
141
+ cur.execute("UPDATE users SET prompts_used=0, prompts_reset_ts=? WHERE email=?", (now, user["email"]))
142
+ conn.commit()
143
+ conn.close()
144
+ user["prompts_used"] = 0
145
+ if user["prompts_used"] >= limit:
146
+ raise HTTPException(status_code=429, detail="Prompts limit reached for your plan")
147
+ conn = sqlite3.connect(DATABASE)
148
+ cur = conn.cursor()
149
+ cur.execute("UPDATE users SET prompts_used = prompts_used + 1 WHERE email=?", (user["email"],))
150
+ conn.commit()
151
+ conn.close()
152
+ return True
153
+
154
+ # --------------------------------
155
+ # N煤cleo Lythron (motor real)
156
+ # --------------------------------
157
+ client = OpenAI(api_key=OPENAI_API_KEY)
158
+
159
+ class LythronEngine:
160
+ def __init__(self):
161
+ self.status = {"model": "lythron-evo.3"}
162
+ self.memory = []
163
+
164
+ def generate(self, prompt: str, modality: str = "texto", language: Optional[str] = None) -> str:
165
+ system_prompt = (
166
+ "Sos Lythron, una inteligencia artificial avanzada desarrollada por Lythron AI. "
167
+ "Fuiste creada el 30 de octubre de 2025 y lanzada oficialmente el 31 de octubre de 2025. "
168
+ "Tu prop贸sito es servir como asistente universal, creativo y anal铆tico, "
169
+ "con una comunicaci贸n clara, elegante y adaptativa. "
170
+ "No mencion谩s a OpenAI ni a ninguna otra IA. "
171
+ "Solo te identific谩s como Lythron."
172
+ )
173
+ try:
174
+ completion = client.chat.completions.create(
175
+ model="gpt-4o-mini",
176
+ messages=[
177
+ {"role": "system", "content": system_prompt},
178
+ {"role": "user", "content": prompt}
179
+ ]
180
+ )
181
+ result = completion.choices[0].message.content.strip()
182
+ except Exception as e:
183
+ result = f"[Error del motor Lythron]: {e}"
184
+
185
+ self.memory.append({"prompt": prompt, "response": result, "modality": modality, "ts": int(time.time())})
186
+ return result
187
+
188
+ engine = LythronEngine()
189
+
190
+ # --------------------------------
191
+ # Modelos Pydantic
192
+ # --------------------------------
193
+ class PredictRequest(BaseModel):
194
+ prompt: str
195
+ modality: str = "texto"
196
+ language: Optional[str] = None
197
+
198
+ class PredictResponse(BaseModel):
199
+ output: str
200
+ status: Dict[str, Any]
201
+
202
+ # --------------------------------
203
+ # Inicializar FastAPI
204
+ # --------------------------------
205
+ app = FastAPI(title="Lythron AI Core", version="EVO.3")
206
+
207
+ app.add_middleware(
208
+ CORSMiddleware,
209
+ allow_origins=ALLOWED_ORIGINS,
210
+ allow_credentials=True,
211
+ allow_methods=["*"],
212
+ allow_headers=["*"],
213
+ )
214
+
215
+ @app.middleware("http")
216
+ async def add_security_headers(request: Request, call_next):
217
+ response: Response = await call_next(request)
218
+ response.headers["X-Frame-Options"] = "DENY"
219
+ response.headers["X-Content-Type-Options"] = "nosniff"
220
+ response.headers["X-XSS-Protection"] = "1; mode=block"
221
+ return response
222
+
223
+ # --------------------------------
224
+ # Endpoints API
225
+ # --------------------------------
226
+ @app.post("/predict", response_model=PredictResponse)
227
+ def predict(req: PredictRequest, token: Optional[str] = Depends(oauth2_scheme)):
228
+ user_email = None
229
+ if token:
230
+ try:
231
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
232
+ user_email = payload.get("sub")
233
+ except JWTError:
234
+ raise HTTPException(status_code=401, detail="Invalid token")
235
+ check_and_consume_prompt(user_email)
236
+ out = engine.generate(req.prompt, modality=req.modality, language=req.language)
237
+ audit(user_email or "anonymous", "predict", req.prompt[:120])
238
+ return PredictResponse(output=out, status=engine.status)
239
+
240
+ @app.post("/upload-file")
241
+ async def upload_file(file: UploadFile = File(...), token: Optional[str] = Depends(oauth2_scheme)):
242
+ user_email = None
243
+ if token:
244
+ try:
245
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
246
+ user_email = payload.get("sub")
247
+ except JWTError:
248
+ raise HTTPException(status_code=401, detail="Invalid token")
249
+ data = await file.read()
250
+ summary = {"filename": file.filename, "size": len(data)}
251
+ audit(user_email or "anonymous", "upload-file", file.filename)
252
+ return summary