The core idea

Extraction accuracy is only half the task. To assemble a document automatically, we also need to decide where each fact belongs and which original terms must be preserved.

While working on business proposal imports in KPNova, we encountered a revealing bug. The system correctly identified the amount before discount, the discount itself and the final total. Yet the finished PDF showed them twice: first in a neatly formatted totals block, then in a paragraph copied from the source document.

At first glance, this looks like deduplication. In fact, it raised a more fundamental question: which representation is responsible for each fact in the final document?

Correct numbers, wrong result

Document import has several stages. First, it extracts information: products, prices, company details, deadlines and payment terms. Then it turns that information into editable fields and blocks in a business proposal.

At the same time, the system preserves some original wording. This is necessary: not every meaningful detail fits a table or a predefined field. A single paragraph may contain the final amount, a tax qualification and a payment term.

That is how the duplicate appeared. The financial figures were already in the totals block, but the paragraph remained intact because it contained an important condition: “VAT included.”

The system preserved all the information, yet produced a poor user experience. Checking only for data loss is therefore not enough: we also need to check how the information is presented.

Why we cannot simply delete the duplicate

Simple string comparison is useless here. The same amount may be written in different ways, and identical numbers may refer to different items. Deleting a paragraph because it contains a known amount risks losing an additional condition.

The opposite approach is no better: preserve all the source text “just in case” while also constructing a structured document. Duplicates then become inevitable, and the user cannot tell which totals to trust.

We therefore had to separate two tasks: preserving the meaning of the source and choosing where to display an extracted fact. They are related, but they are not the same.

One rule for every representation

The solution was a shared representation plan for financial data. It identifies the information already covered by the totals block, the repeated text that can be removed and the conditions that must be preserved separately.

Several parts of the system use this plan: preview, proposal creation and transfer completeness checks. This matters because, if each part independently decides which text to keep, inconsistencies return after an edit or when the document is reopened.

Validation and generation share one decision about how each fact is represented.

Meanwhile, the original files and data provenance remain unchanged. The system corrects the interpretation rather than rewriting the source. This lets us return to the original and explain where a particular value came from.

Where automation must stop

For example, “5% VAT is included in the price” does not mean we should add another 5% to the calculated total. It is a separate financial condition. We can reflect it in the totals block and remove the repeated paragraph only if every other detail in that paragraph has also been accounted for.

When documents contradict each other, the currency is unknown, the rate is ambiguous or data is missing, automatic text deletion is unacceptable. The right result is to ask the user a question rather than choose a plausible answer.

The same rule applies to unit prices: a repetition can be removed only when the structured field conveys the same price, unit of measure and necessary qualifications. Matching a number alone is insufficient.

What the checks showed

The fix was checked against a real set of documents and images, followed by PDF generation. The result contained one totals block without the repeated financial paragraph; payment terms, warranty and the tax qualification were preserved. The tested set passed the completeness check without detected omissions, and the generated pages were compared visually as well as by text.

This confirms the fix for that specific scenario. It does not mean every document will be recognized perfectly. Extraction errors, conflicting sources and incomplete data remain separate problems that need their own checks and a path to manual resolution.

What this means in practice

The central mistake was not that the AI misread the document. It extracted the required information, but different parts of the system independently decided how to use it. Each part appeared reasonable on its own, while the final document was wrong.

Automated document processing ends with a single, accurate and verifiable representation of the facts, not with extraction.

In systems like this, I would start with an explicit rule rather than another prompt saying “do not duplicate amounts”: which block owns a fact, which source conditions it covers and what remains in the text. Avoiding duplicates and avoiding information loss then become two checks of the same decision, instead of competing heuristics.

Have a question about this topic?Discuss on Telegram