real time

This commit is contained in:
Saifeddine ALOUI 2024-05-19 14:35:05 +02:00
parent b0be864770
commit 6e92575777
10 changed files with 414 additions and 305 deletions

View File

@ -454,6 +454,9 @@ async def open_personality_folder(request: PersonalityFolderRequest):
lollmsElfServer.error(ex)
return {"status": False, "error": "An error occurred while processing the request"}
@router.get("/is_rt_on")
def is_rt_on():
return {"status": lollmsElfServer.rt_com is not None}
@router.post("/start_recording")
def start_recording(data:Identification):
@ -467,11 +470,11 @@ def start_recording(data:Identification):
lollmsElfServer.info("Starting audio capture")
try:
from lollms.media import AudioRecorder
from lollms.media import RTCom
lollmsElfServer.rec_output_folder = lollmsElfServer.lollms_paths.personal_outputs_path/"audio_rec"
lollmsElfServer.rec_output_folder.mkdir(exist_ok=True, parents=True)
lollmsElfServer.summoned = False
lollmsElfServer.audio_cap = AudioRecorder(
lollmsElfServer.rt_com = RTCom(
lollmsElfServer,
lollmsElfServer.sio,
lollmsElfServer.personality,
@ -483,14 +486,14 @@ def start_recording(data:Identification):
rate=44100,
channels=1,
buffer_size=10,
model="small.en",
model=lollmsElfServer.config.whisper_model,
snd_device=None,
logs_folder="logs",
voice=None,
block_while_talking=True,
context_size=4096
)
lollmsElfServer.audio_cap.start_recording()
lollmsElfServer.rt_com.start_recording()
except:
lollmsElfServer.InfoMessage("Couldn't load media library.\nYou will not be able to perform any of the media linked operations. please verify the logs and install any required installations")
@ -506,7 +509,7 @@ def stop_recording(data:Identification):
return {"status":False,"error":"Stop recording is blocked when the server is exposed outside for very obvious reasons!"}
lollmsElfServer.info("Stopping audio capture")
text = lollmsElfServer.audio_cap.stop_recording()
text = lollmsElfServer.rt_com.stop_recording()
# ai_text = lollmsElfServer.receive_and_generate(text, client, n_predict=lollmsElfServer.config, callback= lollmsElfServer.tasks_library.sink)
# if lollmsElfServer.tts and lollmsElfServer.tts.ready:

View File

@ -65,11 +65,11 @@ def add_events(sio:socketio):
lollmsElfServer.info("Starting audio capture")
try:
from lollms.media import AudioRecorder
from lollms.media import RTCom
lollmsElfServer.rec_output_folder = lollmsElfServer.lollms_paths.personal_outputs_path/"audio_rec"
lollmsElfServer.rec_output_folder.mkdir(exist_ok=True, parents=True)
lollmsElfServer.summoned = False
lollmsElfServer.audio_cap = AudioRecorder(
lollmsElfServer.rt_com = RTCom(
lollmsElfServer,
lollmsElfServer.sio,
lollmsElfServer.personality,
@ -81,14 +81,14 @@ def add_events(sio:socketio):
rate=44100,
channels=1,
buffer_size=10,
model="small.en",
model=lollmsElfServer.config.whisper_model,
snd_device=None,
logs_folder="logs",
voice=None,
block_while_talking=True,
context_size=4096
)
lollmsElfServer.audio_cap.start_recording()
lollmsElfServer.rt_com.start_recording()
except Exception as ex:
trace_exception(ex)
lollmsElfServer.InfoMessage("Couldn't load media library.\nYou will not be able to perform any of the media linked operations. please verify the logs and install any required installations")
@ -99,7 +99,8 @@ def add_events(sio:socketio):
def stop_audio_stream(sid):
client = check_access(lollmsElfServer, sid)
lollmsElfServer.info("Stopping audio capture")
lollmsElfServer.audio_cap.stop_recording()
lollmsElfServer.rt_com.stop_recording()
lollmsElfServer.rt_com = None

@ -1 +1 @@
Subproject commit 5e0f38da1bf4620713f196a24ba1332499fcad72
Subproject commit 124f614480049b8f67d55bbe0d10e13bf441c55d

View File

@ -826,7 +826,45 @@ class LOLLMSWebUI(LOLLMSElfServer):
}, to=client_id
)
)
def new_block( self,
client_id,
sender=None,
content="",
parameters=None,
metadata=None,
ui=None,
message_type:MSG_TYPE=MSG_TYPE.MSG_TYPE_FULL,
sender_type:SENDER_TYPES=SENDER_TYPES.SENDER_TYPES_AI,
open=False
):
# like new_message but without adding the information to the database
client = self.session.get_client(client_id)
run_async(partial(
self.sio.emit,'new_message',
{
"sender": sender,
"message_type": message_type.value,
"sender_type": SENDER_TYPES.SENDER_TYPES_AI.value,
"content": content,
"parameters": parameters,
"metadata": metadata,
"ui": ui,
"id": 0,
"parent_message_id": 0,
'binding': self.config["binding_name"],
'model' : self.config["model_name"],
'personality': self.config["personalities"][self.config["active_personality_id"]],
'created_at': client.discussion.current_message.created_at,
'started_generating_at': client.discussion.current_message.started_generating_at,
'finished_generating_at': client.discussion.current_message.finished_generating_at,
'nb_tokens': client.discussion.current_message.nb_tokens,
'open': open
}, to=client_id
)
)
def send_refresh(self, client_id):
client = self.session.get_client(client_id)
run_async(

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-d452ede2.js"></script>
<link rel="stylesheet" href="/assets/index-1f5d7ed5.css">
<script type="module" crossorigin src="/assets/index-a89a59fe.js"></script>
<link rel="stylesheet" href="/assets/index-a5441302.css">
</head>
<body>
<div id="app"></div>

View File

@ -250,13 +250,35 @@
<button v-if="!loading"
type="button"
@click="startSpeechRecognition"
:class="{ 'text-red-500': isLesteningToVoice }"
:class="{ 'text-red-500': isListeningToVoice }"
class="w-6 hover:text-secondary duration-75 active:scale-90 cursor-pointer transform transition-transform hover:translate-y-[-5px] active:scale-90"
>
<i data-feather="mic"></i>
</button>
<div class="pointer-events-none absolute -top-20 left-1/2 w-max -translate-x-1/2 rounded-md bg-gray-100 p-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-gray-800"><p class="max-w-sm text-sm text-gray-800 dark:text-gray-200">Press and talk.</p></div>
</div>
<div class="group relative w-max">
<button v-if="$store.state.config.active_tts_service!='None' && !$store.state.is_rt_on"
type="button"
@click="startRTCom"
:class="{ 'text-red-500': isListeningToVoice }"
class="w-6 hover:text-secondary duration-75 active:scale-90 cursor-pointer transform transition-transform hover:translate-y-[-5px] active:scale-90 bg-green-500 border border-green-700 rounded-md"
>
<i data-feather="mic"></i>
</button>
<div class="pointer-events-none absolute -top-20 left-1/2 w-max -translate-x-1/2 rounded-md bg-gray-100 p-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-gray-800"><p class="max-w-sm text-sm text-gray-800 dark:text-gray-200">Real time bidirectional audio mode.</p></div>
<button v-if="$store.state.config.active_tts_service!='None' && $store.state.is_rt_on"
type="button"
@click="stopRTCom"
:class="{ 'text-red-500': isListeningToVoice }"
class="w-6 hover:text-secondary duration-75 active:scale-90 cursor-pointer transform transition-transform hover:translate-y-[-5px] active:scale-90 bg-red-500 border border-red-700 rounded-md"
>
<i data-feather="mic"></i>
</button>
<div class="pointer-events-none absolute -top-20 left-1/2 w-max -translate-x-1/2 rounded-md bg-gray-100 p-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-gray-800"><p class="max-w-sm text-sm text-gray-800 dark:text-gray-200">Real time bidirectional audio mode.</p></div>
</div>
<div v-if="!loading" class="group relative w-max">
<input type="file" ref="fileDialog" style="display: none" @change="addFiles" multiple />
<button type="button" @click.prevent="add_file"
@ -389,7 +411,7 @@ export default {
selecting_binding:false,
selecting_model:false,
selectedModel:'',
isLesteningToVoice:false,
isListeningToVoice:false,
filesList: [],
isFileSentList: [],
totalSize: 0,
@ -639,6 +661,8 @@ export default {
await this.$store.dispatch('refreshConfig');
await this.$store.dispatch('fetchLanguages');
await this.$store.dispatch('fetchLanguage');
await this.$store.dispatch('fetchisRTOn');
console.log('pers is mounted', res)
if (res && res.status && res.active_personality_id > -1) {
@ -829,6 +853,22 @@ export default {
makeAnEmptyAIMessage() {
this.$emit('createEmptyAIMessage')
},
startRTCom(){
socket.emit('start_audio_stream', ()=>{this.isAudioActive = true;});
nextTick(() => {
feather.replace()
}
)
this.$store.state.is_rt_on = true;
},
stopRTCom(){
socket.emit('stop_audio_stream', ()=>{this.isAudioActive = true;});
nextTick(() => {
feather.replace()
}
)
this.$store.state.is_rt_on = false;
},
startSpeechRecognition() {
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) {
this.recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
@ -836,7 +876,7 @@ export default {
this.recognition.interimResults = true; // Enable interim results to get real-time updates
this.recognition.onstart = () => {
this.isLesteningToVoice = true;
this.isListeningToVoice = true;
this.silenceTimer = setTimeout(() => {
this.recognition.stop();
}, this.silenceTimeout); // Set the silence timeout to stop recognition
@ -856,13 +896,13 @@ export default {
this.recognition.onerror = (event) => {
console.error('Speech recognition error:', event.error);
this.isLesteningToVoice = false;
this.isListeningToVoice = false;
clearTimeout(this.silenceTimer); // Clear the silence timeout on error
};
this.recognition.onend = () => {
console.log('Speech recognition ended.');
this.isLesteningToVoice = false;
this.isListeningToVoice = false;
clearTimeout(this.silenceTimer); // Clear the silence timeout when recognition ends normally
this.submit(); // Call the function to handle form submission or action once speech recognition ends
};

View File

@ -24,6 +24,7 @@ function copyObject(obj) {
export const store = createStore({
state () {
return {
is_rt_on:false,
language: "english",
languages: [],
currentTheme: '',
@ -83,6 +84,11 @@ export const store = createStore({
}
},
mutations: {
setisRTOn(state, is_rt_on) {
state.is_rt_on = is_rt_on;
},
setLanguages(state, languages) {
state.languages = languages;
},
@ -162,6 +168,10 @@ export const store = createStore({
}
},
getters: {
getisRTOn(state) {
return state.is_rt_on;
},
getLanguages(state) {
return state.languages;
},
@ -275,7 +285,17 @@ export const store = createStore({
console.log("databases:",databases)
commit('setDatabases', databases);
},
async fetchisRTOn({ commit }) {
console.log("is_rt_on", this.state.client_id)
const response = await axios.get(
'/is_rt_on'
);
console.log("response", response)
const is_rt_on = response.data;
console.log("languages", is_rt_on)
commit('setRTOn', is_rt_on);
},
async fetchLanguages({ commit }) {
console.log("get_personality_languages_list", this.state.client_id)
const response = await axios.post(
@ -770,7 +790,14 @@ app.mixin({
catch (ex){
console.log("Error cought:", ex)
}
try{
await this.$store.dispatch('fetchisRTOn');
}
catch (ex){
console.log("Error cought:", ex)
}
this.$store.state.ready = true;
}

@ -1 +1 @@
Subproject commit 4107557398450addb7500e06d80f26b37f572805
Subproject commit 7f6b99c1e5fc01050b6c60b30706dd141a18d734