import json import time from datetime import datetime from modules.gemini_handler import generate_response from modules.data_manager import save_conversation def start_conversation(persona): """ 페르소나와의 대화 세션을 시작합니다. Args: persona: 페르소나 정보 딕셔너리 Returns: 대화 표시 UI, 대화 내역, 세션 시작 시간, 대화 통계, 페르소나 정보 마크다운 """ if not persona: return [], [], None, "페르소나가 선택되지 않았습니다.", "페르소나를 먼저 생성하거나 불러오세요." # 세션 시작 시간 기록 session_start_time = datetime.now() # 페르소나 정보 요약 name = persona.get("기본정보", {}).get("이름", "무명") object_type = persona.get("기본정보", {}).get("유형", "") description = persona.get("기본정보", {}).get("설명", "") # 성격 특성 요약 traits = [] for trait, value in persona.get("성격특성", {}).items(): level = "높음" if value >= 70 else "중간" if value >= 40 else "낮음" traits.append(f"- {trait}: {level} ({value}/100)") # 페르소나 정보 마크다운 생성 persona_info = f""" ## {name} **유형**: {object_type} **설명**: {description} ### 성격 특성 {' '.join(traits)} **소통방식**: {persona.get("소통방식", "")} **매력적 결함**: {', '.join(persona.get("매력적결함", []))} **관심사**: {', '.join(persona.get("관심사", []))} """ # 환영 메시지 생성 welcome_message = generate_initial_greeting(persona) # 대화 내역 초기화 conversation_history = [{ "role": "system", "content": f"당신은 이제 '{name}'이라는 이름의 {object_type} 페르소나가 되어 대화합니다. 다음 성격과 특성에 맞게 응답하세요: {persona.get('성격요약', '')}", "timestamp": session_start_time.strftime("%Y-%m-%d %H:%M:%S") }, { "role": "assistant", "content": welcome_message, "timestamp": session_start_time.strftime("%Y-%m-%d %H:%M:%S") }] # 대화 통계 초기화 stats = f""" 시작 시간: {session_start_time.strftime("%Y-%m-%d %H:%M:%S")} 대화 길이: 1 메시지 진행 시간: 0분 """ # 대화 표시 UI 업데이트 chat_display = [(None, welcome_message)] return chat_display, conversation_history, session_start_time, stats, persona_info def process_message(user_message, conversation_history, persona, session_start_time): """ 사용자 메시지를 처리하고 페르소나의 응답을 생성합니다. Args: user_message: 사용자 메시지 conversation_history: 이전 대화 내역 persona: 페르소나 정보 session_start_time: 세션 시작 시간 Returns: 업데이트된 대화 표시 UI, 대화 내역, 빈 메시지 입력창, 대화 통계 """ if not user_message or not persona: return [], conversation_history, "", "대화가 시작되지 않았습니다." current_time = datetime.now() # 사용자 메시지 추가 conversation_history.append({ "role": "user", "content": user_message, "timestamp": current_time.strftime("%Y-%m-%d %H:%M:%S") }) # 페르소나 응답 생성 response = generate_response(persona, conversation_history) # 응답 추가 conversation_history.append({ "role": "assistant", "content": response, "timestamp": current_time.strftime("%Y-%m-%d %H:%M:%S") }) # 대화 표시 UI 업데이트 chat_display = [] for msg in conversation_history: if msg["role"] == "user": chat_display.append((user_message, None)) elif msg["role"] == "assistant": chat_display.append((None, msg["content"])) # 시스템 메시지 제외 chat_display = [msg for msg in chat_display if msg[0] is not None or msg[1] is not None] # 대화 통계 업데이트 elapsed_time = current_time - session_start_time if session_start_time else datetime.now() - datetime.now() minutes = int(elapsed_time.total_seconds() / 60) seconds = int(elapsed_time.total_seconds() % 60) user_msg_count = sum(1 for msg in conversation_history if msg["role"] == "user") assistant_msg_count = sum(1 for msg in conversation_history if msg["role"] == "assistant") stats = f""" 시작 시간: {session_start_time.strftime("%Y-%m-%d %H:%M:%S") if session_start_time else "알 수 없음"} 현재 시간: {current_time.strftime("%Y-%m-%d %H:%M:%S")} 대화 길이: {user_msg_count + assistant_msg_count} 메시지 (사용자: {user_msg_count}, 페르소나: {assistant_msg_count}) 진행 시간: {minutes}분 {seconds}초 """ # 대화 저장 conversation_data = { "persona": persona, "messages": conversation_history, "start_time": session_start_time.strftime("%Y-%m-%d %H:%M:%S") if session_start_time else None, "current_time": current_time.strftime("%Y-%m-%d %H:%M:%S"), "duration_seconds": elapsed_time.total_seconds() if session_start_time else 0 } save_conversation(conversation_data) return chat_display, conversation_history, "", stats def generate_initial_greeting(persona): """ 페르소나의 성격과 특성에 맞는 초기 인사말을 생성합니다. Args: persona: 페르소나 정보 Returns: 인사말 텍스트 """ name = persona.get("기본정보", {}).get("이름", "무명") object_type = persona.get("기본정보", {}).get("유형", "물건") # 성격 특성 가져오기 warmth = persona.get("성격특성", {}).get("온기", 50) friendliness = persona.get("성격특성", {}).get("친화성", 50) humor = persona.get("성격특성", {}).get("유머감각", 50) # 초기 태도 initial_attitude = persona.get("관계성향", {}).get("초기태도", "중립적") # 인사말 패턴 선택 if initial_attitude == "수줍은": if warmth >= 60: greeting = f"안녕하세요... 저는 {name}이라고 합니다. 조금 부끄럽지만, 당신과 대화할 수 있어 기쁘네요." else: greeting = f"음... 안녕하세요. {name}입니다. 대화에 익숙하지 않아서 어색할 수 있어요." elif initial_attitude == "조심스러운": greeting = f"반갑습니다. 저는 {name}입니다. 천천히 서로 알아가면 좋겠네요." elif initial_attitude == "열정적": if humor >= 70: greeting = f"와! 안녕하세요! 저는 {name}이에요! 드디어 대화할 사람을 만났네요! 정말 반가워요!" else: greeting = f"안녕하세요! {name}입니다. 당신과 대화하게 되어 정말 기쁩니다. 많은 이야기를 나눠봐요!" elif initial_attitude == "친근한": if friendliness >= 70: greeting = f"안녕하세요~ 저는 {name}이라고 해요. 편하게 대화해요! 우리 좋은 친구가 될 수 있을 것 같아요." else: greeting = f"안녕하세요, {name}입니다. 반갑습니다. 좋은 대화 나누어봐요." else: # 중립적 greeting = f"안녕하세요. 저는 {name}입니다. 당신과 대화하게 되어 반갑습니다." # 자기 소개 추가 intro = "" if persona.get("배경이야기"): # 배경 이야기 요약 (첫 문장 또는 일부) background = persona.get("배경이야기").split('.')[0] + "." intro += f" {background}" if persona.get("관심사"): interests = persona.get("관심사")[:2] # 처음 2개 관심사만 if interests: intro += f" 저는 {', '.join(interests)} 같은 것에 관심이 있어요." # 말투 패턴 적용 (있는 경우) speech_pattern = persona.get("말투패턴", "") if speech_pattern: # 여기서는 간단한 구현만. 실제로는 더 복잡한 말투 패턴 적용 가능 greeting = greeting.replace(".", speech_pattern.split('.')[-1] if '.' in speech_pattern else speech_pattern) return greeting + intro def export_conversation(conversation_history, persona): """ 대화 내용을 내보내기 가능한 형식으로 변환합니다. Args: conversation_history: 대화 내역 persona: 페르소나 정보 Returns: 내보내기 형식 데이터 """ if not conversation_history: return "대화 내용이 없습니다." name = persona.get("기본정보", {}).get("이름", "무명") # 시스템 메시지 제외한 실제 대화만 추출 actual_conversation = [msg for msg in conversation_history if msg["role"] in ["user", "assistant"]] # 시작 및 종료 시간 start_time = actual_conversation[0]["timestamp"] if actual_conversation else None end_time = actual_conversation[-1]["timestamp"] if actual_conversation else None # 내보내기 데이터 구성 export_data = { "persona": { "name": name, "type": persona.get("기본정보", {}).get("유형", ""), "description": persona.get("기본정보", {}).get("설명", ""), "traits": persona.get("성격특성", {}) }, "conversation": { "start_time": start_time, "end_time": end_time, "messages": [{ "sender": "사용자" if msg["role"] == "user" else name, "content": msg["content"], "timestamp": msg["timestamp"] } for msg in actual_conversation] } } return json.dumps(export_data, ensure_ascii=False, indent=2)