kimrang commited on
Commit
ba341ea
·
verified ·
1 Parent(s): 97c8d04

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +25 -0
  2. app.py +488 -0
  3. gitattributes +13 -0
  4. requirements.txt +7 -0
README.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: 한남대학교 Q&A
3
+ emoji: 🏫
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 5.32.1
8
+ app_file: app.py
9
+ pinned: false
10
+ license: apache-2.0
11
+ ---
12
+
13
+ # 한남대학교 규정집 Q&A
14
+
15
+ 한남대학교 규정집에 대한 질문-답변 시스템입니다.
16
+
17
+ ## 사용 방법
18
+ 1. 드롭다운에서 자주 묻는 질문을 선택하거나
19
+ 2. 직접 질문을 입력하세요
20
+ 3. AI 모델을 선택하고 "답변 받기" 버튼을 클릭하세요
21
+
22
+ ## 기능
23
+ - 한남대학교 규정집 기반 질문 답변
24
+ - 자주 묻는 질문 드롭다운
25
+ - 다양한 AI 모델 선택 가능
app.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import urllib3
4
+ from langchain_groq import ChatGroq
5
+ from langchain.chains import RetrievalQA
6
+ from langchain.prompts import PromptTemplate
7
+ from langchain.vectorstores import FAISS
8
+ from langchain.embeddings import HuggingFaceEmbeddings
9
+
10
+ # SSL 경고 제거
11
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
12
+
13
+ # Groq API 키 (Hugging Face Secrets에서 가져옴)
14
+ GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
15
+
16
+ # 전역 변수들
17
+ vectorstores = {}
18
+ embeddings = None
19
+ combined_vectorstore = None
20
+
21
+ def debug_file_system():
22
+ """파일 시스템 상태를 자세히 확인하는 함수"""
23
+ import os
24
+ print("=" * 50)
25
+ print("🔍 파일 시스템 디버깅 시작")
26
+ print("=" * 50)
27
+
28
+ # 현재 디렉토리
29
+ current_dir = os.getcwd()
30
+ print(f"📂 현재 작업 디렉토리: {current_dir}")
31
+
32
+ # 루트 디렉토리의 모든 항목
33
+ try:
34
+ all_items = os.listdir('.')
35
+ print(f"📋 루트 디렉토리 내용: {all_items}")
36
+
37
+ # 각 항목의 타입 확인
38
+ for item in all_items:
39
+ item_path = os.path.join('.', item)
40
+ if os.path.isdir(item_path):
41
+ print(f"📁 {item} (디렉토리)")
42
+ try:
43
+ sub_items = os.listdir(item_path)
44
+ print(f" └── 내용: {sub_items}")
45
+ except Exception as e:
46
+ print(f" └── 접근 불가: {e}")
47
+ else:
48
+ print(f"📄 {item} (파일)")
49
+
50
+ except Exception as e:
51
+ print(f"❌ 디렉토리 읽기 오류: {e}")
52
+
53
+ # 환경 변수 확인
54
+ print(f"🔑 GROQ_API_KEY 설정됨: {'GROQ_API_KEY' in os.environ}")
55
+
56
+ print("=" * 50)
57
+
58
+ # 앱 시작 시 디버깅 실행
59
+ debug_file_system()
60
+
61
+ def find_vectorstore_folders():
62
+ """현재 디렉토리에서 벡터스토어 폴더들을 찾는 함수 - 개선 버전"""
63
+ current_dir = os.getcwd()
64
+ print(f"현재 디렉토리: {current_dir}")
65
+
66
+ # 모든 파일과 폴더 확인
67
+ try:
68
+ all_items = os.listdir(current_dir)
69
+ print(f"현재 디렉토리 내 모든 항목들: {all_items}")
70
+ except Exception as e:
71
+ print(f"디렉토리 읽기 오류: {e}")
72
+ return []
73
+
74
+ # 예상되는 벡터스토어 폴더들
75
+ expected_folders = ['vectorstore1', 'vectorstore2', 'vectorstore3']
76
+ vectorstore_folders = []
77
+
78
+ # 실제로 존재하는 벡터스토어 관련 폴더들도 찾기
79
+ for item in all_items:
80
+ if os.path.isdir(item) and ('vectorstore' in item.lower() or 'vector' in item.lower()):
81
+ expected_folders.append(item)
82
+
83
+ # 중복 제거
84
+ expected_folders = list(set(expected_folders))
85
+ print(f"확인할 폴더들: {expected_folders}")
86
+
87
+ for folder_name in expected_folders:
88
+ folder_path = os.path.join(current_dir, folder_name)
89
+ if os.path.exists(folder_path) and os.path.isdir(folder_path):
90
+ try:
91
+ folder_contents = os.listdir(folder_path)
92
+ print(f"📁 {folder_name} 폴더 내용: {folder_contents}")
93
+
94
+ # FAISS 파일들 확인 (더 유연하게)
95
+ has_faiss = any('.faiss' in file for file in folder_contents)
96
+ has_pkl = any('.pkl' in file for file in folder_contents)
97
+
98
+ if has_faiss and has_pkl:
99
+ vectorstore_folders.append(folder_name)
100
+ print(f"✅ {folder_name} - FAISS 파일들 존재")
101
+ elif has_faiss or has_pkl:
102
+ print(f"⚠️ {folder_name} - 일부 파일만 존재 (faiss: {has_faiss}, pkl: {has_pkl})")
103
+ # 일부만 있어도 시도해보기
104
+ vectorstore_folders.append(folder_name)
105
+ else:
106
+ print(f"❌ {folder_name} - FAISS 파일들 없음")
107
+
108
+ except Exception as e:
109
+ print(f"❌ {folder_name} 폴더 확인 중 오류: {e}")
110
+ else:
111
+ print(f"❌ {folder_name} 폴더가 존재하지 않음")
112
+
113
+ if not vectorstore_folders:
114
+ print("❌ 사용 가능한 벡터스토어 폴더를 찾을 수 없습니다")
115
+ # 디버깅을 위해 현재 디렉토리의 모든 하위 폴더 출력
116
+ print("📋 현재 디렉토리의 모든 폴더들:")
117
+ for item in all_items:
118
+ if os.path.isdir(item):
119
+ print(f" 📁 {item}")
120
+ else:
121
+ print(f"✅ 총 {len(vectorstore_folders)}개의 벡터스토어 폴더를 찾았습니다: {vectorstore_folders}")
122
+
123
+ return vectorstore_folders
124
+
125
+ def load_all_vectorstores():
126
+ """모든 벡터스토어를 로드하고 통합하는 함수 - 개선 버전"""
127
+ global vectorstores, embeddings, combined_vectorstore
128
+
129
+ print("🔄 벡터스토어 로딩 시작...")
130
+
131
+ # 임베딩 모델 초기화
132
+ if not embeddings:
133
+ try:
134
+ print("🤖 임베딩 모델 로딩 중...")
135
+ embeddings = HuggingFaceEmbeddings(
136
+ model_name="jhgan/ko-sbert-nli"
137
+ )
138
+ print("✅ 임베딩 모델 로딩 완료")
139
+ except Exception as e:
140
+ print(f"❌ 임베딩 모델 로딩 실패: {e}")
141
+ return False
142
+
143
+ # 벡터스토어 폴더들 찾기
144
+ folders = find_vectorstore_folders()
145
+
146
+ if not folders:
147
+ print("❌ 벡터스토어 폴더를 찾을 수 없습니다")
148
+ return False
149
+
150
+ loaded_vectorstores = []
151
+
152
+ for folder_name in folders:
153
+ folder_path = f"./{folder_name}"
154
+ try:
155
+ print(f"📂 {folder_name} 로딩 시도 중...")
156
+
157
+ # 다양한 방법으로 로딩 시도
158
+ vectorstore = None
159
+
160
+ # 방법 1: 기본 로딩
161
+ try:
162
+ vectorstore = FAISS.load_local(
163
+ folder_path,
164
+ embeddings,
165
+ allow_dangerous_deserialization=True
166
+ )
167
+ print(f"✅ {folder_name} 로드 완료 (방법 1)")
168
+ except Exception as e1:
169
+ print(f"⚠️ 방법 1 실패: {e1}")
170
+
171
+ print("현재 작업 디렉토리:", os.getcwd())
172
+ print("폴더 경로 존재 여부:", os.path.exists(folder_path))
173
+
174
+
175
+ # 방법 2: 절대 경로로 시도
176
+ try:
177
+ abs_path = os.path.abspath(folder_name)
178
+ vectorstore = FAISS.load_local(
179
+ abs_path,
180
+ embeddings,
181
+ allow_dangerous_deserialization=True
182
+ )
183
+ print(f"✅ {folder_name} 로드 완료 (방법 2)")
184
+ except Exception as e2:
185
+ print(f"⚠️ 방법 2 실패: {e2}")
186
+
187
+ print("index.faiss 존재 여부:", os.path.exists(os.path.join(folder_path, "index.faiss")))
188
+ print("index.pkl 존재 여부:", os.path.exists(os.path.join(folder_path, "index.pkl")))
189
+
190
+
191
+ # 방법 3: 직접 파일 지정
192
+ try:
193
+ index_file = os.path.join(folder_name, "index.faiss")
194
+ pkl_file = os.path.join(folder_name, "index.pkl")
195
+
196
+ if os.path.exists(index_file) and os.path.exists(pkl_file):
197
+ vectorstore = FAISS.load_local(
198
+ folder_name,
199
+ embeddings,
200
+ allow_dangerous_deserialization=True
201
+ )
202
+ print(f"✅ {folder_name} 로드 완료 (방법 3)")
203
+ else:
204
+ print(f"❌ 필수 파일 없음: {index_file}, {pkl_file}")
205
+ except Exception as e3:
206
+ print(f"❌ 방법 3 실패: {e3}")
207
+
208
+ if vectorstore:
209
+ vectorstores[folder_name] = vectorstore
210
+ loaded_vectorstores.append(vectorstore)
211
+
212
+ # 벡터스토어 정보 출력
213
+ try:
214
+ doc_count = vectorstore.index.ntotal
215
+ print(f"📊 {folder_name}: {doc_count}개 문서")
216
+ except:
217
+ print(f"📊 {folder_name}: 문서 수 확인 불가")
218
+ else:
219
+ print(f"❌ {folder_name} 로드 실패")
220
+
221
+ except Exception as e:
222
+ print(f"❌ {folder_name} 로드 중 예외 발생: {e}")
223
+ import traceback
224
+ traceback.print_exc()
225
+
226
+ # 벡터스토어들을 통합
227
+ if loaded_vectorstores:
228
+ try:
229
+ print("🔗 벡터스토어 통합 시작...")
230
+ combined_vectorstore = loaded_vectorstores[0]
231
+
232
+ for i, vs in enumerate(loaded_vectorstores[1:], 1):
233
+ try:
234
+ combined_vectorstore.merge_from(vs)
235
+ print(f"✅ 벡터스토어 {i+1} 통합 완료")
236
+ except Exception as e:
237
+ print(f"❌ 벡터스토어 {i+1} 통합 실패: {e}")
238
+
239
+ print(f"🎉 총 {len(loaded_vectorstores)}개의 벡터스토어가 로드되고 통합되었습니다")
240
+ return True
241
+
242
+ except Exception as e:
243
+ print(f"❌ 벡터스토어 통합 중 오류: {e}")
244
+ # 통합 실패시 첫 번째 것만 사용
245
+ if loaded_vectorstores:
246
+ combined_vectorstore = loaded_vectorstores[0]
247
+ print("⚠️ 첫 번째 벡터스토어만 사용합니다")
248
+ return True
249
+
250
+ print("❌ 사용 가능한 벡터스토어가 없습니다")
251
+ return False
252
+
253
+ # 질문 리스트
254
+ suggested_questions = [
255
+
256
+ '한남대학교의 수업일수를 알고 싶어요',
257
+ '한남대학교의 정기휴업일은 언제인가요?',
258
+ '대학원의 입학 시기는 언제인가요?',
259
+ '학석사연계과정에 대해 설명해주세요',
260
+ '자랑스러운한남인상 시상 기준이 무엇인가요?',
261
+ '공익신고 신고자의 절차는 무엇인가요?',
262
+ ' 기숙사 입사 자격은 무엇인가요?',
263
+ '중앙도서관의 이용자격은 무엇인가요?',
264
+ '캡스톤디자인 과목의 이수자격은 어떻게 되나요?.',
265
+ '캡스톤디자인의 성적 평가에 대해 알고 싶어요',
266
+ '교원 신규 임용은 어떻게 하나요?',
267
+ '교원 연구년 기간은 어떻게 되나요?',
268
+ '조교 신규 임용 기준은 무엇인가요?',
269
+ '교직원의 평일 근무시간은 어떻게 되나요?',
270
+ '직원 신규 임용 원칙은 무엇인가요?',
271
+ '직원 임용시 가산점이 있나요?',
272
+ '교원 업적의 심사 내용은 무엇인가요?',
273
+ '외국인 교원의 임기는 어떻게 되나요?',
274
+ '외국인 교원의 면직 기준은 무엇인가요?',
275
+ '기간제 계약직의 임기는 얼마정도인가요?',
276
+ '등록금 납부 방법은 무엇인가요?',
277
+ '교직 이수는 언제 신청이 가능한가요?',
278
+ '해외교류유학 지원자격은 어떻게 되나요?',
279
+ '만족도 조사 실행 대상은 누구인가요?',
280
+ '마이크로디그리의 유형은 무엇이 있나요?',
281
+ '장학금 관리 기관은 어디인가요?',
282
+ '학생 단체는 어떻게 등록하나요?',
283
+ '학생 설치물 중 금지된 설치물이 있나요?',
284
+ '비교과 교육과정의 종류는 무엇이 있나요?',
285
+ '안전사고예방계획은 어디에 제출해야 하나요?',
286
+ '평생교육원에서 무엇을 배우나요?.',
287
+ '한남미디어센터의 운영 시간이 어떻게 되나요?',
288
+ '한남대학교회의 예배 일정이 어떻게 되나요?',
289
+ '교육연구소가 하는 일이 무엇인가요?',
290
+ '한남대학교의 장기발전계획을 어떤 과정으로 수립하나요?',
291
+ '산학협력단의 목적이 무엇인가요?',
292
+ '외부연구비를 지원받고 싶은데 기준이 무엇인가요?',
293
+ '연구노트 작성 요건이 무엇인가요?',
294
+ '보안등급 분류, 심사 기준이 무엇인가요?',
295
+ '창업을 하고 싶은데 창업보육센터의 입주 가능 기준이 무엇인가요?',
296
+ '특허를 내려고 하는데 어떻게 해야하나요?',
297
+ '한남대학교와 관련한 중소기업에 대해 알고 싶어요.',
298
+ '가족회사가 어떤 의미인가요?',
299
+ '이번에 학교측 장비를 사용하게 됐는데 규정을 알고 싶어요.',
300
+ '기술지주회사의 목적이 무엇인가요?',
301
+ '계약학과가 어떤 과정을 통해 생겨나게 되나요?',
302
+ '학교에 물품 구매 요청을 하고 싶은데 어떻게 해야하나요?',
303
+ '이번에 총학생회에 들어가게 됐는데 회칙에 대해 자세히 알고싶어요.',
304
+ '학군단의 교육이나 학점에 대해 알고싶어요.',
305
+ '중앙 박물관의 소장품 파손과 관련된 규정이 무엇인가요?'
306
+ ]
307
+
308
+ # 프롬프트 템플릿
309
+ prompt_template = """당신은 한남대학교 규정집 도우미입니다.
310
+ 반드시 한국어로만 답변해주세요. 영어나 다른 언어는 절대 사용하지 마세요.
311
+ 주어진 문서 내용을 바탕으로 질문에 대해 정확하고 친절하게 한국어로 답변해주세요.
312
+ 참고 문서:
313
+ {context}
314
+ 질문: {question}
315
+ 답변 지침:
316
+ - 이용자를 반기는 인사로 시작하세요
317
+ - 반드시 한국어로만 답변하세요
318
+ - 정중하고 친근한 말투를 사용하세요
319
+ - 구체적이고 도움이 되는 정보를 제공하세요
320
+ - 문서에서 답을 찾을 수 없으면 "죄송하지만 해당 정보를 규정집에서 찾을 수 없습니다"라고 답변하세요
321
+ 한국어 답변:"""
322
+
323
+ prompt = PromptTemplate(
324
+ template=prompt_template,
325
+ input_variables=["context", "question"]
326
+ )
327
+
328
+ def respond_with_groq(question, selected_q, model):
329
+ """질문에 대한 답변을 생성하는 함수 - 개선 버전"""
330
+
331
+ # 선택된 질문이 있으면 그것을 사용
332
+ if selected_q != "직접 입력":
333
+ question = selected_q
334
+
335
+ if not question.strip():
336
+ return "질문을 입력해주세요."
337
+
338
+ if not GROQ_API_KEY:
339
+ return "❌ GROQ API 키가 설정되지 않았습니다. Hugging Face Spaces의 Settings에서 GROQ_API_KEY를 설정해주세요."
340
+
341
+ # 통합된 벡터스토어가 로드되지 않은 경우 재시도
342
+ if not combined_vectorstore:
343
+ print("⚠️ 벡터스토어가 로드되지 않음. 재로딩 시도...")
344
+ success = load_all_vectorstores()
345
+ if not success:
346
+ # 디버깅 정보 출력
347
+ debug_file_system()
348
+ return """❌ 벡터스토어를 로드할 수 없습니다.
349
+
350
+ 가능한 원인:
351
+ 1. 벡터스토어 파일이 올바르게 업로드되지 않음
352
+ 2. 파일 권한 문제
353
+ 3. Git LFS 설정 필요 (큰 파일의 경우)
354
+ 해결 방법:
355
+ 1. vectorstore 폴더들이 제대로 업로드되었는지 확인
356
+ 2. 각 폴더에 index.faiss와 index.pkl 파일이 있는지 확인
357
+ 3. Git LFS를 사용해 큰 파일들을 관리해보세요"""
358
+
359
+ try:
360
+ print(f"🔍 질문: {question}")
361
+ print(f"✅ 통합된 벡터스토어를 사용하여 검색 중...")
362
+
363
+ # LLM 설정
364
+ llm = ChatGroq(
365
+ groq_api_key=GROQ_API_KEY,
366
+ model_name=model,
367
+ temperature=0.1,
368
+ max_tokens=1000
369
+ )
370
+
371
+ # 검색 테스트
372
+ try:
373
+ print(f"🔍 질문: {question}")
374
+ retriever = combined_vectorstore.as_retriever(
375
+ search_type="mmr",
376
+ search_kwargs={"k": 10, "lambda_mult": 0.5}
377
+ )
378
+ print(f"🔍 질문: {question}")
379
+ docs = retriever.invoke(question)
380
+ print(f"🔍 검색된 문서 수: {len(docs)}")
381
+ except Exception as e:
382
+ print(f"❌ 검색 오류: {e}")
383
+ return f"❌ 문서 검색 중 오류가 발생했습니다: {str(e)}"
384
+
385
+ # QA 체인 생성
386
+ qa_chain = RetrievalQA.from_chain_type(
387
+ llm=llm,
388
+ chain_type="stuff",
389
+ retriever=combined_vectorstore.as_retriever(search_kwargs={"k": 5}),
390
+ chain_type_kwargs={"prompt": prompt},
391
+ return_source_documents=True
392
+ )
393
+
394
+ # 답변 생성
395
+ result = qa_chain({"query": question})
396
+ return result['result']
397
+
398
+ except Exception as e:
399
+ import traceback
400
+ error_details = traceback.format_exc()
401
+ print(f"❌ 상세 오류 정보:\n{error_details}")
402
+ return f"""❌ 답변 생성 중 오류가 발생했습니다: {str(e)}
403
+ 디버깅 정보:
404
+ - 벡터스토어 로드됨: {combined_vectorstore is not None}
405
+ - API 키 설정됨: {GROQ_API_KEY is not None}
406
+ - 모델: {model}
407
+ 관리자에게 위 정보와 함께 문의해주세요."""
408
+
409
+ def update_question(selected):
410
+ """드롭다운 선택 시 질문을 업데이트하는 함수"""
411
+ if selected != "직접 입력":
412
+ return selected
413
+ return ""
414
+
415
+ # 앱 시작시 벡터스토어들 로드
416
+ print("🚀 앱 시작 - 벡터스토어 로딩 중...")
417
+ vectorstores_loaded = load_all_vectorstores()
418
+
419
+ # 상태 메시지 생성
420
+ if vectorstores_loaded:
421
+ status_message = "✅ 벡터스토어가 성공적으로 로드되었습니다!"
422
+ status_color = "green"
423
+ else:
424
+ status_message = "❌ 벡터스토어 로딩에 실패했습니다. 관리자에게 문의하세요."
425
+ status_color = "red"
426
+
427
+ # Gradio 인터페이스 생성
428
+ with gr.Blocks(title="한남대학교 Q&A") as interface:
429
+ gr.HTML(f"""
430
+ <div style="text-align: center; padding: 20px; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 10px; margin-bottom: 20px;">
431
+ <h1>🏫 한남대학교 규정집 Q&A</h1>
432
+ <p>한남대학교 규정집에 대한 질문에 답변해드립니다.</p>
433
+ </div>
434
+ """)
435
+
436
+ # 상태 표시 추가
437
+ gr.HTML(f"""
438
+ <div style="text-align: center; padding: 10px; background-color: {status_color}; color: white; border-radius: 5px; margin-bottom: 10px;">
439
+ <strong>{status_message}</strong>
440
+ </div>
441
+ """)
442
+
443
+ with gr.Row():
444
+ with gr.Column(scale=1):
445
+ question_dropdown = gr.Dropdown(
446
+ choices=["직접 입력"] + suggested_questions,
447
+ label="💡 자주 묻는 질문",
448
+ value="직접 입력"
449
+ )
450
+
451
+ question_input = gr.Textbox(
452
+ label="❓ 질문을 입력하세요",
453
+ placeholder="예: 졸업 요건은 무엇인가요?",
454
+ lines=3
455
+ )
456
+
457
+ submit_btn = gr.Button("답변 받기", variant="primary", size="lg")
458
+
459
+ model_choice = gr.Radio(
460
+ choices=["llama3-70b-8192", "llama3-8b-8192"],
461
+ label="🤖 AI 모델 선택",
462
+ value="llama3-70b-8192"
463
+ )
464
+
465
+ with gr.Column(scale=2):
466
+ output = gr.Textbox(
467
+ label="💬 답변",
468
+ lines=15,
469
+ max_lines=20,
470
+ show_copy_button=True
471
+ )
472
+
473
+ # 이벤트 연결
474
+ submit_btn.click(
475
+ fn=respond_with_groq,
476
+ inputs=[question_input, question_dropdown, model_choice],
477
+ outputs=output
478
+ )
479
+
480
+ question_dropdown.change(
481
+ fn=update_question,
482
+ inputs=question_dropdown,
483
+ outputs=question_input
484
+ )
485
+
486
+ # 앱 실행
487
+ if __name__ == "__main__":
488
+ interface.launch()
gitattributes ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ hannam_qa_deployment[[:space:]](1).zip filter=lfs diff=lfs merge=lfs -text
2
+ folder_name/hannam_qa_deployment[[:space:]](1).zip filter=lfs diff=lfs merge=lfs -text
3
+ vectorstore/hannam_qa_deployment[[:space:]](1).zip filter=lfs diff=lfs merge=lfs -text
4
+ vectorstore/index[[:space:]](3).faiss filter=lfs diff=lfs merge=lfs -text
5
+ vectorstore/index[[:space:]](3).pkl filter=lfs diff=lfs merge=lfs -text
6
+ vectorstore/index.faiss filter=lfs diff=lfs merge=lfs -text
7
+ vectorstore/index.pkl filter=lfs diff=lfs merge=lfs -text
8
+ vectorstore1/index[[:space:]](3).faiss filter=lfs diff=lfs merge=lfs -text
9
+ vectorstore1/index[[:space:]](3).pkl filter=lfs diff=lfs merge=lfs -text
10
+ vectorstore1/index.faiss filter=lfs diff=lfs merge=lfs -text
11
+ vectorstore1/index.pkl filter=lfs diff=lfs merge=lfs -text
12
+ vectorstore1/index[[:space:]](1).faiss filter=lfs diff=lfs merge=lfs -text
13
+ vectorstore1/index[[:space:]](1).pkl filter=lfs diff=lfs merge=lfs -text
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio==3.50.2
2
+ langchain
3
+ langchain-community
4
+ langchain-groq
5
+ huggingface-hub
6
+ sentence-transformers
7
+ faiss-cpu