Spaces:
Running
Running
Download app.mjs from Valen-Team/Valen-API: direct link, hf CLI and curl.
- Browser
- Download file 9.02 kB
-
https://huggingface.co/spaces/Valen-Team/Valen-API/resolve/main/app.mjs
- Command line
-
hf download hf://spaces/Valen-Team/Valen-API/app.mjs
-
curl -L -o app.mjs https://huggingface.co/spaces/Valen-Team/Valen-API/resolve/main/app.mjs
9.02 kB
| import {buildPayload, previewPayload, pythonExample, requestDecision} from './api.mjs'; | |
| import {words, examples, exampleMedia, ratingOptions} from './locales.mjs'; | |
| import {readMedia} from './media.mjs'; | |
| const $ = id => document.getElementById(id); | |
| let language = new URL(location.href).searchParams.get('lang') === 'zh' ? 'zh' : 'en'; | |
| let imageData, attachment, mediaController, mediaRequired = false, controller, resultData, requestPayload, lastError, state = 'ready', statusKey = ''; | |
| const t = key => words[language][key] || key; | |
| function renderLanguage() { | |
| document.documentElement.lang = language === 'zh' ? 'zh-CN' : 'en'; | |
| document.querySelectorAll('[data-i18n]').forEach(el => {el.textContent = t(el.dataset.i18n);}); | |
| document.querySelectorAll('[data-placeholder]').forEach(el => {el.placeholder = t(el.dataset.placeholder);}); | |
| $('language').textContent = language === 'en' ? '中文' : 'EN'; | |
| $('language').ariaLabel = language === 'en' ? '切换到中文' : 'Switch to English'; | |
| $('theme').ariaLabel = language === 'en' ? 'Switch color theme' : '切换主题'; | |
| configureOptions(); renderState(); | |
| if (resultData) renderAnswer(resultData.answer, resultData.data, requestPayload); | |
| } | |
| function configureOptions() { | |
| $('options-field').hidden = $('mode').value === 'predicate'; | |
| $('options-label').textContent = t($('mode').value === 'score' ? 'levelsLabel' : 'choicesLabel'); | |
| } | |
| function renderState() { | |
| $('state-badge').dataset.state = state; | |
| $('state-badge').textContent = t(state); | |
| $('status').className = state === 'error' ? 'error' : ''; | |
| $('status').textContent = lastError ? (words[language].errors[lastError] || `HTTP ${lastError.replace('http_', '')}`) : statusKey ? t(statusKey) : ''; | |
| } | |
| function clearResult() { | |
| resultData = null; lastError = null; state = 'ready'; statusKey = ''; | |
| $('answer').hidden = true; $('empty').hidden = false; | |
| $('response-json').textContent = ''; $('probabilities').replaceChildren();renderState(); | |
| } | |
| function showError(error) { | |
| state = 'error'; lastError = error instanceof TypeError ? 'network' : error.message; | |
| if (!words[language].errors[lastError] && !/^http_\d+$/.test(lastError)) lastError = 'response'; | |
| renderState(); | |
| } | |
| function currentPayload() { | |
| if(mediaRequired&&!imageData)throw new Error('image'); | |
| return buildPayload({model:$('model').value,mode:$('mode').value,question:$('question').value, | |
| context:$('context').value,options:$('options').value,image:imageData}); | |
| } | |
| function updatePreview(report = false) { | |
| try { | |
| const payload = currentPayload(); | |
| $('python-code').textContent = pythonExample(payload,attachment); | |
| $('request-json').textContent = JSON.stringify(previewPayload(payload),null,2); | |
| $('copy-code').disabled = false;return payload; | |
| } catch (error) { | |
| $('python-code').textContent = t('noCode');$('request-json').textContent = '';$('copy-code').disabled = true; | |
| if (report) showError(error); | |
| } | |
| } | |
| function renderAnswer(answer, data, payload) { | |
| $('empty').hidden = true;$('answer').hidden = false; | |
| const isPredicate = payload.questions[0].type === 'predicate'; | |
| $('decision-title').textContent = isPredicate ? t(answer.title) : answer.title; | |
| $('probabilities').replaceChildren(); | |
| for (const row of answer.rows) { | |
| const label = isPredicate ? t(row.label) : row.label; | |
| const block = document.createElement('div');block.className = 'prob-row'; | |
| const top = document.createElement('div');top.className = 'prob-label'; | |
| const name = document.createElement('span');name.textContent = label; | |
| const number = document.createElement('strong');number.textContent = `${(row.probability*100).toFixed(1)}%`;top.append(name,number); | |
| const progress = document.createElement('progress');progress.max=1;progress.value=row.probability;progress.ariaLabel=label; | |
| block.append(top,progress);$('probabilities').append(block); | |
| } | |
| $('score-note').hidden = payload.questions[0].type !== 'score'; | |
| $('confidence').textContent = answer.confidence === undefined ? '' : `${t('confidence')}: ${(answer.confidence*100).toFixed(1)}%`; | |
| $('model-id').textContent = data.model_id ? `${t('modelId')}: ${data.model_id}` : ''; | |
| $('response-json').textContent = JSON.stringify(data,null,2); | |
| } | |
| function lock(value) { | |
| $('fields').disabled=value; | |
| document.querySelectorAll('[data-example]').forEach(button=>{button.disabled=value;}); | |
| $('preview-code').disabled=value; | |
| } | |
| function removeImage() { | |
| mediaController?.abort();mediaController=null; | |
| $('video-preview').pause();$('video-preview').removeAttribute('src');$('video-preview').load();$('video-preview').hidden=true; | |
| if(attachment?.objectUrl)URL.revokeObjectURL(attachment.objectUrl); | |
| attachment=undefined;imageData=undefined;mediaRequired=false;$('image').value=''; | |
| $('thumbnail').removeAttribute('src');$('image-preview').hidden=true;$('video-note').hidden=true;clearResult();updatePreview(); | |
| } | |
| async function loadMedia(fileOrExample) { | |
| removeImage();mediaRequired=true; | |
| const active=new AbortController();mediaController=active; | |
| lock(true);state='busy';statusKey='reading';renderState(); | |
| try { | |
| let file=fileOrExample; | |
| if(!(file instanceof File)) { | |
| const response=await fetch(file.src,{signal:active.signal});if(!response.ok)throw new Error('image'); | |
| file=new File([await response.blob()],file.name,{type:file.kind==='video'?'video/mp4':'image/jpeg'}); | |
| } | |
| const next=await readMedia(file,active.signal); | |
| if(active.signal.aborted){URL.revokeObjectURL(next.objectUrl);return;} | |
| attachment=next;imageData=next.image; | |
| $('thumbnail').src=imageData;$('image-name').textContent=next.name;$('image-preview').hidden=false; | |
| if(next.kind==='video'){$('video-preview').src=next.video;$('video-preview').poster=imageData;$('video-preview').hidden=false;$('video-note').hidden=false;} | |
| state='ready';statusKey='';renderState();updatePreview(); | |
| } catch(error) { | |
| if(active.signal.aborted)return; | |
| $('image').value='';showError(new Error(error.message==='size'?'size':'image'));updatePreview(); | |
| } finally {if(mediaController===active){mediaController=null;lock(false);}} | |
| } | |
| $('image').addEventListener('change',()=>{ | |
| const file=$('image').files[0];if(!file){removeImage();return;}void loadMedia(file); | |
| }); | |
| $('decision-form').addEventListener('submit', async event => { | |
| event.preventDefault();if(controller||mediaController)return; | |
| clearResult();const payload=updatePreview(true);if(!payload)return; | |
| requestPayload=payload;controller=new AbortController();const active=controller; | |
| const timeout=setTimeout(()=>active.abort('timeout'),120000); | |
| lock(true);$('cancel').hidden=false;state='busy';statusKey='waiting';renderState(); | |
| try { | |
| const result=await requestDecision(payload,active.signal);if(active.signal.aborted)return; | |
| resultData=result;state='success';statusKey='';renderState();renderAnswer(result.answer,result.data,payload); | |
| } catch(error) { | |
| if(active.signal.aborted) { | |
| if(active.signal.reason==='timeout')showError(new Error('timeout')); | |
| else{state='ready';statusKey='cancelled';renderState();} | |
| } else showError(error); | |
| } finally {clearTimeout(timeout);if(controller===active){controller=null;lock(false);$('cancel').hidden=true;}} | |
| }); | |
| $('cancel').addEventListener('click',()=>controller?.abort('cancelled')); | |
| $('remove-image').addEventListener('click',removeImage); | |
| $('language').addEventListener('click',()=>{language=language==='en'?'zh':'en';renderLanguage();updatePreview();}); | |
| $('theme').addEventListener('click',()=>{document.body.dataset.theme=document.body.dataset.theme==='dark'?'light':'dark';}); | |
| $('mode').addEventListener('change',()=>{ | |
| if($('mode').value==='score'&&!$('options').value.trim())$('options').value=ratingOptions[language];configureOptions(); | |
| }); | |
| for (const name of ['question','context','options','model','mode']) { | |
| $(name).addEventListener('input',()=>{clearResult();updatePreview();}); | |
| $(name).addEventListener('change',()=>{configureOptions();updatePreview();}); | |
| } | |
| document.querySelectorAll('[data-example]').forEach(button=>button.addEventListener('click',async()=>{ | |
| removeImage();const index=Number(button.dataset.example);const example=examples[language][index]; | |
| ['mode','question','context','options'].forEach((id,index)=>{$(id).value=example[index];}); | |
| configureOptions();if(exampleMedia[index])await loadMedia(exampleMedia[index]);else updatePreview(); | |
| $('question').focus({preventScroll:true}); | |
| $('decision-form').scrollIntoView({behavior:matchMedia('(prefers-reduced-motion: reduce)').matches?'instant':'smooth',block:'center'}); | |
| })); | |
| $('preview-code').addEventListener('click',()=>{updatePreview(true);}); | |
| $('copy-code').addEventListener('click',async()=>{ | |
| try{await navigator.clipboard.writeText($('python-code').textContent);$('copy-status').textContent=t('copied');} | |
| catch{$('copy-status').textContent=t('copyFailed');} | |
| }); | |
| document.body.dataset.theme=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'; | |
| renderLanguage();updatePreview(); | |