Sitemap

GLM-5.3-Flash and the Work That Comes After an AI Answer

10 min readOct 30, 2026

--

Three tasks showed where this multimodal model was useful — and where a convincing response still fell short of a finished result.

GLM-5.3-Flash is part of Zhipu’s GLM model family. Z.ai’s documentation introduces Flash and FlashX as native multimodal models, with an emphasis on visual coding, office work, and documents. That puts the model in an interesting position: it can help interpret material as well as produce text and code, but those abilities do not all have the same finish line.

This article was written with AI assistance. The findings come from recorded API requests and separate checks of the returned data, reasoning, and code.

I tested glm-5.3-flash on October 30, 2026, through Crazyrouter: a registration table supplied as an image, a conditional-probability problem, and a small expense-splitting webpage. The first two gave correct results in their single attempts. The webpage needed another request before the code was complete, and its interface has not been tested in a real browser.

The unfinished webpage was the most useful reminder of what a model introduction needs to explain. A list of supported tasks tells you where to start. It does not tell you when to stop checking.

What GLM-5.3-Flash actually returns

“Multimodal” describes the kinds of material a model can work with. It is not a promise that every response will arrive as a finished file or working application.

Crop from a screenshot of BigModel’s official Flash/FlashX page. The original Chinese cards list multiple input types on the left and text output on the right. This test used text and one PNG image; it did not test every listed input type.

Text output can contain an explanation, a table, or an entire HTML document. Turning that document into a tool still requires saving it, running it, and checking what happens when someone uses it. The distinction matters even if you never intend to write code yourself: generated code can be the beginning of a useful tool without being the end of the job.

The model names also need care. The GLM-5.3 documentation lists text input and output; Flash has its own multimodal description. FlashX is a separate model, not another name for the version tested here. I did not test FlashX or measure any speed advantage between them.

The expense splitter returned successfully. The HTML was unfinished.

The webpage request sounded small: one offline HTML file for splitting shared expenses. People should be able to add, rename, and remove participants, choose who shares each expense, edit or delete entries, and reset the page.

I also specified the arithmetic. Amounts had to be handled in integer minor units, with any remainder assigned in display order. Splitting 100.00 among three people should produce 33.34, 33.33, and 33.33. Splitting 0.01 should produce 0.01, 0, and 0. A page that looks balanced but loses a minor unit does not satisfy that requirement.

The first response had HTTP status 200. It had plenty of content, too. But it stopped partway through the expense-handling code, with finish_reason: "length".

That was a failed attempt at producing a complete file. The API had returned a response; the requested artifact was missing its ending.

The output allowance was 32,000 tokens. According to the response’s usage fields, that count included 25,707 reasoning tokens. It was not 32,000 tokens of final HTML. Looking only at the visible code would therefore have given an incomplete picture of where the allowance went.

I kept the prompt and system message unchanged and raised the allowance to 48,000 tokens. The second request returned complete HTML and ended with stop. I did not finish the file by hand or edit the model's code before checking it.

The complete script passed a syntax check. I then executed its unchanged calculation and validation functions in Node.js. All 40 checks passed, including one check covering 132 combinations of amounts and participant counts. Those combinations tested conservation of the total, the order of remainder allocation, and a maximum difference of one minor unit between shares. Other checks covered selected participants, invalid amounts, and rejecting removal of the only participant assigned to an expense.

The interface remains a separate question. There was no real-browser verification of layout, button clicks, editing, or resetting. A correct function does not establish that every control passes the right data to it.

The result is specific: the second output was complete, its script was syntactically valid, and its tested calculation logic passed. It is not evidence that the whole application has been accepted for use. Nor does a successful second generation prove that increasing the limit will fix every truncated response.

A table was a better fit for a result I could inspect

The image task had a much clearer boundary. I created a synthetic registration table containing 12 records. Some IDs appeared more than once because their status had changed. The rule was to keep the latest record for each ID, exclude cancellations from active registrations, and account separately for payments and refunds.

Press enter or click to view image in full size

The actual test input, retained in its original Simplified Chinese. The columns are registration ID, category, amount due, paid, refunded, status, and update time. These are fictional records and amounts, expressed in yuan. This is a test fixture, not a screenshot of real customer data.

I sent the PNG as a Base64 Data URL in an image_url content block, together with the rules. I did not send the reference answer.

The model returned nine latest records. Their fields matched the source image, and all ten aggregate statistics matched the independent reference. There were seven active registrations, 720 due, 580 collected net, and 140 outstanding. The cancelled records had 200 paid and 80 refunded.

More interesting than the totals were two exceptions. A004 had been cancelled but had no recorded refund. A006 had paid only part of the amount due. The model flagged both, while also saying that the image did not provide cancellation reasons or a refund policy.

Get rhythm’s stories in your inbox

Join Medium for free to get updates from this writer.

That last distinction matters. A missing refund entry is something to investigate. It is not, by itself, proof that the amount should have been refunded. The model kept the observed record separate from the business rule it could not know.

For a person reviewing the result, the list of retained records is valuable. A summary alone can hide where an error entered the process. A row-by-row answer lets you ask whether a mismatch came from reading the image, selecting the wrong update, or applying the wrong rule.

This was one clear, purpose-made image. It does not establish performance on blurred scans, phone photographs, multiple pages, or complicated merged cells. The checks are evidence about this task, not a general accuracy percentage.

The probability answer had a second route to verification

The reasoning task used two boxes. A contained four red balls and two blue balls; B contained two red and four blue. The chance of choosing A was one-third, and B two-thirds. After selecting a box, three balls were drawn without replacement. Given that at least one of the first two was red, what was the chance that the third was red? What was the updated probability that A had been chosen?

GLM-5.3-Flash returned 13/32 and 7/16, respectively. Its derivation matched the independent solution. It accounted for the unequal probabilities of choosing the boxes and did not treat draws without replacement as independent events.

There was another way to check. Before the call, I had prepared an independent enumeration of the ordered draws, treating each ball as a distinct physical object: 120 possible sequences per box. I then ran the separate JavaScript enumeration program supplied in the model’s answer. It used exact fractions with BigInt and returned the same two results.

That gave me agreement among the derivation, the model’s executed code, and an independently prepared reference. It is stronger evidence than matching a final number alone. It remains one problem and one request; it does not establish a general mathematics success rate.

The conditions behind those observations

These were three independent tasks and four API requests, all made on October 30, 2026, to https://api.crazyrouter.com/v1/chat/completions, using glm-5.3-flash.

The prompts were in Simplified Chinese. The image and probability tasks each received one request, with output limits of 16,000 and 24,000 tokens. The webpage used 32,000 in its first attempt and 48,000 in its second. The second webpage request is recorded separately, not folded into a headline success rate.

All requests used stream: false. I did not explicitly set temperature, top_p, or reasoning_effort; those followed the service's default behavior. No external tools were configured for the model. The code execution described above happened separately after the responses arrived.

Those details also limit what I can conclude. This was not a comparison of providers, a speed benchmark, an English-language evaluation, or a test of long-term reliability.

A small first call you can check

The official BigModel or Z.ai APIs are valid ways to access the model. Use the key, service address, and parameters supplied by the service you choose. A key created for one provider cannot simply be paired with another provider’s address.

The example below uses Crazyrouter because that is where the recorded tests ran. Its chat-model directory is a broader listing, not a dedicated Flash page; the exact model identifier for this example is glm-5.3-flash.

You need Node.js 22 or later and two local files. After installing Node.js, run node --version in a terminal to confirm it is available. In the Crazyrouter console's API token section, create a key and, if you restrict its models, include glm-5.3-flash. Save only your own key in api-key.txt. Keep that file out of screenshots and public repositories.

Save the following as glm-flash-english.cjs beside the key file. It uses an English example of the probability problem, not the original Chinese prompt. I checked the script locally, but did not make a new live model call with this English wording. The measured results above belong to the original requests.

'use strict';
const fs = require('node:fs');
const path = require('node:path');
​
async function main() {
const key = fs.readFileSync(path.join(__dirname, 'api-key.txt'), 'utf8').trim();
if (!key || /\s/.test(key)) throw new Error('Invalid key file');
const request = {
model: 'glm-5.3-flash',
messages: [
{
role: 'system',
content: 'State your assumptions, show your calculations, and distinguish missing information from facts. Do not claim to have run code.'
},
{
role: 'user',
content: 'Box A contains 4 red balls and 2 blue balls. Box B contains 2 red balls and 4 blue balls. Choose A with probability 1/3 or B with probability 2/3, then draw 3 balls without replacement from that same box. Given that at least one of the first two balls is red, find the probability that the third ball is red and the posterior probability that box A was chosen. Give exact fractions and explain the reasoning. Include a Node.js program that checks the answers by enumerating ordered draws of distinct physical balls, not by random simulation.'
}
],
max_tokens: 24000,
stream: false
};
const response = await fetch('https://api.crazyrouter.com/v1/chat/completions', {
method: 'POST',
redirect: 'error',
signal: AbortSignal.timeout(720000),
headers: { Authorization: 'Bearer ' + key, 'Content-Type': 'application/json' },
body: JSON.stringify(request)
});
if (!response.ok) {
console.error('Request failed. HTTP status: ' + response.status);
process.exitCode = 1;
return;
}
const data = await response.json();
const choice = data.choices?.[0];
const redact = value => String(value).split(key).join('[redacted]');
console.log('Finish reason: ' + redact(choice?.finish_reason || 'not provided'));
const answer = choice?.message?.content;
if (typeof answer !== 'string' || !answer.trim()) {
console.error('No non-empty answer was returned. Check the output limit and supported parameters.');
process.exitCode = 1;
return;
}
console.log(redact(answer));
}
main().catch(() => {
console.error('Request not completed. Check the local file, connection, and configuration. Sensitive error details are omitted.');
process.exitCode = 1;
});

Open a terminal in that folder and run:

node glm-flash-english.cjs

On Windows, typing powershell in the folder's address bar and pressing Enter opens a terminal there. Check that the script has not been saved with an extra .txt extension.

Running the command sends a real API request. The script waits for the complete response and prints its finish reason and text; it does not execute any code in the answer. The exact mathematical reference values are 13/32 and 7/16, but a new model response still needs checking.

If you receive length, inspect the answer for truncation. If you receive HTTP 401, check that the key is valid and belongs to Crazyrouter. A missing-file error calls for checking the filenames and folder. Avoid repeatedly resending an unchanged failing request.

For a client that asks for an OpenAI-compatible Base URL, use https://api.crazyrouter.com/v1. The script itself uses the full endpoint ending in /chat/completions. The API documentation index is the reference for other request formats. This example sends text; image input requires an image_url content block.

Where I would start using GLM-5.3-Flash

The most promising first task is one with an inspectable answer: a list you can compare against its source, a calculation with an independent solution, or a small function with explicit rules. In those settings, the model can do useful work while leaving you a practical way to judge it.

The expense splitter asks for more. Its computation passed the checks, but the final step is still to operate the page. Until that happens, the honest description is a complete code artifact with tested calculation logic — not a fully verified tool.

That is how I would read the model’s broad feature list: as a set of things worth trying, followed by a different verification step for each kind of result.

Sources: the official model documentation linked above; API responses and independent checks recorded on October 30, 2026. Figure captions distinguish the official screenshot from the synthetic test input.

--

--