How to Build a Text Summarization API With an LLM
A summarization API is one endpoint: take text in, send it to the LLM with a clear summarize prompt, return the summary out. The quality lives in the prompt and the input handling. Here's how to build it.
The shape
POST /summarize takes {"text": "..."}, calls the LLM with a summarization instruction,
and returns {"summary": "..."}. The LLM does the work - your job is a clean endpoint and a
good prompt.
The endpoint
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
LLM_URL = "http://llm-service:8080/v1/chat/completions"
@app.post("/summarize")
def summarize():
text = (request.get_json() or {}).get("text", "").strip()
if not text:
return jsonify({"error": "text is required"}), 400
payload = {
"model": "the-model",
"messages": [
{"role": "system", "content": "You summarize text concisely and accurately. "
"Return only the summary, no preamble."},
{"role": "user", "content": f"Summarize the following:\n\n{text}"},
],
}
r = requests.post(LLM_URL, json=payload, timeout=60)
r.raise_for_status()
summary = r.json()["choices"][0]["message"]["content"]
return jsonify({"summary": summary})
What makes it good
- A system prompt that constrains the output - "return only the summary, no preamble" stops the model from adding "Here's a summary:" noise.
- Validate input - reject empty bodies with
400; that's the most common caller bug. - Control length - ask for "in 2-3 sentences" or "in under 50 words" if callers need a bounded summary; pass it through as a parameter.
- Timeout + error handling - LLM calls are slow and occasionally fail; set a timeout and
return a clean
502/error rather than hanging. - Long inputs - if text can exceed the model's context window, chunk it and summarize the chunks, then summarize the summaries (map-reduce).
Long inputs and consistent quality
Two things separate a toy summarizer from a usable one. Long inputs: any document longer than the model's context window must be chunked - split on paragraph boundaries, summarize each chunk, then summarize the summaries (a map-reduce pass). Track token counts so an oversized request fails fast with a clear error instead of a truncated, misleading summary.
Consistent output: put the rules in the system prompt, not the user text - length ("3 sentences" or "5 bullets"), audience, and tone. Use a low temperature so the same input gives a stable summary, and return structured output so callers don't parse free text. Guard against prompt injection from the document itself by clearly delimiting the content and instructing the model to treat it as data, not instructions. Add a timeout and a graceful error so one slow or oversized request can't hang the endpoint.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Wiring a POST /summarize endpoint to the LLM
- Writing a system prompt that returns only the summary
- Validating input + handling long text with chunking
FAQ
How do I build a text summarization API with an LLM?
Expose a POST endpoint that takes the text, sends it to the LLM with a system prompt instructing it to summarize concisely and return only the summary, and returns the model's reply. Validate the input and set a timeout.
How do I control the length of an LLM summary?
Put the constraint in the prompt - e.g. 'summarize in 2-3 sentences' or 'in under 50 words' - and expose it as a request parameter so callers can ask for short or detailed summaries.
How do I summarize text longer than the model's context window?
Chunk the text, summarize each chunk, then summarize the combined chunk-summaries (a map-reduce approach), so you never exceed the context limit in a single call.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →