Spaces:
Runtime error
Runtime error
| # app.py | |
| import gradio as gr | |
| import yake | |
| from transformers import AutoTokenizer, AutoModelForSeq2SeqLM | |
| import math | |
| # --- Models / tools (küçük ve CPU-dostu) | |
| MODEL_NAME = "google/flan-t5-small" | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) | |
| model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME) | |
| # YAKE keyword extractor (çok hafif) | |
| def extract_keywords(text, lang="en", max_kw=8): | |
| kw_extractor = yake.KeywordExtractor(lan=lang, n=1, top=max_kw) | |
| kws = kw_extractor.extract_keywords(text) | |
| # returns list of keywords (sorted) | |
| return [kw for kw, score in kws] | |
| # Basit SEO puanı hesaplama | |
| def seo_score(title, description, keywords, tags): | |
| score = 0 | |
| # title presence & length | |
| if title and title.strip(): | |
| score += 15 | |
| L = len(title) | |
| if 40 <= L <= 70: | |
| score += 20 | |
| elif 30 <= L < 40 or 71 <= L <= 90: | |
| score += 10 | |
| # keywords in title/description | |
| kw_in_title = sum(1 for k in keywords if k.lower() in (title or "").lower()) | |
| kw_in_desc = sum(1 for k in keywords if k.lower() in (description or "").lower()) | |
| score += min(20, kw_in_title * 10) | |
| score += min(15, kw_in_desc * 5) | |
| # description length | |
| dlen = len(description or "") | |
| if dlen >= 300: | |
| score += 20 | |
| elif dlen >= 150: | |
| score += 10 | |
| # tags | |
| if tags: | |
| if 3 <= len(tags) <= 15: | |
| score += 10 | |
| elif len(tags) > 15: | |
| score += 5 | |
| # normalize | |
| return min(100, score) | |
| # Title & description generator (Flan-T5) | |
| def gen_suggestions(main_text, keywords, max_titles=3): | |
| prompt = ( | |
| "You are an assistant that generates catchy YouTube video titles and an SEO-optimized description.\n" | |
| f"Main content: {main_text}\n" | |
| f"Keywords: {', '.join(keywords)}\n" | |
| "Produce 3 short catchy titles (each <70 chars) and one SEO-friendly description (2 paragraphs). " | |
| "Return clearly, titles separated by '||' then '---' then the description." | |
| ) | |
| inputs = tokenizer(prompt, return_tensors="pt") | |
| out = model.generate(**inputs, max_new_tokens=300) | |
| text = tokenizer.decode(out[0], skip_special_tokens=True) | |
| # Try to split results | |
| if "||" in text: | |
| parts = text.split("---") | |
| titles = parts[0].split("||") | |
| desc = parts[1].strip() if len(parts) > 1 else "" | |
| else: | |
| # fallback: guess | |
| lines = [l.strip() for l in text.split("\n") if l.strip()] | |
| titles = lines[:max_titles] | |
| desc = "\n".join(lines[max_titles:]) | |
| titles = [t.strip() for t in titles if t.strip()] | |
| return titles[:max_titles], desc | |
| # Gradio function | |
| def analyze(title, description, lang_choice): | |
| text = (title or "") + "\n" + (description or "") | |
| lang = "tr" if lang_choice == "Türkçe" else "en" | |
| # extract keywords | |
| keywords = extract_keywords(text, lang=lang, max_kw=8) | |
| # generate suggestions | |
| gen_titles, gen_desc = gen_suggestions(text if text.strip() else "Short video about ...", keywords) | |
| # tags: use keywords as tags (shorten) | |
| tags = [k.replace(" ", "_") for k in keywords][:12] | |
| # score | |
| score = seo_score(title, description, keywords, tags) | |
| return { | |
| "SEO Skoru (0-100)": score, | |
| "Çıkarılan Anahtar Kelimeler": ", ".join(keywords), | |
| "Önerilen Başlıklar": "\n".join([f"- {t}" for t in gen_titles]), | |
| "Önerilen Açıklama": gen_desc, | |
| "Önerilen Etiketler (tags)": ", ".join(tags) | |
| } | |
| # Gradio UI | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## YouTube SEO Asistanı — Basit & Ücretsiz (örnek)") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| title_in = gr.Textbox(label="Mevcut başlık (isteğe bağlı)", lines=1, placeholder="Var olan videonuzun başlığını yazın") | |
| desc_in = gr.Textbox(label="Açıklama / Transcript / İçerik", lines=8, placeholder="Video açıklaması veya transkriptinizi buraya yapıştırın") | |
| lang = gr.Radio(choices=["Türkçe", "English"], value="Türkçe", label="Dil") | |
| btn = gr.Button("Analiz Et") | |
| with gr.Column(scale=1): | |
| score_out = gr.Label(num_top_classes=1, label="Sonuç") | |
| result_box = gr.JSON(label="Detaylı Öneriler") | |
| btn.click(fn=analyze, inputs=[title_in, desc_in, lang], outputs=[score_out, result_box]) | |
| if __name__ == "__main__": | |
| demo.launch() | |