mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 10:16:24 +00:00
197 lines
5.9 KiB
Python
197 lines
5.9 KiB
Python
"""
|
|
용어집 데이터 로딩 스크립트
|
|
"""
|
|
import sys
|
|
import json
|
|
import logging
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
# 프로젝트 루트 디렉토리를 Python 경로에 추가
|
|
project_root = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
from src.models.term import Term, DocumentSource
|
|
from src.db.postgres_vector import PostgresVectorDB
|
|
from src.utils.config import load_config, get_database_url
|
|
from src.utils.embedding import EmbeddingGenerator
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def load_terms_from_json(file_path: Path) -> List[Term]:
|
|
"""
|
|
JSON 파일에서 용어 데이터 로드
|
|
|
|
Args:
|
|
file_path: JSON 파일 경로
|
|
|
|
Returns:
|
|
용어 리스트
|
|
"""
|
|
logger.info(f"JSON 파일 로딩: {file_path}")
|
|
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
|
|
terms = []
|
|
|
|
# 도메인별 데이터 처리
|
|
for domain_data in data.get("terms", []):
|
|
domain = domain_data.get("domain")
|
|
source_type = domain_data.get("source_type")
|
|
|
|
for term_data in domain_data.get("data", []):
|
|
# DocumentSource 파싱
|
|
doc_source = None
|
|
if "document_source" in term_data:
|
|
doc_source = DocumentSource(**term_data["document_source"])
|
|
|
|
# Term 객체 생성
|
|
term = Term(
|
|
term_id=term_data["term_id"],
|
|
term_name=term_data["term_name"],
|
|
normalized_name=term_data["normalized_name"],
|
|
category=term_data["category"],
|
|
definition=term_data["definition"],
|
|
context=term_data.get("context", ""),
|
|
synonyms=term_data.get("synonyms", []),
|
|
related_terms=term_data.get("related_terms", []),
|
|
document_source=doc_source,
|
|
confidence_score=term_data.get("confidence_score", 0.0),
|
|
usage_count=term_data.get("usage_count", 0),
|
|
last_updated=term_data.get("last_updated"),
|
|
embedding=None # 나중에 생성
|
|
)
|
|
|
|
terms.append(term)
|
|
|
|
logger.info(f" → {len(terms)}개 용어 로드 완료")
|
|
return terms
|
|
|
|
|
|
def generate_embeddings(
|
|
terms: List[Term],
|
|
embedding_gen: EmbeddingGenerator
|
|
) -> List[Term]:
|
|
"""
|
|
용어 임베딩 생성
|
|
|
|
Args:
|
|
terms: 용어 리스트
|
|
embedding_gen: 임베딩 생성기
|
|
|
|
Returns:
|
|
임베딩이 추가된 용어 리스트
|
|
"""
|
|
logger.info(f"임베딩 생성 시작: {len(terms)}개 용어")
|
|
|
|
# 임베딩 텍스트 준비 (용어명 + 정의 + 맥락)
|
|
texts = []
|
|
for term in terms:
|
|
text = f"{term.term_name}\n{term.definition}"
|
|
if term.context:
|
|
text += f"\n{term.context}"
|
|
texts.append(text)
|
|
|
|
# 배치 임베딩 생성
|
|
embeddings = embedding_gen.generate_embeddings_batch(texts, batch_size=50)
|
|
|
|
# 임베딩 추가
|
|
for term, embedding in zip(terms, embeddings):
|
|
term.embedding = embedding
|
|
|
|
logger.info(f" → 임베딩 생성 완료")
|
|
return terms
|
|
|
|
|
|
def main():
|
|
"""메인 함수"""
|
|
logger.info("=" * 60)
|
|
logger.info("용어집 데이터 로딩 시작")
|
|
logger.info("=" * 60)
|
|
|
|
# 1. 설정 로드
|
|
config = load_config(str(project_root / "config.yaml"))
|
|
logger.info("✓ 설정 로드 완료")
|
|
|
|
# 2. PostgreSQL 연결
|
|
db_url = get_database_url(config)
|
|
db = PostgresVectorDB(db_url)
|
|
logger.info("✓ PostgreSQL 연결 완료")
|
|
|
|
# 3. 데이터베이스 초기화
|
|
db.init_database()
|
|
logger.info("✓ 데이터베이스 초기화 완료")
|
|
|
|
# 4. 임베딩 생성기 초기화
|
|
azure_openai = config["azure_openai"]
|
|
embedding_gen = EmbeddingGenerator(
|
|
api_key=azure_openai["api_key"],
|
|
endpoint=azure_openai["endpoint"],
|
|
model=azure_openai["embedding_model"],
|
|
dimension=azure_openai["embedding_dimension"],
|
|
api_version=azure_openai["api_version"]
|
|
)
|
|
logger.info("✓ 임베딩 생성기 초기화 완료")
|
|
|
|
# 5. 용어 데이터 로딩
|
|
all_terms = []
|
|
data_dir = project_root.parent / config["data"]["terms_dir"]
|
|
|
|
for filename in config["data"]["terms_files"]:
|
|
file_path = data_dir / filename
|
|
if file_path.exists():
|
|
terms = load_terms_from_json(file_path)
|
|
all_terms.extend(terms)
|
|
else:
|
|
logger.warning(f"⚠ 파일 없음: {file_path}")
|
|
|
|
logger.info(f"✓ 총 {len(all_terms)}개 용어 로드 완료")
|
|
|
|
# 6. 임베딩 생성
|
|
all_terms = generate_embeddings(all_terms, embedding_gen)
|
|
|
|
# 7. 데이터베이스에 삽입
|
|
logger.info(f"데이터베이스 삽입 시작: {len(all_terms)}개 용어")
|
|
success_count = 0
|
|
fail_count = 0
|
|
|
|
for i, term in enumerate(all_terms, 1):
|
|
if db.insert_term(term):
|
|
success_count += 1
|
|
else:
|
|
fail_count += 1
|
|
|
|
if i % 100 == 0:
|
|
logger.info(f" 진행: {i}/{len(all_terms)} (성공: {success_count}, 실패: {fail_count})")
|
|
|
|
logger.info(f"✓ 삽입 완료: 성공 {success_count}, 실패 {fail_count}")
|
|
|
|
# 8. 통계 조회
|
|
stats = db.get_stats()
|
|
logger.info("=" * 60)
|
|
logger.info("용어집 통계")
|
|
logger.info("=" * 60)
|
|
logger.info(f"전체 용어: {stats['total_terms']}개")
|
|
logger.info(f"평균 신뢰도: {stats['avg_confidence']:.2f}")
|
|
logger.info("\n카테고리별 통계:")
|
|
for category, count in sorted(stats['by_category'].items(), key=lambda x: x[1], reverse=True):
|
|
logger.info(f" - {category}: {count}개")
|
|
|
|
logger.info("=" * 60)
|
|
logger.info("용어집 데이터 로딩 완료")
|
|
logger.info("=" * 60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except Exception as e:
|
|
logger.error(f"오류 발생: {str(e)}", exc_info=True)
|
|
sys.exit(1)
|