sonamu 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/config.d.ts +1 -4
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +1 -1
- package/dist/api/sonamu.d.ts +2 -0
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +19 -47
- package/dist/bin/cli.js +6 -6
- package/dist/database/base-model.d.ts +1 -1
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +15 -4
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +3 -3
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +1 -1
- package/dist/database/puri-wrapper.d.ts +11 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +7 -11
- package/dist/database/puri.d.ts +36 -17
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +54 -7
- package/dist/database/puri.types.d.ts +54 -17
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +2 -4
- package/dist/database/puri.types.test-d.js +129 -0
- package/dist/database/upsert-builder.d.ts +16 -10
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +10 -19
- package/dist/entity/entity-manager.d.ts +113 -22
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +1 -1
- package/dist/entity/entity.d.ts +34 -0
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +110 -37
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +341 -149
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +21 -5
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +7 -1
- package/dist/migration/postgresql-schema-reader.d.ts +11 -1
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +111 -10
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +5 -4
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +12 -2
- package/dist/template/implementations/generated_sso.template.d.ts +3 -3
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +50 -2
- package/dist/template/implementations/model.template.js +6 -6
- package/dist/template/implementations/model_test.template.js +4 -4
- package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
- package/dist/template/implementations/view_enums_select.template.js +2 -2
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +12 -9
- package/dist/template/implementations/view_id_async_select.template.js +4 -4
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +12 -9
- package/dist/template/implementations/view_search_input.template.js +2 -2
- package/dist/template/template.js +2 -2
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +17 -2
- package/dist/testing/fixture-manager.d.ts +2 -1
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +29 -29
- package/dist/types/types.d.ts +593 -68
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +113 -9
- package/dist/vector/chunking.d.ts +25 -0
- package/dist/vector/chunking.d.ts.map +1 -0
- package/dist/vector/chunking.js +97 -0
- package/dist/vector/config.d.ts +12 -0
- package/dist/vector/config.d.ts.map +1 -0
- package/dist/vector/config.js +83 -0
- package/dist/vector/embedding.d.ts +42 -0
- package/dist/vector/embedding.d.ts.map +1 -0
- package/dist/vector/embedding.js +147 -0
- package/dist/vector/types.d.ts +105 -0
- package/dist/vector/types.d.ts.map +1 -0
- package/dist/vector/types.js +5 -0
- package/dist/vector/vector-search.d.ts +47 -0
- package/dist/vector/vector-search.d.ts.map +1 -0
- package/dist/vector/vector-search.js +176 -0
- package/package.json +11 -11
- package/src/api/config.ts +0 -4
- package/src/api/sonamu.ts +21 -36
- package/src/bin/cli.ts +5 -5
- package/src/database/base-model.ts +20 -11
- package/src/database/code-generator.ts +6 -2
- package/src/database/db.ts +1 -0
- package/src/database/puri-wrapper.ts +22 -16
- package/src/database/puri.ts +150 -27
- package/src/database/puri.types.test-d.ts +457 -0
- package/src/database/puri.types.ts +231 -33
- package/src/database/upsert-builder.ts +43 -34
- package/src/entity/entity-manager.ts +2 -2
- package/src/entity/entity.ts +134 -44
- package/src/index.ts +6 -0
- package/src/migration/code-generation.ts +377 -174
- package/src/migration/migration-set.ts +22 -3
- package/src/migration/migrator.ts +6 -0
- package/src/migration/postgresql-schema-reader.ts +121 -21
- package/src/syncer/syncer.ts +4 -3
- package/src/template/implementations/generated.template.ts +51 -9
- package/src/template/implementations/generated_sso.template.ts +71 -2
- package/src/template/implementations/model.template.ts +5 -5
- package/src/template/implementations/model_test.template.ts +3 -3
- package/src/template/implementations/view_enums_dropdown.template.ts +1 -1
- package/src/template/implementations/view_enums_select.template.ts +1 -1
- package/src/template/implementations/view_form.template.ts +11 -8
- package/src/template/implementations/view_id_async_select.template.ts +3 -3
- package/src/template/implementations/view_list.template.ts +11 -8
- package/src/template/implementations/view_search_input.template.ts +1 -1
- package/src/template/template.ts +1 -1
- package/src/template/zod-converter.ts +20 -0
- package/src/testing/fixture-manager.ts +31 -30
- package/src/types/types.ts +226 -48
- package/src/vector/chunking.ts +115 -0
- package/src/vector/config.ts +68 -0
- package/src/vector/embedding.ts +193 -0
- package/src/vector/types.ts +122 -0
- package/src/vector/vector-search.ts +261 -0
- package/dist/template/implementations/view_enums_buttonset.template.d.ts +0 -17
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +0 -1
- package/dist/template/implementations/view_enums_buttonset.template.js +0 -31
- package/dist/template/implementations/view_list_columns.template.d.ts +0 -17
- package/dist/template/implementations/view_list_columns.template.d.ts.map +0 -1
- package/dist/template/implementations/view_list_columns.template.js +0 -49
- package/src/template/implementations/view_enums_buttonset.template.ts +0 -34
- package/src/template/implementations/view_list_columns.template.ts +0 -53
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { DEFAULT_VECTOR_CONFIG } from "./config.js";
|
|
2
|
+
/**
|
|
3
|
+
* 텍스트 청킹
|
|
4
|
+
* - 현재 가이드에서는 400토큰 이하만 저장하므로 기본적으로 사용하지 않음
|
|
5
|
+
* - 추후 긴 문서 처리 시 사용
|
|
6
|
+
*/ export class Chunking {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config = {}){
|
|
9
|
+
this.config = {
|
|
10
|
+
...DEFAULT_VECTOR_CONFIG.chunking,
|
|
11
|
+
...config
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 텍스트를 청크로 분할
|
|
16
|
+
*/ chunk(text) {
|
|
17
|
+
if (text.length < this.config.skipThreshold) {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
index: 0,
|
|
21
|
+
text: text.trim(),
|
|
22
|
+
startOffset: 0,
|
|
23
|
+
endOffset: text.length
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
const chunks = [];
|
|
28
|
+
let currentPosition = 0;
|
|
29
|
+
while(currentPosition < text.length){
|
|
30
|
+
const remainingText = text.slice(currentPosition);
|
|
31
|
+
const { chunk, length } = this.extractChunk(remainingText);
|
|
32
|
+
if (chunk.trim().length >= this.config.minChunkSize) {
|
|
33
|
+
chunks.push({
|
|
34
|
+
index: chunks.length,
|
|
35
|
+
text: chunk.trim(),
|
|
36
|
+
startOffset: currentPosition,
|
|
37
|
+
endOffset: currentPosition + length
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const advance = Math.max(length - this.config.chunkOverlap, this.config.minChunkSize);
|
|
41
|
+
currentPosition += advance;
|
|
42
|
+
}
|
|
43
|
+
return chunks;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 청킹이 필요한지 확인
|
|
47
|
+
*/ needsChunking(text) {
|
|
48
|
+
return text.length > this.config.chunkSize;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 예상 청크 수 계산
|
|
52
|
+
*/ estimateChunkCount(text) {
|
|
53
|
+
if (text.length <= this.config.chunkSize) {
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
const effectiveChunkSize = this.config.chunkSize - this.config.chunkOverlap;
|
|
57
|
+
return Math.ceil(text.length / effectiveChunkSize);
|
|
58
|
+
}
|
|
59
|
+
extractChunk(text) {
|
|
60
|
+
if (text.length <= this.config.chunkSize) {
|
|
61
|
+
return {
|
|
62
|
+
chunk: text,
|
|
63
|
+
length: text.length
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
for (const separator of this.config.separators){
|
|
67
|
+
const result = this.splitBySeparator(text, separator);
|
|
68
|
+
if (result) return result;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
chunk: text.slice(0, this.config.chunkSize),
|
|
72
|
+
length: this.config.chunkSize
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
splitBySeparator(text, separator) {
|
|
76
|
+
const searchRange = text.slice(0, this.config.chunkSize + 100);
|
|
77
|
+
let lastIndex = -1;
|
|
78
|
+
let index = 0;
|
|
79
|
+
while(true){
|
|
80
|
+
index = searchRange.indexOf(separator, index);
|
|
81
|
+
if (index === -1) break;
|
|
82
|
+
if (index <= this.config.chunkSize) {
|
|
83
|
+
lastIndex = index + separator.length;
|
|
84
|
+
}
|
|
85
|
+
index++;
|
|
86
|
+
}
|
|
87
|
+
if (lastIndex > this.config.minChunkSize) {
|
|
88
|
+
return {
|
|
89
|
+
chunk: text.slice(0, lastIndex),
|
|
90
|
+
length: lastIndex
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZWN0b3IvY2h1bmtpbmcudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgREVGQVVMVF9WRUNUT1JfQ09ORklHIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IENodW5rLCBDaHVua2luZ0NvbmZpZyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICog7YWN7Iqk7Yq4IOyyre2CuVxuICogLSDtmITsnqwg6rCA7J2065Oc7JeQ7ISc64qUIDQwMO2GoO2BsCDsnbTtlZjrp4wg7KCA7J6l7ZWY66+A66GcIOq4sOuzuOyggeycvOuhnCDsgqzsmqntlZjsp4Ag7JWK7J2MXG4gKiAtIOy2lO2bhCDquLQg66y47IScIOyymOumrCDsi5wg7IKs7JqpXG4gKi9cbmV4cG9ydCBjbGFzcyBDaHVua2luZyB7XG4gIHByaXZhdGUgY29uZmlnOiBDaHVua2luZ0NvbmZpZztcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFBhcnRpYWw8Q2h1bmtpbmdDb25maWc+ID0ge30pIHtcbiAgICB0aGlzLmNvbmZpZyA9IHsgLi4uREVGQVVMVF9WRUNUT1JfQ09ORklHLmNodW5raW5nLCAuLi5jb25maWcgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiDthY3siqTtirjrpbwg7LKt7YGs66GcIOu2hO2VoFxuICAgKi9cbiAgY2h1bmsodGV4dDogc3RyaW5nKTogQ2h1bmtbXSB7XG4gICAgaWYgKHRleHQubGVuZ3RoIDwgdGhpcy5jb25maWcuc2tpcFRocmVzaG9sZCkge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAge1xuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgIHRleHQ6IHRleHQudHJpbSgpLFxuICAgICAgICAgIHN0YXJ0T2Zmc2V0OiAwLFxuICAgICAgICAgIGVuZE9mZnNldDogdGV4dC5sZW5ndGgsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgIH1cblxuICAgIGNvbnN0IGNodW5rczogQ2h1bmtbXSA9IFtdO1xuICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSAwO1xuXG4gICAgd2hpbGUgKGN1cnJlbnRQb3NpdGlvbiA8IHRleHQubGVuZ3RoKSB7XG4gICAgICBjb25zdCByZW1haW5pbmdUZXh0ID0gdGV4dC5zbGljZShjdXJyZW50UG9zaXRpb24pO1xuICAgICAgY29uc3QgeyBjaHVuaywgbGVuZ3RoIH0gPSB0aGlzLmV4dHJhY3RDaHVuayhyZW1haW5pbmdUZXh0KTtcblxuICAgICAgaWYgKGNodW5rLnRyaW0oKS5sZW5ndGggPj0gdGhpcy5jb25maWcubWluQ2h1bmtTaXplKSB7XG4gICAgICAgIGNodW5rcy5wdXNoKHtcbiAgICAgICAgICBpbmRleDogY2h1bmtzLmxlbmd0aCxcbiAgICAgICAgICB0ZXh0OiBjaHVuay50cmltKCksXG4gICAgICAgICAgc3RhcnRPZmZzZXQ6IGN1cnJlbnRQb3NpdGlvbixcbiAgICAgICAgICBlbmRPZmZzZXQ6IGN1cnJlbnRQb3NpdGlvbiArIGxlbmd0aCxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFkdmFuY2UgPSBNYXRoLm1heChsZW5ndGggLSB0aGlzLmNvbmZpZy5jaHVua092ZXJsYXAsIHRoaXMuY29uZmlnLm1pbkNodW5rU2l6ZSk7XG4gICAgICBjdXJyZW50UG9zaXRpb24gKz0gYWR2YW5jZTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2h1bmtzO1xuICB9XG5cbiAgLyoqXG4gICAqIOyyre2CueydtCDtlYTsmpTtlZzsp4Ag7ZmV7J24XG4gICAqL1xuICBuZWVkc0NodW5raW5nKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0ZXh0Lmxlbmd0aCA+IHRoaXMuY29uZmlnLmNodW5rU2l6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiDsmIjsg4Eg7LKt7YGsIOyImCDqs4TsgrBcbiAgICovXG4gIGVzdGltYXRlQ2h1bmtDb3VudCh0ZXh0OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGlmICh0ZXh0Lmxlbmd0aCA8PSB0aGlzLmNvbmZpZy5jaHVua1NpemUpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICBjb25zdCBlZmZlY3RpdmVDaHVua1NpemUgPSB0aGlzLmNvbmZpZy5jaHVua1NpemUgLSB0aGlzLmNvbmZpZy5jaHVua092ZXJsYXA7XG4gICAgcmV0dXJuIE1hdGguY2VpbCh0ZXh0Lmxlbmd0aCAvIGVmZmVjdGl2ZUNodW5rU2l6ZSk7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RDaHVuayh0ZXh0OiBzdHJpbmcpOiB7IGNodW5rOiBzdHJpbmc7IGxlbmd0aDogbnVtYmVyIH0ge1xuICAgIGlmICh0ZXh0Lmxlbmd0aCA8PSB0aGlzLmNvbmZpZy5jaHVua1NpemUpIHtcbiAgICAgIHJldHVybiB7IGNodW5rOiB0ZXh0LCBsZW5ndGg6IHRleHQubGVuZ3RoIH07XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzZXBhcmF0b3Igb2YgdGhpcy5jb25maWcuc2VwYXJhdG9ycykge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5zcGxpdEJ5U2VwYXJhdG9yKHRleHQsIHNlcGFyYXRvcik7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaHVuazogdGV4dC5zbGljZSgwLCB0aGlzLmNvbmZpZy5jaHVua1NpemUpLFxuICAgICAgbGVuZ3RoOiB0aGlzLmNvbmZpZy5jaHVua1NpemUsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc3BsaXRCeVNlcGFyYXRvcihcbiAgICB0ZXh0OiBzdHJpbmcsXG4gICAgc2VwYXJhdG9yOiBzdHJpbmcsXG4gICk6IHsgY2h1bms6IHN0cmluZzsgbGVuZ3RoOiBudW1iZXIgfSB8IG51bGwge1xuICAgIGNvbnN0IHNlYXJjaFJhbmdlID0gdGV4dC5zbGljZSgwLCB0aGlzLmNvbmZpZy5jaHVua1NpemUgKyAxMDApO1xuXG4gICAgbGV0IGxhc3RJbmRleCA9IC0xO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgaW5kZXggPSBzZWFyY2hSYW5nZS5pbmRleE9mKHNlcGFyYXRvciwgaW5kZXgpO1xuICAgICAgaWYgKGluZGV4ID09PSAtMSkgYnJlYWs7XG4gICAgICBpZiAoaW5kZXggPD0gdGhpcy5jb25maWcuY2h1bmtTaXplKSB7XG4gICAgICAgIGxhc3RJbmRleCA9IGluZGV4ICsgc2VwYXJhdG9yLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGluZGV4Kys7XG4gICAgfVxuXG4gICAgaWYgKGxhc3RJbmRleCA+IHRoaXMuY29uZmlnLm1pbkNodW5rU2l6ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2h1bms6IHRleHQuc2xpY2UoMCwgbGFzdEluZGV4KSxcbiAgICAgICAgbGVuZ3RoOiBsYXN0SW5kZXgsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iXSwibmFtZXMiOlsiREVGQVVMVF9WRUNUT1JfQ09ORklHIiwiQ2h1bmtpbmciLCJjb25maWciLCJjaHVua2luZyIsImNodW5rIiwidGV4dCIsImxlbmd0aCIsInNraXBUaHJlc2hvbGQiLCJpbmRleCIsInRyaW0iLCJzdGFydE9mZnNldCIsImVuZE9mZnNldCIsImNodW5rcyIsImN1cnJlbnRQb3NpdGlvbiIsInJlbWFpbmluZ1RleHQiLCJzbGljZSIsImV4dHJhY3RDaHVuayIsIm1pbkNodW5rU2l6ZSIsInB1c2giLCJhZHZhbmNlIiwiTWF0aCIsIm1heCIsImNodW5rT3ZlcmxhcCIsIm5lZWRzQ2h1bmtpbmciLCJjaHVua1NpemUiLCJlc3RpbWF0ZUNodW5rQ291bnQiLCJlZmZlY3RpdmVDaHVua1NpemUiLCJjZWlsIiwic2VwYXJhdG9yIiwic2VwYXJhdG9ycyIsInJlc3VsdCIsInNwbGl0QnlTZXBhcmF0b3IiLCJzZWFyY2hSYW5nZSIsImxhc3RJbmRleCIsImluZGV4T2YiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLHFCQUFxQixRQUFRLGNBQVc7QUFHakQ7Ozs7Q0FJQyxHQUNE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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { VectorConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 벡터 검색 기본 설정
|
|
4
|
+
* 사용자는 이 설정을 override하여 커스터마이즈할 수 있음
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_VECTOR_CONFIG: VectorConfig;
|
|
7
|
+
/**
|
|
8
|
+
* 설정 생성 헬퍼 함수
|
|
9
|
+
* 부분 설정만 제공하면 나머지는 기본값 사용
|
|
10
|
+
*/
|
|
11
|
+
export declare function createVectorConfig(overrides?: Partial<VectorConfig>): VectorConfig;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/vector/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,YA6CnC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GACpC,YAAY,CAQd"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 벡터 검색 기본 설정
|
|
3
|
+
* 사용자는 이 설정을 override하여 커스터마이즈할 수 있음
|
|
4
|
+
*/ export const DEFAULT_VECTOR_CONFIG = {
|
|
5
|
+
// Voyage AI 설정
|
|
6
|
+
// apiKey는 Sonamu.secrets에서 로드되므로 여기서는 빈 문자열
|
|
7
|
+
voyage: {
|
|
8
|
+
apiKey: "",
|
|
9
|
+
baseUrl: "https://api.voyageai.com/v1/embeddings",
|
|
10
|
+
model: "voyage-3",
|
|
11
|
+
dimensions: 1024,
|
|
12
|
+
maxTokens: 32000,
|
|
13
|
+
batchSize: 100
|
|
14
|
+
},
|
|
15
|
+
// OpenAI 설정
|
|
16
|
+
// apiKey는 Sonamu.secrets에서 로드되므로 여기서는 빈 문자열
|
|
17
|
+
openai: {
|
|
18
|
+
apiKey: "",
|
|
19
|
+
baseUrl: "https://api.openai.com/v1/embeddings",
|
|
20
|
+
model: "text-embedding-3-small",
|
|
21
|
+
dimensions: 1536,
|
|
22
|
+
maxTokens: 8191,
|
|
23
|
+
batchSize: 100
|
|
24
|
+
},
|
|
25
|
+
// 청킹 설정 (필요시 사용)
|
|
26
|
+
chunking: {
|
|
27
|
+
chunkSize: 500,
|
|
28
|
+
chunkOverlap: 50,
|
|
29
|
+
minChunkSize: 50,
|
|
30
|
+
skipThreshold: 200,
|
|
31
|
+
separators: [
|
|
32
|
+
"\n\n",
|
|
33
|
+
"\n",
|
|
34
|
+
"。",
|
|
35
|
+
". ",
|
|
36
|
+
"! ",
|
|
37
|
+
"? ",
|
|
38
|
+
", ",
|
|
39
|
+
" "
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
// 검색 설정
|
|
43
|
+
search: {
|
|
44
|
+
defaultLimit: 10,
|
|
45
|
+
similarityThreshold: 0.5,
|
|
46
|
+
vectorWeight: 0.7,
|
|
47
|
+
ftsWeight: 0.3
|
|
48
|
+
},
|
|
49
|
+
// pgvector 설정
|
|
50
|
+
pgvector: {
|
|
51
|
+
iterativeScan: true,
|
|
52
|
+
efSearch: 100
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* 설정 생성 헬퍼 함수
|
|
57
|
+
* 부분 설정만 제공하면 나머지는 기본값 사용
|
|
58
|
+
*/ export function createVectorConfig(overrides = {}) {
|
|
59
|
+
return {
|
|
60
|
+
voyage: {
|
|
61
|
+
...DEFAULT_VECTOR_CONFIG.voyage,
|
|
62
|
+
...overrides.voyage
|
|
63
|
+
},
|
|
64
|
+
openai: {
|
|
65
|
+
...DEFAULT_VECTOR_CONFIG.openai,
|
|
66
|
+
...overrides.openai
|
|
67
|
+
},
|
|
68
|
+
chunking: {
|
|
69
|
+
...DEFAULT_VECTOR_CONFIG.chunking,
|
|
70
|
+
...overrides.chunking
|
|
71
|
+
},
|
|
72
|
+
search: {
|
|
73
|
+
...DEFAULT_VECTOR_CONFIG.search,
|
|
74
|
+
...overrides.search
|
|
75
|
+
},
|
|
76
|
+
pgvector: {
|
|
77
|
+
...DEFAULT_VECTOR_CONFIG.pgvector,
|
|
78
|
+
...overrides.pgvector
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZWN0b3IvY29uZmlnLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgVmVjdG9yQ29uZmlnIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiDrsqHthLAg6rKA7IOJIOq4sOuzuCDshKTsoJVcbiAqIOyCrOyaqeyekOuKlCDsnbQg7ISk7KCV7J2EIG92ZXJyaWRl7ZWY7JesIOy7pOyKpO2EsOuniOydtOymiO2VoCDsiJgg7J6I7J2MXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX1ZFQ1RPUl9DT05GSUc6IFZlY3RvckNvbmZpZyA9IHtcbiAgLy8gVm95YWdlIEFJIOyEpOyglVxuICAvLyBhcGlLZXnripQgU29uYW11LnNlY3JldHPsl5DshJwg66Gc65Oc65CY66+A66GcIOyXrOq4sOyEnOuKlCDruYgg66y47J6Q7Je0XG4gIHZveWFnZToge1xuICAgIGFwaUtleTogXCJcIixcbiAgICBiYXNlVXJsOiBcImh0dHBzOi8vYXBpLnZveWFnZWFpLmNvbS92MS9lbWJlZGRpbmdzXCIsXG4gICAgbW9kZWw6IFwidm95YWdlLTNcIixcbiAgICBkaW1lbnNpb25zOiAxMDI0LFxuICAgIG1heFRva2VuczogMzIwMDAsXG4gICAgYmF0Y2hTaXplOiAxMDAsXG4gIH0sXG5cbiAgLy8gT3BlbkFJIOyEpOyglVxuICAvLyBhcGlLZXnripQgU29uYW11LnNlY3JldHPsl5DshJwg66Gc65Oc65CY66+A66GcIOyXrOq4sOyEnOuKlCDruYgg66y47J6Q7Je0XG4gIG9wZW5haToge1xuICAgIGFwaUtleTogXCJcIixcbiAgICBiYXNlVXJsOiBcImh0dHBzOi8vYXBpLm9wZW5haS5jb20vdjEvZW1iZWRkaW5nc1wiLFxuICAgIG1vZGVsOiBcInRleHQtZW1iZWRkaW5nLTMtc21hbGxcIixcbiAgICBkaW1lbnNpb25zOiAxNTM2LFxuICAgIG1heFRva2VuczogODE5MSxcbiAgICBiYXRjaFNpemU6IDEwMCxcbiAgfSxcblxuICAvLyDssq3tgrkg7ISk7KCVICjtlYTsmpTsi5wg7IKs7JqpKVxuICBjaHVua2luZzoge1xuICAgIGNodW5rU2l6ZTogNTAwLFxuICAgIGNodW5rT3ZlcmxhcDogNTAsXG4gICAgbWluQ2h1bmtTaXplOiA1MCxcbiAgICBza2lwVGhyZXNob2xkOiAyMDAsXG4gICAgc2VwYXJhdG9yczogW1wiXFxuXFxuXCIsIFwiXFxuXCIsIFwi44CCXCIsIFwiLiBcIiwgXCIhIFwiLCBcIj8gXCIsIFwiLCBcIiwgXCIgXCJdLFxuICB9LFxuXG4gIC8vIOqygOyDiSDshKTsoJVcbiAgc2VhcmNoOiB7XG4gICAgZGVmYXVsdExpbWl0OiAxMCxcbiAgICBzaW1pbGFyaXR5VGhyZXNob2xkOiAwLjUsXG4gICAgdmVjdG9yV2VpZ2h0OiAwLjcsXG4gICAgZnRzV2VpZ2h0OiAwLjMsXG4gIH0sXG5cbiAgLy8gcGd2ZWN0b3Ig7ISk7KCVXG4gIHBndmVjdG9yOiB7XG4gICAgaXRlcmF0aXZlU2NhbjogdHJ1ZSxcbiAgICBlZlNlYXJjaDogMTAwLFxuICB9LFxufTtcblxuLyoqXG4gKiDshKTsoJUg7IOd7ISxIO2XrO2NvCDtlajsiJhcbiAqIOu2gOu2hCDshKTsoJXrp4wg7KCc6rO17ZWY66m0IOuCmOuouOyngOuKlCDquLDrs7jqsJIg7IKs7JqpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVWZWN0b3JDb25maWcoXG4gIG92ZXJyaWRlczogUGFydGlhbDxWZWN0b3JDb25maWc+ID0ge31cbik6IFZlY3RvckNvbmZpZyB7XG4gIHJldHVybiB7XG4gICAgdm95YWdlOiB7IC4uLkRFRkFVTFRfVkVDVE9SX0NPTkZJRy52b3lhZ2UsIC4uLm92ZXJyaWRlcy52b3lhZ2UgfSxcbiAgICBvcGVuYWk6IHsgLi4uREVGQVVMVF9WRUNUT1JfQ09ORklHLm9wZW5haSwgLi4ub3ZlcnJpZGVzLm9wZW5haSB9LFxuICAgIGNodW5raW5nOiB7IC4uLkRFRkFVTFRfVkVDVE9SX0NPTkZJRy5jaHVua2luZywgLi4ub3ZlcnJpZGVzLmNodW5raW5nIH0sXG4gICAgc2VhcmNoOiB7IC4uLkRFRkFVTFRfVkVDVE9SX0NPTkZJRy5zZWFyY2gsIC4uLm92ZXJyaWRlcy5zZWFyY2ggfSxcbiAgICBwZ3ZlY3RvcjogeyAuLi5ERUZBVUxUX1ZFQ1RPUl9DT05GSUcucGd2ZWN0b3IsIC4uLm92ZXJyaWRlcy5wZ3ZlY3RvciB9LFxuICB9O1xufVxuIl0sIm5hbWVzIjpbIkRFRkFVTFRfVkVDVE9SX0NPTkZJRyIsInZveWFnZSIsImFwaUtleSIsImJhc2VVcmwiLCJtb2RlbCIsImRpbWVuc2lvbnMiLCJtYXhUb2tlbnMiLCJiYXRjaFNpemUiLCJvcGVuYWkiLCJjaHVua2luZyIsImNodW5rU2l6ZSIsImNodW5rT3ZlcmxhcCIsIm1pbkNodW5rU2l6ZSIsInNraXBUaHJlc2hvbGQiLCJzZXBhcmF0b3JzIiwic2VhcmNoIiwiZGVmYXVsdExpbWl0Iiwic2ltaWxhcml0eVRocmVzaG9sZCIsInZlY3RvcldlaWdodCIsImZ0c1dlaWdodCIsInBndmVjdG9yIiwiaXRlcmF0aXZlU2NhbiIsImVmU2VhcmNoIiwiY3JlYXRlVmVjdG9yQ29uZmlnIiwib3ZlcnJpZGVzIl0sIm1hcHBpbmdzIjoiQUFFQTs7O0NBR0MsR0FDRCxPQUFPLE1BQU1BLHdCQUFzQztJQUNqRCxlQUFlO0lBQ2YsNENBQTRDO0lBQzVDQyxRQUFRO1FBQ05DLFFBQVE7UUFDUkMsU0FBUztRQUNUQyxPQUFPO1FBQ1BDLFlBQVk7UUFDWkMsV0FBVztRQUNYQyxXQUFXO0lBQ2I7SUFFQSxZQUFZO0lBQ1osNENBQTRDO0lBQzVDQyxRQUFRO1FBQ05OLFFBQVE7UUFDUkMsU0FBUztRQUNUQyxPQUFPO1FBQ1BDLFlBQVk7UUFDWkMsV0FBVztRQUNYQyxXQUFXO0lBQ2I7SUFFQSxpQkFBaUI7SUFDakJFLFVBQVU7UUFDUkMsV0FBVztRQUNYQyxjQUFjO1FBQ2RDLGNBQWM7UUFDZEMsZUFBZTtRQUNmQyxZQUFZO1lBQUM7WUFBUTtZQUFNO1lBQUs7WUFBTTtZQUFNO1lBQU07WUFBTTtTQUFJO0lBQzlEO0lBRUEsUUFBUTtJQUNSQyxRQUFRO1FBQ05DLGNBQWM7UUFDZEMscUJBQXFCO1FBQ3JCQyxjQUFjO1FBQ2RDLFdBQVc7SUFDYjtJQUVBLGNBQWM7SUFDZEMsVUFBVTtRQUNSQyxlQUFlO1FBQ2ZDLFVBQVU7SUFDWjtBQUNGLEVBQUU7QUFFRjs7O0NBR0MsR0FDRCxPQUFPLFNBQVNDLG1CQUNkQyxZQUFtQyxDQUFDLENBQUM7SUFFckMsT0FBTztRQUNMdkIsUUFBUTtZQUFFLEdBQUdELHNCQUFzQkMsTUFBTTtZQUFFLEdBQUd1QixVQUFVdkIsTUFBTTtRQUFDO1FBQy9ETyxRQUFRO1lBQUUsR0FBR1Isc0JBQXNCUSxNQUFNO1lBQUUsR0FBR2dCLFVBQVVoQixNQUFNO1FBQUM7UUFDL0RDLFVBQVU7WUFBRSxHQUFHVCxzQkFBc0JTLFFBQVE7WUFBRSxHQUFHZSxVQUFVZixRQUFRO1FBQUM7UUFDckVNLFFBQVE7WUFBRSxHQUFHZixzQkFBc0JlLE1BQU07WUFBRSxHQUFHUyxVQUFVVCxNQUFNO1FBQUM7UUFDL0RLLFVBQVU7WUFBRSxHQUFHcEIsc0JBQXNCb0IsUUFBUTtZQUFFLEdBQUdJLFVBQVVKLFFBQVE7UUFBQztJQUN2RTtBQUNGIn0=
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { EmbeddingProvider, EmbeddingResult, ProgressCallback, VectorConfig, VectorInputType } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 임베딩 클라이언트
|
|
4
|
+
* Voyage AI와 OpenAI 임베딩을 통합 지원
|
|
5
|
+
*/
|
|
6
|
+
export declare class Embedding {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config?: Partial<VectorConfig>);
|
|
9
|
+
/**
|
|
10
|
+
* 텍스트 임베딩 생성
|
|
11
|
+
* @param texts - 임베딩할 텍스트 배열
|
|
12
|
+
* @param provider - 'voyage' | 'openai'
|
|
13
|
+
* @param inputType - 'document' | 'query' (Voyage AI만 해당)
|
|
14
|
+
*/
|
|
15
|
+
embed(texts: string[], provider: EmbeddingProvider, inputType?: VectorInputType): Promise<EmbeddingResult[]>;
|
|
16
|
+
/**
|
|
17
|
+
* 단일 텍스트 임베딩 (편의 메서드)
|
|
18
|
+
*/
|
|
19
|
+
embedOne(text: string, provider: EmbeddingProvider, inputType?: VectorInputType): Promise<EmbeddingResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Voyage AI 임베딩
|
|
22
|
+
*/
|
|
23
|
+
private embedVoyage;
|
|
24
|
+
/**
|
|
25
|
+
* OpenAI 임베딩
|
|
26
|
+
*/
|
|
27
|
+
private embedOpenAI;
|
|
28
|
+
/**
|
|
29
|
+
* 배치 임베딩 (대량 처리)
|
|
30
|
+
*/
|
|
31
|
+
embedBatch(texts: string[], provider: EmbeddingProvider, inputType?: VectorInputType, onProgress?: ProgressCallback): Promise<EmbeddingResult[]>;
|
|
32
|
+
/**
|
|
33
|
+
* 벡터를 PostgreSQL vector 타입 문자열로 변환
|
|
34
|
+
*/
|
|
35
|
+
static toVectorString(embedding: number[]): string;
|
|
36
|
+
/**
|
|
37
|
+
* 임베딩 provider의 차원 수 반환
|
|
38
|
+
*/
|
|
39
|
+
getDimensions(provider: EmbeddingProvider): number;
|
|
40
|
+
private delay;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=embedding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/vector/embedding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAU9C;;;;;OAKG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,GAAE,eAA4B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;IAQ7B;;OAEG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,GAAE,eAA4B,GACtC,OAAO,CAAC,eAAe,CAAC;IAK3B;;OAEG;YACW,WAAW;IAyCzB;;OAEG;YACW,WAAW;IAqCzB;;OAEG;IACG,UAAU,CACd,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,GAAE,eAA4B,EACvC,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,eAAe,EAAE,CAAC;IAwB7B;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM;IAIlD;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM;IAMlD,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Sonamu } from "../api/sonamu.js";
|
|
2
|
+
import { DEFAULT_VECTOR_CONFIG } from "./config.js";
|
|
3
|
+
/**
|
|
4
|
+
* 임베딩 클라이언트
|
|
5
|
+
* Voyage AI와 OpenAI 임베딩을 통합 지원
|
|
6
|
+
*/ export class Embedding {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config = {}){
|
|
9
|
+
this.config = {
|
|
10
|
+
voyage: {
|
|
11
|
+
...DEFAULT_VECTOR_CONFIG.voyage,
|
|
12
|
+
...config.voyage
|
|
13
|
+
},
|
|
14
|
+
openai: {
|
|
15
|
+
...DEFAULT_VECTOR_CONFIG.openai,
|
|
16
|
+
...config.openai
|
|
17
|
+
},
|
|
18
|
+
chunking: {
|
|
19
|
+
...DEFAULT_VECTOR_CONFIG.chunking,
|
|
20
|
+
...config.chunking
|
|
21
|
+
},
|
|
22
|
+
search: {
|
|
23
|
+
...DEFAULT_VECTOR_CONFIG.search,
|
|
24
|
+
...config.search
|
|
25
|
+
},
|
|
26
|
+
pgvector: {
|
|
27
|
+
...DEFAULT_VECTOR_CONFIG.pgvector,
|
|
28
|
+
...config.pgvector
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 텍스트 임베딩 생성
|
|
34
|
+
* @param texts - 임베딩할 텍스트 배열
|
|
35
|
+
* @param provider - 'voyage' | 'openai'
|
|
36
|
+
* @param inputType - 'document' | 'query' (Voyage AI만 해당)
|
|
37
|
+
*/ async embed(texts, provider, inputType = "document") {
|
|
38
|
+
if (provider === "voyage") {
|
|
39
|
+
return this.embedVoyage(texts, inputType);
|
|
40
|
+
} else {
|
|
41
|
+
return this.embedOpenAI(texts);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 단일 텍스트 임베딩 (편의 메서드)
|
|
46
|
+
*/ async embedOne(text, provider, inputType = "document") {
|
|
47
|
+
const results = await this.embed([
|
|
48
|
+
text
|
|
49
|
+
], provider, inputType);
|
|
50
|
+
return results[0];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Voyage AI 임베딩
|
|
54
|
+
*/ async embedVoyage(texts, inputType) {
|
|
55
|
+
const voyageConfig = this.config.voyage;
|
|
56
|
+
// config에서 설정된 apiKey 우선, 없으면 Sonamu.secrets에서 로드
|
|
57
|
+
const apiKey = voyageConfig.apiKey || Sonamu.secrets?.voyage_api_key;
|
|
58
|
+
if (!apiKey) {
|
|
59
|
+
throw new Error("VOYAGE_API_KEY가 설정되지 않았습니다. 환경변수를 확인하세요.");
|
|
60
|
+
}
|
|
61
|
+
const response = await fetch(voyageConfig.baseUrl, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
Authorization: `Bearer ${apiKey}`
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
input: texts,
|
|
69
|
+
model: voyageConfig.model,
|
|
70
|
+
input_type: inputType
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
const error = await response.text();
|
|
75
|
+
throw new Error(`Voyage API error: ${response.status} - ${error}`);
|
|
76
|
+
}
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
return data.data.map((item)=>({
|
|
79
|
+
embedding: item.embedding,
|
|
80
|
+
model: voyageConfig.model,
|
|
81
|
+
tokenCount: data.usage?.total_tokens || 0
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* OpenAI 임베딩
|
|
86
|
+
*/ async embedOpenAI(texts) {
|
|
87
|
+
const openaiConfig = this.config.openai;
|
|
88
|
+
// config에서 설정된 apiKey 우선, 없으면 Sonamu.secrets에서 로드
|
|
89
|
+
const apiKey = openaiConfig.apiKey || Sonamu.secrets?.openai_api_key;
|
|
90
|
+
if (!apiKey) {
|
|
91
|
+
throw new Error("OPENAI_API_KEY가 설정되지 않았습니다. 환경변수를 확인하세요.");
|
|
92
|
+
}
|
|
93
|
+
const response = await fetch(openaiConfig.baseUrl, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
Authorization: `Bearer ${apiKey}`
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
input: texts,
|
|
101
|
+
model: openaiConfig.model
|
|
102
|
+
})
|
|
103
|
+
});
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const error = await response.text();
|
|
106
|
+
throw new Error(`OpenAI API error: ${response.status} - ${error}`);
|
|
107
|
+
}
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
return data.data.map((item)=>({
|
|
110
|
+
embedding: item.embedding,
|
|
111
|
+
model: openaiConfig.model,
|
|
112
|
+
tokenCount: data.usage?.total_tokens || 0
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 배치 임베딩 (대량 처리)
|
|
117
|
+
*/ async embedBatch(texts, provider, inputType = "document", onProgress) {
|
|
118
|
+
const batchSize = provider === "voyage" ? this.config.voyage.batchSize : this.config.openai.batchSize;
|
|
119
|
+
const results = [];
|
|
120
|
+
for(let i = 0; i < texts.length; i += batchSize){
|
|
121
|
+
const batch = texts.slice(i, i + batchSize);
|
|
122
|
+
const batchResults = await this.embed(batch, provider, inputType);
|
|
123
|
+
results.push(...batchResults);
|
|
124
|
+
onProgress?.(Math.min(i + batchSize, texts.length), texts.length);
|
|
125
|
+
// Rate limiting (100ms between batches)
|
|
126
|
+
if (i + batchSize < texts.length) {
|
|
127
|
+
await this.delay(100);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return results;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 벡터를 PostgreSQL vector 타입 문자열로 변환
|
|
134
|
+
*/ static toVectorString(embedding) {
|
|
135
|
+
return `[${embedding.join(",")}]`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 임베딩 provider의 차원 수 반환
|
|
139
|
+
*/ getDimensions(provider) {
|
|
140
|
+
return provider === "voyage" ? this.config.voyage.dimensions : this.config.openai.dimensions;
|
|
141
|
+
}
|
|
142
|
+
delay(ms) {
|
|
143
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZWN0b3IvZW1iZWRkaW5nLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGkvc29uYW11XCI7XG5pbXBvcnQgeyBERUZBVUxUX1ZFQ1RPUl9DT05GSUcgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB0eXBlIHtcbiAgRW1iZWRkaW5nUHJvdmlkZXIsXG4gIEVtYmVkZGluZ1Jlc3VsdCxcbiAgUHJvZ3Jlc3NDYWxsYmFjayxcbiAgVmVjdG9yQ29uZmlnLFxuICBWZWN0b3JJbnB1dFR5cGUsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICog7J6E67Kg65SpIO2BtOudvOydtOyWuO2KuFxuICogVm95YWdlIEFJ7JmAIE9wZW5BSSDsnoTrsqDrlKnsnYQg7Ya17ZWpIOyngOybkFxuICovXG5leHBvcnQgY2xhc3MgRW1iZWRkaW5nIHtcbiAgcHJpdmF0ZSBjb25maWc6IFZlY3RvckNvbmZpZztcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFBhcnRpYWw8VmVjdG9yQ29uZmlnPiA9IHt9KSB7XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICB2b3lhZ2U6IHsgLi4uREVGQVVMVF9WRUNUT1JfQ09ORklHLnZveWFnZSwgLi4uY29uZmlnLnZveWFnZSB9LFxuICAgICAgb3BlbmFpOiB7IC4uLkRFRkFVTFRfVkVDVE9SX0NPTkZJRy5vcGVuYWksIC4uLmNvbmZpZy5vcGVuYWkgfSxcbiAgICAgIGNodW5raW5nOiB7IC4uLkRFRkFVTFRfVkVDVE9SX0NPTkZJRy5jaHVua2luZywgLi4uY29uZmlnLmNodW5raW5nIH0sXG4gICAgICBzZWFyY2g6IHsgLi4uREVGQVVMVF9WRUNUT1JfQ09ORklHLnNlYXJjaCwgLi4uY29uZmlnLnNlYXJjaCB9LFxuICAgICAgcGd2ZWN0b3I6IHsgLi4uREVGQVVMVF9WRUNUT1JfQ09ORklHLnBndmVjdG9yLCAuLi5jb25maWcucGd2ZWN0b3IgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIO2FjeyKpO2KuCDsnoTrsqDrlKkg7IOd7ISxXG4gICAqIEBwYXJhbSB0ZXh0cyAtIOyehOuyoOuUqe2VoCDthY3siqTtirgg67Cw7Je0XG4gICAqIEBwYXJhbSBwcm92aWRlciAtICd2b3lhZ2UnIHwgJ29wZW5haSdcbiAgICogQHBhcmFtIGlucHV0VHlwZSAtICdkb2N1bWVudCcgfCAncXVlcnknIChWb3lhZ2UgQUnrp4wg7ZW064u5KVxuICAgKi9cbiAgYXN5bmMgZW1iZWQoXG4gICAgdGV4dHM6IHN0cmluZ1tdLFxuICAgIHByb3ZpZGVyOiBFbWJlZGRpbmdQcm92aWRlcixcbiAgICBpbnB1dFR5cGU6IFZlY3RvcklucHV0VHlwZSA9IFwiZG9jdW1lbnRcIlxuICApOiBQcm9taXNlPEVtYmVkZGluZ1Jlc3VsdFtdPiB7XG4gICAgaWYgKHByb3ZpZGVyID09PSBcInZveWFnZVwiKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbWJlZFZveWFnZSh0ZXh0cywgaW5wdXRUeXBlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZW1iZWRPcGVuQUkodGV4dHMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDri6jsnbwg7YWN7Iqk7Yq4IOyehOuyoOuUqSAo7Y647J2YIOuplOyEnOuTnClcbiAgICovXG4gIGFzeW5jIGVtYmVkT25lKFxuICAgIHRleHQ6IHN0cmluZyxcbiAgICBwcm92aWRlcjogRW1iZWRkaW5nUHJvdmlkZXIsXG4gICAgaW5wdXRUeXBlOiBWZWN0b3JJbnB1dFR5cGUgPSBcImRvY3VtZW50XCJcbiAgKTogUHJvbWlzZTxFbWJlZGRpbmdSZXN1bHQ+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy5lbWJlZChbdGV4dF0sIHByb3ZpZGVyLCBpbnB1dFR5cGUpO1xuICAgIHJldHVybiByZXN1bHRzWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIFZveWFnZSBBSSDsnoTrsqDrlKlcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW1iZWRWb3lhZ2UoXG4gICAgdGV4dHM6IHN0cmluZ1tdLFxuICAgIGlucHV0VHlwZTogVmVjdG9ySW5wdXRUeXBlXG4gICk6IFByb21pc2U8RW1iZWRkaW5nUmVzdWx0W10+IHtcbiAgICBjb25zdCB2b3lhZ2VDb25maWcgPSB0aGlzLmNvbmZpZy52b3lhZ2U7XG5cbiAgICAvLyBjb25maWfsl5DshJwg7ISk7KCV65CcIGFwaUtleSDsmrDshKAsIOyXhuycvOuptCBTb25hbXUuc2VjcmV0c+yXkOyEnCDroZzrk5xcbiAgICBjb25zdCBhcGlLZXkgPSB2b3lhZ2VDb25maWcuYXBpS2V5IHx8IFNvbmFtdS5zZWNyZXRzPy52b3lhZ2VfYXBpX2tleTtcbiAgICBpZiAoIWFwaUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlZPWUFHRV9BUElfS0VZ6rCAIOyEpOygleuQmOyngCDslYrslZjsirXri4jri6QuIO2ZmOqyveuzgOyImOulvCDtmZXsnbjtlZjshLjsmpQuXCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh2b3lhZ2VDb25maWcuYmFzZVVybCwge1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGlucHV0OiB0ZXh0cyxcbiAgICAgICAgbW9kZWw6IHZveWFnZUNvbmZpZy5tb2RlbCxcbiAgICAgICAgaW5wdXRfdHlwZTogaW5wdXRUeXBlLFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICBjb25zdCBlcnJvciA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVm95YWdlIEFQSSBlcnJvcjogJHtyZXNwb25zZS5zdGF0dXN9IC0gJHtlcnJvcn1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuXG4gICAgcmV0dXJuIGRhdGEuZGF0YS5tYXAoKGl0ZW06IHsgZW1iZWRkaW5nOiBudW1iZXJbXSB9KSA9PiAoe1xuICAgICAgZW1iZWRkaW5nOiBpdGVtLmVtYmVkZGluZyxcbiAgICAgIG1vZGVsOiB2b3lhZ2VDb25maWcubW9kZWwsXG4gICAgICB0b2tlbkNvdW50OiBkYXRhLnVzYWdlPy50b3RhbF90b2tlbnMgfHwgMCxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogT3BlbkFJIOyehOuyoOuUqVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbWJlZE9wZW5BSSh0ZXh0czogc3RyaW5nW10pOiBQcm9taXNlPEVtYmVkZGluZ1Jlc3VsdFtdPiB7XG4gICAgY29uc3Qgb3BlbmFpQ29uZmlnID0gdGhpcy5jb25maWcub3BlbmFpO1xuXG4gICAgLy8gY29uZmln7JeQ7IScIOyEpOygleuQnCBhcGlLZXkg7Jqw7ISgLCDsl4bsnLzrqbQgU29uYW11LnNlY3JldHPsl5DshJwg66Gc65OcXG4gICAgY29uc3QgYXBpS2V5ID0gb3BlbmFpQ29uZmlnLmFwaUtleSB8fCBTb25hbXUuc2VjcmV0cz8ub3BlbmFpX2FwaV9rZXk7XG4gICAgaWYgKCFhcGlLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJPUEVOQUlfQVBJX0tFWeqwgCDshKTsoJXrkJjsp4Ag7JWK7JWY7Iq164uI64ukLiDtmZjqsr3rs4DsiJjrpbwg7ZmV7J247ZWY7IS47JqULlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gob3BlbmFpQ29uZmlnLmJhc2VVcmwsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YXBpS2V5fWAsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBpbnB1dDogdGV4dHMsXG4gICAgICAgIG1vZGVsOiBvcGVuYWlDb25maWcubW9kZWwsXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IGVycm9yID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBPcGVuQUkgQVBJIGVycm9yOiAke3Jlc3BvbnNlLnN0YXR1c30gLSAke2Vycm9yfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG5cbiAgICByZXR1cm4gZGF0YS5kYXRhLm1hcCgoaXRlbTogeyBlbWJlZGRpbmc6IG51bWJlcltdIH0pID0+ICh7XG4gICAgICBlbWJlZGRpbmc6IGl0ZW0uZW1iZWRkaW5nLFxuICAgICAgbW9kZWw6IG9wZW5haUNvbmZpZy5tb2RlbCxcbiAgICAgIHRva2VuQ291bnQ6IGRhdGEudXNhZ2U/LnRvdGFsX3Rva2VucyB8fCAwLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrsLDsuZgg7J6E67Kg65SpICjrjIDrn4kg7LKY66asKVxuICAgKi9cbiAgYXN5bmMgZW1iZWRCYXRjaChcbiAgICB0ZXh0czogc3RyaW5nW10sXG4gICAgcHJvdmlkZXI6IEVtYmVkZGluZ1Byb3ZpZGVyLFxuICAgIGlucHV0VHlwZTogVmVjdG9ySW5wdXRUeXBlID0gXCJkb2N1bWVudFwiLFxuICAgIG9uUHJvZ3Jlc3M/OiBQcm9ncmVzc0NhbGxiYWNrXG4gICk6IFByb21pc2U8RW1iZWRkaW5nUmVzdWx0W10+IHtcbiAgICBjb25zdCBiYXRjaFNpemUgPVxuICAgICAgcHJvdmlkZXIgPT09IFwidm95YWdlXCJcbiAgICAgICAgPyB0aGlzLmNvbmZpZy52b3lhZ2UuYmF0Y2hTaXplXG4gICAgICAgIDogdGhpcy5jb25maWcub3BlbmFpLmJhdGNoU2l6ZTtcblxuICAgIGNvbnN0IHJlc3VsdHM6IEVtYmVkZGluZ1Jlc3VsdFtdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRleHRzLmxlbmd0aDsgaSArPSBiYXRjaFNpemUpIHtcbiAgICAgIGNvbnN0IGJhdGNoID0gdGV4dHMuc2xpY2UoaSwgaSArIGJhdGNoU2l6ZSk7XG4gICAgICBjb25zdCBiYXRjaFJlc3VsdHMgPSBhd2FpdCB0aGlzLmVtYmVkKGJhdGNoLCBwcm92aWRlciwgaW5wdXRUeXBlKTtcbiAgICAgIHJlc3VsdHMucHVzaCguLi5iYXRjaFJlc3VsdHMpO1xuXG4gICAgICBvblByb2dyZXNzPy4oTWF0aC5taW4oaSArIGJhdGNoU2l6ZSwgdGV4dHMubGVuZ3RoKSwgdGV4dHMubGVuZ3RoKTtcblxuICAgICAgLy8gUmF0ZSBsaW1pdGluZyAoMTAwbXMgYmV0d2VlbiBiYXRjaGVzKVxuICAgICAgaWYgKGkgKyBiYXRjaFNpemUgPCB0ZXh0cy5sZW5ndGgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5kZWxheSgxMDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIOuyoe2EsOulvCBQb3N0Z3JlU1FMIHZlY3RvciDtg4DsnoUg66y47J6Q7Je066GcIOuzgO2ZmFxuICAgKi9cbiAgc3RhdGljIHRvVmVjdG9yU3RyaW5nKGVtYmVkZGluZzogbnVtYmVyW10pOiBzdHJpbmcge1xuICAgIHJldHVybiBgWyR7ZW1iZWRkaW5nLmpvaW4oXCIsXCIpfV1gO1xuICB9XG5cbiAgLyoqXG4gICAqIOyehOuyoOuUqSBwcm92aWRlcuydmCDssKjsm5Ag7IiYIOuwmO2ZmFxuICAgKi9cbiAgZ2V0RGltZW5zaW9ucyhwcm92aWRlcjogRW1iZWRkaW5nUHJvdmlkZXIpOiBudW1iZXIge1xuICAgIHJldHVybiBwcm92aWRlciA9PT0gXCJ2b3lhZ2VcIlxuICAgICAgPyB0aGlzLmNvbmZpZy52b3lhZ2UuZGltZW5zaW9uc1xuICAgICAgOiB0aGlzLmNvbmZpZy5vcGVuYWkuZGltZW5zaW9ucztcbiAgfVxuXG4gIHByaXZhdGUgZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpO1xuICB9XG59XG4iXSwibmFtZXMiOlsiU29uYW11IiwiREVGQVVMVF9WRUNUT1JfQ09ORklHIiwiRW1iZWRkaW5nIiwiY29uZmlnIiwidm95YWdlIiwib3BlbmFpIiwiY2h1bmtpbmciLCJzZWFyY2giLCJwZ3ZlY3RvciIsImVtYmVkIiwidGV4dHMiLCJwcm92aWRlciIsImlucHV0VHlwZSIsImVtYmVkVm95YWdlIiwiZW1iZWRPcGVuQUkiLCJlbWJlZE9uZSIsInRleHQiLCJyZXN1bHRzIiwidm95YWdlQ29uZmlnIiwiYXBpS2V5Iiwic2VjcmV0cyIsInZveWFnZV9hcGlfa2V5IiwiRXJyb3IiLCJyZXNwb25zZSIsImZldGNoIiwiYmFzZVVybCIsIm1ldGhvZCIsImhlYWRlcnMiLCJBdXRob3JpemF0aW9uIiwiYm9keSIsIkpTT04iLCJzdHJpbmdpZnkiLCJpbnB1dCIsIm1vZGVsIiwiaW5wdXRfdHlwZSIsIm9rIiwiZXJyb3IiLCJzdGF0dXMiLCJkYXRhIiwianNvbiIsIm1hcCIsIml0ZW0iLCJlbWJlZGRpbmciLCJ0b2tlbkNvdW50IiwidXNhZ2UiLCJ0b3RhbF90b2tlbnMiLCJvcGVuYWlDb25maWciLCJvcGVuYWlfYXBpX2tleSIsImVtYmVkQmF0Y2giLCJvblByb2dyZXNzIiwiYmF0Y2hTaXplIiwiaSIsImxlbmd0aCIsImJhdGNoIiwic2xpY2UiLCJiYXRjaFJlc3VsdHMiLCJwdXNoIiwiTWF0aCIsIm1pbiIsImRlbGF5IiwidG9WZWN0b3JTdHJpbmciLCJqb2luIiwiZ2V0RGltZW5zaW9ucyIs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
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pgvector 통합을 위한 타입 정의
|
|
3
|
+
*/
|
|
4
|
+
/** 임베딩 제공자 */
|
|
5
|
+
export type EmbeddingProvider = "voyage" | "openai";
|
|
6
|
+
/** 입력 타입 (Voyage AI 전용 - 비대칭 임베딩) */
|
|
7
|
+
export type VectorInputType = "document" | "query";
|
|
8
|
+
/** 임베딩 결과 */
|
|
9
|
+
export interface EmbeddingResult {
|
|
10
|
+
embedding: number[];
|
|
11
|
+
model: string;
|
|
12
|
+
tokenCount: number;
|
|
13
|
+
}
|
|
14
|
+
/** 청크 정보 */
|
|
15
|
+
export interface Chunk {
|
|
16
|
+
index: number;
|
|
17
|
+
text: string;
|
|
18
|
+
startOffset: number;
|
|
19
|
+
endOffset: number;
|
|
20
|
+
}
|
|
21
|
+
/** 벡터 검색 결과 */
|
|
22
|
+
export interface VectorSearchResult<T = Record<string, unknown>> {
|
|
23
|
+
id: number | string;
|
|
24
|
+
similarity: number;
|
|
25
|
+
data: T;
|
|
26
|
+
}
|
|
27
|
+
/** 하이브리드 검색 결과 (Vector + FTS) */
|
|
28
|
+
export interface HybridSearchResult<T = Record<string, unknown>> extends VectorSearchResult<T> {
|
|
29
|
+
vectorScore?: number;
|
|
30
|
+
ftsScore?: number;
|
|
31
|
+
}
|
|
32
|
+
/** 벤치마크 결과 */
|
|
33
|
+
export interface BenchmarkResult {
|
|
34
|
+
provider: EmbeddingProvider;
|
|
35
|
+
embedTime: number;
|
|
36
|
+
searchTime: number;
|
|
37
|
+
results: VectorSearchResult[];
|
|
38
|
+
}
|
|
39
|
+
/** Voyage AI 설정 */
|
|
40
|
+
export interface VoyageConfig {
|
|
41
|
+
apiKey: string;
|
|
42
|
+
baseUrl: string;
|
|
43
|
+
model: string;
|
|
44
|
+
dimensions: number;
|
|
45
|
+
maxTokens: number;
|
|
46
|
+
batchSize: number;
|
|
47
|
+
}
|
|
48
|
+
/** OpenAI 설정 */
|
|
49
|
+
export interface OpenAIConfig {
|
|
50
|
+
apiKey: string;
|
|
51
|
+
baseUrl: string;
|
|
52
|
+
model: string;
|
|
53
|
+
dimensions: number;
|
|
54
|
+
maxTokens: number;
|
|
55
|
+
batchSize: number;
|
|
56
|
+
}
|
|
57
|
+
/** 청킹 설정 */
|
|
58
|
+
export interface ChunkingConfig {
|
|
59
|
+
chunkSize: number;
|
|
60
|
+
chunkOverlap: number;
|
|
61
|
+
minChunkSize: number;
|
|
62
|
+
skipThreshold: number;
|
|
63
|
+
separators: string[];
|
|
64
|
+
}
|
|
65
|
+
/** 검색 설정 */
|
|
66
|
+
export interface SearchConfig {
|
|
67
|
+
defaultLimit: number;
|
|
68
|
+
similarityThreshold: number;
|
|
69
|
+
vectorWeight: number;
|
|
70
|
+
ftsWeight: number;
|
|
71
|
+
}
|
|
72
|
+
/** pgvector 설정 */
|
|
73
|
+
export interface PgvectorConfig {
|
|
74
|
+
iterativeScan: boolean;
|
|
75
|
+
efSearch: number;
|
|
76
|
+
}
|
|
77
|
+
/** 전체 벡터 설정 */
|
|
78
|
+
export interface VectorConfig {
|
|
79
|
+
voyage: VoyageConfig;
|
|
80
|
+
openai: OpenAIConfig;
|
|
81
|
+
chunking: ChunkingConfig;
|
|
82
|
+
search: SearchConfig;
|
|
83
|
+
pgvector: PgvectorConfig;
|
|
84
|
+
}
|
|
85
|
+
/** 벡터 검색 옵션 */
|
|
86
|
+
export interface VectorSearchOptions {
|
|
87
|
+
embeddingColumn?: string;
|
|
88
|
+
limit?: number;
|
|
89
|
+
threshold?: number;
|
|
90
|
+
where?: string;
|
|
91
|
+
}
|
|
92
|
+
/** 하이브리드 검색 옵션 */
|
|
93
|
+
export interface HybridSearchOptions extends VectorSearchOptions {
|
|
94
|
+
vectorWeight?: number;
|
|
95
|
+
ftsWeight?: number;
|
|
96
|
+
ftsColumn?: string;
|
|
97
|
+
}
|
|
98
|
+
/** 임베딩 저장 항목 */
|
|
99
|
+
export interface EmbeddingItem {
|
|
100
|
+
id: number;
|
|
101
|
+
text: string;
|
|
102
|
+
}
|
|
103
|
+
/** 진행률 콜백 */
|
|
104
|
+
export type ProgressCallback = (processed: number, total: number) => void;
|
|
105
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vector/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pgvector 통합을 위한 타입 정의
|
|
3
|
+
*/ /** 임베딩 제공자 */ /** 진행률 콜백 */ export { };
|
|
4
|
+
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZWN0b3IvdHlwZXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBwZ3ZlY3RvciDthrXtlansnYQg7JyE7ZWcIO2DgOyehSDsoJXsnZhcbiAqL1xuXG4vKiog7J6E67Kg65SpIOygnOqzteyekCAqL1xuZXhwb3J0IHR5cGUgRW1iZWRkaW5nUHJvdmlkZXIgPSBcInZveWFnZVwiIHwgXCJvcGVuYWlcIjtcblxuLyoqIOyeheugpSDtg4DsnoUgKFZveWFnZSBBSSDsoITsmqkgLSDruYTrjIDsua0g7J6E67Kg65SpKSAqL1xuZXhwb3J0IHR5cGUgVmVjdG9ySW5wdXRUeXBlID0gXCJkb2N1bWVudFwiIHwgXCJxdWVyeVwiO1xuXG4vKiog7J6E67Kg65SpIOqysOqzvCAqL1xuZXhwb3J0IGludGVyZmFjZSBFbWJlZGRpbmdSZXN1bHQge1xuICBlbWJlZGRpbmc6IG51bWJlcltdO1xuICBtb2RlbDogc3RyaW5nO1xuICB0b2tlbkNvdW50OiBudW1iZXI7XG59XG5cbi8qKiDssq3tgawg7KCV67O0ICovXG5leHBvcnQgaW50ZXJmYWNlIENodW5rIHtcbiAgaW5kZXg6IG51bWJlcjtcbiAgdGV4dDogc3RyaW5nO1xuICBzdGFydE9mZnNldDogbnVtYmVyO1xuICBlbmRPZmZzZXQ6IG51bWJlcjtcbn1cblxuLyoqIOuyoe2EsCDqsoDsg4kg6rKw6rO8ICovXG5leHBvcnQgaW50ZXJmYWNlIFZlY3RvclNlYXJjaFJlc3VsdDxUID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgaWQ6IG51bWJlciB8IHN0cmluZztcbiAgc2ltaWxhcml0eTogbnVtYmVyO1xuICBkYXRhOiBUO1xufVxuXG4vKiog7ZWY7J2067iM66as65OcIOqygOyDiSDqsrDqs7wgKFZlY3RvciArIEZUUykgKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHlicmlkU2VhcmNoUmVzdWx0PFQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj5cbiAgZXh0ZW5kcyBWZWN0b3JTZWFyY2hSZXN1bHQ8VD4ge1xuICB2ZWN0b3JTY29yZT86IG51bWJlcjtcbiAgZnRzU2NvcmU/OiBudW1iZXI7XG59XG5cbi8qKiDrsqTsuZjrp4jtgawg6rKw6rO8ICovXG5leHBvcnQgaW50ZXJmYWNlIEJlbmNobWFya1Jlc3VsdCB7XG4gIHByb3ZpZGVyOiBFbWJlZGRpbmdQcm92aWRlcjtcbiAgZW1iZWRUaW1lOiBudW1iZXI7XG4gIHNlYXJjaFRpbWU6IG51bWJlcjtcbiAgcmVzdWx0czogVmVjdG9yU2VhcmNoUmVzdWx0W107XG59XG5cbi8qKiBWb3lhZ2UgQUkg7ISk7KCVICovXG5leHBvcnQgaW50ZXJmYWNlIFZveWFnZUNvbmZpZyB7XG4gIGFwaUtleTogc3RyaW5nO1xuICBiYXNlVXJsOiBzdHJpbmc7XG4gIG1vZGVsOiBzdHJpbmc7XG4gIGRpbWVuc2lvbnM6IG51bWJlcjtcbiAgbWF4VG9rZW5zOiBudW1iZXI7XG4gIGJhdGNoU2l6ZTogbnVtYmVyO1xufVxuXG4vKiogT3BlbkFJIOyEpOyglSAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlDb25maWcge1xuICBhcGlLZXk6IHN0cmluZztcbiAgYmFzZVVybDogc3RyaW5nO1xuICBtb2RlbDogc3RyaW5nO1xuICBkaW1lbnNpb25zOiBudW1iZXI7XG4gIG1heFRva2VuczogbnVtYmVyO1xuICBiYXRjaFNpemU6IG51bWJlcjtcbn1cblxuLyoqIOyyre2CuSDshKTsoJUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2h1bmtpbmdDb25maWcge1xuICBjaHVua1NpemU6IG51bWJlcjtcbiAgY2h1bmtPdmVybGFwOiBudW1iZXI7XG4gIG1pbkNodW5rU2l6ZTogbnVtYmVyO1xuICBza2lwVGhyZXNob2xkOiBudW1iZXI7XG4gIHNlcGFyYXRvcnM6IHN0cmluZ1tdO1xufVxuXG4vKiog6rKA7IOJIOyEpOyglSAqL1xuZXhwb3J0IGludGVyZmFjZSBTZWFyY2hDb25maWcge1xuICBkZWZhdWx0TGltaXQ6IG51bWJlcjtcbiAgc2ltaWxhcml0eVRocmVzaG9sZDogbnVtYmVyO1xuICB2ZWN0b3JXZWlnaHQ6IG51bWJlcjtcbiAgZnRzV2VpZ2h0OiBudW1iZXI7XG59XG5cbi8qKiBwZ3ZlY3RvciDshKTsoJUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGd2ZWN0b3JDb25maWcge1xuICBpdGVyYXRpdmVTY2FuOiBib29sZWFuO1xuICBlZlNlYXJjaDogbnVtYmVyO1xufVxuXG4vKiog7KCE7LK0IOuyoe2EsCDshKTsoJUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVjdG9yQ29uZmlnIHtcbiAgdm95YWdlOiBWb3lhZ2VDb25maWc7XG4gIG9wZW5haTogT3BlbkFJQ29uZmlnO1xuICBjaHVua2luZzogQ2h1bmtpbmdDb25maWc7XG4gIHNlYXJjaDogU2VhcmNoQ29uZmlnO1xuICBwZ3ZlY3RvcjogUGd2ZWN0b3JDb25maWc7XG59XG5cbi8qKiDrsqHthLAg6rKA7IOJIOyYteyFmCAqL1xuZXhwb3J0IGludGVyZmFjZSBWZWN0b3JTZWFyY2hPcHRpb25zIHtcbiAgZW1iZWRkaW5nQ29sdW1uPzogc3RyaW5nO1xuICBsaW1pdD86IG51bWJlcjtcbiAgdGhyZXNob2xkPzogbnVtYmVyO1xuICB3aGVyZT86IHN0cmluZztcbn1cblxuLyoqIO2VmOydtOu4jOumrOuTnCDqsoDsg4kg7Ji17IWYICovXG5leHBvcnQgaW50ZXJmYWNlIEh5YnJpZFNlYXJjaE9wdGlvbnMgZXh0ZW5kcyBWZWN0b3JTZWFyY2hPcHRpb25zIHtcbiAgdmVjdG9yV2VpZ2h0PzogbnVtYmVyO1xuICBmdHNXZWlnaHQ/OiBudW1iZXI7XG4gIGZ0c0NvbHVtbj86IHN0cmluZztcbn1cblxuLyoqIOyehOuyoOuUqSDsoIDsnqUg7ZWt66qpICovXG5leHBvcnQgaW50ZXJmYWNlIEVtYmVkZGluZ0l0ZW0ge1xuICBpZDogbnVtYmVyO1xuICB0ZXh0OiBzdHJpbmc7XG59XG5cbi8qKiDsp4TtlonrpaAg7L2c67CxICovXG5leHBvcnQgdHlwZSBQcm9ncmVzc0NhbGxiYWNrID0gKHByb2Nlc3NlZDogbnVtYmVyLCB0b3RhbDogbnVtYmVyKSA9PiB2b2lkO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztDQUVDLEdBRUQsWUFBWSxHQW9IWixXQUFXLEdBQ1gsV0FBMEUifQ==
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import { Embedding } from "./embedding";
|
|
3
|
+
import type { EmbeddingItem, EmbeddingProvider, HybridSearchOptions, HybridSearchResult, ProgressCallback, VectorConfig, VectorSearchOptions, VectorSearchResult } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* 벡터 검색
|
|
6
|
+
* pgvector를 활용한 벡터 검색 및 하이브리드 검색 지원
|
|
7
|
+
*/
|
|
8
|
+
export declare class VectorSearch<T = Record<string, unknown>> {
|
|
9
|
+
private db;
|
|
10
|
+
private config;
|
|
11
|
+
private embedding;
|
|
12
|
+
private tableName;
|
|
13
|
+
constructor(db: Knex, tableName: string, config?: Partial<VectorConfig>);
|
|
14
|
+
/**
|
|
15
|
+
* 단일 항목에 임베딩 저장
|
|
16
|
+
*/
|
|
17
|
+
saveEmbedding(id: number, text: string, provider: EmbeddingProvider, embeddingColumn?: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* 여러 항목에 임베딩 일괄 저장
|
|
20
|
+
*/
|
|
21
|
+
saveEmbeddingsBatch(items: EmbeddingItem[], provider: EmbeddingProvider, embeddingColumn?: string, onProgress?: ProgressCallback): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* 벡터 검색 (코사인 유사도)
|
|
24
|
+
*/
|
|
25
|
+
search(query: string, provider: EmbeddingProvider, options?: VectorSearchOptions): Promise<VectorSearchResult<T>[]>;
|
|
26
|
+
/**
|
|
27
|
+
* 하이브리드 검색 (Vector + FTS)
|
|
28
|
+
*/
|
|
29
|
+
hybridSearch(query: string, provider: EmbeddingProvider, options?: HybridSearchOptions): Promise<HybridSearchResult<T>[]>;
|
|
30
|
+
/**
|
|
31
|
+
* 임베딩 현황 조회
|
|
32
|
+
*/
|
|
33
|
+
getEmbeddingStatus(embeddingColumn?: string): Promise<{
|
|
34
|
+
total: number;
|
|
35
|
+
withEmbedding: number;
|
|
36
|
+
withoutEmbedding: number;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* 임베딩이 없는 항목 ID 조회
|
|
40
|
+
*/
|
|
41
|
+
getItemsWithoutEmbedding(embeddingColumn?: string, limit?: number): Promise<number[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Embedding 인스턴스 반환 (고급 사용)
|
|
44
|
+
*/
|
|
45
|
+
getEmbedding(): Embedding;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=vector-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../src/vector/vector-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,qBAAa,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnD,OAAO,CAAC,EAAE,CAAO;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAEd,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAa3E;;OAEG;IACG,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,GAAE,MAA4B,GAC5C,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,mBAAmB,CACvB,KAAK,EAAE,aAAa,EAAE,EACtB,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,GAAE,MAA4B,EAC7C,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IAyCnC;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IAiFnC;;OAEG;IACG,kBAAkB,CAAC,eAAe,GAAE,MAA4B,GAAG,OAAO,CAAC;QAC/E,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IAgBF;;OAEG;IACG,wBAAwB,CAC5B,eAAe,GAAE,MAA4B,EAC7C,KAAK,GAAE,MAAY,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC;IAUpB;;OAEG;IACH,YAAY,IAAI,SAAS;CAG1B"}
|