-
Notifications
You must be signed in to change notification settings - Fork 0
✨ Feature: erd 수정 #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d63c940
b342d3c
79115f7
31c2465
6e43a37
4ca3f09
66c5f14
0c0ea96
625a91e
cbdf1dd
6669cb5
e929732
db5816f
4671e1a
8b9bf46
8eeb524
1b6cb96
b39b21c
de7c5a6
75c51bd
1f1aefa
6579334
28a397a
1349b69
b2c0a18
4b0f303
90ada31
ccbfcf0
a2db08a
3811cbc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,29 @@ | ||||||||||||||||||||||||||||||||||
| package simplerag.ragback.domain.chat.entity | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| import jakarta.persistence.* | ||||||||||||||||||||||||||||||||||
| import simplerag.ragback.domain.index.entity.Index | ||||||||||||||||||||||||||||||||||
| import simplerag.ragback.domain.prompt.entity.Prompt | ||||||||||||||||||||||||||||||||||
| import simplerag.ragback.global.entity.BaseEntity | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Entity | ||||||||||||||||||||||||||||||||||
| @Table(name = "models") | ||||||||||||||||||||||||||||||||||
| class Model( | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Column(name = "name", nullable = false, unique = true, length = 100) | ||||||||||||||||||||||||||||||||||
| val name: String, | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Column(name = "llm_model", nullable = false) | ||||||||||||||||||||||||||||||||||
| val llmModel: String, | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 입력 유효성 보강 제안 — @notblank로 공백 문자열 방지(옵셔널) DB 제약만으로는 빈 문자열을 막지 못합니다. Bean Validation을 추가하면 API/서비스 레이어에서 조기에 검증 가능합니다. 예시 diff: import jakarta.persistence.*
+import jakarta.validation.constraints.NotBlank
@@
- @Column(name = "name", nullable = false, unique = true, length = 100)
+ @field:NotBlank
+ @Column(name = "name", nullable = false, unique = true, length = 100)
val name: String,
@@
- @Column(name = "llm_model", nullable = false)
+ @field:NotBlank
+ @Column(name = "llm_model", nullable = false)
val llmModel: String,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||||||||||||||||||||
| @JoinColumn(name = "indexes_id") | ||||||||||||||||||||||||||||||||||
| val index: Index, | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||||||||||||||||||||
| @JoinColumn(name = "prompts_id") | ||||||||||||||||||||||||||||||||||
| val prompt: Prompt, | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion FK 컬럼이 NULL 허용 상태 — DB 무결성 보장을 위해 optional=false + nullable=false 지정 권장 ManyToOne의 기본 optional=true, @joincolumn의 기본 nullable=true라 DB에서 NULL을 허용합니다. 모델이 항상 Index/Prompt를 가져야 한다면 명시적으로 비허용으로 바꿔 무결성을 보장하세요. 적용 diff: - @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "indexes_id")
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "indexes_id", nullable = false)
val index: Index,
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "prompts_id")
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "prompts_id", nullable = false)
val prompt: Prompt,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프롬프트랑 인덱스가 없는 경우도 고려하려구요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||||||||||||||||||||||||||||||||
| @Column(name = "models_id") | ||||||||||||||||||||||||||||||||||
| val id: Long? = null, | ||||||||||||||||||||||||||||||||||
| ): BaseEntity() | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,24 @@ | ||
| package simplerag.ragback.domain.document.entity | ||
|
|
||
| import jakarta.persistence.* | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
|
|
||
| @Entity | ||
| @Table( | ||
| name = "data_file_tags", | ||
| uniqueConstraints = [UniqueConstraint(columnNames = ["data_file_id", "tag_id"])] | ||
| name = "data_files_tags", | ||
| uniqueConstraints = [UniqueConstraint(columnNames = ["data_files_id", "tags_id"])] | ||
| ) | ||
| class DataFileTag( | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "tag_id", nullable = false) | ||
| @JoinColumn(name = "tags_id", nullable = false) | ||
| var tag: Tag, | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "data_file_id", nullable = false) | ||
| @JoinColumn(name = "data_files_id", nullable = false) | ||
| var dataFile: DataFile, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "data_files_tags_id") | ||
| val id: Long? = null, | ||
| ) | ||
| ): BaseEntity() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package simplerag.ragback.domain.document.entity | ||
|
|
||
| import jakarta.persistence.* | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
|
|
||
| @Entity | ||
| @Table( | ||
|
|
@@ -13,5 +14,6 @@ class Tag( | |
| val name: String, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "tags_id") | ||
| val id: Long? = null, | ||
|
Comment on lines
+17
to
18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainid 컬럼명을 "tags_id"로 커스텀하면 기존 FK 매핑(특히 DataFileTag)이 깨질 수 있습니다 다른 엔티티가 기본 조인 규칙( 제안(기본 컬럼명으로 복구): @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "tags_id")
val id: Long? = null,검증 스크립트: DataFileTag 등에서의 조인 컬럼을 점검하세요. 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "1) Tag 엔티티의 PK 컬럼 커스텀 여부 확인"
rg -n -C2 'class\s+Tag\b|@Column\s*\(\s*name\s*=\s*"tags?_id"' src/main/kotlin
echo
echo "2) DataFileTag 등 Tag를 참조하는 엔티티에서 JoinColumn 확인"
fd DataFileTag.kt -a | while read -r f; do
echo "---- $f ----"
rg -n -C4 '@ManyToOne|@JoinColumn|Tag\b|tags_id|tag_id' "$f" || true
done
echo
echo "3) 전역적으로 tags_id/tag_id 문자열 사용처 확인"
rg -n -C2 '\btags?_id\b' src/main/kotlinLength of output: 3796 Tag 엔티티 PK 컬럼명 커스텀으로 인한 매핑 불일치 확인 및 수정 필요 Tag.kt에서 PK 컬럼명을 수정이 필요한 위치:
제안 1) Tag 엔티티를 기본 컬럼명으로 복구 @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
-@Column(name = "tags_id")
val id: Long? = null,제안 2) 만약 @ManyToOne(fetch = FetchType.LAZY)
-@JoinColumn(name = "tag_id", nullable = false)
+@JoinColumn(name = "tags_id", nullable = false)
var tag: Tag,🤖 Prompt for AI Agents |
||
| ) | ||
| ): BaseEntity() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package simplerag.ragback.domain.index.entity | ||
|
|
||
| import jakarta.persistence.* | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
| import simplerag.ragback.global.util.FloatArrayToPgVectorStringConverter | ||
|
|
||
| // 임베딩 크기를 서비스단에서 검증을 해줘야함 | ||
| @Entity | ||
| @Table(name = "chunk_embeddings") | ||
| class ChunkEmbedding( | ||
|
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 쿼리 성능 대비: 인덱스 전략 제안
원하시면 Flyway/Liquibase용 마이그레이션 스니펫을 제공하겠습니다. |
||
|
|
||
| @Column(name = "content", nullable = false) | ||
| @Lob | ||
| val content: String, | ||
|
|
||
| @Convert(converter = FloatArrayToPgVectorStringConverter::class) | ||
| @Column(name = "embedding", nullable = false) | ||
| private var _embedding: FloatArray, | ||
|
|
||
| @Column(name = "embedding_dim", nullable = false) | ||
| val embeddingDim: Int, | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "indexes_id", nullable = false) | ||
| val index: Index, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "chunk_embeddings_id") | ||
| val id: Long? = null, | ||
| ): BaseEntity() { | ||
|
|
||
| @get:Transient | ||
| val embedding: FloatArray get() = _embedding.copyOf() | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| fun updateEmbedding(newVec: FloatArray) { | ||
| require(newVec.size == embeddingDim) { | ||
| "Embedding dimension mismatch: expected=$embeddingDim, got=${newVec.size}" | ||
| } | ||
| _embedding = newVec.copyOf() | ||
| } | ||
|
|
||
| } | ||
|
Comment on lines
+35
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 초기 생성 시 차원/유한성 불변식 보강: 영속화 훅 추가 권장 주석대로 서비스단 검증을 하더라도, 엔티티 차원에서 한 번 더 방어하면 데이터 오염을 원천 차단할 수 있습니다. LAZY FK 접근 없이 적용 diff: fun updateEmbedding(newVec: FloatArray) {
require(newVec.size == embeddingDim) {
"Embedding dimension mismatch: expected=$embeddingDim, got=${newVec.size}"
}
_embedding = newVec.copyOf()
}
+ @PrePersist
+ @PreUpdate
+ private fun verifyBeforeSave() {
+ require(_embedding.size == embeddingDim) {
+ "Embedding dimension mismatch: expected=$embeddingDim, got=${_embedding.size}"
+ }
+ require(_embedding.isNotEmpty()) { "Embedding must not be empty" }
+ require(_embedding.all { it.isFinite() }) {
+ "Embedding must not contain NaN/Infinity"
+ }
+ }
}🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package simplerag.ragback.domain.index.entity | ||
|
|
||
| import jakarta.persistence.* | ||
catturtle123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import simplerag.ragback.domain.document.entity.DataFile | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
|
|
||
| @Entity | ||
| @Table(name = "data_files_indexes") | ||
| class DataFileIndex( | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "data_files_id", nullable = false) | ||
| val dataFile: DataFile, | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "indexes_id", nullable = false) | ||
| val index: Index, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "data_files_indexes_id") | ||
| val id: Long? = null, | ||
| ): BaseEntity() | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||||||||
| package simplerag.ragback.domain.index.entity | ||||||||||||
|
|
||||||||||||
| import jakarta.persistence.* | ||||||||||||
| import jakarta.validation.constraints.Min | ||||||||||||
| import simplerag.ragback.domain.index.entity.enums.EmbeddingModel | ||||||||||||
| import simplerag.ragback.domain.index.entity.enums.SimilarityMetric | ||||||||||||
| import simplerag.ragback.global.entity.BaseEntity | ||||||||||||
|
|
||||||||||||
| @Entity | ||||||||||||
| @Table(name = "indexes") | ||||||||||||
| class Index( | ||||||||||||
|
|
||||||||||||
| @Column(name = "snapshot_name", length = 255, nullable = false) | ||||||||||||
| val snapshotName: String, | ||||||||||||
|
|
||||||||||||
| @Column(name = "chunking_size", nullable = false) | ||||||||||||
| @Min(1) | ||||||||||||
| val chunkingSize: Int, | ||||||||||||
|
|
||||||||||||
| @Column(name = "overlap_size", nullable = false) | ||||||||||||
| @Min(0) | ||||||||||||
| val overlapSize: Int, | ||||||||||||
|
Comment on lines
+16
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 교차 필드 제약 추가: overlapSize ≤ chunkingSize 일반적으로 overlap은 청킹 크기를 초과할 수 없습니다. Bean Validation으로 빠르게 실패시키고, 스키마에도 CHECK 제약을 고려하세요. 예시(클래스 내부에 추가): import jakarta.validation.constraints.AssertTrue
@get:AssertTrue(message = "overlapSize must be <= chunkingSize")
val isValidOverlap: Boolean
get() = overlapSize <= chunkingSizeAlso applies to: 28-31 🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그냥 나중에 서비스 단에서 검증해도 되겠죠? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @catturtle123 네, 맞습니다! 서비스 레이어에서 검증하는 것도 충분히 좋은 접근법입니다. 서비스 레이어에서 검증하면 더 구체적인 에러 메시지를 제공할 수 있고, 비즈니스 로직과 함께 관리하기도 편하죠. 엔티티 레벨 검증은 선택사항이니까 나중에 필요하다고 느끼시면 그때 추가하셔도 됩니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그럼 나중에 제가 chunking embedding 저장 관련 PR 올렸을때 언질해주세요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @catturtle123 네, 알겠습니다! chunking embedding 저장 관련 PR에서 overlapSize ≤ chunkingSize 검증 로직을 서비스 레이어에 추가하는 것을 잊지 않고 언급해드리겠습니다. ✏️ Learnings added
🧠 Learnings used |
||||||||||||
|
|
||||||||||||
| @Column(name = "similarity_metric", nullable = false) | ||||||||||||
| @Enumerated(EnumType.STRING) | ||||||||||||
| val similarityMetric: SimilarityMetric, | ||||||||||||
|
|
||||||||||||
| @Column(name = "top_k", nullable = false) | ||||||||||||
| @Min(1) | ||||||||||||
| val topK: Int, | ||||||||||||
|
|
||||||||||||
| @Column(name = "embedding_model", nullable = false, length = 255) | ||||||||||||
| @Enumerated(EnumType.STRING) | ||||||||||||
| val embeddingModel: EmbeddingModel, | ||||||||||||
|
|
||||||||||||
| @Column(name = "reranker", nullable = false) | ||||||||||||
| val reranker: Boolean, | ||||||||||||
|
|
||||||||||||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||||||||||
| @Column(name = "indexes_id") | ||||||||||||
| val id: Long? = null, | ||||||||||||
|
Comment on lines
+39
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) id 컬럼 명시는 선택 사항 — 컨벤션 일관성 검토 다른 엔티티(Tag/DataFile)는 기본 컬럼명( 예시(선택): - @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "indexes_id")
- val id: Long? = null,
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ val id: Long? = null,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| ): BaseEntity() | ||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||||||||||||||
| package simplerag.ragback.domain.index.entity.enums | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| enum class EmbeddingModel( | ||||||||||||||||||||||||||||||||||||||
| val dim: Int, | ||||||||||||||||||||||||||||||||||||||
| val modelId: String | ||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) toString 오버라이드로 로깅/표시 안정성 향상 (선택) 운영 로그/에러 메시지 가독성을 위해 🤖 Prompt for AI Agents🧹 Nitpick (assertive) Provider 메타데이터 추가를 고려해 주세요 (OPENAI/HF/MISTRAL 등) API 라우팅, 레이트리밋/자격증명 분리, 로깅 필터링을 위해 🤖 Prompt for AI Agents🧹 Nitpick (assertive) JPA 저장 전략 재검토 — Enum 이름 변경 리스크 완화 AI 요약에 따르면 Index 엔티티에서 다음 예시는 Converter 스켈레톤입니다: import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
import simplerag.ragback.domain.index.entity.enums.EmbeddingModel
@Converter(autoApply = false)
class EmbeddingModelConverter : AttributeConverter<EmbeddingModel, String> {
override fun convertToDatabaseColumn(attribute: EmbeddingModel?): String? =
attribute?.modelId
override fun convertToEntityAttribute(dbData: String?): EmbeddingModel? =
dbData?.let { EmbeddingModel.findByModelId(it) }
}엔티티 필드에 🤖 Prompt for AI Agents
Comment on lines
+1
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) JPA 영속 안정성 강화: enum 이름 대신 modelId로 저장하도록 Converter 전환 권장 AI 요약상 Index 엔티티에서 예시 Converter: import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
@Converter(autoApply = false)
class EmbeddingModelConverter : AttributeConverter<EmbeddingModel, String> {
override fun convertToDatabaseColumn(attribute: EmbeddingModel?): String? =
attribute?.modelId
override fun convertToEntityAttribute(dbData: String?): EmbeddingModel? =
dbData?.let { EmbeddingModel.findByModelId(it) }
}엔티티 필드 적용 예시: @Convert(converter = EmbeddingModelConverter::class)
@Column(name = "embedding_model", nullable = false)
var embeddingModel: EmbeddingModel이후에는 enum 상수명을 정리(예: MPNET 표기)하더라도 DB 값(=modelId)은 변하지 않아 안전합니다. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| // OpenAI | ||||||||||||||||||||||||||||||||||||||
| TEXT_EMBEDDING_3_SMALL(1536, "text-embedding-3-small"), | ||||||||||||||||||||||||||||||||||||||
| TEXT_EMBEDDING_3_LARGE(3072, "text-embedding-3-large"), | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // SBERT / HuggingFace | ||||||||||||||||||||||||||||||||||||||
| ALL_MINILM_L6_V2(384, "sentence-transformers/all-MiniLM-L6-v2"), | ||||||||||||||||||||||||||||||||||||||
| ALL_MP_NET_BASE_V2(768, "sentence-transformers/all-mpnet-base-v2"), | ||||||||||||||||||||||||||||||||||||||
| MULTI_QA_MP_NET_BASE_DOT_V1(768, "sentence-transformers/multi-qa-mpnet-base-dot-v1"), | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 상수명 일관성(Nit): MPNET 철자 통일 고려
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| DISTILUSE_BASE_MULTILINGUAL_CASED_V2(512, "sentence-transformers/distiluse-base-multilingual-cased-v2"), | ||||||||||||||||||||||||||||||||||||||
| PARAPHRASE_MULTILINGUAL_MINILM_L12_V2(384, "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"), | ||||||||||||||||||||||||||||||||||||||
| KO_SBERT_V1(768, "jhgan/ko-sbert-v1"), | ||||||||||||||||||||||||||||||||||||||
| KOR_SROBERTA(768, "jhgan/ko-sroberta-medium-nli"), | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Korean specific | ||||||||||||||||||||||||||||||||||||||
| BM_KO_SMALL(512, "bespin-global/klue-sroberta-base-continue-learning-by-mnr"), | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Instructor / Mistral | ||||||||||||||||||||||||||||||||||||||
| INSTRUCTOR_BASE(768, "hkunlp/instructor-base"), | ||||||||||||||||||||||||||||||||||||||
| INSTRUCTOR_XL(1024, "hkunlp/instructor-xl"), | ||||||||||||||||||||||||||||||||||||||
| MISTRAL_EMBED(1024, "mistral-embed"), | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // BGE / E5 etc | ||||||||||||||||||||||||||||||||||||||
| BGE_SMALL_EN(384, "BAAI/bge-small-en-v1.5"), | ||||||||||||||||||||||||||||||||||||||
| BGE_BASE_EN(768, "BAAI/bge-base-en-v1.5"), | ||||||||||||||||||||||||||||||||||||||
| BGE_LARGE_EN(1024, "BAAI/bge-large-en-v1.5"), | ||||||||||||||||||||||||||||||||||||||
| BGE_M3(1024, "BAAI/bge-m3"), | ||||||||||||||||||||||||||||||||||||||
| E5_SMALL(384, "intfloat/e5-small-v2"), | ||||||||||||||||||||||||||||||||||||||
| E5_BASE(768, "intfloat/e5-base-v2"), | ||||||||||||||||||||||||||||||||||||||
| E5_LARGE(1024, "intfloat/e5-large-v2"), | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+28
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain차원 수(dimension) 정확성 교차 검증 자동화 제안 HF 모델의 config에서 hidden_size를 읽어 현재 enum의 dim과 비교해 일관성을 점검하세요. 일부 모델은 구조가 달라(예: T5류의 🏁 Script executed: #!/bin/bash
set -euo pipefail
declare -A EXPECTED=(
["BAAI/bge-small-en-v1.5"]=384
["BAAI/bge-base-en-v1.5"]=768
["BAAI/bge-large-en-v1.5"]=1024
["BAAI/bge-m3"]=1024
["intfloat/e5-small-v2"]=384
["intfloat/e5-base-v2"]=768
["intfloat/e5-large-v2"]=1024
)
echo "Model,Field,ConfigValue,Expected,OK"
for m in "${!EXPECTED[@]}"; do
cfg=$(curl -fsSL "https://huggingface.co/${m}/resolve/main/config.json" || true)
if [ -z "$cfg" ]; then
echo "${m},(no-config),-,${EXPECTED[$m]},false"
continue
fi
# 우선 hidden_size, 없으면 d_model 시도
hidden=$(printf '%s' "$cfg" | jq -r 'select(.hidden_size)!=null | .hidden_size' 2>/dev/null || true)
field="hidden_size"
val="$hidden"
if [ -z "$hidden" ] || [ "$hidden" = "null" ]; then
dmodel=$(printf '%s' "$cfg" | jq -r 'select(.d_model)!=null | .d_model' 2>/dev/null || true)
field="d_model"
val="$dmodel"
fi
ok="false"
if [ "$val" = "${EXPECTED[$m]}" ]; then ok="true"; fi
echo "${m},${field},${val},${EXPECTED[$m]},${ok}"
doneLength of output: 23128 자동 차원 검증 테스트/CI 스크립트 추가 권장 현재
예시 스크립트: #!/usr/bin/env bash
set -euo pipefail
declare -A EXPECTED=(
[BAAI/bge-small-en-v1.5]=384
[BAAI/bge-base-en-v1.5]=768
# …생략…
)
for m in "${!EXPECTED[@]}"; do
cfg_url="https://huggingface.co/${m}/resolve/main/config.json"
dim=$(curl -fsSL "$cfg_url" \
| jq -r 'if has("hidden_size") then .hidden_size else .d_model end')
if [ "$dim" -ne "${EXPECTED[$m]}" ]; then
echo "ERROR: $m expected=${EXPECTED[$m]} actual=$dim"
exit 1
fi
done참고: T5 계열처럼 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Old word vectors | ||||||||||||||||||||||||||||||||||||||
| FASTTEXT_KO(300, "fasttext-ko-300d"); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| companion object { | ||||||||||||||||||||||||||||||||||||||
| fun findByModelId(modelId: String): EmbeddingModel? { | ||||||||||||||||||||||||||||||||||||||
| return entries.find { it.modelId == modelId } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| fun getAllModelIds(): List<String> { | ||||||||||||||||||||||||||||||||||||||
| return entries.map { it.modelId } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion O(n) 선형 탐색 제거 및 Kotlin 버전 호환성 보강 (
- companion object {
- fun findByModelId(modelId: String): EmbeddingModel? {
- return entries.find { it.modelId == modelId }
- }
-
- fun getAllModelIds(): List<String> {
- return entries.map { it.modelId }
- }
- }
+ companion object {
+ private val ALL: Array<EmbeddingModel> = values()
+ private val BY_MODEL_ID: Map<String, EmbeddingModel> = ALL.associateBy { it.modelId }
+
+ @JvmStatic
+ fun findByModelId(modelId: String): EmbeddingModel? = BY_MODEL_ID[modelId]
+
+ @JvmStatic
+ fun getAllModelIds(): List<String> = ALL.map { it.modelId }
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 간단한 단위 테스트 추가 제안
원하시면 테스트 템플릿 생성해 드리겠습니다. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,9 @@ | ||||||||||||||||||||||||||||||||
| package simplerag.ragback.domain.index.entity.enums | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| enum class SimilarityMetric( | ||||||||||||||||||||||||||||||||
| val description: String | ||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||
| COSINE("코사인 유사도"), | ||||||||||||||||||||||||||||||||
| EUCLIDEAN("유클리드 거리"), | ||||||||||||||||||||||||||||||||
| DOT_PRODUCT("내적 유사도") | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 유사도 메트릭 enum 추가는 적절하나, 도메인 계층에 사용자 노출 문자열을 하드코딩하면 i18n/문구 변경에 취약 라벨을 바로 한글로 포함하기보다, 메시지 키를 함께 보관하고 표현 계층에서 국제화 리소스로 치환하는 방식을 권장합니다. 하위 호환에 주의하여 적용하세요. 예시(메시지 키 추가): -enum class SimilarityMetric(
- val description: String
-) {
- COSINE("코사인 유사도"),
- EUCLIDEAN("유클리드 거리"),
- DOT_PRODUCT("내적 유사도")
-}
+enum class SimilarityMetric(
+ val description: String,
+ val messageKey: String
+) {
+ COSINE("코사인 유사도", "similarity.cosine"),
+ EUCLIDEAN("유클리드 거리", "similarity.euclidean"),
+ DOT_PRODUCT("내적 유사도", "similarity.dotProduct")
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package simplerag.ragback.domain.prompt.entity | ||
|
|
||
| import jakarta.persistence.* | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
|
|
||
| @Entity | ||
| @Table(name = "few_shots") | ||
| class FewShot( | ||
|
|
||
| @Column(name = "question", nullable = false, length = 255) | ||
| val question: String, | ||
|
|
||
| @Column(name = "answer", nullable = false) | ||
| @Lob | ||
| val answer: String, | ||
|
|
||
| @Column(name = "evidence", nullable = false) | ||
| @Lob | ||
| val evidence: String, | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "prompts_id", nullable = false) | ||
| val prompt: Prompt, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "few_shots_id") | ||
| val id: Long? = null, | ||
| ): BaseEntity() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package simplerag.ragback.domain.prompt.entity | ||
|
|
||
| import jakarta.persistence.* | ||
| import simplerag.ragback.domain.prompt.entity.enums.PreSet | ||
| import simplerag.ragback.global.entity.BaseEntity | ||
|
|
||
| @Entity | ||
| @Table(name = "prompts") | ||
| class Prompt( | ||
|
|
||
| @Column(name = "name", length = 100, nullable = false) | ||
| val name: String, | ||
|
|
||
| @Enumerated(EnumType.STRING) | ||
| @Column(name = "pre_set", nullable = false) | ||
| val preSet: PreSet, | ||
|
|
||
| @Column(name = "system_prompt", nullable = false) | ||
| @Lob | ||
| val systemPrompt: String, | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @Column(name = "prompts_id") | ||
| val id: Long? = null, | ||
| ): BaseEntity() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package simplerag.ragback.domain.prompt.entity.enums | ||
|
|
||
| enum class PreSet { | ||
| NONE | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.