mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-11 16:58:28 +00:00
122 lines
3.3 KiB
TypeScript
122 lines
3.3 KiB
TypeScript
import type { EntityNode } from "@core/types";
|
|
import { runQuery } from "~/lib/neo4j.server";
|
|
|
|
export async function saveEntity(entity: EntityNode): Promise<string> {
|
|
const query = `
|
|
MERGE (n:Entity {uuid: $uuid})
|
|
ON CREATE SET
|
|
n.name = $name,
|
|
n.type = $type,
|
|
n.attributes = $attributes,
|
|
n.nameEmbedding = $nameEmbedding,
|
|
n.createdAt = $createdAt,
|
|
n.userId = $userId,
|
|
n.space = $space
|
|
ON MATCH SET
|
|
n.name = $name,
|
|
n.type = $type,
|
|
n.attributes = $attributes,
|
|
n.nameEmbedding = $nameEmbedding,
|
|
n.space = $space
|
|
RETURN n.uuid as uuid
|
|
`;
|
|
|
|
const params = {
|
|
uuid: entity.uuid,
|
|
name: entity.name,
|
|
type: entity.type,
|
|
attributes: JSON.stringify(entity.attributes || {}),
|
|
nameEmbedding: entity.nameEmbedding,
|
|
createdAt: entity.createdAt.toISOString(),
|
|
userId: entity.userId,
|
|
space: entity.space || null,
|
|
};
|
|
|
|
const result = await runQuery(query, params);
|
|
return result[0].get("uuid");
|
|
}
|
|
|
|
export async function getEntity(uuid: string): Promise<EntityNode | null> {
|
|
const query = `
|
|
MATCH (entity:Entity {uuid: $uuid})
|
|
RETURN entity
|
|
`;
|
|
|
|
const result = await runQuery(query, { uuid });
|
|
if (result.length === 0) return null;
|
|
|
|
const entity = result[0].get("entity").properties;
|
|
return {
|
|
uuid: entity.uuid,
|
|
name: entity.name,
|
|
type: entity.type,
|
|
attributes: JSON.parse(entity.attributes || "{}"),
|
|
nameEmbedding: entity.nameEmbedding,
|
|
createdAt: new Date(entity.createdAt),
|
|
userId: entity.userId,
|
|
space: entity.space,
|
|
};
|
|
}
|
|
|
|
// Find semantically similar entities
|
|
export async function findSimilarEntities(params: {
|
|
queryEmbedding: number[];
|
|
limit: number;
|
|
threshold: number;
|
|
}): Promise<EntityNode[]> {
|
|
const query = `
|
|
MATCH (entity:Entity)
|
|
WHERE entity.nameEmbedding IS NOT NULL
|
|
WITH entity, vector.similarity.cosine($queryEmbedding, entity.nameEmbedding) AS score
|
|
WHERE score >= $threshold
|
|
RETURN entity, score
|
|
ORDER BY score DESC
|
|
`;
|
|
|
|
const result = await runQuery(query, params);
|
|
return result.map((record) => {
|
|
const entity = record.get("entity").properties;
|
|
|
|
return {
|
|
uuid: entity.uuid,
|
|
name: entity.name,
|
|
type: entity.type,
|
|
attributes: JSON.parse(entity.attributes || "{}"),
|
|
nameEmbedding: entity.nameEmbedding,
|
|
createdAt: new Date(entity.createdAt),
|
|
userId: entity.userId,
|
|
space: entity.space,
|
|
};
|
|
});
|
|
}
|
|
|
|
// Find exact predicate matches by name
|
|
export async function findExactPredicateMatches(params: {
|
|
predicateName: string;
|
|
userId: string;
|
|
}): Promise<EntityNode[]> {
|
|
const query = `
|
|
MATCH (entity:Entity)
|
|
WHERE entity.type = 'Predicate'
|
|
AND toLower(entity.name) = toLower($predicateName)
|
|
AND entity.userId = $userId
|
|
RETURN entity
|
|
`;
|
|
|
|
const result = await runQuery(query, params);
|
|
return result.map((record) => {
|
|
const entity = record.get("entity").properties;
|
|
|
|
return {
|
|
uuid: entity.uuid,
|
|
name: entity.name,
|
|
type: entity.type,
|
|
attributes: JSON.parse(entity.attributes || "{}"),
|
|
nameEmbedding: entity.nameEmbedding,
|
|
createdAt: new Date(entity.createdAt),
|
|
userId: entity.userId,
|
|
space: entity.space,
|
|
};
|
|
});
|
|
}
|