hallu11 commited on
Commit
0b15b8d
·
verified ·
1 Parent(s): 57b6a63

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -77
app.py CHANGED
@@ -1,5 +1,3 @@
1
- # app.py
2
-
3
  import os
4
  import fitz # PyMuPDF
5
  import gradio as gr
@@ -8,78 +6,76 @@ import numpy as np
8
  from sentence_transformers import SentenceTransformer
9
  from groq import Groq
10
 
11
- # STEP 1. Groq API 키 설정 (Spaces 환경변수 사용 권장)
12
- GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
13
- client = Groq(api_key=GROQ_API_KEY)
14
 
15
- # STEP 2. PDF 경로
16
  pdf_paths = [
17
- "pdfs/의왕단오축제.pdf",
18
- "pdfs/성인문화학교.pdf",
19
  "pdfs/횡성문화원_문화학교.pdf",
20
- "pdfs/발달장애인교육사업.pdf",
21
- "pdfs/횡성축제소개.pdf",
22
- "pdfs/어린이문화학교.pdf"
23
  ]
24
 
25
- # STEP 3. PDF 텍스트 추출
26
- def extract_texts_from_pdfs(pdf_paths):
27
- chunks = []
28
- for path in pdf_paths:
29
- try:
30
- with fitz.open(path) as doc:
31
- for page in doc:
32
- text = page.get_text().strip()
33
- if len(text) > 30:
34
- chunks.append({"text": text, "source": os.path.basename(path)})
35
- print(f"✅ 추출 성공: {path}")
36
- except Exception as e:
37
- print(f" 오류: {path} -> {e}")
38
- return chunks
39
 
40
  docs = extract_texts_from_pdfs(pdf_paths)
41
 
42
- # STEP 4. 임베딩 및 FAISS 인덱스
43
  embed_model = SentenceTransformer("jhgan/ko-sroberta-multitask")
44
- texts = [doc["text"] for doc in docs]
45
  embeddings = embed_model.encode(texts, convert_to_numpy=True, show_progress_bar=True)
46
  index = faiss.IndexFlatL2(embeddings.shape[1])
47
- index.add(np.array(embeddings))
 
48
 
49
- # STEP 5. 검색 함수
50
  def search_similar_docs(query, top_k=3):
51
- query_emb = embed_model.encode([query])[0]
52
- scores, indices = index.search(np.array([query_emb]), top_k)
53
- results = []
54
- for idx in indices[0]:
55
- results.append(docs[idx]["text"])
56
- return "\n\n".join(results)
57
 
58
- # STEP 6. Groq 질의응답
59
  def ask_with_groq(question, context):
60
- response = client.chat.completions.create(
61
  model="llama3-8b-8192",
62
  messages=[
63
- {"role": "system", "content": "너는 문화 프로그램 관련 문서 기반 한국어 Q&A 챗봇이."},
64
- {"role": "user", "content": f"{question}\n\n[관련 문서 발췌]\n{context[:3000]}"}
65
  ]
66
  )
67
- return response.choices[0].message.content
68
 
69
- # STEP 7. 챗봇 함수
70
  chat_history = []
71
 
72
- def chatbot_fn(message, keyword):
73
  global chat_history
74
- message = message.strip()
75
- if not message:
76
  return "", chat_history
 
77
  context = search_similar_docs(message)
78
  if not context:
79
- chat_history.append(("🙋‍♂️ " + message, "❌ 관련 문서를 찾지 못했습니다."))
80
- return "", chat_history
81
- response = ask_with_groq(message, context)
82
- chat_history.append(("🙋‍♂️ " + message, "🤖 " + response))
83
  return "", chat_history
84
 
85
  def clear_chat():
@@ -87,36 +83,18 @@ def clear_chat():
87
  chat_history = []
88
  return chat_history
89
 
90
- # STEP 8. Gradio UI
91
- suggested_questions = [
92
- "의왕단축제는 언제 열리나요?",
93
- "성인화학교 교육 대상은 누구인가요?",
94
- "횡성문화원 문화학교는 어떤 수업이 있나요?",
95
- "꿈꾸는 마을 프로그램은 어떤 지원을 하나요?",
96
- "어린이 문화학교는 몇 세부터 참여 가능한가요?"
97
- ]
98
-
99
- with gr.Blocks(title="📘 오아시스 문화 챗봇") as demo:
100
- gr.Markdown("## 📘 오아시스 문서 기반 문화 프로그램 챗봇 🤖 '뮤지스(Musesis)'")
101
- gr.Markdown("질문을 입력하면 유사 문서를 검색해 답변해줍니다. (업로드 없이 사용 가능)")
102
-
103
- chatbot = gr.Chatbot(label="🤖 챗봇 응답", height=400)
104
- with gr.Row():
105
- keyword_input = gr.Textbox(label="🔍 키워드 (선택)", placeholder="예: 단오축제, 문화학교")
106
- user_input = gr.Textbox(label="✉️ 질문", placeholder="질문을 입력하세요", lines=1)
107
- with gr.Row():
108
- send_btn = gr.Button("질문하기")
109
- clear_btn = gr.Button("대화 초기화")
110
 
111
- send_btn.click(chatbot_fn, inputs=[user_input, keyword_input], outputs=[user_input, chatbot])
112
- user_input.submit(chatbot_fn, inputs=[user_input, keyword_input], outputs=[user_input, chatbot])
113
- clear_btn.click(clear_chat, outputs=chatbot)
 
114
 
115
- with gr.Accordion("💡 추천 질문", open=False):
116
- for q in suggested_questions:
117
- q_btn = gr.Button(q)
118
- def ask_suggested(q=q):
119
- return chatbot_fn(q, "")
120
- q_btn.click(ask_suggested, outputs=[user_input, chatbot])
121
 
122
  demo.launch()
 
 
 
1
  import os
2
  import fitz # PyMuPDF
3
  import gradio as gr
 
6
  from sentence_transformers import SentenceTransformer
7
  from groq import Groq
8
 
9
+ # 🌟 환경변수
10
+ os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY", "YOUR_GROQ_KEY")
11
+ client = Groq(api_key=os.environ["GROQ_API_KEY"])
12
 
13
+ # 📚 PDF 파일 위치 (Spaces 에서 "pdfs/" 폴더를 사용)
14
  pdf_paths = [
15
+ "pdfs/의왕단오축제 _ 의왕문화원.pdf",
16
+ "pdfs/성인 문화학교 _ 의왕문화원.pdf",
17
  "pdfs/횡성문화원_문화학교.pdf",
18
+ "pdfs/발달장애인 교육사업 _ 꿈꾸는 마을.pdf",
19
+ "pdfs/횡성의지역축제 - 횡성축제소개.pdf",
20
+ "pdfs/어린이 문화학교 _ 의왕문화원.pdf"
21
  ]
22
 
23
+ # 📝 PDF에서 페이지별 텍스트 추출
24
+ def extract_texts_from_pdfs(paths):
25
+ docs = []
26
+ for path in paths:
27
+ if not os.path.exists(path):
28
+ print("⚠️ 파일 없음:", path)
29
+ continue
30
+ doc = fitz.open(path)
31
+ for pg in doc:
32
+ text = pg.get_text().strip()
33
+ if len(text) > 30:
34
+ docs.append({"text": text, "source": os.path.basename(path)})
35
+ print("👉 문서 조각 수:", len(docs))
36
+ return docs
37
 
38
  docs = extract_texts_from_pdfs(pdf_paths)
39
 
40
+ # 🧠 임베딩 및 FAISS
41
  embed_model = SentenceTransformer("jhgan/ko-sroberta-multitask")
42
+ texts = [d["text"] for d in docs]
43
  embeddings = embed_model.encode(texts, convert_to_numpy=True, show_progress_bar=True)
44
  index = faiss.IndexFlatL2(embeddings.shape[1])
45
+ index.add(embeddings)
46
+ print("✅ FAISS 색인 완료:", index.ntotal)
47
 
48
+ # 🔎 유사 문서 검색
49
  def search_similar_docs(query, top_k=3):
50
+ q_emb = embed_model.encode([query])[0]
51
+ scores, idxs = index.search(np.array([q_emb]), top_k)
52
+ return "\n\n".join([texts[i] for i in idxs[0]])
 
 
 
53
 
54
+ # 🤖 Groq 기반 응답
55
  def ask_with_groq(question, context):
56
+ resp = client.chat.completions.create(
57
  model="llama3-8b-8192",
58
  messages=[
59
+ {"role": "system", "content": "한국어 문화 프로그램 Q&A 챗봇이에요."},
60
+ {"role": "user", "content": f"{question}\n\n[관련 문서]\n{context[:3000]}"}
61
  ]
62
  )
63
+ return resp.choices[0].message.content
64
 
65
+ # 💬 챗봇 함수
66
  chat_history = []
67
 
68
+ def chatbot_fn(message):
69
  global chat_history
70
+ if not message.strip():
 
71
  return "", chat_history
72
+
73
  context = search_similar_docs(message)
74
  if not context:
75
+ chat_history.append((f"🙋‍♂️ {message}", "❌ 관련 문서를 찾지 못했습니다."))
76
+ else:
77
+ resp = ask_with_groq(message, context)
78
+ chat_history.append((f"🙋‍♂️ {message}", f"🤖 {resp}"))
79
  return "", chat_history
80
 
81
  def clear_chat():
 
83
  chat_history = []
84
  return chat_history
85
 
86
+ # 🌟 Gradio UI
87
+ with gr.Blocks(title="🧠 뮤지스 문화챗봇") as demo:
88
+ gr.Markdown("## 📘 아시스 문화 프로그램 챗봇")
89
+ gr.Markdown("> 입력하면 문서 기반으로 답변을 드립니다.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ chat = gr.Chatbot()
92
+ inp = gr.Textbox(placeholder="질문을 입력하세요", lines=1)
93
+ send = gr.Button("질문하기")
94
+ clear = gr.Button("대화 초기화")
95
 
96
+ send.click(chatbot_fn, inputs=[inp], outputs=[inp, chat])
97
+ inp.submit(chatbot_fn, inputs=[inp], outputs=[inp, chat])
98
+ clear.click(clear_chat, outputs=[chat])
 
 
 
99
 
100
  demo.launch()