humanda5 commited on
Commit
00b7ce9
·
1 Parent(s): e01cc89

api key 변경 ui 추가

Browse files
npc_social_network/data/vectorstores/alice.faiss CHANGED
Binary files a/npc_social_network/data/vectorstores/alice.faiss and b/npc_social_network/data/vectorstores/alice.faiss differ
 
npc_social_network/routes/npc_route.py CHANGED
@@ -224,4 +224,26 @@ def toggle_player():
224
  is_active = simulation_core.npc_manager.player_is_active
225
  status_text = "활성화" if is_active else "비활성화"
226
  simulation_core.add_log(f"플레이어 상태가 '{status_text}'로 변경되었습니다.")
227
- return jsonify({"success": True, "player_is_active": is_active})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  is_active = simulation_core.npc_manager.player_is_active
225
  status_text = "활성화" if is_active else "비활성화"
226
  simulation_core.add_log(f"플레이어 상태가 '{status_text}'로 변경되었습니다.")
227
+ return jsonify({"success": True, "player_is_active": is_active})
228
+
229
+ @npc_bp.route("/api/set_llm_config", methods=['POST'])
230
+ def set_llm_config():
231
+ """UI로부터 받은 모델과 API 키로 LLM을 실시간으로 재설정하는 API"""
232
+ from ..models.gemini_setup import initialize_model
233
+
234
+ data = request.json
235
+ model_name = data.get("model_name")
236
+ api_key = data.get("api_key")
237
+
238
+ if not all([model_name, api_key]):
239
+ return jsonify({"success": False, "error": "모델과 API 키를 모두 입력해주세요."}), 400
240
+
241
+ # 새로운 설정으로 모델을 초기화 시도
242
+ new_model = initialize_model(model_name, api_key)
243
+
244
+ if new_model:
245
+ # 성공 시, simulation_core의 전역 모델 객체를 새로운 모델로 교체
246
+ simulation_core.active_llm_model = new_model
247
+ return jsonify({"success": True})
248
+ else:
249
+ return jsonify({"success": False, "error": "API 키가 유효하지 않거나 모델 초기화에 실패했습니다."}), 400
templates/dashboard.html CHANGED
@@ -63,6 +63,7 @@
63
  </head>
64
  <body>
65
  <div id="api-modal-overlay">
 
66
  <div id="api-modal-content">
67
  <h2>시뮬레이션 시작</h2>
68
  <p>사용할 LLM 모델과 API 키를 입력해주세요.</p>
@@ -71,7 +72,7 @@
71
  <option value="gemini-2.5-flash">Gemini 2.5 Flash</option>
72
  <option value="gemini-2.5-pro">Gemini 2.5 Pro</option>
73
  </select>
74
- <input type="password" id="api-key-input" placeholder="API Key를 여기에 붙여넣으세요">
75
  <button id="start-simulation-btn">시작하기</button>
76
  <p id="api-modal-message" style="color: red; margin-top: 10px;"></p>
77
  </div>
@@ -93,7 +94,18 @@
93
  <button id="tick-btn">Next Tick</button>
94
  <button id="player-toggle-btn">플레이어 상태: 비활성화</button>
95
  <button id="fit-btn">관계도 보기</button>
 
96
  </div>
 
 
 
 
 
 
 
 
 
 
97
  <!-- 개입 기능 선택 -->
98
  <div id="intervention-area" style="display: flex; gap: 15px; align-items: flex-start;">
99
  <div id="intervention-tabs">
@@ -152,7 +164,12 @@
152
  const apiKeyInput = document.getElementById('api-key-input');
153
  const startSimBtn = document.getElementById('start-simulation-btn');
154
  const apiModalMsg = document.getElementById('api-modal-message');
155
-
 
 
 
 
 
156
  // UI 요소 가져오기
157
  const networkContainer = document.getElementById('network');
158
  const logContainer = document.getElementById('log-container');
@@ -409,6 +426,36 @@
409
  });
410
  await updateWorld();
411
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
  // 모든 이벤트 리스너 복구
414
  playPauseBtn.addEventListener('click', async () => {
@@ -460,7 +507,8 @@
460
  });
461
 
462
  // 초기 로드
463
- updateWorld();
 
464
  });
465
  </script>
466
  </body>
 
63
  </head>
64
  <body>
65
  <div id="api-modal-overlay">
66
+ <!-- API 키 입력_1 -->
67
  <div id="api-modal-content">
68
  <h2>시뮬레이션 시작</h2>
69
  <p>사용할 LLM 모델과 API 키를 입력해주세요.</p>
 
72
  <option value="gemini-2.5-flash">Gemini 2.5 Flash</option>
73
  <option value="gemini-2.5-pro">Gemini 2.5 Pro</option>
74
  </select>
75
+ <input type="password" id="api-key-input" placeholder="API Key를 여기에 입력하세요">
76
  <button id="start-simulation-btn">시작하기</button>
77
  <p id="api-modal-message" style="color: red; margin-top: 10px;"></p>
78
  </div>
 
94
  <button id="tick-btn">Next Tick</button>
95
  <button id="player-toggle-btn">플레이어 상태: 비활성화</button>
96
  <button id="fit-btn">관계도 보기</button>
97
+ <button id="api-settings-toggle-btn" style="margin-left: auto;">API 설정</button>
98
  </div>
99
+ <!-- API 키 입력_2 -->
100
+ <div id="ingame-api-panel" class="control-panel" style="display: none; flex-direction: row; gap: 10px; background-color: #e9ecef; padding: 10px; border-radius: 8px;">
101
+ <select id="ingame-llm-model-select" style="flex: 1;">
102
+ <option value="gemini-2.0-flash">[추천] Gemini 2.0 Flash</option>
103
+ <option value="gemini-2.5-flash">Gemini 2.5 Flash</option>
104
+ <option value="gemini-2.5-pro">Gemini 2.5 Pro</option>
105
+ </select>
106
+ <input type="password" id="ingame-api-key-input" placeholder="API Key를 여기에 입력하세요" style="flex: 2;">
107
+ <button id="ingame-api-key-save-btn" style="flex: 1;">API 변경</button>
108
+ </div>
109
  <!-- 개입 기능 선택 -->
110
  <div id="intervention-area" style="display: flex; gap: 15px; align-items: flex-start;">
111
  <div id="intervention-tabs">
 
164
  const apiKeyInput = document.getElementById('api-key-input');
165
  const startSimBtn = document.getElementById('start-simulation-btn');
166
  const apiModalMsg = document.getElementById('api-modal-message');
167
+ // API 입력 2
168
+ const apiSettingsToggleBtn = document.getElementById('api-settings-toggle-btn');
169
+ const ingameApiPanel = document.getElementById('ingame-api-panel');
170
+ const ingameLlmModelSelect = document.getElementById('ingame-llm-model-select');
171
+ const ingameApiKeyInput = document.getElementById('ingame-api-key-input');
172
+ const ingameApiKeySaveBtn = document.getElementById('ingame-api-key-save-btn');
173
  // UI 요소 가져오기
174
  const networkContainer = document.getElementById('network');
175
  const logContainer = document.getElementById('log-container');
 
426
  });
427
  await updateWorld();
428
  });
429
+ // 인게임 API 설정 패널 토글 이벤트
430
+ apiSettingsToggleBtn.addEventListener('click', () => {
431
+ const isHidden = ingameApiPanel.style.display === 'none';
432
+ ingameApiPanel.style.display = isHidden ? 'flex' : 'none';
433
+ });
434
+ // 인게임 'API 변경' 버튼 이벤트 리스너
435
+ ingameApiKeySaveBtn.addEventListener('click', async () => {
436
+ const model_name = ingameLlmModelSelect.value;
437
+ const api_key = ingameApiKeyInput.value;
438
+
439
+ if (!api_key) {
440
+ return alert('새로운 API 키를 입력해주세요.');
441
+ }
442
+
443
+ ingameApiKeySaveBtn.textContent = '변경 중...';
444
+ const response = await fetch('/api/set_llm_config', { // 2단계에서 만들 API
445
+ method: 'POST',
446
+ headers: { 'Content-Type': 'application/json' },
447
+ body: JSON.stringify({ model_name, api_key })
448
+ });
449
+
450
+ const data = await response.json();
451
+ if (data.success) {
452
+ alert(`API 설정이 변경되었습니다. 이제부터 [${model_name}] 모델을 사용합니다.`);
453
+ ingameApiKeyInput.value = ''; // 입력창 비우기
454
+ } else {
455
+ alert(`API 변경 실패: ${data.error}`);
456
+ }
457
+ ingameApiKeySaveBtn.textContent = 'API 변경';
458
+ });
459
 
460
  // 모든 이벤트 리스너 복구
461
  playPauseBtn.addEventListener('click', async () => {
 
507
  });
508
 
509
  // 초기 로드
510
+ await updateWorld();
511
+ setInterval(updateWorld, 5000);
512
  });
513
  </script>
514
  </body>