Spaces:
Sleeping
Sleeping
| 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) |