AI
AI-Powered Document Classification: Complete Guide for 2025
I built a classifier to stop hand-sorting invoices and contracts. Here’s the setup, code, and what failed along the way.
Written by
Convert Magic Team
Published
Reading time
12 min
I built a classifier to stop hand-sorting invoices and contracts. Here’s the setup, code, and what failed along the way.

AI-Powered Document Classification: Complete Guide for 2025
Three of us were spending an hour a day moving invoices, contracts, and receipts into the right folders. After one mislabeled contract delayed a client payment, I built a small classifier to do the sorting for us. This is the exact setup that worked (and the places I tripped up).
How I tested
- Dataset: 1,200 invoices, 800 contracts, 500 receipts, 300 support emails (all anonymized); 80/10/10 train/val/test split
- Labels:
invoice,contract,receipt,support_email- Hardware: 2021 M1 MacBook Pro; Python 3.11; scikit-learn 1.4
- Goal: >92% macro F1 on the test set, minimal false positives on contracts
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
docs = [...] # list of document texts
labels = [...] # matching labels
train_x, test_x, train_y, test_y = train_test_split(
docs, labels, test_size=0.2, random_state=42, stratify=labels
)
model = Pipeline([
("tfidf", TfidfVectorizer(
max_features=50000,
ngram_range=(1, 2), # unigrams + bigrams
min_df=2
)),
("clf", LogisticRegression(max_iter=200, class_weight="balanced"))
])
model.fit(train_x, train_y)
preds = model.predict(test_x)
print(classification_report(test_y, preds))
contains("governing law")) improved precision; alternatively, set a higher threshold for the contract class.Try our free, browser-based conversion tools. Lightning-fast, secure, and no registration required.
Browse All Tools