mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	query decomp is closer to working
This commit is contained in:
		@@ -376,6 +376,76 @@ export class VectorSearchService {
 | 
				
			|||||||
      return '';
 | 
					      return '';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Find notes that are semantically relevant to multiple queries
 | 
				
			||||||
 | 
					   * Combines results from multiple queries, deduplicates them, and returns the most relevant ones
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param queries - Array of search queries
 | 
				
			||||||
 | 
					   * @param contextNoteId - Optional note ID to restrict search to a branch
 | 
				
			||||||
 | 
					   * @param options - Search options including result limit and summarization preference
 | 
				
			||||||
 | 
					   * @returns Array of relevant notes with similarity scores, deduplicated and sorted
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  async findRelevantNotesMultiQuery(
 | 
				
			||||||
 | 
					    queries: string[],
 | 
				
			||||||
 | 
					    contextNoteId: string | null = null,
 | 
				
			||||||
 | 
					    options: VectorSearchOptions = {}
 | 
				
			||||||
 | 
					  ): Promise<NoteSearchResult[]> {
 | 
				
			||||||
 | 
					    if (!queries || queries.length === 0) {
 | 
				
			||||||
 | 
					      log.info('No queries provided to findRelevantNotesMultiQuery');
 | 
				
			||||||
 | 
					      return [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log.info(`VectorSearchService: Finding relevant notes for ${queries.length} queries`);
 | 
				
			||||||
 | 
					    log.info(`Multi-query parameters: contextNoteId=${contextNoteId || 'global'}, queries=${JSON.stringify(queries.map(q => q.substring(0, 20) + '...'))}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      // Create a Map to deduplicate results across queries
 | 
				
			||||||
 | 
					      const allResults = new Map<string, NoteSearchResult>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // For each query, adjust maxResults to avoid getting too many total results
 | 
				
			||||||
 | 
					      const adjustedMaxResults = options.maxResults ?
 | 
				
			||||||
 | 
					        Math.ceil(options.maxResults / queries.length) :
 | 
				
			||||||
 | 
					        Math.ceil(SEARCH_CONSTANTS.VECTOR_SEARCH.DEFAULT_MAX_RESULTS / queries.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Search for each query and combine results
 | 
				
			||||||
 | 
					      for (const query of queries) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          const queryOptions = {
 | 
				
			||||||
 | 
					            ...options,
 | 
				
			||||||
 | 
					            maxResults: adjustedMaxResults,
 | 
				
			||||||
 | 
					            useEnhancedQueries: false // We're already using enhanced queries
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const results = await this.findRelevantNotes(query, contextNoteId, queryOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Merge results, keeping the highest similarity score for duplicates
 | 
				
			||||||
 | 
					          for (const note of results) {
 | 
				
			||||||
 | 
					            if (!allResults.has(note.noteId) ||
 | 
				
			||||||
 | 
					                (allResults.has(note.noteId) && note.similarity > (allResults.get(note.noteId)?.similarity || 0))) {
 | 
				
			||||||
 | 
					              allResults.set(note.noteId, note);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          log.info(`Found ${results.length} results for query: "${query.substring(0, 30)}..."`);
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					          log.error(`Error searching for query "${query}": ${error}`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Convert map to array and sort by similarity
 | 
				
			||||||
 | 
					      const combinedResults = Array.from(allResults.values())
 | 
				
			||||||
 | 
					        .sort((a, b) => b.similarity - a.similarity)
 | 
				
			||||||
 | 
					        .slice(0, options.maxResults || SEARCH_CONSTANTS.VECTOR_SEARCH.DEFAULT_MAX_RESULTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      log.info(`VectorSearchService: Found ${combinedResults.length} total deduplicated results across ${queries.length} queries`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return combinedResults;
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      log.error(`Error in findRelevantNotesMultiQuery: ${error}`);
 | 
				
			||||||
 | 
					      return [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Export a singleton instance
 | 
					// Export a singleton instance
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -202,21 +202,23 @@ export class ChatPipeline {
 | 
				
			|||||||
            const vectorSearchStartTime = Date.now();
 | 
					            const vectorSearchStartTime = Date.now();
 | 
				
			||||||
            log.info(`========== STAGE 3: VECTOR SEARCH ==========`);
 | 
					            log.info(`========== STAGE 3: VECTOR SEARCH ==========`);
 | 
				
			||||||
            log.info('Using VectorSearchStage pipeline component to find relevant notes');
 | 
					            log.info('Using VectorSearchStage pipeline component to find relevant notes');
 | 
				
			||||||
 | 
					            log.info(`Searching with ${searchQueries.length} queries from decomposition`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Use the vectorSearchStage with multiple queries
 | 
				
			||||||
            const vectorSearchResult = await this.stages.vectorSearch.execute({
 | 
					            const vectorSearchResult = await this.stages.vectorSearch.execute({
 | 
				
			||||||
                query: userQuery,
 | 
					                query: userQuery, // Original query as fallback
 | 
				
			||||||
 | 
					                queries: searchQueries, // All decomposed queries
 | 
				
			||||||
                noteId: input.noteId || 'global',
 | 
					                noteId: input.noteId || 'global',
 | 
				
			||||||
                options: {
 | 
					                options: {
 | 
				
			||||||
                    maxResults: SEARCH_CONSTANTS.CONTEXT.MAX_SIMILAR_NOTES,
 | 
					                    maxResults: SEARCH_CONSTANTS.CONTEXT.MAX_SIMILAR_NOTES,
 | 
				
			||||||
                    useEnhancedQueries: true,
 | 
					                    useEnhancedQueries: false, // We're already using enhanced queries from decomposition
 | 
				
			||||||
                    threshold: SEARCH_CONSTANTS.VECTOR_SEARCH.DEFAULT_THRESHOLD,
 | 
					                    threshold: SEARCH_CONSTANTS.VECTOR_SEARCH.DEFAULT_THRESHOLD,
 | 
				
			||||||
                    llmService: llmService || undefined
 | 
					                    llmService: llmService || undefined
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.updateStageMetrics('vectorSearch', vectorSearchStartTime);
 | 
					            this.updateStageMetrics('vectorSearch', vectorSearchStartTime);
 | 
				
			||||||
 | 
					            log.info(`Vector search found ${vectorSearchResult.searchResults.length} relevant notes across ${searchQueries.length} queries`);
 | 
				
			||||||
            log.info(`Vector search found ${vectorSearchResult.searchResults.length} relevant notes`);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Extract context from search results
 | 
					            // Extract context from search results
 | 
				
			||||||
            log.info(`========== SEMANTIC CONTEXT EXTRACTION ==========`);
 | 
					            log.info(`========== SEMANTIC CONTEXT EXTRACTION ==========`);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ import { SEARCH_CONSTANTS } from '../../constants/search_constants.js';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface VectorSearchInput {
 | 
					export interface VectorSearchInput {
 | 
				
			||||||
  query: string;
 | 
					  query: string;
 | 
				
			||||||
 | 
					  queries?: string[];
 | 
				
			||||||
  noteId?: string;
 | 
					  noteId?: string;
 | 
				
			||||||
  options?: {
 | 
					  options?: {
 | 
				
			||||||
    maxResults?: number;
 | 
					    maxResults?: number;
 | 
				
			||||||
@@ -42,6 +43,7 @@ export class VectorSearchStage {
 | 
				
			|||||||
  async execute(input: VectorSearchInput): Promise<VectorSearchOutput> {
 | 
					  async execute(input: VectorSearchInput): Promise<VectorSearchOutput> {
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
      query,
 | 
					      query,
 | 
				
			||||||
 | 
					      queries = [],
 | 
				
			||||||
      noteId = 'global',
 | 
					      noteId = 'global',
 | 
				
			||||||
      options = {}
 | 
					      options = {}
 | 
				
			||||||
    } = input;
 | 
					    } = input;
 | 
				
			||||||
@@ -53,6 +55,42 @@ export class VectorSearchStage {
 | 
				
			|||||||
      llmService = undefined
 | 
					      llmService = undefined
 | 
				
			||||||
    } = options;
 | 
					    } = options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If queries array is provided, use multi-query search
 | 
				
			||||||
 | 
					    if (queries && queries.length > 0) {
 | 
				
			||||||
 | 
					      log.info(`VectorSearchStage: Searching with ${queries.length} queries`);
 | 
				
			||||||
 | 
					      log.info(`Parameters: noteId=${noteId}, maxResults=${maxResults}, threshold=${threshold}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        // Use the new multi-query method
 | 
				
			||||||
 | 
					        const searchResults = await vectorSearchService.findRelevantNotesMultiQuery(
 | 
				
			||||||
 | 
					          queries,
 | 
				
			||||||
 | 
					          noteId === 'global' ? null : noteId,
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            maxResults,
 | 
				
			||||||
 | 
					            threshold,
 | 
				
			||||||
 | 
					            llmService: llmService || null
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log.info(`VectorSearchStage: Found ${searchResults.length} relevant notes from multi-query search`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          searchResults,
 | 
				
			||||||
 | 
					          originalQuery: query,
 | 
				
			||||||
 | 
					          noteId
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        log.error(`Error in vector search stage multi-query: ${error}`);
 | 
				
			||||||
 | 
					        // Return empty results on error
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          searchResults: [],
 | 
				
			||||||
 | 
					          originalQuery: query,
 | 
				
			||||||
 | 
					          noteId
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fallback to single query search
 | 
				
			||||||
    log.info(`VectorSearchStage: Searching for "${query.substring(0, 50)}..."`);
 | 
					    log.info(`VectorSearchStage: Searching for "${query.substring(0, 50)}..."`);
 | 
				
			||||||
    log.info(`Parameters: noteId=${noteId}, maxResults=${maxResults}, threshold=${threshold}`);
 | 
					    log.info(`Parameters: noteId=${noteId}, maxResults=${maxResults}, threshold=${threshold}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,7 +102,7 @@ export class VectorSearchStage {
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
          maxResults,
 | 
					          maxResults,
 | 
				
			||||||
          threshold,
 | 
					          threshold,
 | 
				
			||||||
          llmService
 | 
					          llmService: llmService || null
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user