med-pdf-nmo 0.1.0
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/LICENSE +21 -0
- package/README.md +298 -0
- package/README.ru.md +298 -0
- package/dist/bm25.d.ts +47 -0
- package/dist/bm25.js +86 -0
- package/dist/browser-shims/buffer.d.ts +30 -0
- package/dist/browser-shims/buffer.js +31 -0
- package/dist/browser-shims/crypto.d.ts +33 -0
- package/dist/browser-shims/crypto.js +45 -0
- package/dist/browser-shims/fs-promises.d.ts +13 -0
- package/dist/browser-shims/fs-promises.js +25 -0
- package/dist/browser-shims/fs.d.ts +14 -0
- package/dist/browser-shims/fs.js +24 -0
- package/dist/browser-shims/globals.d.ts +9 -0
- package/dist/browser-shims/globals.js +23 -0
- package/dist/browser-shims/path.d.ts +57 -0
- package/dist/browser-shims/path.js +65 -0
- package/dist/browser-shims/process.d.ts +22 -0
- package/dist/browser-shims/process.js +27 -0
- package/dist/browser.d.ts +9 -0
- package/dist/browser.js +12 -0
- package/dist/chunk.d.ts +15 -0
- package/dist/chunk.js +76 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +87 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +51 -0
- package/dist/med-pdf-nmo.browser.js +40413 -0
- package/dist/med-pdf-nmo.browser.mjs +40395 -0
- package/dist/normalize.d.ts +73 -0
- package/dist/normalize.js +477 -0
- package/dist/pdf.d.ts +35 -0
- package/dist/pdf.js +396 -0
- package/dist/predictor/config.d.ts +28 -0
- package/dist/predictor/config.js +26 -0
- package/dist/predictor/constants.d.ts +3 -0
- package/dist/predictor/constants.js +59 -0
- package/dist/predictor/runtime.d.ts +15 -0
- package/dist/predictor/runtime.js +59 -0
- package/dist/predictor/scorers/biomedical-symbols.d.ts +36 -0
- package/dist/predictor/scorers/biomedical-symbols.js +347 -0
- package/dist/predictor/scorers/coordinate-table.d.ts +82 -0
- package/dist/predictor/scorers/coordinate-table.js +1210 -0
- package/dist/predictor/scorers/direction.d.ts +71 -0
- package/dist/predictor/scorers/direction.js +345 -0
- package/dist/predictor/scorers/drug-dose.d.ts +6 -0
- package/dist/predictor/scorers/drug-dose.js +221 -0
- package/dist/predictor/scorers/exact-answer.d.ts +10 -0
- package/dist/predictor/scorers/exact-answer.js +75 -0
- package/dist/predictor/scorers/fibrosis-stage.d.ts +6 -0
- package/dist/predictor/scorers/fibrosis-stage.js +103 -0
- package/dist/predictor/scorers/focused.d.ts +40 -0
- package/dist/predictor/scorers/focused.js +204 -0
- package/dist/predictor/scorers/frequency.d.ts +10 -0
- package/dist/predictor/scorers/frequency.js +203 -0
- package/dist/predictor/scorers/numeric.d.ts +77 -0
- package/dist/predictor/scorers/numeric.js +1161 -0
- package/dist/predictor/scorers/recommendation-item.d.ts +27 -0
- package/dist/predictor/scorers/recommendation-item.js +469 -0
- package/dist/predictor/scorers/search.d.ts +41 -0
- package/dist/predictor/scorers/search.js +515 -0
- package/dist/predictor/selection.d.ts +30 -0
- package/dist/predictor/selection.js +370 -0
- package/dist/predictor/text-utils.d.ts +49 -0
- package/dist/predictor/text-utils.js +497 -0
- package/dist/predictor/types.d.ts +23 -0
- package/dist/predictor/types.js +1 -0
- package/dist/predictor.d.ts +52 -0
- package/dist/predictor.js +3834 -0
- package/package.json +82 -0
package/dist/bm25.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { tokenize } from "./normalize.js";
|
|
2
|
+
/**
|
|
3
|
+
* Небольшая реализация BM25 для локального поиска по чанкам PDF.
|
|
4
|
+
*/
|
|
5
|
+
export class BM25Index {
|
|
6
|
+
documents;
|
|
7
|
+
k1;
|
|
8
|
+
b;
|
|
9
|
+
docFreq;
|
|
10
|
+
termFreqs;
|
|
11
|
+
lengths;
|
|
12
|
+
avgdl;
|
|
13
|
+
/**
|
|
14
|
+
* Создает индекс для уже токенизированных документов.
|
|
15
|
+
*
|
|
16
|
+
* @param documents Документы с необязательными массивами `tokens`.
|
|
17
|
+
* @param options Параметры настройки BM25.
|
|
18
|
+
*/
|
|
19
|
+
constructor(documents, { k1 = 1.35, b = 0.72 } = {}) {
|
|
20
|
+
this.documents = documents;
|
|
21
|
+
this.k1 = k1;
|
|
22
|
+
this.b = b;
|
|
23
|
+
this.docFreq = new Map();
|
|
24
|
+
this.termFreqs = [];
|
|
25
|
+
this.lengths = [];
|
|
26
|
+
let totalLength = 0;
|
|
27
|
+
for (const document of documents) {
|
|
28
|
+
const frequencies = new Map();
|
|
29
|
+
for (const token of document.tokens ?? []) {
|
|
30
|
+
frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
|
|
31
|
+
}
|
|
32
|
+
this.termFreqs.push(frequencies);
|
|
33
|
+
this.lengths.push(document.tokens?.length ?? 0);
|
|
34
|
+
totalLength += document.tokens?.length ?? 0;
|
|
35
|
+
for (const token of frequencies.keys()) {
|
|
36
|
+
this.docFreq.set(token, (this.docFreq.get(token) ?? 0) + 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
this.avgdl = documents.length ? totalLength / documents.length : 0;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Считает inverse document frequency для одного нормализованного токена.
|
|
43
|
+
*/
|
|
44
|
+
idf(token) {
|
|
45
|
+
const n = this.documents.length;
|
|
46
|
+
const df = this.docFreq.get(token) ?? 0;
|
|
47
|
+
return Math.log(1 + (n - df + 0.5) / (df + 0.5));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Считает score токенизированного запроса для одного документа в индексе.
|
|
51
|
+
*/
|
|
52
|
+
scoreTokens(queryTokens, docIndex) {
|
|
53
|
+
const frequencies = this.termFreqs[docIndex];
|
|
54
|
+
if (!frequencies)
|
|
55
|
+
return 0;
|
|
56
|
+
const dl = this.lengths[docIndex] || 1;
|
|
57
|
+
let score = 0;
|
|
58
|
+
for (const token of queryTokens) {
|
|
59
|
+
const tf = frequencies.get(token) ?? 0;
|
|
60
|
+
if (!tf)
|
|
61
|
+
continue;
|
|
62
|
+
const idf = this.idf(token);
|
|
63
|
+
const denom = tf + this.k1 * (1 - this.b + this.b * (dl / (this.avgdl || 1)));
|
|
64
|
+
score += idf * ((tf * (this.k1 + 1)) / denom);
|
|
65
|
+
}
|
|
66
|
+
return score;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Ищет по индексу сырой текст или заранее токенизированный запрос.
|
|
70
|
+
*
|
|
71
|
+
* @returns Лучшие совпадающие чанки с положительным BM25 score.
|
|
72
|
+
*/
|
|
73
|
+
search(query, { limit = 10 } = {}) {
|
|
74
|
+
const queryTokens = Array.isArray(query) ? query : tokenize(query);
|
|
75
|
+
if (!queryTokens.length)
|
|
76
|
+
return [];
|
|
77
|
+
const scores = [];
|
|
78
|
+
for (let i = 0; i < this.documents.length; i += 1) {
|
|
79
|
+
const score = this.scoreTokens(queryTokens, i);
|
|
80
|
+
if (score > 0)
|
|
81
|
+
scores.push({ chunk: this.documents[i], score });
|
|
82
|
+
}
|
|
83
|
+
scores.sort((a, b) => b.score - a.score);
|
|
84
|
+
return scores.slice(0, limit);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
declare function from(input: string | ArrayBuffer | ArrayBufferView | ArrayLike<number>, encoding?: string): Uint8Array<ArrayBuffer | SharedArrayBuffer>;
|
|
2
|
+
/**
|
|
3
|
+
* Минимальный browser-compatible `Buffer`, достаточный для `Buffer.from(...)` в пользовательском коде.
|
|
4
|
+
*
|
|
5
|
+
* Это не полный polyfill Node.js Buffer. Для runtime predictor достаточно `Uint8Array`, поэтому shim
|
|
6
|
+
* намеренно покрывает только безопасное преобразование строк, ArrayBuffer и array-like данных в bytes.
|
|
7
|
+
*/
|
|
8
|
+
export declare const Buffer: {
|
|
9
|
+
/**
|
|
10
|
+
* Создает byte buffer из строки, ArrayBuffer, TypedArray или массива чисел.
|
|
11
|
+
*
|
|
12
|
+
* @param input Данные, которые нужно представить как `Uint8Array`.
|
|
13
|
+
* @param encoding Поддерживается только `utf8`/`utf-8` для строк.
|
|
14
|
+
* @returns Uint8Array-совместимый объект с именем `Buffer`.
|
|
15
|
+
*/
|
|
16
|
+
from: typeof from;
|
|
17
|
+
};
|
|
18
|
+
declare const _default: {
|
|
19
|
+
Buffer: {
|
|
20
|
+
/**
|
|
21
|
+
* Создает byte buffer из строки, ArrayBuffer, TypedArray или массива чисел.
|
|
22
|
+
*
|
|
23
|
+
* @param input Данные, которые нужно представить как `Uint8Array`.
|
|
24
|
+
* @param encoding Поддерживается только `utf8`/`utf-8` для строк.
|
|
25
|
+
* @returns Uint8Array-совместимый объект с именем `Buffer`.
|
|
26
|
+
*/
|
|
27
|
+
from: typeof from;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function from(input, encoding = "utf8") {
|
|
2
|
+
if (typeof input === "string") {
|
|
3
|
+
if (encoding && !/^utf-?8$/iu.test(encoding)) {
|
|
4
|
+
throw new Error(`Browser Buffer shim supports only utf8 strings, got "${encoding}".`);
|
|
5
|
+
}
|
|
6
|
+
return new Uint8Array(new TextEncoder().encode(input));
|
|
7
|
+
}
|
|
8
|
+
if (input instanceof ArrayBuffer)
|
|
9
|
+
return new Uint8Array(input.slice(0));
|
|
10
|
+
if (ArrayBuffer.isView(input)) {
|
|
11
|
+
return new Uint8Array(input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength));
|
|
12
|
+
}
|
|
13
|
+
return new Uint8Array(Array.from(input));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Минимальный browser-compatible `Buffer`, достаточный для `Buffer.from(...)` в пользовательском коде.
|
|
17
|
+
*
|
|
18
|
+
* Это не полный polyfill Node.js Buffer. Для runtime predictor достаточно `Uint8Array`, поэтому shim
|
|
19
|
+
* намеренно покрывает только безопасное преобразование строк, ArrayBuffer и array-like данных в bytes.
|
|
20
|
+
*/
|
|
21
|
+
export const Buffer = {
|
|
22
|
+
/**
|
|
23
|
+
* Создает byte buffer из строки, ArrayBuffer, TypedArray или массива чисел.
|
|
24
|
+
*
|
|
25
|
+
* @param input Данные, которые нужно представить как `Uint8Array`.
|
|
26
|
+
* @param encoding Поддерживается только `utf8`/`utf-8` для строк.
|
|
27
|
+
* @returns Uint8Array-совместимый объект с именем `Buffer`.
|
|
28
|
+
*/
|
|
29
|
+
from,
|
|
30
|
+
};
|
|
31
|
+
export default { Buffer };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser shim для небольшого подмножества `node:crypto`.
|
|
3
|
+
*
|
|
4
|
+
* Predictor использует Web Crypto через browser/PDF.js окружение. Этот файл нужен как alias target
|
|
5
|
+
* для bundler-ов, которые встречают `crypto` или `node:crypto` в optional browser dependency branches.
|
|
6
|
+
*/
|
|
7
|
+
export declare const webcrypto: Crypto;
|
|
8
|
+
/**
|
|
9
|
+
* Заполняет TypedArray криптографически случайными байтами через Web Crypto.
|
|
10
|
+
*
|
|
11
|
+
* @param array TypedArray, который нужно заполнить.
|
|
12
|
+
* @returns Тот же TypedArray после заполнения.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getRandomValues<T extends ArrayBufferView>(array: T): T;
|
|
15
|
+
/**
|
|
16
|
+
* Возвращает UUID через Web Crypto, либо генерирует RFC4122 v4 fallback из случайных байтов.
|
|
17
|
+
*
|
|
18
|
+
* @returns UUID string.
|
|
19
|
+
*/
|
|
20
|
+
export declare function randomUUID(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Заглушка для Node-only hashing API.
|
|
23
|
+
*
|
|
24
|
+
* @throws Всегда, потому что `createHash` не имеет совместимого синхронного browser API.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createHash(): void;
|
|
27
|
+
declare const _default: {
|
|
28
|
+
webcrypto: Crypto;
|
|
29
|
+
getRandomValues: typeof getRandomValues;
|
|
30
|
+
randomUUID: typeof randomUUID;
|
|
31
|
+
createHash: typeof createHash;
|
|
32
|
+
};
|
|
33
|
+
export default _default;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser shim для небольшого подмножества `node:crypto`.
|
|
3
|
+
*
|
|
4
|
+
* Predictor использует Web Crypto через browser/PDF.js окружение. Этот файл нужен как alias target
|
|
5
|
+
* для bundler-ов, которые встречают `crypto` или `node:crypto` в optional browser dependency branches.
|
|
6
|
+
*/
|
|
7
|
+
export const webcrypto = globalThis.crypto;
|
|
8
|
+
/**
|
|
9
|
+
* Заполняет TypedArray криптографически случайными байтами через Web Crypto.
|
|
10
|
+
*
|
|
11
|
+
* @param array TypedArray, который нужно заполнить.
|
|
12
|
+
* @returns Тот же TypedArray после заполнения.
|
|
13
|
+
*/
|
|
14
|
+
export function getRandomValues(array) {
|
|
15
|
+
if (!globalThis.crypto?.getRandomValues) {
|
|
16
|
+
throw new Error("Web Crypto getRandomValues() is not available in this browser.");
|
|
17
|
+
}
|
|
18
|
+
globalThis.crypto.getRandomValues(array);
|
|
19
|
+
return array;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Возвращает UUID через Web Crypto, либо генерирует RFC4122 v4 fallback из случайных байтов.
|
|
23
|
+
*
|
|
24
|
+
* @returns UUID string.
|
|
25
|
+
*/
|
|
26
|
+
export function randomUUID() {
|
|
27
|
+
if (globalThis.crypto?.randomUUID)
|
|
28
|
+
return globalThis.crypto.randomUUID();
|
|
29
|
+
const bytes = getRandomValues(new Uint8Array(16));
|
|
30
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
31
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
32
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0"));
|
|
33
|
+
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex
|
|
34
|
+
.slice(8, 10)
|
|
35
|
+
.join("")}-${hex.slice(10, 16).join("")}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Заглушка для Node-only hashing API.
|
|
39
|
+
*
|
|
40
|
+
* @throws Всегда, потому что `createHash` не имеет совместимого синхронного browser API.
|
|
41
|
+
*/
|
|
42
|
+
export function createHash() {
|
|
43
|
+
throw new Error("node:crypto createHash() is not available in the browser shim.");
|
|
44
|
+
}
|
|
45
|
+
export default { webcrypto, getRandomValues, randomUUID, createHash };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function readFile(): Promise<never>;
|
|
2
|
+
export declare function writeFile(): Promise<never>;
|
|
3
|
+
export declare function mkdir(): Promise<never>;
|
|
4
|
+
export declare function rm(): Promise<never>;
|
|
5
|
+
export declare function stat(): Promise<never>;
|
|
6
|
+
declare const _default: {
|
|
7
|
+
readFile: typeof readFile;
|
|
8
|
+
writeFile: typeof writeFile;
|
|
9
|
+
mkdir: typeof mkdir;
|
|
10
|
+
rm: typeof rm;
|
|
11
|
+
stat: typeof stat;
|
|
12
|
+
};
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser shim для `node:fs/promises`.
|
|
3
|
+
*
|
|
4
|
+
* Файловая система недоступна в браузере. Экспортируемые функции существуют только как alias target,
|
|
5
|
+
* чтобы optional Node branches в зависимостях не ломали сборку приложения.
|
|
6
|
+
*/
|
|
7
|
+
function unavailable(name) {
|
|
8
|
+
throw new Error(`node:fs/promises ${name}() is not available in the browser.`);
|
|
9
|
+
}
|
|
10
|
+
export async function readFile() {
|
|
11
|
+
return unavailable("readFile");
|
|
12
|
+
}
|
|
13
|
+
export async function writeFile() {
|
|
14
|
+
return unavailable("writeFile");
|
|
15
|
+
}
|
|
16
|
+
export async function mkdir() {
|
|
17
|
+
return unavailable("mkdir");
|
|
18
|
+
}
|
|
19
|
+
export async function rm() {
|
|
20
|
+
return unavailable("rm");
|
|
21
|
+
}
|
|
22
|
+
export async function stat() {
|
|
23
|
+
return unavailable("stat");
|
|
24
|
+
}
|
|
25
|
+
export default { readFile, writeFile, mkdir, rm, stat };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as promises from "./fs-promises.js";
|
|
2
|
+
export { promises };
|
|
3
|
+
export declare function readFileSync(): never;
|
|
4
|
+
export declare function writeFileSync(): never;
|
|
5
|
+
export declare function existsSync(): false;
|
|
6
|
+
export declare function statSync(): never;
|
|
7
|
+
declare const _default: {
|
|
8
|
+
promises: typeof promises;
|
|
9
|
+
readFileSync: typeof readFileSync;
|
|
10
|
+
writeFileSync: typeof writeFileSync;
|
|
11
|
+
existsSync: typeof existsSync;
|
|
12
|
+
statSync: typeof statSync;
|
|
13
|
+
};
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as promises from "./fs-promises.js";
|
|
2
|
+
/**
|
|
3
|
+
* Browser shim для `node:fs`.
|
|
4
|
+
*
|
|
5
|
+
* Runtime predictor принимает PDF как bytes/File/Blob/URL и не требует доступа к файловой системе.
|
|
6
|
+
* Эти exports нужны для bundler alias-ов, когда optional Node branches попадают в dependency graph.
|
|
7
|
+
*/
|
|
8
|
+
function unavailable(name) {
|
|
9
|
+
throw new Error(`node:fs ${name}() is not available in the browser.`);
|
|
10
|
+
}
|
|
11
|
+
export { promises };
|
|
12
|
+
export function readFileSync() {
|
|
13
|
+
return unavailable("readFileSync");
|
|
14
|
+
}
|
|
15
|
+
export function writeFileSync() {
|
|
16
|
+
return unavailable("writeFileSync");
|
|
17
|
+
}
|
|
18
|
+
export function existsSync() {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
export function statSync() {
|
|
22
|
+
return unavailable("statSync");
|
|
23
|
+
}
|
|
24
|
+
export default { promises, readFileSync, writeFileSync, existsSync, statSync };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Buffer } from "./buffer.js";
|
|
2
|
+
import processShim from "./process.js";
|
|
3
|
+
/**
|
|
4
|
+
* Устанавливает минимальные browser globals, которые часто ожидают Node-oriented dependency branches.
|
|
5
|
+
*
|
|
6
|
+
* Функция не делает браузер Node-средой: `process` остается обычным object, без Node toStringTag.
|
|
7
|
+
*/
|
|
8
|
+
export declare function installBrowserNodeGlobals(): void;
|
|
9
|
+
export { Buffer, processShim as process };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Buffer } from "./buffer.js";
|
|
2
|
+
import processShim from "./process.js";
|
|
3
|
+
/**
|
|
4
|
+
* Устанавливает минимальные browser globals, которые часто ожидают Node-oriented dependency branches.
|
|
5
|
+
*
|
|
6
|
+
* Функция не делает браузер Node-средой: `process` остается обычным object, без Node toStringTag.
|
|
7
|
+
*/
|
|
8
|
+
export function installBrowserNodeGlobals() {
|
|
9
|
+
const target = globalThis;
|
|
10
|
+
if (!target.process) {
|
|
11
|
+
target.process = processShim;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
target.process.env ??= {};
|
|
15
|
+
target.process.versions ??= {};
|
|
16
|
+
target.process.browser ??= true;
|
|
17
|
+
target.process.getBuiltinModule ??= processShim.getBuiltinModule;
|
|
18
|
+
}
|
|
19
|
+
if (!target.Buffer)
|
|
20
|
+
target.Buffer = Buffer;
|
|
21
|
+
}
|
|
22
|
+
installBrowserNodeGlobals();
|
|
23
|
+
export { Buffer, processShim as process };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare const sep = "/";
|
|
2
|
+
export declare const delimiter = ":";
|
|
3
|
+
/**
|
|
4
|
+
* Склеивает части пути через `/`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function join(...parts: string[]): string;
|
|
7
|
+
/**
|
|
8
|
+
* Нормализует `.` и `..` в POSIX-like пути.
|
|
9
|
+
*/
|
|
10
|
+
export declare function normalize(value: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Возвращает последнюю часть пути.
|
|
13
|
+
*/
|
|
14
|
+
export declare function basename(value: string, ext?: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Возвращает путь без последней части.
|
|
17
|
+
*/
|
|
18
|
+
export declare function dirname(value: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Возвращает расширение файла, включая точку.
|
|
21
|
+
*/
|
|
22
|
+
export declare function extname(value: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Делает путь абсолютным относительно корня `/`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolve(...parts: string[]): string;
|
|
27
|
+
export declare const posix: {
|
|
28
|
+
sep: string;
|
|
29
|
+
delimiter: string;
|
|
30
|
+
join: typeof join;
|
|
31
|
+
normalize: typeof normalize;
|
|
32
|
+
basename: typeof basename;
|
|
33
|
+
dirname: typeof dirname;
|
|
34
|
+
extname: typeof extname;
|
|
35
|
+
resolve: typeof resolve;
|
|
36
|
+
};
|
|
37
|
+
declare const _default: {
|
|
38
|
+
sep: string;
|
|
39
|
+
delimiter: string;
|
|
40
|
+
join: typeof join;
|
|
41
|
+
normalize: typeof normalize;
|
|
42
|
+
basename: typeof basename;
|
|
43
|
+
dirname: typeof dirname;
|
|
44
|
+
extname: typeof extname;
|
|
45
|
+
resolve: typeof resolve;
|
|
46
|
+
posix: {
|
|
47
|
+
sep: string;
|
|
48
|
+
delimiter: string;
|
|
49
|
+
join: typeof join;
|
|
50
|
+
normalize: typeof normalize;
|
|
51
|
+
basename: typeof basename;
|
|
52
|
+
dirname: typeof dirname;
|
|
53
|
+
extname: typeof extname;
|
|
54
|
+
resolve: typeof resolve;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export default _default;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Небольшой POSIX-like browser shim для `node:path`.
|
|
3
|
+
*
|
|
4
|
+
* Покрывает частые операции, которые bundler/dependency code может вызвать для URL-like путей.
|
|
5
|
+
*/
|
|
6
|
+
function cleanParts(parts) {
|
|
7
|
+
const out = [];
|
|
8
|
+
for (const part of parts) {
|
|
9
|
+
if (!part || part === ".")
|
|
10
|
+
continue;
|
|
11
|
+
if (part === "..")
|
|
12
|
+
out.pop();
|
|
13
|
+
else
|
|
14
|
+
out.push(part);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
export const sep = "/";
|
|
19
|
+
export const delimiter = ":";
|
|
20
|
+
/**
|
|
21
|
+
* Склеивает части пути через `/`.
|
|
22
|
+
*/
|
|
23
|
+
export function join(...parts) {
|
|
24
|
+
return normalize(parts.filter(Boolean).join("/"));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Нормализует `.` и `..` в POSIX-like пути.
|
|
28
|
+
*/
|
|
29
|
+
export function normalize(value) {
|
|
30
|
+
const absolute = value.startsWith("/");
|
|
31
|
+
const suffix = value.endsWith("/") ? "/" : "";
|
|
32
|
+
const body = cleanParts(value.split("/")).join("/");
|
|
33
|
+
return `${absolute ? "/" : ""}${body || (absolute ? "" : ".")}${body ? suffix : ""}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Возвращает последнюю часть пути.
|
|
37
|
+
*/
|
|
38
|
+
export function basename(value, ext = "") {
|
|
39
|
+
const base = value.split("/").filter(Boolean).pop() ?? "";
|
|
40
|
+
return ext && base.endsWith(ext) ? base.slice(0, -ext.length) : base;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Возвращает путь без последней части.
|
|
44
|
+
*/
|
|
45
|
+
export function dirname(value) {
|
|
46
|
+
const parts = value.split("/").filter(Boolean);
|
|
47
|
+
parts.pop();
|
|
48
|
+
return value.startsWith("/") ? `/${parts.join("/")}` : parts.join("/") || ".";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Возвращает расширение файла, включая точку.
|
|
52
|
+
*/
|
|
53
|
+
export function extname(value) {
|
|
54
|
+
const base = basename(value);
|
|
55
|
+
const index = base.lastIndexOf(".");
|
|
56
|
+
return index > 0 ? base.slice(index) : "";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Делает путь абсолютным относительно корня `/`.
|
|
60
|
+
*/
|
|
61
|
+
export function resolve(...parts) {
|
|
62
|
+
return normalize(`/${join(...parts)}`);
|
|
63
|
+
}
|
|
64
|
+
export const posix = { sep, delimiter, join, normalize, basename, dirname, extname, resolve };
|
|
65
|
+
export default { sep, delimiter, join, normalize, basename, dirname, extname, resolve, posix };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Минимальный browser shim для `process`.
|
|
3
|
+
*
|
|
4
|
+
* Важно: объект не маскируется под настоящий Node.js process, чтобы PDF.js не считал браузер Node-средой.
|
|
5
|
+
*/
|
|
6
|
+
export declare const env: Record<string, string | undefined>;
|
|
7
|
+
export declare const versions: Record<string, string | undefined>;
|
|
8
|
+
export declare const browser = true;
|
|
9
|
+
/**
|
|
10
|
+
* Возвращает browser shim для редких вызовов `process.getBuiltinModule(...)`.
|
|
11
|
+
*
|
|
12
|
+
* @param name Имя Node built-in модуля.
|
|
13
|
+
* @returns Объект shim-а для известных модулей или пустой объект.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBuiltinModule(name: string): {};
|
|
16
|
+
declare const _default: {
|
|
17
|
+
env: Record<string, string>;
|
|
18
|
+
versions: Record<string, string>;
|
|
19
|
+
browser: boolean;
|
|
20
|
+
getBuiltinModule: typeof getBuiltinModule;
|
|
21
|
+
};
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Минимальный browser shim для `process`.
|
|
3
|
+
*
|
|
4
|
+
* Важно: объект не маскируется под настоящий Node.js process, чтобы PDF.js не считал браузер Node-средой.
|
|
5
|
+
*/
|
|
6
|
+
export const env = {};
|
|
7
|
+
export const versions = {};
|
|
8
|
+
export const browser = true;
|
|
9
|
+
/**
|
|
10
|
+
* Возвращает browser shim для редких вызовов `process.getBuiltinModule(...)`.
|
|
11
|
+
*
|
|
12
|
+
* @param name Имя Node built-in модуля.
|
|
13
|
+
* @returns Объект shim-а для известных модулей или пустой объект.
|
|
14
|
+
*/
|
|
15
|
+
export function getBuiltinModule(name) {
|
|
16
|
+
const normalized = name.replace(/^node:/u, "");
|
|
17
|
+
if (normalized === "fs")
|
|
18
|
+
return {};
|
|
19
|
+
if (normalized === "fs/promises")
|
|
20
|
+
return {};
|
|
21
|
+
if (normalized === "path" || normalized === "url" || normalized === "module" || normalized === "stream")
|
|
22
|
+
return {};
|
|
23
|
+
if (normalized === "crypto")
|
|
24
|
+
return globalThis.crypto ?? {};
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
export default { env, versions, browser, getBuiltinModule };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Точка входа для браузерной сборки.
|
|
3
|
+
*
|
|
4
|
+
* Скрипт сборки превращает этот файл в:
|
|
5
|
+
* - `dist/med-pdf-nmo.browser.js` с глобальным объектом `MedPdfNmo`
|
|
6
|
+
* - `dist/med-pdf-nmo.browser.mjs` как браузерный ESM-бандл
|
|
7
|
+
*/
|
|
8
|
+
import "./browser-shims/globals.js";
|
|
9
|
+
export { answerQuestion, predict, clearPredictorCache, setPdfJsLib } from "./index.js";
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Точка входа для браузерной сборки.
|
|
3
|
+
*
|
|
4
|
+
* Скрипт сборки превращает этот файл в:
|
|
5
|
+
* - `dist/med-pdf-nmo.browser.js` с глобальным объектом `MedPdfNmo`
|
|
6
|
+
* - `dist/med-pdf-nmo.browser.mjs` как браузерный ESM-бандл
|
|
7
|
+
*/
|
|
8
|
+
import "./browser-shims/globals.js";
|
|
9
|
+
import * as pdfjsLib from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
10
|
+
import { setPdfJsLib } from "./pdf.js";
|
|
11
|
+
setPdfJsLib(pdfjsLib);
|
|
12
|
+
export { answerQuestion, predict, clearPredictorCache, setPdfJsLib } from "./index.js";
|
package/dist/chunk.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Создает поисковые чанки из извлеченного текста PDF.
|
|
3
|
+
*
|
|
4
|
+
* Predictor комбинирует окна предложений, отдельные строки, пары строк и
|
|
5
|
+
* контексты списков/заголовков, чтобы scorers могли находить и обычный текст,
|
|
6
|
+
* и характерные для рекомендаций таблицы/списки.
|
|
7
|
+
*
|
|
8
|
+
* @param pdfText Результат `extractPdfText`.
|
|
9
|
+
* @param options Настройки размера чанка и перекрытия предложений.
|
|
10
|
+
* @returns Поисковые чанки с нормализованным текстом и токенами.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildChunks(pdfText: any, { targetTokens, overlapSentences }?: {
|
|
13
|
+
targetTokens?: number;
|
|
14
|
+
overlapSentences?: number;
|
|
15
|
+
}): any[];
|
package/dist/chunk.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { normalizeForSearch, tokenize } from "./normalize.js";
|
|
2
|
+
function splitSentences(text) {
|
|
3
|
+
const normalized = String(text ?? "")
|
|
4
|
+
.replace(/\r/g, "")
|
|
5
|
+
.replace(/([.!?;])\s+(?=[А-ЯA-Z0-9])/g, "$1\n")
|
|
6
|
+
.replace(/\n{3,}/g, "\n\n");
|
|
7
|
+
return normalized
|
|
8
|
+
.split(/\n+|(?<=[.!?;])\s+/u)
|
|
9
|
+
.map((part) => part.trim())
|
|
10
|
+
.filter((part) => part.length >= 8);
|
|
11
|
+
}
|
|
12
|
+
function tokenCount(text) {
|
|
13
|
+
return tokenize(text, { keepStopwords: true, stem: false }).length;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Создает поисковые чанки из извлеченного текста PDF.
|
|
17
|
+
*
|
|
18
|
+
* Predictor комбинирует окна предложений, отдельные строки, пары строк и
|
|
19
|
+
* контексты списков/заголовков, чтобы scorers могли находить и обычный текст,
|
|
20
|
+
* и характерные для рекомендаций таблицы/списки.
|
|
21
|
+
*
|
|
22
|
+
* @param pdfText Результат `extractPdfText`.
|
|
23
|
+
* @param options Настройки размера чанка и перекрытия предложений.
|
|
24
|
+
* @returns Поисковые чанки с нормализованным текстом и токенами.
|
|
25
|
+
*/
|
|
26
|
+
export function buildChunks(pdfText, { targetTokens = 95, overlapSentences = 2 } = {}) {
|
|
27
|
+
const chunks = [];
|
|
28
|
+
for (const page of pdfText.pages) {
|
|
29
|
+
const sentences = splitSentences(page.text);
|
|
30
|
+
let current = [];
|
|
31
|
+
let currentTokens = 0;
|
|
32
|
+
for (const sentence of sentences) {
|
|
33
|
+
const sentenceTokens = Math.max(1, tokenCount(sentence));
|
|
34
|
+
if (current.length && currentTokens + sentenceTokens > targetTokens) {
|
|
35
|
+
chunks.push(makeChunk(page.page, current.join(" ")));
|
|
36
|
+
current = current.slice(-overlapSentences);
|
|
37
|
+
currentTokens = tokenCount(current.join(" "));
|
|
38
|
+
}
|
|
39
|
+
current.push(sentence);
|
|
40
|
+
currentTokens += sentenceTokens;
|
|
41
|
+
}
|
|
42
|
+
if (current.length) {
|
|
43
|
+
chunks.push(makeChunk(page.page, current.join(" ")));
|
|
44
|
+
}
|
|
45
|
+
const lines = page.text
|
|
46
|
+
.split(/\n+/)
|
|
47
|
+
.map((line) => line.trim())
|
|
48
|
+
.filter((line) => line.length >= 12);
|
|
49
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
50
|
+
const line = lines[i];
|
|
51
|
+
chunks.push(makeChunk(page.page, line, "line"));
|
|
52
|
+
if (i + 1 < lines.length) {
|
|
53
|
+
chunks.push(makeChunk(page.page, `${line} ${lines[i + 1]}`, "line_pair"));
|
|
54
|
+
}
|
|
55
|
+
const listLike = /^(\d+(?:\.\d+)*[.)]?|[-*•]|[a-zа-я]\))\s+/iu.test(line);
|
|
56
|
+
const headingLike = line.length < 120 && !/[.!?]$/.test(line);
|
|
57
|
+
if (listLike || headingLike) {
|
|
58
|
+
const context = lines.slice(Math.max(0, i - 2), Math.min(lines.length, i + 5)).join(" ");
|
|
59
|
+
chunks.push(makeChunk(page.page, context, listLike ? "list" : "heading"));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return chunks
|
|
64
|
+
.filter((chunk) => chunk.tokens.length)
|
|
65
|
+
.map((chunk, index) => ({ ...chunk, id: index }));
|
|
66
|
+
}
|
|
67
|
+
function makeChunk(page, text, kind = "body") {
|
|
68
|
+
return {
|
|
69
|
+
page,
|
|
70
|
+
kind,
|
|
71
|
+
text: String(text ?? "").replace(/\s+/g, " ").trim(),
|
|
72
|
+
normalized: normalizeForSearch(text),
|
|
73
|
+
tokens: tokenize(text),
|
|
74
|
+
rawTokens: tokenize(text, { keepStopwords: true, stem: false }),
|
|
75
|
+
};
|
|
76
|
+
}
|
package/dist/cli.d.ts
ADDED