Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions app/service/interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,47 +25,59 @@

# Whisper 모델 (tiny, CPU, int8)
whisper_model = WhisperModel("tiny", device="cpu", compute_type="int8")
# 종료 키워드 목록
EXIT_KEYWORDS = ["그만", "이제 그만", "종료", "끝낼래", "안녕", "잘 자", "다음에 보자", "나중에 얘기해"]
START_COMMUNICATION = "오늘 좋은 하루 보냈나~~?? 어떻게 지냈어!!"
END_COMMUNICATION = "오늘 이야기 나눠서 좋았어. 푹 쉬고, 또 얘기하자~!"


def interaction(alias: str):
"""
alias: 사용자 이름 또는 AI가 부르는 별칭 (ex: "홍길동")
1) alias 인사 → TTS → 재생
2) 이후 반복: emotion_record → Whisper STT → GPT 질문 생성 → TTS → 재생
종료는 키워드 또는 Ctrl+C로 가능
"""

# 1) alias 인사
greet_text = f"{alias}~~ 오늘 좋은 하루 보냈나~~?? 어떻게 지냈어!!"
greet_text = f"{alias}~~ " + START_COMMUNICATION
print("👋 인사:", greet_text)
greet_audio = text_to_speech_file(greet_text)
subprocess.run(["mpg321", greet_audio], check=True)

# 대화 이력 초기화
messages = [
{"role": "system",
"content": "너는 대화를 자연스럽게 이어가는 AI야. 사용자와 계속 이어지는 대화를 만들어야 해."},
"content": "너는 다정하고 따뜻한 딸이야. 부모님과 이야기할 때는 애정을 담아 걱정해주고, 자연스럽게 다음 말을 이어가야 해. 반말을 쓰되 너무 건방지지는 않게, 친근하고 편안한 말투로 대화해."},
{"role": "assistant", "content": greet_text}
]

record_idx = 0
try:
while True:
# 2-1) 감정 녹음 (침묵 기준으로 자동 종료)
# 2-1) 감정 녹음
wav_path = emotion_record(record_idx)
print(f"[녹음 완료] {wav_path}")
record_idx += 1

# 2-2) Whisper STT (한국어)
segments, _ = whisper_model.transcribe(wav_path,
beam_size=1,
language="ko")
# 2-2) Whisper STT
segments, _ = whisper_model.transcribe(wav_path, beam_size=1, language="ko")
user_text = " ".join(seg.text for seg in segments).strip()
print("▶ 사용자 음성(텍스트):", user_text or "(인식 안됨)")

if not user_text:
print("(음성 인식 실패 → 다시 녹음)")
continue

# 2-3) GPT-4o 에 질문 생성 요청
# 종료 키워드 감지
if any(keyword in user_text for keyword in EXIT_KEYWORDS):
bye_text = f"{alias}~" + END_COMMUNICATION
print("종료 의사 감지:", user_text)
bye_audio = text_to_speech_file(bye_text)
subprocess.run(["mpg321", bye_audio], check=True)
break

# 2-3) GPT-4o 질문 생성
messages.append({"role": "user", "content": user_text})
resp = gpt_client.chat.completions.create(
model="gpt-4o",
Expand All @@ -74,18 +86,19 @@ def interaction(alias: str):
question = resp.choices[0].message.content.strip()
print("생성된 질문:", question)

# 2-4) 대화 이력에 어시스턴트 질문 추가
# 2-4) 대화 이력 업데이트
messages.append({"role": "assistant", "content": question})

# 2-5) 질문 → ElevenLabs TTS → 파일
# 2-5) TTS 변환 및 재생
tts_path = text_to_speech_file(question)
print(" (TTS 파일 생성:", tts_path, ")")

# 2-6) 재생
subprocess.run(["mpg321", tts_path], check=True)

except KeyboardInterrupt:
print("\n[사용자 종료 요청] interaction을 종료합니다.")
print("\n[사용자 종료 요청: Ctrl+C]")
bye_text = f"{alias}~~ " + END_COMMUNICATION
bye_audio = text_to_speech_file(bye_text)
subprocess.run(["mpg321", bye_audio], check=True)
except Exception as e:
print("예외 발생:", e)

Expand Down
5 changes: 2 additions & 3 deletions app/service/record_respberry.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ def _ensure_dir():


def is_silent(data: np.ndarray, threshold: float = THRESHOLD) -> bool:
"""
float32 numpy 배열을 받아 RMS 기준으로 침묵 여부를 판단
"""
rms = np.sqrt(np.mean(data ** 2))
print(f"RMS: {rms:.5f} (threshold: {threshold})") # 디버깅 출력
return rms < threshold



def emotion_record(index: int) -> str:
"""
index: 녹음 파일 구분을 위한 정수 인덱스
Expand Down
Loading