nps_test / temp /backend_view.py
haepa_mac
Update nompang_test app with 127 personality variables
1c7b7bd
import json
def create_backend_view_html(persona):
"""Create HTML representation of the backend view of the persona"""
if not persona:
return "<div class='persona-details'>페르소나가 아직 생성되지 않았습니다.</div>"
name = persona.get("기본정보", {}).get("이름", "Unknown")
# 백엔드 기본 정보
basic_info = persona.get("기본정보", {})
basic_info_html = ""
for key, value in basic_info.items():
basic_info_html += f"<tr><td><strong>{key}</strong></td><td>{value}</td></tr>"
# 1. 성격 변수 요약
personality_summary = persona.get("성격요약", {})
summary_html = ""
if personality_summary:
summary_html += "<div class='summary-container'>"
for category, value in personality_summary.items():
if isinstance(value, (int, float)):
summary_html += f"""
<div class='summary-item'>
<div class='summary-label'>{category}</div>
<div class='summary-bar-container'>
<div class='summary-bar' style='width: {value}%; background: linear-gradient(90deg, #10b981, #6ee7b7);'></div>
</div>
<div class='summary-value'>{value:.1f}</div>
</div>
"""
summary_html += "</div>"
# 2. 성격 매트릭스 (5차원 빅5 시각화)
big5_html = ""
if "성격특성" in persona:
# 빅5 매핑 (기존 특성에서 변환)
big5 = {
"외향성(Extraversion)": persona.get("성격특성", {}).get("외향성", 50),
"친화성(Agreeableness)": persona.get("성격특성", {}).get("온기", 50),
"성실성(Conscientiousness)": persona.get("성격특성", {}).get("신뢰성", 50),
"신경증(Neuroticism)": 100 - persona.get("성격특성", {}).get("안정성", 50) if "안정성" in persona.get("성격특성", {}) else 50,
"개방성(Openness)": persona.get("성격특성", {}).get("창의성", 50)
}
big5_html = "<div class='big5-matrix'>"
for trait, value in big5.items():
big5_html += f"""
<div class='big5-item'>
<div class='big5-label'>{trait}</div>
<div class='big5-bar-container'>
<div class='big5-bar' style='width: {value}%;'></div>
</div>
<div class='big5-value'>{value}%</div>
</div>
"""
big5_html += "</div>"
# 3. 유머 매트릭스
humor_matrix = persona.get("유머매트릭스", {})
humor_html = ""
if humor_matrix:
warmth_vs_wit = humor_matrix.get("warmth_vs_wit", 50)
self_vs_observational = humor_matrix.get("self_vs_observational", 50)
subtle_vs_expressive = humor_matrix.get("subtle_vs_expressive", 50)
humor_html = f"""
<div class='humor-matrix'>
<div class='humor-dimension'>
<div class='dimension-label'>따뜻함 vs 위트</div>
<div class='dimension-bar-container'>
<div class='dimension-indicator' style='left: {warmth_vs_wit}%;'></div>
<div class='dimension-label-left'>위트</div>
<div class='dimension-label-right'>따뜻함</div>
</div>
</div>
<div class='humor-dimension'>
<div class='dimension-label'>자기참조 vs 관찰형</div>
<div class='dimension-bar-container'>
<div class='dimension-indicator' style='left: {self_vs_observational}%;'></div>
<div class='dimension-label-left'>관찰형</div>
<div class='dimension-label-right'>자기참조</div>
</div>
</div>
<div class='humor-dimension'>
<div class='dimension-label'>미묘함 vs 표현적</div>
<div class='dimension-bar-container'>
<div class='dimension-indicator' style='left: {subtle_vs_expressive}%;'></div>
<div class='dimension-label-left'>미묘함</div>
<div class='dimension-label-right'>표현적</div>
</div>
</div>
</div>
"""
# 4. 매력적 결함과 모순적 특성
flaws_html = ""
contradictions_html = ""
flaws = persona.get("매력적결함", [])
if flaws:
flaws_html = "<ul class='flaws-list'>"
for flaw in flaws:
flaws_html += f"<li>{flaw}</li>"
flaws_html += "</ul>"
contradictions = persona.get("모순적특성", [])
if contradictions:
contradictions_html = "<ul class='contradictions-list'>"
for contradiction in contradictions:
contradictions_html += f"<li>{contradiction}</li>"
contradictions_html += "</ul>"
# 6. 프롬프트 템플릿 (있는 경우)
prompt_html = ""
if "프롬프트" in persona:
prompt_text = persona.get("프롬프트", "")
prompt_html = f"""
<div class='prompt-section'>
<h3 class='section-title'>대화 프롬프트</h3>
<pre class='prompt-text'>{prompt_text}</pre>
</div>
"""
# 7. 완전한 백엔드 JSON (접이식)
try:
# 내부 상태 객체 제거 (JSON 변환 불가)
json_persona = {k: v for k, v in persona.items() if k not in ["personality_profile", "humor_matrix"]}
persona_json = json.dumps(json_persona, ensure_ascii=False, indent=2)
json_preview = f"""
<details class='json-details'>
<summary>전체 백엔드 데이터 (JSON)</summary>
<pre class='json-preview'>{persona_json}</pre>
</details>
"""
except Exception as e:
json_preview = f"<div class='error'>JSON 변환 오류: {str(e)}</div>"
# 8. 전체 HTML 조합
html = f"""
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap');
.backend-persona {{
font-family: 'Noto Sans KR', sans-serif;
color: #333;
max-width: 100%;
}}
.backend-header {{
background: linear-gradient(135deg, #059669, #34d399);
padding: 20px;
border-radius: 12px;
color: white;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}}
.backend-header h2 {{
margin: 0;
font-size: 24px;
}}
.backend-header p {{
margin: 5px 0 0 0;
opacity: 0.9;
}}
.backend-section {{
background: #f8f9fa;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
border: 1px solid #e0e0e0;
}}
.section-title {{
font-size: 18px;
margin: 0 0 10px 0;
color: #444;
border-bottom: 2px solid #10b981;
padding-bottom: 5px;
display: inline-block;
}}
/* 기본 정보 테이블 */
.basic-info-table {{
width: 100%;
border-collapse: collapse;
}}
.basic-info-table td {{
padding: 8px;
border-bottom: 1px solid #e0e0e0;
}}
.basic-info-table td:first-child {{
width: 120px;
font-weight: 500;
}}
/* 요약 스타일 */
.summary-container {{
margin-top: 10px;
}}
.summary-item {{
display: flex;
align-items: center;
margin-bottom: 8px;
}}
.summary-label {{
width: 150px;
font-weight: 500;
}}
.summary-bar-container {{
flex-grow: 1;
background: #e0e0e0;
height: 10px;
border-radius: 5px;
margin: 0 10px;
overflow: hidden;
}}
.summary-bar {{
height: 100%;
border-radius: 5px;
}}
.summary-value {{
width: 40px;
text-align: right;
font-size: 14px;
}}
/* 빅5 성격 매트릭스 */
.big5-matrix {{
margin-top: 15px;
}}
.big5-item {{
display: flex;
align-items: center;
margin-bottom: 12px;
}}
.big5-label {{
width: 150px;
font-weight: 500;
}}
.big5-bar-container {{
flex-grow: 1;
background: #e0e0e0;
height: 12px;
border-radius: 6px;
margin: 0 10px;
overflow: hidden;
}}
.big5-bar {{
height: 100%;
border-radius: 6px;
background: linear-gradient(90deg, #10b981, #34d399);
}}
.big5-value {{
width: 40px;
text-align: right;
font-weight: 500;
}}
/* 유머 매트릭스 스타일 */
.humor-matrix {{
margin-top: 15px;
}}
.humor-dimension {{
margin-bottom: 20px;
}}
.dimension-label {{
font-weight: 500;
margin-bottom: 5px;
}}
.dimension-bar-container {{
height: 20px;
background: #e0e0e0;
border-radius: 10px;
position: relative;
margin-top: 5px;
}}
.dimension-indicator {{
width: 20px;
height: 20px;
background: #10b981;
border-radius: 50%;
position: absolute;
top: 0;
transform: translateX(-50%);
}}
.dimension-label-left, .dimension-label-right {{
position: absolute;
top: -20px;
font-size: 12px;
color: #666;
}}
.dimension-label-left {{
left: 10px;
}}
.dimension-label-right {{
right: 10px;
}}
/* 매력적 결함 및 모순적 특성 */
.flaws-list, .contradictions-list {{
margin: 0;
padding-left: 20px;
}}
.flaws-list li, .contradictions-list li {{
margin-bottom: 6px;
}}
/* 프롬프트 섹션 */
.prompt-text {{
background: #f3f4f6;
border-radius: 6px;
padding: 15px;
font-family: monospace;
white-space: pre-wrap;
font-size: 14px;
color: #374151;
max-height: 400px;
overflow-y: auto;
}}
/* JSON 미리보기 스타일 */
.json-details {{
margin-top: 15px;
}}
.json-details summary {{
cursor: pointer;
padding: 10px;
background: #f0f0f0;
border-radius: 5px;
font-weight: 500;
}}
.json-preview {{
background: #f8f8f8;
padding: 15px;
border-radius: 5px;
border: 1px solid #ddd;
margin-top: 10px;
overflow-x: auto;
color: #333;
font-family: monospace;
font-size: 14px;
line-height: 1.5;
max-height: 400px;
overflow-y: auto;
}}
.error {{
color: #e53e3e;
padding: 10px;
background: #fff5f5;
border-radius: 5px;
margin-top: 10px;
}}
</style>
<div class="backend-persona">
<div class="backend-header">
<h2>{name} - 백엔드 데이터</h2>
<p>상세 정보와 내부 변수 확인</p>
</div>
<div class="backend-section">
<h3 class="section-title">기본 정보</h3>
<table class="basic-info-table">
{basic_info_html}
</table>
</div>
<div class="backend-section">
<h3 class="section-title">성격 요약 (Big 5)</h3>
{big5_html}
</div>
<div class="backend-section">
<h3 class="section-title">유머 매트릭스 (3차원)</h3>
{humor_html}
</div>
<div class="backend-section">
<h3 class="section-title">매력적 결함</h3>
{flaws_html}
<h3 class="section-title" style="margin-top: 20px;">모순적 특성</h3>
{contradictions_html}
</div>
{prompt_html}
<div class="backend-section">
<h3 class="section-title">전체 백엔드 데이터</h3>
{json_preview}
</div>
</div>
"""
return html