generate_title_headline_hooks

An integrity-checked headline generation pipeline that separates proposal, judgment, and verification to prevent hallucinated quotes and unsupported claims.

https://github.com/davidbmar/generate_title_headline_hooks  ·  private  ·  shipped

What it is

A Python-based API and library that generates multiple headline variants for a given story using specific archetypes (e.g., curiosity gap, contrarian). It enforces a 'fail-closed' integrity gate where every headline must pass deterministic quote verification and LLM-based fact-checking against the source body before being ranked and returned. The system is model-agnostic, supporting Anthropic, Alibaba Qwen, Ollama, and MLX via a unified client protocol.

Features

Quickstart

pip install -e ".[dev]"
export ANTHROPIC_API_KEY=sk-...
uvicorn api.app:app --reload
curl -s localhost:8000/headlines -H 'content-type: application/json' -d '{"title": "Flood", "body": "The dam held after an intern caught a crack.", "style": "editorial"}' | jq

Architecture

flowchart TD
    Client[Client] -->|POST /headlines| API[FastAPI App]
    API -->|Depends| Store[(SQLite Store)]
    API -->|Depends| LLMClient[LLM Client Protocol]
    LLMClient -.-> Anthropic[Anthropic Claude]
    LLMClient -.-> DashScope[Alibaba Qwen]
    LLMClient -.-> Ollama[Local Ollama]
    LLMClient -.-> MLX[Local MLX]
    API -->|run| Pipeline[Pipeline Orchestrator]
    Pipeline --> Spine[Spine Extraction]
    Spine --> Gen[Archetype Generation]
    Gen --> Gate[Integrity Gate]
    Gate -->|Pass| Rank[Ranking & Scoring]
    Gate -->|Fail| Drop[Drop Variant]
    Rank --> API

How it's built

Built with FastAPI for the HTTP interface and a modular Python backend. The core logic resides in a pipeline module that orchestrates spine extraction, archetype-constrained generation, and two-stage integrity gating (regex-based quote check + LLM fact check). Scoring uses a strategy pattern with heuristic and LLM judges. Data persistence uses SQLite via a simple Store class. Provider isolation is enforced via AST tests to ensure only the reference client imports provider-specific SDKs.

How it runs

sequenceDiagram
    participant C as Client
    participant A as API
    participant P as Pipeline
    participant L as LLM Client
    participant G as Integrity Gate
    participant S as Store
    C->>A: POST /headlines (title, body)
    A->>P: run(story, options, client)
    P->>L: complete_json (Extract Spine)
    L-->>P: Spine Data (tension, stakes, payoff_claims)
    P->>L: complete_json (Generate Archetypes)
    L-->>P: Raw Headline Variants
    loop For each variant
        P->>G: check_quote_integrity(variant, body)
        alt Quote not in body
            G-->>P: DROP
        else Quote valid
            G-->>P: PASS
            P->>L: complete_json (Fact Integrity Check)
            L-->>P: Verified/Rejected
        end
    end
    P->>P: Score surviving variants
    P-->>A: Ranked Variants
    A->>S: save_request()
    A-->>C: JSON Response (variants)

How to apply & reuse

Integrate as a microservice for newsrooms or content platforms needing safe, high-quality headline variations. Use the `/headlines` endpoint to submit article text and receive ranked, verified headlines. Extend by implementing new `LLMClient` classes for other providers or adding custom `Scorer` implementations to the ranking pipeline without modifying core logic.

At a glance

CapabilitiesHeadline GenerationIntegrity VerificationMulti-Model SupportArchetype ConstraintsAutomated RankingQuote Validation
Componentsapi/app.pyheadline/pipeline.pyheadline/llm.pyheadline/integrity.pyheadline/scorers.pyheadline/db/store.py
TechPythonFastAPIPydanticSQLiteUvicornHTTPX
Depends onanthropichttpxpydanticfastapiuvicornpytest
Integrates withAnthropic ClaudeAlibaba Cloud QwenOllamaMLX (Apple Silicon)
PatternsStrategy Pattern (Scorers)Protocol Interface (LLMClient)Pipeline ArchitectureFail-Closed SecurityDependency Injection
Reuse tagscontent-generationnlp-pipelinehallucination-preventionllm-orchestrationfastapi-service

Repo hygiene

✓ all on main — nothing unmerged.