Local AI in practice: thousands of images described without an external AI service
A huge database of images with no keywords and no organization. Searching this illustration archive's collection was barely possible, and describing everything by hand would have taken weeks. So came the question we hear more and more often: can't AI do that?
It could. After half a day of building, it took just a few hours to give the collection keywords, descriptions and the text that appears on the images. The model ran locally, on our own hardware, and not a single image went to an external AI service.
This article is part of our series on local AI models. Those are open models you run yourself, instead of sending your data to a big AI service like the ones from Anthropic or ChatGPT. We show how it works through real (small) projects: what it delivers, what it takes and where the limits are.
What it came down to
The archive keeps its collection in ResourceSpace, a system for managing image files. The images are the archive's most important asset, and they are for internal use. Sending them to a big AI service in the cloud means handing every file to a third party, on terms the archive doesn't set itself.
That was the starting point: AI, yes, but without a single image going to an external AI service. That's why the model ran on our own hardware, on site with us in Germany. The images only traveled from the archive to us and back again, just like the other work we already did for this client.
Concept first
We started with the question of what data we actually needed. That turned out to be three things per image: keywords, a short description and all the text on the image, such as printed captions or handwritten notes. Everything had to land directly in ResourceSpace, so nothing would change in how the users work.
Before anything was written back, 50 results were reviewed in an overview with thumbnails. Based on the archive's feedback, we adjusted the instructions for the model. That brought to light, for example, that artists' names were ending up in the descriptions, something no automated test would have caught.
Then the build
The build itself was a connection between the model and ResourceSpace. It's built on the existing APIs and links the images to our LLM. The result is a small, fixed route for every image:
The image is fetched from ResourceSpace.
First, the model only reads the text on the image, word for word. A model that reads and describes at the same time starts "improving" what it reads.
Then it describes the image: a title, a description and 8 to 15 keywords.
The keywords are matched to the terms the archive already uses, so new variants don't keep piling up.
The result goes back to ResourceSpace, but only into fields that are empty or still contain its own earlier output. Anything a user filled in themselves is kept.
What it delivered
All images now have keywords, and where the fields were empty, a description and the text from the image as well. The scripts took about 1 hour per 1,500 images. Images added later can be processed separately.
The model isn't perfect: sometimes it reads too much into a figure. The result is a solid starting point for the collection managers, and little time lost tagging new images. Over time, the quality improves on its own, based on previously processed images.
What this means for your system
Almost every company has a collection nobody can properly search anymore: product photos, technical drawings, scanned documents, inspection photos. The same approach works there too. The system you already have stays in place, the data doesn't go to an external AI service, and the people who know the collection review the result before anything is saved.
The technical side
Here's a short explanation of the specific setup we used for this project. There are of course different ways to approach this; this one worked well for this project.
Model: Qwen3-VL-30B-A3B, an open-source model served with vLLM.
Hardware: an NVIDIA DGX Spark (128 GB unified memory). The model uses about 45 GB, of which 30 GB are weights, and about 75 GB of disk space. A server GPU with at least 48 GB of memory will also work.
Speed: about 2.5 seconds per image, roughly 1,500 images per hour.
Integration: the ResourceSpace API for fetching previews and writing fields back. The only traffic runs between the tagger and the archive's own server.
Structure: two separate steps (transcription first, then description), structured output, keywords mapped to the existing term list, and a write rule that only overwrites empty fields or its own earlier output.
Lessons from practice: some previews had inverted colors, some originals were very small, and one drawing made the model repeat itself until it hit its limit. Each case needed a small adjustment.
Have a question like this?
Wrestling with a question about running AI locally? Feel free to run it by us. We always start with a concept: what do you need, what is the system allowed to do, and which data has to stay in-house?