@heripo/pdf-parser 0.1.29 → 0.1.31
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 +158 -85
- package/README.md +158 -86
- package/dist/index.cjs +8085 -5789
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -45
- package/dist/index.d.ts +47 -45
- package/dist/index.js +8131 -5833
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/README.ko.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
- [사전 요구사항](#사전-요구사항)
|
|
21
21
|
- [설치](#설치)
|
|
22
22
|
- [사용법](#사용법)
|
|
23
|
-
- [
|
|
23
|
+
- [필수 보정 파이프라인](#필수-보정-파이프라인)
|
|
24
24
|
- [Review Assistance](#review-assistance)
|
|
25
25
|
- [문서 유형 검증](#문서-유형-검증)
|
|
26
26
|
- [대용량 PDF 청크 변환](#대용량-pdf-청크-변환)
|
|
@@ -36,15 +36,16 @@
|
|
|
36
36
|
|
|
37
37
|
## 주요 기능
|
|
38
38
|
|
|
39
|
-
-
|
|
40
|
-
-
|
|
39
|
+
- **ocrmac 고정 OCR**: Docling 변환은 항상 ocrmac / Apple Vision Framework를 사용
|
|
40
|
+
- **필수 VLM 보정**: Docling 이후 텍스트 보정, page gate, 구조 review 모델을 항상 실행
|
|
41
41
|
- **Apple Silicon 최적화**: M1/M2/M3/M4/M5 칩에서 GPU 가속 지원
|
|
42
42
|
- **자동 환경 설정**: Python 가상환경 및 docling-serve 자동 설치
|
|
43
43
|
- **이미지 추출**: PDF 내 이미지 자동 추출 및 저장
|
|
44
44
|
- **문서 유형 검증**: LLM 기반 고고학 보고서 여부 검증 (선택)
|
|
45
45
|
- **청크 변환**: 대용량 PDF를 청크로 분할하여 안정적으로 처리
|
|
46
46
|
- **이미지 PDF 폴백**: 변환 실패 시 이미지 기반 PDF로 자동 재시도
|
|
47
|
-
- **Review Assistance**:
|
|
47
|
+
- **Review Assistance**: page-level VLM review로 audit proposal을 기록하고, 의미 낮은 페이지는 관찰 가능한 사유와 함께 skip하며, 고신뢰도 수정만 자동 적용
|
|
48
|
+
- **표 보정 강화**: 표별 work item으로 셀, span, header, 단위, 각주, 인접 페이지 연속표를 검증
|
|
48
49
|
- **AbortSignal 지원**: 진행 중인 파싱 작업 취소
|
|
49
50
|
- **서버 크래시 복구**: ECONNREFUSED 발생 시 docling-serve 자동 재시작
|
|
50
51
|
|
|
@@ -84,7 +85,7 @@ python3.11 --version
|
|
|
84
85
|
|
|
85
86
|
#### 4. poppler (PDF 텍스트 추출)
|
|
86
87
|
|
|
87
|
-
PDF 페이지 수 확인(`pdfinfo`)과 텍스트 레이어 추출(`pdftotext`)에 필요하며,
|
|
88
|
+
PDF 페이지 수 확인(`pdfinfo`)과 텍스트 레이어 추출(`pdftotext`)에 필요하며, Docling 이후 보정의 참조 텍스트로 사용됩니다.
|
|
88
89
|
|
|
89
90
|
```bash
|
|
90
91
|
brew install poppler
|
|
@@ -140,6 +141,7 @@ yarn add @heripo/pdf-parser @heripo/logger
|
|
|
140
141
|
### 기본 사용법
|
|
141
142
|
|
|
142
143
|
```typescript
|
|
144
|
+
import { openai } from '@ai-sdk/openai';
|
|
143
145
|
import { Logger } from '@heripo/logger';
|
|
144
146
|
import { PDFParser } from '@heripo/pdf-parser';
|
|
145
147
|
|
|
@@ -156,6 +158,8 @@ const pdfParser = new PDFParser({
|
|
|
156
158
|
logger,
|
|
157
159
|
});
|
|
158
160
|
|
|
161
|
+
const correctionModel = openai('gpt-5.1');
|
|
162
|
+
|
|
159
163
|
// 초기화 (환경 설정 및 docling-serve 시작)
|
|
160
164
|
await pdfParser.init();
|
|
161
165
|
|
|
@@ -168,7 +172,15 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
168
172
|
console.log('PDF 변환 완료:', outputPath);
|
|
169
173
|
},
|
|
170
174
|
false, // cleanupAfterCallback
|
|
171
|
-
{
|
|
175
|
+
{
|
|
176
|
+
correction: {
|
|
177
|
+
models: {
|
|
178
|
+
textCorrection: correctionModel,
|
|
179
|
+
pageGate: correctionModel,
|
|
180
|
+
reviewAssistance: correctionModel,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
}, // PDFConvertOptions
|
|
172
184
|
);
|
|
173
185
|
|
|
174
186
|
// 토큰 사용량 리포트 (LLM 사용이 없으면 null)
|
|
@@ -201,23 +213,41 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
201
213
|
async (outputPath) => console.log(outputPath),
|
|
202
214
|
false,
|
|
203
215
|
{
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
216
|
+
// Docling 이후 필수 보정
|
|
217
|
+
correction: {
|
|
218
|
+
models: {
|
|
219
|
+
textCorrection: openai('gpt-5.1'),
|
|
220
|
+
pageGate: openai('gpt-5.1'),
|
|
221
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
222
|
+
tableCorrection: openai('gpt-5.1'),
|
|
223
|
+
reviewAssistanceTasks: {
|
|
224
|
+
text_ocr_hanja: openai('gpt-5.1'),
|
|
225
|
+
tables: openai('gpt-5.1'),
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
concurrency: {
|
|
229
|
+
pages: 1,
|
|
230
|
+
reviewTasks: 4,
|
|
231
|
+
tables: 1,
|
|
232
|
+
},
|
|
233
|
+
localModelConcurrency: 1,
|
|
234
|
+
workItemTimeoutMs: 900000,
|
|
235
|
+
maxRetries: {
|
|
236
|
+
textCorrection: 3,
|
|
237
|
+
pageGate: 3,
|
|
238
|
+
reviewAssistance: 3,
|
|
239
|
+
tableCorrection: 3,
|
|
240
|
+
},
|
|
215
241
|
autoApplyThreshold: 0.85,
|
|
216
242
|
proposalThreshold: 0.5,
|
|
243
|
+
temperature: 0,
|
|
217
244
|
outputLanguage: 'ko-KR',
|
|
218
245
|
},
|
|
219
246
|
onReviewAssistanceProgress: (event) => console.log(event),
|
|
220
247
|
|
|
248
|
+
// 문서 유형 검증
|
|
249
|
+
documentValidationModel: openai('gpt-5.1'),
|
|
250
|
+
|
|
221
251
|
// 대용량 PDF 청크 변환
|
|
222
252
|
chunkedConversion: true,
|
|
223
253
|
chunkSize: 50,
|
|
@@ -244,58 +274,52 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
244
274
|
await pdfParser.dispose();
|
|
245
275
|
```
|
|
246
276
|
|
|
247
|
-
##
|
|
277
|
+
## 필수 보정 파이프라인
|
|
248
278
|
|
|
249
|
-
###
|
|
279
|
+
### ocrmac을 고정하는 이유
|
|
250
280
|
|
|
251
281
|
**ocrmac(Apple Vision Framework)은 매우 우수한 OCR 엔진입니다** -- 무료이고, GPU 가속을 지원하며, 고품질 결과를 제공합니다. 수천~수백만 권의 고고학 보고서를 처리할 때 이만한 솔루션이 없습니다.
|
|
252
282
|
|
|
253
|
-
|
|
283
|
+
`@heripo/pdf-parser`는 더 이상 OCR strategy를 sampling하거나 VLM OCR 경로로 전환하지 않습니다. Docling 변환은 항상 ocrmac으로 실행하고, VLM은 Docling 이후 필수 보정 단계에서만 사용합니다.
|
|
254
284
|
|
|
255
|
-
###
|
|
285
|
+
### 필수 correction 계약
|
|
256
286
|
|
|
257
|
-
|
|
258
|
-
2. **VLM 샘플링** (필요 시에만): 최대 15페이지를 샘플링(앞뒤 10%는 표지·부록으로 제외)하여 Vision LLM으로 언어를 판정합니다. `ko-KR` 감지 시 즉시 종료합니다.
|
|
287
|
+
모든 `parse()` 호출은 `correction.models.textCorrection`, `correction.models.pageGate`, `correction.models.reviewAssistance`를 제공해야 합니다. 필수 모델이 누락되면 변환 callback을 감싸기 전에 명확히 실패합니다.
|
|
259
288
|
|
|
260
|
-
|
|
289
|
+
보정 단계는 다음 순서로 실행됩니다.
|
|
261
290
|
|
|
262
|
-
|
|
291
|
+
1. 변경 전 `result_ocr_origin.json`을 저장합니다.
|
|
292
|
+
2. `textCorrection` 모델로 페이지 텍스트와 표 셀 OCR을 보정합니다.
|
|
293
|
+
3. `pageGate` 모델로 Review Assistance page gate를 실행하고 `review_assistance_page_gate.json`을 기록합니다.
|
|
294
|
+
4. task별 모델로 구조 Review Assistance work item을 실행합니다.
|
|
295
|
+
5. 감지된 표마다 table-specific correction work item을 실행합니다.
|
|
296
|
+
6. 실행 중 `review_assistance_checkpoint.json`을 기록하고, 완료 시 `review_assistance.json`을 기록합니다.
|
|
263
297
|
|
|
264
|
-
|
|
265
|
-
- `pdftotext` 참조 텍스트를 품질 기준으로 활용
|
|
266
|
-
- VLM이 치환 기반 보정(find -> replace)을 반환
|
|
267
|
-
- 실패한 페이지는 원본 OCR 텍스트를 유지하며 건너뜀
|
|
298
|
+
텍스트 보정은 텍스트나 표가 있는 모든 페이지에 적용됩니다. page gate는 구조적 Review Assistance 노이즈만 제어하며, OCR 텍스트 보정 범위를 줄이지 않습니다.
|
|
268
299
|
|
|
269
|
-
###
|
|
300
|
+
### 로컬 모델 권장 실행 방식
|
|
270
301
|
|
|
271
|
-
|
|
272
|
-
const tokenUsageReport = await pdfParser.parse(
|
|
273
|
-
'file:///path/to/input.pdf',
|
|
274
|
-
'report-001',
|
|
275
|
-
async (outputPath) => console.log(outputPath),
|
|
276
|
-
false,
|
|
277
|
-
{
|
|
278
|
-
// OCR 전략 샘플링 활성화 (Vision LLM 모델 제공)
|
|
279
|
-
strategySamplerModel: openai('gpt-5.1'),
|
|
302
|
+
보정 파이프라인은 로컬 VLM 기준으로 설계되었습니다. 큰 context 하나보다 작은 context를 자주 호출하고, deterministic validator와 retry, timeout, checkpoint/resume으로 안정성을 확보합니다. 처음에는 `concurrency.pages: 1`, `concurrency.tables: 1`, `localModelConcurrency: 1`, `temperature: 0`, 충분한 `workItemTimeoutMs`로 시작하고, 모델이 안정화된 뒤 동시성을 높이는 것을 권장합니다.
|
|
280
303
|
|
|
281
|
-
|
|
282
|
-
vlmProcessorModel: openai('gpt-5.1'),
|
|
304
|
+
### 롤아웃 smoke test
|
|
283
305
|
|
|
284
|
-
|
|
285
|
-
vlmConcurrency: 3,
|
|
306
|
+
레포 contributor는 로컬 demo 고고학 보고서 산출물 2종으로 correction rollout smoke test를 실행할 수 있습니다.
|
|
286
307
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
},
|
|
290
|
-
);
|
|
308
|
+
```bash
|
|
309
|
+
pnpm --filter @heripo/pdf-parser smoke:correction
|
|
291
310
|
```
|
|
292
311
|
|
|
312
|
+
이 smoke test는 기존 demo artifact를 `/private/tmp/heripo-pdf-parser-correction-smoke`로 복사하고, deterministic local fake model로 correction을 실행한 뒤 `review_assistance.json`, 표 work-item trace, validation status, checkpoint resume 동작을 검증합니다. 파이프라인 기계적 경로를 검증하는 용도이며, 의미론적 표 보정 품질은 실제로 설정한 로컬 VLM 품질에 의존합니다.
|
|
313
|
+
|
|
293
314
|
## Review Assistance
|
|
294
315
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
316
|
+
Review Assistance는 텍스트 보정 이후 항상 실행되지만 모든 페이지를 같은 강도로 처리하지 않습니다. page gate가 표지, 챕터 표지, 바코드/ISBN 페이지, 장식 중심 페이지를 구조 review 저가치 페이지로 분류합니다. skip된 페이지도 `review_assistance.json`에 info issue와 skip reason으로 남습니다.
|
|
317
|
+
|
|
318
|
+
eligible page는 text OCR/Hanja, text integrity, text role/footnote, tables, pictures/captions, layout/bbox/order, table-specific correction 같은 작은 work item으로 쪼개집니다. 각 호출의 timing, model id, attempts, target refs, deterministic validation status는 `review_assistance.json`에 기록됩니다.
|
|
319
|
+
|
|
320
|
+
### 표 보정 전략
|
|
321
|
+
|
|
322
|
+
표는 page 부속물이 아니라 1급 보정 대상으로 처리합니다. scheduler는 표마다 독립 table-specific work item을 만들기 때문에 한 페이지에 표가 여러 개 있어도 bbox, crop, context, validation 상태가 섞이지 않습니다. table validator는 target identity, 같은 페이지 다른 표 내용 혼입, cell, span, header, unit, footnote, empty-cell expansion, adjacent-page continuation ref를 확인한 뒤에야 auto-apply 또는 proposal 결정을 허용합니다.
|
|
299
323
|
|
|
300
324
|
```typescript
|
|
301
325
|
const tokenUsageReport = await pdfParser.parse(
|
|
@@ -304,13 +328,21 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
304
328
|
async (outputPath) => console.log(outputPath),
|
|
305
329
|
false,
|
|
306
330
|
{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
331
|
+
correction: {
|
|
332
|
+
models: {
|
|
333
|
+
textCorrection: openai('gpt-5.1'),
|
|
334
|
+
pageGate: openai('gpt-5.1-mini'),
|
|
335
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
336
|
+
tableCorrection: openai('gpt-5.1'),
|
|
337
|
+
},
|
|
311
338
|
autoApplyThreshold: 0.85,
|
|
312
339
|
proposalThreshold: 0.5,
|
|
313
|
-
maxRetries:
|
|
340
|
+
maxRetries: {
|
|
341
|
+
textCorrection: 3,
|
|
342
|
+
pageGate: 3,
|
|
343
|
+
reviewAssistance: 3,
|
|
344
|
+
tableCorrection: 3,
|
|
345
|
+
},
|
|
314
346
|
temperature: 0,
|
|
315
347
|
outputLanguage: 'ko-KR',
|
|
316
348
|
},
|
|
@@ -321,10 +353,7 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
321
353
|
);
|
|
322
354
|
```
|
|
323
355
|
|
|
324
|
-
Review Assistance는 로컬 `file://` PDF
|
|
325
|
-
`strategySamplerModel`이 필요합니다. 고신뢰도 수정은 `result.json`에 적용하고,
|
|
326
|
-
원본 snapshot은 `result_review_origin.json`, `result_ocr_origin.json`에 보존하며,
|
|
327
|
-
페이지별 결정, 이슈, proposal, 요약 count는 `review_assistance.json`에 기록합니다.
|
|
356
|
+
Review Assistance는 page image와 text-layer reference를 위해 로컬 `file://` PDF를 필요로 합니다. 고신뢰도 수정은 `result.json`에 적용하고, 원본 snapshot은 `result_review_origin.json`, `result_ocr_origin.json`에 보존하며, `review_assistance_page_gate.json`과 페이지별 결정, 이슈, proposal, call trace, validation status, 요약 count를 담은 `review_assistance.json`을 기록합니다.
|
|
328
357
|
|
|
329
358
|
## 문서 유형 검증
|
|
330
359
|
|
|
@@ -340,6 +369,13 @@ try {
|
|
|
340
369
|
async (outputPath) => console.log(outputPath),
|
|
341
370
|
false,
|
|
342
371
|
{
|
|
372
|
+
correction: {
|
|
373
|
+
models: {
|
|
374
|
+
textCorrection: openai('gpt-5.1'),
|
|
375
|
+
pageGate: openai('gpt-5.1'),
|
|
376
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
377
|
+
},
|
|
378
|
+
},
|
|
343
379
|
documentValidationModel: openai('gpt-5.1'),
|
|
344
380
|
},
|
|
345
381
|
);
|
|
@@ -361,6 +397,13 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
361
397
|
async (outputPath) => console.log(outputPath),
|
|
362
398
|
false,
|
|
363
399
|
{
|
|
400
|
+
correction: {
|
|
401
|
+
models: {
|
|
402
|
+
textCorrection: openai('gpt-5.1'),
|
|
403
|
+
pageGate: openai('gpt-5.1'),
|
|
404
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
405
|
+
},
|
|
406
|
+
},
|
|
364
407
|
chunkedConversion: true,
|
|
365
408
|
chunkSize: 50, // 청크당 페이지 수 (기본값: 상수에서 설정)
|
|
366
409
|
chunkMaxRetries: 3, // 실패한 청크의 최대 재시도 횟수 (기본값: 상수에서 설정)
|
|
@@ -395,6 +438,13 @@ const tokenUsageReport = await pdfParser.parse(
|
|
|
395
438
|
async (outputPath) => console.log(outputPath),
|
|
396
439
|
false,
|
|
397
440
|
{
|
|
441
|
+
correction: {
|
|
442
|
+
models: {
|
|
443
|
+
textCorrection: openai('gpt-5.1'),
|
|
444
|
+
pageGate: openai('gpt-5.1'),
|
|
445
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
446
|
+
},
|
|
447
|
+
},
|
|
398
448
|
forceImagePdf: true, // 항상 이미지 PDF로 먼저 변환
|
|
399
449
|
},
|
|
400
450
|
);
|
|
@@ -418,7 +468,15 @@ try {
|
|
|
418
468
|
'report-001',
|
|
419
469
|
async (outputPath) => console.log(outputPath),
|
|
420
470
|
false,
|
|
421
|
-
{
|
|
471
|
+
{
|
|
472
|
+
correction: {
|
|
473
|
+
models: {
|
|
474
|
+
textCorrection: openai('gpt-5.1'),
|
|
475
|
+
pageGate: openai('gpt-5.1'),
|
|
476
|
+
reviewAssistance: openai('gpt-5.1'),
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
422
480
|
controller.signal, // AbortSignal
|
|
423
481
|
);
|
|
424
482
|
} catch (error) {
|
|
@@ -560,12 +618,8 @@ await pdfParser.dispose();
|
|
|
560
618
|
|
|
561
619
|
```typescript
|
|
562
620
|
type PDFConvertOptions = {
|
|
563
|
-
//
|
|
564
|
-
|
|
565
|
-
vlmProcessorModel?: LanguageModel; // 텍스트 보정용 Vision LLM
|
|
566
|
-
vlmConcurrency?: number; // 병렬 페이지 처리 (기본값: 1)
|
|
567
|
-
skipSampling?: boolean; // 전략 샘플링 건너뛰기
|
|
568
|
-
forcedMethod?: 'ocrmac' | 'vlm'; // 특정 OCR 방식 강제
|
|
621
|
+
// Docling 이후 필수 보정
|
|
622
|
+
correction: PDFCorrectionOptions;
|
|
569
623
|
|
|
570
624
|
// 이미지 PDF 옵션
|
|
571
625
|
forceImagePdf?: boolean; // 이미지 기반 PDF 사전 변환 강제
|
|
@@ -578,8 +632,7 @@ type PDFConvertOptions = {
|
|
|
578
632
|
document_timeout?: number; // 문서 처리 타임아웃 (초)
|
|
579
633
|
documentValidationModel?: LanguageModel; // 문서 유형 검증용 LLM
|
|
580
634
|
|
|
581
|
-
//
|
|
582
|
-
reviewAssistance?: boolean | ReviewAssistanceOptions; // 선택적 page-level review
|
|
635
|
+
// 보정 진행 상황
|
|
583
636
|
onReviewAssistanceProgress?: (event: ReviewAssistanceProgressEvent) => void; // 진행 상황 callback
|
|
584
637
|
|
|
585
638
|
// 청크 변환 (대용량 PDF)
|
|
@@ -594,27 +647,47 @@ type PDFConvertOptions = {
|
|
|
594
647
|
};
|
|
595
648
|
```
|
|
596
649
|
|
|
597
|
-
###
|
|
650
|
+
### PDFCorrectionOptions
|
|
598
651
|
|
|
599
652
|
```typescript
|
|
600
|
-
interface
|
|
601
|
-
|
|
653
|
+
interface PDFCorrectionOptions {
|
|
654
|
+
models: {
|
|
655
|
+
textCorrection: LanguageModel; // 필수: 페이지 텍스트와 표 셀 OCR 보정
|
|
656
|
+
pageGate: LanguageModel; // 필수: 구조 Review Assistance page gate
|
|
657
|
+
reviewAssistance: LanguageModel; // 필수: 기본 구조 review 모델
|
|
658
|
+
tableCorrection?: LanguageModel; // 선택: 표 전용 보정 override
|
|
659
|
+
reviewAssistanceTasks?: Partial<
|
|
660
|
+
Record<
|
|
661
|
+
| 'text_ocr_hanja'
|
|
662
|
+
| 'text_integrity'
|
|
663
|
+
| 'text_role_footnote'
|
|
664
|
+
| 'tables'
|
|
665
|
+
| 'pictures_captions'
|
|
666
|
+
| 'layout_bbox_order',
|
|
667
|
+
LanguageModel
|
|
668
|
+
>
|
|
669
|
+
>;
|
|
670
|
+
};
|
|
671
|
+
concurrency?: {
|
|
672
|
+
pages?: number; // 페이지 단위 text correction/page gate 동시성
|
|
673
|
+
reviewTasks?: number; // 구조 Review Assistance work-item 동시성
|
|
674
|
+
tables?: number; // 표 전용 보정 동시성
|
|
675
|
+
};
|
|
676
|
+
maxRetries?: {
|
|
677
|
+
textCorrection?: number;
|
|
678
|
+
pageGate?: number;
|
|
679
|
+
reviewAssistance?: number;
|
|
680
|
+
tableCorrection?: number;
|
|
681
|
+
};
|
|
682
|
+
localModelConcurrency?: number; // 로컬 모델 요청 동시성 상한
|
|
683
|
+
workItemTimeoutMs?: number; // work item별 timeout
|
|
684
|
+
outputLanguage?: string; // 사람이 읽는 review reason 언어 (기본값: en-US)
|
|
685
|
+
pageGate?: {
|
|
686
|
+
structuralNoiseThreshold?: number;
|
|
687
|
+
};
|
|
602
688
|
autoApplyThreshold?: number; // 자동 적용 최소 confidence (기본값: 0.85)
|
|
603
689
|
proposalThreshold?: number; // sidecar proposal 최소 confidence (기본값: 0.5)
|
|
604
|
-
maxRetries?: number; // page-level VLM 호출별 최대 재시도 횟수 (기본값: 3)
|
|
605
690
|
temperature?: number; // VLM 생성 temperature (기본값: 0)
|
|
606
|
-
outputLanguage?: string; // 사람이 읽는 review reason 언어 (기본값: en-US)
|
|
607
|
-
}
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
### ConvertWithStrategyResult
|
|
611
|
-
|
|
612
|
-
```typescript
|
|
613
|
-
interface ConvertWithStrategyResult {
|
|
614
|
-
/** 결정된 OCR 전략 */
|
|
615
|
-
strategy: OcrStrategy;
|
|
616
|
-
/** 샘플링 및/또는 VLM 처리의 토큰 사용량 리포트 (LLM 사용이 없으면 null) */
|
|
617
|
-
tokenUsageReport: TokenUsageReport | null;
|
|
618
691
|
}
|
|
619
692
|
```
|
|
620
693
|
|