@mastra/rag 0.0.0-commonjs-20250227130920

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.
Files changed (40) hide show
  1. package/.turbo/turbo-build.log +23 -0
  2. package/CHANGELOG.md +1151 -0
  3. package/LICENSE +44 -0
  4. package/README.md +26 -0
  5. package/dist/_tsup-dts-rollup.d.cts +620 -0
  6. package/dist/_tsup-dts-rollup.d.ts +620 -0
  7. package/dist/index.cjs +2524 -0
  8. package/dist/index.d.cts +22 -0
  9. package/dist/index.d.ts +22 -0
  10. package/dist/index.js +2505 -0
  11. package/docker-compose.yaml +22 -0
  12. package/eslint.config.js +6 -0
  13. package/package.json +72 -0
  14. package/src/document/document.test.ts +985 -0
  15. package/src/document/document.ts +281 -0
  16. package/src/document/index.ts +2 -0
  17. package/src/document/transformers/character.ts +279 -0
  18. package/src/document/transformers/html.ts +346 -0
  19. package/src/document/transformers/json.ts +265 -0
  20. package/src/document/transformers/latex.ts +19 -0
  21. package/src/document/transformers/markdown.ts +244 -0
  22. package/src/document/transformers/text.ts +134 -0
  23. package/src/document/transformers/token.ts +148 -0
  24. package/src/document/transformers/transformer.ts +5 -0
  25. package/src/document/types.ts +103 -0
  26. package/src/graph-rag/index.test.ts +235 -0
  27. package/src/graph-rag/index.ts +306 -0
  28. package/src/index.ts +6 -0
  29. package/src/rerank/index.test.ts +150 -0
  30. package/src/rerank/index.ts +154 -0
  31. package/src/tools/document-chunker.ts +30 -0
  32. package/src/tools/graph-rag.ts +117 -0
  33. package/src/tools/index.ts +3 -0
  34. package/src/tools/vector-query.ts +90 -0
  35. package/src/utils/default-settings.ts +33 -0
  36. package/src/utils/index.ts +2 -0
  37. package/src/utils/vector-prompts.ts +729 -0
  38. package/src/utils/vector-search.ts +41 -0
  39. package/tsconfig.json +5 -0
  40. package/vitest.config.ts +11 -0
@@ -0,0 +1,244 @@
1
+ import { Document } from 'llamaindex';
2
+
3
+ import { Language } from '../types';
4
+
5
+ import { RecursiveCharacterTransformer } from './character';
6
+
7
+ interface LineType {
8
+ metadata: Record<string, string>;
9
+ content: string;
10
+ }
11
+
12
+ interface HeaderType {
13
+ level: number;
14
+ name: string;
15
+ data: string;
16
+ }
17
+
18
+ export class MarkdownTransformer extends RecursiveCharacterTransformer {
19
+ constructor(
20
+ options: {
21
+ chunkSize?: number;
22
+ chunkOverlap?: number;
23
+ lengthFunction?: (text: string) => number;
24
+ keepSeparator?: boolean | 'start' | 'end';
25
+ addStartIndex?: boolean;
26
+ stripWhitespace?: boolean;
27
+ } = {},
28
+ ) {
29
+ const separators = RecursiveCharacterTransformer.getSeparatorsForLanguage(Language.MARKDOWN);
30
+ super({ separators, isSeparatorRegex: true, options });
31
+ }
32
+ }
33
+
34
+ export class MarkdownHeaderTransformer {
35
+ private headersToSplitOn: [string, string][];
36
+ private returnEachLine: boolean;
37
+ private stripHeaders: boolean;
38
+
39
+ constructor(headersToSplitOn: [string, string][], returnEachLine: boolean = false, stripHeaders: boolean = true) {
40
+ this.headersToSplitOn = [...headersToSplitOn].sort((a, b) => b[0].length - a[0].length);
41
+ this.returnEachLine = returnEachLine;
42
+ this.stripHeaders = stripHeaders;
43
+ }
44
+
45
+ private aggregateLinesToChunks(lines: LineType[]): Document[] {
46
+ if (this.returnEachLine) {
47
+ return lines.flatMap(line => {
48
+ const contentLines = line.content.split('\n');
49
+ return contentLines
50
+ .filter(l => l.trim() !== '' || this.headersToSplitOn.some(([sep]) => l.trim().startsWith(sep)))
51
+ .map(
52
+ l =>
53
+ new Document({
54
+ text: l.trim(),
55
+ metadata: line.metadata,
56
+ }),
57
+ );
58
+ });
59
+ }
60
+
61
+ const aggregatedChunks: LineType[] = [];
62
+
63
+ for (const line of lines) {
64
+ if (
65
+ aggregatedChunks.length > 0 &&
66
+ JSON.stringify(aggregatedChunks?.[aggregatedChunks.length - 1]!.metadata) === JSON.stringify(line.metadata)
67
+ ) {
68
+ const aggChunk = aggregatedChunks[aggregatedChunks.length - 1];
69
+ aggChunk!.content += ' \n' + line.content;
70
+ } else if (
71
+ aggregatedChunks.length > 0 &&
72
+ JSON.stringify(aggregatedChunks?.[aggregatedChunks.length - 1]!.metadata) !== JSON.stringify(line.metadata) &&
73
+ Object.keys(aggregatedChunks?.[aggregatedChunks.length - 1]!.metadata).length <
74
+ Object.keys(line.metadata).length &&
75
+ aggregatedChunks?.[aggregatedChunks.length - 1]?.content?.split('\n')?.slice(-1)[0]![0] === '#' &&
76
+ !this.stripHeaders
77
+ ) {
78
+ if (aggregatedChunks && aggregatedChunks?.[aggregatedChunks.length - 1]) {
79
+ const aggChunk = aggregatedChunks[aggregatedChunks.length - 1];
80
+ if (aggChunk) {
81
+ aggChunk.content += ' \n' + line.content;
82
+ aggChunk.metadata = line.metadata;
83
+ }
84
+ }
85
+ } else {
86
+ aggregatedChunks.push(line);
87
+ }
88
+ }
89
+
90
+ return aggregatedChunks.map(
91
+ chunk =>
92
+ new Document({
93
+ text: chunk.content,
94
+ metadata: chunk.metadata,
95
+ }),
96
+ );
97
+ }
98
+
99
+ splitText({ text }: { text: string }): Document[] {
100
+ const lines = text.split('\n');
101
+ const linesWithMetadata: LineType[] = [];
102
+ let currentContent: string[] = [];
103
+ let currentMetadata: Record<string, string> = {};
104
+ const headerStack: HeaderType[] = [];
105
+ const initialMetadata: Record<string, string> = {};
106
+
107
+ let inCodeBlock = false;
108
+ let openingFence = '';
109
+
110
+ for (let i = 0; i < lines.length; i++) {
111
+ const line = lines[i]!;
112
+ const strippedLine = line.trim();
113
+
114
+ if (!inCodeBlock) {
115
+ if (
116
+ (strippedLine.startsWith('```') && strippedLine.split('```').length === 2) ||
117
+ strippedLine.startsWith('~~~')
118
+ ) {
119
+ inCodeBlock = true;
120
+ openingFence = strippedLine.startsWith('```') ? '```' : '~~~';
121
+ }
122
+ } else {
123
+ if (strippedLine.startsWith(openingFence)) {
124
+ inCodeBlock = false;
125
+ openingFence = '';
126
+ }
127
+ }
128
+
129
+ if (inCodeBlock) {
130
+ currentContent.push(line);
131
+ continue;
132
+ }
133
+
134
+ let headerMatched = false;
135
+ for (const [sep, name] of this.headersToSplitOn) {
136
+ if (strippedLine.startsWith(sep) && (strippedLine.length === sep.length || strippedLine[sep.length] === ' ')) {
137
+ headerMatched = true;
138
+
139
+ // If we have existing content, save it before processing the header
140
+ if (currentContent.length > 0) {
141
+ linesWithMetadata.push({
142
+ content: currentContent.join('\n'),
143
+ metadata: { ...currentMetadata },
144
+ });
145
+ currentContent = [];
146
+ }
147
+
148
+ if (name !== null) {
149
+ const currentHeaderLevel = (sep.match(/#/g) || []).length;
150
+
151
+ // Pop headers of lower or same level
152
+ while (headerStack.length > 0 && headerStack?.[headerStack.length - 1]!.level >= currentHeaderLevel) {
153
+ const poppedHeader = headerStack.pop()!;
154
+ if (poppedHeader.name in initialMetadata) {
155
+ delete initialMetadata[poppedHeader.name];
156
+ }
157
+ }
158
+
159
+ // Push current header
160
+ const header: HeaderType = {
161
+ level: currentHeaderLevel,
162
+ name,
163
+ data: strippedLine.slice(sep.length).trim(),
164
+ };
165
+ headerStack.push(header);
166
+ initialMetadata[name] = header.data;
167
+ }
168
+
169
+ // Always create a separate chunk for the header
170
+ linesWithMetadata.push({
171
+ content: line,
172
+ metadata: { ...currentMetadata, ...initialMetadata },
173
+ });
174
+
175
+ break;
176
+ }
177
+ }
178
+
179
+ if (!headerMatched) {
180
+ if (strippedLine || this.returnEachLine) {
181
+ currentContent.push(line);
182
+
183
+ if (this.returnEachLine) {
184
+ // In returnEachLine mode, flush each non-header line immediately
185
+ linesWithMetadata.push({
186
+ content: line,
187
+ metadata: { ...currentMetadata },
188
+ });
189
+ currentContent = [];
190
+ }
191
+ } else if (currentContent.length > 0) {
192
+ linesWithMetadata.push({
193
+ content: currentContent.join('\n'),
194
+ metadata: { ...currentMetadata },
195
+ });
196
+ currentContent = [];
197
+ }
198
+ }
199
+
200
+ currentMetadata = { ...initialMetadata };
201
+ }
202
+
203
+ // Handle any remaining content
204
+ if (currentContent.length > 0) {
205
+ linesWithMetadata.push({
206
+ content: currentContent.join('\n'),
207
+ metadata: currentMetadata,
208
+ });
209
+ }
210
+
211
+ return this.aggregateLinesToChunks(linesWithMetadata);
212
+ }
213
+
214
+ createDocuments(texts: string[], metadatas?: Record<string, any>[]): Document[] {
215
+ const _metadatas = metadatas || Array(texts.length).fill({});
216
+ const documents: Document[] = [];
217
+
218
+ texts.forEach((text, i) => {
219
+ this.splitText({ text }).forEach(chunk => {
220
+ const metadata = { ..._metadatas[i], ...chunk.metadata };
221
+ documents.push(
222
+ new Document({
223
+ text: chunk.text,
224
+ metadata,
225
+ }),
226
+ );
227
+ });
228
+ });
229
+
230
+ return documents;
231
+ }
232
+
233
+ transformDocuments(documents: Document[]): Document[] {
234
+ const texts: string[] = [];
235
+ const metadatas: Record<string, any>[] = [];
236
+
237
+ for (const doc of documents) {
238
+ texts.push(doc.text);
239
+ metadatas.push(doc.metadata);
240
+ }
241
+
242
+ return this.createDocuments(texts, metadatas);
243
+ }
244
+ }
@@ -0,0 +1,134 @@
1
+ import { Document } from 'llamaindex';
2
+
3
+ import type { ChunkOptions } from '../types';
4
+
5
+ import type { Transformer } from './transformer';
6
+
7
+ export abstract class TextTransformer implements Transformer {
8
+ protected size: number;
9
+ protected overlap: number;
10
+ protected lengthFunction: (text: string) => number;
11
+ protected keepSeparator: boolean | 'start' | 'end';
12
+ protected addStartIndex: boolean;
13
+ protected stripWhitespace: boolean;
14
+
15
+ constructor({
16
+ size = 4000,
17
+ overlap = 200,
18
+ lengthFunction = (text: string) => text.length,
19
+ keepSeparator = false,
20
+ addStartIndex = false,
21
+ stripWhitespace = true,
22
+ }: ChunkOptions) {
23
+ if (overlap > size) {
24
+ throw new Error(`Got a larger chunk overlap (${overlap}) than chunk size ` + `(${size}), should be smaller.`);
25
+ }
26
+ this.size = size;
27
+ this.overlap = overlap;
28
+ this.lengthFunction = lengthFunction;
29
+ this.keepSeparator = keepSeparator;
30
+ this.addStartIndex = addStartIndex;
31
+ this.stripWhitespace = stripWhitespace;
32
+ }
33
+
34
+ setAddStartIndex(value: boolean): void {
35
+ this.addStartIndex = value;
36
+ }
37
+
38
+ abstract splitText({ text }: { text: string }): string[];
39
+
40
+ createDocuments(texts: string[], metadatas?: Record<string, any>[]): Document[] {
41
+ const _metadatas = metadatas || Array(texts.length).fill({});
42
+ const documents: Document[] = [];
43
+
44
+ texts.forEach((text, i) => {
45
+ let index = 0;
46
+ let previousChunkLen = 0;
47
+
48
+ this.splitText({ text }).forEach(chunk => {
49
+ const metadata = { ..._metadatas[i] };
50
+ if (this.addStartIndex) {
51
+ const offset = index + previousChunkLen - this.overlap;
52
+ index = text.indexOf(chunk, Math.max(0, offset));
53
+ metadata.startIndex = index;
54
+ previousChunkLen = chunk.length;
55
+ }
56
+ documents.push(
57
+ new Document({
58
+ text: chunk,
59
+ metadata,
60
+ }),
61
+ );
62
+ });
63
+ });
64
+
65
+ return documents;
66
+ }
67
+
68
+ splitDocuments(documents: Document[]): Document[] {
69
+ const texts: string[] = [];
70
+ const metadatas: Record<string, any>[] = [];
71
+ for (const doc of documents) {
72
+ texts.push(doc.text);
73
+ metadatas.push(doc.metadata);
74
+ }
75
+ return this.createDocuments(texts, metadatas);
76
+ }
77
+
78
+ transformDocuments(documents: Document[]): Document[] {
79
+ const texts: string[] = [];
80
+ const metadatas: Record<string, any>[] = [];
81
+
82
+ for (const doc of documents) {
83
+ texts.push(doc.text);
84
+ metadatas.push(doc.metadata);
85
+ }
86
+
87
+ return this.createDocuments(texts, metadatas);
88
+ }
89
+
90
+ protected joinDocs(docs: string[], separator: string): string | null {
91
+ let text = docs.join(separator);
92
+ if (this.stripWhitespace) {
93
+ text = text.trim();
94
+ }
95
+ return text === '' ? null : text;
96
+ }
97
+
98
+ protected mergeSplits(splits: string[], separator: string): string[] {
99
+ const separatorLen = this.lengthFunction(separator);
100
+ const docs: string[] = [];
101
+ let currentDoc: string[] = [];
102
+ let total = 0;
103
+
104
+ splits.forEach(d => {
105
+ const len = this.lengthFunction(d);
106
+ if (total + len + (currentDoc.length > 0 ? separatorLen : 0) > this.size) {
107
+ if (total > this.size) {
108
+ console.warn(`Created a chunk of size ${total}, ` + `which is longer than the specified ${this.size}`);
109
+ }
110
+ if (currentDoc.length > 0) {
111
+ const doc = this.joinDocs(currentDoc, separator);
112
+ if (doc !== null) {
113
+ docs.push(doc);
114
+ }
115
+ while (
116
+ total > this.overlap ||
117
+ (total + len + (currentDoc.length > 0 ? separatorLen : 0) > this.size && total > 0)
118
+ ) {
119
+ total -= this.lengthFunction(currentDoc?.[0]!) + (currentDoc.length > 1 ? separatorLen : 0);
120
+ currentDoc = currentDoc.slice(1);
121
+ }
122
+ }
123
+ }
124
+ currentDoc.push(d);
125
+ total += len + (currentDoc.length > 1 ? separatorLen : 0);
126
+ });
127
+
128
+ const doc = this.joinDocs(currentDoc, separator);
129
+ if (doc !== null) {
130
+ docs.push(doc);
131
+ }
132
+ return docs;
133
+ }
134
+ }
@@ -0,0 +1,148 @@
1
+ import type { TiktokenModel, TiktokenEncoding, Tiktoken } from 'js-tiktoken';
2
+ import { encodingForModel, getEncoding } from 'js-tiktoken';
3
+
4
+ import { TextTransformer } from './text';
5
+
6
+ interface Tokenizer {
7
+ overlap: number;
8
+ tokensPerChunk: number;
9
+ decode: (tokens: number[]) => string;
10
+ encode: (text: string) => number[];
11
+ }
12
+
13
+ export function splitTextOnTokens({ text, tokenizer }: { text: string; tokenizer: Tokenizer }): string[] {
14
+ const splits: string[] = [];
15
+ const inputIds = tokenizer.encode(text);
16
+ let startIdx = 0;
17
+ let curIdx = Math.min(startIdx + tokenizer.tokensPerChunk, inputIds.length);
18
+ let chunkIds = inputIds.slice(startIdx, curIdx);
19
+
20
+ while (startIdx < inputIds.length) {
21
+ splits.push(tokenizer.decode(chunkIds));
22
+ if (curIdx === inputIds.length) {
23
+ break;
24
+ }
25
+ startIdx += tokenizer.tokensPerChunk - tokenizer.overlap;
26
+ curIdx = Math.min(startIdx + tokenizer.tokensPerChunk, inputIds.length);
27
+ chunkIds = inputIds.slice(startIdx, curIdx);
28
+ }
29
+
30
+ return splits;
31
+ }
32
+
33
+ export class TokenTransformer extends TextTransformer {
34
+ private tokenizer: Tiktoken;
35
+ private allowedSpecial: Set<string> | 'all';
36
+ private disallowedSpecial: Set<string> | 'all';
37
+
38
+ constructor({
39
+ encodingName = 'cl100k_base',
40
+ modelName,
41
+ allowedSpecial = new Set(),
42
+ disallowedSpecial = 'all',
43
+ options = {},
44
+ }: {
45
+ encodingName: TiktokenEncoding;
46
+ modelName?: TiktokenModel;
47
+ allowedSpecial?: Set<string> | 'all';
48
+ disallowedSpecial?: Set<string> | 'all';
49
+ options: {
50
+ size?: number;
51
+ overlap?: number;
52
+ lengthFunction?: (text: string) => number;
53
+ keepSeparator?: boolean | 'start' | 'end';
54
+ addStartIndex?: boolean;
55
+ stripWhitespace?: boolean;
56
+ };
57
+ }) {
58
+ super(options);
59
+
60
+ try {
61
+ this.tokenizer = modelName ? encodingForModel(modelName) : getEncoding(encodingName);
62
+ } catch {
63
+ throw new Error('Could not load tiktoken encoding. ' + 'Please install it with `npm install js-tiktoken`.');
64
+ }
65
+
66
+ this.allowedSpecial = allowedSpecial;
67
+ this.disallowedSpecial = disallowedSpecial;
68
+ }
69
+
70
+ splitText({ text }: { text: string }): string[] {
71
+ const encode = (text: string): number[] => {
72
+ const allowed = this.allowedSpecial === 'all' ? 'all' : Array.from(this.allowedSpecial);
73
+
74
+ const disallowed = this.disallowedSpecial === 'all' ? 'all' : Array.from(this.disallowedSpecial);
75
+
76
+ // If stripWhitespace is enabled, trim the text before encoding
77
+ const processedText = this.stripWhitespace ? text.trim() : text;
78
+ return Array.from(this.tokenizer.encode(processedText, allowed, disallowed));
79
+ };
80
+
81
+ const decode = (tokens: number[]): string => {
82
+ const text = this.tokenizer.decode(tokens);
83
+ return this.stripWhitespace ? text.trim() : text;
84
+ };
85
+
86
+ const tokenizer: Tokenizer = {
87
+ overlap: this.overlap,
88
+ tokensPerChunk: this.size,
89
+ decode,
90
+ encode,
91
+ };
92
+
93
+ return splitTextOnTokens({ text, tokenizer });
94
+ }
95
+
96
+ static fromTikToken({
97
+ encodingName = 'cl100k_base',
98
+ modelName,
99
+ options = {},
100
+ }: {
101
+ encodingName?: TiktokenEncoding;
102
+ modelName?: TiktokenModel;
103
+ options?: {
104
+ size?: number;
105
+ overlap?: number;
106
+ allowedSpecial?: Set<string> | 'all';
107
+ disallowedSpecial?: Set<string> | 'all';
108
+ };
109
+ }): TokenTransformer {
110
+ let tokenizer: Tiktoken;
111
+
112
+ try {
113
+ if (modelName) {
114
+ tokenizer = encodingForModel(modelName);
115
+ } else {
116
+ tokenizer = getEncoding(encodingName);
117
+ }
118
+ } catch {
119
+ throw new Error('Could not load tiktoken encoding. ' + 'Please install it with `npm install js-tiktoken`.');
120
+ }
121
+
122
+ const tikTokenEncoder = (text: string): number => {
123
+ const allowed =
124
+ options.allowedSpecial === 'all' ? 'all' : options.allowedSpecial ? Array.from(options.allowedSpecial) : [];
125
+
126
+ const disallowed =
127
+ options.disallowedSpecial === 'all'
128
+ ? 'all'
129
+ : options.disallowedSpecial
130
+ ? Array.from(options.disallowedSpecial)
131
+ : [];
132
+
133
+ return tokenizer.encode(text, allowed, disallowed).length;
134
+ };
135
+
136
+ return new TokenTransformer({
137
+ encodingName,
138
+ modelName,
139
+ allowedSpecial: options.allowedSpecial,
140
+ disallowedSpecial: options.disallowedSpecial,
141
+ options: {
142
+ size: options.size,
143
+ overlap: options.overlap,
144
+ lengthFunction: tikTokenEncoder,
145
+ },
146
+ });
147
+ }
148
+ }
@@ -0,0 +1,5 @@
1
+ import type { Document } from 'llamaindex';
2
+
3
+ export interface Transformer {
4
+ transformDocuments(documents: Document[]): Document[];
5
+ }
@@ -0,0 +1,103 @@
1
+ import type { TiktokenEncoding, TiktokenModel } from 'js-tiktoken';
2
+ import type {
3
+ LLM,
4
+ TitleCombinePrompt,
5
+ TitleExtractorPrompt,
6
+ SummaryPrompt,
7
+ QuestionExtractPrompt,
8
+ KeywordExtractPrompt,
9
+ } from 'llamaindex';
10
+
11
+ export enum Language {
12
+ CPP = 'cpp',
13
+ GO = 'go',
14
+ JAVA = 'java',
15
+ KOTLIN = 'kotlin',
16
+ JS = 'js',
17
+ TS = 'ts',
18
+ PHP = 'php',
19
+ PROTO = 'proto',
20
+ PYTHON = 'python',
21
+ RST = 'rst',
22
+ RUBY = 'ruby',
23
+ RUST = 'rust',
24
+ SCALA = 'scala',
25
+ SWIFT = 'swift',
26
+ MARKDOWN = 'markdown',
27
+ LATEX = 'latex',
28
+ HTML = 'html',
29
+ SOL = 'sol',
30
+ CSHARP = 'csharp',
31
+ COBOL = 'cobol',
32
+ C = 'c',
33
+ LUA = 'lua',
34
+ PERL = 'perl',
35
+ HASKELL = 'haskell',
36
+ ELIXIR = 'elixir',
37
+ POWERSHELL = 'powershell',
38
+ }
39
+
40
+ export type ExtractParams = {
41
+ title?: TitleExtractorsArgs | boolean;
42
+ summary?: SummaryExtractArgs | boolean;
43
+ questions?: QuestionAnswerExtractArgs | boolean;
44
+ keywords?: boolean | Record<string, any>;
45
+ };
46
+
47
+ export type ChunkOptions = {
48
+ headers?: [string, string][];
49
+ returnEachLine?: boolean;
50
+ sections?: [string, string][];
51
+ separator?: string;
52
+ separators?: string[];
53
+ isSeparatorRegex?: boolean;
54
+ size?: number;
55
+ maxSize?: number;
56
+ minSize?: number;
57
+ overlap?: number;
58
+ lengthFunction?: (text: string) => number;
59
+ keepSeparator?: boolean | 'start' | 'end';
60
+ addStartIndex?: boolean;
61
+ stripWhitespace?: boolean;
62
+ language?: Language;
63
+ ensureAscii?: boolean;
64
+ convertLists?: boolean;
65
+ encodingName?: TiktokenEncoding;
66
+ modelName?: TiktokenModel;
67
+ allowedSpecial?: Set<string> | 'all';
68
+ disallowedSpecial?: Set<string> | 'all';
69
+ stripHeaders?: boolean;
70
+ };
71
+
72
+ export type TitleExtractorsArgs = {
73
+ llm?: LLM;
74
+ nodes?: number;
75
+ nodeTemplate?: TitleExtractorPrompt['template'];
76
+ combineTemplate?: TitleCombinePrompt['template'];
77
+ };
78
+
79
+ export type SummaryExtractArgs = {
80
+ llm?: LLM;
81
+ summaries?: string[];
82
+ promptTemplate?: SummaryPrompt['template'];
83
+ };
84
+
85
+ export type QuestionAnswerExtractArgs = {
86
+ llm?: LLM;
87
+ questions?: number;
88
+ promptTemplate?: QuestionExtractPrompt['template'];
89
+ embeddingOnly?: boolean;
90
+ };
91
+
92
+ export type KeywordExtractArgs = {
93
+ llm?: LLM;
94
+ keywords?: number;
95
+ promptTemplate?: KeywordExtractPrompt['template'];
96
+ };
97
+
98
+ export type ChunkStrategy = 'recursive' | 'character' | 'token' | 'markdown' | 'html' | 'json' | 'latex';
99
+
100
+ export interface ChunkParams extends ChunkOptions {
101
+ strategy?: ChunkStrategy;
102
+ extract?: ExtractParams;
103
+ }