A powerful NestJS-based API for extracting structured data from documents and images using DeepSeek-OCR. Automatically detects document types (invoices, receipts, forms, tables) and returns structured JSON schemas.
sudo apt-get install poppler-utilsbrew install popplergit clone <repository-url>
cd deekseek
npm install
# or
yarn install
cp .env.example .env
Edit .env file with your configuration (see Configuration section).
If using local model inference, you'll need to set up the Python environment:
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install PyTorch (CUDA 11.8)
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu118
# Install transformers and dependencies
pip install transformers accelerate sentencepiece protobuf
# Install DeepSeek-OCR dependencies
pip install flash-attn --no-build-isolation
Edit the .env file in the root directory:
# Application
NODE_ENV=development
PORT=3000
# OCR Configuration
OCR_MODE=local
# Options: 'local' (use local model) or 'api' (use DeepSeek API service)
# DeepSeek API Configuration (required when OCR_MODE=api)
DEEPSEEK_API_KEY=your_api_key_here
DEEPSEEK_API_URL=https://api.deepseek.com/ocr
# File Upload Configuration
MAX_FILE_SIZE_MB=10
ALLOWED_FILE_TYPES=jpg,jpeg,png,pdf
# Storage Configuration
TEMP_DIR=./temp
# Python Configuration (required when OCR_MODE=local)
PYTHON_PATH=python3
DEEPSEEK_MODEL_PATH=deepseek-ai/DeepSeek-OCR
npm run start:dev
# or
yarn start:dev
# Build the application
npm run build
# Start production server
npm run start:prod
docker build -t deepseek-ocr-api .
docker run -p 3000:3000 --env-file .env deepseek-ocr-api
The API will be available at:
http://localhost:3000http://localhost:3000/api/docshttp://localhost:3000/api/docs-jsonPOST /ocr/extract
Upload a single image or PDF to extract structured data.
Query Parameters:
documentType (optional): Hint about document type (invoice, receipt, form, table)Request:
curl -X POST http://localhost:3000/ocr/extract \
-F "file=@/path/to/document.pdf"
Response:
{
"filename": "invoice.pdf",
"documentType": "invoice",
"confidence": 0.92,
"schema": {
"vendor": "Acme Corporation",
"invoiceNumber": "INV-2024-001",
"date": "2024-01-15",
"items": [
{
"description": "Product A",
"quantity": 2,
"unitPrice": 50.0,
"total": 100.0
}
],
"subtotal": 100.0,
"tax": 10.0,
"total": 110.0,
"currency": "USD"
},
"rawText": "..."
}
POST /ocr/extract/batch
Upload multiple files for batch processing.
Request:
curl -X POST http://localhost:3000/ocr/extract/batch \
-F "files=@/path/to/doc1.pdf" \
-F "files=@/path/to/doc2.jpg"
Response:
{
"results": [
{ "filename": "doc1.pdf", "documentType": "invoice", "schema": {...} },
{ "filename": "doc2.jpg", "documentType": "receipt", "schema": {...} }
],
"totalProcessed": 2,
"successful": 2,
"failed": 0
}
GET /ocr/health
Check service status and model availability.
Response:
{
"status": "ok",
"ocrMode": "local",
"modelAvailable": true,
"timestamp": "2024-01-15T10:30:00.000Z"
}
GET /ocr/supported-formats
Get information about supported formats and example schemas.
Response:
{
"supportedFileTypes": ["jpg", "jpeg", "png", "pdf"],
"supportedDocumentTypes": ["invoice", "receipt", "form", "table"],
"maxFileSizeMB": 10,
"exampleSchemas": {...}
}
A complete Postman collection is available in the /postman directory with:
Quick Start:
postman/DeepSeek-OCR-API.postman_collection.json into Postmanpostman/Local.postman_environment.json for local testingSee postman/README.md for detailed instructions.
// Single file upload
async function extractDocument(file: File) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('http://localhost:3000/ocr/extract', {
method: 'POST',
body: formData,
});
const result = await response.json();
console.log(result);
}
// With document type hint
async function extractInvoice(file: File) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('http://localhost:3000/ocr/extract?documentType=invoice', {
method: 'POST',
body: formData,
});
return await response.json();
}
import requests
# Single file upload
def extract_document(file_path):
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post('http://localhost:3000/ocr/extract', files=files)
return response.json()
# Batch upload
def extract_multiple(file_paths):
files = [('files', open(path, 'rb')) for path in file_paths]
response = requests.post('http://localhost:3000/ocr/extract/batch', files=files)
return response.json()
# Extract from image
curl -X POST http://localhost:3000/ocr/extract \
-F "file=@receipt.jpg"
# Extract from PDF with type hint
curl -X POST "http://localhost:3000/ocr/extract?documentType=invoice" \
-F "file=@invoice.pdf"
# Batch processing
curl -X POST http://localhost:3000/ocr/extract/batch \
-F "files=@doc1.pdf" \
-F "files=@doc2.jpg" \
-F "files=@doc3.png"
# Health check
curl http://localhost:3000/ocr/health
# Get supported formats
curl http://localhost:3000/ocr/supported-formats
Extracts vendor information, line items, totals, tax, and dates.
Schema:
{
vendor: string;
invoiceNumber?: string;
date?: string;
dueDate?: string;
items: Array<{
description: string;
quantity?: number;
unitPrice?: number;
total?: number;
}>;
subtotal?: number;
tax?: number;
total: number;
currency?: string;
}
Extracts merchant, transaction details, and purchased items.
Schema:
{
merchant: string;
date?: string;
items: Array<{
name: string;
quantity?: number;
price?: number;
}>;
total: number;
transactionId?: string;
paymentMethod?: string;
}
Extracts field-value pairs from forms.
Schema:
{
fields: Record<string, string>;
}
Extracts structured table data with headers and rows.
Schema:
{
headers: string[];
rows: string[][];
}
deekseek/
โโโ src/
โ โโโ main.ts # Application entry point
โ โโโ app.module.ts # Root module
โ โโโ common/ # Shared utilities
โ โ โโโ filters/
โ โ โโโ interceptors/
โ โโโ config/ # Configuration
โ โโโ ocr/ # OCR module
โ โ โโโ ocr.controller.ts
โ โ โโโ ocr.service.ts
โ โ โโโ providers/ # Local & API providers
โ โ โโโ dto/ # Data transfer objects
โ โ โโโ interfaces/
โ โโโ document/ # Document processing
โ โ โโโ services/
โ โโโ storage/ # File storage
โโโ test/ # Tests
โโโ package.json
โโโ tsconfig.json
# Development
npm run start:dev
# Build
npm run build
# Production
npm run start:prod
# Tests
npm run test
npm run test:watch
npm run test:cov
# Linting
npm run lint
This project has comprehensive unit test coverage with 87.67% code coverage and 77 passing tests.
| Metric | Coverage | Status |
|---|---|---|
| Statements | 87.67% | โ |
| Branches | 72.72% | โ |
| Functions | 77.63% | โ |
| Lines | 87.45% | โ |
See TEST_COVERAGE.md for detailed coverage report.
# Run all unit tests
npm run test
# Run tests with coverage report
npm run test:cov
# Run tests in watch mode
npm run test:watch
# Run specific test file
npm test -- ocr.controller.spec
ocr.controller.spec.ts - Controller endpoint testsocr.service.spec.ts - Business logic testsstorage.service.spec.ts - File storage testsdocument-detector.service.spec.ts - Document type detection testspdf-processor.service.spec.ts - PDF processing testsschema-extractor.service.spec.ts - Schema extraction testshttp-exception.filter.spec.ts - Error handling testslogging.interceptor.spec.ts - Logging testsTotal: 77 tests across 8 test suites
After running npm run test:cov, view the HTML coverage report:
open coverage/lcov-report/index.html
PDF conversion fails
Python model not loading
API rate limits
File upload errors
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and questions, please open an issue on GitHub.
TypeScript
95.2%
Python
2.4%
JavaScript
1.3%
Dockerfile
1.1%
A powerful NestJS-based API for extracting structured data from documents and images using DeepSeek-OCR. Automatically detects document types (invoices, receipts, forms, tables) and returns structured JSON schemas.
sudo apt-get install poppler-utilsbrew install popplergit clone <repository-url>
cd deekseek
npm install
# or
yarn install
cp .env.example .env
Edit .env file with your configuration (see Configuration section).
If using local model inference, you'll need to set up the Python environment:
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install PyTorch (CUDA 11.8)
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu118
# Install transformers and dependencies
pip install transformers accelerate sentencepiece protobuf
# Install DeepSeek-OCR dependencies
pip install flash-attn --no-build-isolation
Edit the .env file in the root directory:
# Application
NODE_ENV=development
PORT=3000
# OCR Configuration
OCR_MODE=local
# Options: 'local' (use local model) or 'api' (use DeepSeek API service)
# DeepSeek API Configuration (required when OCR_MODE=api)
DEEPSEEK_API_KEY=your_api_key_here
DEEPSEEK_API_URL=https://api.deepseek.com/ocr
# File Upload Configuration
MAX_FILE_SIZE_MB=10
ALLOWED_FILE_TYPES=jpg,jpeg,png,pdf
# Storage Configuration
TEMP_DIR=./temp
# Python Configuration (required when OCR_MODE=local)
PYTHON_PATH=python3
DEEPSEEK_MODEL_PATH=deepseek-ai/DeepSeek-OCR
npm run start:dev
# or
yarn start:dev
# Build the application
npm run build
# Start production server
npm run start:prod
docker build -t deepseek-ocr-api .
docker run -p 3000:3000 --env-file .env deepseek-ocr-api
The API will be available at:
http://localhost:3000http://localhost:3000/api/docshttp://localhost:3000/api/docs-jsonPOST /ocr/extract
Upload a single image or PDF to extract structured data.
Query Parameters:
documentType (optional): Hint about document type (invoice, receipt, form, table)Request:
curl -X POST http://localhost:3000/ocr/extract \
-F "file=@/path/to/document.pdf"
Response:
{
"filename": "invoice.pdf",
"documentType": "invoice",
"confidence": 0.92,
"schema": {
"vendor": "Acme Corporation",
"invoiceNumber": "INV-2024-001",
"date": "2024-01-15",
"items": [
{
"description": "Product A",
"quantity": 2,
"unitPrice": 50.0,
"total": 100.0
}
],
"subtotal": 100.0,
"tax": 10.0,
"total": 110.0,
"currency": "USD"
},
"rawText": "..."
}
POST /ocr/extract/batch
Upload multiple files for batch processing.
Request:
curl -X POST http://localhost:3000/ocr/extract/batch \
-F "files=@/path/to/doc1.pdf" \
-F "files=@/path/to/doc2.jpg"
Response:
{
"results": [
{ "filename": "doc1.pdf", "documentType": "invoice", "schema": {...} },
{ "filename": "doc2.jpg", "documentType": "receipt", "schema": {...} }
],
"totalProcessed": 2,
"successful": 2,
"failed": 0
}
GET /ocr/health
Check service status and model availability.
Response:
{
"status": "ok",
"ocrMode": "local",
"modelAvailable": true,
"timestamp": "2024-01-15T10:30:00.000Z"
}
GET /ocr/supported-formats
Get information about supported formats and example schemas.
Response:
{
"supportedFileTypes": ["jpg", "jpeg", "png", "pdf"],
"supportedDocumentTypes": ["invoice", "receipt", "form", "table"],
"maxFileSizeMB": 10,
"exampleSchemas": {...}
}
A complete Postman collection is available in the /postman directory with:
Quick Start:
postman/DeepSeek-OCR-API.postman_collection.json into Postmanpostman/Local.postman_environment.json for local testingSee postman/README.md for detailed instructions.
// Single file upload
async function extractDocument(file: File) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('http://localhost:3000/ocr/extract', {
method: 'POST',
body: formData,
});
const result = await response.json();
console.log(result);
}
// With document type hint
async function extractInvoice(file: File) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('http://localhost:3000/ocr/extract?documentType=invoice', {
method: 'POST',
body: formData,
});
return await response.json();
}
import requests
# Single file upload
def extract_document(file_path):
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post('http://localhost:3000/ocr/extract', files=files)
return response.json()
# Batch upload
def extract_multiple(file_paths):
files = [('files', open(path, 'rb')) for path in file_paths]
response = requests.post('http://localhost:3000/ocr/extract/batch', files=files)
return response.json()
# Extract from image
curl -X POST http://localhost:3000/ocr/extract \
-F "file=@receipt.jpg"
# Extract from PDF with type hint
curl -X POST "http://localhost:3000/ocr/extract?documentType=invoice" \
-F "file=@invoice.pdf"
# Batch processing
curl -X POST http://localhost:3000/ocr/extract/batch \
-F "files=@doc1.pdf" \
-F "files=@doc2.jpg" \
-F "files=@doc3.png"
# Health check
curl http://localhost:3000/ocr/health
# Get supported formats
curl http://localhost:3000/ocr/supported-formats
Extracts vendor information, line items, totals, tax, and dates.
Schema:
{
vendor: string;
invoiceNumber?: string;
date?: string;
dueDate?: string;
items: Array<{
description: string;
quantity?: number;
unitPrice?: number;
total?: number;
}>;
subtotal?: number;
tax?: number;
total: number;
currency?: string;
}
Extracts merchant, transaction details, and purchased items.
Schema:
{
merchant: string;
date?: string;
items: Array<{
name: string;
quantity?: number;
price?: number;
}>;
total: number;
transactionId?: string;
paymentMethod?: string;
}
Extracts field-value pairs from forms.
Schema:
{
fields: Record<string, string>;
}
Extracts structured table data with headers and rows.
Schema:
{
headers: string[];
rows: string[][];
}
deekseek/
โโโ src/
โ โโโ main.ts # Application entry point
โ โโโ app.module.ts # Root module
โ โโโ common/ # Shared utilities
โ โ โโโ filters/
โ โ โโโ interceptors/
โ โโโ config/ # Configuration
โ โโโ ocr/ # OCR module
โ โ โโโ ocr.controller.ts
โ โ โโโ ocr.service.ts
โ โ โโโ providers/ # Local & API providers
โ โ โโโ dto/ # Data transfer objects
โ โ โโโ interfaces/
โ โโโ document/ # Document processing
โ โ โโโ services/
โ โโโ storage/ # File storage
โโโ test/ # Tests
โโโ package.json
โโโ tsconfig.json
# Development
npm run start:dev
# Build
npm run build
# Production
npm run start:prod
# Tests
npm run test
npm run test:watch
npm run test:cov
# Linting
npm run lint
This project has comprehensive unit test coverage with 87.67% code coverage and 77 passing tests.
| Metric | Coverage | Status |
|---|---|---|
| Statements | 87.67% | โ |
| Branches | 72.72% | โ |
| Functions | 77.63% | โ |
| Lines | 87.45% | โ |
See TEST_COVERAGE.md for detailed coverage report.
# Run all unit tests
npm run test
# Run tests with coverage report
npm run test:cov
# Run tests in watch mode
npm run test:watch
# Run specific test file
npm test -- ocr.controller.spec
ocr.controller.spec.ts - Controller endpoint testsocr.service.spec.ts - Business logic testsstorage.service.spec.ts - File storage testsdocument-detector.service.spec.ts - Document type detection testspdf-processor.service.spec.ts - PDF processing testsschema-extractor.service.spec.ts - Schema extraction testshttp-exception.filter.spec.ts - Error handling testslogging.interceptor.spec.ts - Logging testsTotal: 77 tests across 8 test suites
After running npm run test:cov, view the HTML coverage report:
open coverage/lcov-report/index.html
PDF conversion fails
Python model not loading
API rate limits
File upload errors
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and questions, please open an issue on GitHub.
TypeScript
95.2%
Python
2.4%
JavaScript
1.3%
Dockerfile
1.1%