Meetings generate hours of audio that nobody re-listens to, and decisions get lost. Automatic summarization turns a raw transcript into a tight recap with action items and owners. This article builds a meeting summarization service on Model Database that handles long transcripts and produces structured, shareable output.
The interesting engineering is in handling length and extracting structure reliably, not in a single clever prompt. We'll cover chunking, structured extraction, and quality checks.
From audio to text
Summarization starts with a transcript. Use any speech-to-text service to produce one, ideally with speaker labels and timestamps. Everything below operates on that text, so the pipeline works equally for meetings, interviews, or support calls.
Handling long transcripts
An hour-long meeting can exceed what you want in a single prompt. The reliable approach is map-reduce: summarize chunks, then summarize the summaries.
def chunk_transcript(text, size=6000, overlap=400):
out, i = [], 0
while i < len(text):
out.append(text[i:i + size])
i += size - overlap
return out
Overlap preserves context across boundaries so a thought that spans two chunks isn't lost.
The map step: summarize each chunk
from openai import OpenAI
client = OpenAI(
base_url="https://modeldatabase.com/v1",
api_key="mdb_live_...",
)
def summarize_chunk(chunk):
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "system", "content":
"Summarize this meeting segment in 4-6 bullet points. "
"Capture decisions, action items, and open questions. "
"Preserve who said what when named."},
{"role": "user", "content": chunk},
],
temperature=0.2,
)
return resp.choices[0].message.content
The map step is high-volume, so a fast, cheap model like openai/gpt-4o-mini keeps cost low.
The reduce step: structured final summary
Combine the chunk summaries into one structured object. Here a stronger model pays off because it must reconcile and deduplicate across the whole meeting.
import json
def final_summary(chunk_summaries):
joined = "\n\n".join(chunk_summaries)
resp = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[
{"role": "system", "content":
"Combine these segment summaries into JSON: "
"{\"tldr\": str, \"decisions\": [str], "
"\"action_items\": [{\"task\", \"owner\", \"due\"}], "
"\"open_questions\": [str]}. Use null for unknown owners "
"or dates. Do not invent details."},
{"role": "user", "content": joined},
],
response_format={"type": "json_object"},
temperature=0.1,
)
return json.loads(resp.choices[0].message.content)
Structured output means you can drop action items straight into a task tracker and render decisions in a clean recap email.
Action items people actually use
The most valuable output of a meeting summary is a clear list of who owns what. Make the model attribute owners only when the transcript names them, and flag the rest for a human to assign.
def needs_owner(summary):
return [a for a in summary["action_items"] if not a["owner"]]
Surfacing unassigned tasks in the recap prompts the team to fill the gaps, rather than letting the model guess and assign work to the wrong person.
Quality and trust
- Ground every claim: the prompt forbids inventing details, so a missing due date stays null instead of becoming a fabricated deadline.
- Keep the transcript: store it alongside the summary so anyone can verify a contested point against the source.
- Speaker labels help: when the transcript identifies speakers, the model attributes decisions far more accurately.
- Review sensitive meetings: for legal or HR contexts, treat the summary as a draft that a person confirms.
Cost and model choice
Map-reduce keeps cost predictable: the expensive reduce step runs once per meeting, while the cheap map step scales with length. Log token usage per meeting, and if your transcripts are short, you may skip chunking entirely and summarize in one call. Test whether the small model alone is good enough for your meetings before reaching for a larger one. Every model is behind the same Model Database endpoint, so changing the mix is a one-line edit, and prepaid pay-as-you-go billing means short meetings cost almost nothing.
Get a key and credit at your dashboard, and see JSON-mode and limits in the docs.