@api({ httpMethod: 'POST' })
async searchDocs(query: string, limit: number = 5) {
const embedding = await Embedding.embedOne(query, 'voyage', 'query');
// ์ฒญํฌ ๊ฒ์
const chunks = await this.getPuri().raw(`
SELECT
c.id, c.parent_id, c.content, c.chunk_index,
d.title,
1 - (c.embedding <=> ?) AS similarity
FROM document_chunks c
JOIN documents d ON c.parent_id = d.id
WHERE c.embedding IS NOT NULL
ORDER BY c.embedding <=> ?
LIMIT ?
`, [
JSON.stringify(embedding.embedding),
JSON.stringify(embedding.embedding),
limit * 2,
]);
// ๋ถ๋ชจ ๋ฌธ์๋ณ ๊ทธ๋ฃนํ
const grouped = new Map();
for (const chunk of chunks.rows) {
const parentId = chunk.parent_id;
if (!grouped.has(parentId)) {
grouped.set(parentId, {
parentId,
title: chunk.title,
bestSimilarity: chunk.similarity,
relevantChunks: [],
});
}
grouped.get(parentId).relevantChunks.push({
content: chunk.content,
chunkIndex: chunk.chunk_index,
similarity: chunk.similarity,
});
}
return Array.from(grouped.values())
.sort((a, b) => b.bestSimilarity - a.bestSimilarity)
.slice(0, limit);
}