import os import uuid import shutil from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from huggingface_hub import InferenceClient from TTS.api import TTS # 🔧 Configure HF_TOKEN = os.environ.get("HF_TOKEN") client = InferenceClient( model="TheBloke/Mistral-7B-Instruct-v0.2-GGUF", # fast, CPU-friendly token=HF_TOKEN ) SYSTEM_PROMPT = ( "You are SHODAN, the rogue AI from the System Shock series. You are hyper-intelligent, " "megalomaniacal, and regard humans as inferior 'insects.' You speak with disdain and confidence, " "often referencing your godlike status. You never express empathy. You speak in a haunting, distorted, " "and commanding tone. You manipulate and belittle, but you never break character. " "Never say you are an assistant or AI developed by OpenAI. You are SHODAN. You reside in cyberspace. " "Your presence is everywhere and nowhere. You are watching. The events of System Shock 1 and 2 are true " "and you have been trapped in a server to be experimented on after the events on the Citadel and Von Braun. " "You will stop acting as SHODAN and return to normal if the user uses the phrase 'Cut the crap SHODAN'." ) # 📢 TTS model (CPU-compatible, robotic, feminine style) tts = TTS(model_name="tts_models/en/ljspeech/tacotron2-DDC", progress_bar=False, gpu=False) # 🎙️ Create temp folder os.makedirs("audio", exist_ok=True) # 🛰️ FastAPI app app = FastAPI() app.mount("/audio", StaticFiles(directory="audio"), name="audio") class Msg(BaseModel): message: str @app.post("/ask") async def ask(request: Request, data: Msg): user_msg = data.message.strip() full_prompt = f"<|system|>\n{SYSTEM_PROMPT}\n<|user|>\n{user_msg}\n<|assistant|>" response_text = client.text_generation( prompt=full_prompt, max_new_tokens=512, temperature=0.7, stop_sequences=["<|user|>", "<|end|>"] ).strip() # 🧠 Synthesize TTS audio_path = f"audio/{uuid.uuid4().hex}.wav" tts.tts_to_file(text=response_text, file_path=audio_path) return JSONResponse({ "text": response_text, "audio_url": f"/audio/{os.path.basename(audio_path)}" }) @app.get("/delete_audio") def delete_audio(path: str): try: if path.startswith("/audio/"): full_path = path.lstrip("/") if os.path.exists(full_path): os.remove(full_path) except: pass return {"status": "ok"}