use std::collections::HashMap;
use async_trait::async_trait;
use crate::agent::AgentContext;
use crate::oxyde_game::intent::{Intent, IntentType};
use crate::Result;
use super::base::{Behavior, BehaviorResult, BaseBehavior};
#[derive(Debug)]
pub struct DialogueBehavior {
#[allow(dead_code)]
base: BaseBehavior,
topics: HashMap<String, Vec<String>>,
default_responses: Vec<String>,
}
impl DialogueBehavior {
pub fn new(topics: HashMap<String, Vec<String>>, default_responses: Vec<String>) -> Self {
Self {
base: BaseBehavior::new(
"dialogue",
"Responds to topic-based conversations",
5,
vec!["question".to_string(), "chat".to_string()],
0, ),
topics,
default_responses,
}
}
}
#[async_trait]
impl Behavior for DialogueBehavior {
async fn matches_intent(&self, intent: &Intent) -> bool {
matches!(
intent.intent_type,
IntentType::Question | IntentType::Chat | IntentType::Command
)
}
async fn execute(&self, intent: &Intent, _context: &AgentContext) -> Result<BehaviorResult> {
let topic = intent.raw_input.to_lowercase();
let response = self
.topics
.iter()
.find(|(key, _)| topic.contains(key.as_str()))
.and_then(|(_, responses)| {
if responses.is_empty() {
None
} else {
let idx = rand::random::<usize>() % responses.len();
Some(responses[idx].clone())
}
});
let final_response = match response {
Some(r) => r,
None => {
if self.default_responses.is_empty() {
return Ok(BehaviorResult::None);
}
let idx = rand::random::<usize>() % self.default_responses.len();
self.default_responses[idx].clone()
}
};
Ok(BehaviorResult::Response(final_response))
}
}