@kreuzberg/node 4.2.15 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,199 +0,0 @@
1
- // typescript/ocr/guten-ocr.ts
2
- var GutenOcrBackend = class {
3
- ocr = null;
4
- ocrModule = null;
5
- options;
6
- /**
7
- * Create a new Guten OCR backend.
8
- *
9
- * @param options - Optional configuration for Guten OCR
10
- * @param options.models - Custom model paths (default: uses bundled models)
11
- * @param options.isDebug - Enable debug mode (default: false)
12
- * @param options.debugOutputDir - Directory for debug output (default: undefined)
13
- * @param options.onnxOptions - Custom ONNX Runtime options (default: undefined)
14
- *
15
- * @example
16
- * ```typescript
17
- * // Default configuration
18
- * const backend = new GutenOcrBackend();
19
- *
20
- * // With debug enabled
21
- * const debugBackend = new GutenOcrBackend({
22
- * isDebug: true,
23
- * debugOutputDir: './ocr_debug'
24
- * });
25
- * ```
26
- */
27
- constructor(options) {
28
- if (options !== void 0) {
29
- this.options = options;
30
- }
31
- }
32
- /**
33
- * Get the backend name.
34
- *
35
- * @returns Backend name ("guten-ocr")
36
- */
37
- name() {
38
- return "guten-ocr";
39
- }
40
- /**
41
- * Get list of supported language codes.
42
- *
43
- * Guten OCR supports multiple languages depending on the model configuration.
44
- * The default models support English and Chinese.
45
- *
46
- * @returns Array of ISO 639-1/2 language codes
47
- */
48
- supportedLanguages() {
49
- return ["en", "eng", "ch_sim", "ch_tra", "chinese"];
50
- }
51
- /**
52
- * Initialize the OCR backend.
53
- *
54
- * This method loads the Guten OCR module and creates an OCR instance.
55
- * Call this before using processImage().
56
- *
57
- * @throws {Error} If @gutenye/ocr-node is not installed
58
- * @throws {Error} If OCR initialization fails
59
- *
60
- * @example
61
- * ```typescript
62
- * const backend = new GutenOcrBackend();
63
- * await backend.initialize();
64
- * ```
65
- */
66
- async initialize() {
67
- if (this.ocr !== null) {
68
- return;
69
- }
70
- try {
71
- this.ocrModule = await import("@gutenye/ocr-node").then((m) => m.default || m);
72
- } catch (e) {
73
- const error = e;
74
- throw new Error(
75
- `Guten OCR support requires the '@gutenye/ocr-node' package. Install with: npm install @gutenye/ocr-node. Error: ${error.message}`
76
- );
77
- }
78
- try {
79
- this.ocr = await this.ocrModule?.create(this.options) ?? null;
80
- } catch (e) {
81
- const error = e;
82
- throw new Error(`Failed to initialize Guten OCR: ${error.message}`);
83
- }
84
- }
85
- /**
86
- * Shutdown the backend and release resources.
87
- *
88
- * This method cleans up all resources associated with the backend,
89
- * including the GutenOCR instance and module references.
90
- *
91
- * @example
92
- * ```typescript
93
- * const backend = new GutenOcrBackend();
94
- * await backend.initialize();
95
- * // ... use backend ...
96
- * await backend.shutdown();
97
- * ```
98
- */
99
- async shutdown() {
100
- if (this.ocr !== null) {
101
- this.ocr = null;
102
- }
103
- if (this.ocrModule !== null) {
104
- this.ocrModule = null;
105
- }
106
- }
107
- /**
108
- * Process image bytes and extract text using Guten OCR.
109
- *
110
- * This method:
111
- * 1. Decodes the image using sharp (if pixel data is needed) or passes bytes directly
112
- * 2. Runs OCR detection to find text regions
113
- * 3. Runs OCR recognition on each text region
114
- * 4. Returns extracted text with metadata
115
- *
116
- * @param imageBytes - Raw image data (PNG, JPEG, TIFF, etc.)
117
- * @param language - Language code (must be in supportedLanguages())
118
- * @returns Promise resolving to OCR result with content and metadata
119
- *
120
- * @throws {Error} If backend is not initialized
121
- * @throws {Error} If OCR processing fails
122
- *
123
- * @example
124
- * ```typescript
125
- * import { readFile } from 'fs/promises';
126
- *
127
- * const backend = new GutenOcrBackend();
128
- * await backend.initialize();
129
- *
130
- * const imageBytes = await readFile('scanned.png');
131
- * const result = await backend.processImage(imageBytes, 'en');
132
- * console.log(result.content);
133
- * console.log(result.metadata.confidence);
134
- * ```
135
- */
136
- async processImage(imageBytes, language) {
137
- if (this.ocr === null) {
138
- await this.initialize();
139
- }
140
- if (this.ocr === null) {
141
- throw new Error("Guten OCR backend failed to initialize");
142
- }
143
- try {
144
- const buffer = typeof imageBytes === "string" ? Buffer.from(imageBytes, "base64") : Buffer.from(imageBytes);
145
- const debugEnv = process.env["KREUZBERG_DEBUG_GUTEN"];
146
- if (debugEnv === "1") {
147
- const header = Array.from(buffer.subarray(0, 8));
148
- console.log("[Guten OCR] Debug input header:", header);
149
- console.log(
150
- "[Guten OCR] Buffer?",
151
- Buffer.isBuffer(buffer),
152
- "constructor",
153
- imageBytes?.constructor?.name,
154
- "length",
155
- buffer.length,
156
- "type",
157
- typeof imageBytes
158
- );
159
- }
160
- let width = 0;
161
- let height = 0;
162
- try {
163
- const sharpModule = await import("sharp");
164
- const sharp = sharpModule.default || sharpModule;
165
- const image = sharp(buffer);
166
- const metadata = await image.metadata();
167
- const metadataRecord = metadata;
168
- width = metadataRecord["width"] ?? 0;
169
- height = metadataRecord["height"] ?? 0;
170
- } catch (metadataError) {
171
- const error = metadataError;
172
- console.warn(`[Guten OCR] Unable to read image metadata via sharp: ${error.message}`);
173
- }
174
- const result = await this.ocr.detect(buffer);
175
- const textLines = result.map((line) => line.text);
176
- const content = textLines.join("\n");
177
- const avgConfidence = result.length > 0 ? result.reduce((sum, line) => sum + line.mean, 0) / result.length : 0;
178
- return {
179
- content,
180
- mime_type: "text/plain",
181
- metadata: {
182
- width,
183
- height,
184
- confidence: avgConfidence,
185
- text_regions: result.length,
186
- language
187
- },
188
- tables: []
189
- };
190
- } catch (e) {
191
- const error = e;
192
- throw new Error(`Guten OCR processing failed: ${error.message}`);
193
- }
194
- }
195
- };
196
- export {
197
- GutenOcrBackend
198
- };
199
- //# sourceMappingURL=guten-ocr.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../typescript/ocr/guten-ocr.ts"],"sourcesContent":["/**\n * Guten OCR backend for document OCR processing.\n *\n * This module provides integration with @gutenye/ocr-node for optical character recognition.\n * Guten OCR uses PaddleOCR models via ONNX Runtime for high-performance text extraction.\n *\n * @module ocr/guten-ocr\n */\n\nimport type { OcrBackendProtocol } from \"../types.js\";\n\n/**\n * Text line detected by Guten OCR.\n */\ninterface TextLine {\n\ttext: string;\n\tmean: number;\n\tbox: number[][];\n}\n\n/**\n * Guten OCR instance interface.\n */\ninterface GutenOcr {\n\tdetect(imagePath: string | Buffer, options?: { onnxOptions?: unknown }): Promise<TextLine[]>;\n}\n\n/**\n * Guten OCR module interface.\n */\ninterface GutenOcrModule {\n\tcreate(options?: {\n\t\tmodels?: {\n\t\t\tdetectionPath: string;\n\t\t\trecognitionPath: string;\n\t\t\tdictionaryPath: string;\n\t\t};\n\t\tisDebug?: boolean;\n\t\tdebugOutputDir?: string;\n\t\tonnxOptions?: unknown;\n\t}): Promise<GutenOcr>;\n}\n\n/**\n * Guten OCR backend for OCR processing.\n *\n * This backend uses @gutenye/ocr-node for text extraction from images.\n * It uses PaddleOCR models via ONNX Runtime for efficient processing.\n *\n * ## Installation\n *\n * Install the optional dependency:\n * ```bash\n * npm install @gutenye/ocr-node\n * # or\n * pnpm add @gutenye/ocr-node\n * # or\n * bun add @gutenye/ocr-node\n * ```\n *\n * ## Usage\n *\n * ```typescript\n * import { GutenOcrBackend } from '@kreuzberg/node/ocr/guten-ocr';\n * import { registerOcrBackend, extractFile } from '@kreuzberg/node';\n *\n * // Create and register the backend\n * const backend = new GutenOcrBackend();\n * await backend.initialize();\n * registerOcrBackend(backend);\n *\n * // Extract with OCR enabled\n * const result = await extractFile('scanned.pdf', null, {\n * ocr: { backend: 'guten-ocr', language: 'en' },\n * });\n * console.log(result.content);\n * ```\n *\n * ## Supported Languages\n *\n * Guten OCR supports multiple languages via different model configurations.\n * The default models support English (\"en\") and Chinese (\"ch_sim\", \"ch_tra\").\n *\n * @example\n * ```typescript\n * // Basic usage with default settings\n * const backend = new GutenOcrBackend();\n * await backend.initialize();\n *\n * // Custom model configuration\n * const customBackend = new GutenOcrBackend({\n * models: {\n * detectionPath: './models/detection.onnx',\n * recognitionPath: './models/recognition.onnx',\n * dictionaryPath: './models/dict.txt'\n * }\n * });\n * await customBackend.initialize();\n * ```\n */\nexport class GutenOcrBackend implements OcrBackendProtocol {\n\tprivate ocr: GutenOcr | null = null;\n\tprivate ocrModule: GutenOcrModule | null = null;\n\tprivate options?: {\n\t\tmodels?: {\n\t\t\tdetectionPath: string;\n\t\t\trecognitionPath: string;\n\t\t\tdictionaryPath: string;\n\t\t};\n\t\tisDebug?: boolean;\n\t\tdebugOutputDir?: string;\n\t\tonnxOptions?: unknown;\n\t};\n\n\t/**\n\t * Create a new Guten OCR backend.\n\t *\n\t * @param options - Optional configuration for Guten OCR\n\t * @param options.models - Custom model paths (default: uses bundled models)\n\t * @param options.isDebug - Enable debug mode (default: false)\n\t * @param options.debugOutputDir - Directory for debug output (default: undefined)\n\t * @param options.onnxOptions - Custom ONNX Runtime options (default: undefined)\n\t *\n\t * @example\n\t * ```typescript\n\t * // Default configuration\n\t * const backend = new GutenOcrBackend();\n\t *\n\t * // With debug enabled\n\t * const debugBackend = new GutenOcrBackend({\n\t * isDebug: true,\n\t * debugOutputDir: './ocr_debug'\n\t * });\n\t * ```\n\t */\n\tconstructor(options?: {\n\t\tmodels?: {\n\t\t\tdetectionPath: string;\n\t\t\trecognitionPath: string;\n\t\t\tdictionaryPath: string;\n\t\t};\n\t\tisDebug?: boolean;\n\t\tdebugOutputDir?: string;\n\t\tonnxOptions?: unknown;\n\t}) {\n\t\tif (options !== undefined) {\n\t\t\tthis.options = options;\n\t\t}\n\t}\n\n\t/**\n\t * Get the backend name.\n\t *\n\t * @returns Backend name (\"guten-ocr\")\n\t */\n\tname(): string {\n\t\treturn \"guten-ocr\";\n\t}\n\n\t/**\n\t * Get list of supported language codes.\n\t *\n\t * Guten OCR supports multiple languages depending on the model configuration.\n\t * The default models support English and Chinese.\n\t *\n\t * @returns Array of ISO 639-1/2 language codes\n\t */\n\tsupportedLanguages(): string[] {\n\t\treturn [\"en\", \"eng\", \"ch_sim\", \"ch_tra\", \"chinese\"];\n\t}\n\n\t/**\n\t * Initialize the OCR backend.\n\t *\n\t * This method loads the Guten OCR module and creates an OCR instance.\n\t * Call this before using processImage().\n\t *\n\t * @throws {Error} If @gutenye/ocr-node is not installed\n\t * @throws {Error} If OCR initialization fails\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new GutenOcrBackend();\n\t * await backend.initialize();\n\t * ```\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.ocr !== null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.ocrModule = await import(\"@gutenye/ocr-node\").then((m) => (m.default || m) as GutenOcrModule);\n\t\t} catch (e) {\n\t\t\tconst error = e as Error;\n\t\t\tthrow new Error(\n\t\t\t\t`Guten OCR support requires the '@gutenye/ocr-node' package. ` +\n\t\t\t\t\t`Install with: npm install @gutenye/ocr-node. ` +\n\t\t\t\t\t`Error: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tthis.ocr = (await this.ocrModule?.create(this.options)) ?? null;\n\t\t} catch (e) {\n\t\t\tconst error = e as Error;\n\t\t\tthrow new Error(`Failed to initialize Guten OCR: ${error.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Shutdown the backend and release resources.\n\t *\n\t * This method cleans up all resources associated with the backend,\n\t * including the GutenOCR instance and module references.\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new GutenOcrBackend();\n\t * await backend.initialize();\n\t * // ... use backend ...\n\t * await backend.shutdown();\n\t * ```\n\t */\n\tasync shutdown(): Promise<void> {\n\t\tif (this.ocr !== null) {\n\t\t\tthis.ocr = null;\n\t\t}\n\n\t\tif (this.ocrModule !== null) {\n\t\t\tthis.ocrModule = null;\n\t\t}\n\t}\n\n\t/**\n\t * Process image bytes and extract text using Guten OCR.\n\t *\n\t * This method:\n\t * 1. Decodes the image using sharp (if pixel data is needed) or passes bytes directly\n\t * 2. Runs OCR detection to find text regions\n\t * 3. Runs OCR recognition on each text region\n\t * 4. Returns extracted text with metadata\n\t *\n\t * @param imageBytes - Raw image data (PNG, JPEG, TIFF, etc.)\n\t * @param language - Language code (must be in supportedLanguages())\n\t * @returns Promise resolving to OCR result with content and metadata\n\t *\n\t * @throws {Error} If backend is not initialized\n\t * @throws {Error} If OCR processing fails\n\t *\n\t * @example\n\t * ```typescript\n\t * import { readFile } from 'fs/promises';\n\t *\n\t * const backend = new GutenOcrBackend();\n\t * await backend.initialize();\n\t *\n\t * const imageBytes = await readFile('scanned.png');\n\t * const result = await backend.processImage(imageBytes, 'en');\n\t * console.log(result.content);\n\t * console.log(result.metadata.confidence);\n\t * ```\n\t */\n\tasync processImage(\n\t\timageBytes: Uint8Array | string,\n\t\tlanguage: string,\n\t): Promise<{\n\t\tcontent: string;\n\t\tmime_type: string;\n\t\tmetadata: {\n\t\t\twidth: number;\n\t\t\theight: number;\n\t\t\tconfidence: number;\n\t\t\ttext_regions: number;\n\t\t\tlanguage: string;\n\t\t};\n\t\ttables: never[];\n\t}> {\n\t\tif (this.ocr === null) {\n\t\t\tawait this.initialize();\n\t\t}\n\n\t\tif (this.ocr === null) {\n\t\t\tthrow new Error(\"Guten OCR backend failed to initialize\");\n\t\t}\n\n\t\ttry {\n\t\t\tconst buffer = typeof imageBytes === \"string\" ? Buffer.from(imageBytes, \"base64\") : Buffer.from(imageBytes);\n\n\t\t\t// biome-ignore lint/complexity/useLiteralKeys: required for strict TypeScript noUncheckedIndexedAccess\n\t\t\tconst debugEnv = process.env[\"KREUZBERG_DEBUG_GUTEN\"];\n\t\t\tif (debugEnv === \"1\") {\n\t\t\t\tconst header = Array.from(buffer.subarray(0, 8));\n\t\t\t\tconsole.log(\"[Guten OCR] Debug input header:\", header);\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"[Guten OCR] Buffer?\",\n\t\t\t\t\tBuffer.isBuffer(buffer),\n\t\t\t\t\t\"constructor\",\n\t\t\t\t\timageBytes?.constructor?.name,\n\t\t\t\t\t\"length\",\n\t\t\t\t\tbuffer.length,\n\t\t\t\t\t\"type\",\n\t\t\t\t\ttypeof imageBytes,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet width = 0;\n\t\t\tlet height = 0;\n\n\t\t\ttry {\n\t\t\t\tconst sharpModule = await import(\"sharp\");\n\t\t\t\tconst sharp = (sharpModule as unknown as { default?: unknown }).default || sharpModule;\n\t\t\t\tconst image = (sharp as (buffer: Buffer) => { metadata: () => Promise<Record<string, unknown>> })(buffer);\n\t\t\t\tconst metadata = await image.metadata();\n\t\t\t\tconst metadataRecord = metadata as Record<string, unknown>;\n\t\t\t\t// biome-ignore lint/complexity/useLiteralKeys: TypeScript TS4111 requires bracket notation for index signature properties\n\t\t\t\twidth = (metadataRecord[\"width\"] as number | undefined) ?? 0;\n\t\t\t\t// biome-ignore lint/complexity/useLiteralKeys: TypeScript TS4111 requires bracket notation for index signature properties\n\t\t\t\theight = (metadataRecord[\"height\"] as number | undefined) ?? 0;\n\t\t\t} catch (metadataError) {\n\t\t\t\tconst error = metadataError as Error;\n\t\t\t\tconsole.warn(`[Guten OCR] Unable to read image metadata via sharp: ${error.message}`);\n\t\t\t}\n\n\t\t\tconst result = await this.ocr.detect(buffer);\n\n\t\t\tconst textLines = result.map((line) => line.text);\n\t\t\tconst content = textLines.join(\"\\n\");\n\n\t\t\tconst avgConfidence = result.length > 0 ? result.reduce((sum, line) => sum + line.mean, 0) / result.length : 0;\n\n\t\t\treturn {\n\t\t\t\tcontent,\n\t\t\t\tmime_type: \"text/plain\",\n\t\t\t\tmetadata: {\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tconfidence: avgConfidence,\n\t\t\t\t\ttext_regions: result.length,\n\t\t\t\t\tlanguage,\n\t\t\t\t},\n\t\t\t\ttables: [],\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconst error = e as Error;\n\t\t\tthrow new Error(`Guten OCR processing failed: ${error.message}`);\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}