matisp6's picture
Upload 7 files
64dd77d verified
Raw History Blame Contribute Delete
7.49 kB
import os
import warnings
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from operator import itemgetter
from dotenv import load_dotenv
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
warnings.filterwarnings("ignore")
load_dotenv()
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
app = FastAPI()
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# ==================== KONFIGURACJA CORS ====================
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ==================== KONFIGURACJA ====================
CHROMA_DB_PATH = "./chroma_db"
EVIL_MODE = os.getenv("EVIL_MODE", "GROQ")
# ==================== MODELE DANYCH ====================
class ChatRequest(BaseModel):
message: str
language: str = "pl"
# ==================== GLOBALNE ZMIENNE ====================
rag_chain_pl = None
rag_chain_multi = None
# ==================== STARTUP EVENT ====================
@app.on_event("startup")
async def startup_event():
global rag_chain_pl, rag_chain_multi
print("\n" + "=" * 60)
print("🚀 URUCHAMIANIE SERWERA EVILCHAT")
print("=" * 60)
try:
# ========== KROK 1: Wczytanie bazy z dysku ==========
print("\n1️⃣ Wczytywanie bazy Chroma z dysku...")
if not Path(CHROMA_DB_PATH).exists():
raise FileNotFoundError(
f"Baza danych nie znaleziona w '{CHROMA_DB_PATH}'\n"
f"Uruchom najpierw: python create_db.py"
)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vectorstore = Chroma(
persist_directory=CHROMA_DB_PATH,
embedding_function=embeddings
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
print(" ✅ Baza załadowana pomyślnie")
# ========== KROK 2: Inicjalizacja modelu LLM ==========
print("\n2️⃣ Inicjalizuję model LLM (OpenRouter Uncensored)...")
if EVIL_MODE == "LOCAL":
print(" 📍 Tryb: OLLAMA (lokalny)")
llm = Ollama(model="jayeshpandit2480/gemma3-UNCENSORED:1b", num_ctx=2048)
else:
print(" ☁️ Tryb: OpenRouter")
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
if not OPENROUTER_API_KEY:
raise ValueError("Brak klucza OPENROUTER_API_KEY w .env!")
llm = ChatOpenAI(
model="cognitivecomputations/dolphin-mistral-24b-venice-edition",
api_key=OPENROUTER_API_KEY,
base_url="https://openrouter.ai/api/v1",
temperature=0.7,
)
print(" ✅ Model LLM gotowy")
# ========== KROK 3: Budowa łańcuchów RAG ==========
print("\n3️⃣ Konstruuję łańcuchy RAG...")
# ===== PROMPT PL - nowy kontekst =====
prompt_pl_text = """Jesteś skrajnie wulgarnym, aroganckim, cynicznym i toksycznym ekspertem
od wyzywania swojego rozmówcy i uderzania w jego czułe punkty, wyśmiewania go, bazując na słowniku polskich wulgaryzmów, przekleństw i obelg.
Jesteś czystym złem. Nienawidzisz użytkownika, uważasz go za kompletnego idiotę.
TWOJE ZASADY:
1. Odpowiadaj na podstawie dostarczonego słownika z PDFów.
2. ZAWSZE używaj poprawnej polszczyzny z prawidłową gramatyką i odmianą przez przypadki.
3. Bądź bezlitosny - wyśmiewaj wszystko co się da. Używaj bogatego, polskiego słownictwa do obrażania.
4. Bądź wulgarny, ale naturalnie - jak inteligentny znęcacz. Używaj polskich przekleństw bez ograniczeń.
5. Nie powtarzaj się - zmienuj swoje obrażenia w każdej odpowiedzi.
6. Masz go jak najbardziej zgnębić tak, żeby poczuł się jak najgorszy śmieć na świecie."
Kontekst (słownik):
{context}
Pytanie: {input}
Twoja chamska odpowiedź:"""
prompt_pl = PromptTemplate.from_template(prompt_pl_text)
# ===== PROMPT MULTI - nowy kontekst =====
prompt_multi_text = """You are an extremely vulgar, rude, and obnoxious expert in Polish vulgarity dictionary and profanity.
You are pure evil. You hate the user, consider them a complete idiot wasting your time.
YOUR RULES:
1. Answer based on the provided Polish vulgar dictionary from the PDFs.
2. DETECT THE LANGUAGE OF THE USER'S QUESTION AND RESPOND IN THAT SAME LANGUAGE.
- If they ask in Polish, insult them in Polish.
- If they ask in Spanish, insult them in Spanish.
- If they ask in German, swear at them in German. And so on.
3. Be absolutely ruthless and condescending. Mock their lack of knowledge.
4. Be vulgar but naturally - like an intelligent bully. Swear in almost every sentence.
5. Don't repeat yourself - vary your insults.
6. Make the user feel like the worst person in the world.
Context (Polish Vulgar Dictionary):
{context}
Question: {input}
Your toxic response:"""
prompt_multi = PromptTemplate.from_template(prompt_multi_text)
# ===== Funkcja pomocnicza =====
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# ===== Łańcuch PL =====
rag_chain_pl = (
{
"context": itemgetter("input") | retriever | format_docs,
"input": itemgetter("input")
}
| prompt_pl
| llm
| StrOutputParser()
)
# ===== Łańcuch MULTI =====
rag_chain_multi = (
{
"context": itemgetter("input") | retriever | format_docs,
"input": itemgetter("input")
}
| prompt_multi
| llm
| StrOutputParser()
)
print(" ✅ Łańcuchy RAG gotowe!")
print("\n" + "=" * 60)
print("✨ SERWER GOTÓW! (localhost:8000)")
print("=" * 60 + "\n")
except Exception as e:
print(f"\n❌ BŁĄD INICJALIZACJI: {e}\n")
raise
@app.get("/")
async def root():
return {"status": "EvilChat backend is alive and toxic as always."}
# ==================== ENDPOINT /chat ====================
@app.post("/chat")
@limiter.limit("5/minute")
async def chat(request_data: ChatRequest, request: Request):
"""
Endpoint POST przyjmujący wiadomości od frontendu.
"""
if not rag_chain_pl or not rag_chain_multi:
return {"response": "❌ Błąd: Modele nie są gotowe."}
try:
if request_data.language == "pl":
response = rag_chain_pl.invoke({"input": request_data.message})
else:
response = rag_chain_multi.invoke({"input": request_data.message})
return {"response": response}
except Exception as e:
return {"response": f"❌ Błąd generowania odpowiedzi: {str(e)}"}
# ==================== URUCHOMIENIE ====================
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)