Update app.py
Browse files
app.py
CHANGED
|
@@ -2,13 +2,26 @@ import os
|
|
| 2 |
import gradio as gr
|
| 3 |
import requests
|
| 4 |
import json
|
|
|
|
| 5 |
|
| 6 |
# Load secrets
|
| 7 |
PAYWALLS_API_KEY = os.environ.get("PAYWALLS_API_KEY")
|
| 8 |
PAYWALLS_API_URL = os.environ.get("PAYWALLS_API_URL", "https://api.paywalls.ai/v1")
|
| 9 |
-
HF_MODEL = "openai/gpt-oss-20b"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
# Check if user is connected and authorized to use the paywall
|
| 12 |
def check_paywall(user_id: str):
|
| 13 |
headers = {
|
| 14 |
"Authorization": f"Bearer {PAYWALLS_API_KEY}",
|
|
@@ -18,16 +31,11 @@ def check_paywall(user_id: str):
|
|
| 18 |
resp = requests.get(f"{PAYWALLS_API_URL}/user/connect?user={user_id}", headers=headers, timeout=10)
|
| 19 |
resp.raise_for_status()
|
| 20 |
data = resp.json()
|
| 21 |
-
|
| 22 |
-
return True, ""
|
| 23 |
-
else:
|
| 24 |
-
message = f"Please connect or top up to access. Visit: {data.get('url', 'No URL provided')}"
|
| 25 |
-
return False, message
|
| 26 |
except Exception as e:
|
| 27 |
-
print(f"[Paywall] Error
|
| 28 |
-
return False, "
|
| 29 |
|
| 30 |
-
# Perform a chat completion request via Paywalls proxy endpoint
|
| 31 |
def chat_completion(user_id, system_message, history, user_message, max_tokens, temperature, top_p):
|
| 32 |
headers = {
|
| 33 |
"Authorization": f"Bearer {PAYWALLS_API_KEY}",
|
|
@@ -47,48 +55,83 @@ def chat_completion(user_id, system_message, history, user_message, max_tokens,
|
|
| 47 |
}
|
| 48 |
|
| 49 |
try:
|
| 50 |
-
response = requests.post(f"{PAYWALLS_API_URL}/chat/completions", headers=headers,
|
| 51 |
response.raise_for_status()
|
| 52 |
data = response.json()
|
| 53 |
choices = data.get("choices", [])
|
| 54 |
if choices:
|
| 55 |
return choices[0]["message"]["content"]
|
| 56 |
-
|
| 57 |
-
return "No response from model."
|
| 58 |
except Exception as e:
|
| 59 |
-
print(f"[Paywall]
|
| 60 |
-
return f"Error
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
):
|
| 66 |
-
user_id = "demo_user"
|
| 67 |
-
connected, paywall_msg = check_paywall(user_id)
|
| 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 |
if __name__ == "__main__":
|
| 94 |
-
demo.launch()
|
|
|
|
| 2 |
import gradio as gr
|
| 3 |
import requests
|
| 4 |
import json
|
| 5 |
+
from datetime import datetime
|
| 6 |
|
| 7 |
# Load secrets
|
| 8 |
PAYWALLS_API_KEY = os.environ.get("PAYWALLS_API_KEY")
|
| 9 |
PAYWALLS_API_URL = os.environ.get("PAYWALLS_API_URL", "https://api.paywalls.ai/v1")
|
| 10 |
+
HF_MODEL = "openai/gpt-oss-20b"
|
| 11 |
+
|
| 12 |
+
# Free tier limits
|
| 13 |
+
FREE_MAX_TOKENS = 150
|
| 14 |
+
PREMIUM_MAX_TOKENS = 2048
|
| 15 |
+
|
| 16 |
+
# Style presets (premium feature)
|
| 17 |
+
STYLE_PRESETS = {
|
| 18 |
+
"neutral": "You are a creative writing assistant.",
|
| 19 |
+
"poetic": "You are a poetic writing assistant. Write in lyrical, expressive language with vivid imagery.",
|
| 20 |
+
"dramatic": "You are a dramatic writing assistant. Create tension, conflict, and emotional depth.",
|
| 21 |
+
"comedic": "You are a comedic writing assistant. Use humor, wit, and light-hearted tone.",
|
| 22 |
+
"horror": "You are a horror writing assistant. Build suspense and create eerie, unsettling atmospheres."
|
| 23 |
+
}
|
| 24 |
|
|
|
|
| 25 |
def check_paywall(user_id: str):
|
| 26 |
headers = {
|
| 27 |
"Authorization": f"Bearer {PAYWALLS_API_KEY}",
|
|
|
|
| 31 |
resp = requests.get(f"{PAYWALLS_API_URL}/user/connect?user={user_id}", headers=headers, timeout=10)
|
| 32 |
resp.raise_for_status()
|
| 33 |
data = resp.json()
|
| 34 |
+
return data.get("connected", False), data.get('url', '')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
except Exception as e:
|
| 36 |
+
print(f"[Paywall] Error: {e}")
|
| 37 |
+
return False, ""
|
| 38 |
|
|
|
|
| 39 |
def chat_completion(user_id, system_message, history, user_message, max_tokens, temperature, top_p):
|
| 40 |
headers = {
|
| 41 |
"Authorization": f"Bearer {PAYWALLS_API_KEY}",
|
|
|
|
| 55 |
}
|
| 56 |
|
| 57 |
try:
|
| 58 |
+
response = requests.post(f"{PAYWALLS_API_URL}/chat/completions", headers=headers, json=payload, timeout=60)
|
| 59 |
response.raise_for_status()
|
| 60 |
data = response.json()
|
| 61 |
choices = data.get("choices", [])
|
| 62 |
if choices:
|
| 63 |
return choices[0]["message"]["content"]
|
| 64 |
+
return "No response from model."
|
|
|
|
| 65 |
except Exception as e:
|
| 66 |
+
print(f"[Paywall] Error: {e}")
|
| 67 |
+
return f"Error: {e}"
|
| 68 |
|
| 69 |
+
def respond(message, history, style, max_tokens, temperature, top_p):
|
| 70 |
+
user_id = "demo_user" # Replace with gr.Request for real user sessions
|
| 71 |
+
is_premium, paywall_url = check_paywall(user_id)
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
+
# Apply free tier limits
|
| 74 |
+
if not is_premium:
|
| 75 |
+
max_tokens = min(max_tokens, FREE_MAX_TOKENS)
|
| 76 |
+
if style != "neutral":
|
| 77 |
+
return f"π Style customization requires premium. [Unlock here]({paywall_url})"
|
| 78 |
|
| 79 |
+
system_message = STYLE_PRESETS.get(style, STYLE_PRESETS["neutral"])
|
| 80 |
+
reply = chat_completion(user_id, system_message, history, message, max_tokens, temperature, top_p)
|
| 81 |
+
|
| 82 |
+
# Add tier indicator
|
| 83 |
+
tier_badge = "β¨ PREMIUM" if is_premium else "π FREE"
|
| 84 |
+
return f"{reply}\n\n---\n_{tier_badge}_"
|
| 85 |
|
| 86 |
+
def export_conversation(history):
|
| 87 |
+
user_id = "demo_user"
|
| 88 |
+
is_premium, paywall_url = check_paywall(user_id)
|
| 89 |
+
|
| 90 |
+
if not is_premium:
|
| 91 |
+
return None, f"π Export requires premium. [Unlock here]({paywall_url})"
|
| 92 |
+
|
| 93 |
+
# Generate text file
|
| 94 |
+
content = f"Creative Writing Session - {datetime.now().strftime('%Y-%m-%d %H:%M')}\n\n"
|
| 95 |
+
for msg in history:
|
| 96 |
+
role = msg["role"].upper()
|
| 97 |
+
content += f"{role}: {msg['content']}\n\n"
|
| 98 |
+
|
| 99 |
+
filepath = "/tmp/creative_writing.txt"
|
| 100 |
+
with open(filepath, "w") as f:
|
| 101 |
+
f.write(content)
|
| 102 |
+
|
| 103 |
+
return filepath, "β
Exported successfully!"
|
| 104 |
|
| 105 |
+
# Build UI
|
| 106 |
+
with gr.Blocks(title="Creative Writing Assistant") as demo:
|
| 107 |
+
gr.Markdown("# π Creative Writing Assistant\n**Free:** 150 tokens | **Premium:** 2048 tokens + styles + export")
|
| 108 |
+
|
| 109 |
+
with gr.Row():
|
| 110 |
+
with gr.Column(scale=3):
|
| 111 |
+
chatbot = gr.Chatbot(type="messages", height=500)
|
| 112 |
+
msg = gr.Textbox(label="Your prompt", placeholder="Write a story about...", lines=3)
|
| 113 |
+
submit = gr.Button("β¨ Generate", variant="primary")
|
| 114 |
+
|
| 115 |
+
with gr.Column(scale=1):
|
| 116 |
+
style = gr.Dropdown(
|
| 117 |
+
choices=list(STYLE_PRESETS.keys()),
|
| 118 |
+
value="neutral",
|
| 119 |
+
label="π¨ Writing Style (Premium)",
|
| 120 |
+
info="Unlock premium for custom styles"
|
| 121 |
+
)
|
| 122 |
+
max_tokens = gr.Slider(FREE_MAX_TOKENS, PREMIUM_MAX_TOKENS, value=FREE_MAX_TOKENS, step=50, label="Max Tokens")
|
| 123 |
+
temperature = gr.Slider(0.1, 2.0, value=0.8, step=0.1, label="Creativity")
|
| 124 |
+
top_p = gr.Slider(0.1, 1.0, value=0.95, step=0.05, label="Diversity")
|
| 125 |
+
|
| 126 |
+
gr.Markdown("---")
|
| 127 |
+
export_btn = gr.Button("πΎ Export (Premium)", variant="secondary")
|
| 128 |
+
download_file = gr.File(label="Download")
|
| 129 |
+
export_status = gr.Textbox(label="Status", interactive=False)
|
| 130 |
+
|
| 131 |
+
# Event handlers
|
| 132 |
+
submit.click(respond, [msg, chatbot, style, max_tokens, temperature, top_p], [chatbot])
|
| 133 |
+
msg.submit(respond, [msg, chatbot, style, max_tokens, temperature, top_p], [chatbot])
|
| 134 |
+
export_btn.click(export_conversation, [chatbot], [download_file, export_status])
|
| 135 |
|
| 136 |
if __name__ == "__main__":
|
| 137 |
+
demo.launch()
|