@heripo/document-processor 0.1.21 → 0.1.23
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.
- package/README.ko.md +81 -4
- package/README.md +81 -4
- package/dist/index.cjs +48 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -69
- package/dist/index.d.ts +96 -69
- package/dist/index.js +48 -35
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.ko.md
CHANGED
|
@@ -75,7 +75,7 @@ const processor = new DocumentProcessor({
|
|
|
75
75
|
const { document, usage } = await processor.process(
|
|
76
76
|
doclingDocument, // PDF 파서 출력
|
|
77
77
|
'report-001', // 리포트 ID
|
|
78
|
-
|
|
78
|
+
artifactDir, // 이미지/페이지 등 parser 산출물이 있는 디렉토리
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
// 결과 사용
|
|
@@ -111,13 +111,81 @@ const processor = new DocumentProcessor({
|
|
|
111
111
|
|
|
112
112
|
// 재시도 설정
|
|
113
113
|
maxRetries: 3,
|
|
114
|
+
maxValidationRetries: 3,
|
|
114
115
|
enableFallbackRetry: true, // fallback 모델로 자동 재시도 (기본값: false)
|
|
115
116
|
});
|
|
116
117
|
|
|
117
118
|
const { document, usage } = await processor.process(
|
|
118
119
|
doclingDocument,
|
|
119
120
|
'report-001',
|
|
120
|
-
|
|
121
|
+
artifactDir,
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 수동 페이지 범위 매핑
|
|
126
|
+
|
|
127
|
+
페이지 범위 매핑을 이미 검수했다면 `process()`의 네 번째 인자로 전달해
|
|
128
|
+
PageRangeParser 자동 실행을 건너뛸 수 있습니다. 전달한 매핑은 추가 후처리 없이
|
|
129
|
+
그대로 사용됩니다.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import type { PageRange } from '@heripo/model';
|
|
133
|
+
|
|
134
|
+
const pageRangeMap: Record<number, PageRange> = {
|
|
135
|
+
1: { startPageNo: 0, endPageNo: 0 },
|
|
136
|
+
2: { startPageNo: 1, endPageNo: 1 },
|
|
137
|
+
3: { startPageNo: 2, endPageNo: 3 },
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const { document, usage } = await processor.process(
|
|
141
|
+
doclingDocument,
|
|
142
|
+
'report-001',
|
|
143
|
+
artifactDir,
|
|
144
|
+
{ pageRangeMap },
|
|
145
|
+
);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 수동 TOC 항목
|
|
149
|
+
|
|
150
|
+
목차를 이미 검수했다면 `process()`의 네 번째 인자로 `tocEntries`를 전달해
|
|
151
|
+
자동 TOC 추출을 건너뛸 수 있습니다. 전달한 항목은 추가 추출이나 검증 없이
|
|
152
|
+
그대로 사용됩니다.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import type { TocEntry } from '@heripo/document-processor';
|
|
156
|
+
|
|
157
|
+
const tocEntries: TocEntry[] = [
|
|
158
|
+
{
|
|
159
|
+
title: '제1장 조사 개요',
|
|
160
|
+
level: 1,
|
|
161
|
+
pageNo: 1,
|
|
162
|
+
children: [
|
|
163
|
+
{
|
|
164
|
+
title: '1. 조사 경위',
|
|
165
|
+
level: 2,
|
|
166
|
+
pageNo: 3,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const { document, usage } = await processor.process(
|
|
173
|
+
doclingDocument,
|
|
174
|
+
'report-001',
|
|
175
|
+
artifactDir,
|
|
176
|
+
{ tocEntries },
|
|
177
|
+
);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
수동 페이지 범위 매핑과 TOC 항목을 함께 전달하면 두 자동 단계를 모두
|
|
181
|
+
건너뜁니다.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const { document, usage } = await processor.process(
|
|
185
|
+
doclingDocument,
|
|
186
|
+
'report-001',
|
|
187
|
+
artifactDir,
|
|
188
|
+
{ pageRangeMap, tocEntries },
|
|
121
189
|
);
|
|
122
190
|
```
|
|
123
191
|
|
|
@@ -206,6 +274,7 @@ interface DocumentProcessorOptions {
|
|
|
206
274
|
|
|
207
275
|
// 재시도 설정
|
|
208
276
|
maxRetries?: number; // LLM API 재시도 횟수 (기본값: 3)
|
|
277
|
+
maxValidationRetries?: number; // TOC 검증 보정 재시도 횟수 (기본값: 3)
|
|
209
278
|
enableFallbackRetry?: boolean; // Fallback 재시도 활성화 (기본값: false)
|
|
210
279
|
|
|
211
280
|
// 고급 옵션
|
|
@@ -216,15 +285,23 @@ interface DocumentProcessorOptions {
|
|
|
216
285
|
|
|
217
286
|
#### 메서드
|
|
218
287
|
|
|
219
|
-
##### `process(doclingDoc, reportId,
|
|
288
|
+
##### `process(doclingDoc, reportId, artifactDir, processOptions?): Promise<DocumentProcessResult>`
|
|
220
289
|
|
|
221
290
|
DoclingDocument를 ProcessedDocument로 변환합니다.
|
|
222
291
|
|
|
292
|
+
```typescript
|
|
293
|
+
interface DocumentProcessorProcessOptions {
|
|
294
|
+
pageRangeMap?: Record<number, PageRange>;
|
|
295
|
+
tocEntries?: TocEntry[];
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
223
299
|
**파라미터:**
|
|
224
300
|
|
|
225
301
|
- `doclingDoc` (DoclingDocument): PDF 파서의 출력
|
|
226
302
|
- `reportId` (string): 리포트 ID
|
|
227
|
-
- `
|
|
303
|
+
- `artifactDir` (string): `images/`, `pages/`, `result.json` 같은 parser 산출물이 들어 있는 디렉토리
|
|
304
|
+
- `processOptions` (DocumentProcessorProcessOptions, 선택): 문서별 처리 입력값. `pageRangeMap`이 제공되면 자동 페이지 범위 파싱을 건너뜁니다. `tocEntries`가 제공되면 자동 TOC 추출을 건너뜁니다.
|
|
228
305
|
|
|
229
306
|
**반환값:**
|
|
230
307
|
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ const processor = new DocumentProcessor({
|
|
|
75
75
|
const { document, usage } = await processor.process(
|
|
76
76
|
doclingDocument, // PDF parser output
|
|
77
77
|
'report-001', // Report ID
|
|
78
|
-
|
|
78
|
+
artifactDir, // Directory containing parser artifacts such as images/pages
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
// Use results
|
|
@@ -111,13 +111,81 @@ const processor = new DocumentProcessor({
|
|
|
111
111
|
|
|
112
112
|
// Retry settings
|
|
113
113
|
maxRetries: 3,
|
|
114
|
+
maxValidationRetries: 3,
|
|
114
115
|
enableFallbackRetry: true, // Automatic retry with fallback model (default: false)
|
|
115
116
|
});
|
|
116
117
|
|
|
117
118
|
const { document, usage } = await processor.process(
|
|
118
119
|
doclingDocument,
|
|
119
120
|
'report-001',
|
|
120
|
-
|
|
121
|
+
artifactDir,
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Manual Page Range Map
|
|
126
|
+
|
|
127
|
+
If page range mapping has already been reviewed, pass it as the fourth
|
|
128
|
+
`process()` argument to skip automatic PageRangeParser execution. The provided
|
|
129
|
+
map is used as-is without additional post-processing.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import type { PageRange } from '@heripo/model';
|
|
133
|
+
|
|
134
|
+
const pageRangeMap: Record<number, PageRange> = {
|
|
135
|
+
1: { startPageNo: 0, endPageNo: 0 },
|
|
136
|
+
2: { startPageNo: 1, endPageNo: 1 },
|
|
137
|
+
3: { startPageNo: 2, endPageNo: 3 },
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const { document, usage } = await processor.process(
|
|
141
|
+
doclingDocument,
|
|
142
|
+
'report-001',
|
|
143
|
+
artifactDir,
|
|
144
|
+
{ pageRangeMap },
|
|
145
|
+
);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Manual TOC Entries
|
|
149
|
+
|
|
150
|
+
If the table of contents has already been reviewed, pass `tocEntries` as the
|
|
151
|
+
fourth `process()` argument to skip automatic TOC extraction. The provided
|
|
152
|
+
entries are used as-is without additional extraction or validation.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import type { TocEntry } from '@heripo/document-processor';
|
|
156
|
+
|
|
157
|
+
const tocEntries: TocEntry[] = [
|
|
158
|
+
{
|
|
159
|
+
title: 'Chapter 1. Overview',
|
|
160
|
+
level: 1,
|
|
161
|
+
pageNo: 1,
|
|
162
|
+
children: [
|
|
163
|
+
{
|
|
164
|
+
title: '1. Background',
|
|
165
|
+
level: 2,
|
|
166
|
+
pageNo: 3,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const { document, usage } = await processor.process(
|
|
173
|
+
doclingDocument,
|
|
174
|
+
'report-001',
|
|
175
|
+
artifactDir,
|
|
176
|
+
{ tocEntries },
|
|
177
|
+
);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Manual page range maps and TOC entries can be provided together to skip both
|
|
181
|
+
automatic stages.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const { document, usage } = await processor.process(
|
|
185
|
+
doclingDocument,
|
|
186
|
+
'report-001',
|
|
187
|
+
artifactDir,
|
|
188
|
+
{ pageRangeMap, tocEntries },
|
|
121
189
|
);
|
|
122
190
|
```
|
|
123
191
|
|
|
@@ -206,6 +274,7 @@ interface DocumentProcessorOptions {
|
|
|
206
274
|
|
|
207
275
|
// Retry settings
|
|
208
276
|
maxRetries?: number; // LLM API retry count (default: 3)
|
|
277
|
+
maxValidationRetries?: number; // TOC validation correction retry count (default: 3)
|
|
209
278
|
enableFallbackRetry?: boolean; // Enable fallback retry (default: false)
|
|
210
279
|
|
|
211
280
|
// Advanced options
|
|
@@ -216,15 +285,23 @@ interface DocumentProcessorOptions {
|
|
|
216
285
|
|
|
217
286
|
#### Methods
|
|
218
287
|
|
|
219
|
-
##### `process(doclingDoc, reportId,
|
|
288
|
+
##### `process(doclingDoc, reportId, artifactDir, processOptions?): Promise<DocumentProcessResult>`
|
|
220
289
|
|
|
221
290
|
Transforms DoclingDocument into ProcessedDocument.
|
|
222
291
|
|
|
292
|
+
```typescript
|
|
293
|
+
interface DocumentProcessorProcessOptions {
|
|
294
|
+
pageRangeMap?: Record<number, PageRange>;
|
|
295
|
+
tocEntries?: TocEntry[];
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
223
299
|
**Parameters:**
|
|
224
300
|
|
|
225
301
|
- `doclingDoc` (DoclingDocument): PDF parser output
|
|
226
302
|
- `reportId` (string): Report ID
|
|
227
|
-
- `
|
|
303
|
+
- `artifactDir` (string): Artifact directory containing parser outputs such as `images/`, `pages/`, and `result.json`
|
|
304
|
+
- `processOptions` (DocumentProcessorProcessOptions, optional): Per-document processing inputs. When `pageRangeMap` is provided, automatic page range parsing is skipped. When `tocEntries` is provided, automatic TOC extraction is skipped.
|
|
228
305
|
|
|
229
306
|
**Returns:**
|
|
230
307
|
|
package/dist/index.cjs
CHANGED
|
@@ -1284,12 +1284,12 @@ var ResourceConverter = class {
|
|
|
1284
1284
|
*
|
|
1285
1285
|
* Runs image and table conversions in parallel, then footnotes synchronously.
|
|
1286
1286
|
*/
|
|
1287
|
-
async convertAll(doclingDoc,
|
|
1287
|
+
async convertAll(doclingDoc, artifactDir) {
|
|
1288
1288
|
this.logger.info(
|
|
1289
1289
|
"[ResourceConverter] Converting images, tables, and footnotes..."
|
|
1290
1290
|
);
|
|
1291
1291
|
const [images, tables] = await Promise.all([
|
|
1292
|
-
this.convertImages(doclingDoc,
|
|
1292
|
+
this.convertImages(doclingDoc, artifactDir),
|
|
1293
1293
|
this.convertTables(doclingDoc)
|
|
1294
1294
|
]);
|
|
1295
1295
|
const footnotes = this.convertFootnotes(doclingDoc);
|
|
@@ -1301,7 +1301,7 @@ var ResourceConverter = class {
|
|
|
1301
1301
|
/**
|
|
1302
1302
|
* Convert images from DoclingDocument to ProcessedImage[]
|
|
1303
1303
|
*/
|
|
1304
|
-
async convertImages(doclingDoc,
|
|
1304
|
+
async convertImages(doclingDoc, artifactDir) {
|
|
1305
1305
|
this.logger.info(
|
|
1306
1306
|
`[ResourceConverter] Converting ${doclingDoc.pictures.length} images...`
|
|
1307
1307
|
);
|
|
@@ -1311,7 +1311,7 @@ var ResourceConverter = class {
|
|
|
1311
1311
|
const images = doclingDoc.pictures.map(
|
|
1312
1312
|
(picture, index) => ({
|
|
1313
1313
|
id: this.idGenerator.generateImageId(),
|
|
1314
|
-
path: `${
|
|
1314
|
+
path: `${artifactDir}/images/image_${index}.png`,
|
|
1315
1315
|
pdfPageNo: picture.prov?.[0]?.page_no ?? 0
|
|
1316
1316
|
})
|
|
1317
1317
|
);
|
|
@@ -2132,7 +2132,7 @@ var TextLLMComponent = class extends BaseLLMComponent {
|
|
|
2132
2132
|
};
|
|
2133
2133
|
|
|
2134
2134
|
// src/extractors/toc-extractor.ts
|
|
2135
|
-
var
|
|
2135
|
+
var DEFAULT_MAX_VALIDATION_RETRIES = 3;
|
|
2136
2136
|
var VALIDATION_CODE_DESCRIPTIONS = {
|
|
2137
2137
|
V001: "Page numbers must be in non-decreasing order within the same level. A decrease usually means a hierarchy or page number error.",
|
|
2138
2138
|
V002: "Page number is out of valid range (must be >= 1 and <= total pages).",
|
|
@@ -2165,6 +2165,7 @@ var TocResponseSchema = import_zod.z.object({
|
|
|
2165
2165
|
var TocExtractor = class extends TextLLMComponent {
|
|
2166
2166
|
validationOptions;
|
|
2167
2167
|
skipValidation;
|
|
2168
|
+
maxValidationRetries;
|
|
2168
2169
|
constructor(logger, model, options, fallbackModel, abortSignal) {
|
|
2169
2170
|
super(
|
|
2170
2171
|
logger,
|
|
@@ -2175,11 +2176,12 @@ var TocExtractor = class extends TextLLMComponent {
|
|
|
2175
2176
|
);
|
|
2176
2177
|
this.validationOptions = options?.validation;
|
|
2177
2178
|
this.skipValidation = options?.skipValidation ?? false;
|
|
2179
|
+
this.maxValidationRetries = options?.maxValidationRetries ?? DEFAULT_MAX_VALIDATION_RETRIES;
|
|
2178
2180
|
}
|
|
2179
2181
|
/**
|
|
2180
2182
|
* Extract TOC structure from Markdown
|
|
2181
2183
|
*
|
|
2182
|
-
* When validation fails, retries with correction feedback up to
|
|
2184
|
+
* When validation fails, retries with correction feedback up to maxValidationRetries times.
|
|
2183
2185
|
*
|
|
2184
2186
|
* @param markdown - Markdown representation of TOC area
|
|
2185
2187
|
* @param validationOverrides - Optional overrides for validation options (merged with constructor options)
|
|
@@ -2209,10 +2211,10 @@ var TocExtractor = class extends TextLLMComponent {
|
|
|
2209
2211
|
entries,
|
|
2210
2212
|
validationOverrides
|
|
2211
2213
|
);
|
|
2212
|
-
for (let attempt = 1; attempt <=
|
|
2214
|
+
for (let attempt = 1; attempt <= this.maxValidationRetries && validationError !== null; attempt++) {
|
|
2213
2215
|
this.log(
|
|
2214
2216
|
"warn",
|
|
2215
|
-
`Validation failed (attempt ${attempt}/${
|
|
2217
|
+
`Validation failed (attempt ${attempt}/${this.maxValidationRetries}), retrying with correction feedback`
|
|
2216
2218
|
);
|
|
2217
2219
|
const correctionPrompt = this.buildCorrectionPrompt(
|
|
2218
2220
|
markdown,
|
|
@@ -2235,7 +2237,7 @@ var TocExtractor = class extends TextLLMComponent {
|
|
|
2235
2237
|
if (validationError !== null) {
|
|
2236
2238
|
this.log(
|
|
2237
2239
|
"error",
|
|
2238
|
-
`Validation failed after ${
|
|
2240
|
+
`Validation failed after ${this.maxValidationRetries} retries:
|
|
2239
2241
|
${validationError.getSummary()}`
|
|
2240
2242
|
);
|
|
2241
2243
|
throw validationError;
|
|
@@ -2427,10 +2429,10 @@ var import_zod2 = require("zod");
|
|
|
2427
2429
|
var fs = __toESM(require("fs"), 1);
|
|
2428
2430
|
var path = __toESM(require("path"), 1);
|
|
2429
2431
|
var VisionLLMComponent = class extends BaseLLMComponent {
|
|
2430
|
-
|
|
2431
|
-
constructor(logger, model, componentName,
|
|
2432
|
+
artifactDir;
|
|
2433
|
+
constructor(logger, model, componentName, artifactDir, options, fallbackModel, aggregator) {
|
|
2432
2434
|
super(logger, model, componentName, options, fallbackModel, aggregator);
|
|
2433
|
-
this.
|
|
2435
|
+
this.artifactDir = artifactDir;
|
|
2434
2436
|
}
|
|
2435
2437
|
/**
|
|
2436
2438
|
* Call LLM with vision capabilities using LLMCaller.callVision()
|
|
@@ -2462,12 +2464,12 @@ var VisionLLMComponent = class extends BaseLLMComponent {
|
|
|
2462
2464
|
/**
|
|
2463
2465
|
* Build image content object for vision LLM messages
|
|
2464
2466
|
*
|
|
2465
|
-
* @param imagePath - Path to the image file (relative to
|
|
2467
|
+
* @param imagePath - Path to the image file (relative to artifactDir or absolute)
|
|
2466
2468
|
* @param mimeType - MIME type of the image (default: 'image/png')
|
|
2467
2469
|
* @returns ImageContent object for LLM message
|
|
2468
2470
|
*/
|
|
2469
2471
|
buildImageContent(imagePath, mimeType = "image/png") {
|
|
2470
|
-
const absolutePath = path.isAbsolute(imagePath) ? imagePath : path.resolve(this.
|
|
2472
|
+
const absolutePath = path.isAbsolute(imagePath) ? imagePath : path.resolve(this.artifactDir, imagePath);
|
|
2471
2473
|
const imageData = new Uint8Array(fs.readFileSync(absolutePath));
|
|
2472
2474
|
return {
|
|
2473
2475
|
type: "image",
|
|
@@ -2486,12 +2488,12 @@ var VisionTocExtractionSchema = import_zod2.z.object({
|
|
|
2486
2488
|
var VisionTocExtractor = class extends VisionLLMComponent {
|
|
2487
2489
|
firstBatchSize;
|
|
2488
2490
|
secondBatchSize;
|
|
2489
|
-
constructor(logger, model,
|
|
2491
|
+
constructor(logger, model, artifactDir, options, fallbackModel, aggregator) {
|
|
2490
2492
|
super(
|
|
2491
2493
|
logger,
|
|
2492
2494
|
model,
|
|
2493
2495
|
"VisionTocExtractor",
|
|
2494
|
-
|
|
2496
|
+
artifactDir,
|
|
2495
2497
|
options,
|
|
2496
2498
|
fallbackModel,
|
|
2497
2499
|
aggregator ?? new LLMTokenUsageAggregator()
|
|
@@ -2624,7 +2626,7 @@ var VisionTocExtractor = class extends VisionLLMComponent {
|
|
|
2624
2626
|
const imageContents = [];
|
|
2625
2627
|
for (let pageNo = startPage; pageNo <= endPage; pageNo++) {
|
|
2626
2628
|
const imagePath = path2.resolve(
|
|
2627
|
-
this.
|
|
2629
|
+
this.artifactDir,
|
|
2628
2630
|
`pages/page_${pageNo - 1}.png`
|
|
2629
2631
|
);
|
|
2630
2632
|
const imageData = new Uint8Array(fs2.readFileSync(imagePath));
|
|
@@ -3034,12 +3036,12 @@ var PageRangeParser = class extends VisionLLMComponent {
|
|
|
3034
3036
|
SAMPLE_SIZE = 3;
|
|
3035
3037
|
MAX_PATTERN_RETRIES = 19;
|
|
3036
3038
|
SIZE_TOLERANCE = 5;
|
|
3037
|
-
constructor(logger, model,
|
|
3039
|
+
constructor(logger, model, artifactDir, maxRetries = 3, fallbackModel, aggregator, abortSignal) {
|
|
3038
3040
|
super(
|
|
3039
3041
|
logger,
|
|
3040
3042
|
model,
|
|
3041
3043
|
"PageRangeParser",
|
|
3042
|
-
|
|
3044
|
+
artifactDir,
|
|
3043
3045
|
{ maxRetries, abortSignal },
|
|
3044
3046
|
fallbackModel,
|
|
3045
3047
|
aggregator ?? new LLMTokenUsageAggregator()
|
|
@@ -3238,7 +3240,7 @@ var PageRangeParser = class extends VisionLLMComponent {
|
|
|
3238
3240
|
const imageContentsFromPages = pageNos.map((pageNo) => {
|
|
3239
3241
|
const page = pages[pageNo - 1];
|
|
3240
3242
|
const imagePath = path3.resolve(
|
|
3241
|
-
this.
|
|
3243
|
+
this.artifactDir,
|
|
3242
3244
|
`pages/page_${pageNo - 1}.png`
|
|
3243
3245
|
);
|
|
3244
3246
|
const imageData = new Uint8Array(fs3.readFileSync(imagePath));
|
|
@@ -4422,6 +4424,7 @@ var DocumentProcessor = class {
|
|
|
4422
4424
|
captionParserBatchSize;
|
|
4423
4425
|
captionValidatorBatchSize;
|
|
4424
4426
|
maxRetries;
|
|
4427
|
+
maxValidationRetries;
|
|
4425
4428
|
enableFallbackRetry;
|
|
4426
4429
|
abortSignal;
|
|
4427
4430
|
onTokenUsage;
|
|
@@ -4451,6 +4454,7 @@ var DocumentProcessor = class {
|
|
|
4451
4454
|
this.captionParserBatchSize = options.captionParserBatchSize;
|
|
4452
4455
|
this.captionValidatorBatchSize = options.captionValidatorBatchSize;
|
|
4453
4456
|
this.maxRetries = options.maxRetries ?? 3;
|
|
4457
|
+
this.maxValidationRetries = options.maxValidationRetries ?? 3;
|
|
4454
4458
|
this.enableFallbackRetry = options.enableFallbackRetry ?? false;
|
|
4455
4459
|
this.abortSignal = options.abortSignal;
|
|
4456
4460
|
this.onTokenUsage = options.onTokenUsage;
|
|
@@ -4482,7 +4486,7 @@ var DocumentProcessor = class {
|
|
|
4482
4486
|
* Conversion process:
|
|
4483
4487
|
* 1. Initialize processors and resolvers
|
|
4484
4488
|
* 2. Normalize and filter texts
|
|
4485
|
-
* 3. Clean texts and
|
|
4489
|
+
* 3. Clean texts and resolve page ranges
|
|
4486
4490
|
* 4. Extract table of contents
|
|
4487
4491
|
* 5. Convert images and tables (parallel)
|
|
4488
4492
|
* 6. Convert chapters and link resources
|
|
@@ -4491,19 +4495,20 @@ var DocumentProcessor = class {
|
|
|
4491
4495
|
*
|
|
4492
4496
|
* @param doclingDoc - Original document extracted from Docling SDK
|
|
4493
4497
|
* @param reportId - Report unique identifier
|
|
4494
|
-
* @param
|
|
4498
|
+
* @param artifactDir - Directory containing parser artifacts such as images/, pages/, and result.json
|
|
4499
|
+
* @param processOptions - Per-document processing inputs such as manually verified page range mappings and TOC entries
|
|
4495
4500
|
* @returns Document processing result with ProcessedDocument and token usage report
|
|
4496
4501
|
*
|
|
4497
4502
|
* @throws {TocExtractError} When TOC extraction fails
|
|
4498
4503
|
* @throws {PageRangeParseError} When page range parsing fails
|
|
4499
4504
|
* @throws {ConversionError} When error occurs during conversion
|
|
4500
4505
|
*/
|
|
4501
|
-
async process(doclingDoc, reportId,
|
|
4506
|
+
async process(doclingDoc, reportId, artifactDir, processOptions = {}) {
|
|
4502
4507
|
this.logger.info("[DocumentProcessor] Starting document processing...");
|
|
4503
4508
|
this.logger.info("[DocumentProcessor] Report ID:", reportId);
|
|
4504
4509
|
this.usageAggregator.reset();
|
|
4505
4510
|
this.checkAborted();
|
|
4506
|
-
this.initializeProcessors(doclingDoc,
|
|
4511
|
+
this.initializeProcessors(doclingDoc, artifactDir);
|
|
4507
4512
|
const startTimeFilter = Date.now();
|
|
4508
4513
|
const filtered = this.normalizeAndFilterTexts(doclingDoc);
|
|
4509
4514
|
const filteringTime = Date.now() - startTimeFilter;
|
|
@@ -4512,24 +4517,31 @@ var DocumentProcessor = class {
|
|
|
4512
4517
|
);
|
|
4513
4518
|
this.checkAborted();
|
|
4514
4519
|
const startTimePageRange = Date.now();
|
|
4515
|
-
const pageRangeMap = await this.parsePageRanges(doclingDoc);
|
|
4520
|
+
const pageRangeMap = processOptions.pageRangeMap !== void 0 ? processOptions.pageRangeMap : await this.parsePageRanges(doclingDoc);
|
|
4521
|
+
if (processOptions.pageRangeMap !== void 0) {
|
|
4522
|
+
this.logger.info(
|
|
4523
|
+
`[DocumentProcessor] Using injected page range map with ${Object.keys(pageRangeMap).length} entries`
|
|
4524
|
+
);
|
|
4525
|
+
}
|
|
4516
4526
|
const pageRangeTime = Date.now() - startTimePageRange;
|
|
4517
4527
|
this.logger.info(
|
|
4518
|
-
`[DocumentProcessor] Page range
|
|
4528
|
+
`[DocumentProcessor] Page range resolution took ${pageRangeTime}ms`
|
|
4519
4529
|
);
|
|
4520
4530
|
this.emitTokenUsage();
|
|
4521
4531
|
this.checkAborted();
|
|
4522
4532
|
const startTimeToc = Date.now();
|
|
4523
|
-
const tocEntries = await this.tocExtractionPipeline.extract(
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4533
|
+
const tocEntries = processOptions.tocEntries !== void 0 ? processOptions.tocEntries : await this.tocExtractionPipeline.extract(doclingDoc, filtered);
|
|
4534
|
+
if (processOptions.tocEntries !== void 0) {
|
|
4535
|
+
this.logger.info(
|
|
4536
|
+
`[DocumentProcessor] Using injected TOC entries with ${tocEntries.length} top-level entries`
|
|
4537
|
+
);
|
|
4538
|
+
}
|
|
4527
4539
|
const tocTime = Date.now() - startTimeToc;
|
|
4528
4540
|
this.logger.info(`[DocumentProcessor] TOC extraction took ${tocTime}ms`);
|
|
4529
4541
|
this.emitTokenUsage();
|
|
4530
4542
|
this.checkAborted();
|
|
4531
4543
|
const startTimeResources = Date.now();
|
|
4532
|
-
const { images, tables, footnotes } = await this.resourceConverter.convertAll(doclingDoc,
|
|
4544
|
+
const { images, tables, footnotes } = await this.resourceConverter.convertAll(doclingDoc, artifactDir);
|
|
4533
4545
|
const resourcesTime = Date.now() - startTimeResources;
|
|
4534
4546
|
this.logger.info(
|
|
4535
4547
|
`[DocumentProcessor] Resource conversion took ${resourcesTime}ms`
|
|
@@ -4573,7 +4585,7 @@ var DocumentProcessor = class {
|
|
|
4573
4585
|
*
|
|
4574
4586
|
* Sets up RefResolver, PageRangeParser, TocFinder, and TocExtractor
|
|
4575
4587
|
*/
|
|
4576
|
-
initializeProcessors(doclingDoc,
|
|
4588
|
+
initializeProcessors(doclingDoc, artifactDir) {
|
|
4577
4589
|
this.logger.info("[DocumentProcessor] Initializing processors...");
|
|
4578
4590
|
this.logger.info("[DocumentProcessor] - RefResolver");
|
|
4579
4591
|
this.refResolver = new RefResolver(this.logger, doclingDoc);
|
|
@@ -4581,7 +4593,7 @@ var DocumentProcessor = class {
|
|
|
4581
4593
|
this.pageRangeParser = new PageRangeParser(
|
|
4582
4594
|
this.logger,
|
|
4583
4595
|
this.pageRangeParserModel,
|
|
4584
|
-
|
|
4596
|
+
artifactDir,
|
|
4585
4597
|
this.maxRetries,
|
|
4586
4598
|
this.enableFallbackRetry ? this.fallbackModel : void 0,
|
|
4587
4599
|
this.usageAggregator,
|
|
@@ -4594,7 +4606,8 @@ var DocumentProcessor = class {
|
|
|
4594
4606
|
this.logger,
|
|
4595
4607
|
this.tocExtractorModel,
|
|
4596
4608
|
{
|
|
4597
|
-
maxRetries: this.maxRetries
|
|
4609
|
+
maxRetries: this.maxRetries,
|
|
4610
|
+
maxValidationRetries: this.maxValidationRetries
|
|
4598
4611
|
},
|
|
4599
4612
|
this.enableFallbackRetry ? this.fallbackModel : void 0,
|
|
4600
4613
|
this.abortSignal
|
|
@@ -4619,7 +4632,7 @@ var DocumentProcessor = class {
|
|
|
4619
4632
|
this.visionTocExtractor = new VisionTocExtractor(
|
|
4620
4633
|
this.logger,
|
|
4621
4634
|
this.visionTocExtractorModel,
|
|
4622
|
-
|
|
4635
|
+
artifactDir,
|
|
4623
4636
|
{ maxRetries: this.maxRetries, abortSignal: this.abortSignal },
|
|
4624
4637
|
this.enableFallbackRetry ? this.fallbackModel : void 0,
|
|
4625
4638
|
this.usageAggregator
|