deankk commited on
Commit
0eec904
·
verified ·
1 Parent(s): 684c556

Update app.py

Browse files

❌ Versi lama: panggil API di internet → ERROR (Space gratis ga bisa akses internet)
✅ Versi baru: model di-load langsung di Space → jalan 100% offline

❌ Versi lama: butuh setup HF_TOKEN
✅ Versi baru: GA PERLU TOKEN, ga perlu setup apapun

❌ Versi lama: model 3B (ga bisa di-load di Space gratis)
✅ Versi baru: model 0.5B (muat di RAM Space gratis)

Satu-satunya trade-off:
- Model lebih kecil → kualitas caption sedikit lebih rendah
- Tapi tetap bisa bikin caption yang usable!

Files changed (1) hide show
  1. app.py +44 -129
app.py CHANGED
@@ -1,39 +1,32 @@
1
  """
2
  ✍️ CapGen AI — Caption Generator Indonesia
3
  ===========================================
4
- SETUP (HANYA 2 LANGKAH):
5
- ------------------------
6
- 1. Buat token gratis di: https://huggingface.co/settings/tokens
7
- - Klik "New token"
8
- - Type pilih "Read" (cukup ini saja)
9
- - Copy token-nya
10
-
11
- 2. Di Space kamu, buka: Settings → Repository Secrets
12
- - Name: HF_TOKEN
13
- - Value: paste token tadi
14
- - Klik Save
15
-
16
- SELESAI! Restart Space dan langsung bisa dipakai.
17
  """
18
 
19
  import gradio as gr
20
- import requests
21
- import os
22
 
23
  # ══════════════════════════════════════════════════════
24
  # KONFIGURASI MODEL
25
  # ══════════════════════════════════════════════════════
26
- # Ganti model di sini kalau ada yang error.
27
- # Model-model ini biasanya tersedia gratis:
28
- MODEL_NAME = "Qwen/Qwen2.5-1.5B-Instruct"
29
- # MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct" # Paling kecil, paling pasti gratis
30
- # MODEL_NAME = "google/gemma-2-2b-it" # Alternatif
31
- # MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.3" # Alternatif
32
- # MODEL_NAME = "HuggingFaceH4/zephyr-7b-beta" # Alternatif
33
-
34
- HF_TOKEN = os.environ.get("HF_TOKEN", "")
35
- CHAT_API = f"https://api-inference.huggingface.co/models/{MODEL_NAME}/v1/chat/completions"
36
- TEXT_API = f"https://api-inference.huggingface.co/models/{MODEL_NAME}"
 
 
 
 
37
 
38
  # ══════════════════════════════════════════════════════
39
  # DATA
@@ -91,69 +84,29 @@ ATURAN KETAT (WAJIB DIIKUTI):
91
 
92
 
93
  # ══════════════════════════════════════════════════════
94
- # LOGIC
95
  # ══════════════════════════════════════════════════════
96
 
97
- def call_api(messages):
98
- headers = {
99
- "Authorization": f"Bearer {HF_TOKEN}",
100
- "Content-Type": "application/json"
101
- }
102
- params = {"max_tokens": 1000, "temperature": 0.85, "top_p": 0.9}
103
-
104
- # ── Attempt 1: Chat Completions API ──
105
- try:
106
- resp = requests.post(
107
- CHAT_API, headers=headers,
108
- json={"model": MODEL_NAME, "messages": messages, **params},
109
- timeout=60
 
 
110
  )
111
- if resp.status_code == 200:
112
- return resp.json()["choices"][0]["message"]["content"]
113
- if resp.status_code == 503:
114
- return "LOADING"
115
- if resp.status_code == 429:
116
- return "RATE_LIMIT"
117
- # Error lainnya — simpan info buat debugging
118
- return f"CHAT_ERROR_{resp.status_code}:{resp.text[:300]}"
119
- except requests.exceptions.Timeout:
120
- return "TIMEOUT"
121
- except Exception as e:
122
- return f"CHAT_EXCEPTION:{str(e)[:200]}"
123
 
124
- # ── Attempt 2: Text Generation API (fallback) ──
125
- # Kode di bawah ini hanya jalan kalau chat API tidak reachable sama sekali
126
- try:
127
- prompt = f"{messages[0]['content']}\n\n{messages[1]['content']}"
128
- resp = requests.post(
129
- TEXT_API, headers=headers,
130
- json={
131
- "inputs": prompt,
132
- "parameters": {
133
- "max_new_tokens": 1000,
134
- "temperature": 0.85,
135
- "top_p": 0.9,
136
- "return_full_text": False
137
- }
138
- },
139
- timeout=60
140
- )
141
- if resp.status_code == 200:
142
- data = resp.json()
143
- if isinstance(data, list) and "generated_text" in data[0]:
144
- text = data[0]["generated_text"]
145
- if prompt in text:
146
- text = text.replace(prompt, "").strip()
147
- return text
148
- if resp.status_code == 503:
149
- return "LOADING"
150
- if resp.status_code == 429:
151
- return "RATE_LIMIT"
152
- return f"TEXT_ERROR_{resp.status_code}:{resp.text[:300]}"
153
- except requests.exceptions.Timeout:
154
- return "TIMEOUT"
155
- except Exception as e:
156
- return f"TEXT_EXCEPTION:{str(e)[:200]}"
157
 
158
 
159
  def clean_text(text):
@@ -202,18 +155,6 @@ def generate_caption(konteks, platform, gaya, bahasa, jumlah):
202
  vals = ["⚠️ Tulis dulu deskripsi foto/konten kamu di kolom atas!"] + [""] * 4
203
  return tuple(gr.update(value=v, visible=True) for v in vals)
204
 
205
- if not HF_TOKEN:
206
- msg = (
207
- "⚠️ TOKEN BELUM DISET!\n\n"
208
- "Cara setup:\n"
209
- "1. Buat token di huggingface.co/settings/tokens\n"
210
- "2. Di Space ini: Settings → Repository Secrets\n"
211
- "3. Name: HF_TOKEN Value: paste token\n"
212
- "4. Restart Space"
213
- )
214
- vals = [msg] + [""] * 4
215
- return tuple(gr.update(value=v, visible=True) for v in vals)
216
-
217
  user_msg = f"""PLATFORM: {platform}
218
  {PLATFORMS[platform]}
219
 
@@ -233,38 +174,12 @@ BUAT TEPAT {jumlah} CAPTION YANG BERBEDA."""
233
  {"role": "user", "content": user_msg}
234
  ]
235
 
236
- result = call_api(messages)
237
-
238
- # Handle error spesifik
239
- if result == "LOADING":
240
- vals = ["⏳ Model sedang loading... Tunggu 20-30 detik lalu coba lagi."] + [""] * 4
241
- return tuple(gr.update(value=v, visible=True) for v in vals)
242
-
243
- if result == "RATE_LIMIT":
244
- vals = ["⚠️ Terlalu banyak request. Tunggu 1-2 menit lalu coba lagi."] + [""] * 4
245
- return tuple(gr.update(value=v, visible=True) for v in vals)
246
-
247
- if result == "TIMEOUT":
248
- vals = ["⏳ Request timeout. Coba lagi."] + [""] * 4
249
- return tuple(gr.update(value=v, visible=True) for v in vals)
250
-
251
- # Kalau error dari API, tampilkan detailnya biar bisa debug
252
- if result and (result.startswith("CHAT_ERROR") or result.startswith("TEXT_ERROR")
253
- or result.startswith("CHAT_EXCEPTION") or result.startswith("TEXT_EXCEPTION")):
254
- detail = result.replace("CHAT_ERROR_", "").replace("TEXT_ERROR_", "")
255
- msg = (
256
- f"❌ Error dari API:\n\n{detail}\n\n"
257
- f"Model yang dipakai: {MODEL_NAME}\n\n"
258
- f"Coba ganti model di kode app.py baris paling atas.\n"
259
- f"Model yang biasanya gratis:\n"
260
- f"• Qwen/Qwen2.5-0.5B-Instruct\n"
261
- f"• Qwen/Qwen2.5-1.5B-Instruct\n"
262
- f"• google/gemma-2-2b-it"
263
- )
264
- vals = [msg] + [""] * 4
265
  return tuple(gr.update(value=v, visible=True) for v in vals)
266
 
267
- # Sukses — parse caption
268
  captions = parse_captions(result, jumlah)
269
 
270
  output = []
@@ -322,7 +237,7 @@ with gr.Blocks() as demo:
322
  Caption Generator Khusus Bahasa Indonesia
323
  </p>
324
  <p style="font-size:13px; color:#999; margin:2px 0 0 0;">
325
- Gak perlu login · Gak perlu jago prompt · Langsung kepakai
326
  </p>
327
  </div>
328
  """)
@@ -425,7 +340,7 @@ with gr.Blocks() as demo:
425
  gr.Markdown(
426
  '<div class="footer-text">'
427
  "Dibuat dengan ❤️ untuk komunitas Indonesia · "
428
- "Powered by Hugging Face Inference API"
429
  "</div>"
430
  )
431
 
 
1
  """
2
  ✍️ CapGen AI — Caption Generator Indonesia
3
  ===========================================
4
+ GA PERLU TOKEN. GA PERLU SETUP APAPUN.
5
+ Langsung jalan setelah Space selesai building.
 
 
 
 
 
 
 
 
 
 
 
6
  """
7
 
8
  import gradio as gr
9
+ import torch
10
+ from transformers import AutoTokenizer, AutoModelForCausalLM
11
 
12
  # ══════════════════════════════════════════════════════
13
  # KONFIGURASI MODEL
14
  # ══════════════════════════════════════════════════════
15
+ # Model kecil yang pasti muat di akun gratis (CPU, ~2GB RAM)
16
+ MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
17
+ # MODEL_NAME = "Qwen/Qwen2.5-1.5B-Instruct" # Lebih pintar, tapi butuh lebih banyak RAM
18
+
19
+ print(f"⏳ Loading model {MODEL_NAME}...")
20
+ print("Ini bisa memakan waktu 1-3 menit saat pertama kali...")
21
+
22
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
23
+ model = AutoModelForCausalLM.from_pretrained(
24
+ MODEL_NAME,
25
+ torch_dtype=torch.float32,
26
+ trust_remote_code=True,
27
+ )
28
+ model.eval()
29
+ print("✅ Model siap!")
30
 
31
  # ══════════════════════════════════════════════════════
32
  # DATA
 
84
 
85
 
86
  # ══════════════════════════════════════════════════════
87
+ # LOGIC — GENERATE LANGSUNG DI CPU
88
  # ══════════════════════════════════════════════════════
89
 
90
+ def generate_text(messages, max_new_tokens=800, temperature=0.85, top_p=0.9):
91
+ """Generate teks pakai model lokal"""
92
+ text = tokenizer.apply_chat_template(
93
+ messages, tokenize=False, add_generation_prompt=True
94
+ )
95
+ inputs = tokenizer(text, return_tensors="pt")
96
+
97
+ with torch.no_grad():
98
+ outputs = model.generate(
99
+ **inputs,
100
+ max_new_tokens=max_new_tokens,
101
+ temperature=temperature,
102
+ top_p=top_p,
103
+ do_sample=True,
104
+ repetition_penalty=1.15,
105
  )
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
+ # Ambil hanya bagian yang di-generate (bukan prompt)
108
+ new_tokens = outputs[0][inputs["input_ids"].shape[-1]:]
109
+ return tokenizer.decode(new_tokens, skip_special_tokens=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
 
112
  def clean_text(text):
 
155
  vals = ["⚠️ Tulis dulu deskripsi foto/konten kamu di kolom atas!"] + [""] * 4
156
  return tuple(gr.update(value=v, visible=True) for v in vals)
157
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  user_msg = f"""PLATFORM: {platform}
159
  {PLATFORMS[platform]}
160
 
 
174
  {"role": "user", "content": user_msg}
175
  ]
176
 
177
+ try:
178
+ result = generate_text(messages)
179
+ except Exception as e:
180
+ vals = [f"❌ Error saat generate: {str(e)[:300]}"] + [""] * 4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  return tuple(gr.update(value=v, visible=True) for v in vals)
182
 
 
183
  captions = parse_captions(result, jumlah)
184
 
185
  output = []
 
237
  Caption Generator Khusus Bahasa Indonesia
238
  </p>
239
  <p style="font-size:13px; color:#999; margin:2px 0 0 0;">
240
+ Gak perlu login · Gak perlu token · Langsung kepakai
241
  </p>
242
  </div>
243
  """)
 
340
  gr.Markdown(
341
  '<div class="footer-text">'
342
  "Dibuat dengan ❤️ untuk komunitas Indonesia · "
343
+ f"Model: {MODEL_NAME}"
344
  "</div>"
345
  )
346