@heripo/document-processor 0.1.28 → 0.1.30

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 CHANGED
@@ -20,6 +20,7 @@
20
20
  - [사용법](#사용법)
21
21
  - [처리 파이프라인](#처리-파이프라인)
22
22
  - [API 문서](#api-문서)
23
+ - [후원](#후원)
23
24
  - [라이선스](#라이선스)
24
25
 
25
26
  ## 주요 기능
@@ -28,6 +29,8 @@
28
29
  - **계층 구조**: 장/절/소절 계층 구조 자동 생성
29
30
  - **페이지 매핑**: Vision LLM을 활용한 실제 페이지 번호 매핑
30
31
  - **캡션 파싱**: 이미지 및 테이블 캡션 자동 파싱
32
+ - **원천 추적성**: Docling 원천 metadata와 node-level reference 보존
33
+ - **테이블 그리드 정규화**: row/column span을 보존하고 병합 셀 shadow entry 제거
31
34
  - **LLM 유연성**: OpenAI, Anthropic, Google 등 다양한 LLM 지원
32
35
  - **Fallback 재시도**: 실패 시 자동으로 fallback 모델로 재시도
33
36
 
@@ -35,13 +38,13 @@
35
38
 
36
39
  ```bash
37
40
  # npm으로 설치
38
- npm install @heripo/document-processor @heripo/model
41
+ npm install @heripo/document-processor @heripo/model @heripo/logger
39
42
 
40
43
  # pnpm으로 설치
41
- pnpm add @heripo/document-processor @heripo/model
44
+ pnpm add @heripo/document-processor @heripo/model @heripo/logger
42
45
 
43
46
  # yarn으로 설치
44
- yarn add @heripo/document-processor @heripo/model
47
+ yarn add @heripo/document-processor @heripo/model @heripo/logger
45
48
  ```
46
49
 
47
50
  추가로 LLM 프로파이더의 SDK가 필요합니다:
@@ -60,7 +63,12 @@ import { anthropic } from '@ai-sdk/anthropic';
60
63
  import { DocumentProcessor } from '@heripo/document-processor';
61
64
  import { Logger } from '@heripo/logger';
62
65
 
63
- const logger = Logger(...);
66
+ const logger = new Logger({
67
+ debug: (...args) => console.debug('[heripo]', ...args),
68
+ info: (...args) => console.info('[heripo]', ...args),
69
+ warn: (...args) => console.warn('[heripo]', ...args),
70
+ error: (...args) => console.error('[heripo]', ...args),
71
+ });
64
72
 
65
73
  // 기본 사용 - fallback 모델만 지정
66
74
  const processor = new DocumentProcessor({
@@ -189,6 +197,50 @@ const { document, usage } = await processor.process(
189
197
  );
190
198
  ```
191
199
 
200
+ ### 원천 Docling 참조 보존
201
+
202
+ 호출자가 원천 Docling JSON의 저장 위치나 해시를 알고 있다면 `source`로 전달할 수 있습니다. 이 값은 `ProcessedDocument.source`에 그대로 보존됩니다. `validateSourceRefs` 또는 `sourceRefValidationMode`를 사용하면 processor가 생성한 `sourceRef`, `captionSourceRefs`가 입력 `DoclingDocument`에 실제로 존재하는지 검증합니다.
203
+
204
+ ```typescript
205
+ const { document } = await processor.process(
206
+ doclingDocument,
207
+ 'report-001',
208
+ artifactDir,
209
+ {
210
+ pageRangeMap,
211
+ tocEntries,
212
+ source: {
213
+ pipelineRunId: 'run-001',
214
+ doclingObjectKey: 'docling/report-001.json',
215
+ doclingSha256: '...',
216
+ handoffManifestObjectKey: 'manifests/run-001.json',
217
+ },
218
+ sourceRefValidationMode: 'warn', // 'off' | 'warn' | 'error'
219
+ },
220
+ );
221
+
222
+ console.log(document.source);
223
+ console.log(document.chapters[0].textBlocks[0].sourceRef);
224
+ console.log(document.images[0].captionSourceRefs);
225
+ ```
226
+
227
+ `ProcessedDocument.source`는 처리에 사용된 Docling artifact 자체를 가리키는 문서 단위 metadata입니다. `TextBlock.sourceRef`, `Chapter.sourceRefs`, `ProcessedImage.sourceRef`, `ProcessedTable.sourceRef`, `ProcessedFootnote.sourceRef`는 해당 processed node가 어떤 Docling node에서 왔는지 가리키는 node-level 참조입니다. 이미지와 테이블의 `captionSourceRefs`는 resource node가 아니라 caption text node의 참조만 담습니다.
228
+
229
+ `sourceRefValidationMode: 'error'`는 누락된 참조가 있으면 처리를 실패시킵니다. `validateSourceRefs: true`는 호환용 단축 옵션이며, 별도 mode를 지정하지 않으면 `'error'`와 같습니다.
230
+
231
+ 테이블 셀에는 cell-level `sourceRef`를 만들지 않습니다. 특정 셀의 원천 위치는 `table.sourceRef`와 `grid[row][col]`의 row/column index를 함께 사용해 추적합니다.
232
+
233
+ ### 테이블 그리드 처리
234
+
235
+ 처리된 테이블은 화면에 보이는 셀만 담은 compact `grid`를 제공합니다. processor는 다음을 수행합니다:
236
+
237
+ - Docling의 row/column span을 `rowSpan`, `colSpan`으로 보존
238
+ - 행/열 헤더를 `isHeader`로 표시
239
+ - Docling이 병합 셀의 덮인 영역을 반복 제공하는 경우 shadow entry 제거
240
+ - Docling의 `data.grid`가 비어 있으면 `table_cells`에서 그리드 구성
241
+
242
+ `numRows`와 `numCols`는 논리적 테이블 크기를 유지합니다. 개별 셀에는 `sourceRef`를 저장하지 않으므로, 셀의 원천 위치를 추적할 때는 `table.sourceRef`와 `grid[row][col]` 위치를 함께 사용합니다.
243
+
192
244
  ## 처리 파이프라인
193
245
 
194
246
  DocumentProcessor는 다음 5단계 파이프라인으로 문서를 처리합니다:
@@ -237,7 +289,7 @@ DocumentProcessor는 다음 5단계 파이프라인으로 문서를 처리합니
237
289
  ### 4. 리소스 변환
238
290
 
239
291
  - **이미지**: CaptionParser로 캡션 추출 및 파싱
240
- - **테이블**: 그리드 데이터 변환 및 캡션 파싱
292
+ - **테이블**: 그리드 데이터 변환, 병합 셀 shadow filtering, span 보존 및 캡션 파싱
241
293
  - **캡션 검증**: CaptionValidator로 파싱 결과 검증
242
294
 
243
295
  ### 5. 챕터 변환 (ChapterConverter)
@@ -247,7 +299,7 @@ DocumentProcessor는 다음 5단계 파이프라인으로 문서를 처리합니
247
299
  - 페이지 범위별로 텍스트 블록을 챕터에 연결
248
300
  - 이미지/테이블 ID를 적절한 챕터에 연결
249
301
  - 각주 ID를 적절한 챕터에 연결
250
- - Fallback: TOC가 비어있을 때 단일 "Document" 챕터 생성
302
+ - TOC 항목이 비어 있으면 TOC 기반 챕터 변환을 진행할 수 없으므로 `TocNotFoundError` 발생
251
303
 
252
304
  ## API 문서
253
305
 
@@ -257,7 +309,7 @@ DocumentProcessor는 다음 5단계 파이프라인으로 문서를 처리합니
257
309
 
258
310
  ```typescript
259
311
  interface DocumentProcessorOptions {
260
- logger: Logger; // 로거 인스턴스 (필수)
312
+ logger: LoggerMethods; // 로거 인스턴스 (필수)
261
313
 
262
314
  // LLM 모델 설정
263
315
  fallbackModel: LanguageModel; // Fallback 모델 (필수)
@@ -293,6 +345,9 @@ DoclingDocument를 ProcessedDocument로 변환합니다.
293
345
  interface DocumentProcessorProcessOptions {
294
346
  pageRangeMap?: Record<number, PageRange>;
295
347
  tocEntries?: TocEntry[];
348
+ source?: ProcessedDocumentSource;
349
+ validateSourceRefs?: boolean;
350
+ sourceRefValidationMode?: 'off' | 'warn' | 'error';
296
351
  }
297
352
  ```
298
353
 
@@ -301,7 +356,7 @@ interface DocumentProcessorProcessOptions {
301
356
  - `doclingDoc` (DoclingDocument): PDF 파서의 출력
302
357
  - `reportId` (string): 리포트 ID
303
358
  - `artifactDir` (string): `images/`, `pages/`, `result.json` 같은 parser 산출물이 들어 있는 디렉토리
304
- - `processOptions` (DocumentProcessorProcessOptions, 선택): 문서별 처리 입력값. `pageRangeMap`이 제공되면 자동 페이지 범위 파싱을 건너뜁니다. `tocEntries`가 제공되면 자동 TOC 추출을 건너뜁니다.
359
+ - `processOptions` (DocumentProcessorProcessOptions, 선택): 문서별 처리 입력값. `pageRangeMap`이 제공되면 자동 페이지 범위 파싱을 건너뜁니다. `tocEntries`가 제공되면 자동 TOC 추출을 건너뜁니다. `source`는 원천 Docling artifact metadata를 결과에 보존하고, `sourceRefValidationMode`는 생성된 원천 참조의 검증 방식을 제어합니다.
305
360
 
306
361
  **반환값:**
307
362
 
@@ -349,7 +404,7 @@ try {
349
404
  const { document, usage } = await processor.process(doc, 'id', 'path');
350
405
  } catch (error) {
351
406
  if (error instanceof TocNotFoundError) {
352
- console.log('TOC를 찾을 수 없습니다. 단일 챕터로 처리됩니다.');
407
+ console.error('TOC를 찾을 수 없습니다. 수동 TOC 검수가 필요합니다.');
353
408
  } else if (error instanceof TocParseError) {
354
409
  console.error('TOC 파싱 실패:', error.message);
355
410
  }
@@ -394,6 +449,13 @@ console.log('토큰 사용:', tokenUsage);
394
449
  - [@heripo/pdf-parser](../pdf-parser) - PDF 파싱 및 OCR
395
450
  - [@heripo/model](../model) - 데이터 모델 및 타입 정의
396
451
 
452
+ ## 후원
453
+
454
+ heripo lab의 오픈소스 연구를 후원하려면 다음 경로를 이용할 수 있습니다:
455
+
456
+ - [Open Collective](https://opencollective.com/heripo-project): 전반적인 프로젝트 후원
457
+ - [fairy.hada.io/@heripo](https://fairy.hada.io/@heripo): 한국인 개인 후원자를 위한 원화 결제
458
+
397
459
  ## 라이선스
398
460
 
399
461
  이 패키지는 [Apache License 2.0](../../LICENSE) 라이선스 하에 배포됩니다.
package/README.md CHANGED
@@ -20,6 +20,7 @@
20
20
  - [Usage](#usage)
21
21
  - [Processing Pipeline](#processing-pipeline)
22
22
  - [API Documentation](#api-documentation)
23
+ - [Sponsor](#sponsor)
23
24
  - [License](#license)
24
25
 
25
26
  ## Key Features
@@ -28,6 +29,8 @@
28
29
  - **Hierarchical Structure**: Automatic generation of chapter/section/subsection hierarchy
29
30
  - **Page Mapping**: Actual page number mapping using Vision LLM
30
31
  - **Caption Parsing**: Automatic parsing of image and table captions
32
+ - **Source Provenance**: Preserves Docling source metadata and node-level references
33
+ - **Table Grid Normalization**: Preserves row/column spans and removes merged-cell shadow entries
31
34
  - **LLM Flexibility**: Support for various LLMs including OpenAI, Anthropic, Google
32
35
  - **Fallback Retry**: Automatic retry with fallback model on failure
33
36
 
@@ -35,13 +38,13 @@
35
38
 
36
39
  ```bash
37
40
  # Install with npm
38
- npm install @heripo/document-processor @heripo/model
41
+ npm install @heripo/document-processor @heripo/model @heripo/logger
39
42
 
40
43
  # Install with pnpm
41
- pnpm add @heripo/document-processor @heripo/model
44
+ pnpm add @heripo/document-processor @heripo/model @heripo/logger
42
45
 
43
46
  # Install with yarn
44
- yarn add @heripo/document-processor @heripo/model
47
+ yarn add @heripo/document-processor @heripo/model @heripo/logger
45
48
  ```
46
49
 
47
50
  Additionally, LLM provider SDKs are required:
@@ -60,7 +63,12 @@ import { anthropic } from '@ai-sdk/anthropic';
60
63
  import { DocumentProcessor } from '@heripo/document-processor';
61
64
  import { Logger } from '@heripo/logger';
62
65
 
63
- const logger = Logger(...);
66
+ const logger = new Logger({
67
+ debug: (...args) => console.debug('[heripo]', ...args),
68
+ info: (...args) => console.info('[heripo]', ...args),
69
+ warn: (...args) => console.warn('[heripo]', ...args),
70
+ error: (...args) => console.error('[heripo]', ...args),
71
+ });
64
72
 
65
73
  // Basic usage - specify fallback model only
66
74
  const processor = new DocumentProcessor({
@@ -189,6 +197,66 @@ const { document, usage } = await processor.process(
189
197
  );
190
198
  ```
191
199
 
200
+ ### Preserving Source Docling References
201
+
202
+ If the caller knows where the source Docling JSON is stored or has its hash,
203
+ pass that metadata through `source`. The value is preserved as
204
+ `ProcessedDocument.source`. Use `validateSourceRefs` or
205
+ `sourceRefValidationMode` to verify that generated `sourceRef` and
206
+ `captionSourceRefs` values exist in the input `DoclingDocument`.
207
+
208
+ ```typescript
209
+ const { document } = await processor.process(
210
+ doclingDocument,
211
+ 'report-001',
212
+ artifactDir,
213
+ {
214
+ pageRangeMap,
215
+ tocEntries,
216
+ source: {
217
+ pipelineRunId: 'run-001',
218
+ doclingObjectKey: 'docling/report-001.json',
219
+ doclingSha256: '...',
220
+ handoffManifestObjectKey: 'manifests/run-001.json',
221
+ },
222
+ sourceRefValidationMode: 'warn', // 'off' | 'warn' | 'error'
223
+ },
224
+ );
225
+
226
+ console.log(document.source);
227
+ console.log(document.chapters[0].textBlocks[0].sourceRef);
228
+ console.log(document.images[0].captionSourceRefs);
229
+ ```
230
+
231
+ `ProcessedDocument.source` is document-level metadata that identifies the
232
+ Docling artifact used for processing. `TextBlock.sourceRef`,
233
+ `Chapter.sourceRefs`, `ProcessedImage.sourceRef`, `ProcessedTable.sourceRef`,
234
+ and `ProcessedFootnote.sourceRef` are node-level references that point back to
235
+ the Docling nodes each processed node came from. For images and tables,
236
+ `captionSourceRefs` contains only caption text node references, not the resource
237
+ node reference.
238
+
239
+ `sourceRefValidationMode: 'error'` fails processing when references are missing.
240
+ `validateSourceRefs: true` is a compatibility shortcut and behaves like
241
+ `'error'` unless a mode is explicitly provided.
242
+
243
+ Table cells do not receive cell-level `sourceRef` values. To locate a specific
244
+ cell in the source artifact, combine `table.sourceRef` with the
245
+ `grid[row][col]` row/column indexes.
246
+
247
+ ### Table Grid Handling
248
+
249
+ Processed tables expose a compact `grid` of visible cells. The processor:
250
+
251
+ - Preserves Docling row/column spans as `rowSpan` and `colSpan`
252
+ - Marks row and column headers through `isHeader`
253
+ - Removes merged-cell shadow entries when Docling repeats covered cells
254
+ - Falls back to `table_cells` when Docling's `data.grid` is empty
255
+
256
+ `numRows` and `numCols` keep the logical table size. Individual cells do not
257
+ store `sourceRef`; use `table.sourceRef` together with the `grid[row][col]`
258
+ position when tracing a cell back to the source table.
259
+
192
260
  ## Processing Pipeline
193
261
 
194
262
  DocumentProcessor processes documents through a 5-stage pipeline:
@@ -237,7 +305,7 @@ DocumentProcessor processes documents through a 5-stage pipeline:
237
305
  ### 4. Resource Transformation
238
306
 
239
307
  - **Images**: Caption extraction and parsing with CaptionParser
240
- - **Tables**: Grid data transformation and caption parsing
308
+ - **Tables**: Grid data transformation, merged-cell shadow filtering, span preservation, and caption parsing
241
309
  - **Caption Validation**: Parsing result validation with CaptionValidator
242
310
 
243
311
  ### 5. Chapter Conversion (ChapterConverter)
@@ -247,7 +315,7 @@ DocumentProcessor processes documents through a 5-stage pipeline:
247
315
  - Link text blocks to chapters by page range
248
316
  - Connect image/table IDs to appropriate chapters
249
317
  - Link footnote IDs to appropriate chapters
250
- - Fallback: Create single "Document" chapter when TOC is empty
318
+ - Throws `TocNotFoundError` when TOC entries are empty because TOC-based chapter conversion is required
251
319
 
252
320
  ## API Documentation
253
321
 
@@ -257,7 +325,7 @@ DocumentProcessor processes documents through a 5-stage pipeline:
257
325
 
258
326
  ```typescript
259
327
  interface DocumentProcessorOptions {
260
- logger: Logger; // Logger instance (required)
328
+ logger: LoggerMethods; // Logger instance (required)
261
329
 
262
330
  // LLM model settings
263
331
  fallbackModel: LanguageModel; // Fallback model (required)
@@ -293,6 +361,9 @@ Transforms DoclingDocument into ProcessedDocument.
293
361
  interface DocumentProcessorProcessOptions {
294
362
  pageRangeMap?: Record<number, PageRange>;
295
363
  tocEntries?: TocEntry[];
364
+ source?: ProcessedDocumentSource;
365
+ validateSourceRefs?: boolean;
366
+ sourceRefValidationMode?: 'off' | 'warn' | 'error';
296
367
  }
297
368
  ```
298
369
 
@@ -301,7 +372,7 @@ interface DocumentProcessorProcessOptions {
301
372
  - `doclingDoc` (DoclingDocument): PDF parser output
302
373
  - `reportId` (string): Report ID
303
374
  - `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.
375
+ - `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. `source` preserves source Docling artifact metadata, and `sourceRefValidationMode` controls generated source reference validation.
305
376
 
306
377
  **Returns:**
307
378
 
@@ -349,7 +420,7 @@ try {
349
420
  const { document, usage } = await processor.process(doc, 'id', 'path');
350
421
  } catch (error) {
351
422
  if (error instanceof TocNotFoundError) {
352
- console.log('TOC not found. Processing as single chapter.');
423
+ console.error('TOC not found. Manual TOC review is required.');
353
424
  } else if (error instanceof TocParseError) {
354
425
  console.error('TOC parsing failed:', error.message);
355
426
  }
@@ -394,6 +465,13 @@ console.log('Token usage:', tokenUsage);
394
465
  - [@heripo/pdf-parser](../pdf-parser) - PDF parsing and OCR
395
466
  - [@heripo/model](../model) - Data models and type definitions
396
467
 
468
+ ## Sponsor
469
+
470
+ If you'd like to support heripo lab's open-source research, you can sponsor us through:
471
+
472
+ - [Open Collective](https://opencollective.com/heripo-project) for general project sponsorship.
473
+ - [fairy.hada.io/@heripo](https://fairy.hada.io/@heripo) for Korean individual supporters who prefer KRW payments.
474
+
397
475
  ## License
398
476
 
399
477
  This package is distributed under the [Apache License 2.0](../../LICENSE).