SEO / app.py
Ugurrrrr's picture
Create app.py
91cb15f verified
# 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()