This commit is contained in:
2026-01-21 18:59:55 +09:00
parent 56945a56d1
commit dfc5de7cdc
8 changed files with 174 additions and 36 deletions
+27 -21
View File
@@ -1,5 +1,6 @@
// src/main/kotlin/network/RagService.kt
import VectorStoreTable.metadata
import dev.langchain4j.data.segment.TextSegment
import dev.langchain4j.model.openai.OpenAiChatModel
import dev.langchain4j.model.openai.OpenAiEmbeddingModel
@@ -25,14 +26,13 @@ object RagService {
* 텍스트를 임베딩하여 H2 DB에 저장합니다.
*/
fun ingest(text: String, meta: String = "") {
val embedding = embeddingModel.embed(text).content().vector()
val embeddingVector: DoubleArray = embeddingModel.embed(text).content().vector().map { it.toDouble() }.toDoubleArray()
transaction {
VectorStoreTable.insert {
it[content] = text
it[metadata] = meta
// 벡터 데이터를 문자열 형태로 저장 (H2 포맷)
it[VectorStoreTable.embedding] = embedding.joinToString(",", "[", "]")
// [수정] 문자열 변환 없이 객체 그대로 전달
it[embedding] = embeddingVector
}
}
println("💾 H2 벡터 저장 완료: ${text.take(15)}...")
@@ -41,35 +41,41 @@ object RagService {
/**
* 질문과 가장 유사한 정보를 H2에서 검색하여 AI 답변을 생성합니다.
*/
fun ask(question: String): String {
fun askWithContext(question: String): String {
val queryVector = embeddingModel.embed(question).content().vector()
val vectorStr = queryVector.joinToString(",", "[", "]")
// H2 ARRAY 포맷에 맞춰 (v1, v2, ...) 형태로 변환
val vectorStr = queryVector.joinToString(",", "(", ")")
// H2의 VECTOR_COSINE_SIMILARITY 함수를 사용하여 검색
val context = transaction {
val query = "SELECT content FROM VECTOR_STORE " +
"ORDER BY VECTOR_COSINE_SIMILARITY(embedding, '$vectorStr') DESC " +
"LIMIT 3"
// 코사인 유사도 기준 상위 5개 뉴스 추출
val query = """
SELECT CONTENT FROM VECTOR_STORE
ORDER BY VECTOR_COSINE_SIMILARITY(EMBEDDING, CAST('$vectorStr' AS FLOAT8 ARRAY)) DESC
LIMIT 5
""".trimIndent()
val results = mutableListOf<String>()
exec(query) { rs ->
while (rs.next()) {
results.add(rs.getString("content"))
results.add(rs.getString("CONTENT"))
}
}
results.joinToString("\n\n")
}
val prompt = """
[참고 정보]
$context
[질문]
$question
위 정보를 참고하여 분석 결과를 말해주세요.
""".trimIndent()
val finalPrompt = """
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
당신은 실시간 뉴스 분석에 능통한 20년 경력의 주식 전문가입니다.
제공된 [참고 자료]를 바탕으로 사용자의 질문에 전문적이고 단호하게 답하세요.<|eot_id|>
<|start_header_id|>user<|end_header_id|>
[참고 자료]
$context
return chatModel.generate(prompt)
[질문]
$question
<|eot_id|><|start_header_id|>assistant<|end_header_id|>
""".trimIndent()
return chatModel.generate(finalPrompt)
}
}