@memberjunction/ai-segmentation 0.0.0 → 5.51.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/README.md +177 -43
- package/dist/generic/AdaptiveBoundarySegmenter.d.ts +98 -0
- package/dist/generic/AdaptiveBoundarySegmenter.d.ts.map +1 -0
- package/dist/generic/AdaptiveBoundarySegmenter.js +177 -0
- package/dist/generic/AdaptiveBoundarySegmenter.js.map +1 -0
- package/dist/generic/BaseContentCleaner.d.ts +101 -0
- package/dist/generic/BaseContentCleaner.d.ts.map +1 -0
- package/dist/generic/BaseContentCleaner.js +114 -0
- package/dist/generic/BaseContentCleaner.js.map +1 -0
- package/dist/generic/BaseSegmenter.d.ts +106 -0
- package/dist/generic/BaseSegmenter.d.ts.map +1 -0
- package/dist/generic/BaseSegmenter.js +260 -0
- package/dist/generic/BaseSegmenter.js.map +1 -0
- package/dist/generic/FixedWindowSegmenter.d.ts +49 -0
- package/dist/generic/FixedWindowSegmenter.d.ts.map +1 -0
- package/dist/generic/FixedWindowSegmenter.js +106 -0
- package/dist/generic/FixedWindowSegmenter.js.map +1 -0
- package/dist/generic/HtmlContentCleaner.d.ts +61 -0
- package/dist/generic/HtmlContentCleaner.d.ts.map +1 -0
- package/dist/generic/HtmlContentCleaner.js +130 -0
- package/dist/generic/HtmlContentCleaner.js.map +1 -0
- package/dist/generic/PagedContentSegmenter.d.ts +55 -0
- package/dist/generic/PagedContentSegmenter.d.ts.map +1 -0
- package/dist/generic/PagedContentSegmenter.js +99 -0
- package/dist/generic/PagedContentSegmenter.js.map +1 -0
- package/dist/generic/PlainTextContentCleaner.d.ts +22 -0
- package/dist/generic/PlainTextContentCleaner.d.ts.map +1 -0
- package/dist/generic/PlainTextContentCleaner.js +37 -0
- package/dist/generic/PlainTextContentCleaner.js.map +1 -0
- package/dist/generic/Segmentation.types.d.ts +198 -0
- package/dist/generic/Segmentation.types.d.ts.map +1 -0
- package/dist/generic/Segmentation.types.js +19 -0
- package/dist/generic/Segmentation.types.js.map +1 -0
- package/dist/generic/SegmentationResolver.d.ts +43 -0
- package/dist/generic/SegmentationResolver.d.ts.map +1 -0
- package/dist/generic/SegmentationResolver.js +83 -0
- package/dist/generic/SegmentationResolver.js.map +1 -0
- package/dist/generic/SemanticTextSegmenter.d.ts +80 -0
- package/dist/generic/SemanticTextSegmenter.d.ts.map +1 -0
- package/dist/generic/SemanticTextSegmenter.js +201 -0
- package/dist/generic/SemanticTextSegmenter.js.map +1 -0
- package/dist/generic/StructuralTextSegmenter.d.ts +63 -0
- package/dist/generic/StructuralTextSegmenter.d.ts.map +1 -0
- package/dist/generic/StructuralTextSegmenter.js +177 -0
- package/dist/generic/StructuralTextSegmenter.js.map +1 -0
- package/dist/generic/TranscriptSegmenter.d.ts +78 -0
- package/dist/generic/TranscriptSegmenter.d.ts.map +1 -0
- package/dist/generic/TranscriptSegmenter.js +194 -0
- package/dist/generic/TranscriptSegmenter.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SemanticTextSegmenter.js","sourceRoot":"","sources":["../../src/generic/SemanticTextSegmenter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;;;;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAY,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,cAAc,CAAC;AAE1D,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iCAAiC,GAAG,+BAA+B,CAAC;AAqCjF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,aAAa;IACpD,IAAW,GAAG;QACV,OAAO,2BAA2B,CAAC;IACvC,CAAC;IAED,IAAW,mBAAmB;QAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAES,KAAK,CAAC,WAAW,CAAC,MAA2D;QACnF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACd,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,EAAE,eAAe,IAAI,GAAG,CAAC;QACzD,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChE,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,gDAAgD;IAChD,oBAAoB;IACpB,gDAAgD;IAEhD,kEAAkE;IAC1D,WAAW,CAAC,IAAY,EAAE,OAAyC;QACvE,MAAM,MAAM,GAAoB,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC;QACzB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAClD,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACvC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,iDAAiD;IACzC,SAAS,CAAC,MAAuB,EAAE,IAAY,EAAE,KAAa,EAAE,GAAW;QAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1F,CAAC;IACL,CAAC;IAED,gDAAgD;IAChD,yBAAyB;IACzB,gDAAgD;IAEhD,+EAA+E;IACvE,KAAK,CAAC,iBAAiB,CAC3B,MAAuB,EACvB,MAA2D;QAE3D,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,IAAI,iCAAiC,CAAC;QACnF,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;QACrG,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,SAAS,CAAC,mCAAmC,UAAU,wDAAwD,CAAC,CAAC;YACjH,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,cAAc,EAAE,CAAC;QAC1C,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC;QAC7B,YAAY,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAC9C,YAAY,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACvG,YAAY,CAAC,iBAAiB,GAAG,IAAI,CAAC;QACtC,YAAY,CAAC,oBAAoB,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;QACzD,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;YAC1B,YAAY,CAAC,QAAQ,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC,aAAa,CAAmB,YAAY,CAAC,CAAC;QACxF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAClB,QAAQ,CAAC,mDAAmD,MAAM,CAAC,YAAY,IAAI,eAAe,EAAE,CAAC,CAAC;YACtG,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnF,CAAC;IAED,wDAAwD;IAChD,YAAY,CAAC,MAAuB,EAAE,OAAyC;QACnF,MAAM,YAAY,GAAG,OAAO,EAAE,iBAAiB,IAAI,GAAG,CAAC;QACvD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3F,CAAC;IAED,sEAAsE;IAC9D,WAAW,CAAC,GAA0C;QAC1D,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC;QACf,CAAC;QACD,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACL,QAAQ,CAAC,0DAA0D,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5F,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,kBAAkB,CACtB,QAAiC,EACjC,UAAkB;QAElB,MAAM,GAAG,GAAG,QAAQ,EAAE,UAAU,IAAI,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,OAAO,GAA6C,EAAE,CAAC;QAE7D,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClF,SAAS;YACb,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,gDAAgD;IAChD,mBAAmB;IACnB,gDAAgD;IAEhD,wEAAwE;IAChE,aAAa,CAAC,MAAuB,EAAE,UAAoD;QAC/F,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE;YAClC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;YAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnD,OAAO;gBACH,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;gBAC1D,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW;gBAClC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS;aAChD,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED,0FAA0F;IAClF,KAAK,CAAC,QAAQ,CAAC,MAA2D;QAC9E,MAAM,UAAU,GAAG,IAAI,uBAAuB,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACnH,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,SAAS,EAAE,CAAC,CAAC,SAAS;SACzB,CAAC,CAAC,CAAC;IACR,CAAC;CACJ,CAAA;AA7KY,qBAAqB;IADjC,aAAa,CAAC,aAAa,EAAE,2BAA2B,CAAC;GAC7C,qBAAqB,CA6KjC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Structure-aware text segmenter — splits on document headings.
|
|
3
|
+
*
|
|
4
|
+
* @module @memberjunction/ai-segmentation
|
|
5
|
+
*/
|
|
6
|
+
import { BaseSegmenter } from './BaseSegmenter.js';
|
|
7
|
+
import { ContentModality, RawSegment, SegmentationOptions, SegmentationParams } from './Segmentation.types.js';
|
|
8
|
+
/** Registration key for {@link StructuralTextSegmenter}. */
|
|
9
|
+
export declare const STRUCTURAL_TEXT_SEGMENTER_KEY = "StructuralText";
|
|
10
|
+
/** Options specific to {@link StructuralTextSegmenter}. */
|
|
11
|
+
export interface StructuralTextSegmentationOptions extends SegmentationOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Prepend the heading text to each section's body before embedding. Keeps a
|
|
14
|
+
* section's topic in its own vector, which materially helps retrieval when the
|
|
15
|
+
* body uses pronouns ("it", "the above"). Default: true.
|
|
16
|
+
*/
|
|
17
|
+
IncludeHeadingInText?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Heading syntax to look for. `'auto'` detects markdown vs. HTML from the
|
|
20
|
+
* content (and honours `params.MimeType` when supplied). Default: `'auto'`.
|
|
21
|
+
*/
|
|
22
|
+
HeadingSyntax?: 'auto' | 'markdown' | 'html';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Segments text along its own document structure (markdown `#` headings or HTML
|
|
26
|
+
* `<h1>`-`<h6>`), emitting one segment per section and preserving the heading
|
|
27
|
+
* hierarchy as parent/child links.
|
|
28
|
+
*
|
|
29
|
+
* This is the recommended default for documents, PDFs-converted-to-text, wiki
|
|
30
|
+
* pages, and knowledge-base articles. Compared with splitting purely on a token
|
|
31
|
+
* budget, sections are coherent units of meaning, so each vector represents one
|
|
32
|
+
* topic instead of an arbitrary window that may straddle two.
|
|
33
|
+
*
|
|
34
|
+
* When the content has no headings it degrades gracefully to paragraph segments,
|
|
35
|
+
* which is still better than fixed windows because paragraph breaks are authored
|
|
36
|
+
* boundaries. In both cases {@link BaseSegmenter} enforces the token ceiling.
|
|
37
|
+
*/
|
|
38
|
+
export declare class StructuralTextSegmenter extends BaseSegmenter {
|
|
39
|
+
get Key(): string;
|
|
40
|
+
get SupportedModalities(): ContentModality[];
|
|
41
|
+
protected SegmentCore(params: SegmentationParams<StructuralTextSegmentationOptions>): RawSegment[];
|
|
42
|
+
/** Decide which heading syntax applies to this content. */
|
|
43
|
+
private resolveSyntax;
|
|
44
|
+
/** Locate ATX-style markdown headings (`#` through `######`). */
|
|
45
|
+
private findMarkdownHeadings;
|
|
46
|
+
/** Locate HTML `<h1>`-`<h6>` headings. */
|
|
47
|
+
private findHtmlHeadings;
|
|
48
|
+
/** Remove inline tags from a heading's inner HTML. */
|
|
49
|
+
private stripTags;
|
|
50
|
+
/** Build one segment per heading section, plus any preamble, with parent links. */
|
|
51
|
+
private buildSectionSegments;
|
|
52
|
+
/** Text preceding the first heading, if any. */
|
|
53
|
+
private buildPreamble;
|
|
54
|
+
/** Section body, optionally prefixed with its heading for self-contained context. */
|
|
55
|
+
private buildSectionText;
|
|
56
|
+
/** Nearest preceding heading with a lower level number (i.e. the enclosing section). */
|
|
57
|
+
private findParentHeading;
|
|
58
|
+
/** Fallback for unstructured text: one segment per paragraph, offsets preserved. */
|
|
59
|
+
private segmentByParagraph;
|
|
60
|
+
/** Append a paragraph segment when the slice has content. */
|
|
61
|
+
private pushParagraph;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=StructuralTextSegmenter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StructuralTextSegmenter.d.ts","sourceRoot":"","sources":["../../src/generic/StructuralTextSegmenter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE5G,4DAA4D;AAC5D,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,WAAW,iCAAkC,SAAQ,mBAAmB;IAC1E;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;CAChD;AAYD;;;;;;;;;;;;;GAaG;AACH,qBACa,uBAAwB,SAAQ,aAAa;IACtD,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED,IAAW,mBAAmB,IAAI,eAAe,EAAE,CAElD;IAED,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,iCAAiC,CAAC,GAAG,UAAU,EAAE;IAiBlG,2DAA2D;IAC3D,OAAO,CAAC,aAAa;IAWrB,iEAAiE;IACjE,OAAO,CAAC,oBAAoB;IAgB5B,0CAA0C;IAC1C,OAAO,CAAC,gBAAgB;IAgBxB,sDAAsD;IACtD,OAAO,CAAC,SAAS;IAQjB,mFAAmF;IACnF,OAAO,CAAC,oBAAoB;IA6B5B,gDAAgD;IAChD,OAAO,CAAC,aAAa;IAQrB,qFAAqF;IACrF,OAAO,CAAC,gBAAgB;IAcxB,wFAAwF;IACxF,OAAO,CAAC,iBAAiB;IASzB,oFAAoF;IACpF,OAAO,CAAC,kBAAkB;IAc1B,6DAA6D;IAC7D,OAAO,CAAC,aAAa;CAMxB"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Structure-aware text segmenter — splits on document headings.
|
|
3
|
+
*
|
|
4
|
+
* @module @memberjunction/ai-segmentation
|
|
5
|
+
*/
|
|
6
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
9
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
10
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
11
|
+
};
|
|
12
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
13
|
+
import { BaseSegmenter } from './BaseSegmenter.js';
|
|
14
|
+
/** Registration key for {@link StructuralTextSegmenter}. */
|
|
15
|
+
export const STRUCTURAL_TEXT_SEGMENTER_KEY = 'StructuralText';
|
|
16
|
+
/**
|
|
17
|
+
* Segments text along its own document structure (markdown `#` headings or HTML
|
|
18
|
+
* `<h1>`-`<h6>`), emitting one segment per section and preserving the heading
|
|
19
|
+
* hierarchy as parent/child links.
|
|
20
|
+
*
|
|
21
|
+
* This is the recommended default for documents, PDFs-converted-to-text, wiki
|
|
22
|
+
* pages, and knowledge-base articles. Compared with splitting purely on a token
|
|
23
|
+
* budget, sections are coherent units of meaning, so each vector represents one
|
|
24
|
+
* topic instead of an arbitrary window that may straddle two.
|
|
25
|
+
*
|
|
26
|
+
* When the content has no headings it degrades gracefully to paragraph segments,
|
|
27
|
+
* which is still better than fixed windows because paragraph breaks are authored
|
|
28
|
+
* boundaries. In both cases {@link BaseSegmenter} enforces the token ceiling.
|
|
29
|
+
*/
|
|
30
|
+
let StructuralTextSegmenter = class StructuralTextSegmenter extends BaseSegmenter {
|
|
31
|
+
get Key() {
|
|
32
|
+
return STRUCTURAL_TEXT_SEGMENTER_KEY;
|
|
33
|
+
}
|
|
34
|
+
get SupportedModalities() {
|
|
35
|
+
return ['text'];
|
|
36
|
+
}
|
|
37
|
+
SegmentCore(params) {
|
|
38
|
+
const text = params.Text ?? '';
|
|
39
|
+
if (text.trim().length === 0) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const syntax = this.resolveSyntax(text, params);
|
|
43
|
+
const headings = syntax === 'html' ? this.findHtmlHeadings(text) : this.findMarkdownHeadings(text);
|
|
44
|
+
if (headings.length === 0) {
|
|
45
|
+
return this.segmentByParagraph(text);
|
|
46
|
+
}
|
|
47
|
+
return this.buildSectionSegments(text, headings, params.Options);
|
|
48
|
+
}
|
|
49
|
+
// ─────────────────────────────────────────────
|
|
50
|
+
// Heading detection
|
|
51
|
+
// ─────────────────────────────────────────────
|
|
52
|
+
/** Decide which heading syntax applies to this content. */
|
|
53
|
+
resolveSyntax(text, params) {
|
|
54
|
+
const configured = params.Options?.HeadingSyntax ?? 'auto';
|
|
55
|
+
if (configured !== 'auto') {
|
|
56
|
+
return configured;
|
|
57
|
+
}
|
|
58
|
+
if (params.MimeType && params.MimeType.toLowerCase().includes('html')) {
|
|
59
|
+
return 'html';
|
|
60
|
+
}
|
|
61
|
+
return /<h[1-6][\s>]/i.test(text) ? 'html' : 'markdown';
|
|
62
|
+
}
|
|
63
|
+
/** Locate ATX-style markdown headings (`#` through `######`). */
|
|
64
|
+
findMarkdownHeadings(text) {
|
|
65
|
+
const regex = /^(#{1,6})[ \t]+(.+?)[ \t]*$/gm;
|
|
66
|
+
const matches = [];
|
|
67
|
+
let match = regex.exec(text);
|
|
68
|
+
while (match !== null) {
|
|
69
|
+
matches.push({
|
|
70
|
+
Level: match[1].length,
|
|
71
|
+
Title: match[2].trim(),
|
|
72
|
+
StartOffset: match.index,
|
|
73
|
+
BodyStart: match.index + match[0].length,
|
|
74
|
+
});
|
|
75
|
+
match = regex.exec(text);
|
|
76
|
+
}
|
|
77
|
+
return matches;
|
|
78
|
+
}
|
|
79
|
+
/** Locate HTML `<h1>`-`<h6>` headings. */
|
|
80
|
+
findHtmlHeadings(text) {
|
|
81
|
+
const regex = /<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi;
|
|
82
|
+
const matches = [];
|
|
83
|
+
let match = regex.exec(text);
|
|
84
|
+
while (match !== null) {
|
|
85
|
+
matches.push({
|
|
86
|
+
Level: Number(match[1]),
|
|
87
|
+
Title: this.stripTags(match[2]).trim(),
|
|
88
|
+
StartOffset: match.index,
|
|
89
|
+
BodyStart: match.index + match[0].length,
|
|
90
|
+
});
|
|
91
|
+
match = regex.exec(text);
|
|
92
|
+
}
|
|
93
|
+
return matches;
|
|
94
|
+
}
|
|
95
|
+
/** Remove inline tags from a heading's inner HTML. */
|
|
96
|
+
stripTags(html) {
|
|
97
|
+
return html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ');
|
|
98
|
+
}
|
|
99
|
+
// ─────────────────────────────────────────────
|
|
100
|
+
// Segment construction
|
|
101
|
+
// ─────────────────────────────────────────────
|
|
102
|
+
/** Build one segment per heading section, plus any preamble, with parent links. */
|
|
103
|
+
buildSectionSegments(text, headings, options) {
|
|
104
|
+
const segments = [];
|
|
105
|
+
const segmentIndexByHeading = new Map();
|
|
106
|
+
const preamble = this.buildPreamble(text, headings[0].StartOffset);
|
|
107
|
+
if (preamble) {
|
|
108
|
+
segments.push(preamble);
|
|
109
|
+
}
|
|
110
|
+
headings.forEach((heading, index) => {
|
|
111
|
+
const end = index + 1 < headings.length ? headings[index + 1].StartOffset : text.length;
|
|
112
|
+
const parentHeading = this.findParentHeading(headings, index);
|
|
113
|
+
segments.push({
|
|
114
|
+
Modality: 'text',
|
|
115
|
+
Title: heading.Title,
|
|
116
|
+
Text: this.buildSectionText(text, heading, end, options),
|
|
117
|
+
StartOffset: heading.StartOffset,
|
|
118
|
+
EndOffset: end,
|
|
119
|
+
ParentIndex: parentHeading === undefined ? undefined : segmentIndexByHeading.get(parentHeading),
|
|
120
|
+
});
|
|
121
|
+
segmentIndexByHeading.set(index, segments.length - 1);
|
|
122
|
+
});
|
|
123
|
+
return segments;
|
|
124
|
+
}
|
|
125
|
+
/** Text preceding the first heading, if any. */
|
|
126
|
+
buildPreamble(text, firstHeadingOffset) {
|
|
127
|
+
const body = text.slice(0, firstHeadingOffset).trim();
|
|
128
|
+
if (body.length === 0) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return { Modality: 'text', Text: body, StartOffset: 0, EndOffset: firstHeadingOffset };
|
|
132
|
+
}
|
|
133
|
+
/** Section body, optionally prefixed with its heading for self-contained context. */
|
|
134
|
+
buildSectionText(text, heading, end, options) {
|
|
135
|
+
const body = text.slice(heading.BodyStart, end).trim();
|
|
136
|
+
const includeHeading = options?.IncludeHeadingInText ?? true;
|
|
137
|
+
if (!includeHeading) {
|
|
138
|
+
return body;
|
|
139
|
+
}
|
|
140
|
+
return body.length > 0 ? `${heading.Title}\n${body}` : heading.Title;
|
|
141
|
+
}
|
|
142
|
+
/** Nearest preceding heading with a lower level number (i.e. the enclosing section). */
|
|
143
|
+
findParentHeading(headings, index) {
|
|
144
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
145
|
+
if (headings[i].Level < headings[index].Level) {
|
|
146
|
+
return i;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
/** Fallback for unstructured text: one segment per paragraph, offsets preserved. */
|
|
152
|
+
segmentByParagraph(text) {
|
|
153
|
+
const segments = [];
|
|
154
|
+
const regex = /\n\s*\n/g;
|
|
155
|
+
let cursor = 0;
|
|
156
|
+
let match = regex.exec(text);
|
|
157
|
+
while (match !== null) {
|
|
158
|
+
this.pushParagraph(segments, text, cursor, match.index);
|
|
159
|
+
cursor = match.index + match[0].length;
|
|
160
|
+
match = regex.exec(text);
|
|
161
|
+
}
|
|
162
|
+
this.pushParagraph(segments, text, cursor, text.length);
|
|
163
|
+
return segments;
|
|
164
|
+
}
|
|
165
|
+
/** Append a paragraph segment when the slice has content. */
|
|
166
|
+
pushParagraph(segments, text, start, end) {
|
|
167
|
+
const body = text.slice(start, end).trim();
|
|
168
|
+
if (body.length > 0) {
|
|
169
|
+
segments.push({ Modality: 'text', Text: body, StartOffset: start, EndOffset: end });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
StructuralTextSegmenter = __decorate([
|
|
174
|
+
RegisterClass(BaseSegmenter, STRUCTURAL_TEXT_SEGMENTER_KEY)
|
|
175
|
+
], StructuralTextSegmenter);
|
|
176
|
+
export { StructuralTextSegmenter };
|
|
177
|
+
//# sourceMappingURL=StructuralTextSegmenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StructuralTextSegmenter.js","sourceRoot":"","sources":["../../src/generic/StructuralTextSegmenter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Transcript-driven segmenter — turns timed cues into chapters.
|
|
3
|
+
*
|
|
4
|
+
* @module @memberjunction/ai-segmentation
|
|
5
|
+
*/
|
|
6
|
+
import { BaseSegmenter } from './BaseSegmenter.js';
|
|
7
|
+
import { ContentModality, RawSegment, SegmentationOptions, SegmentationParams } from './Segmentation.types.js';
|
|
8
|
+
/** Registration key for {@link TranscriptSegmenter}. */
|
|
9
|
+
export declare const TRANSCRIPT_SEGMENTER_KEY = "Transcript";
|
|
10
|
+
/** Options specific to {@link TranscriptSegmenter}. */
|
|
11
|
+
export interface TranscriptSegmentationOptions extends SegmentationOptions {
|
|
12
|
+
/** Maximum wall-clock length of one chapter, in ms. Default: 300000 (5 minutes). */
|
|
13
|
+
MaxChapterMs?: number;
|
|
14
|
+
/**
|
|
15
|
+
* A silence gap at least this long is treated as a chapter boundary — the
|
|
16
|
+
* cheapest reliable topic-shift signal in a recording. Default: 4000.
|
|
17
|
+
*/
|
|
18
|
+
BoundaryGapMs?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Also emit one child segment per speaker turn inside each chapter. Doubles
|
|
21
|
+
* embedding cost, so it is opt-in; enable for panel/interview content where
|
|
22
|
+
* per-speaker retrieval matters. Default: false.
|
|
23
|
+
*/
|
|
24
|
+
EmitSubChapters?: boolean;
|
|
25
|
+
/** Modality to stamp on emitted segments when it can't be inferred. Default: `'audio'`. */
|
|
26
|
+
DefaultModality?: Extract<ContentModality, 'audio' | 'video'>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Segments audio/video into **chapters** using its timed transcript.
|
|
30
|
+
*
|
|
31
|
+
* A 60-minute session recording embedded as a single vector is a mush vector —
|
|
32
|
+
* multimodal embedders only see a short window, and no single vector can represent
|
|
33
|
+
* an hour of distinct topics. This segmenter finds real boundaries first (silence
|
|
34
|
+
* gaps, speaker changes, a duration ceiling) and emits time-windowed chapters that
|
|
35
|
+
* each carry **both** a media reference (with `StartMs`/`EndMs`) *and* the
|
|
36
|
+
* transcript text for that window.
|
|
37
|
+
*
|
|
38
|
+
* That dual payload is deliberate: the media reference is what a multimodal model
|
|
39
|
+
* embeds for retrieval, while the transcript is what an agent can actually read,
|
|
40
|
+
* what a cross-encoder can rerank, and what keyword search can match.
|
|
41
|
+
*
|
|
42
|
+
* Cues come from any ASR source, including MemberJunction's realtime session
|
|
43
|
+
* capture, which already records per-turn text with speaker labels and timings.
|
|
44
|
+
*/
|
|
45
|
+
export declare class TranscriptSegmenter extends BaseSegmenter {
|
|
46
|
+
get Key(): string;
|
|
47
|
+
get SupportedModalities(): ContentModality[];
|
|
48
|
+
protected SegmentCore(params: SegmentationParams<TranscriptSegmentationOptions>): RawSegment[];
|
|
49
|
+
/** Cues must be time-ordered before boundary detection; callers may supply any order. */
|
|
50
|
+
private sortCues;
|
|
51
|
+
/** Accumulate cues into chapters, breaking on gap, duration, or token pressure. */
|
|
52
|
+
private groupIntoChapters;
|
|
53
|
+
/** True when `next` should start a new chapter rather than extend the current one. */
|
|
54
|
+
private isChapterBoundary;
|
|
55
|
+
/** Split a chapter's cues into runs of consecutive same-speaker cues. */
|
|
56
|
+
private groupBySpeaker;
|
|
57
|
+
/** Wrap a cue list with its computed time span. */
|
|
58
|
+
private toGroup;
|
|
59
|
+
/** Emit chapter segments, plus per-speaker children when configured. */
|
|
60
|
+
private buildSegments;
|
|
61
|
+
/** Append one child segment per speaker run within a chapter. */
|
|
62
|
+
private appendSubChapters;
|
|
63
|
+
/** Build a segment carrying both the media time-window and the transcript text. */
|
|
64
|
+
private toRawSegment;
|
|
65
|
+
/** Prefix a cue with its speaker so the transcript reads as dialogue. */
|
|
66
|
+
private formatCue;
|
|
67
|
+
/** The only speaker in the group, or undefined when several speak. */
|
|
68
|
+
private dominantSpeaker;
|
|
69
|
+
/** Infer audio vs. video from the media mime type, else use the configured default. */
|
|
70
|
+
private resolveModality;
|
|
71
|
+
/** Merge caller options with transcript-specific defaults. */
|
|
72
|
+
private resolveTranscriptOptions;
|
|
73
|
+
/** Estimated tokens for a set of cues. */
|
|
74
|
+
private textTokens;
|
|
75
|
+
/** Estimated tokens for one cue. */
|
|
76
|
+
private cueTokens;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=TranscriptSegmenter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TranscriptSegmenter.d.ts","sourceRoot":"","sources":["../../src/generic/TranscriptSegmenter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACH,eAAe,EACf,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAErB,MAAM,sBAAsB,CAAC;AAE9B,wDAAwD;AACxD,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,uDAAuD;AACvD,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB;IACtE,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2FAA2F;IAC3F,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC;CACjE;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,mBAAoB,SAAQ,aAAa;IAClD,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED,IAAW,mBAAmB,IAAI,eAAe,EAAE,CAElD;IAED,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,6BAA6B,CAAC,GAAG,UAAU,EAAE;IAc9F,yFAAyF;IACzF,OAAO,CAAC,QAAQ;IAIhB,mFAAmF;IACnF,OAAO,CAAC,iBAAiB;IAiBzB,sFAAsF;IACtF,OAAO,CAAC,iBAAiB;IAezB,yEAAyE;IACzE,OAAO,CAAC,cAAc;IAiBtB,mDAAmD;IACnD,OAAO,CAAC,OAAO;IAYf,wEAAwE;IACxE,OAAO,CAAC,aAAa;IAkBrB,iEAAiE;IACjE,OAAO,CAAC,iBAAiB;IAkBzB,mFAAmF;IACnF,OAAO,CAAC,YAAY;IAiBpB,yEAAyE;IACzE,OAAO,CAAC,SAAS;IAIjB,sEAAsE;IACtE,OAAO,CAAC,eAAe;IAKvB,uFAAuF;IACvF,OAAO,CAAC,eAAe;IAkBvB,8DAA8D;IAC9D,OAAO,CAAC,wBAAwB;IAUhC,0CAA0C;IAC1C,OAAO,CAAC,UAAU;IAIlB,oCAAoC;IACpC,OAAO,CAAC,SAAS;CAGpB"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Transcript-driven segmenter — turns timed cues into chapters.
|
|
3
|
+
*
|
|
4
|
+
* @module @memberjunction/ai-segmentation
|
|
5
|
+
*/
|
|
6
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
9
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
10
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
11
|
+
};
|
|
12
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
13
|
+
import { BaseSegmenter } from './BaseSegmenter.js';
|
|
14
|
+
/** Registration key for {@link TranscriptSegmenter}. */
|
|
15
|
+
export const TRANSCRIPT_SEGMENTER_KEY = 'Transcript';
|
|
16
|
+
/**
|
|
17
|
+
* Segments audio/video into **chapters** using its timed transcript.
|
|
18
|
+
*
|
|
19
|
+
* A 60-minute session recording embedded as a single vector is a mush vector —
|
|
20
|
+
* multimodal embedders only see a short window, and no single vector can represent
|
|
21
|
+
* an hour of distinct topics. This segmenter finds real boundaries first (silence
|
|
22
|
+
* gaps, speaker changes, a duration ceiling) and emits time-windowed chapters that
|
|
23
|
+
* each carry **both** a media reference (with `StartMs`/`EndMs`) *and* the
|
|
24
|
+
* transcript text for that window.
|
|
25
|
+
*
|
|
26
|
+
* That dual payload is deliberate: the media reference is what a multimodal model
|
|
27
|
+
* embeds for retrieval, while the transcript is what an agent can actually read,
|
|
28
|
+
* what a cross-encoder can rerank, and what keyword search can match.
|
|
29
|
+
*
|
|
30
|
+
* Cues come from any ASR source, including MemberJunction's realtime session
|
|
31
|
+
* capture, which already records per-turn text with speaker labels and timings.
|
|
32
|
+
*/
|
|
33
|
+
let TranscriptSegmenter = class TranscriptSegmenter extends BaseSegmenter {
|
|
34
|
+
get Key() {
|
|
35
|
+
return TRANSCRIPT_SEGMENTER_KEY;
|
|
36
|
+
}
|
|
37
|
+
get SupportedModalities() {
|
|
38
|
+
return ['audio', 'video', 'multimodal'];
|
|
39
|
+
}
|
|
40
|
+
SegmentCore(params) {
|
|
41
|
+
const cues = this.sortCues(params.Cues ?? []);
|
|
42
|
+
if (cues.length === 0) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const settings = this.resolveTranscriptOptions(params.Options);
|
|
46
|
+
const chapters = this.groupIntoChapters(cues, settings);
|
|
47
|
+
return this.buildSegments(chapters, params, settings);
|
|
48
|
+
}
|
|
49
|
+
// ─────────────────────────────────────────────
|
|
50
|
+
// Grouping
|
|
51
|
+
// ─────────────────────────────────────────────
|
|
52
|
+
/** Cues must be time-ordered before boundary detection; callers may supply any order. */
|
|
53
|
+
sortCues(cues) {
|
|
54
|
+
return [...cues].filter((c) => !!c && c.Text.trim().length > 0).sort((a, b) => a.StartMs - b.StartMs);
|
|
55
|
+
}
|
|
56
|
+
/** Accumulate cues into chapters, breaking on gap, duration, or token pressure. */
|
|
57
|
+
groupIntoChapters(cues, settings) {
|
|
58
|
+
const chapters = [];
|
|
59
|
+
let current = [];
|
|
60
|
+
for (const cue of cues) {
|
|
61
|
+
if (current.length > 0 && this.isChapterBoundary(current, cue, settings)) {
|
|
62
|
+
chapters.push(this.toGroup(current));
|
|
63
|
+
current = [];
|
|
64
|
+
}
|
|
65
|
+
current.push(cue);
|
|
66
|
+
}
|
|
67
|
+
if (current.length > 0) {
|
|
68
|
+
chapters.push(this.toGroup(current));
|
|
69
|
+
}
|
|
70
|
+
return chapters;
|
|
71
|
+
}
|
|
72
|
+
/** True when `next` should start a new chapter rather than extend the current one. */
|
|
73
|
+
isChapterBoundary(current, next, settings) {
|
|
74
|
+
const previous = current[current.length - 1];
|
|
75
|
+
if (next.StartMs - previous.EndMs >= settings.BoundaryGapMs) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (next.EndMs - current[0].StartMs > settings.MaxChapterMs) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return this.textTokens(current) + this.cueTokens(next) > settings.MaxSegmentTokens;
|
|
82
|
+
}
|
|
83
|
+
/** Split a chapter's cues into runs of consecutive same-speaker cues. */
|
|
84
|
+
groupBySpeaker(cues) {
|
|
85
|
+
const runs = [];
|
|
86
|
+
let current = [];
|
|
87
|
+
for (const cue of cues) {
|
|
88
|
+
const previous = current[current.length - 1];
|
|
89
|
+
if (previous && previous.Speaker !== cue.Speaker) {
|
|
90
|
+
runs.push(this.toGroup(current));
|
|
91
|
+
current = [];
|
|
92
|
+
}
|
|
93
|
+
current.push(cue);
|
|
94
|
+
}
|
|
95
|
+
if (current.length > 0) {
|
|
96
|
+
runs.push(this.toGroup(current));
|
|
97
|
+
}
|
|
98
|
+
return runs;
|
|
99
|
+
}
|
|
100
|
+
/** Wrap a cue list with its computed time span. */
|
|
101
|
+
toGroup(cues) {
|
|
102
|
+
return {
|
|
103
|
+
Cues: cues,
|
|
104
|
+
StartMs: cues[0].StartMs,
|
|
105
|
+
EndMs: cues[cues.length - 1].EndMs,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// ─────────────────────────────────────────────
|
|
109
|
+
// Segment construction
|
|
110
|
+
// ─────────────────────────────────────────────
|
|
111
|
+
/** Emit chapter segments, plus per-speaker children when configured. */
|
|
112
|
+
buildSegments(chapters, params, settings) {
|
|
113
|
+
const modality = this.resolveModality(params, settings);
|
|
114
|
+
const segments = [];
|
|
115
|
+
chapters.forEach((chapter, index) => {
|
|
116
|
+
segments.push(this.toRawSegment(chapter, modality, params, `Chapter ${index + 1}`));
|
|
117
|
+
const chapterIndex = segments.length - 1;
|
|
118
|
+
if (settings.EmitSubChapters) {
|
|
119
|
+
this.appendSubChapters(segments, chapter, modality, params, chapterIndex);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return segments;
|
|
123
|
+
}
|
|
124
|
+
/** Append one child segment per speaker run within a chapter. */
|
|
125
|
+
appendSubChapters(segments, chapter, modality, params, parentIndex) {
|
|
126
|
+
const runs = this.groupBySpeaker(chapter.Cues);
|
|
127
|
+
if (runs.length <= 1) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
for (const run of runs) {
|
|
131
|
+
const child = this.toRawSegment(run, modality, params, run.Cues[0].Speaker);
|
|
132
|
+
child.ParentIndex = parentIndex;
|
|
133
|
+
segments.push(child);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Build a segment carrying both the media time-window and the transcript text. */
|
|
137
|
+
toRawSegment(group, modality, params, title) {
|
|
138
|
+
return {
|
|
139
|
+
Modality: modality,
|
|
140
|
+
Text: group.Cues.map((c) => this.formatCue(c)).join(' ').trim(),
|
|
141
|
+
Media: params.Media,
|
|
142
|
+
Title: title,
|
|
143
|
+
StartMs: group.StartMs,
|
|
144
|
+
EndMs: group.EndMs,
|
|
145
|
+
Speaker: this.dominantSpeaker(group.Cues),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/** Prefix a cue with its speaker so the transcript reads as dialogue. */
|
|
149
|
+
formatCue(cue) {
|
|
150
|
+
return cue.Speaker ? `${cue.Speaker}: ${cue.Text.trim()}` : cue.Text.trim();
|
|
151
|
+
}
|
|
152
|
+
/** The only speaker in the group, or undefined when several speak. */
|
|
153
|
+
dominantSpeaker(cues) {
|
|
154
|
+
const speakers = new Set(cues.map((c) => c.Speaker).filter((s) => !!s));
|
|
155
|
+
return speakers.size === 1 ? [...speakers][0] : undefined;
|
|
156
|
+
}
|
|
157
|
+
/** Infer audio vs. video from the media mime type, else use the configured default. */
|
|
158
|
+
resolveModality(params, settings) {
|
|
159
|
+
const mime = (params.Media?.MimeType ?? params.MimeType ?? '').toLowerCase();
|
|
160
|
+
if (mime.startsWith('video/')) {
|
|
161
|
+
return 'video';
|
|
162
|
+
}
|
|
163
|
+
if (mime.startsWith('audio/')) {
|
|
164
|
+
return 'audio';
|
|
165
|
+
}
|
|
166
|
+
return settings.DefaultModality;
|
|
167
|
+
}
|
|
168
|
+
// ─────────────────────────────────────────────
|
|
169
|
+
// Helpers
|
|
170
|
+
// ─────────────────────────────────────────────
|
|
171
|
+
/** Merge caller options with transcript-specific defaults. */
|
|
172
|
+
resolveTranscriptOptions(options) {
|
|
173
|
+
return {
|
|
174
|
+
...this.resolveOptions(options),
|
|
175
|
+
MaxChapterMs: options?.MaxChapterMs ?? 300_000,
|
|
176
|
+
BoundaryGapMs: options?.BoundaryGapMs ?? 4_000,
|
|
177
|
+
EmitSubChapters: options?.EmitSubChapters ?? false,
|
|
178
|
+
DefaultModality: options?.DefaultModality ?? 'audio',
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/** Estimated tokens for a set of cues. */
|
|
182
|
+
textTokens(cues) {
|
|
183
|
+
return cues.reduce((sum, cue) => sum + this.cueTokens(cue), 0);
|
|
184
|
+
}
|
|
185
|
+
/** Estimated tokens for one cue. */
|
|
186
|
+
cueTokens(cue) {
|
|
187
|
+
return this.tokensOf({ Modality: 'text', Text: cue.Text });
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
TranscriptSegmenter = __decorate([
|
|
191
|
+
RegisterClass(BaseSegmenter, TRANSCRIPT_SEGMENTER_KEY)
|
|
192
|
+
], TranscriptSegmenter);
|
|
193
|
+
export { TranscriptSegmenter };
|
|
194
|
+
//# sourceMappingURL=TranscriptSegmenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TranscriptSegmenter.js","sourceRoot":"","sources":["../../src/generic/TranscriptSegmenter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/ai-segmentation
|
|
3
|
+
*
|
|
4
|
+
* Pluggable content segmentation for RAG ingestion. Importing this package
|
|
5
|
+
* registers every built-in segmenter with the MJ class factory, so
|
|
6
|
+
* `BaseSegmenter.Resolve(key)` works for any of them.
|
|
7
|
+
*/
|
|
8
|
+
export * from './generic/Segmentation.types.js';
|
|
9
|
+
export * from './generic/BaseSegmenter.js';
|
|
10
|
+
export * from './generic/StructuralTextSegmenter.js';
|
|
11
|
+
export * from './generic/SemanticTextSegmenter.js';
|
|
12
|
+
export * from './generic/TranscriptSegmenter.js';
|
|
13
|
+
export * from './generic/FixedWindowSegmenter.js';
|
|
14
|
+
export * from './generic/AdaptiveBoundarySegmenter.js';
|
|
15
|
+
export * from './generic/PagedContentSegmenter.js';
|
|
16
|
+
export * from './generic/BaseContentCleaner.js';
|
|
17
|
+
export * from './generic/HtmlContentCleaner.js';
|
|
18
|
+
export * from './generic/PlainTextContentCleaner.js';
|
|
19
|
+
export * from './generic/SegmentationResolver.js';
|
|
20
|
+
/**
|
|
21
|
+
* Load-prevention export.
|
|
22
|
+
*
|
|
23
|
+
* Modern bundlers (ESBuild, Vite) tree-shake classes that are only ever instantiated
|
|
24
|
+
* dynamically through MJ's `ClassFactory` — which is exactly how segmenters and cleaners
|
|
25
|
+
* are resolved. If a built-in is dropped from the bundle, `Resolve()` returns null and the
|
|
26
|
+
* resolver silently degrades to its fallback: content still gets cleaned and chunked, just
|
|
27
|
+
* by the wrong strategy, with no error to show for it.
|
|
28
|
+
*
|
|
29
|
+
* Call this no-op from the consuming application's bootstrap to force a static reference
|
|
30
|
+
* so the `@RegisterClass`-decorated segmenters are retained.
|
|
31
|
+
*/
|
|
32
|
+
export declare function LoadContentSegmenters(): void;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/ai-segmentation
|
|
3
|
+
*
|
|
4
|
+
* Pluggable content segmentation for RAG ingestion. Importing this package
|
|
5
|
+
* registers every built-in segmenter with the MJ class factory, so
|
|
6
|
+
* `BaseSegmenter.Resolve(key)` works for any of them.
|
|
7
|
+
*/
|
|
8
|
+
export * from './generic/Segmentation.types.js';
|
|
9
|
+
export * from './generic/BaseSegmenter.js';
|
|
10
|
+
export * from './generic/StructuralTextSegmenter.js';
|
|
11
|
+
export * from './generic/SemanticTextSegmenter.js';
|
|
12
|
+
export * from './generic/TranscriptSegmenter.js';
|
|
13
|
+
export * from './generic/FixedWindowSegmenter.js';
|
|
14
|
+
export * from './generic/AdaptiveBoundarySegmenter.js';
|
|
15
|
+
export * from './generic/PagedContentSegmenter.js';
|
|
16
|
+
export * from './generic/BaseContentCleaner.js';
|
|
17
|
+
export * from './generic/HtmlContentCleaner.js';
|
|
18
|
+
export * from './generic/PlainTextContentCleaner.js';
|
|
19
|
+
export * from './generic/SegmentationResolver.js';
|
|
20
|
+
/**
|
|
21
|
+
* Load-prevention export.
|
|
22
|
+
*
|
|
23
|
+
* Modern bundlers (ESBuild, Vite) tree-shake classes that are only ever instantiated
|
|
24
|
+
* dynamically through MJ's `ClassFactory` — which is exactly how segmenters and cleaners
|
|
25
|
+
* are resolved. If a built-in is dropped from the bundle, `Resolve()` returns null and the
|
|
26
|
+
* resolver silently degrades to its fallback: content still gets cleaned and chunked, just
|
|
27
|
+
* by the wrong strategy, with no error to show for it.
|
|
28
|
+
*
|
|
29
|
+
* Call this no-op from the consuming application's bootstrap to force a static reference
|
|
30
|
+
* so the `@RegisterClass`-decorated segmenters are retained.
|
|
31
|
+
*/
|
|
32
|
+
export function LoadContentSegmenters() {
|
|
33
|
+
// Intentionally empty — importing this module is what fires the @RegisterClass
|
|
34
|
+
// decorators; this function exists purely as a static import target.
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB;IACjC,+EAA+E;IAC/E,qEAAqE;AACzE,CAAC"}
|