Dongjin commited on
Commit
cc4b346
·
unverified ·
1 Parent(s): 43e9f4e

벡터 DB 대시보드 관련 코드 삭제

Browse files
Files changed (1) hide show
  1. src/visualization/vector_db_loader.py +0 -296
src/visualization/vector_db_loader.py DELETED
@@ -1,296 +0,0 @@
1
- """
2
- ChromaDB 벡터 데이터베이스 로더
3
- 임베딩 벡터와 메타데이터를 추출하여 시각화용 데이터 준비
4
- """
5
-
6
- import pandas as pd
7
- import numpy as np
8
- from typing import Dict, List, Optional
9
- from langchain_chroma import Chroma
10
- from langchain_openai.embeddings import OpenAIEmbeddings
11
-
12
- from src.utils.config import RAGConfig
13
-
14
-
15
- class VectorDBLoader:
16
- """ChromaDB에서 벡터와 메타데이터를 추출하는 클래스"""
17
-
18
- def __init__(self, config: RAGConfig = None):
19
- """
20
- 초기화
21
-
22
- Args:
23
- config: RAG 설정 객체
24
- """
25
- self.config = config or RAGConfig()
26
- self.vectorstore = None
27
- self.embeddings = None
28
-
29
- self._initialize()
30
-
31
- def _initialize(self):
32
- """임베딩 모델 및 벡터스토어 초기화"""
33
- # 임베딩 모델 초기화
34
- self.embeddings = OpenAIEmbeddings(
35
- model=self.config.EMBEDDING_MODEL_NAME,
36
- openai_api_key=self.config.OPENAI_API_KEY
37
- )
38
-
39
- # 벡터스토어 연결
40
- self.vectorstore = Chroma(
41
- embedding_function=self.embeddings,
42
- persist_directory=self.config.DB_DIRECTORY,
43
- collection_name=self.config.COLLECTION_NAME
44
- )
45
-
46
- print(f"✅ ChromaDB 연결 완료")
47
- print(f" 경로: {self.config.DB_DIRECTORY}")
48
- print(f" Collection: {self.config.COLLECTION_NAME}")
49
-
50
- def get_collection_info(self) -> Dict:
51
- """
52
- Collection 기본 정보 반환
53
-
54
- Returns:
55
- dict: Collection 통계 정보
56
- """
57
- collection = self.vectorstore._collection
58
- count = collection.count()
59
-
60
- if count == 0:
61
- return {
62
- 'total_documents': 0,
63
- 'embedding_dimension': 0,
64
- 'metadata_keys': [],
65
- 'collection_name': self.config.COLLECTION_NAME
66
- }
67
-
68
- # 샘플 데이터 가져오기
69
- sample = collection.get(limit=1, include=['embeddings', 'metadatas'])
70
-
71
- # 임베딩 차원 확인
72
- embedding_dim = 0
73
- if sample.get('embeddings') is not None and len(sample['embeddings']) > 0:
74
- embedding_dim = len(sample['embeddings'][0])
75
-
76
- # 메타데이터 키 확인
77
- metadata_keys = []
78
- if sample.get('metadatas') is not None and len(sample['metadatas']) > 0:
79
- if sample['metadatas'][0]:
80
- metadata_keys = list(sample['metadatas'][0].keys())
81
-
82
- info = {
83
- 'total_documents': count,
84
- 'embedding_dimension': embedding_dim,
85
- 'metadata_keys': metadata_keys,
86
- 'collection_name': self.config.COLLECTION_NAME
87
- }
88
-
89
- return info
90
-
91
- def extract_all_data(self) -> Dict:
92
- """
93
- 모든 데이터를 추출
94
-
95
- Returns:
96
- dict: {
97
- 'embeddings': 임베딩 벡터 배열 (numpy),
98
- 'metadatas': 메타데이터 리스트,
99
- 'documents': 문서 텍스트 리스트,
100
- 'ids': 문서 ID 리스트
101
- }
102
- """
103
- print("\n데이터 추출 중...")
104
-
105
- collection = self.vectorstore._collection
106
-
107
- # 모든 데이터 가져오기
108
- results = collection.get(
109
- include=['embeddings', 'metadatas', 'documents']
110
- )
111
-
112
- # 데이터가 없는 경우 처리
113
- if not results['ids'] or len(results['ids']) == 0:
114
- print("⚠️ ChromaDB에 데이터가 없습니다!")
115
- print(" 먼저 임베딩 단계를 실행하세요: python main.py --step embed")
116
- return {
117
- 'embeddings': np.array([]),
118
- 'metadatas': [],
119
- 'documents': [],
120
- 'ids': []
121
- }
122
-
123
- # numpy array로 변환
124
- embeddings_array = np.array(results['embeddings'])
125
-
126
- print(f"✅ 총 {len(results['ids'])}개의 청크를 불러왔습니다.")
127
- if embeddings_array.ndim == 2: # 2D 배열인 경우에만
128
- print(f"✅ 임베딩 차원: {embeddings_array.shape[1]}차원")
129
-
130
- return {
131
- 'embeddings': embeddings_array,
132
- 'metadatas': results['metadatas'],
133
- 'documents': results['documents'],
134
- 'ids': results['ids']
135
- }
136
-
137
- def to_dataframe(self, data: Dict = None) -> pd.DataFrame:
138
- """
139
- 추출한 데이터를 DataFrame으로 변환
140
-
141
- Args:
142
- data: extract_all_data()의 결과 (None이면 자동 추출)
143
-
144
- Returns:
145
- pd.DataFrame: 정리된 데이터프레임
146
- """
147
- if data is None:
148
- data = self.extract_all_data()
149
-
150
- # 데이터가 없으면 빈 DataFrame 반환
151
- if len(data['ids']) == 0:
152
- return pd.DataFrame()
153
-
154
- # 기본 컬럼
155
- df = pd.DataFrame({
156
- 'id': data['ids'],
157
- 'document': data['documents'],
158
- })
159
-
160
- # 메타데이터를 개별 컬럼으로 분리
161
- if data['metadatas']:
162
- # 메타데이터의 모든 키 추출
163
- metadata_keys = set()
164
- for metadata in data['metadatas']:
165
- if metadata:
166
- metadata_keys.update(metadata.keys())
167
-
168
- # 각 메타데이터 키를 컬럼으로 추가
169
- for key in metadata_keys:
170
- df[key] = [
171
- metadata.get(key, None) if metadata else None
172
- for metadata in data['metadatas']
173
- ]
174
-
175
- # 임베딩 벡터 추가 (numpy array로)
176
- df['embedding'] = list(data['embeddings'])
177
-
178
- print(f"\n📊 DataFrame 정보:")
179
- print(f" - Shape: {df.shape}")
180
- print(f" - Columns: {df.columns.tolist()}")
181
-
182
- return df
183
-
184
- def get_metadata_stats(self, df: pd.DataFrame = None) -> Dict:
185
- """
186
- 메타데이터 통계 정보
187
-
188
- Args:
189
- df: DataFrame (None이면 자동 생성)
190
-
191
- Returns:
192
- dict: 메타데이터별 통계
193
- """
194
- if df is None or len(df) == 0:
195
- return {}
196
-
197
- stats = {}
198
-
199
- # embedding과 document 컬럼 제외
200
- metadata_cols = [col for col in df.columns
201
- if col not in ['id', 'document', 'embedding']]
202
-
203
- for col in metadata_cols:
204
- if df[col].dtype == 'object': # 범주형 데이터
205
- stats[col] = {
206
- 'type': 'categorical',
207
- 'unique_count': df[col].nunique(),
208
- 'top_values': df[col].value_counts().head(10).to_dict()
209
- }
210
- else: # 숫자형 데이터
211
- stats[col] = {
212
- 'type': 'numerical',
213
- 'mean': float(df[col].mean()),
214
- 'std': float(df[col].std()),
215
- 'min': float(df[col].min()),
216
- 'max': float(df[col].max())
217
- }
218
-
219
- return stats
220
-
221
- def print_summary(self):
222
- """데이터 요약 정보 출력"""
223
- print("\n" + "="*60)
224
- print("ChromaDB 데이터 요약")
225
- print("="*60)
226
-
227
- # Collection 정보
228
- info = self.get_collection_info()
229
- print(f"\n📦 Collection: {info['collection_name']}")
230
- print(f"📊 총 문서 수: {info['total_documents']}")
231
-
232
- # 데이터가 없으면 여기서 종료
233
- if info['total_documents'] == 0:
234
- print("\n⚠️ ChromaDB에 데이터가 없습니다!")
235
- print(" 먼저 임베딩 단계를 실행하세요:")
236
- print(" python main.py --step embed")
237
- print("="*60)
238
- return None
239
-
240
- print(f"🧮 임베딩 차원: {info['embedding_dimension']}")
241
- print(f"🏷️ 메타데이터 키: {', '.join(info['metadata_keys'])}")
242
-
243
- # DataFrame 생성
244
- df = self.to_dataframe()
245
-
246
- if len(df) == 0:
247
- print("\n⚠️ DataFrame 생성 실패")
248
- print("="*60)
249
- return None
250
-
251
- # 메타데이터 통계
252
- stats = self.get_metadata_stats(df)
253
-
254
- if stats:
255
- print("\n📈 메타데이터 분포:")
256
- for key, stat in stats.items():
257
- if stat['type'] == 'categorical':
258
- print(f"\n [{key}]")
259
- print(f" - 고유값: {stat['unique_count']}개")
260
- print(f" - 상위 값:")
261
- for val, count in list(stat['top_values'].items())[:5]:
262
- print(f" • {val}: {count}개")
263
-
264
- print("\n" + "="*60)
265
-
266
- return df
267
-
268
-
269
- # ===== 단독 실행용 =====
270
- if __name__ == "__main__":
271
- import argparse
272
-
273
- parser = argparse.ArgumentParser(description='ChromaDB 데이터 추출 및 확인')
274
- parser.add_argument(
275
- '--export',
276
- type=str,
277
- help='DataFrame을 CSV로 저장할 경로 (선택사항)'
278
- )
279
-
280
- args = parser.parse_args()
281
-
282
- # 설정 초기화
283
- config = RAGConfig()
284
-
285
- # 데이터 로더 초기화
286
- loader = VectorDBLoader(config)
287
-
288
- # 요약 정보 출력 및 DataFrame 생성
289
- df = loader.print_summary()
290
-
291
- # CSV 저장 (옵션)
292
- if df is not None and args.export:
293
- # 임베딩 벡터를 제외하고 저장 (파일 크기 때문)
294
- df_export = df.drop(columns=['embedding'])
295
- df_export.to_csv(args.export, index=False, encoding='utf-8-sig')
296
- print(f"\n✅ 데이터 저장 완료: {args.export}")