use crate::{
application::StaticRecord, error::Error, extension::TomlTableExt, state::State, LazyLock, Map,
};
use toml::Table;
mod client;
#[cfg(feature = "chatbot-openai")]
mod chatbot_openai;
pub use client::Chatbot;
#[cfg(feature = "chatbot-openai")]
use chatbot_openai::OpenAiChatCompletion;
pub trait ChatbotService {
fn try_new_chatbot(config: &Table) -> Result<Chatbot, Error>;
fn model(&self) -> &str;
async fn try_send(&self, message: String, options: Option<Map>) -> Result<Vec<String>, Error>;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct GlobalChatbot;
impl GlobalChatbot {
#[inline]
pub fn get(name: &str) -> Option<&'static Chatbot> {
SHARED_CHATBOT_SERVICES.find(name)
}
}
static SHARED_CHATBOT_SERVICES: LazyLock<StaticRecord<Chatbot>> = LazyLock::new(|| {
let mut chatbot_services = StaticRecord::new();
if let Some(chatbots) = State::shared().config().get_array("chatbot") {
for chatbot in chatbots.iter().filter_map(|v| v.as_table()) {
let service = chatbot.get_str("service").unwrap_or("unkown");
let name = chatbot.get_str("name").unwrap_or(service);
let chatbot_service = Chatbot::try_new(service, chatbot)
.unwrap_or_else(|err| panic!("fail to connect chatbot `{name}`: {err}"));
chatbot_services.add(name, chatbot_service);
}
}
chatbot_services
});