Engineering drawing search with AI: what Kuken built and how to build your own

On this page
Kuken Industries, a Japanese maker of cooling towers and ventilation equipment, has made more than 70 years of engineering drawings searchable with AI. Engineers type a drawing or part number, or upload an image or PDF of a drawing or a parts list. The system reads the numbers, proposes matching drawing pages with previews, and the engineer decides by checking the original. During the trial, Kuken says, a search took 4.5 minutes on average instead of tens of minutes to half a day.
Kuken has not published the model, the architecture or the cost, so we built the pattern ourselves: a vision model reads the title blocks, Postgres searches normalized numbers, full text and visual similarity, and a second model call compares the candidates. We tested it on 134 pages, including 60 real scans from 1909. This post walks through the Kuken case, the building blocks of a drawing search, our prototype with code and measurements, and the places where it breaks.
What Kuken built
Kuken Industries (空研工業) is based in Fukuoka, was founded in 1956 and, according to its press release, has 572 employees. It builds air-conditioning and ventilation equipment for large buildings, shopping centers and factories and holds one of the largest shares of Japan's cooling-tower market.
The problem will sound familiar to any equipment maker with a long history. When a cooling tower needs a replacement part, parts made today do not always fit older towers, and without the original drawing the part may have to be designed again from scratch. A search by model or part name often returns several drawings, because Kuken has adapted its equipment to individual customers for decades, so the design depends on the customer and the installation date. When the archive was on paper, a search could take half a day. Even after digitization, engineers had to know which name or number to look up and where the file was. Newer engineers asked experienced colleagues.
Kuken built the system with Recursive, a Tokyo AI firm and official OpenAI partner, on the OpenAI API. According to OpenAI, the two companies tested several models on a range of drawings to see how accurately, and at what cost, each could extract the details.
The workflow in the web app, as described by OpenAI and the press release:
- The engineer enters a drawing or part number, or uploads an image or PDF of a drawing or parts list. A screenshot of a parts list saves typing in each number.
- The AI extracts the part numbers and structures them.
- The search returns exact matches plus candidates that allow for different revision numbers, sub-numbers (枝番) and similar spellings.
- The app shows the matching drawing pages with previews, including drawings of similar designs.
- The engineer checks the tower's specifications and past replacement records and decides.
The press release puts the principle in one sentence: the AI supports searching and comparing, and the engineer checks the original and makes the final call.
A second feature is still a prototype: a drawing check. Per the press release, it compares the internal factory order notice with the outline drawing and the delivery specification, shows the differences and where they are, and also runs drawing-specific checks such as missing mandatory notes or balloons. It explicitly does not catch every handwritten note or layout error, and the engineer has the final say.
The results Kuken reports
All figures come from Kuken and have not been independently verified:
| Metric | Value | Type of figure | Source |
|---|---|---|---|
| Search time in the trial (Fukuoka plant) | 4.5 minutes on average, previously tens of minutes to an hour, sometimes half a day | measured in the trial | press release, MONOist |
| Search hours per year | about 90 % fewer | projection based on actual figures for fiscal 2025 | OpenAI, MONOist |
| Drawing check | about 90 % of the issues the AI flagged were genuine discrepancies | prototype test | OpenAI |
The 90 % for the drawing check is precision: nine out of ten flagged issues were real. How many issues the tool missed is not reported. OpenAI adds that experienced engineers spend some of the saved time mentoring newer colleagues, and that reviewing drawings in the app cuts printing. According to the press release, Kuken aims to roll the system out fully at its Fukuoka and Chiba plants by the end of the year.
Kuken has not disclosed the model, the architecture, the cost, the size of the archive or how the times were measured. Everything this post says about the technology from here on comes from our own prototype, not from Kuken.
The building blocks of a drawing search
An engineering drawing is mostly graphics. Searchable text sits almost entirely in the title block and the parts list, and that is exactly where the numbers engineers search for are printed. That leads to a pipeline with four stages:
How an AI drawing search works: prepare, read, search, decide
- Prepare: scans and PDFs become images, blueprints (white lines on a dark background) are inverted, skewed scans are straightened. The title block in the lower right is also saved as a separate crop.
- Read: a vision model reads drawing number, revision, title, material, date and the parts list into a fixed schema. A local OCR engine reads the title block independently, and mismatches get flagged.
- Search: the exact number, in normalized form, comes first. After that, several ranked lists are merged: fuzzy matching on the numbers, full-text search over titles and OCR text and, when an image was uploaded, visual similarity.
- Decide: the engineer sees previews and, on request, an AI comparison per candidate, checks the original and confirms or rejects. Those decisions can later improve the ranking.
The order has a reason. Numbers are precise and cheap to search, so they carry the search. Visual similarity helps when there is no number, for example with a photo taken on site. And because drawings in one product family often differ only in their dimensions, a person makes the final call.
Our prototype and the test data
To measure whether a search works, you need drawings whose correct answer you know. We used two datasets:
- 74 generated drawings from a fictional manufacturer: six kinds of parts
(flange, cover, shaft, bushing, bracket, valve body), five sizes each and
one to four revisions, with a title block, a revision table and German
material designations. Older sheets print the number in the old format
KT 2041/03, newer ones asKT-2041-03, and 60 of the 74 sheets are aged to look like old scans (noise, ink loss, skew, JPEG). On top of that come five parts lists with 40 lines in messy notation and 30 photographed crops taken at an angle. - 60 real scans from the US National Archives: engine drawings of the destroyer USS Preston from around 1909, in the public domain, with valves, pumps, turbine parts and printed parts lists on the sheet.
Generated A3 drawing of a flange with title block and revision table
Real drawing from 1909: standard composition valve of the USS Preston, inverted (source: National Archives)
The prototype uses a handful of components, all in Python 3.13, tested on November 11, 2026:
| Component | Tool | Version |
|---|---|---|
| Reading title blocks | OpenAI gpt-6.1-terra via the Responses API | openai 3.49.0, pydantic 2.14.3 |
| OCR cross-check | RapidOCR with PP-OCRv6 on onnxruntime | 3.10.0 / 1.31.1 |
| Database and search | PostgreSQL with pg_trgm and pgvector | 17.11 / 1.6 / 0.8.0 |
| Image vectors | facebook/dinov2-base on CPU | transformers 5.22.2, torch 2.15.0+cpu |
| Image preparation | PyMuPDF, Pillow, OpenCV | 2.1 / 13.0.0 / 5.0.0.93 |
| UI | FastAPI with a single Jinja page | 0.162.4 |
One installation note: pip install torch pulls the CUDA build from PyPI,
several gigabytes of it. For a CPU-only server, install torch from the index
https://download.pytorch.org/whl/cpu.
Reading title blocks with a vision model
The model gets two images per page: the whole sheet at high resolution
(detail: "high") and the lower-right crop at original resolution
(detail: "original"). The whole sheet provides context, such as a parts
list in the top right corner. The crop keeps small digits in the title block
from getting lost when the sheet is scaled down.
The answer is bound to a Pydantic schema. That guarantees valid JSON with
fixed fields and turns "not on the sheet" into null instead of an invented
value:
The call itself is short. responses.parse returns a DrawingMeta object
directly, and setting reasoning to low keeps it fast and cheap:
The prompt asks the model to copy numbers character by character as printed
and to mark unreadable characters with ?. Normalization happens later in
code, not in the model. For an aged sheet from 1973, this came back:
On the 74 generated sheets, the model got number, revision, title, material and date right every time, aged or not. Plain OCR with a regular expression also found number and revision on all 74 sheets. Mostly that tells you our generated title blocks were too clean: printed lettering, always the same layout. The real scans were a lot harder.
Each page used 4,904 input and 305 output tokens on average. At the list
prices for gpt-6.1-terra (1 US dollar per million input tokens, 5 US
dollars per million output tokens), that is about 0.6 cents per page. By
that arithmetic, 100,000 pages cost about 640 US dollars, and half that with
the Batch API according to the price list. The median call took 4.4 seconds.
The OCR cross-check
A vision model does not read perfectly, and its errors look plausible. So a second, completely different technique reads the same title block: the local OCR engine RapidOCR. If the number the model read does not roughly appear in the OCR text, the page gets flagged:
Use partial_ratio, not a plain comparison. On the old sheets the number is
usually preceded by "Dr." or "Dr. No.", and OCR reads that as part of the
number (DR.NO.62-553-69). With a plain comparison we first flagged 30 of
the 60 real scans, almost all of them wrongly. With the substring comparison,
four flags remained. Two were real misreads by the model, and two were
fractions like "1½" that OCR reads as "12".
When the model misreads the title block
The 1909 scans showed an error that will happen in any archive that grew over decades. Our prompt said the revision sits in the "Index" or "Rev" field, as it does on German drawings. The New York Shipbuilding Company sheets, however, have a box in the lower right labeled "INDEX / GROUP / FILE NUMBER", which is a filing reference:
Title block of a 1909 drawing with drawing number N-583L-1½ and the filing box INDEX 24 (source: National Archives)
The model followed our prompt and returned the filing number as the revision:
The fix is one sentence per title-block layout, appended to the prompt for pages from that collection:
| Prompt | Pages | Revision wrongly filled | OCR confirms the number | Parts list found |
|---|---|---|---|---|
| generic | 60 | 27 (45 %) | 57 (95 %) | 50 (83 %) |
| with layout hint | 60 | 0 | 56 (93 %) | 50 (83 %) |
The hint removed the revision error completely, but it also introduced a new
one: 62-534-4 became 62-534-A, probably because of the sentence about
trailing letters. The OCR cross-check flagged exactly that page. Two other
misreads stayed in both versions: 62-553-7 read as 62-333-7 (flagged by
the cross-check) and 62-584-6 read as G2-584-6. OCR made the second
mistake too, so it was not flagged, but the normalization in the next section
absorbs it.
Two practical rules follow. First, give every title-block layout in your
archive a short description, and test any change to it on a sample before
you re-read the whole archive. Second, put flagged pages on a review list for
a person during ingestion. A misread number makes a drawing impossible to
find: in our test, the correct search for 62-553-7 did not return the
affected sheet in the top three, because the index said 62-333-7.
Normalizing drawing numbers and fuzzy matching
Kuken names revisions, sub-numbers and spelling variants explicitly as the
reason a plain search falls short. The same number shows up in many forms:
KT-2041-03, KT 2041/03, KT204103, kt-2041-3 or with the letter O
instead of a zero. The prototype therefore stores two keys next to the
printed number:
Both functions run on both sides, at ingestion and at search time. Turning
real letters into digits (G2 becomes 62) is intended: as long as it
happens symmetrically, the search still finds the drawing. Before that, the
search splits off the revision when it can recognize one (Rev. B,
Ind. C, -B) and sorts the matching revision to the top, otherwise the
newest.
For everything that does not match exactly, Postgres uses the pg_trgm
extension: it splits strings into three-character groups and finds similar
numbers through a GIN index. The schema, shortened:
The drawing_parts table holds the parts-list rows the model found on the
sheets (334 rows on 50 of the 60 old scans). That way a part number also
finds a drawing where the part only appears in the parts list.
To see how much normalization buys, we searched for all 30 parts in seven notations each. We counted whether the right part was in first place (Hit@1) or in the top three (Hit@3). For the notation with a revision, the revision has to match as well.
| Query notation | String equals | Normalized equals | Hit@1 without zero key | Hit@1 | Hit@3 |
|---|---|---|---|---|---|
KT-2041-03 (new format) | 67 % | 100 % | 100 % | 100 % | 100 % |
KT 2041/03 (old format) | 53 % | 100 % | 100 % | 100 % | 100 % |
KT204103 | 0 % | 100 % | 100 % | 100 % | 100 % |
kt-2041-3 | 0 % | 0 % | 20 % | 100 % | 100 % |
KT-2O41-03 (O for 0) | 0 % | 100 % | 100 % | 100 % | 100 % |
KT-2041-03 Rev. B | 0 % | 100 % | 100 % | 100 % | 100 % |
KT-2401-03 (transposed digits) | 0 % | 0 % | 50 % | 50 % | 70 % |
Plain string matching finds only two thirds even with the correct notation,
because older sheets carry the old format. The key without leading zeros
takes kt-2041-3 from 20 to 100 %. Transposed digits stay hard: for
KT-2401-03, trigram search does put the intended KT-2041-03 in first and
second place (both revisions), but right behind it comes a cover numbered
KT 2014/01. That is why the UI shows several candidates for fuzzy matches
rather than a single answer. On 134 pages, the search itself took a median
of one millisecond.
Search for kt-2041-3: the exact matches KT-2041-03 in revisions B and A come first, followed by similar numbers with their ranks
Exact matches first, then rank fusion
How do you merge an exact number search, a fuzzy search, full text and visual
similarity into one list? The scores of the individual searches are not
comparable: a trigram similarity of 0.6 and a cosine distance of 0.2 have
nothing to do with each other. Reciprocal Rank Fusion (RRF) sidesteps that
and only uses ranks. Each list gives a candidate 1 / (60 + rank) points,
and the points add up, the same approach as the
pgvector hybrid search example.
The prototype puts exact matches in front:
Each result carries its rank from every list (trgm #2, fts #3,
vector #1), and the UI shows them. That helps adoption: an engineer sees at
a glance whether a candidate ranks high because of its number or only because
it looks similar. For hybrid search in a managed service, see our post on
RAG with Azure AI Search.
Uploading parts lists instead of typing
Kuken's engineers upload screenshots of parts lists instead of typing every number. The prototype does this with a second schema: the model decides whether the image is a drawing, a parts list or something else, and returns every line of a parts list. Each line's number then goes through the same search.
Uploaded parts list with numbers in different notations: KT 5032/01, KT201402, kt-5032-1, KT-6120-03 Ind. A
We tested five parts lists with 40 lines in total, two of them aged:
| Check | Result |
|---|---|
| Recognized as a parts list | 5 of 5 |
| Lines found | 40 of 40 |
| Number copied exactly as printed | 37 of 40 |
| Right drawing in first place (33 lines in the archive) | 30 of 33 |
| Right drawing in the top three | 31 of 33 |
| False exact match for parts not in the archive (7 lines) | 0 of 7 |
In the three numbers that were not copied exactly, the model silently "corrected" the letter O to a zero, although the prompt says otherwise. The correction happened to be right here, but do not count on it: normalize on both sides anyway. The three misses in first place were transposed digits. For standard parts that are not in the archive at all, the search never reported an exact match, only similar candidates.
Result of an uploaded parts list: the top three candidates per line, exact matches marked
We cover pulling structured data out of PDFs and Office files with language models in more detail in LLM document extraction.
Searching by visual similarity
Sometimes there is no number: a photo of a part on a printout, a crop without a title block. For those cases the prototype computes an image vector for every page with DINOv2, an openly available image model from Meta (Apache-2.0), and stores it in pgvector. Two preprocessing steps are meant to help: the frame and the title block are painted white, so the identical form template does not dominate the vector, and the image is cropped to the line work, so a photo and a full sheet end up at a similar scale.
The image is first padded onto a white 448-pixel square. do_center_crop=False
matters: the DINOv2 processor's default cuts out the center and would throw
away half of a landscape drawing. On CPU, one vector took 0.83 seconds.
As queries we used 30 photographed crops of the views without the title block, taken at an angle, searched against all 134 pages:
Query image for visual search: angled photo of a flange drawing without the title block
| Archive vector | Same part in first place | Same part in the top three |
|---|---|---|
| whole sheet | 20 % | 43 % |
| frame and title block painted out | 30 % | 43 % |
| painted out and cropped to the line work | 27 % | 43 % |
The reason is simple: five flanges differ only in diameter, hole count and thickness, and a general image model sees "a flange" in all five. It did get the kind of part right: in 26 of 30 cases (87 %), the first result was the right kind. On the real scans, where sheets differ a lot, visual search found the source sheet in first place for 12 of 15 rotated, blurred crops covering 55 % of a sheet, and in the top three for 14.
Visual similarity is a good entry point ("show me bushings like this one") and helps spot duplicates, but it does not replace the number. That fits Kuken, whose search, according to the press release, is built on part numbers. If you want to tell size variants apart by image, you need more than a general-purpose vector, for example extracted main dimensions as a filter.
Search results across the 1909 scans, with flags for OCR mismatch and partly illegible sheets
The AI check as a second opinion
The last component follows Kuken's principle: the AI compares, the person
decides. At the click of a button, the prototype sends the query and the
candidate sheet to the model and gets a fixed result back: same_part with
yes, no or uncertain, a list of concrete differences and the evidence
on the drawing. The prompt only allows "yes" when the number family and, if
requested, the revision match and nothing visible contradicts the query.
We ran this for 14 parts-list lines and their top three candidates each, 42 comparisons in total:
| Candidate per test data | Model says "yes" | "uncertain" | "no" |
|---|---|---|---|
| wrong part (16) | 0 | 0 | 16 |
| right part (26) | 13 | 4 | 9 |
The model never said "yes" to a wrong part. Most of the "no" answers for right parts had a good reason. Three times the number in the parts list had transposed digits, and the model rightly objected. Six times it found real contradictions on our drawings: the title reads "Haltewinkel 120x120" while the dimensions say 120 by 100 millimeters, or a shaft was lengthened in a revision without the title being updated. That was a bug in our generator, but exactly the kind of mistake that happens on real drawings. The four "uncertain" answers concerned numbers with the letter O, which the model reported as a possible transcription error.
AI check of a candidate: same number, but the title contradicts the dimensions
This matches what Kuken reports for its own drawing check: the flags are mostly justified. Whether a contradiction matters in a given case is for the engineer to judge. That is why every candidate in the UI has "Confirm" and "Reject" buttons, and the decisions go into their own table.
What the prototype shows and what it does not
The prototype shows that the pattern can be rebuilt from standard components in about 600 lines of Python, and that number search with proper normalization is very reliable. All test runs together cost 1.55 US dollars for 245 model calls, 196 of them for reading pages.
It does not show how well the approach works on your archive. 134 pages is small. With 100,000 pages there are many more similar numbers, and Hit@1 is likely to drop. Our generated title blocks were too clean to really test the model and OCR. The 1909 scans had no answer key, so we checked the disagreements between model and OCR by hand against the images. We did not test handwritten changes, folded sheets, multi-sheet drawing sets or CAD formats. Our test can neither confirm nor refute Kuken's time savings.
For your own project, the measurements suggest this order:
- Take a sample of 200 to 500 pages from every era and title-block layout and record the correct numbers by hand. Without that answer key, you cannot measure anything.
- Write a description for every layout and test the extraction on the sample, with an OCR cross-check and a review list for flagged pages.
- Derive the normalization rules from the notations that actually occur in your parts lists, your ERP system and your email.
- Only then add visual similarity and the AI check, and collect the engineers' confirmations to improve the ranking.
If you want to make a technical archive searchable this way and need help scoping it or building a prototype, get in touch.
Sources and image credits
- OpenAI: Kuken Industries searches 70 years of drawings in minutes and the Japanese version
- Recursive and Kuken: press release of November 4, 2026 (Japanese)
- MONOist: report of November 6, 2026 (Japanese)
- OpenAI: Recursive partner page
- OpenAI: gpt-6.1-terra model page
- pgvector-python: hybrid search example with RRF
- Meta: DINOv2 on Hugging Face
- Drawings from 1909: U.S. National Archives, Record Group 19, Alphabetical Series of Ship Engineering Drawings, USS Preston (DD-19), public domain. Inverted and scaled down for display.
- All other drawings, parts lists and screenshots: our own.
Interested in building high-quality AI agent systems?
We prepared a comprehensive guide based on cutting-edge research for how to build robust, reliable AI agent systems that actually work in production. This guide covers:
- Understanding the 14 systematic failure modes in multi-agent systems
- Evidence-based best practices for agent design
- Structured communication protocols and verification mechanisms



