mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
fix formatting in vector_search_tool
This commit is contained in:
parent
0f23be96ca
commit
d1295ede90
@ -15,196 +15,196 @@ import type { ContextService } from '../context/services/context_service.js';
|
|||||||
import vectorSearchService from '../context/services/vector_search_service.js';
|
import vectorSearchService from '../context/services/vector_search_service.js';
|
||||||
|
|
||||||
export interface VectorSearchResult {
|
export interface VectorSearchResult {
|
||||||
noteId: string;
|
noteId: string;
|
||||||
title: string;
|
title: string;
|
||||||
contentPreview: string;
|
contentPreview: string;
|
||||||
similarity: number;
|
similarity: number;
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
dateCreated?: string;
|
dateCreated?: string;
|
||||||
dateModified?: string;
|
dateModified?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchResultItem {
|
export interface SearchResultItem {
|
||||||
noteId: string;
|
noteId: string;
|
||||||
noteTitle: string;
|
noteTitle: string;
|
||||||
contentPreview: string;
|
contentPreview: string;
|
||||||
similarity: number;
|
similarity: number;
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
dateCreated?: string;
|
dateCreated?: string;
|
||||||
dateModified?: string;
|
dateModified?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VectorSearchOptions {
|
export interface VectorSearchOptions {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
threshold?: number;
|
threshold?: number;
|
||||||
includeContent?: boolean;
|
includeContent?: boolean;
|
||||||
summarize?: boolean;
|
summarize?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a type for the context service
|
// Define a type for the context service
|
||||||
export interface IVectorContextService {
|
export interface IVectorContextService {
|
||||||
findRelevantNotes?: (query: string, contextNoteId: string | null, options: Record<string, unknown>) => Promise<unknown[]>;
|
findRelevantNotes?: (query: string, contextNoteId: string | null, options: Record<string, unknown>) => Promise<unknown[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VectorSearchTool {
|
export class VectorSearchTool {
|
||||||
private contextService: IVectorContextService | null = null;
|
private contextService: IVectorContextService | null = null;
|
||||||
private maxResults: number = 5;
|
private maxResults: number = 5;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
log.info('VectorSearchTool initialized using consolidated VectorSearchService');
|
log.info('VectorSearchTool initialized using consolidated VectorSearchService');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the context service for performing vector searches
|
* Set the context service for performing vector searches
|
||||||
*/
|
*/
|
||||||
setContextService(contextService: IVectorContextService): void {
|
setContextService(contextService: IVectorContextService): void {
|
||||||
this.contextService = contextService;
|
this.contextService = contextService;
|
||||||
log.info('Context service set in VectorSearchTool');
|
log.info('Context service set in VectorSearchTool');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a vector search for related notes
|
* Perform a vector search for related notes
|
||||||
*/
|
*/
|
||||||
async search(
|
async search(
|
||||||
query: string,
|
query: string,
|
||||||
contextNoteId?: string,
|
contextNoteId?: string,
|
||||||
searchOptions: VectorSearchOptions = {}
|
searchOptions: VectorSearchOptions = {}
|
||||||
): Promise<VectorSearchResult[]> {
|
): Promise<VectorSearchResult[]> {
|
||||||
try {
|
try {
|
||||||
// Set more aggressive defaults to return more content
|
// Set more aggressive defaults to return more content
|
||||||
const options = {
|
const options = {
|
||||||
maxResults: searchOptions.limit || 15, // Increased from default
|
maxResults: searchOptions.limit || 15, // Increased from default
|
||||||
threshold: searchOptions.threshold || 0.5, // Lower threshold to include more results
|
threshold: searchOptions.threshold || 0.5, // Lower threshold to include more results
|
||||||
includeContent: searchOptions.includeContent !== undefined ? searchOptions.includeContent : true,
|
includeContent: searchOptions.includeContent !== undefined ? searchOptions.includeContent : true,
|
||||||
summarizeContent: searchOptions.summarize || false,
|
summarizeContent: searchOptions.summarize || false,
|
||||||
...searchOptions
|
...searchOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
log.info(`Vector search: "${query.substring(0, 50)}..." with limit=${options.maxResults}, threshold=${options.threshold}`);
|
log.info(`Vector search: "${query.substring(0, 50)}..." with limit=${options.maxResults}, threshold=${options.threshold}`);
|
||||||
|
|
||||||
// Use the consolidated vector search service
|
// Use the consolidated vector search service
|
||||||
const searchResults = await vectorSearchService.findRelevantNotes(
|
const searchResults = await vectorSearchService.findRelevantNotes(
|
||||||
query,
|
query,
|
||||||
contextNoteId || null,
|
contextNoteId || null,
|
||||||
{
|
{
|
||||||
maxResults: options.maxResults,
|
maxResults: options.maxResults,
|
||||||
threshold: options.threshold,
|
threshold: options.threshold,
|
||||||
summarizeContent: options.summarizeContent
|
summarizeContent: options.summarizeContent
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
log.info(`Vector search found ${searchResults.length} relevant notes`);
|
||||||
|
|
||||||
|
// Format results to match the expected VectorSearchResult interface
|
||||||
|
return searchResults.map(note => ({
|
||||||
|
noteId: note.noteId,
|
||||||
|
title: note.title,
|
||||||
|
contentPreview: note.content
|
||||||
|
? note.content.length > 200
|
||||||
|
? note.content.substring(0, 200) + '...'
|
||||||
|
: note.content
|
||||||
|
: 'No content available',
|
||||||
|
similarity: note.similarity,
|
||||||
|
parentId: note.parentId
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`Vector search error: ${error}`);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
log.info(`Vector search found ${searchResults.length} relevant notes`);
|
|
||||||
|
|
||||||
// Format results to match the expected VectorSearchResult interface
|
|
||||||
return searchResults.map(note => ({
|
|
||||||
noteId: note.noteId,
|
|
||||||
title: note.title,
|
|
||||||
contentPreview: note.content
|
|
||||||
? note.content.length > 200
|
|
||||||
? note.content.substring(0, 200) + '...'
|
|
||||||
: note.content
|
|
||||||
: 'No content available',
|
|
||||||
similarity: note.similarity,
|
|
||||||
parentId: note.parentId
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
log.error(`Vector search error: ${error}`);
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for notes that are semantically related to the query
|
* Search for notes that are semantically related to the query
|
||||||
*/
|
*/
|
||||||
async searchNotes(query: string, options: {
|
async searchNotes(query: string, options: {
|
||||||
parentNoteId?: string,
|
parentNoteId?: string,
|
||||||
maxResults?: number,
|
maxResults?: number,
|
||||||
similarityThreshold?: number,
|
similarityThreshold?: number,
|
||||||
summarize?: boolean
|
summarize?: boolean
|
||||||
} = {}): Promise<VectorSearchResult[]> {
|
} = {}): Promise<VectorSearchResult[]> {
|
||||||
try {
|
try {
|
||||||
// Set defaults
|
// Set defaults
|
||||||
const maxResults = options.maxResults || this.maxResults;
|
const maxResults = options.maxResults || this.maxResults;
|
||||||
const threshold = options.similarityThreshold || 0.6;
|
const threshold = options.similarityThreshold || 0.6;
|
||||||
const parentNoteId = options.parentNoteId || null;
|
const parentNoteId = options.parentNoteId || null;
|
||||||
const summarize = options.summarize || false;
|
const summarize = options.summarize || false;
|
||||||
|
|
||||||
// Use the consolidated vector search service
|
// Use the consolidated vector search service
|
||||||
const results = await vectorSearchService.findRelevantNotes(
|
const results = await vectorSearchService.findRelevantNotes(
|
||||||
query,
|
query,
|
||||||
parentNoteId,
|
parentNoteId,
|
||||||
{
|
{
|
||||||
maxResults,
|
maxResults,
|
||||||
threshold,
|
threshold,
|
||||||
summarizeContent: summarize
|
summarizeContent: summarize
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Format results to match the expected interface
|
||||||
|
return results.map(result => ({
|
||||||
|
noteId: result.noteId,
|
||||||
|
title: result.title,
|
||||||
|
contentPreview: result.content ?
|
||||||
|
(result.content.length > 200 ?
|
||||||
|
result.content.substring(0, 200) + '...' :
|
||||||
|
result.content)
|
||||||
|
: 'No content available',
|
||||||
|
similarity: result.similarity,
|
||||||
|
parentId: result.parentId
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`Error in vector search: ${error}`);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
// Format results to match the expected interface
|
|
||||||
return results.map(result => ({
|
|
||||||
noteId: result.noteId,
|
|
||||||
title: result.title,
|
|
||||||
contentPreview: result.content ?
|
|
||||||
(result.content.length > 200 ?
|
|
||||||
result.content.substring(0, 200) + '...' :
|
|
||||||
result.content)
|
|
||||||
: 'No content available',
|
|
||||||
similarity: result.similarity,
|
|
||||||
parentId: result.parentId
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
log.error(`Error in vector search: ${error}`);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for content chunks that are semantically related to the query
|
|
||||||
*/
|
|
||||||
async searchContentChunks(query: string, options: {
|
|
||||||
noteId?: string,
|
|
||||||
maxResults?: number,
|
|
||||||
similarityThreshold?: number,
|
|
||||||
summarize?: boolean
|
|
||||||
} = {}): Promise<VectorSearchResult[]> {
|
|
||||||
try {
|
|
||||||
// For now, use the same implementation as searchNotes,
|
|
||||||
// but in the future we'll implement chunk-based search
|
|
||||||
return this.searchNotes(query, {
|
|
||||||
parentNoteId: options.noteId,
|
|
||||||
maxResults: options.maxResults,
|
|
||||||
similarityThreshold: options.similarityThreshold,
|
|
||||||
summarize: options.summarize
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
log.error(`Error in vector chunk search: ${error}`);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Elaborate on why certain results were returned for a query
|
|
||||||
*/
|
|
||||||
explainResults(query: string, results: VectorSearchResult[]): string {
|
|
||||||
if (!query || !results || results.length === 0) {
|
|
||||||
return "No results to explain.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let explanation = `For query "${query}", I found these semantically related notes:\n\n`;
|
/**
|
||||||
|
* Search for content chunks that are semantically related to the query
|
||||||
|
*/
|
||||||
|
async searchContentChunks(query: string, options: {
|
||||||
|
noteId?: string,
|
||||||
|
maxResults?: number,
|
||||||
|
similarityThreshold?: number,
|
||||||
|
summarize?: boolean
|
||||||
|
} = {}): Promise<VectorSearchResult[]> {
|
||||||
|
try {
|
||||||
|
// For now, use the same implementation as searchNotes,
|
||||||
|
// but in the future we'll implement chunk-based search
|
||||||
|
return this.searchNotes(query, {
|
||||||
|
parentNoteId: options.noteId,
|
||||||
|
maxResults: options.maxResults,
|
||||||
|
similarityThreshold: options.similarityThreshold,
|
||||||
|
summarize: options.summarize
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`Error in vector chunk search: ${error}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
results.forEach((result, index) => {
|
/**
|
||||||
explanation += `${index + 1}. "${result.title}" (similarity: ${(result.similarity * 100).toFixed(1)}%)\n`;
|
* Elaborate on why certain results were returned for a query
|
||||||
explanation += ` Preview: ${result.contentPreview.substring(0, 150)}...\n`;
|
*/
|
||||||
|
explainResults(query: string, results: VectorSearchResult[]): string {
|
||||||
|
if (!query || !results || results.length === 0) {
|
||||||
|
return "No results to explain.";
|
||||||
|
}
|
||||||
|
|
||||||
if (index < results.length - 1) {
|
let explanation = `For query "${query}", I found these semantically related notes:\n\n`;
|
||||||
explanation += "\n";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
explanation += "\nThese results were found based on semantic similarity rather than just keyword matching.";
|
results.forEach((result, index) => {
|
||||||
|
explanation += `${index + 1}. "${result.title}" (similarity: ${(result.similarity * 100).toFixed(1)}%)\n`;
|
||||||
|
explanation += ` Preview: ${result.contentPreview.substring(0, 150)}...\n`;
|
||||||
|
|
||||||
return explanation;
|
if (index < results.length - 1) {
|
||||||
}
|
explanation += "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
explanation += "\nThese results were found based on semantic similarity rather than just keyword matching.";
|
||||||
|
|
||||||
|
return explanation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new VectorSearchTool();
|
export default new VectorSearchTool();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user