intent recognition added (first implementation)
This commit is contained in:
parent
0c28304840
commit
5f1f9ce321
20 changed files with 625 additions and 255 deletions
|
|
@ -16,6 +16,9 @@ winit = "0.30"
|
|||
image.workspace = true
|
||||
platform-dirs.workspace = true
|
||||
rand.workspace = true
|
||||
parking_lot.workspace = true
|
||||
|
||||
tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winit]
|
||||
version = "0.30"
|
||||
|
|
@ -26,4 +29,4 @@ winapi = { version = "0.3", features = ["winuser"] }
|
|||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
gtk = "0.18"
|
||||
glib = "0.18"
|
||||
glib = "0.21.5"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::SystemTime;
|
||||
|
||||
use jarvis_core::{audio, commands, config, listener, recorder, stt, COMMANDS_LIST};
|
||||
use jarvis_core::{audio, commands, config, listener, recorder, stt, COMMANDS_LIST, intent};
|
||||
use rand::prelude::*;
|
||||
|
||||
pub fn start() -> Result<(), ()> {
|
||||
|
|
@ -9,6 +9,7 @@ pub fn start() -> Result<(), ()> {
|
|||
}
|
||||
|
||||
fn main_loop() -> Result<(), ()> {
|
||||
let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
|
||||
let mut start: SystemTime;
|
||||
let sounds_directory = audio::get_sound_directory().unwrap();
|
||||
let frame_length: usize = 512; // default for every wake-word engine
|
||||
|
|
@ -34,7 +35,7 @@ fn main_loop() -> Result<(), ()> {
|
|||
|
||||
// recognize wake-word
|
||||
match listener::data_callback(&frame_buffer) {
|
||||
Some(keyword_index) => {
|
||||
Some(_keyword_index) => {
|
||||
// wake-word activated, process further commands
|
||||
// capture current time
|
||||
start = SystemTime::now();
|
||||
|
|
@ -66,13 +67,18 @@ fn main_loop() -> Result<(), ()> {
|
|||
}
|
||||
recognized_voice = recognized_voice.trim().into();
|
||||
|
||||
// infer command
|
||||
if let Some((cmd_path, cmd_config)) = commands::fetch_command(
|
||||
&recognized_voice,
|
||||
&COMMANDS_LIST.get().unwrap(),
|
||||
) {
|
||||
// some debug info
|
||||
info!("Recognized voice (filtered): {}", recognized_voice);
|
||||
// infer command (try intent recognition first, fallback to levenshtein)
|
||||
let cmd_result = if let Some((intent_id, confidence)) =
|
||||
rt.block_on(intent::classify(&recognized_voice))
|
||||
{
|
||||
info!("Intent recognized: {} (confidence: {:.2})", intent_id, confidence);
|
||||
intent::get_command_by_intent(COMMANDS_LIST.get().unwrap(), &intent_id)
|
||||
} else {
|
||||
info!("Intent not recognized, trying levenshtein fallback...");
|
||||
commands::fetch_command(&recognized_voice, COMMANDS_LIST.get().unwrap())
|
||||
};
|
||||
|
||||
if let Some((cmd_path, cmd_config)) = cmd_result {
|
||||
info!("Command found: {:?}", cmd_path);
|
||||
info!("Executing!");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::path::PathBuf;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
// include core
|
||||
use jarvis_core::{
|
||||
audio, commands, config, db, listener, recorder, stt,
|
||||
audio, commands, config, db, listener, recorder, stt, intent,
|
||||
APP_CONFIG_DIR, APP_LOG_DIR, COMMANDS_LIST, DB,
|
||||
};
|
||||
|
||||
|
|
@ -32,7 +33,8 @@ fn main() -> Result<(), String> {
|
|||
info!("Log directory is: {}", APP_LOG_DIR.get().unwrap().display());
|
||||
|
||||
// initialize database (settings)
|
||||
let _ = DB.set(db::init_settings());
|
||||
DB.set(Arc::new(RwLock::new(db::init_settings())))
|
||||
.expect("DB already initialized");
|
||||
|
||||
// initialize tray
|
||||
// @TODO. macOS currently not supported for tray functionality,
|
||||
|
|
@ -58,7 +60,13 @@ fn main() -> Result<(), String> {
|
|||
|
||||
// init commands
|
||||
info!("Initializing commands.");
|
||||
let cmds = commands::parse_commands().unwrap();
|
||||
let cmds = match commands::parse_commands() {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
warn!("Failed to parse commands: {}. Starting with empty command list.", e);
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
info!("Commands initialized. Count: {}, List: {:?}", cmds.len(), commands::list(&cmds));
|
||||
COMMANDS_LIST.set(cmds).unwrap();
|
||||
|
||||
|
|
@ -73,6 +81,15 @@ fn main() -> Result<(), String> {
|
|||
app::close(1); // cannot continue without wake-word engine
|
||||
}
|
||||
|
||||
// init intent-recognition engine
|
||||
let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
|
||||
rt.block_on(async {
|
||||
if intent::init(COMMANDS_LIST.get().unwrap()).await.is_err() {
|
||||
error!("Failed to initialize intent classifier");
|
||||
app::close(1);
|
||||
}
|
||||
});
|
||||
|
||||
// start the app (in the background thread)
|
||||
std::thread::spawn(|| {
|
||||
let _ = app::start();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue