rag-lite-ts 2.2.0 → 2.3.1
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 +88 -5
- package/dist/cjs/cli/indexer.js +73 -15
- package/dist/cjs/cli/search.js +77 -2
- package/dist/cjs/cli/ui-server.d.ts +5 -0
- package/dist/cjs/cli/ui-server.js +152 -0
- package/dist/cjs/cli.js +53 -7
- package/dist/cjs/core/abstract-generator.d.ts +97 -0
- package/dist/cjs/core/abstract-generator.js +222 -0
- package/dist/cjs/core/binary-index-format.js +53 -10
- package/dist/cjs/core/db.d.ts +56 -0
- package/dist/cjs/core/db.js +105 -0
- package/dist/cjs/core/generator-registry.d.ts +114 -0
- package/dist/cjs/core/generator-registry.js +280 -0
- package/dist/cjs/core/index.d.ts +4 -0
- package/dist/cjs/core/index.js +11 -0
- package/dist/cjs/core/ingestion.js +3 -0
- package/dist/cjs/core/knowledge-base-manager.d.ts +109 -0
- package/dist/cjs/core/knowledge-base-manager.js +256 -0
- package/dist/cjs/core/lazy-dependency-loader.d.ts +43 -0
- package/dist/cjs/core/lazy-dependency-loader.js +111 -2
- package/dist/cjs/core/prompt-templates.d.ts +138 -0
- package/dist/cjs/core/prompt-templates.js +225 -0
- package/dist/cjs/core/response-generator.d.ts +132 -0
- package/dist/cjs/core/response-generator.js +69 -0
- package/dist/cjs/core/search-pipeline.js +1 -1
- package/dist/cjs/core/search.d.ts +72 -1
- package/dist/cjs/core/search.js +80 -7
- package/dist/cjs/core/types.d.ts +1 -0
- package/dist/cjs/core/vector-index-messages.d.ts +52 -0
- package/dist/cjs/core/vector-index-messages.js +5 -0
- package/dist/cjs/core/vector-index-worker.d.ts +6 -0
- package/dist/cjs/core/vector-index-worker.js +314 -0
- package/dist/cjs/core/vector-index.d.ts +45 -10
- package/dist/cjs/core/vector-index.js +279 -218
- package/dist/cjs/factories/generator-factory.d.ts +88 -0
- package/dist/cjs/factories/generator-factory.js +151 -0
- package/dist/cjs/factories/index.d.ts +1 -0
- package/dist/cjs/factories/index.js +5 -0
- package/dist/cjs/factories/ingestion-factory.js +3 -7
- package/dist/cjs/factories/search-factory.js +11 -0
- package/dist/cjs/index-manager.d.ts +23 -3
- package/dist/cjs/index-manager.js +84 -15
- package/dist/cjs/index.d.ts +11 -1
- package/dist/cjs/index.js +19 -1
- package/dist/cjs/text/generators/causal-lm-generator.d.ts +65 -0
- package/dist/cjs/text/generators/causal-lm-generator.js +197 -0
- package/dist/cjs/text/generators/index.d.ts +10 -0
- package/dist/cjs/text/generators/index.js +10 -0
- package/dist/cjs/text/generators/instruct-generator.d.ts +62 -0
- package/dist/cjs/text/generators/instruct-generator.js +192 -0
- package/dist/esm/cli/indexer.js +73 -15
- package/dist/esm/cli/search.js +77 -2
- package/dist/esm/cli/ui-server.d.ts +5 -0
- package/dist/esm/cli/ui-server.js +152 -0
- package/dist/esm/cli.js +53 -7
- package/dist/esm/core/abstract-generator.d.ts +97 -0
- package/dist/esm/core/abstract-generator.js +222 -0
- package/dist/esm/core/binary-index-format.js +53 -10
- package/dist/esm/core/db.d.ts +56 -0
- package/dist/esm/core/db.js +105 -0
- package/dist/esm/core/generator-registry.d.ts +114 -0
- package/dist/esm/core/generator-registry.js +280 -0
- package/dist/esm/core/index.d.ts +4 -0
- package/dist/esm/core/index.js +11 -0
- package/dist/esm/core/ingestion.js +3 -0
- package/dist/esm/core/knowledge-base-manager.d.ts +109 -0
- package/dist/esm/core/knowledge-base-manager.js +256 -0
- package/dist/esm/core/lazy-dependency-loader.d.ts +43 -0
- package/dist/esm/core/lazy-dependency-loader.js +111 -2
- package/dist/esm/core/prompt-templates.d.ts +138 -0
- package/dist/esm/core/prompt-templates.js +225 -0
- package/dist/esm/core/response-generator.d.ts +132 -0
- package/dist/esm/core/response-generator.js +69 -0
- package/dist/esm/core/search-pipeline.js +1 -1
- package/dist/esm/core/search.d.ts +72 -1
- package/dist/esm/core/search.js +80 -7
- package/dist/esm/core/types.d.ts +1 -0
- package/dist/esm/core/vector-index-messages.d.ts +52 -0
- package/dist/esm/core/vector-index-messages.js +5 -0
- package/dist/esm/core/vector-index-worker.d.ts +6 -0
- package/dist/esm/core/vector-index-worker.js +314 -0
- package/dist/esm/core/vector-index.d.ts +45 -10
- package/dist/esm/core/vector-index.js +279 -218
- package/dist/esm/factories/generator-factory.d.ts +88 -0
- package/dist/esm/factories/generator-factory.js +151 -0
- package/dist/esm/factories/index.d.ts +1 -0
- package/dist/esm/factories/index.js +5 -0
- package/dist/esm/factories/ingestion-factory.js +3 -7
- package/dist/esm/factories/search-factory.js +11 -0
- package/dist/esm/index-manager.d.ts +23 -3
- package/dist/esm/index-manager.js +84 -15
- package/dist/esm/index.d.ts +11 -1
- package/dist/esm/index.js +19 -1
- package/dist/esm/text/generators/causal-lm-generator.d.ts +65 -0
- package/dist/esm/text/generators/causal-lm-generator.js +197 -0
- package/dist/esm/text/generators/index.d.ts +10 -0
- package/dist/esm/text/generators/index.js +10 -0
- package/dist/esm/text/generators/instruct-generator.d.ts +62 -0
- package/dist/esm/text/generators/instruct-generator.js +192 -0
- package/package.json +14 -7
package/dist/esm/cli/search.js
CHANGED
|
@@ -132,7 +132,7 @@ export async function runSearch(query, options = {}) {
|
|
|
132
132
|
process.exit(EXIT_CODES.MODEL_ERROR);
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
// Prepare search options
|
|
135
|
+
// Prepare search options (with generation support)
|
|
136
136
|
const searchOptions = {};
|
|
137
137
|
if (options['top-k'] !== undefined) {
|
|
138
138
|
searchOptions.top_k = options['top-k'];
|
|
@@ -164,9 +164,60 @@ export async function runSearch(query, options = {}) {
|
|
|
164
164
|
}
|
|
165
165
|
// Track whether reranking will actually be used in this search
|
|
166
166
|
const rerankingUsed = searchOptions.rerank === true;
|
|
167
|
+
// Handle generation options (experimental, text mode only)
|
|
168
|
+
const generateResponse = options.generate === true;
|
|
169
|
+
const generatorModel = options.generator;
|
|
170
|
+
const maxGenerationTokens = options['max-tokens'];
|
|
171
|
+
const generationTemperature = options.temperature;
|
|
172
|
+
const maxChunksForContext = options['max-chunks'];
|
|
173
|
+
// Generation only supported in text mode
|
|
174
|
+
if (generateResponse && isImage) {
|
|
175
|
+
console.warn('⚠️ [EXPERIMENTAL] Generation is only supported for text searches.');
|
|
176
|
+
console.warn(' Image search results will be returned without generation.');
|
|
177
|
+
console.warn('');
|
|
178
|
+
}
|
|
179
|
+
// Generation requires reranking - enable it automatically
|
|
180
|
+
let rerankingEnabledForGeneration = false;
|
|
181
|
+
if (generateResponse && !isImage && !searchOptions.rerank) {
|
|
182
|
+
searchOptions.rerank = true;
|
|
183
|
+
rerankingEnabledForGeneration = true;
|
|
184
|
+
console.log('📋 Reranking automatically enabled (required for generation)');
|
|
185
|
+
}
|
|
186
|
+
// Set up generator if generation is requested (text mode only)
|
|
187
|
+
let generateFn;
|
|
188
|
+
if (generateResponse && !isImage) {
|
|
189
|
+
try {
|
|
190
|
+
console.log('🤖 [EXPERIMENTAL] Initializing response generator...');
|
|
191
|
+
const { createGenerateFunctionFromModel, getDefaultGeneratorModel } = await import('../factories/generator-factory.js');
|
|
192
|
+
const { getDefaultMaxChunksForContext } = await import('../core/generator-registry.js');
|
|
193
|
+
const modelToUse = generatorModel || getDefaultGeneratorModel();
|
|
194
|
+
const defaultChunks = getDefaultMaxChunksForContext(modelToUse) || 3;
|
|
195
|
+
console.log(` Model: ${modelToUse}`);
|
|
196
|
+
console.log(` Max chunks for context: ${maxChunksForContext || defaultChunks} (default: ${defaultChunks})`);
|
|
197
|
+
generateFn = await createGenerateFunctionFromModel(modelToUse);
|
|
198
|
+
searchEngine.setGenerateFunction(generateFn);
|
|
199
|
+
console.log('✅ Generator initialized');
|
|
200
|
+
console.log('');
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.error('❌ [EXPERIMENTAL] Failed to initialize generator:', error instanceof Error ? error.message : 'Unknown error');
|
|
204
|
+
console.error(' Continuing without generation...');
|
|
205
|
+
console.error('');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Set generation options if generator is ready
|
|
209
|
+
if (generateFn && generateResponse && !isImage) {
|
|
210
|
+
searchOptions.generateResponse = true;
|
|
211
|
+
searchOptions.generationOptions = {
|
|
212
|
+
maxTokens: maxGenerationTokens,
|
|
213
|
+
temperature: generationTemperature,
|
|
214
|
+
maxChunksForContext: maxChunksForContext
|
|
215
|
+
};
|
|
216
|
+
}
|
|
167
217
|
// Perform search
|
|
168
218
|
const startTime = Date.now();
|
|
169
219
|
let results;
|
|
220
|
+
let generationResult;
|
|
170
221
|
if (isImage && embedder) {
|
|
171
222
|
// Image-based search: embed the image and search with the vector
|
|
172
223
|
console.log('Embedding image...');
|
|
@@ -174,8 +225,14 @@ export async function runSearch(query, options = {}) {
|
|
|
174
225
|
console.log('Searching with image embedding...');
|
|
175
226
|
results = await searchEngine.searchWithVector(imageEmbedding.vector, searchOptions);
|
|
176
227
|
}
|
|
228
|
+
else if (generateResponse && generateFn) {
|
|
229
|
+
// Text-based search with generation
|
|
230
|
+
const searchResult = await searchEngine.searchWithGeneration(query, searchOptions);
|
|
231
|
+
results = searchResult.results;
|
|
232
|
+
generationResult = searchResult.generation;
|
|
233
|
+
}
|
|
177
234
|
else {
|
|
178
|
-
//
|
|
235
|
+
// Standard text-based search
|
|
179
236
|
results = await searchEngine.search(query, searchOptions);
|
|
180
237
|
}
|
|
181
238
|
const searchTime = Date.now() - startTime;
|
|
@@ -216,6 +273,21 @@ export async function runSearch(query, options = {}) {
|
|
|
216
273
|
}
|
|
217
274
|
console.log('');
|
|
218
275
|
});
|
|
276
|
+
// Display generated response if available (experimental)
|
|
277
|
+
if (generationResult) {
|
|
278
|
+
console.log('─'.repeat(50));
|
|
279
|
+
console.log('🤖 Generated Response [EXPERIMENTAL]');
|
|
280
|
+
console.log(`Model: ${generationResult.modelUsed}`);
|
|
281
|
+
console.log('─'.repeat(50));
|
|
282
|
+
console.log('');
|
|
283
|
+
console.log(generationResult.response);
|
|
284
|
+
console.log('');
|
|
285
|
+
console.log('─'.repeat(50));
|
|
286
|
+
console.log(`⏱️ Generation: ${(generationResult.generationTimeMs / 1000).toFixed(1)}s | ` +
|
|
287
|
+
`📊 ${generationResult.tokensUsed} tokens | ` +
|
|
288
|
+
`📄 ${generationResult.chunksUsedForContext} chunks used` +
|
|
289
|
+
(generationResult.truncated ? ' (context truncated)' : ''));
|
|
290
|
+
}
|
|
219
291
|
// Show search statistics
|
|
220
292
|
const stats = await searchEngine.getStats();
|
|
221
293
|
console.log('─'.repeat(50));
|
|
@@ -233,6 +305,9 @@ export async function runSearch(query, options = {}) {
|
|
|
233
305
|
else {
|
|
234
306
|
console.log('Reranking: disabled');
|
|
235
307
|
}
|
|
308
|
+
if (generationResult) {
|
|
309
|
+
console.log('Generation: enabled [EXPERIMENTAL]');
|
|
310
|
+
}
|
|
236
311
|
}
|
|
237
312
|
}
|
|
238
313
|
finally {
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Get the project root directory
|
|
9
|
+
* When built, CLI is at dist/esm/cli/ui-server.js, so go up 3 levels
|
|
10
|
+
* When running from source, CLI is at src/cli/ui-server.ts, so go up 2 levels
|
|
11
|
+
*/
|
|
12
|
+
function getProjectRoot() {
|
|
13
|
+
// Try going up 3 levels first (for built version)
|
|
14
|
+
const builtPath = join(__dirname, '../../..');
|
|
15
|
+
if (fs.existsSync(join(builtPath, 'package.json'))) {
|
|
16
|
+
return builtPath;
|
|
17
|
+
}
|
|
18
|
+
// Fallback: go up 2 levels (for source execution)
|
|
19
|
+
return join(__dirname, '../..');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Launch the UI server
|
|
23
|
+
*/
|
|
24
|
+
export async function runUI(options = {}) {
|
|
25
|
+
const port = options.port || 3000;
|
|
26
|
+
const backendPort = options.backendPort || 3001;
|
|
27
|
+
console.log('🚀 Launching RAG-lite TS UI...');
|
|
28
|
+
// Resolve UI paths from project root
|
|
29
|
+
const projectRoot = getProjectRoot();
|
|
30
|
+
const backendBuiltPath = join(projectRoot, 'ui', 'backend', 'dist', 'index.js');
|
|
31
|
+
const backendSourcePath = join(projectRoot, 'ui', 'backend', 'src', 'index.ts');
|
|
32
|
+
const frontendBuiltPath = join(projectRoot, 'ui', 'frontend', 'dist');
|
|
33
|
+
const frontendSourcePath = join(projectRoot, 'ui', 'frontend');
|
|
34
|
+
// Check if built files exist
|
|
35
|
+
const useBuiltBackend = fs.existsSync(backendBuiltPath);
|
|
36
|
+
const useBuiltFrontend = fs.existsSync(frontendBuiltPath);
|
|
37
|
+
if (!useBuiltBackend && !fs.existsSync(backendSourcePath)) {
|
|
38
|
+
console.error(`❌ UI backend not found at: ${backendSourcePath}`);
|
|
39
|
+
console.error(' Make sure the UI is set up in the ui/ directory.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
if (!useBuiltFrontend && !fs.existsSync(frontendSourcePath)) {
|
|
43
|
+
console.error(`❌ UI frontend not found at: ${frontendSourcePath}`);
|
|
44
|
+
console.error(' Make sure the UI is set up in the ui/ directory.');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
// Pass the working directory where 'raglite ui' was called to the backend
|
|
48
|
+
const workingDir = process.cwd();
|
|
49
|
+
// Built mode: single server on port (UI + API). Dev mode: backend on backendPort, frontend on port.
|
|
50
|
+
const effectiveBackendPort = useBuiltFrontend ? port : backendPort;
|
|
51
|
+
console.log(`📡 Starting backend on port ${effectiveBackendPort}...`);
|
|
52
|
+
// Start backend server - use built version if available
|
|
53
|
+
const backendCommand = useBuiltBackend ? 'node' : 'npx';
|
|
54
|
+
const backendArgs = useBuiltBackend
|
|
55
|
+
? [backendBuiltPath]
|
|
56
|
+
: ['tsx', backendSourcePath];
|
|
57
|
+
const backendProcess = spawn(backendCommand, backendArgs, {
|
|
58
|
+
stdio: 'pipe',
|
|
59
|
+
env: {
|
|
60
|
+
...process.env,
|
|
61
|
+
PORT: effectiveBackendPort.toString(),
|
|
62
|
+
RAG_WORKING_DIR: workingDir,
|
|
63
|
+
UI_FRONTEND_DIST: useBuiltFrontend ? frontendBuiltPath : undefined
|
|
64
|
+
},
|
|
65
|
+
shell: true
|
|
66
|
+
});
|
|
67
|
+
backendProcess.on('error', (err) => {
|
|
68
|
+
console.error('❌ Failed to start backend process:', err);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
71
|
+
// Forward backend output with prefix
|
|
72
|
+
backendProcess.stdout?.on('data', (data) => {
|
|
73
|
+
process.stdout.write(`[Backend] ${data}`);
|
|
74
|
+
});
|
|
75
|
+
backendProcess.stderr?.on('data', (data) => {
|
|
76
|
+
process.stderr.write(`[Backend] ${data}`);
|
|
77
|
+
});
|
|
78
|
+
// Only start frontend dev server if built version doesn't exist
|
|
79
|
+
let frontendProcess = null;
|
|
80
|
+
if (!useBuiltFrontend) {
|
|
81
|
+
console.log(`🎨 Starting frontend dev server on port ${port}...`);
|
|
82
|
+
frontendProcess = spawn('npm', ['run', 'dev'], {
|
|
83
|
+
cwd: frontendSourcePath,
|
|
84
|
+
stdio: 'pipe',
|
|
85
|
+
env: {
|
|
86
|
+
...process.env,
|
|
87
|
+
VITE_API_URL: `http://localhost:${effectiveBackendPort}`
|
|
88
|
+
},
|
|
89
|
+
shell: true
|
|
90
|
+
});
|
|
91
|
+
frontendProcess.on('error', (err) => {
|
|
92
|
+
console.error('❌ Failed to start frontend process:', err);
|
|
93
|
+
backendProcess.kill();
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|
|
96
|
+
// Forward frontend output with prefix
|
|
97
|
+
frontendProcess.stdout?.on('data', (data) => {
|
|
98
|
+
process.stdout.write(`[Frontend] ${data}`);
|
|
99
|
+
});
|
|
100
|
+
frontendProcess.stderr?.on('data', (data) => {
|
|
101
|
+
process.stderr.write(`[Frontend] ${data}`);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log(`🎨 Using built frontend from ${frontendBuiltPath}`);
|
|
106
|
+
console.log(` Frontend will be served by backend on port ${effectiveBackendPort}`);
|
|
107
|
+
}
|
|
108
|
+
// Wait a bit for servers to start
|
|
109
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
110
|
+
console.log(`\n✨ UI Access:`);
|
|
111
|
+
if (useBuiltFrontend) {
|
|
112
|
+
console.log(` Frontend & Backend: http://localhost:${port}`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log(` Frontend: http://localhost:${port}`);
|
|
116
|
+
console.log(` Backend: http://localhost:${effectiveBackendPort}`);
|
|
117
|
+
}
|
|
118
|
+
console.log(`\n💡 Press Ctrl+C to stop both servers\n`);
|
|
119
|
+
// Keep the process alive and handle cleanup
|
|
120
|
+
return new Promise((resolve) => {
|
|
121
|
+
const cleanup = () => {
|
|
122
|
+
console.log('\n🛑 Shutting down servers...');
|
|
123
|
+
backendProcess.kill();
|
|
124
|
+
if (frontendProcess) {
|
|
125
|
+
frontendProcess.kill();
|
|
126
|
+
}
|
|
127
|
+
resolve();
|
|
128
|
+
};
|
|
129
|
+
process.on('SIGINT', cleanup);
|
|
130
|
+
process.on('SIGTERM', cleanup);
|
|
131
|
+
// Handle process exits
|
|
132
|
+
backendProcess.on('exit', (code) => {
|
|
133
|
+
if (code !== 0 && code !== null) {
|
|
134
|
+
console.error(`\n❌ Backend process exited with code ${code}`);
|
|
135
|
+
if (frontendProcess) {
|
|
136
|
+
frontendProcess.kill();
|
|
137
|
+
}
|
|
138
|
+
resolve();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
if (frontendProcess) {
|
|
142
|
+
frontendProcess.on('exit', (code) => {
|
|
143
|
+
if (code !== 0 && code !== null) {
|
|
144
|
+
console.error(`\n❌ Frontend process exited with code ${code}`);
|
|
145
|
+
backendProcess.kill();
|
|
146
|
+
resolve();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=ui-server.js.map
|
package/dist/esm/cli.js
CHANGED
|
@@ -6,8 +6,18 @@ import { EXIT_CODES, ConfigurationError } from './core/config.js';
|
|
|
6
6
|
// Get package.json for version info
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = dirname(__filename);
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// When built, CLI is at dist/esm/cli.js, so go up two levels to root
|
|
10
|
+
// When running from source, CLI is at src/cli.ts, so go up one level to root
|
|
11
|
+
const packageJsonPath = join(__dirname, '..', '..', 'package.json');
|
|
12
|
+
let packageJson;
|
|
13
|
+
try {
|
|
14
|
+
packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Fallback: try one level up (for source execution)
|
|
18
|
+
const fallbackPath = join(__dirname, '..', 'package.json');
|
|
19
|
+
packageJson = JSON.parse(readFileSync(fallbackPath, 'utf-8'));
|
|
20
|
+
}
|
|
11
21
|
/**
|
|
12
22
|
* Display version information
|
|
13
23
|
*/
|
|
@@ -28,6 +38,7 @@ Usage:
|
|
|
28
38
|
Commands:
|
|
29
39
|
ingest <path> Ingest documents from file or directory
|
|
30
40
|
search <query> Search indexed documents (text or image)
|
|
41
|
+
ui Launch the web interface
|
|
31
42
|
rebuild Rebuild the vector index
|
|
32
43
|
version Show version information
|
|
33
44
|
help Show this help message
|
|
@@ -43,6 +54,8 @@ Examples:
|
|
|
43
54
|
raglite search "red car" --content-type image # Search only image results
|
|
44
55
|
raglite search ./photo.jpg # Search with image (multimodal mode only)
|
|
45
56
|
raglite search ./image.png --top-k 5 # Find similar images
|
|
57
|
+
raglite search "How does auth work?" --generate # [EXPERIMENTAL] Generate AI response
|
|
58
|
+
raglite ui # Launch web interface
|
|
46
59
|
|
|
47
60
|
raglite rebuild # Rebuild the entire index
|
|
48
61
|
|
|
@@ -52,10 +65,17 @@ Options for search:
|
|
|
52
65
|
--no-rerank Disable reranking
|
|
53
66
|
--content-type <type> Filter results by content type: 'text', 'image', or 'all' (default: all)
|
|
54
67
|
|
|
68
|
+
[EXPERIMENTAL] AI Response Generation (text mode only):
|
|
69
|
+
--generate Generate an AI response from search results
|
|
70
|
+
--generator <model> Generator model to use (default: SmolLM2-135M-Instruct)
|
|
71
|
+
--max-tokens <n> Maximum tokens to generate (default: 512)
|
|
72
|
+
--temperature <n> Sampling temperature 0-1 (default: 0.1)
|
|
73
|
+
--max-chunks <n> Maximum chunks for context (default: 3 for 135M, 5 for 360M)
|
|
74
|
+
|
|
55
75
|
Options for ingest:
|
|
56
76
|
--model <name> Use specific embedding model
|
|
57
77
|
--mode <mode> Processing mode: 'text' (default) or 'multimodal'
|
|
58
|
-
--
|
|
78
|
+
--force-rebuild Wipe DB+index and rebuild from scratch (DESTRUCTIVE)
|
|
59
79
|
--path-strategy <strategy> Path storage strategy: 'relative' (default) or 'absolute'
|
|
60
80
|
--path-base <path> Base directory for relative paths (defaults to current directory)
|
|
61
81
|
|
|
@@ -71,6 +91,12 @@ Available reranking strategies (multimodal mode):
|
|
|
71
91
|
text-derived Use image-to-text conversion + cross-encoder (default)
|
|
72
92
|
disabled No reranking, use vector similarity only
|
|
73
93
|
|
|
94
|
+
[EXPERIMENTAL] Available generator models:
|
|
95
|
+
HuggingFaceTB/SmolLM2-135M-Instruct (balanced, recommended default, uses top 3 chunks)
|
|
96
|
+
HuggingFaceTB/SmolLM2-360M-Instruct (higher quality, slower, uses top 5 chunks)
|
|
97
|
+
|
|
98
|
+
Note: Generation requires reranking (--rerank is automatically enabled with --generate)
|
|
99
|
+
|
|
74
100
|
For more information, visit: https://github.com/your-repo/rag-lite-ts
|
|
75
101
|
`);
|
|
76
102
|
}
|
|
@@ -111,8 +137,12 @@ function parseArgs() {
|
|
|
111
137
|
else if (optionName === 'no-rerank') {
|
|
112
138
|
options.rerank = false;
|
|
113
139
|
}
|
|
114
|
-
else if (optionName === 'rebuild
|
|
115
|
-
options.
|
|
140
|
+
else if (optionName === 'force-rebuild') {
|
|
141
|
+
options.forceRebuild = true;
|
|
142
|
+
}
|
|
143
|
+
else if (optionName === 'generate') {
|
|
144
|
+
// Handle --generate flag for experimental response generation
|
|
145
|
+
options.generate = true;
|
|
116
146
|
}
|
|
117
147
|
else if (optionName === 'help') {
|
|
118
148
|
return { command: 'help', args: [], options: {} };
|
|
@@ -124,7 +154,16 @@ function parseArgs() {
|
|
|
124
154
|
// Handle options with values
|
|
125
155
|
const nextArg = args[i + 1];
|
|
126
156
|
if (nextArg && !nextArg.startsWith('--')) {
|
|
127
|
-
|
|
157
|
+
// Parse numeric values for specific options
|
|
158
|
+
if (optionName === 'max-tokens' || optionName === 'top-k' || optionName === 'max-chunks') {
|
|
159
|
+
options[optionName] = parseInt(nextArg, 10);
|
|
160
|
+
}
|
|
161
|
+
else if (optionName === 'temperature') {
|
|
162
|
+
options[optionName] = parseFloat(nextArg);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
options[optionName] = nextArg;
|
|
166
|
+
}
|
|
128
167
|
i++; // Skip the next argument as it's the value
|
|
129
168
|
}
|
|
130
169
|
else {
|
|
@@ -169,7 +208,7 @@ function validateArgs(command, args, options) {
|
|
|
169
208
|
console.error('Options:');
|
|
170
209
|
console.error(' --model <name> Use specific embedding model');
|
|
171
210
|
console.error(' --mode <mode> Processing mode: text (default) or multimodal');
|
|
172
|
-
console.error(' --rebuild
|
|
211
|
+
console.error(' --force-rebuild Wipe DB+index and rebuild from scratch (DESTRUCTIVE)');
|
|
173
212
|
console.error('');
|
|
174
213
|
console.error('The path can be either a file (.md or .txt) or a directory.');
|
|
175
214
|
process.exit(EXIT_CODES.INVALID_ARGUMENTS);
|
|
@@ -201,6 +240,9 @@ function validateArgs(command, args, options) {
|
|
|
201
240
|
case 'rebuild':
|
|
202
241
|
// No arguments required
|
|
203
242
|
break;
|
|
243
|
+
case 'ui':
|
|
244
|
+
// No arguments required
|
|
245
|
+
break;
|
|
204
246
|
case 'version':
|
|
205
247
|
// No validation needed
|
|
206
248
|
break;
|
|
@@ -412,6 +454,10 @@ async function main() {
|
|
|
412
454
|
const { runRebuild } = await import('./cli/indexer.js');
|
|
413
455
|
await runRebuild();
|
|
414
456
|
break;
|
|
457
|
+
case 'ui':
|
|
458
|
+
const { runUI } = await import('./cli/ui-server.js');
|
|
459
|
+
await runUI(options);
|
|
460
|
+
break;
|
|
415
461
|
default:
|
|
416
462
|
console.error(`Error: Unknown command '${command}'`);
|
|
417
463
|
process.exit(1);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORE MODULE — Abstract Base Generator
|
|
3
|
+
*
|
|
4
|
+
* Provides model-agnostic base functionality for all generator implementations.
|
|
5
|
+
* This is an abstract base class, not a concrete implementation.
|
|
6
|
+
*
|
|
7
|
+
* ARCHITECTURAL NOTE:
|
|
8
|
+
* Similar to BaseUniversalEmbedder, this class provides shared infrastructure:
|
|
9
|
+
* - Model lifecycle management (loading, cleanup, disposal)
|
|
10
|
+
* - Token budget management
|
|
11
|
+
* - Error handling with helpful messages
|
|
12
|
+
* - Common utility methods
|
|
13
|
+
*
|
|
14
|
+
* IMPLEMENTATION LAYERS:
|
|
15
|
+
* - Text: InstructGenerator extends this class (SmolLM2-Instruct)
|
|
16
|
+
* - Text: CausalLMGenerator extends this class (DistilGPT2)
|
|
17
|
+
*
|
|
18
|
+
* @experimental This feature is experimental and may change in future versions.
|
|
19
|
+
*/
|
|
20
|
+
import type { ResponseGenerator, GeneratorModelInfo, GeneratorModelType, GenerationRequest, GenerationResult, GeneratorCreationOptions } from './response-generator.js';
|
|
21
|
+
import { GenerationError } from './response-generator.js';
|
|
22
|
+
/**
|
|
23
|
+
* Abstract base class for response generators
|
|
24
|
+
* Provides common functionality and lifecycle management
|
|
25
|
+
*/
|
|
26
|
+
export declare abstract class BaseResponseGenerator implements ResponseGenerator {
|
|
27
|
+
readonly modelName: string;
|
|
28
|
+
protected _isLoaded: boolean;
|
|
29
|
+
protected _modelInfo: GeneratorModelInfo;
|
|
30
|
+
protected _options: GeneratorCreationOptions;
|
|
31
|
+
constructor(modelName: string, options?: GeneratorCreationOptions);
|
|
32
|
+
get modelType(): GeneratorModelType;
|
|
33
|
+
get maxContextLength(): number;
|
|
34
|
+
get maxOutputLength(): number;
|
|
35
|
+
isLoaded(): boolean;
|
|
36
|
+
getModelInfo(): GeneratorModelInfo;
|
|
37
|
+
/**
|
|
38
|
+
* Load the model - must be implemented by subclasses
|
|
39
|
+
*/
|
|
40
|
+
abstract loadModel(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Generate text using the model - must be implemented by subclasses
|
|
43
|
+
* @param prompt - The formatted prompt string
|
|
44
|
+
* @param options - Generation options
|
|
45
|
+
* @returns Generated text
|
|
46
|
+
*/
|
|
47
|
+
protected abstract generateText(prompt: string, options: {
|
|
48
|
+
maxTokens: number;
|
|
49
|
+
temperature: number;
|
|
50
|
+
topP: number;
|
|
51
|
+
topK: number;
|
|
52
|
+
repetitionPenalty: number;
|
|
53
|
+
stopSequences: string[];
|
|
54
|
+
}): Promise<{
|
|
55
|
+
text: string;
|
|
56
|
+
promptTokens: number;
|
|
57
|
+
completionTokens: number;
|
|
58
|
+
finishReason: 'complete' | 'length' | 'stop_sequence' | 'error';
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Clean up resources - must be implemented by subclasses
|
|
62
|
+
*/
|
|
63
|
+
abstract cleanup(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Generate a response based on query and retrieved chunks
|
|
66
|
+
* This method orchestrates the generation pipeline
|
|
67
|
+
*/
|
|
68
|
+
generate(request: GenerationRequest): Promise<GenerationResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Validate that the model is loaded before operations
|
|
71
|
+
*/
|
|
72
|
+
protected ensureLoaded(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Clean up response text by removing artifacts
|
|
75
|
+
*/
|
|
76
|
+
protected cleanResponseText(text: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Log model loading progress
|
|
79
|
+
*/
|
|
80
|
+
protected logModelLoading(stage: string, details?: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Handle model loading errors with helpful messages
|
|
83
|
+
*/
|
|
84
|
+
protected handleLoadingError(error: Error): GenerationError;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extended options for generator instances
|
|
88
|
+
*/
|
|
89
|
+
export interface GeneratorOptions extends GeneratorCreationOptions {
|
|
90
|
+
/** Log level for debugging */
|
|
91
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Create generator options with defaults
|
|
95
|
+
*/
|
|
96
|
+
export declare function createGeneratorOptions(options?: Partial<GeneratorOptions>): GeneratorOptions;
|
|
97
|
+
//# sourceMappingURL=abstract-generator.d.ts.map
|