BlogWriter / pipeline /search_terms.py
vivekchakraverty's picture
Add grounded blog-post generator pipeline
31fa536
Raw
History Blame Contribute Delete
2.31 kB
"""Step 1: LLM turns the topic/keywords/brief into optimized web-search queries."""
from __future__ import annotations
import json
import re
from typing import List
from huggingface_hub import InferenceClient
from . import config, llm
_SYSTEM = (
"You are an SEO research assistant. Given a blog topic, its target keywords, and a "
"brief, produce a small set of high-signal web search queries that will surface the "
"most authoritative, information-rich sources to write the post from. Vary angle and "
"specificity. Return ONLY a JSON array of query strings, nothing else."
)
def _fallback_terms(topic: str, primary: str, secondary: str) -> List[str]:
base = [t for t in [topic, primary, secondary] if t]
extra = [f"{topic} {primary}".strip(), f"{topic} guide", f"{topic} best practices"]
seen, out = set(), []
for t in base + extra:
t = t.strip()
if t and t.lower() not in seen:
seen.add(t.lower())
out.append(t)
return out[: config.N_SEARCH_TERMS]
def generate_search_terms(
client: InferenceClient,
topic: str,
primary_keyword: str,
secondary_keyword: str,
brief: str,
) -> List[str]:
user = (
f"Topic: {topic}\n"
f"Primary keyword: {primary_keyword}\n"
f"Secondary keyword: {secondary_keyword}\n"
f"Brief: {brief}\n\n"
f"Return {config.N_SEARCH_TERMS} search queries as a JSON array."
)
try:
raw = llm.chat(
client, config.MODEL_REASONING, _SYSTEM, user,
max_tokens=400, temperature=0.4,
)
terms = _parse_terms(raw)
if terms:
return terms[: config.N_SEARCH_TERMS]
except Exception:
pass
return _fallback_terms(topic, primary_keyword, secondary_keyword)
def _parse_terms(raw: str) -> List[str]:
"""Extract a list of strings from a (possibly fenced) LLM response."""
match = re.search(r"\[.*\]", raw, re.DOTALL)
if match:
try:
data = json.loads(match.group(0))
return [str(t).strip() for t in data if str(t).strip()]
except Exception:
pass
# line-based fallback
lines = [re.sub(r'^[\s\-\*\d\.\)"]+', "", ln).strip().strip('"') for ln in raw.splitlines()]
return [ln for ln in lines if ln]