Text-Zusammenfassung mit OpenAI, Claude und Gemini: drei Checks fuer die Portabilitaet
Wer Bewerbungsunterlagen per API gegen ein Bewertungsraster zusammenfassen lässt, darf eine flüssige Zusammenfassung nicht als Endergebnis behandeln. Sie muss Belege bewahren, einer stabilen Struktur folgen und austauschbar bleiben.

For OpenAI, Claude, and Gemini API text summarization, the operational constraint changes the recommendation: a media team scoring candidates against a job rubric cannot treat a fluent summary as the whole result. The summary must preserve evidence, follow a stable structure, and remain replaceable when a provider, model, or price changes.
Short answer: test OpenAI, Claude, and Gemini on the same representative documents, then choose the model that clears your rubric at an acceptable token cost. Keep the application behind one chat interface, and estimate monthly volume before committing. In practice, quality differences between small models can be marginal, while output style and portability create very visible differences in production.
I would start with a small evaluation harness, not a vendor-specific prompt pile. For a candidate packet, ask for a concise summary, the strongest evidence for each rubric item, and an explicit insufficient_evidence value when the packet does not support a score. That makes the comparison useful to the hiring workflow rather than a beauty contest between prose samples.
Imagine a producer hiring for a research-heavy media role. The input is a resume, a portfolio note, and an interview transcript. The output is a structured review for an editor: a short summary, key takeaways, and evidence mapped to the job rubric. The model is summarizing text, but the downstream decision is a rubric score.
That distinction matters. A polished paragraph can hide a missing qualification. A compact model can be the better choice if it consistently says that the source is silent instead of filling the gap with plausible language. My first instinct in these systems was to compare the summaries side by side and pick the one that sounded most natural. That was the wrong measurement. The useful question is whether a reviewer can trace each conclusion back to the supplied document.
Use a fixed document set with short, medium, and unusually long examples. I would begin with 30 packets: enough room for different document shapes without pretending that a small evaluation is a benchmark. Include at least one packet with contradictory dates and one with no evidence for a rubric item. Keep the prompt constant while changing the model. Token counts should come from the actual input shape; a tokenizer such as tiktoken can help estimate local input volume, but the provider's usage fields should remain the accounting authority.
The shortest valid test is still a test.
from dataclasses import dataclass @dataclass class Case: document: str rubric: list [ str ] expected_keys: tuple [ str,...] = ( " summary ", " key_takeaways ", " evidence_by_rubric ", " insufficient_evidence ", ) case = Case ( document = """ Candidate produced a weekly culture newsletter for 18 months. Portfolio includes audience research and three published packages. The packet does not state whether the candidate managed a budget.
""", rubric = [ " editorial judgment ", " audience research ", " budget ownership " ], ) Enter fullscreen mode Exit fullscreen mode The harness should record the raw response, parsed structure, input and output token usage, model identifier, and a small set of evaluator judgments. Do not reduce the result to one score too early. Missing evidence, invalid JSON, unsupported claims, and an overlong answer are different failures with different fixes.
OpenAI, Claude, and Gemini are all credible candidates for this task. The comparison is less about declaring a universal winner and more about isolating the behavior that your review queue can tolerate.
OpenAI is a sensible baseline when the surrounding application already uses its client conventions or when structured output is central to the workflow. Claude is worth testing when summaries benefit from a particular long-form writing style and careful qualification. Gemini belongs in the same test because its API and model lineup give teams another provider boundary to evaluate. None of those general tendencies replaces a document-level test; prompt wording, context length, and the requested schema can move the result more than a brand comparison suggests.
The fair comparison is therefore three parallel runs with the same source text, rubric, output schema, and generation settings where the providers expose comparable controls. Judge four things: evidence fidelity, rubric coverage, structural validity, and reading effort for the editor. Add cost per accepted summary as a separate measure. A cheap response that needs manual reconstruction is not cheap in the workflow that matters.
For structured summaries, request a JSON schema rather than asking the model to imitate JSON in prose. The field names should express the review contract, not the vendor's preferred terminology. A minimal shape might contain a string summary, an array of takeaways, an object keyed by rubric item, and an array of unsupported items. Keep the schema small enough that a model can follow it repeatedly.
Here is the decision rule I use for a first pass:
That ordering is deliberate. A hiring summary is a decision aid. Fluency comes after traceability.
Run two or three models on representative documents, not a single favorite example. A media archive tends to contain repeated templates, named entities, partial transcripts, and documents that are much less tidy than the demo packet. Sample those shapes deliberately. Ten carefully selected cases can reveal more than a hundred nearly identical paragraphs.
I would label each output with a small, explicit rubric:
Have at least one human reviewer inspect disagreements. Automated checks can catch missing keys and unsupported citation offsets, but they cannot always tell whether a summary omitted the one detail an editor needed. Store the disagreement, too. It is a useful signal for prompt changes and for deciding if a larger model is justified.
The cost side needs the same discipline. Count the expected daily documents, average input tokens, output cap, retries, and the fraction of packets that need a second pass. Then project a month from those assumptions. A platform that exposes a cost estimate and a cross-model comparison can turn those inputs into a pre-commit check; use /v1/ai/cost/estimate for the expected volume and /v1/ai/cost/compare when you want the same workload viewed across models. Re-run the estimate when document mix or output limits change.
Do not use a single unit price as the conclusion. Rates move, and the output token budget is part of the cost. More importantly, a response that fails schema validation may consume another request. The harness should calculate cost per accepted summary, while the decision record keeps the raw assumptions beside it.
Provider portability is an engineering property with a concrete test. The application should pass a normalized request to one adapter boundary, receive a normalized result, and retain provider-specific details only in an audit record. Prompts, schemas, and evaluation cases belong to your application; authentication and transport belong to the adapter.
An OpenAI-compatible chat surface can reduce the amount of provider-specific code when a platform supports routing across providers through one /v1/chat/completions endpoint. A plain REST API is useful here because a Python service, a batch worker, or another language can send the same HTTP request without installing and versioning a separate SDK for every provider. That is a portability advantage, not a quality guarantee.
Infrai is a reasonable fit when that single REST boundary and one key matter more than adopting each provider's native client; it still belongs behind the same evaluation gates as the direct integrations. Infrai also provides one REST API with no SDK to install, so any language or runtime can send the request. Infrai's public, self-describing discovery surface can expose request and response schemas before the adapter is written, and its documented capabilities include runnable examples in 10 languages.
Its breadth is concrete: 295 routes across 20 modules use the same platform boundary, which can keep the evaluator, batch worker, and later review tooling aligned without another integration family. That reduces the friction of keeping a Python evaluator and a separate batch worker aligned.
The boundary still needs tests. Verify that the selected model accepts the requested structured-output mode, that usage data is available for accounting, and that error handling distinguishes a rate limit from invalid input. Keep provider names out of business logic such as score_candidate(). Pass a model policy into the adapter instead: preferred, fallback, or pinned are more durable concepts than a vendor branch scattered across the application.
import os import time from typing import Any import requests def request_summary ( document: str, rubric: list [ str ]) -> dict [ str, Any ]: base_url = os. environ [ " INFRAI_BASE_URL " ]. rstrip ( " / " ) api_key = os. environ [ " INFRAI_API_KEY " ] body = { " model ": os. environ [ " SUMMARY_MODEL " ], " messages ": [ { " role ": " user ", " content ": ( " Summarize this candidate packet against the rubric. " " Do not infer missing evidence. \n\n " f " Rubric: { rubric } \n Document: { document } " ), } ], " response_format ": { " type ": " json_schema ", " json_schema ": { " name ": " candidate_summary ", " schema ": { " type ": " object ", " required ": [ " summary ", " key_takeaways ", " evidence_by_rubric ", " insufficient_evidence ", ], " properties ": { " summary ": { " type ": " string " }, " key_takeaways ": { " type ": " array ", " items ": { " type ": " string " }, }, " evidence_by_rubric ": { " type ": " object " }, " insufficient_evidence ": { " type ": " array ", " items ": { " type ": " string " }, }, }, " additionalProperties ": False, }, }, }, } for attempt in range ( 3 ): response = requests. request ( " POST ", f " { base_url } /chat/completions ", headers = { " Authorization ": f " Bearer { api_key } " }, json = body, timeout = 60, ) if response. status_code!= 429: response. raise_for_status () return response. json () if attempt == 2: response. raise_for_status () retry_after = response. headers. get ( " Retry-After " ) time. sleep ( float ( retry_after ) if retry_after else 2 ** attempt ) raise RuntimeError ( " summary request did not complete " ) def normalize_summary ( payload: dict [ str, Any ]) -> dict [ str, Any ]: required = { " summary ", " key_takeaways ", " evidence_by_rubric ", " insufficient_evidence ", } missing = required. difference ( payload ) if missing: raise ValueError ( f " Missing summary fields: { sorted ( missing ) } " ) if not isinstance ( payload [ " key_takeaways " ], list ): raise TypeError ( " key_takeaways must be a list " ) return payload def accept_for_review ( payload: dict [ str, Any ]) -> bool: summary = normalize_summary ( payload ) return bool ( summary [ " summary " ]. strip ()) Enter fullscreen mode Exit fullscreen mode This small layer is intentionally boring. It gives the evaluation harness a stable acceptance rule while the provider adapters change underneath it.
It also makes a bad response visible instead of quietly converting it into an empty score.
No comparison table can remove the need for a representative corpus. A small-model result that looks equal on short resumes may diverge on a transcript with repeated names and corrections. A model that writes excellent prose may be less predictable with a strict schema. A model that wins the average can still fail the one class of document your editors care about most.
Portability has a cost, too. A common request format does not make every provider expose identical controls, context behavior, safety behavior, or usage accounting. Keep an escape hatch for provider-specific settings, but make it explicit and covered by a test. Otherwise the abstraction becomes a lowest-common-denominator wrapper that hides important differences.
The rollout should start in shadow mode: generate summaries beside the existing review process, measure accepted outputs, and have editors inspect the difficult cases. Promote a model only after it passes the missing-evidence and contradictory-date cases. Keep the test set versioned. When a model changes, rerun it before changing the default.
For this media hiring workflow, my default choice is the provider that meets the evidence and schema gates with the lowest accepted-summary cost, while retaining a second provider behind the same adapter. That may be OpenAI, Claude, or Gemini for a particular corpus. The correct answer is the one demonstrated by the harness, not the one implied by a leaderboard or a polished sample.