Document Question Answering
Transformers
PyTorch
English
document-processing
ocr
ner
text-classification
information-extraction
invoice
receipt
form
Instructions to use mrrobot2610/IDP-Machine-learning with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use mrrobot2610/IDP-Machine-learning with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("document-question-answering", model="mrrobot2610/IDP-Machine-learning")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("mrrobot2610/IDP-Machine-learning", device_map="auto") - Notebooks
- Google Colab
- Kaggle
|
Download nextjs_integration_guide.md from mrrobot2610/IDP-Machine-learning: direct link, hf CLI and curl.
- Browser
- Download file 11.7 kB
-
https://huggingface.co/mrrobot2610/IDP-Machine-learning/resolve/main/nextjs_integration_guide.md
- Command line
-
hf download hf://mrrobot2610/IDP-Machine-learning/nextjs_integration_guide.md
-
curl -L -o nextjs_integration_guide.md https://huggingface.co/mrrobot2610/IDP-Machine-learning/resolve/main/nextjs_integration_guide.md
11.7 kB
| # Next.js Integration Guide | |
| Guide for integrating the IDP API with your Next.js frontend hosted on Vercel. | |
| ## Overview | |
| The IDP API provides a RESTful interface for document processing. Your Next.js app will: | |
| 1. Allow users to upload documents (PDF/images) | |
| 2. Send files to the API via POST request | |
| 3. Display extracted document data with confidence scores | |
| 4. Handle loading states and errors | |
| ## API Endpoints | |
| ### Base URL | |
| ``` | |
| https://YOUR_USERNAME-idp-api.hf.space | |
| ``` | |
| Replace `YOUR_USERNAME-idp-api` with your actual Space name. | |
| ### Endpoints | |
| #### GET /health | |
| Health check endpoint. | |
| **Response:** | |
| ```json | |
| { | |
| "status": "ok", | |
| "models_loaded": true, | |
| "version": "1.0.0" | |
| } | |
| ``` | |
| #### POST /process | |
| Process a document and extract structured data. | |
| **Request:** | |
| - Method: `POST` | |
| - Content-Type: `multipart/form-data` | |
| - Body: `file` (PDF or image file) | |
| - Optional params: | |
| - `adaptive_threshold`: boolean (default: false) | |
| - `page_number`: number (for PDFs, process specific page) | |
| **Response:** | |
| ```typescript | |
| { | |
| file_type: "image" | "pdf"; | |
| total_pages: number; | |
| processed_pages: number; | |
| filename: string; | |
| file_size_kb: number; | |
| pages: Array<{ | |
| document_type: "INVOICE" | "RECEIPT" | "FORM" | "OTHER"; | |
| classification_confidence: number; | |
| classification_probabilities: { | |
| INVOICE: number; | |
| RECEIPT: number; | |
| FORM: number; | |
| OTHER: number; | |
| }; | |
| fields: { | |
| [key: string]: { | |
| value: string; | |
| confidence: number; | |
| bbox?: [number, number, number, number]; | |
| source: "ner" | "regex"; | |
| normalized?: boolean; | |
| currency?: string; | |
| numeric_value?: number; | |
| }; | |
| }; | |
| processing_time: { | |
| preprocessing: number; | |
| ocr: number; | |
| classification: number; | |
| ner: number; | |
| postprocessing: number; | |
| total: number; | |
| }; | |
| raw_ocr_text: string; | |
| page_number?: number; | |
| }>; | |
| } | |
| ``` | |
| ## Implementation | |
| ### 1. Create TypeScript Types | |
| Create `types/idp.ts`: | |
| ```typescript | |
| export interface IDPField { | |
| value: string; | |
| confidence: number; | |
| bbox?: [number, number, number, number]; | |
| source: "ner" | "regex"; | |
| normalized?: boolean; | |
| currency?: string; | |
| numeric_value?: number; | |
| } | |
| export interface IDPPage { | |
| document_type: "INVOICE" | "RECEIPT" | "FORM" | "OTHER"; | |
| classification_confidence: number; | |
| classification_probabilities: { | |
| INVOICE: number; | |
| RECEIPT: number; | |
| FORM: number; | |
| OTHER: number; | |
| }; | |
| fields: Record<string, IDPField>; | |
| processing_time: { | |
| preprocessing: number; | |
| ocr: number; | |
| classification: number; | |
| ner: number; | |
| postprocessing: number; | |
| total: number; | |
| }; | |
| raw_ocr_text: string; | |
| page_number?: number; | |
| } | |
| export interface IDPResponse { | |
| file_type: "image" | "pdf"; | |
| total_pages: number; | |
| processed_pages: number; | |
| filename: string; | |
| file_size_kb: number; | |
| pages: IDPPage[]; | |
| } | |
| export interface HealthResponse { | |
| status: string; | |
| models_loaded: boolean; | |
| version: string; | |
| } | |
| ``` | |
| ### 2. Create API Client | |
| Create `lib/idp-api.ts`: | |
| ```typescript | |
| const API_BASE_URL = process.env.NEXT_PUBLIC_IDP_API_URL || | |
| 'https://YOUR_USERNAME-idp-api.hf.space'; | |
| export class IDPAPIError extends Error { | |
| constructor( | |
| message: string, | |
| public statusCode?: number, | |
| public details?: any | |
| ) { | |
| super(message); | |
| this.name = 'IDPAPIError'; | |
| } | |
| } | |
| export async function checkHealth(): Promise<HealthResponse> { | |
| try { | |
| const response = await fetch(`${API_BASE_URL}/health`); | |
| if (!response.ok) { | |
| throw new IDPAPIError( | |
| 'Health check failed', | |
| response.status | |
| ); | |
| } | |
| return await response.json(); | |
| } catch (error) { | |
| if (error instanceof IDPAPIError) throw error; | |
| throw new IDPAPIError('Network error: ' + (error as Error).message); | |
| } | |
| } | |
| export async function processDocument( | |
| file: File, | |
| options?: { | |
| adaptiveThreshold?: boolean; | |
| pageNumber?: number; | |
| onProgress?: (progress: number) => void; | |
| } | |
| ): Promise<IDPResponse> { | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| if (options?.adaptiveThreshold !== undefined) { | |
| formData.append('adaptive_threshold', String(options.adaptiveThreshold)); | |
| } | |
| if (options?.pageNumber !== undefined) { | |
| formData.append('page_number', String(options.pageNumber)); | |
| } | |
| try { | |
| const response = await fetch(`${API_BASE_URL}/process`, { | |
| method: 'POST', | |
| body: formData, | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json().catch(() => ({})); | |
| throw new IDPAPIError( | |
| error.detail || 'Document processing failed', | |
| response.status, | |
| error | |
| ); | |
| } | |
| return await response.json(); | |
| } catch (error) { | |
| if (error instanceof IDPAPIError) throw error; | |
| throw new IDPAPIError('Network error: ' + (error as Error).message); | |
| } | |
| } | |
| ``` | |
| ### 3. Create Document Upload Component | |
| Create `components/DocumentUpload.tsx`: | |
| ```typescript | |
| 'use client'; | |
| import { useState, useCallback } from 'react'; | |
| import { processDocument, IDPResponse, IDPAPIError } from '@/lib/idp-api'; | |
| export default function DocumentUpload() { | |
| const [file, setFile] = useState<File | null>(null); | |
| const [loading, setLoading] = useState(false); | |
| const [result, setResult] = useState<IDPResponse | null>(null); | |
| const [error, setError] = useState<string | null>(null); | |
| const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { | |
| const selectedFile = e.target.files?.[0]; | |
| if (selectedFile) { | |
| setFile(selectedFile); | |
| setResult(null); | |
| setError(null); | |
| } | |
| }; | |
| const handleUpload = useCallback(async () => { | |
| if (!file) return; | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const response = await processDocument(file); | |
| setResult(response); | |
| } catch (err) { | |
| if (err instanceof IDPAPIError) { | |
| setError(err.message); | |
| } else { | |
| setError('An unexpected error occurred'); | |
| } | |
| } finally { | |
| setLoading(false); | |
| } | |
| }, [file]); | |
| return ( | |
| <div className="max-w-4xl mx-auto p-6"> | |
| <h1 className="text-3xl font-bold mb-6">Document Processing</h1> | |
| {/* File Upload */} | |
| <div className="mb-6"> | |
| <label className="block mb-2 font-medium"> | |
| Upload Document (PDF or Image) | |
| </label> | |
| <input | |
| type="file" | |
| accept=".pdf,.png,.jpg,.jpeg" | |
| onChange={handleFileChange} | |
| className="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer" | |
| /> | |
| </div> | |
| {/* Upload Button */} | |
| <button | |
| onClick={handleUpload} | |
| disabled={!file || loading} | |
| className="px-6 py-2 bg-blue-600 text-white rounded-lg disabled:bg-gray-400 disabled:cursor-not-allowed" | |
| > | |
| {loading ? 'Processing...' : 'Process Document'} | |
| </button> | |
| {/* Error Display */} | |
| {error && ( | |
| <div className="mt-6 p-4 bg-red-50 border border-red-200 rounded-lg"> | |
| <p className="text-red-800">{error}</p> | |
| </div> | |
| )} | |
| {/* Results Display */} | |
| {result && ( | |
| <div className="mt-6 space-y-4"> | |
| <h2 className="text-2xl font-semibold">Results</h2> | |
| {result.pages.map((page, idx) => ( | |
| <div key={idx} className="border rounded-lg p-4"> | |
| <div className="mb-4"> | |
| <span className="font-medium">Document Type:</span>{' '} | |
| <span className="px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm"> | |
| {page.document_type} | |
| </span> | |
| <span className="ml-3 text-sm text-gray-600"> | |
| Confidence: {(page.classification_confidence * 100).toFixed(1)}% | |
| </span> | |
| </div> | |
| <h3 className="font-semibold mb-2">Extracted Fields:</h3> | |
| <div className="space-y-2"> | |
| {Object.entries(page.fields).map(([key, field]) => ( | |
| <div key={key} className="flex justify-between p-2 bg-gray-50 rounded"> | |
| <span className="font-medium capitalize"> | |
| {key.replace(/_/g, ' ')}: | |
| </span> | |
| <div className="text-right"> | |
| <div>{field.value}</div> | |
| <div className="text-xs text-gray-500"> | |
| Confidence: {(field.confidence * 100).toFixed(1)}% | |
| </div> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| <div className="mt-4 text-sm text-gray-600"> | |
| Processing time: {page.processing_time.total.toFixed(2)}s | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |
| ``` | |
| ### 4. Environment Variables | |
| Create `.env.local`: | |
| ```env | |
| NEXT_PUBLIC_IDP_API_URL=https://YOUR_USERNAME-idp-api.hf.space | |
| ``` | |
| ### 5. Add to Your Page | |
| In `app/page.tsx`: | |
| ```typescript | |
| import DocumentUpload from '@/components/DocumentUpload'; | |
| export default function Home() { | |
| return ( | |
| <main> | |
| <DocumentUpload /> | |
| </main> | |
| ); | |
| } | |
| ``` | |
| ## Advanced Features | |
| ### Health Check on Mount | |
| ```typescript | |
| useEffect(() => { | |
| checkHealth() | |
| .then(health => { | |
| if (!health.models_loaded) { | |
| setWarning('API is starting up, please wait...'); | |
| } | |
| }) | |
| .catch(() => setError('API is unavailable')); | |
| }, []); | |
| ``` | |
| ### File Preview | |
| ```typescript | |
| const [preview, setPreview] = useState<string | null>(null); | |
| useEffect(() => { | |
| if (file && file.type.startsWith('image/')) { | |
| const url = URL.createObjectURL(file); | |
| setPreview(url); | |
| return () => URL.revokeObjectURL(url); | |
| } | |
| }, [file]); | |
| ``` | |
| ### Progress Indicator | |
| ```typescript | |
| const [progress, setProgress] = useState(0); | |
| await processDocument(file, { | |
| onProgress: (p) => setProgress(p) | |
| }); | |
| ``` | |
| ## Deployment to Vercel | |
| 1. Push your Next.js code to GitHub | |
| 2. Go to [Vercel](https://vercel.com) | |
| 3. Import your repository | |
| 4. Add environment variable: | |
| - `NEXT_PUBLIC_IDP_API_URL`: Your HF Space URL | |
| 5. Deploy | |
| ## Error Handling | |
| Common errors and solutions: | |
| | Error | Cause | Solution | | |
| |-------|-------|----------| | |
| | CORS error | API not allowing origin | Check CORS config in `api_server.py` | | |
| | 503 Service Unavailable | Models not loaded | Wait for API to finish starting | | |
| | 413 Payload Too Large | File > 10MB | Compress file or increase limit | | |
| | 400 Unsupported file type | Wrong file format | Check file extension | | |
| ## Performance Tips | |
| - **Debounce uploads**: Prevent rapid re-uploads | |
| - **Show progress**: Use loading states for better UX | |
| - **Validate files**: Check size/type before uploading | |
| - **Cache results**: Store processed documents if re-processing same file | |
| - **Error boundaries**: Wrap component in error boundary | |
| ## Example: Full Featured Component | |
| See `components/AdvancedDocumentUpload.tsx` in the example repository for a production-ready component with: | |
| - Drag & drop support | |
| - File preview | |
| - Progress tracking | |
| - Error handling | |
| - Result visualization | |
| - Download processed JSON | |
| ## Support | |
| For integration issues: | |
| - Check browser console for errors | |
| - Test API directly with `curl` first | |
| - Verify CORS configuration | |
| - Check network tab in DevTools | |