diff --git a/crates/index-scheduler/src/lib.rs b/crates/index-scheduler/src/lib.rs index 505ce23f8..eed847662 100644 --- a/crates/index-scheduler/src/lib.rs +++ b/crates/index-scheduler/src/lib.rs @@ -45,6 +45,9 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; use std::time::Duration; +use crate::features::FeatureData; +use crate::index_mapper::IndexMapper; +use crate::utils::clamp_to_page_size; use dump::Dump; pub use error::Error; pub use features::RoFeatures; @@ -71,9 +74,6 @@ use scheduler::Scheduler; use time::OffsetDateTime; use versioning::Versioning; -use crate::index_mapper::IndexMapper; -use crate::utils::clamp_to_page_size; - pub(crate) type BEI128 = I128; const TASK_SCHEDULER_SIZE_THRESHOLD_PERCENT_INT: u64 = 40; @@ -136,6 +136,8 @@ pub struct IndexSchedulerOptions { pub embedding_cache_cap: usize, /// Snapshot compaction status. pub experimental_no_snapshot_compaction: bool, + /// Whether the chat completions are enabled or not. + pub experimental_chat_completions: bool, } /// Structure which holds meilisearch's indexes and schedules the tasks @@ -273,7 +275,7 @@ impl IndexScheduler { .open(&options.tasks_path) }?; - // We **must** starts by upgrading the version because it'll also upgrade the required database before we can open them + // We **must** start by upgrading the version because it'll also upgrade the required database before we can open them let version = versioning::Versioning::new(&env, from_db_version)?; let mut wtxn = env.write_txn()?; @@ -281,8 +283,11 @@ impl IndexScheduler { let queue = Queue::new(&env, &mut wtxn, &options)?; let index_mapper = IndexMapper::new(&env, &mut wtxn, &options, budget)?; let chat_settings = env.create_database(&mut wtxn, Some(CHAT_SETTINGS_DB_NAME))?; + wtxn.commit()?; + configure_experimental_features(&env, &features, &options)?; + // allow unreachable_code to get rids of the warning in the case of a test build. let this = Self { processing_tasks: Arc::new(RwLock::new(ProcessingTasks::new())), @@ -922,6 +927,22 @@ impl IndexScheduler { } } +fn configure_experimental_features( + env: &Env, + features: &FeatureData, + options: &IndexSchedulerOptions, +) -> Result<()> { + let current_features = features.features().runtime_features(); + + let new_features = RuntimeTogglableFeatures { + chat_completions: options.experimental_chat_completions, + ..current_features + }; + + let wtxn = env.write_txn().map_err(Error::HeedTransaction)?; + features.put_runtime_features(wtxn, new_features) +} + /// The outcome of calling the [`IndexScheduler::tick`] function. pub enum TickOutcome { /// The scheduler should immediately attempt another `tick`. diff --git a/crates/meilisearch/src/analytics/segment_analytics.rs b/crates/meilisearch/src/analytics/segment_analytics.rs index c7e0634f4..6ab4e88b8 100644 --- a/crates/meilisearch/src/analytics/segment_analytics.rs +++ b/crates/meilisearch/src/analytics/segment_analytics.rs @@ -279,6 +279,7 @@ impl Infos { indexer_options, config_file_path, no_analytics: _, + experimental_chat_completions: _, } = options; let schedule_snapshot = match schedule_snapshot { diff --git a/crates/meilisearch/src/lib.rs b/crates/meilisearch/src/lib.rs index 1e0c205d0..b376a967e 100644 --- a/crates/meilisearch/src/lib.rs +++ b/crates/meilisearch/src/lib.rs @@ -237,6 +237,7 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc, Arc< auto_upgrade: opt.experimental_dumpless_upgrade, embedding_cache_cap: opt.experimental_embedding_cache_entries, experimental_no_snapshot_compaction: opt.experimental_no_snapshot_compaction, + experimental_chat_completions: opt.experimental_chat_completions, }; let binary_version = (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); diff --git a/crates/meilisearch/src/option.rs b/crates/meilisearch/src/option.rs index 35ce71cf4..36704b712 100644 --- a/crates/meilisearch/src/option.rs +++ b/crates/meilisearch/src/option.rs @@ -66,6 +66,7 @@ const MEILI_EXPERIMENTAL_LIMIT_BATCHED_TASKS_TOTAL_SIZE: &str = const MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES: &str = "MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES"; const MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION: &str = "MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION"; +const MEILI_EXPERIMENTAL_CHAT_COMPLETIONS: &str = "MEILI_EXPERIMENTAL_CHAT_COMPLETIONS"; const DEFAULT_CONFIG_FILE_PATH: &str = "./config.toml"; const DEFAULT_DB_PATH: &str = "./data.ms"; const DEFAULT_HTTP_ADDR: &str = "localhost:7700"; @@ -473,6 +474,11 @@ pub struct Opt { /// Format must be TOML. #[clap(long)] pub config_file_path: Option, + + /// Enables the chat completions functionality. + #[serde(default)] + #[clap(long, env = MEILI_EXPERIMENTAL_CHAT_COMPLETIONS, default_value_t = false)] + pub experimental_chat_completions: bool, } impl Opt { @@ -498,25 +504,21 @@ impl Opt { Ok(config) => { // If the file is successfully read, we deserialize it with `toml`. let opt_from_config = toml::from_str::(&config)?; - // Return an error if config file contains 'config_file_path' + // Return an error if the config file contains 'config_file_path' // Using that key in the config file doesn't make sense bc it creates a logical loop (config file referencing itself) if opt_from_config.config_file_path.is_some() { anyhow::bail!("`config_file_path` is not supported in the configuration file") } // We inject the values from the toml in the corresponding env vars if needs be. Doing so, we respect the priority toml < env vars < cli args. opt_from_config.export_to_env(); - // Once injected we parse the cli args once again to take the new env vars into scope. + // Once injected, we parse the cli args once again to take the new env vars into scope. opts = Opt::parse(); config_read_from = Some(config_file_path); } Err(e) => { if let Some(path) = user_specified_config_file_path { // If we have an error while reading the file defined by the user. - anyhow::bail!( - "unable to open or read the {:?} configuration file: {}.", - path, - e, - ) + anyhow::bail!("unable to open or read the {path:?} configuration file: {e}.") } } } @@ -570,6 +572,7 @@ impl Opt { experimental_limit_batched_tasks_total_size, experimental_embedding_cache_entries, experimental_no_snapshot_compaction, + experimental_chat_completions, } = self; export_to_env_if_not_present(MEILI_DB_PATH, db_path); export_to_env_if_not_present(MEILI_HTTP_ADDR, http_addr); @@ -670,6 +673,10 @@ impl Opt { MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION, experimental_no_snapshot_compaction.to_string(), ); + export_to_env_if_not_present( + MEILI_EXPERIMENTAL_CHAT_COMPLETIONS, + experimental_chat_completions.to_string(), + ); indexer_options.export_to_env(); }