Spaces:
Sleeping
Sleeping
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>
|