persona_create / modules /data_manager.py
haepada's picture
Upload 12 files
5581923 verified
import os
import json
import time
from datetime import datetime
# 디렉터리 경로 설정
PERSONAS_DIR = "data/user_personas"
CONVERSATIONS_DIR = "data/conversation_logs"
def ensure_directories():
"""필요한 디렉터리가 존재하는지 확인하고, 없으면 생성합니다."""
for dir_path in [PERSONAS_DIR, CONVERSATIONS_DIR]:
try:
os.makedirs(dir_path, exist_ok=True)
except Exception as e:
print(f"디렉토리 생성 중 오류: {str(e)}")
# 허깅페이스 환경에서는 임시 디렉토리 사용
temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "temp_data")
os.makedirs(temp_dir, exist_ok=True)
return False
return True
def save_persona(persona_data):
"""
페르소나 데이터를 JSON 파일로 저장합니다.
Args:
persona_data: 저장할 페르소나 데이터
Returns:
저장된 파일 경로
"""
if not ensure_directories():
print("경고: 디렉토리 생성에 실패했습니다. 세션 데이터만 유지됩니다.")
persona_data["_temp_storage_warning"] = "임시 스토리지만 사용 가능합니다. 페르소나는 세션이 종료되면 사라집니다."
return "temp_persona"
# 파일명 생성 (이름_타임스탬프.json)
name = persona_data.get("기본정보", {}).get("이름", "unnamed").replace(" ", "_")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{name}_{timestamp}.json"
file_path = os.path.join(PERSONAS_DIR, filename)
try:
# JSON 파일로 저장
with open(file_path, "w", encoding="utf-8") as f:
json.dump(persona_data, f, ensure_ascii=False, indent=2)
return file_path
except Exception as e:
print(f"페르소나 저장 오류: {str(e)}")
persona_data["_storage_error"] = str(e)
return "failed_to_save"
def load_persona(file_path):
"""
JSON 파일에서 페르소나 데이터를 로드합니다.
Args:
file_path: 페르소나 파일 경로
Returns:
로드된 페르소나 데이터
"""
# 임시 저장 케이스 처리
if file_path == "temp_persona" or file_path == "failed_to_save":
return None
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data
except Exception as e:
print(f"페르소나 로딩 오류: {str(e)}")
return None
def list_personas():
"""
저장된 모든 페르소나 목록을 가져옵니다.
Returns:
페르소나 목록 (테이블 형식)
"""
ensure_directories()
personas = []
# 디렉터리 내 모든 JSON 파일 확인
for filename in os.listdir(PERSONAS_DIR):
if filename.endswith(".json"):
file_path = os.path.join(PERSONAS_DIR, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 필요한 정보 추출
name = data.get("기본정보", {}).get("이름", "무명")
object_type = data.get("기본정보", {}).get("유형", "")
created = data.get("기본정보", {}).get("생성일시", "")
personas.append([name, object_type, created, filename])
except Exception as e:
print(f"파일 읽기 오류 ({filename}): {str(e)}")
# 최신 순으로 정렬
personas.sort(key=lambda x: x[2], reverse=True)
return personas
def save_conversation(conversation_data):
"""
대화 데이터를 JSON 파일로 저장합니다.
Args:
conversation_data: 저장할 대화 데이터
Returns:
저장된 파일 경로
"""
if not ensure_directories():
print("경고: 디렉토리 생성에 실패했습니다. 대화 데이터를 저장할 수 없습니다.")
return "temp_conversation"
# 페르소나 정보 추출
persona = conversation_data.get("persona", {})
name = persona.get("기본정보", {}).get("이름", "unnamed").replace(" ", "_")
# 페르소나별 대화 저장 디렉터리
persona_conv_dir = os.path.join(CONVERSATIONS_DIR, name)
try:
os.makedirs(persona_conv_dir, exist_ok=True)
except Exception as e:
print(f"대화 저장 디렉토리 생성 오류: {str(e)}")
return "failed_to_save_conv"
# 파일명 생성 (타임스탬프.json)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"conversation_{timestamp}.json"
file_path = os.path.join(persona_conv_dir, filename)
try:
# JSON 파일로 저장
with open(file_path, "w", encoding="utf-8") as f:
# 메시지 내용만 저장하여 파일 크기 최적화
simplified_data = {
"persona_name": name,
"persona_type": persona.get("기본정보", {}).get("유형", ""),
"start_time": conversation_data.get("start_time", ""),
"current_time": conversation_data.get("current_time", ""),
"duration_seconds": conversation_data.get("duration_seconds", 0),
"messages": [{
"role": msg["role"],
"content": msg["content"],
"timestamp": msg.get("timestamp", "")
} for msg in conversation_data.get("messages", [])]
}
json.dump(simplified_data, f, ensure_ascii=False, indent=2)
return file_path
except Exception as e:
print(f"대화 저장 오류: {str(e)}")
return "failed_to_save_conv"
def list_conversations(persona_name=None):
"""
저장된 대화 목록을 가져옵니다.
Args:
persona_name: 특정 페르소나의 대화만 필터링 (선택 사항)
Returns:
대화 목록 (테이블 형식)
"""
ensure_directories()
conversations = []
# 모든 페르소나 디렉터리 탐색
for persona_dir in os.listdir(CONVERSATIONS_DIR):
# 특정 페르소나만 필터링
if persona_name and persona_name != persona_dir:
continue
persona_path = os.path.join(CONVERSATIONS_DIR, persona_dir)
if os.path.isdir(persona_path):
# 디렉터리 내 모든 대화 파일 확인
for filename in os.listdir(persona_path):
if filename.endswith(".json"):
file_path = os.path.join(persona_path, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 필요한 정보 추출
persona_name = data.get("persona_name", "무명")
start_time = data.get("start_time", "")
duration = data.get("duration_seconds", 0)
msg_count = len(data.get("messages", []))
conversations.append([
persona_name,
start_time,
f"{int(duration // 60)}{int(duration % 60)}초",
msg_count,
file_path
])
except Exception as e:
print(f"대화 파일 읽기 오류 ({file_path}): {str(e)}")
# 최신 순으로 정렬
conversations.sort(key=lambda x: x[1], reverse=True)
return conversations
def load_conversation(file_path):
"""
JSON 파일에서 대화 데이터를 로드합니다.
Args:
file_path: 대화 파일 경로
Returns:
로드된 대화 데이터
"""
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data
except Exception as e:
print(f"대화 로딩 오류: {str(e)}")
return None
def analyze_persona_trait_distribution():
"""
저장된 모든 페르소나의 성격 특성 분포를 분석합니다.
Returns:
특성별 평균값, 최소값, 최대값, 중앙값을 포함한 분석 결과
"""
ensure_directories()
traits_data = {
"온기": [],
"능력": [],
"신뢰성": [],
"친화성": [],
"창의성": [],
"유머감각": []
}
# 모든 페르소나 파일에서 성격 특성 수집
for filename in os.listdir(PERSONAS_DIR):
if filename.endswith(".json"):
file_path = os.path.join(PERSONAS_DIR, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 성격 특성 값 추출
for trait, values in traits_data.items():
trait_value = data.get("성격특성", {}).get(trait)
if trait_value is not None:
values.append(trait_value)
except Exception as e:
print(f"파일 분석 오류 ({filename}): {str(e)}")
# 분석 결과 계산
analysis = {}
for trait, values in traits_data.items():
if values:
analysis[trait] = {
"평균": sum(values) / len(values),
"최소": min(values),
"최대": max(values),
"중앙값": sorted(values)[len(values) // 2],
"페르소나 수": len(values)
}
else:
analysis[trait] = {
"평균": 0,
"최소": 0,
"최대": 0,
"중앙값": 0,
"페르소나 수": 0
}
return analysis
def get_conversation_statistics(persona_name=None):
"""
대화 데이터의 통계 정보를 분석합니다.
Args:
persona_name: 특정 페르소나의 대화만 필터링 (선택 사항)
Returns:
대화 통계 정보
"""
ensure_directories()
stats = {
"총_대화_수": 0,
"총_메시지_수": 0,
"평균_대화_시간": 0,
"평균_메시지_수": 0,
"페르소나별_대화": {}
}
total_duration = 0
# 모든 페르소나 디렉터리 탐색
for persona_dir in os.listdir(CONVERSATIONS_DIR):
# 특정 페르소나만 필터링
if persona_name and persona_name != persona_dir:
continue
persona_path = os.path.join(CONVERSATIONS_DIR, persona_dir)
if os.path.isdir(persona_path):
persona_stats = {
"대화_수": 0,
"메시지_수": 0,
"총_대화_시간": 0
}
# 디렉터리 내 모든 대화 파일 확인
for filename in os.listdir(persona_path):
if filename.endswith(".json"):
file_path = os.path.join(persona_path, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 통계 누적
msg_count = len(data.get("messages", []))
duration = data.get("duration_seconds", 0)
stats["총_대화_수"] += 1
stats["총_메시지_수"] += msg_count
total_duration += duration
persona_stats["대화_수"] += 1
persona_stats["메시지_수"] += msg_count
persona_stats["총_대화_시간"] += duration
except Exception as e:
print(f"대화 파일 분석 오류 ({file_path}): {str(e)}")
# 페르소나별 평균 계산
if persona_stats["대화_수"] > 0:
persona_stats["평균_메시지_수"] = persona_stats["메시지_수"] / persona_stats["대화_수"]
persona_stats["평균_대화_시간"] = persona_stats["총_대화_시간"] / persona_stats["대화_수"]
stats["페르소나별_대화"][persona_dir] = persona_stats
# 전체 평균 계산
if stats["총_대화_수"] > 0:
stats["평균_대화_시간"] = total_duration / stats["총_대화_수"]
stats["평균_메시지_수"] = stats["총_메시지_수"] / stats["총_대화_수"]
return stats