zino_chatbot/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![doc(html_favicon_url = "https://zino.cc/assets/zino-logo.png")]
4#![doc(html_logo_url = "https://zino.cc/assets/zino-logo.svg")]
5#![allow(async_fn_in_trait)]
6
7use toml::Table;
8use zino_core::{
9    LazyLock, Map, application::StaticRecord, error::Error, extension::TomlTableExt, state::State,
10};
11
12mod client;
13
14/// Supported chatbot services.
15mod openai;
16
17pub use client::Chatbot;
18use openai::OpenAiChatCompletion;
19
20/// Underlying trait of all chatbot services for implementors.
21pub trait ChatbotService {
22    /// Constructs a new chatbot with the configuration,
23    /// returning an error if it fails.
24    fn try_new_chatbot(config: &Table) -> Result<Chatbot, Error>;
25
26    /// Returns the model.
27    fn model(&self) -> &str;
28
29    /// Attempts to send a message to generate chat completions.
30    async fn try_send(&self, message: String, options: Option<Map>) -> Result<Vec<String>, Error>;
31}
32
33/// Global access to the shared chatbot services.
34#[derive(Debug, Clone, Copy, Default)]
35pub struct GlobalChatbot;
36
37impl GlobalChatbot {
38    /// Gets the chatbot for the specific service.
39    #[inline]
40    pub fn get(name: &str) -> Option<&'static Chatbot> {
41        SHARED_CHATBOT_SERVICES.find(name)
42    }
43}
44
45/// Shared chatbot services.
46static SHARED_CHATBOT_SERVICES: LazyLock<StaticRecord<Chatbot>> = LazyLock::new(|| {
47    let mut chatbot_services = StaticRecord::new();
48    if let Some(chatbots) = State::shared().config().get_array("chatbot") {
49        for chatbot in chatbots.iter().filter_map(|v| v.as_table()) {
50            let service = chatbot.get_str("service").unwrap_or("unkown");
51            let name = chatbot.get_str("name").unwrap_or(service);
52            let chatbot_service = Chatbot::try_new(service, chatbot)
53                .unwrap_or_else(|err| panic!("fail to connect chatbot `{name}`: {err}"));
54            chatbot_services.add(name, chatbot_service);
55        }
56    }
57    chatbot_services
58});