{"id":50278091,"url":"https://github.com/shivansh2904/nlpipe","last_synced_at":"2026-05-27T22:04:13.903Z","repository":{"id":358408637,"uuid":"1241244926","full_name":"Shivansh2904/nlpipe","owner":"Shivansh2904","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-27T13:26:04.000Z","size":381,"stargazers_count":0,"open_issues_count":16,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T15:12:23.830Z","etag":null,"topics":["docker","fastapi","huggingface","machine-learning","nlp","python","react","sdk","sentiment-analysis","transformers","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shivansh2904.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T06:17:07.000Z","updated_at":"2026-05-27T13:26:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Shivansh2904/nlpipe","commit_stats":null,"previous_names":["shivansh2904/nlpipe"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Shivansh2904/nlpipe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shivansh2904%2Fnlpipe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shivansh2904%2Fnlpipe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shivansh2904%2Fnlpipe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shivansh2904%2Fnlpipe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shivansh2904","download_url":"https://codeload.github.com/Shivansh2904/nlpipe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shivansh2904%2Fnlpipe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33585230,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","fastapi","huggingface","machine-learning","nlp","python","react","sdk","sentiment-analysis","transformers","typescript"],"created_at":"2026-05-27T22:03:56.592Z","updated_at":"2026-05-27T22:04:13.897Z","avatar_url":"https://github.com/Shivansh2904.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NLPipe\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Python-3.11-3776ab?style=for-the-badge\u0026logo=python\u0026logoColor=white\" alt=\"Python 3.11\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/FastAPI-0.109+-009688?style=for-the-badge\u0026logo=fastapi\u0026logoColor=white\" alt=\"FastAPI\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/HuggingFace-Transformers-FFD21F?style=for-the-badge\u0026logo=huggingface\u0026logoColor=black\" alt=\"HuggingFace\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/TypeScript-5.x-3178c6?style=for-the-badge\u0026logo=typescript\u0026logoColor=white\" alt=\"TypeScript\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/React-18-61dafb?style=for-the-badge\u0026logo=react\u0026logoColor=black\" alt=\"React 18\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Docker-Compose-2496ed?style=for-the-badge\u0026logo=docker\u0026logoColor=white\" alt=\"Docker\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/License-MIT-green?style=for-the-badge\" alt=\"MIT License\" /\u003e\n  \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/Shivansh2904/nlpipe/ci.yml?branch=main\u0026style=for-the-badge\u0026label=CI\" alt=\"CI\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA self-hosted NLP API serving 6 tasks through one unified REST interface — no API keys, no rate limits, runs on your hardware.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#quick-start\"\u003eQuick Start\u003c/a\u003e ·\n  \u003ca href=\"#supported-tasks\"\u003eTasks\u003c/a\u003e ·\n  \u003ca href=\"#typescript-sdk\"\u003eTypeScript SDK\u003c/a\u003e ·\n  \u003ca href=\"#api-reference\"\u003eAPI Reference\u003c/a\u003e ·\n  \u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e ·\n  \u003ca href=\"#performance\"\u003ePerformance\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What is NLPipe?\n\nNLPipe is a production-grade NLP inference server that wraps best-in-class HuggingFace models behind a single, clean REST API. Drop it into any stack — call it from Python, TypeScript, curl, or any HTTP client. No cloud subscription, no per-request billing, no cold starts from someone else's servers.\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                        Your App                          │\n│   Python · TypeScript SDK · curl · Any HTTP client       │\n└──────────────────────────┬───────────────────────────────┘\n                           │  REST / JSON\n┌──────────────────────────▼───────────────────────────────┐\n│                    NLPipe API (FastAPI)                   │\n│  POST /sentiment  POST /ner  POST /classify              │\n│  POST /summarize  POST /keywords  POST /translate        │\n│  GET /health  GET /models                                │\n└──────┬──────┬──────┬──────────┬──────┬────────────────────┘\n       │      │      │          │      │\n   distil  bert  bart-large  distilbart  sklearn  Helsinki-NLP\n   -bert   NER   mnli        cnn-12-6    TF-IDF   opus-mt-*\n```\n\n---\n\n## Supported Tasks\n\n| Task | Model | Input | Output |\n|------|-------|-------|--------|\n| **Sentiment Analysis** | `distilbert-base-uncased-finetuned-sst-2-english` | text | `label` (POSITIVE/NEGATIVE) + `score` |\n| **Batch Sentiment** | `distilbert-base-uncased-finetuned-sst-2-english` | list of texts (max 100) | list of `{ label, score, text }` + `count` |\n| **Named Entity Recognition** | `dslim/bert-base-NER` | text | list of entities with type, score, offsets |\n| **Zero-Shot Classification** | `facebook/bart-large-mnli` | text + candidate labels | per-label confidence scores |\n| **Text Summarization** | `sshleifer/distilbart-cnn-12-6` | long text | abstractive summary |\n| **Keyword Extraction** | NLTK/TF-IDF (sklearn) | text | ranked keywords + scores |\n| **Translation** | `Helsinki-NLP/opus-mt-{src}-{target}` | text + language codes | translated text (loaded on demand per language pair) |\n\n---\n\n## Deploy\n\n[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/Shivansh2904/nlpipe)\n\nA `render.yaml` blueprint provisions the API on a Standard plan with a 10 GB persistent disk for HuggingFace model caching.\n\n---\n\n## Quick Start\n\n### Option A — Docker Compose (recommended)\n\n```bash\ngit clone https://github.com/Shivansh2904/nlpipe.git\ncd nlpipe\ndocker-compose up\n```\n\n| Service | URL |\n|---------|-----|\n| API | http://localhost:8000 |\n| Interactive Docs | http://localhost:8000/docs |\n| React Playground | http://localhost:5173 |\n\n\u003e **First-run note:** HuggingFace models are downloaded on first request (~3 GB total) and cached in a Docker volume. Subsequent starts are instant.\n\n### Option B — Local Development\n\n**API:**\n```bash\ncd api\npython -m venv .venv \u0026\u0026 source .venv/bin/activate   # Windows: .venv\\Scripts\\activate\npip install -r requirements.txt\nuvicorn main:app --reload --port 8000\n```\n\n**Playground:**\n```bash\ncd playground\nnpm install\nnpm run dev        # opens http://localhost:5173\n```\n\n---\n\n## curl Examples\n\n```bash\n# Sentiment Analysis\ncurl -X POST http://localhost:8000/sentiment \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"This product exceeded all my expectations!\"}'\n# → {\"label\":\"POSITIVE\",\"score\":0.999832,\"text\":\"...\"}\n\n# Batch Sentiment Analysis (up to 100 texts in one call)\ncurl -X POST http://localhost:8000/sentiment/batch \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"texts\": [\"I love this!\", \"This is terrible.\", \"Meh, it works.\"]}'\n# → {\"results\":[{\"label\":\"POSITIVE\",\"score\":0.9998,\"text\":\"I love this!\"},...],\"count\":3}\n\n# Named Entity Recognition\ncurl -X POST http://localhost:8000/ner \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"Elon Musk founded SpaceX in Hawthorne, California.\"}'\n# → {\"entities\":[{\"word\":\"Elon Musk\",\"label\":\"PER\",\"score\":0.9993,...},...],\"text\":\"...\"}\n\n# Zero-Shot Classification\ncurl -X POST http://localhost:8000/classify \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"The stock market surged 3% on rate cut hopes.\", \"labels\": [\"finance\",\"sports\",\"technology\"]}'\n# → {\"scores\":{\"finance\":0.9721,...},\"top_label\":\"finance\",\"text\":\"...\"}\n\n# Summarization\ncurl -X POST http://localhost:8000/summarize \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"...long article...\", \"max_length\": 100, \"min_length\": 30}'\n# → {\"summary\":\"...\",\"original_length\":312,\"summary_length\":47}\n\n# Keyword Extraction\ncurl -X POST http://localhost:8000/keywords \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"Machine learning transforms how we process natural language.\", \"top_k\": 5}'\n# → {\"keywords\":[{\"word\":\"machine learning\",\"score\":0.8234},...],\"text\":\"...\"}\n\n# Translation (Helsinki-NLP opus-mt, loaded on demand)\ncurl -X POST http://localhost:8000/translate \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"Hello, how are you?\", \"source_lang\": \"en\", \"target_lang\": \"fr\"}'\n# → {\"translation\":\"Bonjour, comment allez-vous ?\",\"source_lang\":\"en\",\"target_lang\":\"fr\",\"text\":\"...\"}\n\n# Health Check\ncurl http://localhost:8000/health\n# → {\"status\":\"ok\",\"models_loaded\":{...},\"uptime_seconds\":142.3}\n```\n\n\u003e **Python demo:** A runnable end-to-end Python example that exercises every endpoint lives in [`examples/demo.py`](examples/demo.py). See [`examples/README.md`](examples/README.md) for usage.\n\n---\n\n## TypeScript SDK\n\nInstall from the `sdk/` directory (or publish to npm):\n\n```bash\ncd sdk \u0026\u0026 npm install \u0026\u0026 npm run build\n```\n\n```typescript\nimport { NLPipeClient } from 'nlpipe-sdk';\n\nconst nlp = new NLPipeClient('http://localhost:8000');\n\n// Sentiment\nconst s = await nlp.sentiment('I love how simple this API is!');\nconsole.log(s.label, s.score);  // POSITIVE  0.9998\n\n// Batch Sentiment (up to 100 texts in a single call)\nconst batch = await nlp.sentimentBatch([\n  'I love this!',\n  'This is terrible.',\n  'Meh, it works.',\n]);\nconsole.log(batch.count);  // 3\nbatch.results.forEach(r =\u003e console.log(r.label, r.text));\n\n// NER\nconst n = await nlp.ner('Barack Obama was born in Honolulu, Hawaii.');\nn.entities.forEach(e =\u003e console.log(e.word, e.label));  // Barack Obama PER  ...\n\n// Zero-shot\nconst c = await nlp.classify('The game went into overtime.', ['sports', 'politics', 'tech']);\nconsole.log(c.top_label);  // sports\n\n// Summarize\nconst sum = await nlp.summarize(longArticle, { maxLength: 150, minLength: 40 });\nconsole.log(sum.summary);\n\n// Keywords\nconst kw = await nlp.keywords('Deep learning and transformer models...', 8);\nkw.keywords.forEach(k =\u003e console.log(k.word, k.score));\n\n// Translate (defaults: en → fr)\nconst tr = await nlp.translate('Hello, how are you?');\nconsole.log(tr.translation);  // Bonjour, comment allez-vous ?\n\n// Translate with explicit language codes\nconst tr2 = await nlp.translate('Good morning', 'en', 'de');\nconsole.log(tr2.translation);  // Guten Morgen\n```\n\nAll methods return fully typed `Promise\u003cT\u003e` results. Errors throw `NLPipeError` with `statusCode` and `detail` properties.\n\n---\n\n## API Reference\n\nInteractive Swagger UI is served at **http://localhost:8000/docs**. ReDoc is at **/redoc**.\n\n### `POST /sentiment`\n| Field | Type | Description |\n|-------|------|-------------|\n| `text` | `string` | Input text (1–10,000 chars) |\n\nResponse: `{ label, score, text }`\n\n### `POST /sentiment/batch`\n| Field | Type | Description |\n|-------|------|-------------|\n| `texts` | `string[]` | List of texts to analyse (1–100 items, each 1–10,000 chars) |\n\nResponse: `{ results: [{ label, score, text }], count }`\n\n### `POST /ner`\n| Field | Type | Description |\n|-------|------|-------------|\n| `text` | `string` | Input text (1–10,000 chars) |\n\nResponse: `{ entities: [{ word, label, score, start, end }], text }`\n\n### `POST /classify`\n| Field | Type | Description |\n|-------|------|-------------|\n| `text` | `string` | Input text (1–10,000 chars) |\n| `labels` | `string[]` | Candidate category labels |\n\nResponse: `{ scores: { label: score }, top_label, text }`\n\n### `POST /summarize`\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `text` | `string` | — | Source text (1–10,000 chars) |\n| `max_length` | `int` | `130` | Max output token length (30–512) |\n| `min_length` | `int` | `30` | Min output token length (10–256) |\n\nResponse: `{ summary, original_length, summary_length }`\n\n### `POST /keywords`\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `text` | `string` | — | Source text (1–10,000 chars) |\n| `top_k` | `int` | `10` | Number of keywords to return (1–50) |\n\nResponse: `{ keywords: [{ word, score }], text }`\n\n### `POST /translate`\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `text` | `string` | — | Source text to translate (1–5,000 chars) |\n| `source_lang` | `string` | `\"en\"` | ISO 639-1 source language code |\n| `target_lang` | `string` | `\"fr\"` | ISO 639-1 target language code |\n\nResponse: `{ translation, source_lang, target_lang, text }`\n\nThe appropriate `Helsinki-NLP/opus-mt-{src}-{target}` model is loaded on demand and cached for subsequent requests with the same language pair.\n\n### `GET /health`\nResponse: `{ status, models_loaded: { sentiment, ner, classifier, summarizer, keywords }, uptime_seconds }`\n\n### `GET /models`\nResponse: array of `{ name, task, loaded, approx_size_mb, description }`\n\n### Rate Limiting\n\nNLPipe ships with per-IP rate limiting (powered by [`slowapi`](https://github.com/laurentS/slowapi)) so that a self-hosted instance can safely be exposed to the public internet without a single client monopolizing inference time.\n\n| Scope | Limit |\n|-------|-------|\n| **Default** (all endpoints) | `100` requests / minute / IP |\n| `POST /summarize` (heavy) | `10` requests / minute / IP |\n| `POST /translate` (heavy) | `15` requests / minute / IP |\n| `POST /classify` | `20` requests / minute / IP |\n| `POST /sentiment/batch` | `30` requests / minute / IP |\n| `POST /sentiment`, `POST /ner`, `POST /keywords` | default `100/min` |\n\nWhen a client exceeds its limit, the API responds with **HTTP `429 Too Many Requests`** and a `Retry-After` header indicating how many seconds to wait before retrying. Limits are tracked in-memory per server process and reset every rolling minute.\n\n### Error codes\n| Code | Meaning |\n|------|---------|\n| `422` | Validation error (empty text, bad input shape) |\n| `413` | Text exceeds 10,000-character limit |\n| `429` | Rate limit exceeded — see `Retry-After` header |\n| `500` | Unexpected server error |\n\nEvery response includes an `X-Process-Time` header with inference duration in seconds.\n\n---\n\n## Architecture\n\n```\nnlpipe/\n├── api/\n│   ├── main.py          # FastAPI app, all endpoints, lazy model cache\n│   ├── models.py        # Model loading functions (one per task)\n│   ├── schemas.py       # Pydantic v2 request/response models\n│   ├── requirements.txt\n│   └── Dockerfile\n├── sdk/\n│   ├── src/\n│   │   ├── index.ts     # NLPipeClient class + all TypeScript types\n│   │   └── index.test.ts\n│   ├── package.json\n│   └── tsconfig.json\n├── playground/\n│   ├── src/\n│   │   ├── App.tsx      # React playground UI (dark theme + Tailwind)\n│   │   └── index.css\n│   ├── index.html\n│   ├── Dockerfile       # Multi-stage nginx build\n│   └── nginx.conf\n├── docker-compose.yml\n└── .github/workflows/ci.yml\n```\n\n**Lazy model loading:** Models are stored in a module-level `_models: dict` in `main.py`. On the first request to each endpoint, the relevant model loads into memory and stays cached for all subsequent requests. This means zero startup latency for tasks you don't use.\n\n**CORS:** All origins are allowed, making the API callable directly from browser-based applications.\n\n**Request timing:** A middleware layer captures wall-clock time for every request and injects it into the `X-Process-Time` response header.\n\n---\n\n## Performance\n\n\u003e Benchmarks measured on an Apple M2 Pro (CPU inference, no GPU).\n\n| Task | Model load (cold) | Inference (warm) |\n|------|-------------------|------------------|\n| Sentiment | ~4 s | ~80 ms |\n| NER | ~8 s | ~120 ms |\n| Zero-Shot | ~18 s | ~800 ms |\n| Summarization | ~15 s | ~2–8 s (text length dependent) |\n| Keywords | \u003c1 s | \u003c10 ms |\n\n**GPU acceleration:** Set the device in `api/models.py` by passing `device=0` to each `pipeline()` call when a CUDA GPU is available. Inference latency drops 5–10x.\n\n**Model caching:** Mount a persistent volume at `/cache` (configured in `docker-compose.yml`) to avoid re-downloading models on container restart.\n\n---\n\n## Development\n\n### Running tests\n\n```bash\n# SDK unit tests (mocked fetch — no live server needed)\ncd sdk \u0026\u0026 npm test\n\n# Python syntax check\npython -m py_compile api/main.py api/models.py api/schemas.py\n```\n\n### CI\n\nGitHub Actions runs three parallel jobs on every push and pull request:\n1. **Python** — `pyflakes` lint + compile check on all `.py` files\n2. **SDK** — `npm ci` → `tsc` build → Jest unit tests\n3. **Playground** — `npm ci` → `vite build`\n\n---\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feat/my-feature`\n3. Commit your changes\n4. Open a pull request\n\n---\n\n## License\n\n[MIT](LICENSE) © 2025 Shivansh Mishra\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshivansh2904%2Fnlpipe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshivansh2904%2Fnlpipe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshivansh2904%2Fnlpipe/lists"}