One request that triggers many model calls
Extra model calls (moderation, titles, summaries) multiplying every request.
Why it costs money
A user sends one message and sees one answer. Behind it, the handler may rewrite the query, embed it, classify it, generate the answer, write a title and update a memory store. Each of those is billed like any other call.
These side calls are usually added one at a time, each small and reasonable, so no single change looks expensive. The per-request cost is the sum, and it multiplies with every request. Side calls that repeat the full conversation as input can cost more than the answer itself.
Example
Flagged
export async function POST(req: Request) {
const { chatId, message, isFirstMessage } = await req.json();
const rewrite = await openai.chat.completions.create({
model: "gpt-4o", max_tokens: 100,
messages: [{ role: "user", content: "Rewrite as a search query: " + message }],
});
const query = rewrite.choices[0].message.content ?? message;
const emb = await openai.embeddings.create({ model: "text-embedding-3-small", input: query });
const docs = await searchDocs(emb.data[0].embedding);
const answer = await openai.chat.completions.create({
model: "gpt-4o", max_tokens: 800,
messages: [{ role: "system", content: docs }, { role: "user", content: message }],
});
const title = await openai.chat.completions.create({
model: "gpt-4o", max_tokens: 20,
messages: [{ role: "user", content: "Title for this chat: " + message }],
});
await saveChat(chatId, answer.choices[0].message.content, title.choices[0].message.content);
return Response.json({ answer: answer.choices[0].message.content });
}Fixed
export async function POST(req: Request) {
const { chatId, message, isFirstMessage } = await req.json();
const emb = await openai.embeddings.create({ model: "text-embedding-3-small", input: message });
const docs = await searchDocs(emb.data[0].embedding);
const answer = await openai.chat.completions.create({
model: "gpt-4o", max_tokens: 800,
messages: [{ role: "system", content: docs }, { role: "user", content: message }],
});
const reply = answer.choices[0].message.content;
// Title once per chat, on a small model.
const title = isFirstMessage
? (await openai.chat.completions.create({
model: "gpt-4o-mini", max_tokens: 20,
messages: [{ role: "user", content: "Title for this chat: " + message }],
})).choices[0].message.content
: undefined;
await saveChat(chatId, reply, title);
return Response.json({ answer: reply });
}How to fix it
List every model call a single user action triggers and ask which ones the user would notice if they disappeared. Remove those that nobody would miss, and make optional ones opt-in.
For the rest: run side tasks such as titles, tags and classification on a small model, do them once per conversation rather than once per message, cache results that do not change, and merge steps into one structured call where the outputs can come back together.
What the audit detects
- Groups LLM call sites by the function that contains them. It fires when a function the parser recognizes as a request handler has 3 or more distinct call sites, or when any other function has 5 or more.
- Text and embedding calls are counted separately, and the report estimates cost per request when the models are known.
- It counts call sites, not executions. Calls in mutually exclusive branches are all counted, so the multiplier is an upper bound. Calls made inside helper functions are counted in those helpers, not in the handler that calls them.