feat: add match visibility and semantic highlighting to hybrid search
- Add textMatches, textScore, semanticScore, matchSource to search results - Add highlight() method for zero-config text + semantic highlighting - Increase word indexing limit to 5000 (handles articles/chapters) - Optimize findMatchingWords() with O(1) fast path for semantic-only results - Add production safety limits (500 chunks for highlight) - Add comprehensive tests for new features (35 tests) - Update docs with match visibility and highlight() API
This commit is contained in:
parent
b0ea2f3810
commit
4adba1b254
7 changed files with 1727 additions and 31 deletions
|
|
@ -82,6 +82,12 @@ export interface Result<T = any> {
|
|||
|
||||
// Score transparency
|
||||
explanation?: ScoreExplanation
|
||||
|
||||
// Match visibility (v7.8.0) - shows what matched in hybrid search
|
||||
textMatches?: string[] // Query words found in entity (e.g., ["david", "warrior"])
|
||||
textScore?: number // Normalized text match score (0-1)
|
||||
semanticScore?: number // Semantic similarity score (0-1)
|
||||
matchSource?: 'text' | 'semantic' | 'both' // Where this result came from
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,6 +198,10 @@ export interface FindParams<T = any> {
|
|||
includeRelations?: boolean // Include entity relationships
|
||||
excludeVFS?: boolean // v4.7.0: Exclude VFS entities from results (default: false - VFS included)
|
||||
service?: string // Multi-tenancy filter
|
||||
|
||||
// Hybrid search options (v7.7.0)
|
||||
searchMode?: 'auto' | 'text' | 'semantic' | 'vector' | 'hybrid' // Search strategy: auto (default), text-only, semantic/vector-only, or explicit hybrid
|
||||
hybridAlpha?: number // Weight between text (0.0) and semantic (1.0) search, default: auto-detected by query length
|
||||
|
||||
// Triple Intelligence Fusion
|
||||
fusion?: {
|
||||
|
|
@ -223,12 +233,14 @@ export interface GraphConstraints {
|
|||
/**
|
||||
* Search modes
|
||||
*/
|
||||
export type SearchMode =
|
||||
| 'auto' // Automatically choose best mode
|
||||
| 'vector' // Pure vector search
|
||||
export type SearchMode =
|
||||
| 'auto' // Automatically choose best mode (default - enables hybrid text+semantic)
|
||||
| 'vector' // Pure vector search (semantic only)
|
||||
| 'semantic' // Alias for vector search
|
||||
| 'text' // Pure text/keyword search
|
||||
| 'metadata' // Pure metadata filtering
|
||||
| 'graph' // Pure graph traversal
|
||||
| 'hybrid' // Combine all intelligences
|
||||
| 'hybrid' // Combine all intelligences (explicit hybrid mode)
|
||||
|
||||
/**
|
||||
* Parameters for similarity search
|
||||
|
|
@ -777,6 +789,62 @@ export interface NeuralAnomalyParams {
|
|||
returnScores?: boolean // Return anomaly scores
|
||||
}
|
||||
|
||||
// ============= Semantic Highlighting Types (v7.8.0) =============
|
||||
|
||||
/**
|
||||
* Parameters for hybrid highlighting (v7.8.0)
|
||||
*
|
||||
* Zero-config highlighting that returns both text (exact) and semantic (concept) matches.
|
||||
* Perfect for UI highlighting at different levels.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const highlights = await brain.highlight({
|
||||
* query: "david the warrior",
|
||||
* text: "David Smith is a brave fighter who battles dragons"
|
||||
* })
|
||||
* // Returns: [
|
||||
* // { text: "David", score: 1.0, position: [0, 5], matchType: 'text' }, // Exact match
|
||||
* // { text: "fighter", score: 0.78, position: [25, 32], matchType: 'semantic' }, // Concept match
|
||||
* // { text: "battles", score: 0.72, position: [37, 44], matchType: 'semantic' } // Concept match
|
||||
* // ]
|
||||
* ```
|
||||
*/
|
||||
export interface HighlightParams {
|
||||
/** The search query to match against */
|
||||
query: string
|
||||
|
||||
/** The text to highlight (e.g., entity.data) */
|
||||
text: string
|
||||
|
||||
/** Granularity of highlighting: 'word' (default), 'phrase', or 'sentence' */
|
||||
granularity?: 'word' | 'phrase' | 'sentence'
|
||||
|
||||
/** Minimum semantic similarity score for semantic matches (default: 0.5) */
|
||||
threshold?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* A highlight showing which text matched the query
|
||||
*
|
||||
* matchType tells the UI how to style the highlight:
|
||||
* - 'text': Exact word match (strongest signal, highest confidence)
|
||||
* - 'semantic': Conceptually similar match (may need softer highlight)
|
||||
*/
|
||||
export interface Highlight {
|
||||
/** The text that matched */
|
||||
text: string
|
||||
|
||||
/** Match score (0-1). For text matches, always 1.0. For semantic, varies by similarity. */
|
||||
score: number
|
||||
|
||||
/** Position in original text [start, end] */
|
||||
position: [number, number]
|
||||
|
||||
/** Match type: 'text' (exact word match) or 'semantic' (concept match) */
|
||||
matchType: 'text' | 'semantic'
|
||||
}
|
||||
|
||||
// ============= Export all types =============
|
||||
|
||||
export * from './graphTypes.js' // Re-export NounType, VerbType, etc.
|
||||
Loading…
Add table
Add a link
Reference in a new issue