Spaces:
Running
Running
/** | |
* 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('μ€λμ€ μ²λ¦¬ μ€ μ€λ₯κ° λ°μνμ΅λλ€. λ€μ μλν΄ μ£ΌμΈμ.'); | |
} | |
} | |