persona_create / modules /chat_engine.py
haepada's picture
Upload 12 files
5581923 verified
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)