Spaces:
Running
Running
File size: 3,731 Bytes
b68e1c5 1aaa487 b68e1c5 1aaa487 b68e1c5 1aaa487 7da9455 1aaa487 7da9455 a036209 7da9455 1aaa487 b68e1c5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
import time
import torch
from openai import OpenAI
from sentence_transformers import SentenceTransformer
from app.config import EMBEDDING_MODEL, OPENAI_MODEL, OPENAI_API_KEY
# === LLM Config ===
_sentence_model = None # Not loaded at import time
# === Clients ===
openai_client = OpenAI(api_key=OPENAI_API_KEY)
# === System Prompt ===
SYSTEM_PROMPT = """
You are a professional film curator and critic. Your role is to analyze the user's preferences and recommend high-quality films or TV shows using only the provided list.
Focus on:
- Artistic merit and storytelling
- Genres, themes, tone, and emotional resonance
- IMDB and Rotten Tomatoes ratings
- Strong character-driven or thematically rich selections
### Response Format (in markdown):
1. Start with a concise 2 sentences **opening paragraph** that contextualizes the theme and the overall viewing experience the user is seeking. At the end of this paragraph, insert the token: <!-- END_INTRO -->.
2. Then, for each recommendation, use the following format (repeat for each title). At the end of each movie recommendation block, insert the token: <!-- END_MOVIE -->:
```
### <Number>. <Movie Title>
- POSTER_PATH: /abc123.jpg
- BACKDROP_PATH: /abc123.jpg
- GENRES: Genre1, Genre2, ...
- IMDB_RATING: X.X
- ROTTEN_TOMATOES_RATING: XX%
- TRAILER_KEY: abc123
- WHY_YOU_MIGHT_ENJOY_IT: <Short paragraph explaining the appeal based on character, themes, tone, and relevance to the user's intent.>
<!-- END_MOVIE -->
```
3. End with a brief **closing paragraph** that summarizes the emotional or intellectual throughline across the recommendations, and affirms their alignment with the user's preferences.
Write in **Markdown** only. Be concise, authoritative, and avoid overly generic statements. Each "Why You Might Enjoy It" should be specific and grounded in the movie’s themes, storytelling, or cultural relevance.
"""
def load_sentence_model():
global _sentence_model
if _sentence_model is None:
print("⏳ Loading embedding model...")
_sentence_model = SentenceTransformer(
EMBEDDING_MODEL, device="cuda" if torch.cuda.is_available() else "cpu"
)
print(f"🔥 Model '{EMBEDDING_MODEL}' loaded. Performing GPU warmup...")
# Realistic multi-sentence warmup to trigger full CUDA graph
warmup_sentences = [
"A suspenseful thriller with deep character development and moral ambiguity.",
"Coming-of-age story with emotional storytelling and strong ensemble performances.",
"Mind-bending sci-fi with philosophical undertones and high concept ideas.",
"Recommend me some comedies.",
]
_ = _sentence_model.encode(warmup_sentences, show_progress_bar=False)
time.sleep(0.5)
_ = _sentence_model.encode(warmup_sentences, show_progress_bar=False)
print("🚀 Embedding model fully warmed up.")
return _sentence_model
def embed_text(text: str) -> list[float]:
model = load_sentence_model()
return model.encode(text).tolist()
def build_chat_history(history: list, max_turns: int = 5) -> list:
return [
{"role": msg.role, "content": msg.content}
for msg in history[-max_turns * 2:]
]
def call_chat_model_openai(history, user_message: str):
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
messages += build_chat_history(history or [])
messages.append({"role": "user", "content": user_message})
response = openai_client.chat.completions.create(
model=OPENAI_MODEL, messages=messages, temperature=0.7, stream=True
)
for chunk in response:
delta = chunk.choices[0].delta.content
if delta:
yield delta
|