@heripo/document-processor 0.1.43 → 0.1.45

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.
Files changed (3) hide show
  1. package/README.ko.md +43 -21
  2. package/README.md +45 -24
  3. package/package.json +11 -11
package/README.ko.md CHANGED
@@ -56,6 +56,14 @@ npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google
56
56
 
57
57
  ## 사용법
58
58
 
59
+ ### 실행 조건과 결과 저장
60
+
61
+ 이 패키지는 Node.js 24 이상에서 사용하는 ESM 라이브러리입니다. Python이나 macOS는 이 패키지 자체의 필수 조건이 아니며, PDF를 만드는 `@heripo/pdf-parser`에서 요구합니다. AI SDK/provider 버전은 저장소의 [catalog](../../pnpm-workspace.yaml)와 맞추세요.
62
+
63
+ 아래 예제의 `doclingDocument`는 파서의 보정된 `result.json`, `artifactDir`는 해당 이미지·페이지 산출물이 있는 디렉터리입니다. 기본 모델은 개별 모델이 생략된 모든 컴포넌트에도 사용되므로 이미지 입력과 구조화된 출력을 지원해야 합니다. 예제용 환경 변수 `HERIPO_ANTHROPIC_MODEL`과 `HERIPO_OPENAI_MODEL`에 사용할 모델 ID를 설정하고, 선택한 provider의 API 키도 설정하세요.
64
+
65
+ `process()`는 파일을 저장하지 않습니다. 반환한 `document`를 직접 JSON으로 저장하고 참조 이미지도 보존하세요. 출력 `schemaVersion`은 내보낸 `PROCESSED_DOCUMENT_SCHEMA_VERSION` 값인 `processed-document.v2`입니다.
66
+
59
67
  ### 기본 사용법
60
68
 
61
69
  ```typescript
@@ -73,7 +81,7 @@ const logger = new Logger({
73
81
  // 기본 사용 - fallback 모델만 지정
74
82
  const processor = new DocumentProcessor({
75
83
  logger,
76
- fallbackModel: anthropic('claude-opus-4-5'),
84
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!),
77
85
  textCleanerBatchSize: 10,
78
86
  captionParserBatchSize: 5,
79
87
  captionValidatorBatchSize: 5,
@@ -103,14 +111,14 @@ import { openai } from '@ai-sdk/openai';
103
111
  const processor = new DocumentProcessor({
104
112
  logger,
105
113
  // Fallback 모델 (실패 시 재시도용)
106
- fallbackModel: anthropic('claude-opus-4-5'),
114
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!),
107
115
 
108
116
  // 컴포넌트별 모델 지정
109
- pageRangeParserModel: openai('gpt-5.1'), // Vision 필요
110
- tocExtractorModel: openai('gpt-5.1'), // 구조화 출력
111
- validatorModel: openai('gpt-5.2'), // 간단한 검증
112
- visionTocExtractorModel: openai('gpt-5.1'), // Vision 필요
113
- captionParserModel: openai('gpt-5-mini'), // 캡션 파싱
117
+ pageRangeParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Vision 필요
118
+ tocExtractorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // 구조화 출력
119
+ validatorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // 간단한 검증
120
+ visionTocExtractorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Vision 필요
121
+ captionParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // 캡션 파싱
114
122
 
115
123
  // 배치 크기 설정
116
124
  textCleanerBatchSize: 20, // 동기 처리 (크게 가능)
@@ -228,7 +236,7 @@ console.log(document.images[0].captionSourceRefs);
228
236
 
229
237
  `sourceRefValidationMode: 'error'`는 누락된 참조가 있으면 처리를 실패시킵니다. `validateSourceRefs: true`는 호환용 단축 옵션이며, 별도 mode를 지정하지 않으면 `'error'`와 같습니다.
230
238
 
231
- 테이블 셀에는 cell-level `sourceRef`를 만들지 않습니다. 특정 셀의 원천 위치는 `table.sourceRef`와 `grid[row][col]`의 row/column index를 함께 사용해 추적합니다.
239
+ 테이블 셀에는 개별 `sourceRef`가 없습니다. `table.sourceRef`로 원천 표를 찾고 span과 원천 셀 좌표를 대조하세요. 압축된 `grid`의 배열 인덱스는 원천 표의 논리적 열 번호와 다를 수 있습니다.
232
240
 
233
241
  ### 테이블 그리드 처리
234
242
 
@@ -239,7 +247,7 @@ console.log(document.images[0].captionSourceRefs);
239
247
  - Docling이 병합 셀의 덮인 영역을 반복 제공하는 경우 shadow entry 제거
240
248
  - Docling의 `data.grid`가 비어 있으면 `table_cells`에서 그리드 구성
241
249
 
242
- `numRows`와 `numCols`는 논리적 테이블 크기를 유지합니다. 개별 셀에는 `sourceRef`를 저장하지 않으므로, 셀의 원천 위치를 추적할 때는 `table.sourceRef`와 `grid[row][col]` 위치를 함께 사용합니다.
250
+ `numRows`와 `numCols`는 논리적 테이블 크기이며 각 배열의 길이와 같다고 가정하면 안 됩니다. 렌더링 시 `rowSpan`과 `colSpan`으로 이미 덮인 위치를 건너뛰세요.
243
251
 
244
252
  ## 처리 파이프라인
245
253
 
@@ -294,6 +302,8 @@ DocumentProcessor는 다음 5단계 파이프라인으로 문서를 처리합니
294
302
 
295
303
  ### 5. 챕터 변환 (ChapterConverter)
296
304
 
305
+ `Front Matter` (`ch-000`) 챕터를 항상 첫 항목으로 생성하여 첫 목차 항목 이전의 내용을 보존합니다. 이후 계층은 제공·추출한 TOC로 구성됩니다.
306
+
297
307
  - TOC 기반 챕터 트리 구성
298
308
  - Chapter 계층 생성
299
309
  - 페이지 범위별로 텍스트 블록을 챕터에 연결
@@ -371,8 +381,8 @@ interface DocumentProcessorProcessOptions {
371
381
  ```typescript
372
382
  const processor = new DocumentProcessor({
373
383
  logger,
374
- fallbackModel: anthropic('claude-opus-4-5'), // 재시도용
375
- pageRangeParserModel: openai('gpt-5.2'), // 첫 시도
384
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!), // 재시도용
385
+ pageRangeParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // 첫 시도
376
386
  enableFallbackRetry: true, // 실패 시 fallback 사용 (기본값: false)
377
387
  textCleanerBatchSize: 10,
378
388
  captionParserBatchSize: 5,
@@ -386,8 +396,10 @@ const { document, usage } = await processor.process(doc, 'id', 'path');
386
396
  ### 배치 크기 파라미터
387
397
 
388
398
  - **textCleanerBatchSize**: 동기 텍스트 정규화 및 필터링 배치 크기. 로컬 처리이므로 큰 값 가능
389
- - **captionParserBatchSize**: LLM 기반 캡션 파싱 배치 크기. API 요청 동시성 및 비용 관리를 위해 작은 값 사용
390
- - **captionValidatorBatchSize**: LLM 기반 캡션 검증 배치 크기. 검증 요청 동시성 제한을 위해 작은 값 사용
399
+ - **captionParserBatchSize**: LLM 기반 캡션 파싱 배치 크기. 요청 하나에 포함하는 캡션 수 조절
400
+ - **captionValidatorBatchSize**: LLM 기반 캡션 검증 배치 크기. 검증할 캡션 묶음 크기 조절
401
+
402
+ `textCleanerBatchSize`, `captionParserBatchSize`, `captionValidatorBatchSize`는 `0`이면 묶음 처리 없이 순차 처리합니다. 묶음 처리를 사용할 때는 양의 정수로 지정하세요. 양수 배치 크기는 항목 묶음 크기이며 전체 API 호출 동시성의 상한은 아닙니다.
391
403
 
392
404
  ## 에러 처리
393
405
 
@@ -397,9 +409,15 @@ TOC 추출 실패 시 발생하는 에러들:
397
409
 
398
410
  - `TocNotFoundError`: 문서에서 TOC를 찾을 수 없음
399
411
  - `TocParseError`: LLM 응답 파싱 실패
400
- - `TocValidationError`: TOC 검증 실패
412
+ - `TocValidationError`: 내부 검증 오류로 발생할 수 있지만 패키지 루트에서 export하지 않습니다. 공개 API에서는 `TocExtractError`를 사용해 처리하세요.
401
413
 
402
414
  ```typescript
415
+ import {
416
+ TocExtractError,
417
+ TocNotFoundError,
418
+ TocParseError,
419
+ } from '@heripo/document-processor';
420
+
403
421
  try {
404
422
  const { document, usage } = await processor.process(doc, 'id', 'path');
405
423
  } catch (error) {
@@ -407,6 +425,10 @@ try {
407
425
  console.error('TOC를 찾을 수 없습니다. 수동 TOC 검수가 필요합니다.');
408
426
  } else if (error instanceof TocParseError) {
409
427
  console.error('TOC 파싱 실패:', error.message);
428
+ } else if (error instanceof TocExtractError) {
429
+ console.error(error.message);
430
+ } else {
431
+ throw error;
410
432
  }
411
433
  }
412
434
  ```
@@ -436,18 +458,18 @@ import {
436
458
 
437
459
  ```typescript
438
460
  // PageRangeParser
439
- const { pageRangeMap, tokenUsage } = await pageRangeParser.parse(doc);
440
- console.log('토큰 사용:', tokenUsage);
461
+ const { pageRangeMap, usage } = await pageRangeParser.parse(doc);
462
+ console.log('Token usage:', usage);
441
463
 
442
464
  // TocExtractor
443
- const { entries, tokenUsage } = await tocExtractor.extract(markdown);
444
- console.log('토큰 사용:', tokenUsage);
465
+ const { entries, usages } = await tocExtractor.extract(markdown);
466
+ console.log('Token usage:', usages);
445
467
  ```
446
468
 
447
469
  ## 관련 패키지
448
470
 
449
- - [@heripo/pdf-parser](../pdf-parser) - PDF 파싱 및 OCR
450
- - [@heripo/model](../model) - 데이터 모델 및 타입 정의
471
+ - [@heripo/pdf-parser](../pdf-parser/README.ko.md) - PDF 파싱 및 OCR
472
+ - [@heripo/model](../model/README.ko.md) - 데이터 모델 및 타입 정의
451
473
 
452
474
  ## 후원
453
475
 
@@ -462,7 +484,7 @@ heripo lab의 오픈소스 연구를 후원하려면 다음 경로를 이용할
462
484
 
463
485
  ## 기여하기
464
486
 
465
- 기여는 언제나 환영합니다! [기여 가이드](../../CONTRIBUTING.ko.md)를 참고하세요.
487
+ 기여는 언제나 환영합니다! [기여 가이드](../../CONTRIBUTING.md)를 참고하세요.
466
488
 
467
489
  ## 이슈 및 지원
468
490
 
package/README.md CHANGED
@@ -56,6 +56,14 @@ npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google
56
56
 
57
57
  ## Usage
58
58
 
59
+ ### Runtime and Result Persistence
60
+
61
+ This package is an ESM library for Node.js 24+. It does not itself require Python or macOS; those requirements belong to `@heripo/pdf-parser`. Align AI SDK/provider versions with the repository [catalog](../../pnpm-workspace.yaml).
62
+
63
+ In the examples, `doclingDocument` is the parser's corrected `result.json`, and `artifactDir` contains its image/page artifacts. The fallback model also serves every component without an explicit model, so it must support image input and structured output. Set the example-specific `HERIPO_ANTHROPIC_MODEL` and `HERIPO_OPENAI_MODEL` environment variables to available model IDs, and configure credentials for the selected providers.
64
+
65
+ `process()` does not save files. Save the returned `document` as JSON and preserve referenced images yourself. Its `schemaVersion` is the exported `PROCESSED_DOCUMENT_SCHEMA_VERSION`, currently `processed-document.v2`.
66
+
59
67
  ### Basic Usage
60
68
 
61
69
  ```typescript
@@ -73,7 +81,7 @@ const logger = new Logger({
73
81
  // Basic usage - specify fallback model only
74
82
  const processor = new DocumentProcessor({
75
83
  logger,
76
- fallbackModel: anthropic('claude-opus-4-5'),
84
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!),
77
85
  textCleanerBatchSize: 10,
78
86
  captionParserBatchSize: 5,
79
87
  captionValidatorBatchSize: 5,
@@ -103,14 +111,14 @@ import { openai } from '@ai-sdk/openai';
103
111
  const processor = new DocumentProcessor({
104
112
  logger,
105
113
  // Fallback model (for retry on failure)
106
- fallbackModel: anthropic('claude-opus-4-5'),
114
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!),
107
115
 
108
116
  // Per-component model specification
109
- pageRangeParserModel: openai('gpt-5.1'), // Vision required
110
- tocExtractorModel: openai('gpt-5.1'), // Structured output
111
- validatorModel: openai('gpt-5.2'), // Simple validation
112
- visionTocExtractorModel: openai('gpt-5.1'), // Vision required
113
- captionParserModel: openai('gpt-5-mini'), // Caption parsing
117
+ pageRangeParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Vision required
118
+ tocExtractorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Structured output
119
+ validatorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Simple validation
120
+ visionTocExtractorModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Vision required
121
+ captionParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // Caption parsing
114
122
 
115
123
  // Batch size settings
116
124
  textCleanerBatchSize: 20, // Synchronous processing (can be large)
@@ -240,9 +248,9 @@ node reference.
240
248
  `validateSourceRefs: true` is a compatibility shortcut and behaves like
241
249
  `'error'` unless a mode is explicitly provided.
242
250
 
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.
251
+ Table cells do not receive cell-level `sourceRef` values. Use `table.sourceRef`
252
+ to find the source table, then compare spans and source cell coordinates.
253
+ Compact `grid` array indexes may differ from logical source column indexes.
246
254
 
247
255
  ### Table Grid Handling
248
256
 
@@ -253,9 +261,8 @@ Processed tables expose a compact `grid` of visible cells. The processor:
253
261
  - Removes merged-cell shadow entries when Docling repeats covered cells
254
262
  - Falls back to `table_cells` when Docling's `data.grid` is empty
255
263
 
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.
264
+ `numRows` and `numCols` keep the logical table size; do not assume they match
265
+ array lengths. When rendering, skip positions covered by `rowSpan`/`colSpan`.
259
266
 
260
267
  ## Processing Pipeline
261
268
 
@@ -310,6 +317,8 @@ DocumentProcessor processes documents through a 5-stage pipeline:
310
317
 
311
318
  ### 5. Chapter Conversion (ChapterConverter)
312
319
 
320
+ A `Front Matter` (`ch-000`) chapter is always prepended to retain content before the first TOC entry. The remaining hierarchy is built from the supplied or extracted TOC.
321
+
313
322
  - Build chapter tree based on TOC
314
323
  - Create Chapter hierarchy
315
324
  - Link text blocks to chapters by page range
@@ -387,8 +396,8 @@ When `enableFallbackRetry: true` is set (default is `false`), LLM components aut
387
396
  ```typescript
388
397
  const processor = new DocumentProcessor({
389
398
  logger,
390
- fallbackModel: anthropic('claude-opus-4-5'), // For retry
391
- pageRangeParserModel: openai('gpt-5.2'), // First attempt
399
+ fallbackModel: anthropic(process.env.HERIPO_ANTHROPIC_MODEL!), // For retry
400
+ pageRangeParserModel: openai(process.env.HERIPO_OPENAI_MODEL!), // First attempt
392
401
  enableFallbackRetry: true, // Use fallback on failure (default: false)
393
402
  textCleanerBatchSize: 10,
394
403
  captionParserBatchSize: 5,
@@ -402,8 +411,10 @@ const { document, usage } = await processor.process(doc, 'id', 'path');
402
411
  ### Batch Size Parameters
403
412
 
404
413
  - **textCleanerBatchSize**: Synchronous text normalization and filtering batch size. Large values possible due to local processing
405
- - **captionParserBatchSize**: LLM-based caption parsing batch size. Small values for API request concurrency and cost management
406
- - **captionValidatorBatchSize**: LLM-based caption validation batch size. Small values to limit validation request concurrency
414
+ - **captionParserBatchSize**: LLM-based caption parsing batch size. Controls captions included per parsing request
415
+ - **captionValidatorBatchSize**: LLM-based caption validation batch size. Controls captions grouped for validation
416
+
417
+ `textCleanerBatchSize`, `captionParserBatchSize` and `captionValidatorBatchSize` accept `0` for sequential processing without batching. Use positive integers to enable batching. Positive batch sizes group items; they do not impose a global API concurrency limit.
407
418
 
408
419
  ## Error Handling
409
420
 
@@ -413,9 +424,15 @@ Errors thrown when TOC extraction fails:
413
424
 
414
425
  - `TocNotFoundError`: TOC not found in document
415
426
  - `TocParseError`: LLM response parsing failed
416
- - `TocValidationError`: TOC validation failed
427
+ - `TocValidationError`: May be raised internally, but is not exported from the package root. Catch the exported `TocExtractError` base class.
417
428
 
418
429
  ```typescript
430
+ import {
431
+ TocExtractError,
432
+ TocNotFoundError,
433
+ TocParseError,
434
+ } from '@heripo/document-processor';
435
+
419
436
  try {
420
437
  const { document, usage } = await processor.process(doc, 'id', 'path');
421
438
  } catch (error) {
@@ -423,6 +440,10 @@ try {
423
440
  console.error('TOC not found. Manual TOC review is required.');
424
441
  } else if (error instanceof TocParseError) {
425
442
  console.error('TOC parsing failed:', error.message);
443
+ } else if (error instanceof TocExtractError) {
444
+ console.error(error.message);
445
+ } else {
446
+ throw error;
426
447
  }
427
448
  }
428
449
  ```
@@ -452,18 +473,18 @@ Major LLM components return token usage:
452
473
 
453
474
  ```typescript
454
475
  // PageRangeParser
455
- const { pageRangeMap, tokenUsage } = await pageRangeParser.parse(doc);
456
- console.log('Token usage:', tokenUsage);
476
+ const { pageRangeMap, usage } = await pageRangeParser.parse(doc);
477
+ console.log('Token usage:', usage);
457
478
 
458
479
  // TocExtractor
459
- const { entries, tokenUsage } = await tocExtractor.extract(markdown);
460
- console.log('Token usage:', tokenUsage);
480
+ const { entries, usages } = await tocExtractor.extract(markdown);
481
+ console.log('Token usage:', usages);
461
482
  ```
462
483
 
463
484
  ## Related Packages
464
485
 
465
- - [@heripo/pdf-parser](../pdf-parser) - PDF parsing and OCR
466
- - [@heripo/model](../model) - Data models and type definitions
486
+ - [@heripo/pdf-parser](../pdf-parser/README.md) - PDF parsing and OCR
487
+ - [@heripo/model](../model/README.md) - Data models and type definitions
467
488
 
468
489
  ## Sponsor
469
490
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@heripo/document-processor",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "0.1.43",
5
+ "version": "0.1.45",
6
6
  "description": "Document processor with LLM-based analysis for heripo engine",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
@@ -50,20 +50,20 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "ai": "^7.0.66",
54
- "zod": "^4.4.3",
55
- "@heripo/logger": "0.1.43",
56
- "@heripo/model": "0.1.43"
53
+ "@heripo/logger": "0.1.45",
54
+ "@heripo/model": "0.1.45",
55
+ "ai": "^7.0.107",
56
+ "zod": "^4.6.5"
57
57
  },
58
58
  "devDependencies": {
59
- "@vitest/coverage-v8": "^4.1.10",
60
- "@vitest/expect": "^4.1.10",
61
- "tsup": "^8.5.1",
62
- "vitest": "^4.1.10",
63
- "@heripo/tsconfig": "0.0.0",
64
59
  "@heripo/shared": "0.0.0",
60
+ "@heripo/tsconfig": "0.0.0",
61
+ "@heripo/tsup-config": "0.0.0",
65
62
  "@heripo/vitest-config": "0.0.0",
66
- "@heripo/tsup-config": "0.0.0"
63
+ "@vitest/coverage-v8": "^5.0.1",
64
+ "@vitest/expect": "^5.0.1",
65
+ "tsup": "^8.5.1",
66
+ "vitest": "^5.0.1"
67
67
  },
68
68
  "scripts": {
69
69
  "clean": "rimraf dist",