class PersonalizedSearch extends AdvancedSearch {
constructor(apiKey, tenantId) {
super(apiKey, tenantId);
this.userProfiles = new Map();
}
async searchWithMemory(query, userId, options = {}) {
// Get user's AI memory profile (optional - for additional customization)
const userProfile = await this.getUserProfile(userId);
// Build personalized search options
const personalizedOptions = {
...options,
userName: userId, // Cortex can automatically manage user memories
userInstructions: this.buildPersonalizedInstructions(userProfile, query)
};
// Add user's preferred search modes and parameters
if (userProfile.preferredSearchModes) {
personalizedOptions.searchModes = userProfile.preferredSearchModes;
}
if (userProfile.preferredSourceTypes) {
personalizedOptions.metadata = {
...personalizedOptions.metadata,
source_type: userProfile.preferredSourceTypes
};
}
// Use session_id to maintain conversation context
const sessionId = await this.getUserSessionId(userId);
const searchResults = await this.search(query, {
...personalizedOptions,
sessionId
});
// Update user profile based on this interaction (optional)
await this.updateUserProfile(userId, query, searchResults);
return searchResults;
}
async getUserProfile(userId) {
// Retrieve user's AI memory profile from your backend
// Note: Cortex automatically manages user memories via userName and sessionId
// This is for additional customization beyond what Cortex provides
let profile = this.userProfiles.get(userId);
if (!profile) {
profile = {
userId,
preferredSearchModes: ['creative'],
preferredSourceTypes: [],
frequentQueries: [],
preferredFormats: ['bullet_points'],
responseStyle: 'concise',
favoriteSources: [],
searchHistory: [],
lastInteraction: null
};
this.userProfiles.set(userId, profile);
}
return profile;
}
buildPersonalizedInstructions(userProfile, query) {
let instructions = `User preferences: `;
if (userProfile.preferredFormats.includes('bullet_points')) {
instructions += `Prefer bullet point responses. `;
}
if (userProfile.responseStyle === 'concise') {
instructions += `Keep responses concise and to the point. `;
}
if (userProfile.favoriteSources.length > 0) {
instructions += `User frequently uses sources: ${userProfile.favoriteSources.join(', ')}. `;
}
if (userProfile.frequentQueries.length > 0) {
instructions += `User often searches for: ${userProfile.frequentQueries.slice(0, 3).join(', ')}. `;
}
instructions += `Current query: ${query}`;
return instructions;
}
async updateUserProfile(userId, query, searchResults) {
const profile = await this.getUserProfile(userId);
// Update search history
profile.searchHistory.push({
query,
timestamp: new Date().toISOString(),
resultCount: searchResults.sources?.length || 0
});
// Keep only last 50 searches
if (profile.searchHistory.length > 50) {
profile.searchHistory = profile.searchHistory.slice(-50);
}
// Update frequent queries
const queryLower = query.toLowerCase();
const existingIndex = profile.frequentQueries.findIndex(q =>
q.toLowerCase().includes(queryLower) || queryLower.includes(q.toLowerCase())
);
if (existingIndex === -1) {
profile.frequentQueries.unshift(query);
profile.frequentQueries = profile.frequentQueries.slice(0, 10);
}
// Update favorite sources based on what user clicks/uses
if (searchResults.sources) {
searchResults.sources.forEach(source => {
if (!profile.favoriteSources.includes(source.type)) {
profile.favoriteSources.push(source.type);
}
});
profile.favoriteSources = profile.favoriteSources.slice(0, 5);
}
// Update last interaction
profile.lastInteraction = new Date().toISOString();
// Save updated profile
this.userProfiles.set(userId, profile);
await this.saveUserProfile(userId, profile);
}
async saveUserProfile(userId, profile) {
// Save to your backend database
// This could be a simple database call or API call to your backend
console.log(`Saving profile for user ${userId}:`, profile);
}
async getUserSessionId(userId) {
// Maintain persistent session IDs for users to enable conversation memory
const sessionKey = `session_${userId}`;
let sessionId = localStorage.getItem(sessionKey);
if (!sessionId) {
sessionId = this.generateSessionId();
localStorage.setItem(sessionKey, sessionId);
}
return sessionId;
}
}