From 55acf05ad6673f62e5f5a438f64fb395b962da29 Mon Sep 17 00:00:00 2001 From: Richard R Date: Thu, 21 May 2026 21:41:37 -0600 Subject: [PATCH] refactor(compute-core): rename pdf and whisper modules to clean capability layout --- Dockerfile | 4 ++-- compute/core/src/index.ts | 8 ++++---- compute/core/src/local-runtime.ts | 8 ++++---- compute/core/src/pdf-layout/index.ts | 3 --- .../{pdf-layout/model => pdf/assets}/LICENSE.txt | 0 .../{pdf-layout/model => pdf/assets}/manifest.json | 0 compute/core/src/pdf/index.ts | 3 +++ .../mergeTextWithRegions.ts => pdf/merge.ts} | 0 .../src/{pdf-layout/ensureModel.ts => pdf/model.ts} | 4 ++-- .../normalize-text.ts} | 0 .../src/{pdf-layout/parsePdf.ts => pdf/parse.ts} | 10 +++++----- .../src/{pdf-layout/renderPage.ts => pdf/render.ts} | 0 .../core/src/{pdf-layout => pdf}/runLayoutModel.ts | 2 +- .../stitchCrossPageBlocks.ts => pdf/stitch.ts} | 0 compute/core/src/{pdf-layout => pdf}/types.ts | 0 compute/core/src/whisper/{alignment.ts => align.ts} | 6 +++--- .../{alignment-mapping.ts => alignment-map.ts} | 0 .../core/src/whisper/{model => assets}/LICENSE.txt | 0 .../src/whisper/{model => assets}/manifest.json | 0 .../src/whisper/{model => assets}/mel_filters.npz | Bin compute/core/src/whisper/index.ts | 6 +++--- .../core/src/whisper/{ensureModel.ts => model.ts} | 4 ++-- tests/unit/whisper-alignment-mapping.spec.ts | 2 +- tests/unit/whisper-alignment-smoke.spec.ts | 2 +- tests/unit/whisper-ensure-model.spec.ts | 2 +- 25 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 compute/core/src/pdf-layout/index.ts rename compute/core/src/{pdf-layout/model => pdf/assets}/LICENSE.txt (100%) rename compute/core/src/{pdf-layout/model => pdf/assets}/manifest.json (100%) create mode 100644 compute/core/src/pdf/index.ts rename compute/core/src/{pdf-layout/mergeTextWithRegions.ts => pdf/merge.ts} (100%) rename compute/core/src/{pdf-layout/ensureModel.ts => pdf/model.ts} (97%) rename compute/core/src/{pdf-layout/normalizeTextItemsForLayout.ts => pdf/normalize-text.ts} (100%) rename compute/core/src/{pdf-layout/parsePdf.ts => pdf/parse.ts} (94%) rename compute/core/src/{pdf-layout/renderPage.ts => pdf/render.ts} (100%) rename compute/core/src/{pdf-layout => pdf}/runLayoutModel.ts (99%) rename compute/core/src/{pdf-layout/stitchCrossPageBlocks.ts => pdf/stitch.ts} (100%) rename compute/core/src/{pdf-layout => pdf}/types.ts (100%) rename compute/core/src/whisper/{alignment.ts => align.ts} (99%) rename compute/core/src/whisper/{alignment-mapping.ts => alignment-map.ts} (100%) rename compute/core/src/whisper/{model => assets}/LICENSE.txt (100%) rename compute/core/src/whisper/{model => assets}/manifest.json (100%) rename compute/core/src/whisper/{model => assets}/mel_filters.npz (100%) rename compute/core/src/whisper/{ensureModel.ts => model.ts} (98%) diff --git a/Dockerfile b/Dockerfile index 612e250..f48c16d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,14 +58,14 @@ COPY --from=app-builder /app/THIRD_PARTY_LICENSES /licenses # Include SeaweedFS license text for the copied weed binary. COPY --from=seaweedfs-builder /tmp/SeaweedFS-LICENSE.txt /licenses/SeaweedFS-LICENSE.txt # Include static model notices for runtime-downloaded assets. -COPY --from=app-builder /app/compute/core/src/pdf-layout/model/LICENSE.txt /licenses/pp-doclayoutv3-LICENSE.txt +COPY --from=app-builder /app/compute/core/src/pdf/assets/LICENSE.txt /licenses/pp-doclayoutv3-LICENSE.txt # Copy seaweedfs weed binary for optional embedded local S3. COPY --from=seaweedfs-builder /tmp/weed /usr/local/bin/weed RUN chmod +x /usr/local/bin/weed # Include OpenAI Whisper license text for runtime-downloaded ONNX artifacts. -COPY --from=app-builder /app/compute/core/src/whisper/model/LICENSE.txt /licenses/openai-whisper-LICENSE.txt +COPY --from=app-builder /app/compute/core/src/whisper/assets/LICENSE.txt /licenses/openai-whisper-LICENSE.txt # Expose the port the app runs on EXPOSE 3003 diff --git a/compute/core/src/index.ts b/compute/core/src/index.ts index 8cfc7c9..e8b43b2 100644 --- a/compute/core/src/index.ts +++ b/compute/core/src/index.ts @@ -13,7 +13,7 @@ export { type ComputeOperationKind, type IdleTimeoutAndHardCapInput, } from './config/timeout'; -export { renderPage } from './pdf-layout/renderPage'; -export { mergeTextWithRegions } from './pdf-layout/mergeTextWithRegions'; -export { stitchCrossPageBlocks } from './pdf-layout/stitchCrossPageBlocks'; -export { normalizeTextItemsForLayout } from './pdf-layout/normalizeTextItemsForLayout'; +export { renderPage } from './pdf/render'; +export { mergeTextWithRegions } from './pdf/merge'; +export { stitchCrossPageBlocks } from './pdf/stitch'; +export { normalizeTextItemsForLayout } from './pdf/normalize-text'; diff --git a/compute/core/src/local-runtime.ts b/compute/core/src/local-runtime.ts index 15fe92e..ad57513 100644 --- a/compute/core/src/local-runtime.ts +++ b/compute/core/src/local-runtime.ts @@ -1,7 +1,7 @@ -import { ensureWhisperModel } from './whisper/ensureModel'; -import { alignAudioWithText } from './whisper/alignment'; -import { ensureModel as ensurePdfLayoutModel } from './pdf-layout/ensureModel'; -import { parsePdf } from './pdf-layout/parsePdf'; +import { ensureWhisperModel } from './whisper/model'; +import { alignAudioWithText } from './whisper/align'; +import { ensureModel as ensurePdfLayoutModel } from './pdf/model'; +import { parsePdf } from './pdf/parse'; export async function ensureComputeModels(): Promise { await Promise.all([ensureWhisperModel(), ensurePdfLayoutModel()]); diff --git a/compute/core/src/pdf-layout/index.ts b/compute/core/src/pdf-layout/index.ts deleted file mode 100644 index 17aa00c..0000000 --- a/compute/core/src/pdf-layout/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { renderPage } from './renderPage'; -export { mergeTextWithRegions } from './mergeTextWithRegions'; -export { stitchCrossPageBlocks } from './stitchCrossPageBlocks'; diff --git a/compute/core/src/pdf-layout/model/LICENSE.txt b/compute/core/src/pdf/assets/LICENSE.txt similarity index 100% rename from compute/core/src/pdf-layout/model/LICENSE.txt rename to compute/core/src/pdf/assets/LICENSE.txt diff --git a/compute/core/src/pdf-layout/model/manifest.json b/compute/core/src/pdf/assets/manifest.json similarity index 100% rename from compute/core/src/pdf-layout/model/manifest.json rename to compute/core/src/pdf/assets/manifest.json diff --git a/compute/core/src/pdf/index.ts b/compute/core/src/pdf/index.ts new file mode 100644 index 0000000..fe3093a --- /dev/null +++ b/compute/core/src/pdf/index.ts @@ -0,0 +1,3 @@ +export { renderPage } from './render'; +export { mergeTextWithRegions } from './merge'; +export { stitchCrossPageBlocks } from './stitch'; diff --git a/compute/core/src/pdf-layout/mergeTextWithRegions.ts b/compute/core/src/pdf/merge.ts similarity index 100% rename from compute/core/src/pdf-layout/mergeTextWithRegions.ts rename to compute/core/src/pdf/merge.ts diff --git a/compute/core/src/pdf-layout/ensureModel.ts b/compute/core/src/pdf/model.ts similarity index 97% rename from compute/core/src/pdf-layout/ensureModel.ts rename to compute/core/src/pdf/model.ts index 31a472a..cdc0aa3 100644 --- a/compute/core/src/pdf-layout/ensureModel.ts +++ b/compute/core/src/pdf/model.ts @@ -3,7 +3,7 @@ import { fileURLToPath } from 'url'; import { createHash } from 'crypto'; import { access, mkdir, rename, writeFile, readFile, unlink, copyFile } from 'fs/promises'; import { DOCSTORE_DIR } from '../platform/docstore'; -import manifest from './model/manifest.json'; +import manifest from './assets/manifest.json'; const DEFAULT_MODEL_BASE_URL = 'https://huggingface.co/Bei0001/PP-DocLayoutV3-ONNX/resolve/main'; const PDF_LAYOUT_MODEL_BASE_URL_ENV = 'PDF_LAYOUT_MODEL_BASE_URL'; @@ -14,7 +14,7 @@ export const MODEL_DATA_PATH = path.join(MODEL_DIR, 'PP-DocLayoutV3.onnx.data'); export const MODEL_CONFIG_PATH = path.join(MODEL_DIR, 'pp-doclayoutv3.config.json'); export const MODEL_PREPROCESSOR_PATH = path.join(MODEL_DIR, 'pp-doclayoutv3.preprocessor_config.json'); const LICENSE_PATH = path.join(MODEL_DIR, 'pp-doclayoutv3.LICENSE.txt'); -const STATIC_LICENSE_PATH = path.join(MODULE_DIR, 'model', 'LICENSE.txt'); +const STATIC_LICENSE_PATH = path.join(MODULE_DIR, 'assets', 'LICENSE.txt'); let inflight: Promise | null = null; diff --git a/compute/core/src/pdf-layout/normalizeTextItemsForLayout.ts b/compute/core/src/pdf/normalize-text.ts similarity index 100% rename from compute/core/src/pdf-layout/normalizeTextItemsForLayout.ts rename to compute/core/src/pdf/normalize-text.ts diff --git a/compute/core/src/pdf-layout/parsePdf.ts b/compute/core/src/pdf/parse.ts similarity index 94% rename from compute/core/src/pdf-layout/parsePdf.ts rename to compute/core/src/pdf/parse.ts index 1b33ed5..6aef27d 100644 --- a/compute/core/src/pdf-layout/parsePdf.ts +++ b/compute/core/src/pdf/parse.ts @@ -1,12 +1,12 @@ import path from 'path'; import type { TextItem } from 'pdfjs-dist/types/src/display/api'; import type { ParsedPdfDocument, ParsedPdfPage } from '../types/parsed-pdf'; -import { ensureModel } from './ensureModel'; +import { ensureModel } from './model'; import { runLayoutModel } from './runLayoutModel'; -import { mergeTextWithRegions } from './mergeTextWithRegions'; -import { stitchCrossPageBlocks } from './stitchCrossPageBlocks'; -import { renderPage } from './renderPage'; -import { normalizeTextItemsForLayout } from './normalizeTextItemsForLayout'; +import { mergeTextWithRegions } from './merge'; +import { stitchCrossPageBlocks } from './stitch'; +import { renderPage } from './render'; +import { normalizeTextItemsForLayout } from './normalize-text'; interface ParsePdfInput { documentId: string; diff --git a/compute/core/src/pdf-layout/renderPage.ts b/compute/core/src/pdf/render.ts similarity index 100% rename from compute/core/src/pdf-layout/renderPage.ts rename to compute/core/src/pdf/render.ts diff --git a/compute/core/src/pdf-layout/runLayoutModel.ts b/compute/core/src/pdf/runLayoutModel.ts similarity index 99% rename from compute/core/src/pdf-layout/runLayoutModel.ts rename to compute/core/src/pdf/runLayoutModel.ts index 5280db6..5b8fb43 100644 --- a/compute/core/src/pdf-layout/runLayoutModel.ts +++ b/compute/core/src/pdf/runLayoutModel.ts @@ -1,7 +1,7 @@ import * as ort from 'onnxruntime-node'; import { readFile } from 'fs/promises'; import type { LayoutRegion, PdfTextItem } from './types'; -import { ensureModel, MODEL_CONFIG_PATH, MODEL_PREPROCESSOR_PATH } from './ensureModel'; +import { ensureModel, MODEL_CONFIG_PATH, MODEL_PREPROCESSOR_PATH } from './model'; import { getOnnxThreadsPerJob } from '../config/cpu-budget'; interface RunLayoutInput { diff --git a/compute/core/src/pdf-layout/stitchCrossPageBlocks.ts b/compute/core/src/pdf/stitch.ts similarity index 100% rename from compute/core/src/pdf-layout/stitchCrossPageBlocks.ts rename to compute/core/src/pdf/stitch.ts diff --git a/compute/core/src/pdf-layout/types.ts b/compute/core/src/pdf/types.ts similarity index 100% rename from compute/core/src/pdf-layout/types.ts rename to compute/core/src/pdf/types.ts diff --git a/compute/core/src/whisper/alignment.ts b/compute/core/src/whisper/align.ts similarity index 99% rename from compute/core/src/whisper/alignment.ts rename to compute/core/src/whisper/align.ts index b10b444..1411701 100644 --- a/compute/core/src/whisper/alignment.ts +++ b/compute/core/src/whisper/align.ts @@ -14,7 +14,7 @@ import { getComputeTimeoutConfig } from '../config/timeout'; import { mapWordsToSentenceOffsets, type WhisperWord, -} from './alignment-mapping'; +} from './alignment-map'; import { buildGoertzelCoefficients, goertzelPower } from './spectral'; import { buildWordsFromTimestampedTokens, @@ -29,7 +29,7 @@ import { WHISPER_ENCODER_MODEL_PATH, WHISPER_DECODER_MERGED_MODEL_PATH, WHISPER_DECODER_WITH_PAST_MODEL_PATH, -} from './ensureModel'; +} from './model'; interface WhisperAlignmentOptions { lang?: string; @@ -114,7 +114,7 @@ const hannWindow = buildHannWindow(N_FFT); const goertzelCoefficients = buildGoertzelCoefficients(MEL_FILTER_BINS, N_FFT); const MODULE_DIR = dirname(fileURLToPath(import.meta.url)); -const MEL_FILTERS_NPZ_PATH = join(MODULE_DIR, 'model', 'mel_filters.npz'); +const MEL_FILTERS_NPZ_PATH = join(MODULE_DIR, 'assets', 'mel_filters.npz'); function buildHannWindow(length: number): Float32Array { const window = new Float32Array(length); diff --git a/compute/core/src/whisper/alignment-mapping.ts b/compute/core/src/whisper/alignment-map.ts similarity index 100% rename from compute/core/src/whisper/alignment-mapping.ts rename to compute/core/src/whisper/alignment-map.ts diff --git a/compute/core/src/whisper/model/LICENSE.txt b/compute/core/src/whisper/assets/LICENSE.txt similarity index 100% rename from compute/core/src/whisper/model/LICENSE.txt rename to compute/core/src/whisper/assets/LICENSE.txt diff --git a/compute/core/src/whisper/model/manifest.json b/compute/core/src/whisper/assets/manifest.json similarity index 100% rename from compute/core/src/whisper/model/manifest.json rename to compute/core/src/whisper/assets/manifest.json diff --git a/compute/core/src/whisper/model/mel_filters.npz b/compute/core/src/whisper/assets/mel_filters.npz similarity index 100% rename from compute/core/src/whisper/model/mel_filters.npz rename to compute/core/src/whisper/assets/mel_filters.npz diff --git a/compute/core/src/whisper/index.ts b/compute/core/src/whisper/index.ts index ed37c33..5246a13 100644 --- a/compute/core/src/whisper/index.ts +++ b/compute/core/src/whisper/index.ts @@ -2,7 +2,7 @@ export { alignAudioWithText, makeWhisperCacheKey, type WhisperRequestBody, -} from './alignment'; +} from './align'; export { ensureWhisperModel, @@ -11,8 +11,8 @@ export { type WhisperArtifactSpec, type WhisperStaticArtifactSpec, type WhisperFetch, -} from './ensureModel'; +} from './model'; -export { mapWordsToSentenceOffsets, type WhisperWord } from './alignment-mapping'; +export { mapWordsToSentenceOffsets, type WhisperWord } from './alignment-map'; export { buildGoertzelCoefficients, goertzelPower } from './spectral'; export { buildWordsFromTimestampedTokens, extractTokenStartTimestamps } from './token-timestamps'; diff --git a/compute/core/src/whisper/ensureModel.ts b/compute/core/src/whisper/model.ts similarity index 98% rename from compute/core/src/whisper/ensureModel.ts rename to compute/core/src/whisper/model.ts index 2ab1455..d24d009 100644 --- a/compute/core/src/whisper/ensureModel.ts +++ b/compute/core/src/whisper/model.ts @@ -3,11 +3,11 @@ import { fileURLToPath } from 'url'; import { createHash } from 'crypto'; import { access, copyFile, mkdir, readFile, rename, unlink, writeFile } from 'fs/promises'; import { DOCSTORE_DIR } from '../platform/docstore'; -import manifest from './model/manifest.json'; +import manifest from './assets/manifest.json'; const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url)); const MODEL_DIR = path.join(DOCSTORE_DIR, 'model', 'whisper-base_timestamped'); -const STATIC_LICENSE_PATH = path.join(MODULE_DIR, 'model', 'LICENSE.txt'); +const STATIC_LICENSE_PATH = path.join(MODULE_DIR, 'assets', 'LICENSE.txt'); export const WHISPER_CONFIG_PATH = path.join(MODEL_DIR, 'config.json'); export const WHISPER_GENERATION_CONFIG_PATH = path.join(MODEL_DIR, 'generation_config.json'); diff --git a/tests/unit/whisper-alignment-mapping.spec.ts b/tests/unit/whisper-alignment-mapping.spec.ts index d700183..9b08eb4 100644 --- a/tests/unit/whisper-alignment-mapping.spec.ts +++ b/tests/unit/whisper-alignment-mapping.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from '@playwright/test'; import { mapWordsToSentenceOffsets, -} from '../../compute/core/src/whisper/alignment-mapping'; +} from '../../compute/core/src/whisper/alignment-map'; test.describe('whisper alignment mapping', () => { test('maps words to sentence offsets with punctuation and repeated spaces', () => { diff --git a/tests/unit/whisper-alignment-smoke.spec.ts b/tests/unit/whisper-alignment-smoke.spec.ts index 83f2e1c..00ba3cc 100644 --- a/tests/unit/whisper-alignment-smoke.spec.ts +++ b/tests/unit/whisper-alignment-smoke.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from '@playwright/test'; import { readFile } from 'fs/promises'; import path from 'path'; -import { alignAudioWithText } from '../../compute/core/src/whisper/alignment'; +import { alignAudioWithText } from '../../compute/core/src/whisper/align'; test.describe('whisper alignment smoke', () => { test('runs ONNX alignment end-to-end without decoder reshape errors', async () => { diff --git a/tests/unit/whisper-ensure-model.spec.ts b/tests/unit/whisper-ensure-model.spec.ts index 613f985..26e946c 100644 --- a/tests/unit/whisper-ensure-model.spec.ts +++ b/tests/unit/whisper-ensure-model.spec.ts @@ -6,7 +6,7 @@ import path from 'path'; import { createSingleflightRunner, ensureWhisperArtifacts, -} from '../../compute/core/src/whisper/ensureModel'; +} from '../../compute/core/src/whisper/model'; function sha256(bytes: Uint8Array): string { return createHash('sha256').update(bytes).digest('hex');