Text Generation
Transformers
English
phi3
finance
entity-extraction
ner
phi-3
production
indian-banking
custom_code
4-bit precision
Instructions to use Ranjit0034/finance-entity-extractor with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Ranjit0034/finance-entity-extractor with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Ranjit0034/finance-entity-extractor", trust_remote_code=True)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("Ranjit0034/finance-entity-extractor", trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained("Ranjit0034/finance-entity-extractor", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Ranjit0034/finance-entity-extractor with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Ranjit0034/finance-entity-extractor" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Ranjit0034/finance-entity-extractor", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Ranjit0034/finance-entity-extractor
- SGLang
How to use Ranjit0034/finance-entity-extractor with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Ranjit0034/finance-entity-extractor" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Ranjit0034/finance-entity-extractor", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Ranjit0034/finance-entity-extractor" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Ranjit0034/finance-entity-extractor", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Ranjit0034/finance-entity-extractor with Docker Model Runner:
docker model run hf.co/Ranjit0034/finance-entity-extractor
| """ | |
| FastAPI Server for LLM Mail Trainer. | |
| Production-grade REST API for financial email entity extraction and | |
| classification. Designed for high performance and reliability. | |
| Features: | |
| - Entity extraction endpoint (/extract) | |
| - Email classification endpoint (/classify) | |
| - Full analysis endpoint (/analyze) | |
| - Batch processing endpoint (/batch) | |
| - Health check and metrics endpoints | |
| - OpenAPI documentation | |
| - CORS support | |
| - Request validation | |
| - Error handling | |
| Endpoints: | |
| GET / - API information | |
| GET /health - Health check | |
| GET /stats - Usage statistics | |
| POST /extract - Extract entities from email | |
| POST /classify - Classify email category | |
| POST /analyze - Full analysis (classify + extract) | |
| POST /batch - Process multiple emails | |
| Example: | |
| Start the server: | |
| $ uvicorn src.api.server:app --reload --port 8000 | |
| Make a request: | |
| $ curl -X POST http://localhost:8000/extract \\ | |
| -H "Content-Type: application/json" \\ | |
| -d '{"body": "Rs.500 debited from account 1234"}' | |
| Author: Ranjit Behera | |
| License: MIT | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import os | |
| import sys | |
| from datetime import datetime | |
| from pathlib import Path | |
| from typing import Any, Dict, List, Optional | |
| from fastapi import FastAPI, HTTPException, Request, status | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from pydantic import BaseModel, Field, field_validator | |
| # Add parent to path for imports | |
| sys.path.insert(0, str(Path(__file__).parent.parent)) | |
| from data.extractor import EntityExtractor, FinancialEntity | |
| from data.classifier import EmailClassifier, ClassificationResult | |
| # Configure logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", | |
| datefmt="%Y-%m-%d %H:%M:%S", | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # ============================================================================= | |
| # Pydantic Models (Request/Response Schemas) | |
| # ============================================================================= | |
| class EmailInput(BaseModel): | |
| """ | |
| Input model for email analysis requests. | |
| Attributes: | |
| subject: Email subject line (optional). | |
| body: Email body text (required). | |
| sender: Sender name or email address (optional). | |
| Example: | |
| { | |
| "subject": "Transaction Alert", | |
| "body": "Rs.500 debited from account 1234", | |
| "sender": "HDFC Bank" | |
| } | |
| """ | |
| subject: str = Field( | |
| default="", | |
| description="Email subject line", | |
| max_length=500, | |
| ) | |
| body: str = Field( | |
| ..., | |
| description="Email body text (required)", | |
| min_length=1, | |
| max_length=10000, | |
| ) | |
| sender: str = Field( | |
| default="", | |
| description="Sender name or email address", | |
| max_length=200, | |
| ) | |
| def body_not_empty(cls, v: str) -> str: | |
| """Validate body is not just whitespace.""" | |
| if not v.strip(): | |
| raise ValueError("Body cannot be empty or whitespace only") | |
| return v.strip() | |
| model_config = { | |
| "json_schema_extra": { | |
| "examples": [ | |
| { | |
| "subject": "β You have done a UPI txn. Check details!", | |
| "body": "Dear Customer, Rs.2500.00 has been debited from account 3545 to VPA swiggy@ybl on 28-12-25. Reference: 534567891234.", | |
| "sender": "HDFC Bank InstaAlerts" | |
| } | |
| ] | |
| } | |
| } | |
| class BatchEmailInput(BaseModel): | |
| """ | |
| Input model for batch processing. | |
| Attributes: | |
| emails: List of emails to process (max 100). | |
| """ | |
| emails: List[EmailInput] = Field( | |
| ..., | |
| description="List of emails to process", | |
| min_length=1, | |
| max_length=100, | |
| ) | |
| class EntityResponse(BaseModel): | |
| """ | |
| Response model for entity extraction. | |
| Attributes: | |
| success: Whether extraction found valid entities. | |
| entities: Dictionary of extracted entities. | |
| extraction_time_ms: Processing time in milliseconds. | |
| confidence: Confidence score (0.0 to 1.0). | |
| """ | |
| success: bool = Field(description="Extraction found valid entities") | |
| entities: Dict[str, Any] = Field(description="Extracted entities") | |
| extraction_time_ms: float = Field(description="Processing time in milliseconds") | |
| confidence: float = Field(default=0.0, description="Confidence score") | |
| model_config = { | |
| "json_schema_extra": { | |
| "examples": [ | |
| { | |
| "success": True, | |
| "entities": { | |
| "amount": "2500.00", | |
| "type": "debit", | |
| "account": "3545", | |
| "date": "28-12-25", | |
| "reference": "534567891234", | |
| "merchant": "swiggy", | |
| "category": "food" | |
| }, | |
| "extraction_time_ms": 1.5, | |
| "confidence": 0.85 | |
| } | |
| ] | |
| } | |
| } | |
| class ClassificationResponse(BaseModel): | |
| """ | |
| Response model for email classification. | |
| Attributes: | |
| category: Predicted email category. | |
| confidence: Confidence level (high/medium/low). | |
| reason: Explanation for classification. | |
| is_transaction: Whether email is a financial transaction. | |
| """ | |
| category: str = Field(description="Predicted category") | |
| confidence: str = Field(description="Confidence level") | |
| reason: str = Field(description="Classification reasoning") | |
| is_transaction: bool = Field(description="Is financial transaction") | |
| model_config = { | |
| "json_schema_extra": { | |
| "examples": [ | |
| { | |
| "category": "finance", | |
| "confidence": "high", | |
| "reason": "Matched: sender:hdfc, debited, account", | |
| "is_transaction": True | |
| } | |
| ] | |
| } | |
| } | |
| class FullAnalysisResponse(BaseModel): | |
| """ | |
| Response model for full email analysis. | |
| Combines classification and entity extraction results. | |
| """ | |
| classification: ClassificationResponse | |
| entities: Optional[Dict[str, Any]] = Field( | |
| default=None, | |
| description="Extracted entities (only for finance emails)" | |
| ) | |
| processing_time_ms: float = Field(description="Total processing time") | |
| class HealthResponse(BaseModel): | |
| """Health check response.""" | |
| status: str = Field(description="Service status") | |
| version: str = Field(description="API version") | |
| timestamp: str = Field(description="Current timestamp") | |
| uptime_seconds: float = Field(description="Server uptime") | |
| class StatsResponse(BaseModel): | |
| """API statistics response.""" | |
| total_requests: int = Field(description="Total requests processed") | |
| entities_extracted: int = Field(description="Successful extractions") | |
| emails_classified: int = Field(description="Emails classified") | |
| uptime_seconds: float = Field(description="Server uptime") | |
| requests_per_minute: float = Field(description="Request rate") | |
| class ErrorResponse(BaseModel): | |
| """Error response model.""" | |
| error: str = Field(description="Error type") | |
| message: str = Field(description="Error message") | |
| details: Optional[Dict[str, Any]] = Field(default=None) | |
| # ============================================================================= | |
| # Application State and Configuration | |
| # ============================================================================= | |
| class AppState: | |
| """ | |
| Application state container. | |
| Holds global state including statistics, service instances, | |
| and configuration. | |
| """ | |
| def __init__(self) -> None: | |
| self.start_time = datetime.now() | |
| self.total_requests = 0 | |
| self.entities_extracted = 0 | |
| self.emails_classified = 0 | |
| # Initialize services | |
| self.extractor = EntityExtractor() | |
| self.classifier = EmailClassifier(use_llm=False) | |
| logger.info("Application state initialized") | |
| def uptime_seconds(self) -> float: | |
| """Calculate server uptime in seconds.""" | |
| return (datetime.now() - self.start_time).total_seconds() | |
| def requests_per_minute(self) -> float: | |
| """Calculate request rate.""" | |
| uptime_minutes = self.uptime_seconds / 60 | |
| if uptime_minutes < 1: | |
| return self.total_requests * 60 | |
| return self.total_requests / uptime_minutes | |
| # Global state | |
| state = AppState() | |
| # ============================================================================= | |
| # Application Factory | |
| # ============================================================================= | |
| def create_app() -> FastAPI: | |
| """ | |
| Create and configure the FastAPI application. | |
| Returns: | |
| FastAPI: Configured application instance. | |
| Example: | |
| >>> app = create_app() | |
| >>> # Run with: uvicorn src.api.server:app | |
| """ | |
| app = FastAPI( | |
| title="π§ LLM Mail Trainer API", | |
| description=""" | |
| ## Financial Email Entity Extraction API | |
| Production-grade API for extracting structured financial data from emails. | |
| ### Features | |
| - **Entity Extraction**: Amount, type, account, date, reference, merchant, category | |
| - **Email Classification**: Finance, shopping, work, newsletter, promotional, etc. | |
| - **Batch Processing**: Process multiple emails efficiently | |
| - **High Performance**: Optimized for speed with < 5ms response time | |
| ### Supported Banks | |
| HDFC, ICICI, SBI, Axis, Kotak, PNB, BoB, and more. | |
| ### Supported Payment Platforms | |
| PhonePe, GPay, Paytm, BHIM UPI | |
| ### Quick Example | |
| ```python | |
| import requests | |
| response = requests.post( | |
| "http://localhost:8000/extract", | |
| json={ | |
| "body": "Rs.500 debited from account 1234 on 01-01-26", | |
| "subject": "Transaction Alert" | |
| } | |
| ) | |
| print(response.json()) | |
| ``` | |
| ### Links | |
| - [Model on HuggingFace](https://huggingface.co/Ranjit0034/finance-entity-extractor) | |
| - [GitHub Repository](https://github.com/ranjit/llm-mail-trainer) | |
| """, | |
| version="0.3.0", | |
| docs_url="/docs", | |
| redoc_url="/redoc", | |
| openapi_url="/openapi.json", | |
| contact={ | |
| "name": "Ranjit Behera", | |
| "email": "ranjit@example.com", | |
| }, | |
| license_info={ | |
| "name": "MIT", | |
| "url": "https://opensource.org/licenses/MIT", | |
| }, | |
| ) | |
| # CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| return app | |
| app = create_app() | |
| # ============================================================================= | |
| # Exception Handlers | |
| # ============================================================================= | |
| async def http_exception_handler( | |
| request: Request, | |
| exc: HTTPException | |
| ) -> JSONResponse: | |
| """Handle HTTP exceptions with consistent format.""" | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content=ErrorResponse( | |
| error="HTTPException", | |
| message=exc.detail, | |
| ).model_dump(), | |
| ) | |
| async def general_exception_handler( | |
| request: Request, | |
| exc: Exception | |
| ) -> JSONResponse: | |
| """Handle unexpected exceptions.""" | |
| logger.error(f"Unhandled exception: {exc}", exc_info=True) | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content=ErrorResponse( | |
| error="InternalServerError", | |
| message="An unexpected error occurred", | |
| ).model_dump(), | |
| ) | |
| # ============================================================================= | |
| # API Endpoints | |
| # ============================================================================= | |
| async def root() -> Dict[str, Any]: | |
| """ | |
| Get API information and available endpoints. | |
| Returns a summary of the API including version, documentation links, | |
| and available endpoints. | |
| """ | |
| return { | |
| "name": "LLM Mail Trainer API", | |
| "version": "0.3.0", | |
| "description": "Financial email entity extraction and classification", | |
| "documentation": { | |
| "swagger": "/docs", | |
| "redoc": "/redoc", | |
| "openapi": "/openapi.json", | |
| }, | |
| "endpoints": { | |
| "extract": "POST /extract - Extract entities from email", | |
| "classify": "POST /classify - Classify email category", | |
| "analyze": "POST /analyze - Full analysis (classify + extract)", | |
| "batch": "POST /batch - Process multiple emails", | |
| "health": "GET /health - Health check", | |
| "stats": "GET /stats - API statistics", | |
| }, | |
| "model": "Ranjit0034/finance-entity-extractor", | |
| } | |
| async def health_check() -> HealthResponse: | |
| """ | |
| Check API health status. | |
| Returns the current health status of the API including version | |
| and uptime information. | |
| """ | |
| return HealthResponse( | |
| status="healthy", | |
| version="0.3.0", | |
| timestamp=datetime.now().isoformat(), | |
| uptime_seconds=round(state.uptime_seconds, 2), | |
| ) | |
| async def get_stats() -> StatsResponse: | |
| """ | |
| Get API usage statistics. | |
| Returns metrics including total requests, successful extractions, | |
| and performance data. | |
| """ | |
| return StatsResponse( | |
| total_requests=state.total_requests, | |
| entities_extracted=state.entities_extracted, | |
| emails_classified=state.emails_classified, | |
| uptime_seconds=round(state.uptime_seconds, 2), | |
| requests_per_minute=round(state.requests_per_minute, 2), | |
| ) | |
| async def extract_entities(email: EmailInput) -> EntityResponse: | |
| """ | |
| Extract financial entities from an email. | |
| Analyzes the email text and extracts structured data including: | |
| - **amount**: Transaction amount | |
| - **type**: Debit or credit | |
| - **account**: Account number (masked) | |
| - **date**: Transaction date | |
| - **reference**: UPI/IMPS reference number | |
| - **merchant**: Identified merchant name | |
| - **category**: Transaction category (food, shopping, etc.) | |
| Args: | |
| email: Email content with subject, body, and sender. | |
| Returns: | |
| EntityResponse: Extracted entities with success status. | |
| Raises: | |
| HTTPException: If extraction fails critically. | |
| """ | |
| state.total_requests += 1 | |
| start = datetime.now() | |
| try: | |
| # Combine subject and body for extraction | |
| full_text = f"Subject: {email.subject}\n\n{email.body}" | |
| result = state.extractor.extract(full_text) | |
| elapsed = (datetime.now() - start).total_seconds() * 1000 | |
| if result.is_valid(): | |
| state.entities_extracted += 1 | |
| return EntityResponse( | |
| success=result.is_valid(), | |
| entities=result.to_dict(), | |
| extraction_time_ms=round(elapsed, 2), | |
| confidence=round(result.confidence_score(), 2), | |
| ) | |
| except Exception as e: | |
| logger.error(f"Extraction error: {e}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail=f"Extraction failed: {str(e)}" | |
| ) | |
| async def classify_email(email: EmailInput) -> ClassificationResponse: | |
| """ | |
| Classify an email into a category. | |
| Categories: | |
| - **finance**: Bank transactions, payments, investments | |
| - **shopping**: Orders, deliveries, e-commerce | |
| - **work**: Job-related, recruitment, meetings | |
| - **newsletter**: Digests, articles, subscriptions | |
| - **promotional**: Marketing, offers, discounts | |
| - **social**: Social networks, personal messages | |
| - **other**: Uncategorized emails | |
| Args: | |
| email: Email content to classify. | |
| Returns: | |
| ClassificationResponse: Category with confidence and reasoning. | |
| """ | |
| state.total_requests += 1 | |
| state.emails_classified += 1 | |
| try: | |
| result = state.classifier.classify( | |
| subject=email.subject, | |
| sender=email.sender, | |
| body=email.body, | |
| ) | |
| return ClassificationResponse( | |
| category=result.category, | |
| confidence=result.confidence, | |
| reason=result.reason, | |
| is_transaction=result.is_transaction, | |
| ) | |
| except Exception as e: | |
| logger.error(f"Classification error: {e}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail=f"Classification failed: {str(e)}" | |
| ) | |
| async def full_analysis(email: EmailInput) -> FullAnalysisResponse: | |
| """ | |
| Perform full analysis: classify the email and extract entities. | |
| This endpoint combines classification and entity extraction in one call. | |
| Entities are only extracted if the email is classified as finance-related. | |
| Args: | |
| email: Email content to analyze. | |
| Returns: | |
| FullAnalysisResponse: Classification and extracted entities. | |
| """ | |
| state.total_requests += 1 | |
| start = datetime.now() | |
| try: | |
| # Classify first | |
| classification = state.classifier.classify( | |
| subject=email.subject, | |
| sender=email.sender, | |
| body=email.body, | |
| ) | |
| state.emails_classified += 1 | |
| # Extract entities if finance-related | |
| entities = None | |
| if classification.category == "finance" or classification.is_transaction: | |
| full_text = f"Subject: {email.subject}\n\n{email.body}" | |
| result = state.extractor.extract(full_text) | |
| entities = result.to_dict() | |
| if result.is_valid(): | |
| state.entities_extracted += 1 | |
| elapsed = (datetime.now() - start).total_seconds() * 1000 | |
| return FullAnalysisResponse( | |
| classification=ClassificationResponse( | |
| category=classification.category, | |
| confidence=classification.confidence, | |
| reason=classification.reason, | |
| is_transaction=classification.is_transaction, | |
| ), | |
| entities=entities, | |
| processing_time_ms=round(elapsed, 2), | |
| ) | |
| except Exception as e: | |
| logger.error(f"Analysis error: {e}", exc_info=True) | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail=f"Analysis failed: {str(e)}" | |
| ) | |
| async def batch_process(batch: BatchEmailInput) -> Dict[str, Any]: | |
| """ | |
| Process multiple emails at once. | |
| Each email is classified and entities are extracted for finance emails. | |
| Results are returned in the same order as input. | |
| Args: | |
| batch: List of emails to process (max 100). | |
| Returns: | |
| Dict with processing results for each email. | |
| Note: | |
| Failed individual emails don't fail the entire batch. | |
| Check the 'error' field in each result. | |
| """ | |
| state.total_requests += 1 | |
| start = datetime.now() | |
| results = [] | |
| for email in batch.emails: | |
| try: | |
| # Classify | |
| classification = state.classifier.classify( | |
| subject=email.subject, | |
| sender=email.sender, | |
| body=email.body, | |
| ) | |
| state.emails_classified += 1 | |
| # Extract if finance | |
| entities = None | |
| if classification.category == "finance" or classification.is_transaction: | |
| full_text = f"Subject: {email.subject}\n\n{email.body}" | |
| result = state.extractor.extract(full_text) | |
| entities = result.to_dict() | |
| if result.is_valid(): | |
| state.entities_extracted += 1 | |
| results.append({ | |
| "subject": email.subject[:50] if email.subject else "(no subject)", | |
| "classification": { | |
| "category": classification.category, | |
| "confidence": classification.confidence, | |
| "is_transaction": classification.is_transaction, | |
| }, | |
| "entities": entities, | |
| }) | |
| except Exception as e: | |
| logger.warning(f"Batch item error: {e}") | |
| results.append({ | |
| "subject": email.subject[:50] if email.subject else "(no subject)", | |
| "error": str(e), | |
| }) | |
| elapsed = (datetime.now() - start).total_seconds() * 1000 | |
| return { | |
| "total_processed": len(results), | |
| "successful": sum(1 for r in results if "error" not in r), | |
| "failed": sum(1 for r in results if "error" in r), | |
| "processing_time_ms": round(elapsed, 2), | |
| "results": results, | |
| } | |
| # ============================================================================= | |
| # CLI Runner | |
| # ============================================================================= | |
| def main() -> None: | |
| """ | |
| Run the API server from command line. | |
| Usage: | |
| python -m src.api.server | |
| Environment Variables: | |
| HOST: Server host (default: 0.0.0.0) | |
| PORT: Server port (default: 8000) | |
| LOG_LEVEL: Logging level (default: info) | |
| """ | |
| import uvicorn | |
| port = int(os.getenv("PORT", "8000")) | |
| host = os.getenv("HOST", "0.0.0.0") | |
| log_level = os.getenv("LOG_LEVEL", "info").lower() | |
| print(f""" | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β π§ LLM Mail Trainer API Server β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£ | |
| β Swagger Docs: http://{host}:{port}/docs β | |
| β ReDoc: http://{host}:{port}/redoc β | |
| β Health Check: http://{host}:{port}/health β | |
| β OpenAPI JSON: http://{host}:{port}/openapi.json β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£ | |
| β Model: Ranjit0034/finance-entity-extractor β | |
| β Version: 0.3.0 β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """) | |
| uvicorn.run( | |
| "src.api.server:app", | |
| host=host, | |
| port=port, | |
| log_level=log_level, | |
| reload=True, | |
| ) | |
| if __name__ == "__main__": | |
| main() | |