Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,6 +3,7 @@ import socketserver
|
|
| 3 |
import json
|
| 4 |
from curl_cffi import requests
|
| 5 |
from openai import OpenAI
|
|
|
|
| 6 |
|
| 7 |
PORT = 7860
|
| 8 |
STT_URL = "https://multi-modal.ai.cloudflare.com/api/inference?model=@cf/deepgram/nova-3&field=audio"
|
|
@@ -13,8 +14,15 @@ client = OpenAI(
|
|
| 13 |
api_key="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"
|
| 14 |
)
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
HTML = """
|
| 17 |
-
<!DOCTYPE html><html><body><h1>Multi-Modal Playground</h1><div id="tabs"><button onclick="showTab('stt')">STT (Nova-3)</button><button onclick="showTab('tts')">TTS (AURA-1)</button><button onclick="showTab('chat')">Chat (Llama)</button></div><div id="sttTabContent" style="display:block;"><p>Upload audio:</p><input type="file" id="audioFile" accept="audio/*"><button onclick="transcribe()">Transcribe</button><p>Status: <span id="status">Idle</span></p><pre id="result" style="background:#eee;padding:10px"></pre></div><div id="ttsTabContent" style="display:none;"><p>Enter text:</p><input type="text" id="textInput" placeholder="Enter text to speak" style="width:100%;"><button onclick="generateAudio()">Generate Audio</button><p>Status: <span id="statusTTS">Idle</span></p><audio id="audioPlayer" controls style="width:100%;"></audio></div><div id="chatTabContent" style="display:none;"><div id="messages" style="height:300px;overflow-y:scroll;border:1px solid #ccc;padding:10px;margin-bottom:10px;background:#eee;"></div><input type="text" id="chatInput" placeholder="Type message..." style="width:70%;"><button onclick="sendMessage()">Send</button><p>Status: <span id="statusChat">Idle</span></p></div><script>let
|
| 18 |
"""
|
| 19 |
|
| 20 |
class Handler(http.server.BaseHTTPRequestHandler):
|
|
|
|
| 3 |
import json
|
| 4 |
from curl_cffi import requests
|
| 5 |
from openai import OpenAI
|
| 6 |
+
import re
|
| 7 |
|
| 8 |
PORT = 7860
|
| 9 |
STT_URL = "https://multi-modal.ai.cloudflare.com/api/inference?model=@cf/deepgram/nova-3&field=audio"
|
|
|
|
| 14 |
api_key="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"
|
| 15 |
)
|
| 16 |
|
| 17 |
+
def simple_md(text):
|
| 18 |
+
text = re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', text)
|
| 19 |
+
text = re.sub(r'\*(.*?)\*', r'<i>\1</i>', text)
|
| 20 |
+
text = re.sub(r'`(.*?)`', r'<code>\1</code>', text)
|
| 21 |
+
text = re.sub(r'\n', r'<br>', text)
|
| 22 |
+
return text
|
| 23 |
+
|
| 24 |
HTML = """
|
| 25 |
+
<!DOCTYPE html><html><body><h1>Multi-Modal Playground</h1><div id="tabs"><button id="tab-stt" onclick="showTab('stt')" class="tab-btn active">STT (Nova-3)</button><button id="tab-tts" onclick="showTab('tts')" class="tab-btn">TTS (AURA-1)</button><button id="tab-chat" onclick="showTab('chat')" class="tab-btn">Chat (Llama)</button><button id="tab-voice" onclick="showTab('voice')" class="tab-btn">Voice Chat</button></div><div id="sttTabContent" style="display:block;"><p>Upload audio:</p><input type="file" id="audioFile" accept="audio/*"><button onclick="transcribe()">Transcribe</button><p>Status: <span id="status">Idle</span></p><pre id="result" style="background:#eee;padding:10px"></pre></div><div id="ttsTabContent" style="display:none;"><p>Enter text:</p><input type="text" id="textInput" placeholder="Enter text to speak" style="width:100%;"><button onclick="generateAudio()">Generate Audio</button><p>Status: <span id="statusTTS">Idle</span></p><audio id="audioPlayer" controls style="width:100%;"></audio></div><div id="chatTabContent" style="display:none;"><div id="messages" style="height:300px;overflow-y:scroll;border:1px solid #ccc;padding:10px;margin-bottom:10px;background:#eee;"></div><input type="text" id="chatInput" placeholder="Type message..." style="width:70%;"><button onclick="sendMessage()">Send</button><p>Status: <span id="statusChat">Idle</span></p></div><div id="voiceTabContent" style="display:none;"><button id="micBtn" onclick="toggleRecord()" style="font-size:48px;">🎤</button><p>Status: <span id="statusVoice">Click to start recording</span></p><audio id="voicePlayer" style="display:none;"></audio></div><script>let chatMessages=[];let mediaRecorder;let audioChunks=[];let voiceStream;function showTab(tab){const tabs=document.querySelectorAll('.tab-btn');tabs.forEach(t=>t.classList.remove('active'));document.getElementById(`tab-${tab}`).classList.add('active');document.getElementById('sttTabContent').style.display=tab==='stt'?'block':'none';document.getElementById('ttsTabContent').style.display=tab==='tts'?'block':'none';document.getElementById('chatTabContent').style.display=tab==='chat'?'block':'none';document.getElementById('voiceTabContent').style.display=tab==='voice'?'block':'none';if(tab==='chat'){document.getElementById('chatInput').focus();}}function renderMD(text){return text.replace(/\*\*(.*?)\*\*/g,'<b>$1</b>').replace(/\*(.*?)\*/g,'<i>$1</i>').replace(/`(.*?)`/g,'<code>$1</code>').replace(/\n/g,'<br>');}function addMessage(role,content){const div=document.getElementById('messages');const msg=document.createElement('div');msg.innerHTML=`<strong>${role}:</strong> ${renderMD(content)}`;div.appendChild(msg);div.scrollTop=div.scrollHeight;}async function sendMessage(){const input=document.getElementById('chatInput');const text=input.value.trim();if(!text)return;addMessage('user',text);input.value='';document.getElementById('statusChat').innerText='Thinking...';chatMessages.push({role:'user',content:text});try{const res=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({messages:chatMessages})});const data=await res.json();const response=data.response;addMessage('assistant',response);chatMessages.push({role:'assistant',content:response});document.getElementById('statusChat').innerText='Done';}catch(e){document.getElementById('statusChat').innerText='Error';}}async function toggleRecord(){const btn=document.getElementById('micBtn');if(!mediaRecorder||mediaRecorder.state==='inactive'){try{voiceStream=await navigator.mediaDevices.getUserMedia({audio:true});mediaRecorder=new MediaRecorder(voiceStream);audioChunks=[];mediaRecorder.ondataavailable=e=>audioChunks.push(e.data);mediaRecorder.onstop=processVoice;mediaRecorder.start();btn.style.color='red';document.getElementById('statusVoice').innerText='Recording... Click to stop';}catch(e){document.getElementById('statusVoice').innerText='Error accessing mic';}}else{mediaRecorder.stop();btn.style.color='black';document.getElementById('statusVoice').innerText='Processing...';}}async function processVoice(){const audioBlob=new Blob(audioChunks,{type:'audio/webm'});voiceStream.getTracks().forEach(track=>track.stop());const formData=new FormData();formData.append('audio',audioBlob);document.getElementById('statusVoice').innerText='Transcribing...';try{const sttRes=await fetch('/api/stt',{method:'POST',body:formData});const sttData=await sttRes.json();let userText='';if(sttData.results&&sttData.results.channels&&sttData.results.channels[0]&&sttData.results.channels[0].alternatives&&sttData.results.channels[0].alternatives[0]){userText=sttData.results.channels[0].alternatives[0].transcript;}if(!userText){document.getElementById('statusVoice').innerText='No speech detected';return;}document.getElementById('statusVoice').innerText='Thinking...';const chatRes=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({messages:[{role:'user',content:userText}]})});const chatData=await chatRes.json();const response=chatData.response;document.getElementById('statusVoice').innerText='Generating speech...';const ttsRes=await fetch('/api/tts',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({text:response})});const ttsData=await ttsRes.json();const audioPlayer=document.getElementById('voicePlayer');audioPlayer.src='data:audio/webm;base64,'+ttsData.audio;audioPlayer.play();document.getElementById('statusVoice').innerText='Done';}catch(e){document.getElementById('statusVoice').innerText='Error';}}async function transcribe(){const file=document.getElementById('audioFile').files[0];if(!file)return;document.getElementById('status').innerText='Processing...';const formData=new FormData();formData.append('file',file);try{const res=await fetch('/api/stt',{method:'POST',body:formData});const data=await res.json();document.getElementById('result').innerText=JSON.stringify(data,null,2);document.getElementById('status').innerText='Done';}catch(e){document.getElementById('status').innerText='Error';}}async function generateAudio(){const text=document.getElementById('textInput').value;if(!text)return;document.getElementById('statusTTS').innerText='Generating...';try{const res=await fetch('/api/tts',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({text:text})});const data=await res.json();document.getElementById('audioPlayer').src='data:audio/webm;base64,'+data.audio;document.getElementById('statusTTS').innerText='Done';}catch(e){document.getElementById('statusTTS').innerText='Error';}}</script><style>.tab-btn.active{background:#ddd;}</style></body></html>
|
| 26 |
"""
|
| 27 |
|
| 28 |
class Handler(http.server.BaseHTTPRequestHandler):
|