@customize-agent/knowledge 4.0.13 → 4.0.15
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/dist/core/knowledge-base-manager.d.ts +0 -2
- package/dist/core/knowledge-base-manager.js +1 -1
- package/dist/extraction/content-extractor.d.ts +8 -9
- package/dist/extraction/content-extractor.js +294 -304
- package/dist/extraction/ocr-providers.d.ts +47 -0
- package/dist/extraction/ocr-providers.js +106 -0
- package/models/paddleocr/PP-OCRv5_mobile_det_infer.onnx +0 -0
- package/models/paddleocr/PP-OCRv5_mobile_rec_infer.onnx +0 -0
- package/models/paddleocr/ppocrv5_dict.txt +18384 -0
- package/models/tessdata/chi_sim.traineddata +0 -0
- package/models/tessdata/eng.traineddata +0 -0
- package/package.json +7 -3
- package/scripts/download-paddleocr-models.sh +63 -0
- package/scripts/render_pdf_pages.py +29 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR 提供者 — tesseract.js 跨平台 WASM
|
|
3
|
+
*
|
|
4
|
+
* 使用 tesseract.js v7(WASM),bundled traineddata,
|
|
5
|
+
* 真正跨平台(Windows/macOS/Linux),无需系统依赖。
|
|
6
|
+
*/
|
|
7
|
+
export interface OcrRegion {
|
|
8
|
+
text: string;
|
|
9
|
+
confidence: number;
|
|
10
|
+
box: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface OcrResult {
|
|
18
|
+
text: string;
|
|
19
|
+
confidence: number;
|
|
20
|
+
regions: OcrRegion[];
|
|
21
|
+
}
|
|
22
|
+
export interface OcrProvider {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly available: boolean;
|
|
25
|
+
recognize(input: {
|
|
26
|
+
data: Uint8Array;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
channels?: number;
|
|
30
|
+
filePath?: string;
|
|
31
|
+
}): Promise<OcrResult>;
|
|
32
|
+
dispose(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export declare class TesseractJsProvider implements OcrProvider {
|
|
35
|
+
readonly id = "tesseract.js";
|
|
36
|
+
private _available;
|
|
37
|
+
get available(): boolean;
|
|
38
|
+
recognize(input: {
|
|
39
|
+
data: Uint8Array;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
channels?: number;
|
|
43
|
+
filePath?: string;
|
|
44
|
+
}): Promise<OcrResult>;
|
|
45
|
+
dispose(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
export declare function createOcrProvider(): Promise<OcrProvider>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR 提供者 — tesseract.js 跨平台 WASM
|
|
3
|
+
*
|
|
4
|
+
* 使用 tesseract.js v7(WASM),bundled traineddata,
|
|
5
|
+
* 真正跨平台(Windows/macOS/Linux),无需系统依赖。
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { resolveAndImport, resolvePackage } from './module-resolver.js';
|
|
12
|
+
// ─── 路径工具 ───────────────────────────────────────────────────
|
|
13
|
+
const knowledgeDir = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
function tessdataDir() {
|
|
15
|
+
if (process.env.TESSDATA_PREFIX)
|
|
16
|
+
return process.env.TESSDATA_PREFIX;
|
|
17
|
+
const pkg = path.resolve(knowledgeDir, '..', '..', 'models', 'tessdata');
|
|
18
|
+
if (fs.existsSync(pkg))
|
|
19
|
+
return pkg;
|
|
20
|
+
return pkg;
|
|
21
|
+
}
|
|
22
|
+
// ─── Tesseract.js Provider(主 OCR 引擎,跨平台) ──────────────
|
|
23
|
+
export class TesseractJsProvider {
|
|
24
|
+
id = 'tesseract.js';
|
|
25
|
+
_available = null;
|
|
26
|
+
get available() {
|
|
27
|
+
if (this._available !== null)
|
|
28
|
+
return this._available;
|
|
29
|
+
// 检查 traineddata 和 tesseract.js 是否可用
|
|
30
|
+
const td = tessdataDir();
|
|
31
|
+
const hasChiSim = fs.existsSync(path.join(td, 'chi_sim.traineddata'));
|
|
32
|
+
try {
|
|
33
|
+
resolvePackage('tesseract.js');
|
|
34
|
+
this._available = hasChiSim;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
this._available = false;
|
|
38
|
+
}
|
|
39
|
+
return this._available;
|
|
40
|
+
}
|
|
41
|
+
async recognize(input) {
|
|
42
|
+
const tessMod = await resolveAndImport('tesseract.js');
|
|
43
|
+
const { createWorker } = tessMod;
|
|
44
|
+
let pngPath;
|
|
45
|
+
let tmpDir = null;
|
|
46
|
+
// 如果传了 filePath,直接使用;否则 raw pixels → PNG
|
|
47
|
+
if (input.filePath && fs.existsSync(input.filePath)) {
|
|
48
|
+
pngPath = input.filePath;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const sharpMod = await resolveAndImport('sharp');
|
|
52
|
+
const sharpFn = sharpMod.default ?? sharpMod;
|
|
53
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ocr-'));
|
|
54
|
+
pngPath = path.join(tmpDir, 'input.png');
|
|
55
|
+
const channels = input.channels ?? 3;
|
|
56
|
+
await sharpFn(Buffer.from(input.data), {
|
|
57
|
+
raw: { width: input.width, height: input.height, channels },
|
|
58
|
+
})
|
|
59
|
+
.removeAlpha().normalize().linear(3.0, -150)
|
|
60
|
+
.withMetadata({ density: 288 })
|
|
61
|
+
.png().toFile(pngPath);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
// tesseract.js worker(数组形式 languages)
|
|
65
|
+
const worker = await createWorker(['chi_sim', 'eng'], 1, {
|
|
66
|
+
langPath: tessdataDir(),
|
|
67
|
+
gzip: false,
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
const result = await worker.recognize(pngPath);
|
|
71
|
+
const text = (result.data.text ?? '').trim();
|
|
72
|
+
const lines = (result.data.lines ?? []);
|
|
73
|
+
const regions = lines
|
|
74
|
+
.filter((l) => l.text?.trim())
|
|
75
|
+
.map((l) => ({
|
|
76
|
+
text: l.text.trim(),
|
|
77
|
+
confidence: l.confidence ?? 0,
|
|
78
|
+
box: {
|
|
79
|
+
x: l.bbox?.x0 ?? 0,
|
|
80
|
+
y: l.bbox?.y0 ?? 0,
|
|
81
|
+
width: (l.bbox?.x1 ?? 0) - (l.bbox?.x0 ?? 0),
|
|
82
|
+
height: (l.bbox?.y1 ?? 0) - (l.bbox?.y0 ?? 0),
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
return { text, confidence: result.data.confidence ?? 0, regions };
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await worker.terminate();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
if (tmpDir)
|
|
93
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async dispose() { }
|
|
97
|
+
}
|
|
98
|
+
// ─── 工厂 ───────────────────────────────────────────────────────
|
|
99
|
+
export async function createOcrProvider() {
|
|
100
|
+
const tess = new TesseractJsProvider();
|
|
101
|
+
if (tess.available)
|
|
102
|
+
return tess;
|
|
103
|
+
const td = tessdataDir();
|
|
104
|
+
throw new Error(`OCR 不可用。请将 chi_sim.traineddata 和 eng.traineddata 放置到 ${td},` +
|
|
105
|
+
'并确保 tesseract.js 已安装。');
|
|
106
|
+
}
|
|
Binary file
|
|
Binary file
|