{"id":34954,"date":"2026-10-16T05:00:00","date_gmt":"2026-10-16T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=34954"},"modified":"2026-10-15T16:24:13","modified_gmt":"2026-10-15T14:24:13","slug":"interpretable-document-clustering","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/","title":{"rendered":"Interpretable document clustering"},"content":{"rendered":"\n<p>Organizations accumulate documents over the years, often without a consistent structure and in a variety of formats. While modern AI systems (e.g.,\u00a0agentic assistants, RAGs) provide new, powerful ways to speed up human workflows, their output is often bound by the quality of the input data. <\/p>\n\n\n\n<p>After years of growing the archives, their owners not only lose any organized structure, but often don&#8217;t even know what kind of documents they contain. This is a poor starting point for an effective AI transformation: not knowing the data makes planning hard, and the messiness is likely to hurt performance.<\/p>\n\n\n\n<p>This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store. This could be useful on its own or as a first step toward automatically (or semi-automatically) organizing such repositories and enriching them with metadata.<\/p>\n\n\n\n<p>As a proof of concept, we keep the scope narrow and:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>focus on how much structure can be recovered from documents in an unsupervised manner<\/li>\n\n\n\n<li>go beyond text and experiment with representations based on layout and visual form<\/li>\n\n\n\n<li>explore grouping documents in an interpretable way and making the inferred structure easily readable<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Background<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Topic modelling<\/strong><\/h3>\n\n\n\n<p>Finding structure in a text corpus is not a new problem, and has historically been solved with methods based on word statistics.<\/p>\n\n\n\n<p>A classic example is LDA (Latent Dirichlet Allocation): each document is treated as a mixture of topics, and each topic as a distribution over words, inferred from which words tend to appear together. It remains a useful tool today, but it has limitations. It only sees text, so anything carried by layout or visual form is invisible to it. It also focuses on word or phrase counts, so it might miss more complex semantic signals that modern language models are built to retrieve.<\/p>\n\n\n\n<p>Clustering asks a different question. Instead of a mixture of topics per document, it groups similar documents based on a representation that is not limited to bag-of-words.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Embedding based clustering<\/strong><\/h3>\n\n\n\n<p>Modern approaches cluster documents in an embedding space (usually a neural embedding, though TF-IDF can also work), following roughly:<\/p>\n\n\n\n<p><code>embeddings \u2192 dimensionality reduction \u2192 clustering<\/code><\/p>\n\n\n\n<p>A concrete example of this approach applied to text is BERTopic, which uses sentence embeddings \u2192 UMAP \u2192 HDBSCAN, followed by the extraction of topic representations based on word frequency.<\/p>\n\n\n\n<p>We follow a similar general pipeline for the clustering part, but focus on the choice of embeddings.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Beyond text<\/strong><\/h3>\n\n\n\n<p>Documents carry more information than just the text&#8217;s semantics: layout and visual style are valuable signals and may be exactly what one wants to group by. We therefore look at how the choice of embedding shapes the resulting clusters and how it influences which signals surface.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Cluster interpretability<\/strong><\/h3>\n\n\n\n<p>Both LDA and BERTopic describe the resulting clusters (topics) using representative words or phrases. That has its practical uses, but it does not make the clusters easy to interpret or organize. One can read into a word list and guess the theme of a group, but it takes effort, and such representation does not give much to base a structure on. The examples below show what this looks like in practice.<\/p>\n\n\n\n<p>Both examples come from our synthetic corpus (described below under Data).<\/p>\n\n\n\n<p>LDA (3 \/ 6 topics shown):<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613a835a&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613a835a\" class=\"wp-block-image size-full wp-lightbox-container\"><img decoding=\"async\" width=\"505\" height=\"187\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/1-EN.png\" alt=\"top 10 words\" class=\"wp-image-34966\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/1-EN.png 505w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/1-EN-300x111.png 300w\" sizes=\"(max-width: 505px) 100vw, 505px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>BERTopic (3 \/ 30 topics shown)<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613a8cec&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613a8cec\" class=\"wp-block-image size-full wp-lightbox-container\"><img decoding=\"async\" width=\"705\" height=\"205\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/2-EN.png\" alt=\"top 10 words\" class=\"wp-image-34968\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/2-EN.png 705w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/2-EN-300x87.png 300w\" sizes=\"(max-width: 705px) 100vw, 705px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>So, besides comparing embeddings and clustering approaches, we also explore a more readable way to interpret and structure the resulting groups.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Experiments<\/strong><\/h2>\n\n\n\n<p>We start with the clustering itself, and come back to cluster interpretability afterward.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Data<\/strong><\/h3>\n\n\n\n<p><strong>Custom synthetic dataset: <\/strong>To be able to analyze the results with respect to different signals, we generate a synthetic dataset with three predefined, fully crossed axes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>topic<\/strong> (5) \u2013 Cybersecurity, Human Resources, Legal &amp; Compliance, Research &amp; Development, Sales &amp; Customer Relations<\/li>\n\n\n\n<li><strong>document_type<\/strong> (5) \u2013 Report, Email, Invoice, Meeting Minutes, Presentation<\/li>\n\n\n\n<li><strong>style<\/strong> (3) \u2013 three distinct visual templates (fonts, colors, layout conventions)<\/li>\n<\/ul>\n\n\n\n<p>Each combination is passed to an LLM that writes the document as HTML, which we then convert to PDF and PNG. The resulting dataset contains 600 samples (5 \u00d7 5 \u00d7 3, with 8 documents per cell). We would rather use documents from a real corpus, but open datasets with actual documents (not just text) and with labels are hard to find.<\/p>\n\n\n\n<p><strong>RVL-CDIP: <\/strong>To benchmark on real data, we use the RVL-CDIP dataset, which contains historical documents from the tobacco industry. It is a standard dataset for image-based document classification and clustering research. The dataset is labeled by one of 16 document types. The quality of the scans is a bit low, which adds a lot of noise. To limit the computational scope, we used 50 samples for each type, resulting in 800 samples in the dataset.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Data preparation<\/strong><\/h3>\n\n\n\n<p>For RVL, we use Azure Content Understanding for OCR (Optical Character Recognition) to extract text from the images (as .md, but almost no formatting). For the custom dataset, we have PDFs available, so we simply run Docling to extract .md, which might include some layout information.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Which embeddings<\/strong><\/h3>\n\n\n\n<p>We want to explore representations that differ in the kinds of signals they carry, so we pick a few families that sit at various points on the text\/visual spectrum. Text embeddings are computed on the extracted markdown, and image embeddings on the page PNG.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cohere Embed v4 (text, image)<\/strong> \u2013 multimodal document embedding; both modalities land in one shared space, and the image version is trained on documents so it seems to read the text too.<\/li>\n\n\n\n<li><strong>text-embedding-3-small<\/strong> \u2013 general-purpose text embedding, a second opinion on the pure semantic signal.<\/li>\n\n\n\n<li><strong>CLIP, SigLIP<\/strong> \u2013 general vision-language models trained to align images with captions.<\/li>\n\n\n\n<li><strong>DINOv2, DiT<\/strong> \u2013 vision models without language supervision (DiT pretrained on scanned documents).<\/li>\n\n\n\n<li><strong>TF-IDF, pixel: thumbnail<\/strong> \u2013 non-neural baselines: weighted term vectors, and the page as a flattened 32\u00d732 grayscale image (we also tried a couple different pixel-based baselines).<\/li>\n<\/ul>\n\n\n\n<p>The two Cohere modalities share one space, so we experiment with combining them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>image \u2212 text<\/strong> \u2013 a guess worth testing: if both modalities share a space, subtracting the text might cancel the semantics and leave the visual and layout signal.<\/li>\n\n\n\n<li><strong>image + text<\/strong> \u2013 carries both signals in one vector of the same width.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Clustering results<\/strong><\/h3>\n\n\n\n<p>Here we run the specific embedding, reduce dimensionality with PCA (32 components), and use k-means as the clustering algorithm.<\/p>\n\n\n\n<p>For each embedding, we reduce the dimensionality with PCA (32 components) and run the clustering with k-means. This gives a stable setup that lets us explore how well different embedding models work for different axes, without extra noise from the downstream settings. We did try UMAP and HDBSCAN (as in BERTopic), but the results were less stable and not consistently better or worse; we stuck to PCA and k-means to focus the comparison on the representations. HDBSCAN\u2019s ability to set outliers aside makes it an appealing direction (potentially worth further exploration), but it would need more tuning to be reliable.<\/p>\n\n\n\n<p>As baselines, we use BERTopic (on its default MiniLM embeddings) and LDA (both with lightly tuned hyperparameters), and a random partition for reference. We also use TF-IDF and a simple pixel baseline to compare with what a much simpler representation can already do.<\/p>\n\n\n\n<p>The performance is measured against the labels (pre-defined axes in the custom dataset and the label in RVL) in terms of purity, which we define as the fraction that matches the dominant class in each cluster (essentially, how clean the clusters are on average). Purity increases with the number of clusters, so we compare configurations at similar cluster counts, denoted by <em>k<\/em> in the table (BERTopic is the exception, since HDBSCAN chooses <em>k<\/em> itself, but it underperforms on its default embeddings regardless).<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613aa6b4&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613aa6b4\" class=\"wp-block-image size-full wp-lightbox-container\"><img decoding=\"async\" width=\"702\" height=\"540\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/3-EN.png\" alt=\"random partition\" class=\"wp-image-34970\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/3-EN.png 702w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/3-EN-300x231.png 300w\" sizes=\"(max-width: 702px) 100vw, 702px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613aae4b&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613aae4b\" class=\"wp-block-image size-full wp-lightbox-container\"><img decoding=\"async\" width=\"703\" height=\"241\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/4-EN.png\" alt=\"DiT\" class=\"wp-image-34972\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/4-EN.png 703w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/4-EN-300x103.png 300w\" sizes=\"(max-width: 703px) 100vw, 703px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Not surprisingly, the visual embeddings (CLIP, SigLIP, DINOv2, DiT) show better results on style and document type, while text-aware embeddings work well for clustering by topic. For RVL Cohere v4 (image) worked best, and it also got a decent score on the custom document type and topic. This makes sense as it&#8217;s a document-specific embedding and likely can read the text well enough.<\/p>\n\n\n\n<p>Subtracting the Cohere v4 (text) embedding from the Cohere v4 (image) embedding appears to strip away the semantics needed for topical grouping and yields a representation that separates document types almost perfectly on the synthetic dataset. Whether that transfers to other corpora is an open question, but it is a very interesting result nevertheless.<\/p>\n\n\n\n<p>We can also get rid of the semantic signal by downscaling the documents until the text becomes unreadable and then passing to Cohere v4 (image) (the Cohere v4 (image, 128px) row). This does improve clustering by document type and style, but nowhere near as much as the subtraction does. Interesting finding, but probably less useful for practical application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Using more than one embedding<\/strong><\/h2>\n\n\n\n<p>Each embedding recovered one axis well, rarely more than one. Rather than a single clustering, we could cluster twice with different configurations, each targeting a different signal. We experiment with two-level clustering to see whether it allows us to recover multiple axes simultaneously.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Approach<\/strong><\/h3>\n\n\n\n<p>We considered different ideas of how to combine two levels of clustering:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cluster independently with each embedding and take the cross-product of the two assignments<\/li>\n\n\n\n<li>cluster the second embedding separately within each level-1 cluster (we lose themes between clusters, but it might scale well on larger corpora)<\/li>\n\n\n\n<li>subtract each level-1 centroid before the second clustering, removing the first axis without splitting the data.<\/li>\n<\/ul>\n\n\n\n<p>The last worked best in our experiments, so we used it for the results, but the margins were not large enough to draw real conclusions. This could be an interesting angle for further improvement.<\/p>\n\n\n\n<p>A simpler alternative is to concatenate two embeddings and cluster the joint space once.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Results<\/strong><\/h3>\n\n\n\n<p>We run 6 clusters at each level and collapse those that end up too small. We compare the 2-level clustering approach against a flat clustering at a matching cluster number to see what we get when just running flat clustering at comparable settings. We use the following notation to mark these configurations in the table below:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>flat: a single clustering on the given embedding.<\/li>\n\n\n\n<li>concat(A, B): a single clustering on the two embeddings stacked into one wider space.<\/li>\n\n\n\n<li>2lvl: A \u2192 B: two-level clustering, level 1 on A and level 2 on B.<\/li>\n<\/ul>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613ac2aa&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613ac2aa\" class=\"wp-block-image size-large wp-lightbox-container\"><img decoding=\"async\" width=\"1024\" height=\"818\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/5-1-1024x818.png\" alt=\"flat: cohere v4\" class=\"wp-image-34974\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/5-1-1024x818.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/5-1-300x240.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/5-1-768x613.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/5-1.png 1092w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Two-level clustering preserves near-perfect document-type performance, while topic or style performance stays close to what flat clustering achieved (one at a time). This is two usable signals instead of one, at the same total number of groups.<\/p>\n\n\n\n<p>For RVL, the results get worse, which is not surprising. The labels are varied along one axis only, and there are 16 classes, so in this case, the trade-off of a smaller number of groups at each level was too harsh. In that case, the concatenated approach worked best, so joining two levels of the signal remains beneficial here. This suggests that a fixed number of clusters at each level might generalize poorly (e.g.,&nbsp;if the data has a lot of semantic variation but the format is homogenous or vice versa), and exploring methods that can adjust that dynamically (like HDBSCAN or some heuristics) might be crucial to make this approach more universal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Grouping and interpretability<\/strong><\/h2>\n\n\n\n<p>As we saw earlier, neither LDA nor BERTopic gives us any usable labels or descriptions of the clusters.<\/p>\n\n\n\n<p>Instead, we use an LLM-based approach to label the groups. Passing all documents via an LLM could be quite expensive for a large corpus. We select <em>N<\/em> samples (we use <em>N=5<\/em>, but that could be tuned) for each cluster to show to the model for interpretation, which keeps it efficient. For this analysis, we picked those at random, but it could be beneficial to experiment with selecting either the most representative or the widest coverage sample.<\/p>\n\n\n\n<p>We run this in 2 phases:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>INTERPRET \u2013 here we ask the LLM to describe the cluster, give it a few-word label, and decide which characteristics are consistent across all the examples (e.g.,\u00a0domain, document type, etc.)<\/li>\n\n\n\n<li>NORMALIZE\/GROUP \u2013 here we pass all of the resulting interpretations at once and ask the LLM to normalize the wording and group the clusters along shared characteristics<\/li>\n<\/ol>\n\n\n\n<p>This turns a long list of clusters into a smaller set of named, coherent groups, with meaningful axes to structure along.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Results<\/strong><\/h3>\n\n\n\n<p>We present the labeling and grouping results as a tree: the top level is the grouping the LLM proposed along one characteristic, and each nested level is a further grouping along the next one. Below, we show the first few groups from two clustering configurations: one that separates document type and topic, and one that separates document type and style.<\/p>\n\n\n\n<p>The colored bars show, for each group, the two most frequent ground-truth classes. These labels were added afterward purely for analysis to show how the naming behaves for clean groups versus mixed ones. The clustering, labeling, and grouping were done fully unsupervised.<\/p>\n\n\n\n<p><strong>A.<\/strong> Cohere v4 (image \u2212 text) \u2192 Cohere v4 (text) \u2013 grouped by document type (level 1) and domain (level 2)<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613ad420&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613ad420\" class=\"wp-block-image size-large wp-lightbox-container\"><img decoding=\"async\" width=\"1024\" height=\"560\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/6-1024x560.png\" alt=\"grouping by document type and domain\" class=\"wp-image-34942\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/6-1024x560.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/6-300x164.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/6-768x420.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/6.png 1102w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p><strong>B.<\/strong> Cohere v4 (image \u2212 text) \u2192 CLIP \u2014 grouped by document type (level 1) and visual style (level 2)<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ad32613adce3&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ad32613adce3\" class=\"wp-block-image size-large wp-lightbox-container\"><img decoding=\"async\" width=\"1024\" height=\"401\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/7-1024x401.png\" alt=\"grouping by document type and visual style\" class=\"wp-image-34944\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/7-1024x401.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/7-300x118.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/7-768x301.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/7.png 1100w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>We can see that where the clustering worked well, the clusters are neatly named and grouped. The labels get more generic when the clusters are messy, and fewer of them can be grouped successfully. A noticeable share of clusters also ends up ungrouped, since the LLM only groups those that genuinely share a characteristic, but the ones it does group are labeled sensibly.<\/p>\n\n\n\n<p>Imperfect as it is at this stage, such a breakdown gives an immediate, high-level insight into what a given corpus contains. If we were able to estimate which clusters are coherent or mark outliers in each group reliably enough, and then pair it with a human-in-the-loop (or even more powerful LLMs) for review and correction, it could make organizing large repositories of messy documents much easier and faster.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Limitations and further directions<\/strong><\/h2>\n\n\n\n<p>Some things did not fit within the scope (as is expected for a <em>proof-of-concept<\/em>) and should be improved if this project were continued.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Data<\/strong> \u2013 we used single pages for simplicity. The synthetic corpus was useful for isolating different kinds of structure (semantic, visual, layout), but it is not a sound basis for estimating absolute performance. RVL-CDIP is real but low-quality and not representative of a modern corporate archive. A large, real, labeled corpus would be the right benchmark; however, such corpora are hard to obtain.<\/li>\n\n\n\n<li><strong>Evaluation<\/strong> \u2013 the methods are unsupervised, but the ground-truth labels were used during model selection. We tried to avoid reporting configurations that scored well by chance and focused on findings that were consistent across settings, but what worked on this data may not generalize; a stricter protocol (model selection and hyperparameter tuning on held-out data) should be used in future work.<\/li>\n\n\n\n<li><strong>Methods<\/strong> \u2013 there are plenty of directions to explore further, such as tuning the clustering, estimating sample confidence or cluster coherence, or selecting samples for labeling.<\/li>\n<\/ul>\n\n\n<div class=\"nsw-o-blogersii-banner\">\n            <picture>\n            <source srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Banner-AI-Offer-Sample-Desktop.jpg\" media=\"(min-width: 992px)\" >\n            <source srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Banner-AI-Offer-Sample-MOB.jpg\" media=\"(min-width: 300px)\" >            <img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Banner-AI-Offer-Sample-Desktop.jpg\" alt=\"\"  class=\"\"  >\n        <\/picture>\n        <div class=\"cnt\">\n                    <div class=\"nsw-m-title-block -h3 -invert  -has-title-margin-bottom-0 -has-title-font-weight-bold\">\n                                <h2 class=\"nsw-m-title-block__title\" >Artificial Intelligence<\/h2>\n                <\/div>\n                            <p class=\"has-nsw-p-4-font-size has-invert-color\">\n                We deliver AI solutions tailored to your business, driving efficiency and boosting productivity within your teams.\n            <\/p>\n                            <a  href=\"https:\/\/sii.pl\/en\/what-we-offer\/artificial-intelligence\/\" class=\"nsw-a-button -ghost -banner-button\"   >\n        <span>AI offering<\/span>\n    <\/a>\n            <\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusions<\/h2>\n\n\n\n<p>We showed that the choice of embedding decides which kind of signal the clustering picks up. An embedding is not necessarily better or worse in general; it just answers different questions about the same corpus. We also explored ways to combine representations so that clustering can surface more than one kind of structure at once.<\/p>\n\n\n\n<p>In addition to that, we propose a quick way to label and organize the clusters in an interpretable way, resulting in a named, grouped structure that a human can easily read. The approach is also cost-effective as the expensive part (the LLM) scales with the number of groups rather than the number of documents.<\/p>\n\n\n\n<p>The approach could already be useful as a discovery tool, revealing themes and structure in large document corpora. The findings would need further verification to be sure they generalize, and making the method robust enough for semi-automatic organization is still ahead. Still, the experiments show promise in recovering meaningful structure from unorganized documents and presenting it in a form a person can actually read.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Sources<\/strong><\/h2>\n\n\n\n<p><strong>Topic models and clustering methods<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>LDA<\/strong> \u2013 Blei, D. M., Ng, A. Y., Jordan, M. I. (2003). <em>Latent Dirichlet Allocation<\/em>. JMLR 3, 993\u20131022. <a href=\"https:\/\/www.jmlr.org\/papers\/volume3\/blei03a\/blei03a.pdf\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.jmlr.org\/papers\/volume3\/blei03a\/blei03a.pdf<\/a><\/li>\n\n\n\n<li><strong>BERTopic<\/strong> \u2013 Grootendorst, M. (2022). <em>BERTopic: Neural topic modeling with a class-based TF-IDF procedure<\/em>. <a href=\"arXiv:2203.05794.%20https:\/\/arxiv.org\/abs\/2203.05794\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >arXiv:2203.05794. https:\/\/arxiv.org\/abs\/2203.05794<\/a><\/li>\n\n\n\n<li><strong>Embedding-based clustering<\/strong> \u2013 Sia, S., Dalmia, A., Mielke, S. J. (2020). <em>Tired of Topic Models? Clusters of Pretrained Word Embeddings Make for Fast and Good Topics too!<\/em>. EMNLP 2020. <a href=\"arXiv:2004.14914.%20https:\/\/arxiv.org\/abs\/2004.14914\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >arXiv:2004.14914. https:\/\/arxiv.org\/abs\/2004.14914<\/a><\/li>\n\n\n\n<li><strong>UMAP<\/strong> \u2013 McInnes, L., Healy, J., Melville, J. (2018). <em>UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction<\/em>. arXiv:1802.03426. <a href=\"https:\/\/arxiv.org\/abs\/1802.03426\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/1802.03426<\/a><\/li>\n\n\n\n<li><strong>HDBSCAN<\/strong> \u2013 Campello, R. J. G. B., Moulavi, D., Sander, J. (2013). <em>Density-Based Clustering Based on Hierarchical Density Estimates<\/em>. PAKDD 2013, 160\u2013172. <a href=\"https:\/\/link.springer.com\/chapter\/10.1007\/978-3-642-37456-2_14\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/link.springer.com\/chapter\/10.1007\/978-3-642-37456-2_14<\/a><\/li>\n<\/ul>\n\n\n\n<p><strong>Embedding models<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cohere Embed v4<\/strong> (text \/ image, shared embedding space) \u2013 Cohere. <em>Embed documentation<\/em>. <a href=\"https:\/\/docs.cohere.com\/docs\/cohere-embed\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/docs.cohere.com\/docs\/cohere-embed<\/a><\/li>\n\n\n\n<li><strong>text-embedding-3-small<\/strong> \u2013 OpenAI. <em>Embeddings guide<\/em>. <a href=\"https:\/\/platform.openai.com\/docs\/guides\/embeddings\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/platform.openai.com\/docs\/guides\/embeddings<\/a><\/li>\n\n\n\n<li><strong>MiniLM \/ Sentence-BERT<\/strong> (BERTopic\u2019s default embedding) \u2013 Reimers, N., Gurevych, I. (2019). <em>Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks<\/em>. <a href=\"arXiv:1908.10084.%20https:\/\/arxiv.org\/abs\/1908.10084\" rel=\"nofollow\" >arXiv:1908.100<\/a><a href=\"arXiv:1908.10084.%20https:\/\/arxiv.org\/abs\/1908.10084\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >8<\/a><a href=\"arXiv:1908.10084.%20https:\/\/arxiv.org\/abs\/1908.10084\" rel=\"nofollow\" >4. https:\/\/arxiv.org\/abs\/1908.10084<\/a><\/li>\n\n\n\n<li><strong>CLIP<\/strong> \u2013 Radford, A. et al.&nbsp;(2021). <em>Learning Transferable Visual Models From Natural Language Supervision<\/em>. arXiv:2103.00020. <a href=\"https:\/\/arxiv.org\/abs\/2103.00020\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/2103.00020<\/a><\/li>\n\n\n\n<li><strong>SigLIP<\/strong> \u2013 Zhai, X. et al.&nbsp;(2023). <em>Sigmoid Loss for Language Image Pre-Training<\/em>. arXiv:2303.15343. <a href=\"https:\/\/arxiv.org\/abs\/2303.15343\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/2303.15343<\/a><\/li>\n\n\n\n<li><strong>DiT<\/strong> \u2013 Li, J. et al.&nbsp;(2022). <em>DiT: Self-supervised Pre-training for Document Image Transformer<\/em>. <a href=\"arXiv:2203.02378.%20https:\/\/arxiv.org\/abs\/2203.02378\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >arXiv:2203.02378. https:\/\/arxiv.org\/abs\/2203.02378<\/a><\/li>\n\n\n\n<li><strong>DINOv2<\/strong> \u2013 Oquab, M. et al.&nbsp;(2023). <em>DINOv2: Learning Robust Visual Features without Supervision<\/em>. arXiv:2304.07193. <a href=\"https:\/\/arxiv.org\/abs\/2304.07193\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/2304.07193<\/a><\/li>\n<\/ul>\n\n\n\n<p><strong>Data and tooling<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>RVL-CDIP<\/strong> \u2013 Harley, A. W., Ufkes, A., Derpanis, K. G. (2015). <em>Evaluation of Deep Convolutional Nets for Document Image Classification and Retrieval<\/em>. ICDAR 2015, 991\u2013995. <a href=\"https:\/\/arxiv.org\/abs\/1502.07058\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/1502.07058<\/a><\/li>\n\n\n\n<li><strong>Docling<\/strong> (PDF \u2192 markdown extraction) \u2013 Auer, C. et al.&nbsp;(2024). <em>Docling Technical Report<\/em>. arXiv:2408.09869. <a href=\"https:\/\/arxiv.org\/abs\/2408.09869\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/arxiv.org\/abs\/2408.09869<\/a><\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;34954&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;2&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5&quot;,&quot;size&quot;:&quot;30&quot;,&quot;title&quot;:&quot;Interpretable document clustering&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/5&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 24px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Organizations accumulate documents over the years, often without a consistent structure and in a variety of formats. While modern AI &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/\">Continued<\/a><\/p>\n","protected":false},"author":829,"featured_media":34948,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[15356,15077,15040,2892,2198],"class_list":["post-34954","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-document-processing-en","tag-artificial-intelligence-en-2","tag-coreai-en","tag-llm-en","tag-case-study-en"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.9 - aioseo.com -->\n\t<meta name=\"description\" content=\"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Jan Latko\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.9\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"blogersii\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Interpretable document clustering in practice\" \/>\n\t\t<meta property=\"og:description\" content=\"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"733\" \/>\n\t\t<meta property=\"og:image:height\" content=\"456\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-16T03:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-15T14:24:13+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Sii.Polska\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Interpretable document clustering in practice\" \/>\n\t\t<meta name=\"twitter:description\" content=\"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#article\",\"name\":\"Interpretable document clustering in practice\",\"description\":\"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store\",\"inLanguage\":\"en-US\",\"headline\":\"Interpretable document clustering\",\"author\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/author\\\/jlatko\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\"},\"datePublished\":\"2026-10-16T03:00:00+02:00\",\"dateModified\":\"2026-10-15T14:24:13+02:00\",\"articleSection\":\"Hard development, Document processing, Artificial Intelligence, coreAI, LLM, Case Study\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#webpage\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/AI_5.jpg\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#articleImage\",\"width\":733,\"height\":456,\"caption\":\"Interpretowalne klastrowanie dokument\\u00f3w\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/hard-development\\\/#listItem\",\"name\":\"Hard development\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/hard-development\\\/#listItem\",\"position\":2,\"name\":\"Hard development\",\"item\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/hard-development\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#listItem\",\"name\":\"Interpretable document clustering\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#listItem\",\"position\":3,\"name\":\"Interpretable document clustering\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/hard-development\\\/#listItem\",\"name\":\"Hard development\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\",\"name\":\"Sii Polska\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/\",\"sameAs\":[\"https:\\\/\\\/www.instagram.com\\\/siipolska\\\/\",\"https:\\\/\\\/www.tiktok.com\\\/@siipolska\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCQ3UQ7RJPEYnAWC_rPE5Dxg\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/sii-polska\",\"https:\\\/\\\/clutch.co\\\/profile\\\/sii-poland\",\"https:\\\/\\\/www.crunchbase.com\\\/organization\\\/sii\",\"https:\\\/\\\/www.wikidata.org\\\/wiki\\\/Q16601096\"]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#webpage\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/\",\"name\":\"Interpretable document clustering in practice\",\"description\":\"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#breadcrumblist\"},\"author\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/author\\\/jlatko\\\/#author\",\"creator\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/author\\\/jlatko\\\/#author\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/AI_5.jpg\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#mainImage\",\"width\":733,\"height\":456,\"caption\":\"Interpretowalne klastrowanie dokument\\u00f3w\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/interpretable-document-clustering\\\/#mainImage\"},\"datePublished\":\"2026-10-16T03:00:00+02:00\",\"dateModified\":\"2026-10-15T14:24:13+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/en\\\/\",\"name\":\"blogersii\",\"description\":\"Sii\\u2019s tech blog \\u2013 practical knowledge from experts\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Interpretable document clustering in practice","description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","canonical_url":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#article","name":"Interpretable document clustering in practice","description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","inLanguage":"en-US","headline":"Interpretable document clustering","author":{"@id":"https:\/\/sii.pl\/blog\/en\/author\/jlatko\/#author"},"publisher":{"@id":"https:\/\/sii.pl\/#organization"},"datePublished":"2026-10-16T03:00:00+02:00","dateModified":"2026-10-15T14:24:13+02:00","articleSection":"Hard development, Document processing, Artificial Intelligence, coreAI, LLM, Case Study","mainEntityOfPage":{"@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#webpage"},"isPartOf":{"@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#webpage"},"image":{"@type":"ImageObject","url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#articleImage","width":733,"height":456,"caption":"Interpretowalne klastrowanie dokument\u00f3w"}},{"@type":"BreadcrumbList","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/#listItem","position":1,"name":"Home","item":"https:\/\/sii.pl\/blog\/en\/","nextItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/hard-development\/#listItem","name":"Hard development"}},{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/hard-development\/#listItem","position":2,"name":"Hard development","item":"https:\/\/sii.pl\/blog\/en\/hard-development\/","nextItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#listItem","name":"Interpretable document clustering"},"previousItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#listItem","position":3,"name":"Interpretable document clustering","previousItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/en\/hard-development\/#listItem","name":"Hard development"}}]},{"@type":"Organization","@id":"https:\/\/sii.pl\/#organization","name":"Sii Polska","url":"https:\/\/sii.pl\/blog\/en\/","sameAs":["https:\/\/www.instagram.com\/siipolska\/","https:\/\/www.tiktok.com\/@siipolska","https:\/\/www.youtube.com\/channel\/UCQ3UQ7RJPEYnAWC_rPE5Dxg","https:\/\/www.linkedin.com\/company\/sii-polska","https:\/\/clutch.co\/profile\/sii-poland","https:\/\/www.crunchbase.com\/organization\/sii","https:\/\/www.wikidata.org\/wiki\/Q16601096"]},{"@type":"WebPage","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#webpage","url":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/","name":"Interpretable document clustering in practice","description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/sii.pl\/blog\/en\/#website"},"breadcrumb":{"@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#breadcrumblist"},"author":"https:\/\/sii.pl\/blog\/en\/author\/jlatko\/#author","creator":"https:\/\/sii.pl\/blog\/en\/author\/jlatko\/#author","image":{"@type":"ImageObject","url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg","@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#mainImage","width":733,"height":456,"caption":"Interpretowalne klastrowanie dokument\u00f3w"},"primaryImageOfPage":{"@id":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/#mainImage"},"datePublished":"2026-10-16T03:00:00+02:00","dateModified":"2026-10-15T14:24:13+02:00"},{"@type":"WebSite","@id":"https:\/\/sii.pl\/blog\/en\/#website","url":"https:\/\/sii.pl\/blog\/en\/","name":"blogersii","description":"Sii\u2019s tech blog \u2013 practical knowledge from experts","inLanguage":"en-US","publisher":{"@id":"https:\/\/sii.pl\/#organization"}}]},"og:locale":"en_US","og:site_name":"blogersii","og:type":"article","og:title":"Interpretable document clustering in practice","og:description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","og:url":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/","og:image":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg","og:image:secure_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg","og:image:width":733,"og:image:height":456,"article:published_time":"2026-10-16T03:00:00+00:00","article:modified_time":"2026-10-15T14:24:13+00:00","article:publisher":"https:\/\/www.facebook.com\/Sii.Polska","twitter:card":"summary","twitter:title":"Interpretable document clustering in practice","twitter:description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","twitter:image":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg"},"aioseo_meta_data":{"post_id":"34954","title":"Interpretable document clustering in practice","description":"This project investigates a lightweight approach to discovering the kinds of data a given corpus contains and to finding structure in a messy document store","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"created":"2026-10-12 08:43:13","updated":"2026-10-16 04:43:49","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/sii.pl\/blog\/en\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/sii.pl\/blog\/en\/hard-development\/\" title=\"Hard development\">Hard development<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tInterpretable document clustering\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/sii.pl\/blog\/en\/"},{"label":"Hard development","link":"https:\/\/sii.pl\/blog\/en\/hard-development\/"},{"label":"Interpretable document clustering","link":"https:\/\/sii.pl\/blog\/en\/interpretable-document-clustering\/"}],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/10\/AI_5.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/34954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/829"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=34954"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/34954\/revisions"}],"predecessor-version":[{"id":34978,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/34954\/revisions\/34978"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/34948"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=34954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=34954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=34954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}