diff --git a/README.md b/README.md index 8033c522..3ecf9b98 100644 --- a/README.md +++ b/README.md @@ -731,6 +731,25 @@ await threadedDb.init() // Directly embed text to vectors const vector = await db.embed("Some text to convert to a vector") + +// Calculate similarity between two texts or vectors +const similarity = await db.calculateSimilarity( + "Cats are furry pets", + "Felines make good companions" +) +console.log(`Similarity score: ${similarity}`) // Higher value means more similar + +// Calculate similarity with custom options +const vectorA = await db.embed("First text") +const vectorB = await db.embed("Second text") +const customSimilarity = await db.calculateSimilarity( + vectorA, // Can use pre-computed vectors + vectorB, + { + forceEmbed: false, // Skip embedding if inputs are already vectors + distanceFunction: cosineDistance // Optional custom distance function + } +) ``` The threaded embedding function runs in a separate thread (Web Worker in browsers, Worker Thread in Node.js) to improve diff --git a/cli-package/types.d.ts b/cli-package/types.d.ts index 74e7790c..725938be 100644 --- a/cli-package/types.d.ts +++ b/cli-package/types.d.ts @@ -15,6 +15,14 @@ declare module '@soulcraft/brainy' { search(query: string, limit?: number, options?: any): Promise searchText(query: string, limit?: number, options?: any): Promise + + embed(data: string | string[]): Promise + + calculateSimilarity( + a: number[] | string | string[], + b: number[] | string | string[], + options?: { forceEmbed?: boolean, distanceFunction?: any } + ): Promise addVerb( sourceId: string, diff --git a/tests/vector-operations.test.ts b/tests/vector-operations.test.ts index 396d6f4f..acc2698d 100644 --- a/tests/vector-operations.test.ts +++ b/tests/vector-operations.test.ts @@ -88,4 +88,54 @@ describe('Vector Operations', () => { // The closest should be the exact match expect(results[0].metadata.id).toBe('vec1') }) + + it('should calculate similarity between vectors correctly', async () => { + const brainy = await import('../dist/unified.js') + + const db = new brainy.BrainyData({ + distanceFunction: euclideanDistance + }) + + await db.init() + + // Create test vectors + const vectorA = createTestVector(0) + const vectorB = createTestVector(0) // Identical to vectorA + const vectorC = createTestVector(1) // Different from vectorA + + // Calculate similarity between identical vectors + const similarityIdentical = await db.calculateSimilarity(vectorA, vectorB) + + // Calculate similarity between different vectors + const similarityDifferent = await db.calculateSimilarity(vectorA, vectorC) + + // Identical vectors should have similarity close to 1 + expect(similarityIdentical).toBeCloseTo(1, 1) + + // Different vectors should have lower similarity + expect(similarityDifferent).toBeLessThan(similarityIdentical) + }) + + it('should calculate similarity between text inputs correctly', async () => { + const brainy = await import('../dist/unified.js') + + const db = new brainy.BrainyData() + + await db.init() + + // Calculate similarity between similar texts + const similarityHigh = await db.calculateSimilarity( + "Cats are furry pets", + "Felines make good companions" + ) + + // Calculate similarity between different texts + const similarityLow = await db.calculateSimilarity( + "Cats are furry pets", + "Python is a programming language" + ) + + // Similar texts should have higher similarity than different texts + expect(similarityHigh).toBeGreaterThan(similarityLow) + }) })