Spaces:
Sleeping
Sleeping
Add 'what the content must cover' brief text area; screenshots stay optional
Browse files
app.py
CHANGED
|
@@ -220,7 +220,7 @@ def _collect_keywords(primary_kw, secondary_kw) -> dict:
|
|
| 220 |
|
| 221 |
def run_pipeline(topic, hf_token, yt_api_key, llm_model, vlm_model,
|
| 222 |
w_llm, w_whisper, lead, max_shots, primary_kw, secondary_kw,
|
| 223 |
-
progress=gr.Progress()):
|
| 224 |
"""Generator yielding (status_md, ranking_df, transcript, docx_file)."""
|
| 225 |
log: list[str] = []
|
| 226 |
|
|
@@ -278,8 +278,11 @@ def run_pipeline(topic, hf_token, yt_api_key, llm_model, vlm_model,
|
|
| 278 |
kw_note = f" • primary: '{keywords['primary']}'" if keywords["primary"] else ""
|
| 279 |
if keywords["secondary"]:
|
| 280 |
kw_note += f" • secondary: {', '.join(keywords['secondary'])}"
|
|
|
|
|
|
|
| 281 |
yield status(f"🤖 Generating tutorial with `{llm_model}`{kw_note}…"), ranking, gr.update(value=transcript), gr.update()
|
| 282 |
-
tut = tutorial_mod.generate_tutorial(transcript, hf_token.strip(), llm_model,
|
|
|
|
| 283 |
if keywords["primary"]:
|
| 284 |
n = tutorial_mod.count_keyword(tut, keywords["primary"])
|
| 285 |
yield (status(f"🔑 Primary keyword '{keywords['primary']}' appears {n}× in the post."),
|
|
@@ -345,6 +348,18 @@ def build_ui():
|
|
| 345 |
vlm_model = gr.Dropdown(VLM_CHOICES, value=VLM_CHOICES[0],
|
| 346 |
label="Vision model (captions)", allow_custom_value=True)
|
| 347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
with gr.Accordion("SEO / AEO keywords (optional)", open=False):
|
| 349 |
gr.Markdown(
|
| 350 |
"The **primary keyword** is used naturally ~3× in the body and placed in "
|
|
@@ -382,7 +397,8 @@ def build_ui():
|
|
| 382 |
run_btn.click(
|
| 383 |
run_pipeline,
|
| 384 |
inputs=[topic, hf_token, yt_api_key, llm_model, vlm_model,
|
| 385 |
-
w_llm, w_whisper, lead, max_shots, primary_kw, secondary_kw
|
|
|
|
| 386 |
outputs=[status_md, ranking_df, transcript_box, docx_file],
|
| 387 |
)
|
| 388 |
return demo
|
|
|
|
| 220 |
|
| 221 |
def run_pipeline(topic, hf_token, yt_api_key, llm_model, vlm_model,
|
| 222 |
w_llm, w_whisper, lead, max_shots, primary_kw, secondary_kw,
|
| 223 |
+
content_brief="", progress=gr.Progress()):
|
| 224 |
"""Generator yielding (status_md, ranking_df, transcript, docx_file)."""
|
| 225 |
log: list[str] = []
|
| 226 |
|
|
|
|
| 278 |
kw_note = f" • primary: '{keywords['primary']}'" if keywords["primary"] else ""
|
| 279 |
if keywords["secondary"]:
|
| 280 |
kw_note += f" • secondary: {', '.join(keywords['secondary'])}"
|
| 281 |
+
if (content_brief or "").strip():
|
| 282 |
+
kw_note += " • honoring your content brief"
|
| 283 |
yield status(f"🤖 Generating tutorial with `{llm_model}`{kw_note}…"), ranking, gr.update(value=transcript), gr.update()
|
| 284 |
+
tut = tutorial_mod.generate_tutorial(transcript, hf_token.strip(), llm_model,
|
| 285 |
+
keywords, brief=content_brief)
|
| 286 |
if keywords["primary"]:
|
| 287 |
n = tutorial_mod.count_keyword(tut, keywords["primary"])
|
| 288 |
yield (status(f"🔑 Primary keyword '{keywords['primary']}' appears {n}× in the post."),
|
|
|
|
| 348 |
vlm_model = gr.Dropdown(VLM_CHOICES, value=VLM_CHOICES[0],
|
| 349 |
label="Vision model (captions)", allow_custom_value=True)
|
| 350 |
|
| 351 |
+
content_brief = gr.Textbox(
|
| 352 |
+
label="What the content must cover (optional)",
|
| 353 |
+
lines=4,
|
| 354 |
+
placeholder=("List the points, steps, or questions the tutorial must address — "
|
| 355 |
+
"one per line or comma-separated.\n"
|
| 356 |
+
"e.g. How to create a pivot table\nHow to refresh data\n"
|
| 357 |
+
"Common pivot table errors"),
|
| 358 |
+
info=("Required coverage for the tutorial writer. Leave blank to just follow "
|
| 359 |
+
"the video. Screenshots stay optional — if none are suitable the post is "
|
| 360 |
+
"produced without them."),
|
| 361 |
+
)
|
| 362 |
+
|
| 363 |
with gr.Accordion("SEO / AEO keywords (optional)", open=False):
|
| 364 |
gr.Markdown(
|
| 365 |
"The **primary keyword** is used naturally ~3× in the body and placed in "
|
|
|
|
| 397 |
run_btn.click(
|
| 398 |
run_pipeline,
|
| 399 |
inputs=[topic, hf_token, yt_api_key, llm_model, vlm_model,
|
| 400 |
+
w_llm, w_whisper, lead, max_shots, primary_kw, secondary_kw,
|
| 401 |
+
content_brief],
|
| 402 |
outputs=[status_md, ranking_df, transcript_box, docx_file],
|
| 403 |
)
|
| 404 |
return demo
|