ibrahim yıldız commited on
Commit
2d24fc3
·
verified ·
1 Parent(s): e9436d7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -0
app.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Rizzy v0.2 – Stream-friendly, streak-building dating-chat ghost-writer
3
+ ──────────────────────────────────────────────────────────────────────
4
+ ▪ Streams Dobby-Unhinged replies live
5
+ ▪ Lets the user pick a vibe (playful / sweet / roast)
6
+ ▪ Keeps only the last few turns to save tokens
7
+ ▪ Uses env var or Streamlit Secrets for the Fireworks key
8
+ ▪ Click-to-copy output (JS hack)
9
+ """
10
+
11
+ from __future__ import annotations
12
+ import os, json, requests, datetime
13
+ from typing import List, Dict
14
+
15
+ import streamlit as st
16
+
17
+ # ── 🔑 API CONFIG ──────────────────────────────────────────────────
18
+ API_KEY = os.getenv("FIREWORKS_API_KEY") or st.secrets["fireworks_key"]
19
+ MODEL_ID = "accounts/sentientfoundation/models/dobby-unhinged-llama-3-3-70b-new"
20
+ FW_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
21
+
22
+ # ── 📝 SYSTEM PROMPT TEMPLATE ────────────────────────────────────
23
+ BASE_PROMPT = """
24
+ You are **Rizzy**, an outrageously charismatic ghost-writer for dating apps.
25
+
26
+ Output **exactly**:
27
+ [Say:"<max-20-token reply>"] <≤7-word reason>
28
+
29
+ Rules
30
+ 1. Tone: {tone}. Abbreviate (ur, tbh, lol).
31
+ 2. Never exceed 2 sentences / 20 tokens.
32
+ 3. No hashtags, no emoji spam (≤2).
33
+ 4. If you break a rule, forcibly truncate.
34
+ """
35
+
36
+ # ── 🏷️ VIBE PICKER ────────────────────────────────────────────────
37
+ TONE2TXT = {
38
+ "Playful": "friendly, jokey, flirty",
39
+ "Sweet": "warm, encouraging, wholesome",
40
+ "Roast": "teasing, sarcastic, cocky-fun"
41
+ }
42
+
43
+ # ── 🔌 FIREWORKS STREAM CALL ─────────────────────────────────────
44
+ def stream_dobby(history: List[Dict], temperature: float = 0.8):
45
+ payload = {
46
+ "model": MODEL_ID,
47
+ "stream": True,
48
+ "temperature": temperature,
49
+ "top_p": 1,
50
+ "top_k": 40,
51
+ "messages": history,
52
+ }
53
+ headers = {
54
+ "Authorization": f"Bearer {API_KEY}",
55
+ "Accept": "application/json",
56
+ "Content-Type": "application/json",
57
+ }
58
+
59
+ with requests.post(FW_URL, headers=headers, data=json.dumps(payload), stream=True, timeout=60) as r:
60
+ r.raise_for_status()
61
+ for line in r.iter_lines():
62
+ if not line or line.startswith(b":"): # skip keep-alive
63
+ continue
64
+ data = json.loads(line.decode().removeprefix("data: "))
65
+ delta = data["choices"][0]["delta"].get("content")
66
+ if delta:
67
+ yield delta
68
+
69
+ # ── 🖼️ UI SETUP ──────────────────────────────────────────────────
70
+ st.set_page_config("Rizzy", "💬")
71
+ st.title("💬 Rizzy – your AI wing-person")
72
+
73
+ # streak badge (simple local)
74
+ today = datetime.date.today()
75
+ if st.session_state.get("last_seen") == today:
76
+ streak = st.session_state.get("streak", 1) + 1
77
+ else:
78
+ streak = 1
79
+ st.session_state["last_seen"] = today
80
+ st.session_state["streak"] = streak
81
+ st.markdown(f"**🔥 Streak: {streak} day(s)**")
82
+
83
+ tone = st.radio("Pick the vibe:", list(TONE2TXT.keys()), horizontal=True)
84
+
85
+ # Chat history container
86
+ if "chat" not in st.session_state:
87
+ st.session_state.chat: List[Dict] = [
88
+ {"role":"assistant","content":"Yo, I'm Rizzy. Drop a dating-app situation and I’ll craft the perfect reply."}
89
+ ]
90
+
91
+ # Print past messages
92
+ for msg in st.session_state.chat:
93
+ with st.chat_message(msg["role"]):
94
+ st.markdown(msg["content"])
95
+
96
+ # ── 💬 USER INPUT ────────────────────────────────────────────────
97
+ prompt = st.chat_input("What's going on?")
98
+ if prompt:
99
+ st.session_state.chat.append({"role":"user","content":prompt})
100
+ with st.chat_message("user"): st.markdown(prompt)
101
+
102
+ # Build trimmed history (last 6 turns to save tokens)
103
+ history = [{"role":"system","content": BASE_PROMPT.format(tone=TONE2TXT[tone])}]
104
+ history += st.session_state.chat[-12:]
105
+
106
+ # Stream assistant reply
107
+ reply_box = st.chat_message("assistant")
108
+ placeholder = reply_box.empty()
109
+ full_reply = ""
110
+
111
+ try:
112
+ for chunk in stream_dobby(history):
113
+ full_reply += chunk
114
+ placeholder.markdown(full_reply)
115
+ except Exception as e:
116
+ full_reply = f"*Error talking to Dobby →* `{e}`"
117
+ placeholder.markdown(full_reply)
118
+
119
+ st.session_state.chat.append({"role":"assistant","content":full_reply})
120
+
121
+ # Click-to-copy (JS hack)
122
+ copy_code = f"""
123
+ <textarea id="toCopy" style="opacity:0">{full_reply}</textarea>
124
+ <button onclick="navigator.clipboard.writeText(document.getElementById('toCopy').value);this.innerText='Copied!'">📋 Copy reply</button>
125
+ """
126
+ reply_box.components.v1.html(copy_code, height=35, scrolling=False)