Spaces:
Sleeping
Sleeping
haepa_mac commited on
Commit ·
19faf7a
1
Parent(s): 698b201
Simplify chat tab: Replace persona list with JSON upload for easy testing
Browse files
app.py
CHANGED
|
@@ -379,84 +379,13 @@ def export_persona_to_json(persona):
|
|
| 379 |
print(f"JSON 내보내기 오류: {error_msg}")
|
| 380 |
return None, f"❌ JSON 내보내기 중 오류 발생: {str(e)}"
|
| 381 |
|
| 382 |
-
def get_saved_personas():
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
personas = list_personas()
|
| 386 |
-
df_data = []
|
| 387 |
-
for i, persona in enumerate(personas):
|
| 388 |
-
df_data.append([
|
| 389 |
-
i,
|
| 390 |
-
persona["name"],
|
| 391 |
-
persona["type"],
|
| 392 |
-
persona["created_at"]
|
| 393 |
-
])
|
| 394 |
-
return df_data, personas
|
| 395 |
-
except Exception as e:
|
| 396 |
-
print(f"페르소나 목록 로딩 오류: {str(e)}")
|
| 397 |
-
return [], []
|
| 398 |
|
| 399 |
-
def load_persona_from_selection(selected_row, personas_list):
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
return None, "선택된 페르소나가 없습니다.", {}, {}, None, [], [], [], ""
|
| 403 |
-
|
| 404 |
-
try:
|
| 405 |
-
# DataFrame에서 선택된 행의 인덱스 추출
|
| 406 |
-
if hasattr(selected_row, 'index'):
|
| 407 |
-
selected_index = selected_row.index[0]
|
| 408 |
-
else:
|
| 409 |
-
selected_index = 0
|
| 410 |
-
|
| 411 |
-
if selected_index >= len(personas_list):
|
| 412 |
-
return None, "잘못된 선택입니다.", {}, {}, None, [], [], [], ""
|
| 413 |
-
|
| 414 |
-
filepath = personas_list[selected_index]["filepath"]
|
| 415 |
-
persona = load_persona(filepath)
|
| 416 |
-
|
| 417 |
-
if not persona:
|
| 418 |
-
return None, "페르소나 로딩에 실패했습니다.", {}, {}, None, [], [], [], ""
|
| 419 |
-
|
| 420 |
-
basic_info = {
|
| 421 |
-
"이름": persona.get("기본정보", {}).get("이름", "Unknown"),
|
| 422 |
-
"유형": persona.get("기본정보", {}).get("유형", "Unknown"),
|
| 423 |
-
"설명": persona.get("기본정보", {}).get("설명", "")
|
| 424 |
-
}
|
| 425 |
-
|
| 426 |
-
personality_traits = persona.get("성격특성", {})
|
| 427 |
-
humor_chart = plot_humor_matrix(persona.get("유머매트릭스", {}))
|
| 428 |
-
|
| 429 |
-
attractive_flaws_df = []
|
| 430 |
-
contradictions_df = []
|
| 431 |
-
personality_variables_df = []
|
| 432 |
-
|
| 433 |
-
if "매력적결함" in persona:
|
| 434 |
-
flaws = persona["매력적결함"]
|
| 435 |
-
attractive_flaws_df = [[flaw, "매력 증가"] for flaw in flaws]
|
| 436 |
-
|
| 437 |
-
if "모순적특성" in persona:
|
| 438 |
-
contradictions = persona["모순적특성"]
|
| 439 |
-
contradictions_df = [[contradiction, "복잡성 증가"] for contradiction in contradictions]
|
| 440 |
-
|
| 441 |
-
if "성격변수127" in persona:
|
| 442 |
-
variables = persona["성격변수127"]
|
| 443 |
-
if isinstance(variables, dict):
|
| 444 |
-
personality_variables_df = [[var_name, score, VARIABLE_DESCRIPTIONS.get(var_name, "")]
|
| 445 |
-
for var_name, score in variables.items()]
|
| 446 |
-
|
| 447 |
-
# 로드된 페르소나 인사말
|
| 448 |
-
persona_name = basic_info.get("이름", "친구")
|
| 449 |
-
greeting = f"반가워! 나는 {persona_name}이야. 다시 만나서 기뻐! 😊"
|
| 450 |
-
|
| 451 |
-
return (persona, f"✅ {persona['기본정보']['이름']}을(를) 로드했습니다.",
|
| 452 |
-
basic_info, personality_traits, humor_chart, attractive_flaws_df,
|
| 453 |
-
contradictions_df, personality_variables_df, greeting)
|
| 454 |
-
|
| 455 |
-
except Exception as e:
|
| 456 |
-
import traceback
|
| 457 |
-
error_msg = traceback.format_exc()
|
| 458 |
-
print(f"로딩 오류: {error_msg}")
|
| 459 |
-
return None, f"❌ 로딩 중 오류 발생: {str(e)}", {}, {}, None, [], [], [], ""
|
| 460 |
|
| 461 |
def chat_with_loaded_persona(persona, user_message, chat_history=None):
|
| 462 |
"""페르소나와 대화"""
|
|
@@ -478,6 +407,48 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
|
|
| 478 |
chat_history.append([user_message, f"대화 중 오류가 발생했습니다: {str(e)}"])
|
| 479 |
return chat_history, ""
|
| 480 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
# 메인 인터페이스 생성
|
| 482 |
def create_main_interface():
|
| 483 |
# State 변수들 - 올바른 방식으로 생성
|
|
@@ -567,18 +538,25 @@ def create_main_interface():
|
|
| 567 |
with gr.Tab("대화하기", id="chat"):
|
| 568 |
with gr.Row():
|
| 569 |
with gr.Column(scale=1):
|
| 570 |
-
gr.Markdown("### 페르소나 불러오기")
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
label="
|
| 575 |
-
|
|
|
|
| 576 |
)
|
| 577 |
-
|
| 578 |
load_status = gr.Markdown("")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 579 |
|
| 580 |
with gr.Column(scale=1):
|
| 581 |
-
gr.Markdown("### 대화")
|
| 582 |
# Gradio 4.x 호환을 위해 명시적으로 type 지정
|
| 583 |
chatbot = gr.Chatbot(height=400, label="대화", type="tuples")
|
| 584 |
with gr.Row():
|
|
@@ -588,6 +566,13 @@ def create_main_interface():
|
|
| 588 |
lines=2
|
| 589 |
)
|
| 590 |
send_btn = gr.Button("전송", variant="primary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 591 |
|
| 592 |
# 이벤트 핸들러
|
| 593 |
create_btn.click(
|
|
@@ -622,25 +607,15 @@ def create_main_interface():
|
|
| 622 |
outputs=[download_file]
|
| 623 |
)
|
| 624 |
|
| 625 |
-
|
| 626 |
-
fn=
|
| 627 |
-
|
| 628 |
-
)
|
| 629 |
-
|
| 630 |
-
load_btn.click(
|
| 631 |
-
fn=load_persona_from_selection,
|
| 632 |
-
inputs=[persona_table, personas_list],
|
| 633 |
outputs=[
|
| 634 |
-
current_persona, load_status,
|
| 635 |
-
humor_chart_output, attractive_flaws_output, contradictions_output,
|
| 636 |
-
personality_variables_output, persona_greeting
|
| 637 |
]
|
| 638 |
-
).then(
|
| 639 |
-
fn=generate_personality_chart,
|
| 640 |
-
inputs=[current_persona],
|
| 641 |
-
outputs=[personality_chart_output]
|
| 642 |
)
|
| 643 |
|
|
|
|
| 644 |
send_btn.click(
|
| 645 |
fn=chat_with_loaded_persona,
|
| 646 |
inputs=[current_persona, message_input, chatbot],
|
|
@@ -653,10 +628,32 @@ def create_main_interface():
|
|
| 653 |
outputs=[chatbot, message_input]
|
| 654 |
)
|
| 655 |
|
| 656 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 657 |
app.load(
|
| 658 |
-
fn=
|
| 659 |
-
outputs=[
|
| 660 |
)
|
| 661 |
|
| 662 |
return app
|
|
|
|
| 379 |
print(f"JSON 내보내기 오류: {error_msg}")
|
| 380 |
return None, f"❌ JSON 내보내기 중 오류 발생: {str(e)}"
|
| 381 |
|
| 382 |
+
# def get_saved_personas():
|
| 383 |
+
# """저장된 페르소나 목록 가져오기 - 더 이상 사용하지 않음"""
|
| 384 |
+
# return [], []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 385 |
|
| 386 |
+
# def load_persona_from_selection(selected_row, personas_list):
|
| 387 |
+
# """선택된 페르소나 로드 - 더 이상 사용하지 않음"""
|
| 388 |
+
# return None, "이 기능은 더 이상 사용하지 않습니다. JSON 업로드를 사용하세요.", {}, {}, None, [], [], [], ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 389 |
|
| 390 |
def chat_with_loaded_persona(persona, user_message, chat_history=None):
|
| 391 |
"""페르소나와 대화"""
|
|
|
|
| 407 |
chat_history.append([user_message, f"대화 중 오류가 발생했습니다: {str(e)}"])
|
| 408 |
return chat_history, ""
|
| 409 |
|
| 410 |
+
def import_persona_from_json(json_file):
|
| 411 |
+
"""JSON 파일에서 페르소나 가져오기"""
|
| 412 |
+
if json_file is None:
|
| 413 |
+
return None, "JSON 파일을 업로드해주세요.", "", {}
|
| 414 |
+
|
| 415 |
+
try:
|
| 416 |
+
# JSON 파일 읽기
|
| 417 |
+
if hasattr(json_file, 'name'):
|
| 418 |
+
# 파일 객체인 경우
|
| 419 |
+
with open(json_file.name, 'r', encoding='utf-8') as f:
|
| 420 |
+
persona_data = json.load(f)
|
| 421 |
+
else:
|
| 422 |
+
# 파일 경로인 경우
|
| 423 |
+
with open(json_file, 'r', encoding='utf-8') as f:
|
| 424 |
+
persona_data = json.load(f)
|
| 425 |
+
|
| 426 |
+
# 페르소나 데이터 검증
|
| 427 |
+
if not isinstance(persona_data, dict) or "기본정보" not in persona_data:
|
| 428 |
+
return None, "❌ 올바른 페르소나 JSON 파일이 아닙니다.", "", {}
|
| 429 |
+
|
| 430 |
+
# 기본 정보 추출
|
| 431 |
+
basic_info = {
|
| 432 |
+
"이름": persona_data.get("기본정보", {}).get("이름", "Unknown"),
|
| 433 |
+
"유형": persona_data.get("기본정보", {}).get("유형", "Unknown"),
|
| 434 |
+
"설명": persona_data.get("기본정보", {}).get("설명", "")
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
# 로드된 페르소나 인사말
|
| 438 |
+
persona_name = basic_info.get("이름", "친구")
|
| 439 |
+
greeting = f"### 🤖 {persona_name}\n\n안녕! 나는 **{persona_name}**이야. JSON에서 다시 깨어났어! 대화해보자~ 😊"
|
| 440 |
+
|
| 441 |
+
return (persona_data, f"✅ {persona_name} 페르소나를 JSON에서 불러왔습니다!",
|
| 442 |
+
greeting, basic_info)
|
| 443 |
+
|
| 444 |
+
except json.JSONDecodeError:
|
| 445 |
+
return None, "❌ JSON 파일 형식이 올바르지 않습니다.", "", {}
|
| 446 |
+
except Exception as e:
|
| 447 |
+
import traceback
|
| 448 |
+
error_msg = traceback.format_exc()
|
| 449 |
+
print(f"JSON 불러오기 오류: {error_msg}")
|
| 450 |
+
return None, f"❌ JSON 불러오기 중 오류 발생: {str(e)}", "", {}
|
| 451 |
+
|
| 452 |
# 메인 인터페이스 생성
|
| 453 |
def create_main_interface():
|
| 454 |
# State 변수들 - 올바른 방식으로 생성
|
|
|
|
| 538 |
with gr.Tab("대화하기", id="chat"):
|
| 539 |
with gr.Row():
|
| 540 |
with gr.Column(scale=1):
|
| 541 |
+
gr.Markdown("### 📁 페르소나 불러오기")
|
| 542 |
+
gr.Markdown("JSON 파일을 업로드하여 페르소나를 불러와 대화를 시작하세요.")
|
| 543 |
+
|
| 544 |
+
json_upload = gr.File(
|
| 545 |
+
label="페르소나 JSON 파일 업로드",
|
| 546 |
+
file_types=[".json"],
|
| 547 |
+
type="filepath"
|
| 548 |
)
|
| 549 |
+
import_btn = gr.Button("JSON에서 페르소나 불러오기", variant="primary", size="lg")
|
| 550 |
load_status = gr.Markdown("")
|
| 551 |
+
|
| 552 |
+
# 현재 로드된 페르소나 정보 표시
|
| 553 |
+
with gr.Group():
|
| 554 |
+
gr.Markdown("### 🤖 현재 페르소나")
|
| 555 |
+
chat_persona_greeting = gr.Markdown("", elem_classes=["persona-greeting"])
|
| 556 |
+
current_persona_info = gr.JSON(label="현재 페르소나 정보", visible=False)
|
| 557 |
|
| 558 |
with gr.Column(scale=1):
|
| 559 |
+
gr.Markdown("### 💬 대화")
|
| 560 |
# Gradio 4.x 호환을 위해 명시적으로 type 지정
|
| 561 |
chatbot = gr.Chatbot(height=400, label="대화", type="tuples")
|
| 562 |
with gr.Row():
|
|
|
|
| 566 |
lines=2
|
| 567 |
)
|
| 568 |
send_btn = gr.Button("전송", variant="primary")
|
| 569 |
+
|
| 570 |
+
# 대화 관련 버튼들
|
| 571 |
+
with gr.Row():
|
| 572 |
+
clear_btn = gr.Button("대화 초기화", variant="secondary", size="sm")
|
| 573 |
+
example_btn1 = gr.Button("\"안녕!\"", variant="outline", size="sm")
|
| 574 |
+
example_btn2 = gr.Button("\"너는 누구야?\"", variant="outline", size="sm")
|
| 575 |
+
example_btn3 = gr.Button("\"뭘 좋아해?\"", variant="outline", size="sm")
|
| 576 |
|
| 577 |
# 이벤트 핸들러
|
| 578 |
create_btn.click(
|
|
|
|
| 607 |
outputs=[download_file]
|
| 608 |
)
|
| 609 |
|
| 610 |
+
import_btn.click(
|
| 611 |
+
fn=import_persona_from_json,
|
| 612 |
+
inputs=[json_upload],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 613 |
outputs=[
|
| 614 |
+
current_persona, load_status, chat_persona_greeting, current_persona_info
|
|
|
|
|
|
|
| 615 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
)
|
| 617 |
|
| 618 |
+
# 대화 관련 이벤트 핸들러
|
| 619 |
send_btn.click(
|
| 620 |
fn=chat_with_loaded_persona,
|
| 621 |
inputs=[current_persona, message_input, chatbot],
|
|
|
|
| 628 |
outputs=[chatbot, message_input]
|
| 629 |
)
|
| 630 |
|
| 631 |
+
# 대화 초기화
|
| 632 |
+
clear_btn.click(
|
| 633 |
+
fn=lambda: [],
|
| 634 |
+
outputs=[chatbot]
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
+
# 예시 메시지 버튼들
|
| 638 |
+
example_btn1.click(
|
| 639 |
+
fn=lambda: "안녕!",
|
| 640 |
+
outputs=[message_input]
|
| 641 |
+
)
|
| 642 |
+
|
| 643 |
+
example_btn2.click(
|
| 644 |
+
fn=lambda: "너는 누구야?",
|
| 645 |
+
outputs=[message_input]
|
| 646 |
+
)
|
| 647 |
+
|
| 648 |
+
example_btn3.click(
|
| 649 |
+
fn=lambda: "뭘 좋아해?",
|
| 650 |
+
outputs=[message_input]
|
| 651 |
+
)
|
| 652 |
+
|
| 653 |
+
# 앱 로드 시 페르소나 목록 로드 (백엔드에서 사용)
|
| 654 |
app.load(
|
| 655 |
+
fn=lambda: [],
|
| 656 |
+
outputs=[personas_list]
|
| 657 |
)
|
| 658 |
|
| 659 |
return app
|