Spaces:
Sleeping
Sleeping
| /** | |
| * RAG κ²μ μ±λ΄ LLM κ΄λ ¨ JavaScript | |
| */ | |
| /** | |
| * LLM λͺ©λ‘ λ‘λ ν¨μ | |
| */ | |
| async function loadLLMs() { | |
| try { | |
| console.log('LLM λͺ©λ‘ λ‘λ μμ'); | |
| // API μμ² | |
| const response = await fetch('/api/llm'); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| supportedLLMs = data.supported_llms; | |
| currentLLM = data.current_llm.id; | |
| console.log(`λ‘λλ LLM μ: ${supportedLLMs.length}, νμ¬ LLM: ${currentLLM}`); | |
| // LLM μ ν λλ‘λ€μ΄ μ λ°μ΄νΈ | |
| llmSelect.innerHTML = ''; | |
| supportedLLMs.forEach(llm => { | |
| const option = document.createElement('option'); | |
| option.value = llm.id; | |
| option.textContent = llm.name; | |
| option.selected = llm.current; | |
| llmSelect.appendChild(option); | |
| }); | |
| // νμ¬ LLM νμ | |
| updateCurrentLLMInfo(data.current_llm); | |
| console.log('LLM λͺ©λ‘ λ‘λ μλ£'); | |
| } catch (error) { | |
| console.error('LLM λͺ©λ‘ λ‘λ μ€ν¨:', error); | |
| } | |
| } | |
| /** | |
| * LLM λ³κ²½ ν¨μ | |
| * @param {string} llmId - λ³κ²½ν LLM ID | |
| */ | |
| async function changeLLM(llmId) { | |
| try { | |
| console.log(`LLM λ³κ²½ μμ: ${llmId}`); | |
| // API μμ² | |
| const response = await fetch('/api/llm', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ llm_id: llmId }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| if (data.success) { | |
| currentLLM = llmId; | |
| updateCurrentLLMInfo(data.current_llm); | |
| console.log(`LLM λ³κ²½ μ±κ³΅: ${data.current_llm.name}`); | |
| // μμ€ν λ©μμ§ μΆκ° | |
| const systemMessage = `LLMμ΄ ${data.current_llm.name}(μΌ)λ‘ λ³κ²½λμμ΅λλ€. λͺ¨λΈ: ${data.current_llm.model}`; | |
| addSystemNotification(systemMessage); | |
| } else if (data.error) { | |
| console.error('LLM λ³κ²½ μ€λ₯:', data.error); | |
| alert(`LLM λ³κ²½ μ€λ₯: ${data.error}`); | |
| } | |
| } catch (error) { | |
| console.error('LLM λ³κ²½ μ€ν¨:', error); | |
| alert('LLM λ³κ²½ μ€ μ€λ₯κ° λ°μνμ΅λλ€.'); | |
| } | |
| } | |
| /** | |
| * νμ¬ LLM μ 보 νμ μ λ°μ΄νΈ | |
| * @param {Object} llmInfo - LLM μ 보 κ°μ²΄ | |
| */ | |
| function updateCurrentLLMInfo(llmInfo) { | |
| console.log(`νμ¬ LLM μ 보 μ λ°μ΄νΈ: ${llmInfo.name} (${llmInfo.model})`); | |
| if (currentLLMInfo) { | |
| currentLLMInfo.textContent = `${llmInfo.name} (${llmInfo.model})`; | |
| } | |
| } | |
| /** | |
| * μ±ν λ©μμ§ μ μ‘ ν¨μ | |
| */ | |
| async function sendMessage() { | |
| const message = userInput.value.trim(); | |
| if (!message) return; | |
| console.log(`λ©μμ§ μ μ‘: "${message}"`); | |
| // UI μ λ°μ΄νΈ | |
| addMessage(message, 'user'); | |
| userInput.value = ''; | |
| adjustTextareaHeight(); | |
| // λ‘λ© λ©μμ§ μΆκ° | |
| const loadingMessageId = addLoadingMessage(); | |
| try { | |
| console.log('μ±ν API μμ² μμ'); | |
| // API μμ² | |
| const response = await fetch('/api/chat', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| query: message, | |
| llm_id: currentLLM // νμ¬ μ νλ LLM μ μ‘ | |
| }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| console.log('μ±ν API μλ΅ μμ μλ£'); | |
| // λ‘λ© λ©μμ§ μ κ±° | |
| removeLoadingMessage(loadingMessageId); | |
| // μλ΅ νμ | |
| if (data.error) { | |
| console.error('μ±ν μλ΅ μ€λ₯:', data.error); | |
| addErrorMessage(data.error); | |
| } else { | |
| // LLM μ 보 μ λ°μ΄νΈ | |
| if (data.llm) { | |
| updateCurrentLLMInfo(data.llm); | |
| } | |
| console.log('λ΄ μλ΅ νμ'); | |
| addMessage(data.answer, 'bot', null, data.sources); | |
| } | |
| } catch (error) { | |
| console.error('μ±ν μμ² μ€λ₯:', error); | |
| removeLoadingMessage(loadingMessageId); | |
| addErrorMessage('μ€λ₯κ° λ°μνμ΅λλ€. λ€μ μλν΄ μ£ΌμΈμ.'); | |
| } | |
| } | |
| /** | |
| * μμ± λ Ήμ μμ ν¨μ | |
| */ | |
| async function startRecording() { | |
| if (isRecording) return; | |
| console.log('μμ± λ Ήμ μμ μμ²'); | |
| try { | |
| const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | |
| isRecording = true; | |
| audioChunks = []; | |
| mediaRecorder = new MediaRecorder(stream); | |
| mediaRecorder.addEventListener('dataavailable', (event) => { | |
| if (event.data.size > 0) audioChunks.push(event.data); | |
| console.log('μ€λμ€ λ°μ΄ν° μ²ν¬ μμ λ¨'); | |
| }); | |
| mediaRecorder.addEventListener('stop', sendAudioMessage); | |
| // λ Ήμ μμ | |
| mediaRecorder.start(); | |
| console.log('MediaRecorder μμλ¨'); | |
| // UI μ λ°μ΄νΈ | |
| micButton.style.display = 'none'; | |
| recordingStatus.classList.remove('hidden'); | |
| } catch (error) { | |
| console.error('μμ± λ Ήμ κΆνμ μ»μ μ μμ΅λλ€:', error); | |
| alert('λ§μ΄ν¬ μ κ·Ό κΆνμ΄ νμν©λλ€.'); | |
| } | |
| } | |
| /** | |
| * μμ± λ Ήμ μ€μ§ ν¨μ | |
| */ | |
| function stopRecording() { | |
| if (!isRecording || !mediaRecorder) return; | |
| console.log('μμ± λ Ήμ μ€μ§ μμ²'); | |
| mediaRecorder.stop(); | |
| isRecording = false; | |
| // UI μ λ°μ΄νΈ | |
| micButton.style.display = 'flex'; | |
| recordingStatus.classList.add('hidden'); | |
| console.log('MediaRecorder μ€μ§λ¨'); | |
| } | |
| /** | |
| * λ Ήμλ μ€λμ€ λ©μμ§ μ μ‘ ν¨μ | |
| */ | |
| async function sendAudioMessage() { | |
| if (audioChunks.length === 0) return; | |
| console.log(`μ€λμ€ λ©μμ§ μ μ‘ μ€λΉ, ${audioChunks.length}κ° μ²ν¬`); | |
| // μ€λμ€ Blob μμ± | |
| const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); | |
| // λ‘λ© λ©μμ§ μΆκ° | |
| const loadingMessageId = addLoadingMessage(); | |
| try { | |
| // FormDataμ μ€λμ€ μΆκ° | |
| const formData = new FormData(); | |
| formData.append('audio', audioBlob, 'recording.wav'); | |
| // νμ¬ μ νλ LLM μΆκ° | |
| formData.append('llm_id', currentLLM); | |
| console.log('μμ± API μμ² μμ'); | |
| // API μμ² | |
| const response = await fetch('/api/voice', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| console.log('μμ± API μλ΅ μμ μλ£'); | |
| // λ‘λ© λ©μμ§ μ κ±° | |
| removeLoadingMessage(loadingMessageId); | |
| // μλ΅ νμ | |
| if (data.error) { | |
| console.error('μμ± μλ΅ μ€λ₯:', data.error); | |
| addErrorMessage(data.error); | |
| } else { | |
| // LLM μ 보 μ λ°μ΄νΈ | |
| if (data.llm) { | |
| updateCurrentLLMInfo(data.llm); | |
| } | |
| // μ¬μ©μ λ©μμ§(μμ± ν μ€νΈ) μΆκ° | |
| if (data.transcription) { | |
| console.log(`μμ± μΈμ κ²°κ³Ό: "${data.transcription}"`); | |
| addMessage(data.transcription, 'user'); | |
| } | |
| // λ΄ μλ΅ μΆκ° | |
| console.log('λ΄ μλ΅ νμ'); | |
| addMessage(data.answer, 'bot', data.transcription, data.sources); | |
| } | |
| } catch (error) { | |
| console.error('μμ± μμ² μ€λ₯:', error); | |
| removeLoadingMessage(loadingMessageId); | |
| addErrorMessage('μ€λμ€ μ²λ¦¬ μ€ μ€λ₯κ° λ°μνμ΅λλ€. λ€μ μλν΄ μ£ΌμΈμ.'); | |
| } | |
| } | |