@heripo/pdf-parser 0.1.15 → 0.1.17
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 +292 -103
- package/README.md +293 -104
- package/dist/index.cjs +2679 -2671
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -12
- package/dist/index.d.ts +3 -12
- package/dist/index.js +2701 -2694
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.ko.md
CHANGED
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
- [설치](#설치)
|
|
22
22
|
- [사용법](#사용법)
|
|
23
23
|
- [OCR 전략 시스템](#ocr-전략-시스템)
|
|
24
|
+
- [문서 유형 검증](#문서-유형-검증)
|
|
25
|
+
- [대용량 PDF 청크 변환](#대용량-pdf-청크-변환)
|
|
26
|
+
- [이미지 PDF 폴백](#이미지-pdf-폴백)
|
|
27
|
+
- [AbortSignal 지원](#abortsignal-지원)
|
|
28
|
+
- [서버 크래시 복구](#서버-크래시-복구)
|
|
24
29
|
- [왜 macOS 전용인가?](#왜-macos-전용인가)
|
|
25
30
|
- [시스템 의존성 상세](#시스템-의존성-상세)
|
|
26
31
|
- [API 문서](#api-문서)
|
|
@@ -34,7 +39,11 @@
|
|
|
34
39
|
- **Apple Silicon 최적화**: M1/M2/M3/M4/M5 칩에서 GPU 가속 지원
|
|
35
40
|
- **자동 환경 설정**: Python 가상환경 및 docling-serve 자동 설치
|
|
36
41
|
- **이미지 추출**: PDF 내 이미지 자동 추출 및 저장
|
|
37
|
-
-
|
|
42
|
+
- **문서 유형 검증**: LLM 기반 고고학 보고서 여부 검증 (선택)
|
|
43
|
+
- **청크 변환**: 대용량 PDF를 청크로 분할하여 안정적으로 처리
|
|
44
|
+
- **이미지 PDF 폴백**: 변환 실패 시 이미지 기반 PDF로 자동 재시도
|
|
45
|
+
- **AbortSignal 지원**: 진행 중인 파싱 작업 취소
|
|
46
|
+
- **서버 크래시 복구**: ECONNREFUSED 발생 시 docling-serve 자동 재시작
|
|
38
47
|
|
|
39
48
|
## 사전 요구사항
|
|
40
49
|
|
|
@@ -60,7 +69,7 @@ npm install -g pnpm
|
|
|
60
69
|
|
|
61
70
|
#### 3. Python 3.9 - 3.12
|
|
62
71
|
|
|
63
|
-
|
|
72
|
+
> **중요**: Python 3.13+는 지원하지 않습니다. Docling SDK의 일부 의존성이 Python 3.13과 호환되지 않습니다.
|
|
64
73
|
|
|
65
74
|
```bash
|
|
66
75
|
# Python 3.11 설치 (권장)
|
|
@@ -92,11 +101,19 @@ macOS에 기본적으로 설치되어 있습니다. 확인:
|
|
|
92
101
|
which lsof
|
|
93
102
|
```
|
|
94
103
|
|
|
104
|
+
#### 7. ImageMagick + Ghostscript (선택)
|
|
105
|
+
|
|
106
|
+
이미지 PDF 폴백 기능(`enableImagePdfFallback` 또는 `forceImagePdf`)을 사용할 때만 필요합니다.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
brew install imagemagick ghostscript
|
|
110
|
+
```
|
|
111
|
+
|
|
95
112
|
### 최초 실행 설정
|
|
96
113
|
|
|
97
114
|
`@heripo/pdf-parser`를 처음 사용할 때 자동으로:
|
|
98
115
|
|
|
99
|
-
1.
|
|
116
|
+
1. 현재 작업 디렉토리의 `.venv`에 Python 가상환경 생성 (`venvPath`로 설정 가능)
|
|
100
117
|
2. `docling-serve` 및 의존성 설치
|
|
101
118
|
3. 로컬 포트에서 docling-serve 프로세스 시작
|
|
102
119
|
|
|
@@ -125,9 +142,9 @@ import { PDFParser } from '@heripo/pdf-parser';
|
|
|
125
142
|
|
|
126
143
|
const logger = Logger(...);
|
|
127
144
|
|
|
128
|
-
// PDFParser 인스턴스 생성
|
|
145
|
+
// PDFParser 인스턴스 생성 (logger는 필수)
|
|
129
146
|
const pdfParser = new PDFParser({
|
|
130
|
-
|
|
147
|
+
port: 5001,
|
|
131
148
|
logger,
|
|
132
149
|
});
|
|
133
150
|
|
|
@@ -135,58 +152,68 @@ const pdfParser = new PDFParser({
|
|
|
135
152
|
await pdfParser.init();
|
|
136
153
|
|
|
137
154
|
// PDF 파싱
|
|
138
|
-
const
|
|
139
|
-
'path/to/report.pdf', //
|
|
140
|
-
'
|
|
141
|
-
(
|
|
155
|
+
const tokenUsageReport = await pdfParser.parse(
|
|
156
|
+
'file:///path/to/report.pdf', // PDF URL (file:// 또는 http://)
|
|
157
|
+
'report-001', // 리포트 ID
|
|
158
|
+
async (outputPath) => {
|
|
142
159
|
// 변환 완료 콜백
|
|
143
|
-
console.log('PDF 변환 완료:',
|
|
160
|
+
console.log('PDF 변환 완료:', outputPath);
|
|
144
161
|
},
|
|
162
|
+
false, // cleanupAfterCallback
|
|
163
|
+
{}, // PDFConvertOptions
|
|
145
164
|
);
|
|
146
165
|
|
|
147
|
-
//
|
|
148
|
-
console.log('
|
|
166
|
+
// 토큰 사용량 리포트 (LLM 사용이 없으면 null)
|
|
167
|
+
console.log('토큰 사용량:', tokenUsageReport);
|
|
149
168
|
```
|
|
150
169
|
|
|
151
170
|
### 고급 옵션
|
|
152
171
|
|
|
153
172
|
```typescript
|
|
173
|
+
// 옵션 A: 로컬 서버 (포트 모드)
|
|
154
174
|
const pdfParser = new PDFParser({
|
|
155
|
-
pythonPath: 'python3.11',
|
|
156
175
|
logger,
|
|
176
|
+
port: 5001, // 사용할 포트 (기본값: 5001)
|
|
177
|
+
timeout: 10000000, // 타임아웃 (밀리초)
|
|
178
|
+
venvPath: '/custom/path/.venv', // 커스텀 venv 경로 (기본값: CWD/.venv)
|
|
179
|
+
killExistingProcess: true, // 포트의 기존 프로세스 종료 (기본값: false)
|
|
180
|
+
enableImagePdfFallback: true, // 이미지 PDF 폴백 활성화 (기본값: false)
|
|
181
|
+
});
|
|
157
182
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// 외부 docling-serve 사용
|
|
163
|
-
externalDoclingUrl: 'http://localhost:5000', // 외부 서버 사용 시
|
|
183
|
+
// 옵션 B: 외부 docling-serve 사용
|
|
184
|
+
const pdfParser = new PDFParser({
|
|
185
|
+
logger,
|
|
186
|
+
baseUrl: 'http://localhost:5000', // 외부 서버 URL
|
|
164
187
|
});
|
|
165
188
|
|
|
166
|
-
// 변환
|
|
167
|
-
await pdfParser.parse(
|
|
168
|
-
|
|
169
|
-
|
|
189
|
+
// 변환 옵션과 함께 파싱
|
|
190
|
+
const tokenUsageReport = await pdfParser.parse(
|
|
191
|
+
'file:///path/to/input.pdf',
|
|
192
|
+
'report-001',
|
|
193
|
+
async (outputPath) => console.log(outputPath),
|
|
194
|
+
false,
|
|
195
|
+
{
|
|
196
|
+
// OCR 전략 옵션
|
|
197
|
+
strategySamplerModel: openai('gpt-5.1'),
|
|
198
|
+
vlmProcessorModel: openai('gpt-5.1'),
|
|
199
|
+
vlmConcurrency: 3,
|
|
170
200
|
|
|
171
|
-
|
|
172
|
-
|
|
201
|
+
// 문서 유형 검증
|
|
202
|
+
documentValidationModel: openai('gpt-5.1'),
|
|
173
203
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
204
|
+
// 대용량 PDF 청크 변환
|
|
205
|
+
chunkedConversion: true,
|
|
206
|
+
chunkSize: 50,
|
|
207
|
+
chunkMaxRetries: 3,
|
|
178
208
|
|
|
179
|
-
|
|
209
|
+
// 이미지 PDF 사전 변환 강제
|
|
210
|
+
forceImagePdf: false,
|
|
180
211
|
|
|
181
|
-
|
|
212
|
+
// 문서 처리 타임아웃 (초)
|
|
213
|
+
document_timeout: 600,
|
|
182
214
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
'report.pdf',
|
|
186
|
-
'output',
|
|
187
|
-
(resultPath) => {
|
|
188
|
-
// 이미지는 output/images/ 디렉토리에 저장됨
|
|
189
|
-
console.log('이미지 추출 완료:', resultPath);
|
|
215
|
+
// 토큰 사용량 추적
|
|
216
|
+
onTokenUsage: (report) => console.log('토큰 사용량:', report),
|
|
190
217
|
},
|
|
191
218
|
);
|
|
192
219
|
```
|
|
@@ -196,15 +223,15 @@ const outputPath = await pdfParser.parse(
|
|
|
196
223
|
작업 완료 후 리소스를 정리합니다:
|
|
197
224
|
|
|
198
225
|
```typescript
|
|
199
|
-
// docling-serve 프로세스 종료
|
|
200
|
-
await pdfParser.
|
|
226
|
+
// docling-serve 프로세스 종료 및 리소스 해제
|
|
227
|
+
await pdfParser.dispose();
|
|
201
228
|
```
|
|
202
229
|
|
|
203
230
|
## OCR 전략 시스템
|
|
204
231
|
|
|
205
232
|
### 왜 이 전략인가?
|
|
206
233
|
|
|
207
|
-
**ocrmac(Apple Vision Framework)은 매우 우수한 OCR 엔진입니다**
|
|
234
|
+
**ocrmac(Apple Vision Framework)은 매우 우수한 OCR 엔진입니다** -- 무료이고, GPU 가속을 지원하며, 고품질 결과를 제공합니다. 수천~수백만 권의 고고학 보고서를 처리할 때 이만한 솔루션이 없습니다.
|
|
208
235
|
|
|
209
236
|
**그러나 ocrmac은 혼합 문자 체계를 처리하지 못합니다.** 한글·한자 혼용 문서(그리고 잠재적으로 다른 혼합 문자 조합)에서 보조 문자가 깨진 텍스트로 변환됩니다. 전체 파이프라인을 비용이 높은 VLM으로 전환하는 대신, **문제가 있는 페이지만 타겟팅**하여 VLM으로 보정합니다.
|
|
210
237
|
|
|
@@ -219,16 +246,17 @@ await pdfParser.shutdown();
|
|
|
219
246
|
|
|
220
247
|
- 각 페이지의 OCR 텍스트 요소와 표 셀을 추출
|
|
221
248
|
- `pdftotext` 참조 텍스트를 품질 기준으로 활용
|
|
222
|
-
- VLM이 치환 기반 보정(find
|
|
249
|
+
- VLM이 치환 기반 보정(find -> replace)을 반환
|
|
223
250
|
- 실패한 페이지는 원본 OCR 텍스트를 유지하며 건너뜀
|
|
224
251
|
|
|
225
252
|
### 전략 옵션
|
|
226
253
|
|
|
227
254
|
```typescript
|
|
228
|
-
const
|
|
229
|
-
'input.pdf',
|
|
230
|
-
'
|
|
231
|
-
(
|
|
255
|
+
const tokenUsageReport = await pdfParser.parse(
|
|
256
|
+
'file:///path/to/input.pdf',
|
|
257
|
+
'report-001',
|
|
258
|
+
async (outputPath) => console.log(outputPath),
|
|
259
|
+
false,
|
|
232
260
|
{
|
|
233
261
|
// OCR 전략 샘플링 활성화 (Vision LLM 모델 제공)
|
|
234
262
|
strategySamplerModel: openai('gpt-5.1'),
|
|
@@ -245,6 +273,114 @@ const outputPath = await pdfParser.parse(
|
|
|
245
273
|
);
|
|
246
274
|
```
|
|
247
275
|
|
|
276
|
+
## 문서 유형 검증
|
|
277
|
+
|
|
278
|
+
LLM 기반으로 PDF가 고고학 발굴조사보고서인지 검증하는 선택적 기능입니다. `documentValidationModel`을 제공하면 파서가 PDF에서 텍스트를 추출하고 LLM을 사용하여 문서 유형을 확인한 후 처리합니다. 검증에 실패하면 `InvalidDocumentTypeError`가 발생합니다.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { InvalidDocumentTypeError } from '@heripo/pdf-parser';
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
await pdfParser.parse(
|
|
285
|
+
'file:///path/to/input.pdf',
|
|
286
|
+
'report-001',
|
|
287
|
+
async (outputPath) => console.log(outputPath),
|
|
288
|
+
false,
|
|
289
|
+
{
|
|
290
|
+
documentValidationModel: openai('gpt-5.1'),
|
|
291
|
+
},
|
|
292
|
+
);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (error instanceof InvalidDocumentTypeError) {
|
|
295
|
+
console.error('고고학 보고서가 아닙니다:', error.message);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 대용량 PDF 청크 변환
|
|
301
|
+
|
|
302
|
+
타임아웃이나 메모리 문제를 일으킬 수 있는 대용량 PDF의 경우, 청크 변환을 활성화하여 PDF를 작은 청크로 분할하고 개별적으로 처리할 수 있습니다. 로컬 파일(`file://` URL)에서만 동작합니다.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const tokenUsageReport = await pdfParser.parse(
|
|
306
|
+
'file:///path/to/large-report.pdf',
|
|
307
|
+
'report-001',
|
|
308
|
+
async (outputPath) => console.log(outputPath),
|
|
309
|
+
false,
|
|
310
|
+
{
|
|
311
|
+
chunkedConversion: true,
|
|
312
|
+
chunkSize: 50, // 청크당 페이지 수 (기본값: 상수에서 설정)
|
|
313
|
+
chunkMaxRetries: 3, // 실패한 청크의 최대 재시도 횟수 (기본값: 상수에서 설정)
|
|
314
|
+
},
|
|
315
|
+
);
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## 이미지 PDF 폴백
|
|
319
|
+
|
|
320
|
+
변환이 실패하면 파서가 PDF를 이미지 기반 PDF로 변환한 후 재시도할 수 있습니다. 복잡하거나 손상된 구조의 PDF에 유용합니다. ImageMagick과 Ghostscript가 필요합니다.
|
|
321
|
+
|
|
322
|
+
### 자동 폴백 (실패 시)
|
|
323
|
+
|
|
324
|
+
생성자 옵션으로 활성화합니다. 변환이 실패하면 파서가 자동으로 이미지 기반 PDF로 재시도합니다:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const pdfParser = new PDFParser({
|
|
328
|
+
logger,
|
|
329
|
+
port: 5001,
|
|
330
|
+
enableImagePdfFallback: true, // 자동 폴백 활성화
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 강제 이미지 PDF (항상)
|
|
335
|
+
|
|
336
|
+
parse 옵션으로 이미지 기반 PDF 사전 변환을 강제합니다:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const tokenUsageReport = await pdfParser.parse(
|
|
340
|
+
'file:///path/to/input.pdf',
|
|
341
|
+
'report-001',
|
|
342
|
+
async (outputPath) => console.log(outputPath),
|
|
343
|
+
false,
|
|
344
|
+
{
|
|
345
|
+
forceImagePdf: true, // 항상 이미지 PDF로 먼저 변환
|
|
346
|
+
},
|
|
347
|
+
);
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
원본 변환과 폴백 변환 모두 실패하면 두 에러를 모두 포함하는 `ImagePdfFallbackError`가 발생합니다.
|
|
351
|
+
|
|
352
|
+
## AbortSignal 지원
|
|
353
|
+
|
|
354
|
+
`AbortSignal`을 전달하여 진행 중인 파싱 작업을 취소할 수 있습니다:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
const controller = new AbortController();
|
|
358
|
+
|
|
359
|
+
// 5분 후 취소
|
|
360
|
+
setTimeout(() => controller.abort(), 5 * 60 * 1000);
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await pdfParser.parse(
|
|
364
|
+
'file:///path/to/input.pdf',
|
|
365
|
+
'report-001',
|
|
366
|
+
async (outputPath) => console.log(outputPath),
|
|
367
|
+
false,
|
|
368
|
+
{},
|
|
369
|
+
controller.signal, // AbortSignal
|
|
370
|
+
);
|
|
371
|
+
} catch (error) {
|
|
372
|
+
if (error.name === 'AbortError') {
|
|
373
|
+
console.log('파싱이 취소되었습니다');
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## 서버 크래시 복구
|
|
379
|
+
|
|
380
|
+
로컬 docling-serve 인스턴스(포트 모드)를 사용할 때, 파서가 서버 크래시(ECONNREFUSED 에러)를 자동으로 감지하고 서버를 재시작합니다. 이 과정은 `parse()` 호출 중에 투명하게 처리되며, 실패한 작업은 서버 재시작 후 재시도됩니다.
|
|
381
|
+
|
|
382
|
+
> **참고**: 서버 크래시 복구는 로컬 서버 모드(`port` 옵션)에서만 사용 가능합니다. 외부 서버(`baseUrl` 옵션)를 사용할 때는 복구를 시도하지 않습니다.
|
|
383
|
+
|
|
248
384
|
## 왜 macOS 전용인가?
|
|
249
385
|
|
|
250
386
|
`@heripo/pdf-parser`는 **의도적으로 macOS에 강하게 의존**합니다. 이 결정의 핵심 이유는 **Docling SDK의 로컬 OCR 성능**입니다.
|
|
@@ -281,14 +417,16 @@ const outputPath = await pdfParser.parse(
|
|
|
281
417
|
|
|
282
418
|
`@heripo/pdf-parser`는 다음 시스템 레벨 의존성이 필요합니다:
|
|
283
419
|
|
|
284
|
-
| 의존성
|
|
285
|
-
|
|
|
286
|
-
| Python
|
|
287
|
-
| poppler
|
|
288
|
-
| jq
|
|
289
|
-
| lsof
|
|
420
|
+
| 의존성 | 필수 버전 | 설치 방법 | 용도 |
|
|
421
|
+
| ----------- | ---------- | -------------------------- | -------------------------------------------------------------- |
|
|
422
|
+
| Python | 3.9 - 3.12 | `brew install python@3.11` | Docling SDK 실행 환경 |
|
|
423
|
+
| poppler | Any | `brew install poppler` | PDF 페이지 수 확인 (pdfinfo) 및 텍스트 레이어 추출 (pdftotext) |
|
|
424
|
+
| jq | Any | `brew install jq` | JSON 처리 (변환 결과 파싱) |
|
|
425
|
+
| lsof | Any | macOS 기본 설치됨 | docling-serve 포트 관리 |
|
|
426
|
+
| ImageMagick | Any (선택) | `brew install imagemagick` | 이미지 PDF 폴백 및 페이지 렌더링 |
|
|
427
|
+
| Ghostscript | Any (선택) | `brew install ghostscript` | 이미지 PDF 폴백 (PDF를 이미지로 변환) |
|
|
290
428
|
|
|
291
|
-
>
|
|
429
|
+
> **Python 3.13+는 지원하지 않습니다.** Docling SDK의 일부 의존성이 Python 3.13과 호환되지 않습니다.
|
|
292
430
|
|
|
293
431
|
### Python 버전 확인
|
|
294
432
|
|
|
@@ -318,13 +456,16 @@ which jq
|
|
|
318
456
|
#### 생성자 옵션
|
|
319
457
|
|
|
320
458
|
```typescript
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
logger?: Logger; // 로거 인스턴스
|
|
324
|
-
port?: number; // docling-serve 포트 (기본값: 5001)
|
|
459
|
+
type Options = {
|
|
460
|
+
logger: LoggerMethods; // 로거 인스턴스 (필수)
|
|
325
461
|
timeout?: number; // 타임아웃 (밀리초, 기본값: 10000000)
|
|
326
|
-
|
|
327
|
-
|
|
462
|
+
venvPath?: string; // Python venv 경로 (기본값: CWD/.venv)
|
|
463
|
+
killExistingProcess?: boolean; // 포트의 기존 프로세스 종료 (기본값: false)
|
|
464
|
+
enableImagePdfFallback?: boolean; // 이미지 PDF 폴백 활성화 (기본값: false, ImageMagick + Ghostscript 필요)
|
|
465
|
+
} & (
|
|
466
|
+
| { port?: number } // 로컬 서버 모드 (기본 포트: 5001)
|
|
467
|
+
| { baseUrl: string } // 외부 서버 모드
|
|
468
|
+
);
|
|
328
469
|
```
|
|
329
470
|
|
|
330
471
|
#### 메서드
|
|
@@ -337,70 +478,102 @@ Python 환경을 설정하고 docling-serve를 시작합니다.
|
|
|
337
478
|
await pdfParser.init();
|
|
338
479
|
```
|
|
339
480
|
|
|
340
|
-
##### `parse(
|
|
481
|
+
##### `parse(url, reportId, onComplete, cleanupAfterCallback, options, abortSignal?): Promise<TokenUsageReport | null>`
|
|
341
482
|
|
|
342
483
|
PDF 파일을 파싱합니다.
|
|
343
484
|
|
|
344
485
|
**파라미터:**
|
|
345
486
|
|
|
346
|
-
- `
|
|
347
|
-
- `
|
|
348
|
-
- `
|
|
349
|
-
- `
|
|
487
|
+
- `url` (string): PDF URL (로컬 파일은 `file://`, 원격은 `http://`)
|
|
488
|
+
- `reportId` (string): 고유 리포트 식별자 (출력 디렉토리 이름에 사용)
|
|
489
|
+
- `onComplete` (ConversionCompleteCallback): 변환 완료 시 출력 디렉토리 경로와 함께 호출되는 콜백 함수
|
|
490
|
+
- `cleanupAfterCallback` (boolean): 콜백 완료 후 출력 디렉토리 삭제 여부
|
|
491
|
+
- `options` (PDFConvertOptions): 변환 옵션
|
|
492
|
+
- `abortSignal` (AbortSignal, 선택): 작업 취소를 위한 시그널
|
|
350
493
|
|
|
351
494
|
**반환값:**
|
|
352
495
|
|
|
353
|
-
- `Promise<
|
|
354
|
-
|
|
355
|
-
##### `shutdown(): Promise<void>`
|
|
356
|
-
|
|
357
|
-
docling-serve 프로세스를 종료합니다.
|
|
496
|
+
- `Promise<TokenUsageReport | null>`: LLM 작업의 토큰 사용량 리포트, LLM 사용이 없으면 `null`
|
|
358
497
|
|
|
359
|
-
|
|
360
|
-
await pdfParser.shutdown();
|
|
361
|
-
```
|
|
498
|
+
##### `dispose(): Promise<void>`
|
|
362
499
|
|
|
363
|
-
|
|
500
|
+
파서 인스턴스를 해제하고, 로컬 docling-serve 프로세스를 종료(시작한 경우)하며, 리소스를 해제합니다.
|
|
364
501
|
|
|
365
502
|
```typescript
|
|
366
|
-
|
|
367
|
-
doOcr?: boolean; // OCR 활성화 (기본값: true)
|
|
368
|
-
formats?: string[]; // 출력 형식 (기본값: ['docling_json'])
|
|
369
|
-
pdfBackend?: string; // PDF 백엔드 (기본값: 'dlparse_v2')
|
|
370
|
-
}
|
|
503
|
+
await pdfParser.dispose();
|
|
371
504
|
```
|
|
372
505
|
|
|
373
|
-
### PDFConvertOptions
|
|
506
|
+
### PDFConvertOptions
|
|
374
507
|
|
|
375
508
|
```typescript
|
|
376
|
-
|
|
509
|
+
type PDFConvertOptions = {
|
|
510
|
+
// OCR 전략 옵션
|
|
377
511
|
strategySamplerModel?: LanguageModel; // OCR 전략 샘플링용 Vision LLM
|
|
378
512
|
vlmProcessorModel?: LanguageModel; // 텍스트 보정용 Vision LLM
|
|
379
513
|
vlmConcurrency?: number; // 병렬 페이지 처리 (기본값: 1)
|
|
380
514
|
skipSampling?: boolean; // 전략 샘플링 건너뛰기
|
|
381
515
|
forcedMethod?: 'ocrmac' | 'vlm'; // 특정 OCR 방식 강제
|
|
516
|
+
|
|
517
|
+
// 이미지 PDF 옵션
|
|
518
|
+
forceImagePdf?: boolean; // 이미지 기반 PDF 사전 변환 강제
|
|
519
|
+
|
|
520
|
+
// 토큰 사용량 추적
|
|
521
|
+
aggregator?: LLMTokenUsageAggregator; // 토큰 사용량 집계기
|
|
522
|
+
onTokenUsage?: (report: TokenUsageReport) => void; // 토큰 사용량 업데이트 콜백
|
|
523
|
+
|
|
524
|
+
// 문서 처리
|
|
525
|
+
document_timeout?: number; // 문서 처리 타임아웃 (초)
|
|
526
|
+
documentValidationModel?: LanguageModel; // 문서 유형 검증용 LLM
|
|
527
|
+
|
|
528
|
+
// 청크 변환 (대용량 PDF)
|
|
529
|
+
chunkedConversion?: boolean; // 청크 변환 활성화
|
|
530
|
+
chunkSize?: number; // 청크당 페이지 수
|
|
531
|
+
chunkMaxRetries?: number; // 실패한 청크의 최대 재시도 횟수
|
|
532
|
+
|
|
533
|
+
// Docling 변환 옵션 (상속)
|
|
534
|
+
num_threads?: number; // 처리 스레드 수
|
|
535
|
+
ocr_lang?: string[]; // OCR 언어
|
|
536
|
+
// ... 기타 Docling ConversionOptions 필드
|
|
537
|
+
};
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### ConvertWithStrategyResult
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
interface ConvertWithStrategyResult {
|
|
544
|
+
/** 결정된 OCR 전략 */
|
|
545
|
+
strategy: OcrStrategy;
|
|
546
|
+
/** 샘플링 및/또는 VLM 처리의 토큰 사용량 리포트 (LLM 사용이 없으면 null) */
|
|
547
|
+
tokenUsageReport: TokenUsageReport | null;
|
|
382
548
|
}
|
|
383
549
|
```
|
|
384
550
|
|
|
385
|
-
|
|
551
|
+
### ConversionCompleteCallback
|
|
386
552
|
|
|
387
|
-
|
|
553
|
+
```typescript
|
|
554
|
+
type ConversionCompleteCallback = (outputPath: string) => Promise<void> | void;
|
|
555
|
+
```
|
|
388
556
|
|
|
389
|
-
|
|
557
|
+
### 에러 타입
|
|
390
558
|
|
|
391
|
-
|
|
559
|
+
#### `InvalidDocumentTypeError`
|
|
392
560
|
|
|
393
|
-
|
|
394
|
-
# Python 3.11 설치
|
|
395
|
-
brew install python@3.11
|
|
561
|
+
PDF가 문서 유형 검증에 실패할 때 발생합니다 (즉, 고고학 발굴조사보고서가 아닌 경우).
|
|
396
562
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
pythonPath: 'python3.11',
|
|
400
|
-
logger,
|
|
401
|
-
});
|
|
563
|
+
```typescript
|
|
564
|
+
import { InvalidDocumentTypeError } from '@heripo/pdf-parser';
|
|
402
565
|
```
|
|
403
566
|
|
|
567
|
+
#### `ImagePdfFallbackError`
|
|
568
|
+
|
|
569
|
+
원본 변환과 이미지 PDF 폴백 변환이 모두 실패할 때 발생합니다. 두 에러에 대한 참조를 포함합니다.
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
import { ImagePdfFallbackError } from '@heripo/pdf-parser';
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
## 문제 해결
|
|
576
|
+
|
|
404
577
|
### jq를 찾을 수 없음
|
|
405
578
|
|
|
406
579
|
**증상**: `Command not found: jq`
|
|
@@ -427,13 +600,19 @@ brew install poppler
|
|
|
427
600
|
|
|
428
601
|
**해결**:
|
|
429
602
|
|
|
430
|
-
```
|
|
431
|
-
|
|
603
|
+
```typescript
|
|
604
|
+
// 다른 포트 사용
|
|
432
605
|
const pdfParser = new PDFParser({
|
|
433
|
-
pythonPath: 'python3.11',
|
|
434
606
|
port: 5002, // 다른 포트 지정
|
|
435
607
|
logger,
|
|
436
608
|
});
|
|
609
|
+
|
|
610
|
+
// 또는 기존 프로세스 종료
|
|
611
|
+
const pdfParser = new PDFParser({
|
|
612
|
+
port: 5001,
|
|
613
|
+
killExistingProcess: true,
|
|
614
|
+
logger,
|
|
615
|
+
});
|
|
437
616
|
```
|
|
438
617
|
|
|
439
618
|
### docling-serve 시작 실패
|
|
@@ -443,21 +622,31 @@ const pdfParser = new PDFParser({
|
|
|
443
622
|
**해결**:
|
|
444
623
|
|
|
445
624
|
```bash
|
|
446
|
-
# 가상환경 재생성
|
|
447
|
-
rm -rf
|
|
625
|
+
# 가상환경 재생성 (기본 위치)
|
|
626
|
+
rm -rf .venv
|
|
448
627
|
# 다시 init() 실행
|
|
449
628
|
```
|
|
450
629
|
|
|
630
|
+
### ImageMagick / Ghostscript를 찾을 수 없음
|
|
631
|
+
|
|
632
|
+
**증상**: `ImageMagick is not installed but enableImagePdfFallback is enabled`
|
|
633
|
+
|
|
634
|
+
**해결**:
|
|
635
|
+
|
|
636
|
+
```bash
|
|
637
|
+
brew install imagemagick ghostscript
|
|
638
|
+
```
|
|
639
|
+
|
|
451
640
|
## Linux 지원 현황
|
|
452
641
|
|
|
453
642
|
현재 **macOS 전용**입니다. Linux 지원은 **완전히 배제한 것은 아니지만**, OCR 성능과 비용 효율성 문제로 **현재는 구체적인 계획이 없습니다**.
|
|
454
643
|
|
|
455
|
-
| 플랫폼 | 상태
|
|
456
|
-
| --------------------- |
|
|
457
|
-
| macOS + Apple Silicon |
|
|
458
|
-
| macOS + Intel |
|
|
459
|
-
| Linux |
|
|
460
|
-
| Windows |
|
|
644
|
+
| 플랫폼 | 상태 | 비고 |
|
|
645
|
+
| --------------------- | ---- | ------------------------------- |
|
|
646
|
+
| macOS + Apple Silicon | 지원 | 최적 성능, GPU 가속 |
|
|
647
|
+
| macOS + Intel | 지원 | GPU 가속 없음 |
|
|
648
|
+
| Linux | 미정 | 성능/비용 문제로 현재 계획 없음 |
|
|
649
|
+
| Windows | 미정 | WSL2 통한 Linux 방식 고려 가능 |
|
|
461
650
|
|
|
462
651
|
### Linux 미지원 사유
|
|
463
652
|
|