꼬맨틀을 좋아하시는 여러분을 보다가 무한맨틀을 만들어보았어요. 단어는 1~100개만 우선 넣었고 uvcorn(streamlit)으로 실행하면 된답니다.
import streamlit as st
import numpy as np
from scipy.spatial.distance import cosine
from sentence_transformers import SentenceTransformer
# -------------------------------------------------------
# 1) 페이지 기본 설정
# -------------------------------------------------------
st.set_page_config(page_title="무한맨틀", layout="centered")
st.title("무한맨틀")
# -------------------------------------------------------
# 2) 모델 로드
# (원하는 다른 한국어 모델로 교체 가능)
# -------------------------------------------------------
@st.cache_resource
def load_model():
return SentenceTransformer("snunlp/KR-SBERT-V40K-klueNLI-augSTS") # "snunlp/KR-SBERT-V40K-klueNLI-augSTS" jhgan/ko-sroberta-multitask
model = load_model()
여기까지는 모델 불러오는 부분! 여기서 추가 학습을 해서 꼬맨틀의 성능을 높혀볼 수 있어요.
# -------------------------------------------------------
# 3) 시드 번호 -> 정답 단어 딕셔너리
# -------------------------------------------------------
word_dict = {
1: "사과",
2: "컴퓨터",
3: "하늘",
4: "숟가락",
5: "의자",
6: "바다",
7: "향수",
8: "텔레비전",
9: "소설",
10: "공원",
11: "그림",
12: "안경",
13: "피아노",
14: "산",
15: "축구",
16: "커피",
17: "책상",
18: "지갑",
19: "빵",
20: "시계",
21: "양말",
22: "자동차",
23: "식물",
24: "우산",
25: "핸드폰",
26: "문",
27: "펜",
28: "구름",
29: "모자",
30: "초콜릿",
31: "버스",
32: "얼음",
33: "볼펜",
34: "샴푸",
35: "가방",
36: "신발",
37: "커튼",
38: "알람",
39: "종이",
40: "비누",
41: "악기",
42: "램프",
43: "토마토",
44: "물",
45: "사진",
46: "비디오",
47: "구두",
48: "조각상",
49: "팔찌",
50: "빗",
51: "옷",
52: "토스트",
53: "종",
54: "노트",
55: "카메라",
56: "마이크",
57: "선풍기",
58: "휴대폰",
59: "물컵",
60: "담요",
61: "헤드폰",
62: "레몬",
63: "반지",
64: "스피커",
65: "드럼",
66: "명함",
67: "안전모",
68: "연필",
69: "지구본",
70: "티셔츠",
71: "선글라스",
72: "노트북",
73: "햄버거",
74: "모니터",
75: "라디오",
76: "손목시계",
77: "이어폰",
78: "컵",
79: "소파",
80: "타이어",
81: "전등",
82: "토끼",
83: "도서관",
84: "브러쉬",
85: "건전지",
86: "타블렛",
87: "가위",
88: "테이프",
89: "거울",
90: "기차",
91: "케이크",
92: "칠판",
93: "화분",
94: "키보드",
95: "랜턴",
96: "마우스",
97: "우표",
98: "자",
99: "헬멧",
100: "전구"
}
단어 목록을 넣구,
# -------------------------------------------------------
# 4) 세션 상태 정의
# -------------------------------------------------------
if "seed_number" not in st.session_state:
st.session_state.seed_number = None
if "answer_word" not in st.session_state:
st.session_state.answer_word = None
if "attempts" not in st.session_state:
st.session_state.attempts = [] # [(guess_word, similarity_score), ...]
if "is_correct" not in st.session_state:
st.session_state.is_correct = False
# "정답 보기" 버튼을 눌렀는지 여부
if "reveal_answer" not in st.session_state:
st.session_state.reveal_answer = False
시드 넘버, 정답 단어, 코사인 유사도를 보여주는 걸 만듭니다. 그리고 정답인지 확인 하는곳, 정 못 맞추겠다면, 정답 보기를 누르면 보이게 합니다
# -------------------------------------------------------
# 5) 시드 번호 입력
# -------------------------------------------------------
st.subheader("1. 시드 번호 선택")
seed_number_input = st.number_input(
label="시드 번호 (1~100)",
min_value=1,
max_value=100,
value=1,
step=1
)
if st.button("시드 적용"):
st.session_state.seed_number = seed_number_input
if seed_number_input in word_dict:
st.session_state.answer_word = word_dict[seed_number_input]
st.session_state.attempts = []
st.session_state.is_correct = False
st.session_state.reveal_answer = False # 새 게임 시작 시 정답보기 리셋
st.success(f"시드번호 {seed_number_input} → 게임시작!")
else:
st.session_state.answer_word = None
st.session_state.attempts = []
st.session_state.is_correct = False
st.session_state.reveal_answer = False
st.warning("잘못된 시드번호입니다.")
시드 번호를 만들고
# -------------------------------------------------------
# 6) 포커스 위한 JavaScript (엔터 후 자동 포커스 복귀)
# -------------------------------------------------------
FOCUS_SCRIPT = """
<script>
var input = window.parent.document.querySelector("input[data-testid='stTextInput']");
if (input) {
input.focus();
}
</script>
"""
편의성을 위한 엔터 자동 복귀! 이게 무었이냐면 엔터를 치면 빈칸이 되고, 커서도 그곳에 있어서 계속 답을 쓸 수 있게 만든 것입니다.
# -------------------------------------------------------
# 7) 추측 단어 입력 (엔터 제출, 제출 후 자동삭제 & 포커스 유지)
# -------------------------------------------------------
st.subheader("2. 추측 단어 입력")
if not st.session_state.answer_word:
st.info("먼저 올바른 시드 번호를 적용해주세요.")
else:
# 폼 사용: 엔터로 제출 + clear_on_submit=True
with st.form("guess_form", clear_on_submit=True):
guess = st.text_input(
"정답 단어를 맞춰보세요 (엔터 제출)",
placeholder="여기에 입력 후 엔터!"
)
submitted = st.form_submit_button("Submit")
if submitted:
if st.session_state.is_correct:
st.warning("이미 정답을 맞추었습니다. 새로운 시드 번호로 시작하세요.")
else:
# 정답 체크
if guess == st.session_state.answer_word:
st.session_state.is_correct = True
st.success("정답입니다! 🎉")
else:
# 유사도 계산
embedding_guess = model.encode(guess)
embedding_answer = model.encode(st.session_state.answer_word)
similarity_score = 1 - cosine(embedding_guess, embedding_answer)
# 로그 저장
st.session_state.attempts.append((guess, similarity_score))
st.info(f"유사도: **{similarity_score:.4f}**")
# 렌더링될 때마다 포커스 스크립트 실행 → 입력창 포커스
st.markdown(FOCUS_SCRIPT, unsafe_allow_html=True)
여긴 추측 단어 입력란 입니다. 여기서 추측 단어를 입력하고 정답을 맞추게 합니다.
# -------------------------------------------------------
# 8) 추측 로그 (코사인 유사도 높은 순 정렬)
# -------------------------------------------------------
st.subheader("3. 추측 로그")
if st.session_state.attempts:
# 코사인 유사도 높은 순 (내림차순)
sorted_attempts = sorted(
st.session_state.attempts,
key=lambda x: x[1],
reverse=True
)
for idx, (g, sim) in enumerate(sorted_attempts, start=1):
st.write(f"**{idx}위** (유사도: {sim:.4f}) → 추측: '{g}'")
else:
st.write("아직 추측 기록이 없습니다.")
해당 부분은 유사도가 높은 순으로 추측 로그를 남깁니다.
진짜 꼬멘틀은 사람수가 많아서 1순위부터 ~10순위까지 잘 맞추면 순위가 나오는 것으로 보이나, 여기는 그렇게 하기 어려워 이렇게 구성했습니다!
# -------------------------------------------------------
# 9) 정답 보기
# -------------------------------------------------------
st.subheader("4. 정답 보기")
if st.session_state.answer_word:
if st.session_state.is_correct:
# 이미 맞혔으면 바로 정답 공개
st.info(f"현재 정답: {st.session_state.answer_word}")
else:
# "정답 보기" 버튼 표시
if st.button("정답 보기"):
st.session_state.reveal_answer = True
# reveal_answer가 True면 정답 공개
if st.session_state.reveal_answer:
st.info(f"현재 정답: {st.session_state.answer_word}")
말그대로 정답 세션입니다.
아래는 실제 실행시 이렇게 보인답니다.
http://121.78.147.172:7195/
'IT - 코딩 > AI, 예측모델' 카테고리의 다른 글
시계열 예측 모델 _ LSTM 환율 예측 (1) | 2023.10.24 |
---|---|
머신러닝 예측모델 선정하기 (인공지능 코테 예제)Adult Census Income Tutorial (1) | 2023.10.23 |
[데이콘]데이크루 6 _ 신용카드 연체 예측 (0) | 2023.09.17 |
전력 사용량 예측 (0) | 2023.08.07 |
chat GPT를 활용한 한국어 댓글 긍부정 판단 vs 공개 사전학습 모델 긍부정 판단 비교 (with python) (0) | 2023.06.23 |