feat: add semantic fact search and embeddings
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { createHash, randomUUID } from 'node:crypto';
|
||||
|
||||
import type { Fact, FactTopic, Topic } from '../types/api';
|
||||
import type { FactRecord, TopicRecord } from '../types/domain';
|
||||
@@ -35,6 +35,42 @@ export function deserializeMetadata(metadata: string | null): unknown | null {
|
||||
return JSON.parse(metadata);
|
||||
}
|
||||
|
||||
export function serializeEmbedding(embedding: number[]): string {
|
||||
return JSON.stringify(embedding);
|
||||
}
|
||||
|
||||
export function deserializeEmbedding(embedding: string): number[] {
|
||||
return JSON.parse(embedding) as number[];
|
||||
}
|
||||
|
||||
export function createContentHash(input: string): string {
|
||||
return createHash('sha256').update(input).digest('hex');
|
||||
}
|
||||
|
||||
export function cosineSimilarity(left: number[], right: number[]): number {
|
||||
if (left.length === 0 || left.length !== right.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let dot = 0;
|
||||
let leftMagnitude = 0;
|
||||
let rightMagnitude = 0;
|
||||
|
||||
for (let index = 0; index < left.length; index += 1) {
|
||||
const leftValue = left[index] ?? 0;
|
||||
const rightValue = right[index] ?? 0;
|
||||
dot += leftValue * rightValue;
|
||||
leftMagnitude += leftValue * leftValue;
|
||||
rightMagnitude += rightValue * rightValue;
|
||||
}
|
||||
|
||||
if (leftMagnitude === 0 || rightMagnitude === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dot / (Math.sqrt(leftMagnitude) * Math.sqrt(rightMagnitude));
|
||||
}
|
||||
|
||||
export function mapTopicRow(record: TopicRecord): Topic {
|
||||
return {
|
||||
id: record.id,
|
||||
|
||||
Reference in New Issue
Block a user