GuXSs commited on
Commit
cdcab04
·
verified ·
1 Parent(s): 70afce1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -48
app.py CHANGED
@@ -5,12 +5,23 @@ import gradio as gr
5
  import requests
6
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
7
  from dotenv import load_dotenv
 
8
 
9
- # ----------------- Load secrets -----------------
 
10
  load_dotenv()
11
- HF_TOKEN = os.environ.get("HF_TOKEN") # Hugging Face Token
12
- SUPABASE_URL = os.environ.get("SUPABASE_URL") # Supabase URL
13
- SUPABASE_KEY = os.environ.get("SUPABASE_KEY") # Supabase API Key
 
 
 
 
 
 
 
 
 
14
 
15
  HEADERS = {
16
  "apikey": SUPABASE_KEY,
@@ -18,52 +29,163 @@ HEADERS = {
18
  "Content-Type": "application/json"
19
  }
20
 
21
- # ----------------- Supabase functions -----------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  def create_user(name: str):
 
 
 
 
23
  api_key = str(uuid.uuid4())
24
- data = {"name": name, "api_key": api_key}
25
- response = requests.post(f"{SUPABASE_URL}/rest/v1/users",
26
- headers=HEADERS,
27
- data=json.dumps(data))
28
- if response.status_code in [200, 201]:
29
- return api_key
30
- else:
31
- return f"Erro: {response.text}"
32
-
33
- def check_key(api_key: str):
34
- response = requests.get(f"{SUPABASE_URL}/rest/v1/users?api_key=eq.{api_key}",
35
- headers=HEADERS)
36
- data = response.json()
37
- return len(data) > 0
38
-
39
- # ----------------- Carregar modelo Gemma 270M -----------------
40
- model_name = "google/gemma-3-270m-it"
41
- tokenizer = AutoTokenizer.from_pretrained(model_name, use_auth_token=HF_TOKEN)
42
- model = AutoModelForCausalLM.from_pretrained(model_name, use_auth_token=HF_TOKEN)
43
- gen_pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
44
-
45
- # ----------------- Função de geração de texto -----------------
46
- def generate_text(prompt, api_key):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  if not check_key(api_key):
 
48
  return "API Key inválida!"
49
- result = gen_pipe(prompt, max_length=100, do_sample=True)
50
- return result[0]["generated_text"]
51
 
52
- # ----------------- Interface Gradio -----------------
53
- with gr.Blocks() as demo:
54
- gr.Markdown("## Gemma 270M API - Hugging Face Space")
55
-
56
- with gr.Tab("Gerar Texto"):
57
- prompt_input = gr.Textbox(label="Prompt")
58
- api_key_input = gr.Textbox(label="API Key")
59
- output_text = gr.Textbox(label="Resultado")
60
- generate_btn = gr.Button("Gerar")
61
- generate_btn.click(fn=generate_text, inputs=[prompt_input, api_key_input], outputs=output_text)
62
-
63
- with gr.Tab("Criar API Key"):
64
- name_input = gr.Textbox(label="Nome do Usuário")
65
- key_output = gr.Textbox(label="Sua API Key")
66
- create_btn = gr.Button("Criar")
67
- create_btn.click(fn=create_user, inputs=name_input, outputs=key_output)
68
-
69
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import requests
6
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
7
  from dotenv import load_dotenv
8
+ import torch
9
 
10
+ # ----------------- Configuration & Secrets -----------------
11
+ # Load environment variables from a .env file for local development
12
  load_dotenv()
13
+
14
+ # --- Hugging Face ---
15
+ HF_TOKEN = os.environ.get("HF_TOKEN")
16
+ MODEL_NAME = "google/gemma-3-270m-it"
17
+
18
+ # --- Supabase ---
19
+ SUPABASE_URL = os.environ.get("SUPABASE_URL")
20
+ SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
21
+
22
+ # Check if essential environment variables are set
23
+ if not all([HF_TOKEN, SUPABASE_URL, SUPABASE_KEY]):
24
+ raise ValueError("Missing required environment variables (HF_TOKEN, SUPABASE_URL, SUPABASE_KEY). Please check your .env file or environment settings.")
25
 
26
  HEADERS = {
27
  "apikey": SUPABASE_KEY,
 
29
  "Content-Type": "application/json"
30
  }
31
 
32
+ # ----------------- Model Loading -----------------
33
+ # Load the Gemma model and tokenizer from Hugging Face
34
+ try:
35
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, token=HF_TOKEN)
36
+ # Load model with torch_dtype=torch.float16 for better performance if a GPU is available
37
+ model = AutoModelForCausalLM.from_pretrained(
38
+ MODEL_NAME,
39
+ token=HF_TOKEN,
40
+ torch_dtype=torch.float16,
41
+ device_map="auto" # Automatically use GPU if available
42
+ )
43
+ gen_pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
44
+ print("✅ Model loaded successfully!")
45
+ except Exception as e:
46
+ print(f"❌ Error loading model: {e}")
47
+ gen_pipe = None
48
+
49
+ # ----------------- Backend Logic (Supabase) -----------------
50
  def create_user(name: str):
51
+ """Creates a new user in Supabase and returns a unique API key."""
52
+ if not name or not name.strip():
53
+ return "⚠️ Error: User name cannot be empty.", ""
54
+
55
  api_key = str(uuid.uuid4())
56
+ data = {"name": name.strip(), "api_key": api_key}
57
+
58
+ try:
59
+ response = requests.post(
60
+ f"{SUPABASE_URL}/rest/v1/users",
61
+ headers=HEADERS,
62
+ data=json.dumps(data)
63
+ )
64
+ response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
65
+
66
+ if response.status_code in [200, 201]:
67
+ return f"✅ Success! Your API key has been created for user '{name}'.", api_key
68
+ else:
69
+ return f"⚠️ Error: Could not create user. Server responded with status {response.status_code}.", ""
70
+
71
+ except requests.exceptions.RequestException as e:
72
+ return f"❌ Network Error: {e}", ""
73
+
74
+ def check_key(api_key: str) -> bool:
75
+ """Checks if a given API key is valid by querying Supabase."""
76
+ if not api_key or not api_key.strip():
77
+ return False
78
+
79
+ try:
80
+ response = requests.get(
81
+ f"{SUPABASE_URL}/rest/v1/users?api_key=eq.{api_key.strip()}",
82
+ headers=HEADERS
83
+ )
84
+ response.raise_for_status()
85
+ return len(response.json()) > 0
86
+ except requests.exceptions.RequestException:
87
+ return False
88
+
89
+ # ----------------- Text Generation Logic -----------------
90
+ def generate_text(prompt: str, api_key: str):
91
+ """Generates text using the Gemma model if the API key is valid."""
92
+ if gen_pipe is None:
93
+ return "❌ Model is not available. Please check the server logs."
94
+
95
  if not check_key(api_key):
96
+ gr.Warning("API Key is invalid or missing! Please create a valid key.")
97
  return "API Key inválida!"
 
 
98
 
99
+ if not prompt or not prompt.strip():
100
+ gr.Warning("Prompt cannot be empty.")
101
+ return ""
102
+
103
+ try:
104
+ # Generate text using the pipeline
105
+ result = gen_pipe(
106
+ prompt,
107
+ max_new_tokens=250, # Use max_new_tokens for more control
108
+ do_sample=True,
109
+ temperature=0.7,
110
+ top_k=50,
111
+ top_p=0.95
112
+ )
113
+ return result[0]["generated_text"]
114
+ except Exception as e:
115
+ gr.Error(f"An error occurred during text generation: {e}")
116
+ return "Sorry, something went wrong."
117
+
118
+ # ----------------- Gradio Interface -----------------
119
+ # Custom CSS for a more polished look
120
+ custom_css = """
121
+ body { background-color: #F8F9FA !important; }
122
+ .gradio-container { max-width: 800px !important; margin: auto !important; }
123
+ footer { display: none !important; }
124
+ .gr-button { background-color: #1d4ed8 !important; color: white !important; border-radius: 8px !important; }
125
+ .gr-button:hover { background-color: #2563eb !important; }
126
+ .gr-input { border-radius: 8px !important; }
127
+ .gr-textbox { border-radius: 8px !important; }
128
+ #title { text-align: center; color: #1e3a8a; font-size: 2.5rem; font-weight: 600; margin-bottom: 1rem; }
129
+ #subtitle { text-align: center; color: #4b5563; font-size: 1.1rem; margin-bottom: 2rem; }
130
+ """
131
+
132
+ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
133
+ # Header
134
+ gr.Markdown("<h1 id='title'>✨ Gemma 270M API Service</h1>", elem_id="title")
135
+ gr.Markdown("<p id='subtitle'>Generate text with Google's Gemma model, secured with your own API key.</p>", elem_id="subtitle")
136
+
137
+ with gr.Tabs() as tabs:
138
+ # --- Text Generation Tab ---
139
+ with gr.TabItem("📝 Generate Text", id=0):
140
+ with gr.Column(gap="md"):
141
+ gr.Markdown("### Enter your prompt and API key below to generate text.")
142
+ api_key_input = gr.Textbox(
143
+ label="🔑 API Key",
144
+ placeholder="Enter your unique API key here...",
145
+ type="password",
146
+ lines=1
147
+ )
148
+ prompt_input = gr.Textbox(
149
+ label="💬 Prompt",
150
+ placeholder="e.g., Write a short story about a robot who discovers music...",
151
+ lines=5
152
+ )
153
+ output_text = gr.Textbox(
154
+ label="💡 Result",
155
+ lines=8,
156
+ interactive=False,
157
+ placeholder="Generated text will appear here..."
158
+ )
159
+ with gr.Row():
160
+ clear_btn_gen = gr.ClearButton(value="Clear", components=[prompt_input, output_text])
161
+ generate_btn = gr.Button("Generate", variant="primary")
162
+
163
+ # --- API Key Creation Tab ---
164
+ with gr.TabItem("🔐 Create API Key", id=1):
165
+ with gr.Column(gap="md"):
166
+ gr.Markdown("### Need an API Key? Create one here.")
167
+ name_input = gr.Textbox(label="👤 Your Name", placeholder="Enter your name to associate with the key...")
168
+ key_status_output = gr.Textbox(label="Status", interactive=False)
169
+ key_output = gr.Textbox(label="✅ Your New API Key", interactive=False)
170
+ with gr.Row():
171
+ clear_btn_key = gr.ClearButton(value="Clear", components=[name_input, key_status_output, key_output])
172
+ create_btn = gr.Button("Create Key", variant="primary")
173
+
174
+ # --- Event Handlers ---
175
+ generate_btn.click(
176
+ fn=generate_text,
177
+ inputs=[prompt_input, api_key_input],
178
+ outputs=output_text,
179
+ api_name="generate_text"
180
+ )
181
+
182
+ create_btn.click(
183
+ fn=create_user,
184
+ inputs=name_input,
185
+ outputs=[key_status_output, key_output],
186
+ api_name="create_user"
187
+ )
188
+
189
+ # Launch the Gradio app
190
+ if __name__ == "__main__":
191
+ demo.launch(server_name="0.0.0.0", server_port=7860)