-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
143 lines (125 loc) · 4.31 KB
/
app.py
File metadata and controls
143 lines (125 loc) · 4.31 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from flask import Flask, jsonify, render_template
import requests
import time
import pyttsx3
import speech_recognition as sr
import threading
import re
# KoGPT2 임포트
from transformers import PreTrainedTokenizerFast, GPT2LMHeadModel
import torch
app = Flask(__name__)
# ESP32 IP 주소 및 포트
ESP32_IP = "192.168.0.100"
ESP32_PORT = 80
tts_engine = pyttsx3.init()
tts_lock = threading.Lock()
slots = {}
# 동의어 사전
synonyms = {
"주민등록증": ["주민등록증", "민증", "등록증"],
"롯데카드": ["롯데카드", "롯데"],
"삼성카드": ["삼성카드", "삼성"],
# 필요시 추가
}
def get_canonical_name(name):
for key, syns in synonyms.items():
if name in syns:
return key
return name
# KoGPT2 모델, 토크나이저 로딩 (필요시 사전 다운로드)
tokenizer = PreTrainedTokenizerFast.from_pretrained("skt/kogpt2-base-v2")
model = GPT2LMHeadModel.from_pretrained("skt/kogpt2-base-v2")
model.eval()
def speak(text):
with tts_lock:
tts_engine.say(text)
tts_engine.runAndWait()
def send_esp32_command(command):
url = f"http://{ESP32_IP}:{ESP32_PORT}/command"
try:
response = requests.post(url, json={"command": command}, timeout=3)
if response.status_code == 200:
print(f"ESP32 명령 전송 성공: {command}")
else:
print(f"ESP32 명령 전송 실패, 상태 코드: {response.status_code}")
except requests.RequestException as e:
print(f"ESP32 통신 오류: {e}")
def listen_command():
r = sr.Recognizer()
with sr.Microphone() as source:
print("🎤 음성 입력 대기 중...")
audio = r.listen(source)
try:
text = r.recognize_google(audio, language='ko-KR')
print(f"🎧 인식된 텍스트: {text}")
return text
except sr.UnknownValueError:
return "인식 실패"
except sr.RequestError as e:
return f"API 오류: {e}"
def kogpt2_classify(text):
"""
KoGPT2 모델을 실제로 생성형 분류기로 사용하지 않고,
간단히 명령어 타입(저장, 삭제, 이동)과 파라미터 추출.
"""
text = text.strip()
if text.startswith("저장"):
content = text[2:].strip()
m = re.match(r"(.+?)\s*(\d+)$", content)
if m:
name = get_canonical_name(m.group(1).strip())
slot_num = int(m.group(2))
return ("저장", name, slot_num)
else:
return ("오류", "슬롯 번호 인식 실패", None)
elif text.startswith("삭제"):
name = get_canonical_name(text[2:].strip())
return ("삭제", name, None)
else:
name = get_canonical_name(text)
return ("이동", name, None)
def process_command(text):
cmd, name, num = kogpt2_classify(text)
print(f"명령 분류 결과 -> cmd: {cmd}, name: {name}, num: {num}")
if cmd == "저장":
slots[name] = num
send_esp32_command(f"M{num * 1000};")
speak(f"{name} 슬롯을 {num}번 위치에 저장했습니다.")
time.sleep(1)
send_esp32_command(f"R{num * 1000};")
speak("카드가 정상적으로 보관되었습니다. 설정이 완료되었습니다!")
elif cmd == "삭제":
if name in slots:
del slots[name]
speak(f"{name} 슬롯을 삭제했습니다.")
else:
speak(f"{name} 슬롯이 없습니다.")
elif cmd == "이동":
if name in slots:
pos = slots[name]
send_esp32_command(f"M{pos * 1000};")
speak(f"{name} 슬롯으로 이동합니다.")
else:
speak(f"{name} 슬롯 정보가 없습니다.")
else:
speak("명령을 이해하지 못했습니다.")
@app.route("/")
def index():
return render_template("index.html")
@app.route("/listen")
def listen():
def worker():
text = listen_command()
print(f"받은 음성 명령: {text}")
if text in ["인식 실패", "API 오류"]:
speak("음성 인식에 실패했습니다. 다시 시도해 주세요.")
return
process_command(text)
threading.Thread(target=worker).start()
return jsonify({"status": "음성 명령 처리 중..."})
@app.route("/slots")
def get_slots():
return jsonify(slots)
if __name__ == "__main__":
app.run(debug=True)