@escher-dbai/rag-module
Version:
Enterprise RAG module with chat context storage, vector search, and session management. Complete chat history retrieval and streaming content extraction for Electron apps.
163 lines (140 loc) • 5.91 kB
JavaScript
/**
* Minimal ContextRetrievalService - Service for retrieving conversation context from local files
* This version works directly with local JSON files instead of Qdrant to avoid ES module dependencies
*/
const fs = require('fs-extra');
const path = require('path');
class ContextRetrievalServiceMinimal {
/**
* @param {Object} qdrantClient - Mock Qdrant client (for compatibility)
* @param {string} collectionName - Collection name (for compatibility)
*/
constructor(qdrantClient, collectionName = 'chat-collection') {
this.qdrantClient = qdrantClient;
this.collectionName = collectionName;
this.dataFolder = null;
// Extract dataFolder from qdrantClient if it's a mock object with dataFolder property
if (qdrantClient && qdrantClient.dataFolder) {
this.dataFolder = qdrantClient.dataFolder;
}
}
/**
* Get organized query-response pairs for a specific context ID
* @param {string|Array} contextId - Context ID(s) to retrieve (string or array of strings)
* @param {number|Object} [limitOrOptions=100] - Maximum pairs to return OR options object
* @param {Object} [options={}] - Additional options (when second param is number)
* @returns {Promise<{contextId: string, chatTitle: string, queries: Array, responses: Array, pairs: Array, stats: Object}>} - Organized query-response data
*/
async getQueryResponsePairs(contextId, limitOrOptions = 100, options = {}) {
// Handle flexible parameter formats
let actualContextId, actualOptions, actualLimit;
if (Array.isArray(contextId)) {
actualContextId = contextId[0]; // Take first element if array
} else {
actualContextId = contextId;
}
if (typeof limitOrOptions === 'number') {
actualLimit = limitOrOptions;
actualOptions = options;
} else {
actualLimit = limitOrOptions.limit || 100;
actualOptions = limitOrOptions;
}
try {
console.log('🔍 ContextRetrievalMinimal: Searching for context:', actualContextId);
console.log('🔍 ContextRetrievalMinimal: Data folder:', this.dataFolder);
// Try to read from local context file
let contextData = null;
if (this.dataFolder) {
const contextFilePath = path.join(this.dataFolder, `${actualContextId}.json`);
console.log('🔍 ContextRetrievalMinimal: Looking for file:', contextFilePath);
if (await fs.pathExists(contextFilePath)) {
console.log('✅ ContextRetrievalMinimal: Found context file');
contextData = await fs.readJson(contextFilePath);
} else {
console.log('❌ ContextRetrievalMinimal: Context file not found');
}
}
// Extract conversation pairs from context data
let pairs = [];
let chatTitle = '';
if (contextData && contextData.final_conversation_context) {
const messages = contextData.final_conversation_context.m || [];
chatTitle = contextData.final_conversation_context.ct || contextData.chat_title || '';
console.log('🔍 ContextRetrievalMinimal: Found', messages.length, 'messages');
// Convert messages to query-response pairs
for (let i = 0; i < messages.length - 1; i += 2) {
if (messages[i] && messages[i + 1]) {
const query = messages[i];
const response = messages[i + 1];
// Only create pairs if we have both query and response
if (query.r === 0 && response.r === 1) { // r=0 is user, r=1 is assistant
pairs.push({
query: {
content: query.c || '',
role: 'user',
timestamp: contextData.final_conversation_context.t
},
response: {
content: response.c || '',
role: 'assistant',
timestamp: contextData.final_conversation_context.l
}
});
}
}
}
// Limit the number of pairs returned
if (pairs.length > actualLimit) {
pairs = pairs.slice(-actualLimit); // Take most recent pairs
}
}
console.log('🔍 ContextRetrievalMinimal: Final results:');
console.log(' - Total pairs:', pairs.length);
console.log(' - Chat title:', chatTitle);
if (pairs.length > 0) {
console.log('🔍 ContextRetrievalMinimal: Sample pair:');
console.log(' - Query:', pairs[0].query.content.substring(0, 100) + '...');
console.log(' - Response:', pairs[0].response.content.substring(0, 100) + '...');
}
return {
contextId: actualContextId,
chatTitle,
queries: pairs.map(p => p.query),
responses: pairs.map(p => p.response),
pairs,
stats: {
totalMessages: pairs.length * 2,
queryCount: pairs.length,
responseCount: pairs.length,
pairCount: pairs.length,
retrievedAt: new Date().toISOString()
}
};
} catch (error) {
console.error('❌ ContextRetrievalMinimal: Error:', error.message);
throw new Error(`Failed to retrieve context messages: ${error.message}`);
}
}
/**
* Find available context IDs (mock implementation for compatibility)
* @param {Object} [options={}] - Search options
* @returns {Promise<Array>} - Array of context IDs
*/
async findContextIds(options = {}) {
try {
if (!this.dataFolder) {
return [];
}
const files = await fs.readdir(this.dataFolder);
const contextIds = files
.filter(file => file.endsWith('.json'))
.map(file => file.replace('.json', ''));
return contextIds;
} catch (error) {
console.error('❌ ContextRetrievalMinimal: Error finding context IDs:', error.message);
return [];
}
}
}
module.exports = ContextRetrievalServiceMinimal;