nano-ai-pdf
Version:
This package helps you summarize pdfs using Gemini nano on edge or on browser, making it compliant safe, faster and free
246 lines (179 loc) • 6.05 kB
Markdown
# nano-ai-pdf
A **TypeScript/JavaScript** library that extracts text from PDF files and **summarizes them using Chrome’s built‑in on-device Summarizer API (Gemini Nano)**.
Runs entirely in the browser on supported Chrome versions — **no API keys, no servers**.
## Badges
## ✨ Features
- 📄 **PDF Text Extraction** using [`react-pdftotext`](https://www.npmjs.com/package/react-pdftotext)
- 🤖 **On-device AI Summarization** — Chrome’s Summarizer API (Gemini Nano)
- ⏳ **Streaming Support** — get real-time summary updates
- 🛡️ **Runs locally** — private \& secure
- 🚫 Rejects **image-only PDFs**
- 📊 **Metrics** — compression ratio, processing time
- 🖥️ **TypeScript typings** included
- 📥 **Progress tracking** — get model download % via functions or callback
## 📦 Installation
```bash
npm install nano-ai-pdf
# or
yarn add nano-ai-pdf
```
## ⚙️ Prerequisites
- 🖥 **Chrome 138+** (desktop)
- Enable flags:
- `chrome://flags/#prompt-api-for-gemini-nano` → **Enabled**
- `chrome://flags/#optimization-guide-on-device-model` → **Enabled BypassPerfRequirement**
- OS: Windows 10/11, macOS 13+, Linux
- ≥ 22 GB disk space, ≥ 4 GB GPU VRAM
- Must be triggered with **user gesture** (`click`, `tap`, etc.)
## 📚 API Reference \& Examples
### 1️⃣ `summarizePdf(file, options?)`
Extracts text from a PDF and returns an AI-generated summary.
```ts
import { summarizePdf } from "nano-ai-pdf";
async function runSummarization(file) {
try {
const result = await summarizePdf(file, {
type: "key-points", // 'tldr' | 'headline' | 'teaser'
format: "markdown", // or 'plain-text'
length: "medium", // 'short' | 'long'
context: "Technical report",
});
console.log("Summary:", result.summary);
console.log("Compression:", result.compressionRatio + "%");
} catch (err) {
console.error("Error summarizing PDF:", err);
}
}
```
**Returns:**
```ts
{
summary: string;
originalText: string;
originalLength: number;
summaryLength: number;
compressionRatio: number;
processingTime: number;
config: PdfSummarizerOptions;
}
```
### 2️⃣ `summarizePdfStreaming(file, options?)`
Like `summarizePdf` but yields chunks of the summary as they arrive.
```ts
import { summarizePdfStreaming } from "nano-ai-pdf";
async function runStreaming(file) {
const result = await summarizePdfStreaming(file, {
type: "tldr",
format: "plain-text",
length: "medium",
});
let summaryText = "";
for await (const chunk of result.summaryStream) {
summaryText += chunk;
console.log("Chunk:", chunk);
}
console.log("Final summary:", summaryText);
}
```
### 3️⃣ `isSummarizerSupported()`
Checks if Chrome’s Summarizer API exists.
```ts
import { isSummarizerSupported } from "nano-ai-pdf";
if (!isSummarizerSupported()) {
console.error("Chrome Summarizer API not supported in this browser.");
}
```
### 4️⃣ `checkModelAvailability()`
Checks if the AI model is ready, needs download, or is unavailable.
```ts
import { checkModelAvailability } from "nano-ai-pdf";
(async () => {
const status = await checkModelAvailability();
console.log("Model status:", status);
})();
```
Returns one of:
`"available" | "downloadable" | "downloading" | "unavailable"`
### 5️⃣ `getDownloadProgress()`
Returns the **last known** download % (0-100).
```ts
import { getDownloadProgress } from "nano-ai-pdf";
// Polling example
setInterval(() => {
console.log("Current download progress:", getDownloadProgress() + "%");
}, 500);
```
### 6️⃣ `onDownloadProgressUpdate(callback)`
Registers a callback to receive **real-time** download updates.
```ts
import { onDownloadProgressUpdate } from "nano-ai-pdf";
onDownloadProgressUpdate((progress) => {
console.log("Progress update:", progress + "%");
});
```
## 🚨 Error Handling
Functions throw `PdfSummarizerError` with a `.code` property.
| Code | Meaning |
| :--------------------------- | :------------------------------ |
| `NO_FILE` | No file provided |
| `INVALID_FILE_TYPE` | File is not PDF |
| `FILE_TOO_LARGE` | Exceeds allowed size |
| `EMPTY_FILE` | File has zero bytes |
| `EXTRACTION_FAILED` | Text extraction failed |
| `INSUFFICIENT_TEXT` | Not enough text content |
| `API_NOT_SUPPORTED` | API not available |
| `USER_ACTIVATION_REQUIRED` | Not called from a user gesture |
| `MODEL_UNAVAILABLE` | AI model unavailable |
| `SUMMARIZER_CREATION_FAILED` | Summarizer could not be created |
| `SUMMARIZATION_FAILED` | Summary generation failed |
## 🖥 Example Minimal React App
```jsx
import { useState } from "react";
import {
summarizePdf,
isSummarizerSupported,
checkModelAvailability,
onDownloadProgressUpdate,
} from "nano-ai-pdf";
export default function App() {
const [summary, setSummary] = useState("");
const [progress, setProgress] = useState(0);
onDownloadProgressUpdate((p) => setProgress(p));
const handleClick = async (e) => {
e.preventDefault();
if (!isSummarizerSupported()) {
alert("Not supported in this browser!");
return;
}
const availability = await checkModelAvailability();
if (availability === "unavailable") {
alert("Model unavailable - check Chrome setup.");
return;
}
const file = document.getElementById("file").files[0];
if (!file) return alert("Pick a PDF first");
const result = await summarizePdf(file, { type: "tldr" });
setSummary(result.summary);
};
return (
<div>
<input id="file" type="file" accept="application/pdf" />
<button onClick={handleClick}>Summarize PDF</button>
<p>Download Progress: {progress}%</p>
<pre>{summary}</pre>
</div>
);
}
```