Spaces:
Sleeping
Sleeping
Add 'what the content must cover' brief text area; screenshots stay optional
Browse files- pipeline/tutorial.py +20 -1
pipeline/tutorial.py
CHANGED
|
@@ -63,6 +63,8 @@ Rules:
|
|
| 63 |
limitations where relevant.
|
| 64 |
- Output valid JSON only. No markdown, no comments in the actual output.
|
| 65 |
|
|
|
|
|
|
|
| 66 |
{keyword_block}
|
| 67 |
|
| 68 |
Transcript (each line is "[mm:ss] text"):
|
|
@@ -72,6 +74,21 @@ Transcript (each line is "[mm:ss] text"):
|
|
| 72 |
"""
|
| 73 |
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
def _keyword_block(keywords: dict | None) -> str:
|
| 76 |
"""Render the SEO/keyword placement guidance injected into the prompt.
|
| 77 |
|
|
@@ -185,11 +202,12 @@ def count_keyword(tutorial: dict, keyword: str) -> int:
|
|
| 185 |
|
| 186 |
|
| 187 |
def generate_tutorial(transcript: str, hf_token: str, model: str = DEFAULT_LLM,
|
| 188 |
-
keywords: dict | None = None) -> dict:
|
| 189 |
"""Call the chat model and return a normalized tutorial dict.
|
| 190 |
|
| 191 |
Returned keys: ``title, slug, meta_description, answer, intro, steps, faqs``.
|
| 192 |
``keywords`` is ``{"primary": str, "secondary": [str, ...]}`` for SEO placement.
|
|
|
|
| 193 |
"""
|
| 194 |
if not hf_token:
|
| 195 |
raise ValueError("An HF token is required for the tutorial LLM (billed to your key).")
|
|
@@ -198,6 +216,7 @@ def generate_tutorial(transcript: str, hf_token: str, model: str = DEFAULT_LLM,
|
|
| 198 |
if len(transcript) > MAX_TRANSCRIPT_CHARS:
|
| 199 |
truncated += "\n[... transcript truncated for length ...]"
|
| 200 |
prompt = (_INSTRUCTIONS
|
|
|
|
| 201 |
.replace("{keyword_block}", _keyword_block(keywords))
|
| 202 |
.replace("{transcript}", truncated))
|
| 203 |
|
|
|
|
| 63 |
limitations where relevant.
|
| 64 |
- Output valid JSON only. No markdown, no comments in the actual output.
|
| 65 |
|
| 66 |
+
{brief_block}
|
| 67 |
+
|
| 68 |
{keyword_block}
|
| 69 |
|
| 70 |
Transcript (each line is "[mm:ss] text"):
|
|
|
|
| 74 |
"""
|
| 75 |
|
| 76 |
|
| 77 |
+
def _brief_block(brief: str | None) -> str:
|
| 78 |
+
"""Render the user's 'what the content must cover' brief into the prompt."""
|
| 79 |
+
brief = (brief or "").strip()
|
| 80 |
+
if not brief:
|
| 81 |
+
return ("Content brief: none provided — cover the video's key steps faithfully "
|
| 82 |
+
"based on the transcript.")
|
| 83 |
+
return (
|
| 84 |
+
"Content brief — REQUIRED COVERAGE. The tutorial MUST address every point below. "
|
| 85 |
+
"Ground each point in the transcript where possible; if the transcript doesn't "
|
| 86 |
+
"cover a required point, still cover it accurately and concisely and don't invent "
|
| 87 |
+
"specifics that contradict the video. Organise the steps so these points are "
|
| 88 |
+
"clearly covered:\n" + brief
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
def _keyword_block(keywords: dict | None) -> str:
|
| 93 |
"""Render the SEO/keyword placement guidance injected into the prompt.
|
| 94 |
|
|
|
|
| 202 |
|
| 203 |
|
| 204 |
def generate_tutorial(transcript: str, hf_token: str, model: str = DEFAULT_LLM,
|
| 205 |
+
keywords: dict | None = None, brief: str | None = None) -> dict:
|
| 206 |
"""Call the chat model and return a normalized tutorial dict.
|
| 207 |
|
| 208 |
Returned keys: ``title, slug, meta_description, answer, intro, steps, faqs``.
|
| 209 |
``keywords`` is ``{"primary": str, "secondary": [str, ...]}`` for SEO placement.
|
| 210 |
+
``brief`` is the user's free-text 'what the content must cover' requirement.
|
| 211 |
"""
|
| 212 |
if not hf_token:
|
| 213 |
raise ValueError("An HF token is required for the tutorial LLM (billed to your key).")
|
|
|
|
| 216 |
if len(transcript) > MAX_TRANSCRIPT_CHARS:
|
| 217 |
truncated += "\n[... transcript truncated for length ...]"
|
| 218 |
prompt = (_INSTRUCTIONS
|
| 219 |
+
.replace("{brief_block}", _brief_block(brief))
|
| 220 |
.replace("{keyword_block}", _keyword_block(keywords))
|
| 221 |
.replace("{transcript}", truncated))
|
| 222 |
|