haepa_mac commited on
Commit
1660aff
·
1 Parent(s): 572fbe8

Fix chat API integration - use global persona_generator with API settings

Browse files
Files changed (4) hide show
  1. .env.example +2 -0
  2. README.md +87 -2
  3. app.py +33 -15
  4. debug_api.py +146 -0
.env.example ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ GEMINI_API_KEY=your_gemini_api_key_here
2
+ OPENAI_API_KEY=your_openai_api_key_here
README.md CHANGED
@@ -10,9 +10,94 @@ pinned: false
10
  license: mit
11
  ---
12
 
13
- # 놈팽쓰(MemoryTag) 테스트
14
 
15
- 사물에 영혼을 불어넣어 대화할 있는 페르소나 생성 테스트 앱입니다. 놈팽쓰 UX 가이드에 따라 사물의 영혼을 깨우고 대화하는 경험을 제공합니다.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  ## 주요 기능
18
 
 
10
  license: mit
11
  ---
12
 
13
+ # 놈팽쓰 (NomPang-S) - AI 페르소나 생성 시스템
14
 
15
+ 127개 변수를 활용한 한국형 AI 페르소나 생성 대화 시스템
16
+
17
+ ## 🚀 주요 기능
18
+
19
+ - **127개 변수 성격 시스템**: 온기, 능력, 외향성, 유머 등 세밀한 성격 설정
20
+ - **8가지 성격 유형**: 열정적 엔터테이너, 차가운 완벽주의자, 따뜻한 상담사 등
21
+ - **멀티 API 지원**: Gemini와 OpenAI GPT-4o/GPT-4o-mini 동시 지원
22
+ - **매력적 결함 시스템**: 완벽하지 않기에 더 매력적인 캐릭터
23
+ - **유머 매트릭스**: 3차원 유머 좌표계로 개성 있는 대화
24
+
25
+ ## ⚙️ API 키 설정 (필수)
26
+
27
+ 대화 기능을 사용하려면 **API 키를 반드시 설정해야 합니다.**
28
+
29
+ ### 로컬 개발 환경
30
+
31
+ 1. `.env` 파일 생성:
32
+ ```bash
33
+ # .env 파일에 다음 내용 추가
34
+ GEMINI_API_KEY=your_gemini_api_key_here
35
+ OPENAI_API_KEY=your_openai_api_key_here
36
+ ```
37
+
38
+ 2. API 키 발급 방법:
39
+ - **Gemini API**: https://makersuite.google.com/app/apikey
40
+ - **OpenAI API**: https://platform.openai.com/api-keys
41
+
42
+ ### Hugging Face Spaces 환경
43
+
44
+ 1. **Spaces Settings** → **Variables and secrets** 이동
45
+ 2. 다음 환경변수 추가:
46
+ ```
47
+ GEMINI_API_KEY = your_gemini_api_key_here
48
+ OPENAI_API_KEY = your_openai_api_key_here
49
+ ```
50
+ 3. **Restart Space** 클릭하여 적용
51
+
52
+ ## 🔧 API 연결 테스트
53
+
54
+ ```bash
55
+ python debug_api.py
56
+ ```
57
+
58
+ ## 💡 사용법
59
+
60
+ 1. **이미지 업로드**: 페르소나를 만들고 싶은 사물의 사진 업로드
61
+ 2. **API 설정**: 상단의 API 설정에서 Gemini 또는 OpenAI 선택 및 키 입력
62
+ 3. **페르소나 생성**: 127개 변수로 구성된 고유한 성격 자동 생성
63
+ 4. **대화하기**: 생성된 페르소나와 자연스러운 대화 시작
64
+
65
+ ## 🎭 성격 유형
66
+
67
+ - **열정적 엔터테이너**: 온기↑ + 유머↑ + 외향성↑
68
+ - **차가운 완벽주의자**: 능력↑ + 온기↓ + 외향성↓
69
+ - **따뜻한 상담사**: 온기↑ + 공감↑ + 유머↓
70
+ - **위트 넘치는 지식인**: 능력↑ + 유머↑ + 온기↓
71
+ - **수줍은 몽상가**: 외향성↓ + 창의성↑ + 온기=
72
+ - **카리스마틱 리더**: 능력↑ + 외향성↑ + 온기=
73
+ - **장난꾸러기 친구**: 유머↑ + 외향성↑ + 능력↓
74
+ - **신비로운 현자**: 창의성↑ + 외향성↓ + 능력↑
75
+
76
+ ## 🐛 문제 해결
77
+
78
+ **"뭔가 문제가 생긴 것 같아" 메시지가 반복될 때:**
79
+ - API 키가 설정되지 않은 상태입니다
80
+ - 위의 API 키 설정 방법을 따라 설정하세요
81
+ - `python debug_api.py`로 연결 상태를 확인하세요
82
+
83
+ ## 📦 의존성
84
+
85
+ ```
86
+ gradio>=4.0.0
87
+ google-generativeai>=0.3.0
88
+ openai==1.54.3
89
+ pillow>=9.0.0
90
+ matplotlib>=3.5.0
91
+ python-dotenv>=0.19.0
92
+ ```
93
+
94
+ ## 🤝 기여
95
+
96
+ 이슈 리포트와 풀 리퀘스트를 환영합니다!
97
+
98
+ ---
99
+
100
+ **Made with ❤️ for Korean AI Persona Generation**
101
 
102
  ## 주요 기능
103
 
app.py CHANGED
@@ -194,7 +194,9 @@ HUMOR_STYLE_MAPPING = {
194
  }
195
 
196
  def create_persona_from_image(image, name, location, time_spent, object_type, progress=gr.Progress()):
197
- """페르소나 생성 함수 - 초기 생성만"""
 
 
198
  if image is None:
199
  return None, "이미지를 업로드해주세요.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
200
 
@@ -222,18 +224,20 @@ def create_persona_from_image(image, name, location, time_spent, object_type, pr
222
  if image.format in ['AVIF', 'WEBP'] or image.mode not in ['RGB', 'RGBA']:
223
  image = image.convert('RGB')
224
 
225
- generator = PersonaGenerator()
 
 
226
 
227
  progress(0.3, desc="이미지 분석 중...")
228
  # 이미지 처리 방식 수정 - PIL Image 객체를 직접 전달
229
- image_analysis = generator.analyze_image(image)
230
 
231
  progress(0.5, desc="페르소나 생성 중...")
232
  # 프론트엔드 페르소나 생성
233
- frontend_persona = generator.create_frontend_persona(image_analysis, user_context)
234
 
235
  # 백엔드 페르소나 생성 (구조화된 프롬프트 포함)
236
- backend_persona = generator.create_backend_persona(frontend_persona, image_analysis)
237
 
238
  # 페르소나 정보 포맷팅
239
  persona_name = backend_persona["기본정보"]["이름"]
@@ -377,18 +381,22 @@ def adjust_persona_traits(persona, warmth, competence, humor, extraversion, humo
377
  return persona, f"조정 중 오류 발생: {str(e)}", {}
378
 
379
  def finalize_persona(persona):
380
- """페르소나 최종 확정"""
 
 
381
  if not persona:
382
  return None, "페르소나가 없습니다.", "", {}, None, [], [], [], "", None
383
 
384
  try:
385
- generator = PersonaGenerator()
 
 
386
 
387
  # 이미 백엔드 페르소나인 경우와 프론트엔드 페르소나인 경우 구분
388
  if "구조화프롬프트" not in persona:
389
  # 프론트엔드 페르소나인 경우 백엔드 페르소나로 변환
390
  image_analysis = {"object_type": persona.get("기본정보", {}).get("유형", "알 수 없는 사물")}
391
- persona = generator.create_backend_persona(persona, image_analysis)
392
 
393
  persona_name = persona["기본정보"]["이름"]
394
 
@@ -608,7 +616,9 @@ def export_persona_to_json(persona):
608
  # return None, "이 기능은 더 이상 사용하지 않습니다. JSON 업로드를 사용하세요.", {}, {}, None, [], [], [], ""
609
 
610
  def chat_with_loaded_persona(persona, user_message, chat_history=None):
611
- """현재 로드된 페르소나와 대화 - Gradio 5.31.0 호환"""
 
 
612
  if not persona:
613
  return chat_history or [], ""
614
 
@@ -616,7 +626,10 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
616
  return chat_history or [], ""
617
 
618
  try:
619
- generator = PersonaGenerator()
 
 
 
620
 
621
  # 대화 기록을 올바른 형태로 변환 (Gradio 5.x messages 형태)
622
  conversation_history = []
@@ -630,8 +643,8 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
630
  conversation_history.append({"role": "user", "content": message[0]})
631
  conversation_history.append({"role": "assistant", "content": message[1]})
632
 
633
- # 페르소나와 대화
634
- response = generator.chat_with_persona(persona, user_message, conversation_history)
635
 
636
  # 새로운 대화를 messages 형태로 추가
637
  if chat_history is None:
@@ -707,13 +720,18 @@ def import_persona_from_json(json_file):
707
  return None, f"❌ JSON 불러오기 중 오류 발생: {str(e)}", "", {}
708
 
709
  def format_personality_traits(persona):
710
- """성격 특성을 ��용자 친화적인 형태로 포맷 (수치 없이 서술형만)"""
 
 
711
  if not persona or "성격특성" not in persona:
712
  return "페르소나가 생성되지 않았습니다."
713
 
714
- generator = PersonaGenerator()
 
 
 
715
  personality_traits = persona["성격특성"]
716
- descriptions = generator.get_personality_descriptions(personality_traits)
717
 
718
  result = "### 🌟 성격 특성\n\n"
719
  for trait, description in descriptions.items():
 
194
  }
195
 
196
  def create_persona_from_image(image, name, location, time_spent, object_type, progress=gr.Progress()):
197
+ """페르소나 생성 함수 - API 설정 적용"""
198
+ global persona_generator
199
+
200
  if image is None:
201
  return None, "이미지를 업로드해주세요.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
202
 
 
224
  if image.format in ['AVIF', 'WEBP'] or image.mode not in ['RGB', 'RGBA']:
225
  image = image.convert('RGB')
226
 
227
+ # 글로벌 persona_generator 사용 (API 설정이 적용된 상태)
228
+ if persona_generator is None:
229
+ persona_generator = PersonaGenerator()
230
 
231
  progress(0.3, desc="이미지 분석 중...")
232
  # 이미지 처리 방식 수정 - PIL Image 객체를 직접 전달
233
+ image_analysis = persona_generator.analyze_image(image)
234
 
235
  progress(0.5, desc="페르소나 생성 중...")
236
  # 프론트엔드 페르소나 생성
237
+ frontend_persona = persona_generator.create_frontend_persona(image_analysis, user_context)
238
 
239
  # 백엔드 페르소나 생성 (구조화된 프롬프트 포함)
240
+ backend_persona = persona_generator.create_backend_persona(frontend_persona, image_analysis)
241
 
242
  # 페르소나 정보 포맷팅
243
  persona_name = backend_persona["기본정보"]["이름"]
 
381
  return persona, f"조정 중 오류 발생: {str(e)}", {}
382
 
383
  def finalize_persona(persona):
384
+ """페르소나 최종 확정 - API 설정 적용"""
385
+ global persona_generator
386
+
387
  if not persona:
388
  return None, "페르소나가 없습니다.", "", {}, None, [], [], [], "", None
389
 
390
  try:
391
+ # 글로벌 persona_generator 사용 (API 설정이 적용된 상태)
392
+ if persona_generator is None:
393
+ persona_generator = PersonaGenerator()
394
 
395
  # 이미 백엔드 페르소나인 경우와 프론트엔드 페르소나인 경우 구분
396
  if "구조화프롬프트" not in persona:
397
  # 프론트엔드 페르소나인 경우 백엔드 페르소나로 변환
398
  image_analysis = {"object_type": persona.get("기본정보", {}).get("유형", "알 수 없는 사물")}
399
+ persona = persona_generator.create_backend_persona(persona, image_analysis)
400
 
401
  persona_name = persona["기본정보"]["이름"]
402
 
 
616
  # return None, "이 기능은 더 이상 사용하지 않습니다. JSON 업로드를 사용하세요.", {}, {}, None, [], [], [], ""
617
 
618
  def chat_with_loaded_persona(persona, user_message, chat_history=None):
619
+ """현재 로드된 페르소나와 대화 - API 설정 적용"""
620
+ global persona_generator
621
+
622
  if not persona:
623
  return chat_history or [], ""
624
 
 
626
  return chat_history or [], ""
627
 
628
  try:
629
+ # 글로벌 persona_generator 사용 (API 설정이 적용된 상태)
630
+ if persona_generator is None:
631
+ # 기본 persona_generator가 없는 경우 생성
632
+ persona_generator = PersonaGenerator()
633
 
634
  # 대화 기록을 올바른 형태로 변환 (Gradio 5.x messages 형태)
635
  conversation_history = []
 
643
  conversation_history.append({"role": "user", "content": message[0]})
644
  conversation_history.append({"role": "assistant", "content": message[1]})
645
 
646
+ # 페르소나와 대화 (설정된 API 사용)
647
+ response = persona_generator.chat_with_persona(persona, user_message, conversation_history)
648
 
649
  # 새로운 대화를 messages 형태로 추가
650
  if chat_history is None:
 
720
  return None, f"❌ JSON 불러오기 중 오류 발생: {str(e)}", "", {}
721
 
722
  def format_personality_traits(persona):
723
+ """성격 특성을 사용자 친화적인 형태로 포맷 (수치 없이 서술형만) - API 설정 적용"""
724
+ global persona_generator
725
+
726
  if not persona or "성격특성" not in persona:
727
  return "페르소나가 생성되지 않았습니다."
728
 
729
+ # 글로벌 persona_generator 사용 (API 설정이 적용된 상태)
730
+ if persona_generator is None:
731
+ persona_generator = PersonaGenerator()
732
+
733
  personality_traits = persona["성격특성"]
734
+ descriptions = persona_generator.get_personality_descriptions(personality_traits)
735
 
736
  result = "### 🌟 성격 특성\n\n"
737
  for trait, description in descriptions.items():
debug_api.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ API 연결 디버깅 스크립트
4
+ 대화 기능이 작동하지 않는 원인을 진단합니다.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ sys.path.append('modules')
10
+
11
+ from persona_generator import PersonaGenerator
12
+ import google.generativeai as genai
13
+
14
+ def test_api_connections():
15
+ """API 연결 상태 테스트"""
16
+
17
+ print("🔍 API 연결 진단을 시작합니다...\n")
18
+
19
+ # 1. 환경변수 확인
20
+ print("1️⃣ 환경변수 확인:")
21
+ gemini_key = os.getenv("GEMINI_API_KEY")
22
+ openai_key = os.getenv("OPENAI_API_KEY")
23
+
24
+ print(f" GEMINI_API_KEY: {'✅ 설정됨' if gemini_key else '❌ 없음'}")
25
+ print(f" OPENAI_API_KEY: {'✅ 설정됨' if openai_key else '❌ 없음'}")
26
+
27
+ if not gemini_key and not openai_key:
28
+ print("\n❌ API 키가 설정되지 않았습니다!")
29
+ print("\n해결 방법:")
30
+ print("1. .env 파일 생성:")
31
+ print(" echo 'GEMINI_API_KEY=your_gemini_key_here' > .env")
32
+ print(" echo 'OPENAI_API_KEY=your_openai_key_here' >> .env")
33
+ print("\n2. 또는 환경변수 직접 설정:")
34
+ print(" export GEMINI_API_KEY=your_gemini_key_here")
35
+ print(" export OPENAI_API_KEY=your_openai_key_here")
36
+ return False
37
+
38
+ # 2. PersonaGenerator 초기화 테스트
39
+ print("\n2️⃣ PersonaGenerator 초기화 테스트:")
40
+
41
+ # Gemini 테스트
42
+ if gemini_key:
43
+ try:
44
+ generator_gemini = PersonaGenerator(api_provider="gemini")
45
+ print(f" Gemini 초기화: ✅ 성공")
46
+ print(f" API 키 길이: {len(gemini_key)} 문자")
47
+ except Exception as e:
48
+ print(f" Gemini 초기화: ❌ 실패 - {str(e)}")
49
+
50
+ # OpenAI 테스트
51
+ if openai_key:
52
+ try:
53
+ generator_openai = PersonaGenerator(api_provider="openai")
54
+ print(f" OpenAI 초기화: ✅ 성공")
55
+ print(f" API 키 길이: {len(openai_key)} 문자")
56
+ except Exception as e:
57
+ print(f" OpenAI 초기화: ❌ 실패 - {str(e)}")
58
+
59
+ # 3. 실제 API 호출 테스트
60
+ print("\n3️⃣ 실제 API 호출 테스트:")
61
+
62
+ if gemini_key:
63
+ try:
64
+ generator = PersonaGenerator(api_provider="gemini")
65
+ test_result = generator._generate_text_with_api("안녕하세요! 간단히 인사해주세요.")
66
+ print(f" Gemini API 호출: ✅ 성공")
67
+ print(f" 응답 길이: {len(test_result)} 문자")
68
+ print(f" 응답 미리보기: {test_result[:100]}...")
69
+ except Exception as e:
70
+ print(f" Gemini API 호출: ❌ 실패 - {str(e)}")
71
+
72
+ if openai_key:
73
+ try:
74
+ generator = PersonaGenerator(api_provider="openai")
75
+ test_result = generator._generate_text_with_api("안녕하세요! 간단히 인사해주세요.")
76
+ print(f" OpenAI API 호출: ✅ 성공")
77
+ print(f" 응답 길이: {len(test_result)} 문자")
78
+ print(f" 응답 미리보기: {test_result[:100]}...")
79
+ except Exception as e:
80
+ print(f" OpenAI API 호출: ❌ 실패 - {str(e)}")
81
+
82
+ # 4. 페르소나 대화 테스트
83
+ print("\n4️⃣ 페르소나 대화 테스트:")
84
+
85
+ # 간단한 테스트 페르소나 생성
86
+ test_persona = {
87
+ "기본정보": {"이름": "테스트봇", "유형": "테스트"},
88
+ "성격특성": {
89
+ "온기": 70,
90
+ "능력": 50,
91
+ "외향성": 60,
92
+ "친화성": 65,
93
+ "성실성": 55,
94
+ "신경증": 40,
95
+ "개방성": 60,
96
+ "창의성": 55,
97
+ "유머감각": 65,
98
+ "공감능력": 70
99
+ }
100
+ }
101
+
102
+ available_apis = []
103
+ if gemini_key:
104
+ available_apis.append("gemini")
105
+ if openai_key:
106
+ available_apis.append("openai")
107
+
108
+ for api in available_apis:
109
+ try:
110
+ generator = PersonaGenerator(api_provider=api)
111
+ response = generator.chat_with_persona(test_persona, "안녕하세요!")
112
+
113
+ if "API 연결이 설정되지 않아" in response or "뭔가 문제가 생긴 것 같아" in response:
114
+ print(f" {api.upper()} 페르소나 대화: ❌ 실패 - API 오류")
115
+ print(f" 오류 응답: {response}")
116
+ else:
117
+ print(f" {api.upper()} 페르소나 대화: ✅ 성공")
118
+ print(f" 응답: {response[:100]}...")
119
+ except Exception as e:
120
+ print(f" {api.upper()} 페르소나 대화: ❌ 실패 - {str(e)}")
121
+
122
+ print("\n🔍 진단 완료!")
123
+ return True
124
+
125
+ def quick_fix_suggestions():
126
+ """빠른 수정 제안"""
127
+ print("\n💡 빠른 해결 방법:")
128
+ print("1. API 키 설정 (.env 파일 생성):")
129
+ print(" GEMINI_API_KEY=your_actual_api_key_here")
130
+ print(" OPENAI_API_KEY=your_actual_api_key_here")
131
+ print()
132
+ print("2. Gemini API ��� 발급: https://makersuite.google.com/app/apikey")
133
+ print("3. OpenAI API 키 발급: https://platform.openai.com/api-keys")
134
+ print()
135
+ print("4. API 키 형식 확인:")
136
+ print(" - Gemini: AIza... (약 40자)")
137
+ print(" - OpenAI: sk-... (약 60자)")
138
+
139
+ if __name__ == "__main__":
140
+ success = test_api_connections()
141
+
142
+ if not success:
143
+ quick_fix_suggestions()
144
+
145
+ print("\n✨ 문제가 해결되지 않으면 다음 명령어로 재테스트:")
146
+ print(" python debug_api.py")