@@ -26,14 +26,23 @@ const isValidMongoURI = (uri) => {
2626} ;
2727
2828const promptWithValidation = async ( promptConfig ) => {
29- const response = await enquirer . prompt ( promptConfig ) ;
30- if ( response [ promptConfig . name ] === '?' ) {
31- console . log ( chalk . yellow ( `ℹ️ Help: ${ promptConfig . helpMessage } \n` ) ) ;
32- return promptWithValidation ( promptConfig ) ;
29+ while ( true ) {
30+ const response = await enquirer . prompt ( promptConfig ) ;
31+ const userInput = response [ promptConfig . name ] ;
32+
33+ if ( userInput === '?' ) {
34+ console . log ( chalk . yellow ( `ℹ️ Help: ${ promptConfig . helpMessage } \n` ) ) ;
35+ continue ;
36+ }
37+ if ( promptConfig . validate && promptConfig . validate ( userInput ) !== true ) {
38+ console . log ( chalk . red ( `❌ ${ promptConfig . validate ( userInput ) } ` ) ) ;
39+ continue ;
40+ }
41+ return userInput ;
3342 }
34- return response ;
3543} ;
3644
45+
3746const CONFIG_PATH = process . env . NODE_ENV === "test"
3847 ? path . join ( process . cwd ( ) , ".mongodb-rag.test.json" )
3948 : path . join ( process . cwd ( ) , ".mongodb-rag.json" ) ;
@@ -172,59 +181,147 @@ program
172181
173182 const responses = { } ;
174183
184+ // MongoDB Connection String
175185 responses . mongoUrl = await promptWithValidation ( {
176186 type : 'input' ,
177187 name : 'mongoUrl' ,
178188 message : 'Enter MongoDB Connection String:' ,
179189 validate : ( input ) => isValidMongoURI ( input ) ? true : 'Invalid MongoDB Atlas connection string.' ,
180- helpMessage : "Example: mongodb+srv://user:password@cluster.mongodb.net/myDatabase?retryWrites=true&w=majority"
190+ helpMessage : "MongoDB Atlas connection string format:\n" +
191+ " mongodb+srv://username:password@cluster.mongodb.net/database\n" +
192+ "- Must be a MongoDB Atlas cluster (starts with mongodb+srv://)\n" +
193+ "- Include your username and password\n" +
194+ "- Should end with your cluster address (.mongodb.net)\n" +
195+ "- Can include optional parameters (e.g. ?retryWrites=true&w=majority)"
181196 } ) ;
182197
198+ // Database Name
183199 responses . database = await promptWithValidation ( {
184200 type : 'input' ,
185201 name : 'database' ,
186202 message : 'Enter Database Name:' ,
187- helpMessage : "Specify the database name where vector search will be performed."
203+ validate : ( input ) => {
204+ if ( ! input || input . trim ( ) . length === 0 ) return 'Database name cannot be empty' ;
205+ if ( input . includes ( ' ' ) ) return 'Database name cannot contain spaces' ;
206+ if ( input . length > 63 ) return 'Database name cannot exceed 63 characters' ;
207+ return true ;
208+ } ,
209+ helpMessage : "Database name requirements:\n" +
210+ "- Cannot be empty\n" +
211+ "- Must not contain spaces\n" +
212+ "- Maximum length of 63 characters\n" +
213+ "- Will be created if it doesn't exist\n" +
214+ "- Common names: 'vectordb', 'ragstore', 'embeddings'"
188215 } ) ;
189216
217+ // Collection Name
190218 responses . collection = await promptWithValidation ( {
191219 type : 'input' ,
192220 name : 'collection' ,
193221 message : 'Enter Collection Name:' ,
194- helpMessage : "Enter the collection that will store vector embeddings."
222+ validate : ( input ) => {
223+ if ( ! input || input . trim ( ) . length === 0 ) return 'Collection name cannot be empty' ;
224+ if ( input . includes ( ' ' ) ) return 'Collection name cannot contain spaces' ;
225+ if ( input . length > 255 ) return 'Collection name cannot exceed 255 characters' ;
226+ return true ;
227+ } ,
228+ helpMessage : "Collection name requirements:\n" +
229+ "- Cannot be empty\n" +
230+ "- Must not contain spaces\n" +
231+ "- Maximum length of 255 characters\n" +
232+ "- Will store your embedded documents\n" +
233+ "- Common names: 'documents', 'embeddings', 'vectors'"
195234 } ) ;
196235
236+ // Embedding Provider
197237 responses . provider = await promptWithValidation ( {
198238 type : 'select' ,
199239 name : 'provider' ,
200240 message : 'Select an Embedding Provider:' ,
201241 choices : [ 'openai' , 'deepseek' , 'ollama' ] ,
202- helpMessage : "Choose an AI provider for generating vector embeddings."
242+ helpMessage : "Available embedding providers:\n" +
243+ "- OpenAI: Most popular, requires API key, uses text-embedding-3-small\n" +
244+ "- DeepSeek: Alternative provider, requires API key\n" +
245+ "- Ollama: Local deployment, no API key needed, requires Ollama installation\n" +
246+ "\nConsiderations:\n" +
247+ "- OpenAI provides consistent, high-quality embeddings\n" +
248+ "- DeepSeek offers competitive pricing\n" +
249+ "- Ollama allows for local processing without API costs"
203250 } ) ;
204251
205- const indexParams = await getIndexParams ( responses ) ; // Keep the existing index prompt functionality
252+ // Get provider-specific configuration
253+ if ( responses . provider === 'openai' || responses . provider === 'deepseek' ) {
254+ responses . apiKey = await promptWithValidation ( {
255+ type : 'password' ,
256+ name : 'apiKey' ,
257+ message : `Enter your ${ responses . provider === 'openai' ? 'OpenAI' : 'DeepSeek' } API Key:` ,
258+ validate : ( input ) => input && input . length > 0 ? true : 'API key is required' ,
259+ helpMessage : responses . provider === 'openai'
260+ ? "OpenAI API key format: sk-....\n- Get your key from: https://platform.openai.com/api-keys"
261+ : "DeepSeek API key format: dk-....\n- Get your key from DeepSeek's platform"
262+ } ) ;
263+ } else if ( responses . provider === 'ollama' ) {
264+ responses . model = await promptWithValidation ( {
265+ type : 'input' ,
266+ name : 'model' ,
267+ message : 'Enter the Ollama model name:' ,
268+ initial : 'llama2' ,
269+ validate : ( input ) => input && input . length > 0 ? true : 'Model name is required' ,
270+ helpMessage : "Ollama model requirements:\n" +
271+ "- Must be installed locally via Ollama\n" +
272+ "- Common models: llama2, codellama, mistral\n" +
273+ "- Check available models with: ollama list"
274+ } ) ;
275+ }
276+
277+ // Vector Search Index Configuration
278+ const indexParams = await getIndexParams ( {
279+ type : 'input' ,
280+ name : 'indexName' ,
281+ message : 'Enter the name for your Vector Search Index:' ,
282+ initial : 'vector_index' ,
283+ validate : ( input ) => {
284+ if ( ! input || input . trim ( ) . length === 0 ) return 'Index name cannot be empty' ;
285+ if ( input . includes ( ' ' ) ) return 'Index name cannot contain spaces' ;
286+ return true ;
287+ } ,
288+ helpMessage : "Vector Search Index requirements:\n" +
289+ "- Cannot be empty or contain spaces\n" +
290+ "- Will be created automatically\n" +
291+ "- Used for similarity search operations\n" +
292+ "- Default name 'vector_index' is recommended"
293+ } ) ;
206294
295+ // Build the configuration object
207296 const newConfig = {
208297 mongoUrl : responses . mongoUrl ,
209298 database : responses . database ,
210299 collection : responses . collection ,
211300 embedding : {
212301 provider : responses . provider ,
302+ ...( responses . apiKey && { apiKey : responses . apiKey } ) ,
303+ ...( responses . model && { model : responses . model } ) ,
213304 dimensions : 1536 ,
214305 batchSize : 100
215306 } ,
216307 search : { maxResults : 5 , minScore : 0.7 } ,
217- indexName : indexParams . indexName // Keep the prompted index name
308+ indexName : indexParams . indexName
218309 } ;
219310
311+ // Save the configuration
220312 fs . writeFileSync ( CONFIG_PATH , JSON . stringify ( newConfig , null , 2 ) ) ;
221313 console . log ( chalk . green ( `✅ Configuration saved to ${ CONFIG_PATH } ` ) ) ;
222314
315+ // Provider-specific follow-up instructions
223316 if ( responses . provider === 'ollama' ) {
224317 console . log ( chalk . yellow ( '\n📝 Additional steps for Ollama setup:' ) ) ;
225318 console . log ( chalk . cyan ( '1. Ensure Ollama is running (`ollama list`)' ) ) ;
226- console . log ( chalk . cyan ( `2. Verify model '${ embeddingConfig . model } ' is installed` ) ) ;
319+ console . log ( chalk . cyan ( `2. Verify model '${ responses . model } ' is installed` ) ) ;
227320 console . log ( chalk . cyan ( '3. Run `npx mongodb-rag test-connection` to validate setup\n' ) ) ;
321+ } else {
322+ console . log ( chalk . cyan ( '\n🔍 Next steps:' ) ) ;
323+ console . log ( chalk . cyan ( '1. Run `npx mongodb-rag test-connection` to verify your setup' ) ) ;
324+ console . log ( chalk . cyan ( '2. Run `npx mongodb-rag create-index` to create your vector search index' ) ) ;
228325 }
229326 } ) ;
230327
0 commit comments