786 lines
30 KiB
Rust
Raw Normal View History

2024-07-22 12:04:05 +02:00
use std::collections::BTreeMap;
2024-08-27 17:52:09 +02:00
use std::num::NonZeroUsize;
2024-07-22 12:04:05 +02:00
use deserr::Deserr;
2024-06-12 14:03:40 +02:00
use roaring::RoaringBitmap;
use serde::{Deserialize, Serialize};
2024-03-27 11:51:04 +01:00
use super::{ollama, openai, DistributionShift};
2024-08-27 17:52:09 +02:00
use crate::prompt::{default_max_bytes, PromptData};
use crate::update::Setting;
use crate::vector::EmbeddingConfig;
2023-12-20 17:08:32 +01:00
use crate::UserError;
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, Deserr)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
#[deserr(rename_all = camelCase, deny_unknown_fields)]
pub struct EmbeddingSettings {
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2023-12-20 17:08:32 +01:00
pub source: Setting<EmbedderSource>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2023-12-20 17:08:32 +01:00
pub model: Setting<String>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
pub revision: Setting<String>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
pub api_key: Setting<String>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
pub dimensions: Setting<usize>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
pub binary_quantized: Setting<bool>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2023-12-20 17:08:32 +01:00
pub document_template: Setting<String>,
2024-03-25 10:05:38 +01:00
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-08-27 17:52:09 +02:00
pub document_template_max_bytes: Setting<usize>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-03-25 10:05:38 +01:00
pub url: Setting<String>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-07-16 16:00:21 +02:00
pub request: Setting<serde_json::Value>,
2024-03-25 10:05:38 +01:00
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-07-16 16:00:21 +02:00
pub response: Setting<serde_json::Value>,
2024-03-27 11:51:04 +01:00
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-07-22 12:04:05 +02:00
pub headers: Setting<BTreeMap<String, String>>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[deserr(default)]
2024-03-27 11:51:04 +01:00
pub distribution: Setting<DistributionShift>,
2023-12-20 17:08:32 +01:00
}
pub fn check_unset<T>(
key: &Setting<T>,
field: &'static str,
source: EmbedderSource,
embedder_name: &str,
) -> Result<(), UserError> {
if matches!(key, Setting::NotSet) {
Ok(())
} else {
Err(UserError::InvalidFieldForSource {
embedder_name: embedder_name.to_owned(),
source_: source,
field,
allowed_fields_for_source: EmbeddingSettings::allowed_fields_for_source(source),
allowed_sources_for_field: EmbeddingSettings::allowed_sources_for_field(field),
})
}
}
2024-06-12 14:03:40 +02:00
/// Indicates what action should take place during a reindexing operation for an embedder
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ReindexAction {
/// An indexing operation should take place for this embedder, keeping existing vectors
/// and checking whether the document template changed or not
RegeneratePrompts,
/// An indexing operation should take place for all documents for this embedder, removing existing vectors
/// (except userProvided ones)
FullReindex,
}
pub enum SettingsDiff {
Remove,
Reindex { action: ReindexAction, updated_settings: EmbeddingSettings, quantize: bool },
UpdateWithoutReindex { updated_settings: EmbeddingSettings, quantize: bool },
}
#[derive(Default, Debug)]
pub struct EmbedderAction {
pub was_quantized: bool,
pub is_being_quantized: bool,
pub write_back: Option<WriteBackToDocuments>,
pub reindex: Option<ReindexAction>,
2024-06-12 14:03:40 +02:00
}
impl EmbedderAction {
pub fn is_being_quantized(&self) -> bool {
self.is_being_quantized
}
pub fn write_back(&self) -> Option<&WriteBackToDocuments> {
self.write_back.as_ref()
}
pub fn reindex(&self) -> Option<&ReindexAction> {
self.reindex.as_ref()
}
pub fn with_is_being_quantized(mut self, quantize: bool) -> Self {
self.is_being_quantized = quantize;
self
}
pub fn with_write_back(write_back: WriteBackToDocuments, was_quantized: bool) -> Self {
Self {
was_quantized,
is_being_quantized: false,
write_back: Some(write_back),
reindex: None,
}
}
pub fn with_reindex(reindex: ReindexAction, was_quantized: bool) -> Self {
Self { was_quantized, is_being_quantized: false, write_back: None, reindex: Some(reindex) }
}
2024-06-12 14:03:40 +02:00
}
#[derive(Debug)]
2024-06-12 14:03:40 +02:00
pub struct WriteBackToDocuments {
pub embedder_id: u8,
pub user_provided: RoaringBitmap,
}
impl SettingsDiff {
pub fn from_settings(
embedder_name: &str,
old: EmbeddingSettings,
new: Setting<EmbeddingSettings>,
) -> Result<Self, UserError> {
let ret = match new {
2024-06-12 14:03:40 +02:00
Setting::Set(new) => {
let EmbeddingSettings {
mut source,
mut model,
mut revision,
mut api_key,
mut dimensions,
mut document_template,
mut url,
2024-07-16 16:00:21 +02:00
mut request,
mut response,
2024-06-12 14:03:40 +02:00
mut distribution,
2024-07-22 12:04:05 +02:00
mut headers,
2024-08-27 17:52:09 +02:00
mut document_template_max_bytes,
binary_quantized: mut binary_quantize,
2024-06-12 14:03:40 +02:00
} = old;
let EmbeddingSettings {
source: new_source,
model: new_model,
revision: new_revision,
api_key: new_api_key,
dimensions: new_dimensions,
document_template: new_document_template,
url: new_url,
2024-07-16 16:00:21 +02:00
request: new_request,
response: new_response,
2024-06-12 14:03:40 +02:00
distribution: new_distribution,
2024-07-22 12:04:05 +02:00
headers: new_headers,
2024-08-27 17:52:09 +02:00
document_template_max_bytes: new_document_template_max_bytes,
binary_quantized: new_binary_quantize,
2024-06-12 14:03:40 +02:00
} = new;
if matches!(binary_quantize, Setting::Set(true))
&& matches!(new_binary_quantize, Setting::Set(false))
{
return Err(UserError::InvalidDisableBinaryQuantization {
embedder_name: embedder_name.to_string(),
});
}
2024-06-12 14:03:40 +02:00
let mut reindex_action = None;
// **Warning**: do not use short-circuiting || here, we want all these operations applied
if source.apply(new_source) {
ReindexAction::push_action(&mut reindex_action, ReindexAction::FullReindex);
// when the source changes, we need to reapply the default settings for the new source
apply_default_for_source(
&source,
&mut model,
&mut revision,
&mut dimensions,
&mut url,
2024-07-16 16:00:21 +02:00
&mut request,
&mut response,
2024-06-12 14:03:40 +02:00
&mut document_template,
2024-08-27 17:52:09 +02:00
&mut document_template_max_bytes,
2024-07-22 12:04:05 +02:00
&mut headers,
2024-06-12 14:03:40 +02:00
)
}
if model.apply(new_model) {
ReindexAction::push_action(&mut reindex_action, ReindexAction::FullReindex);
}
if revision.apply(new_revision) {
ReindexAction::push_action(&mut reindex_action, ReindexAction::FullReindex);
}
if dimensions.apply(new_dimensions) {
2024-07-22 12:09:52 +02:00
match source {
// regenerate on dimensions change in OpenAI since truncation is supported
Setting::Set(EmbedderSource::OpenAi) | Setting::Reset => {
ReindexAction::push_action(
&mut reindex_action,
ReindexAction::FullReindex,
);
}
// for all other embedders, the parameter is a hint that should not be able to change the result
// and so won't cause a reindex by itself.
_ => {}
}
2024-06-12 14:03:40 +02:00
}
let binary_quantize_changed = binary_quantize.apply(new_binary_quantize);
2024-06-12 14:03:40 +02:00
if url.apply(new_url) {
2024-07-15 16:20:19 +02:00
match source {
// do not regenerate on an url change in OpenAI
Setting::Set(EmbedderSource::OpenAi) | Setting::Reset => {}
_ => {
ReindexAction::push_action(
&mut reindex_action,
ReindexAction::FullReindex,
);
}
}
2024-06-12 14:03:40 +02:00
}
2024-07-16 16:00:21 +02:00
if request.apply(new_request) {
2024-06-12 14:03:40 +02:00
ReindexAction::push_action(&mut reindex_action, ReindexAction::FullReindex);
}
2024-07-16 16:00:21 +02:00
if response.apply(new_response) {
2024-06-12 14:03:40 +02:00
ReindexAction::push_action(&mut reindex_action, ReindexAction::FullReindex);
}
if document_template.apply(new_document_template) {
ReindexAction::push_action(
&mut reindex_action,
ReindexAction::RegeneratePrompts,
);
}
2024-09-02 13:52:18 +02:00
2024-08-27 17:52:09 +02:00
if document_template_max_bytes.apply(new_document_template_max_bytes) {
2024-09-02 13:52:18 +02:00
let previous_document_template_max_bytes =
document_template_max_bytes.set().unwrap_or(default_max_bytes().get());
let new_document_template_max_bytes =
new_document_template_max_bytes.set().unwrap_or(default_max_bytes().get());
// only reindex if the size increased. Reasoning:
// - size decrease is a performance optimization, so we don't reindex and we keep the more accurate vectors
// - size increase is an accuracy optimization, so we want to reindex
if new_document_template_max_bytes > previous_document_template_max_bytes {
ReindexAction::push_action(
&mut reindex_action,
ReindexAction::RegeneratePrompts,
)
}
2024-08-27 17:52:09 +02:00
}
2024-06-12 14:03:40 +02:00
distribution.apply(new_distribution);
api_key.apply(new_api_key);
2024-07-22 12:04:05 +02:00
headers.apply(new_headers);
2024-06-12 14:03:40 +02:00
let updated_settings = EmbeddingSettings {
source,
model,
revision,
api_key,
dimensions,
document_template,
url,
2024-07-16 16:00:21 +02:00
request,
response,
2024-06-12 14:03:40 +02:00
distribution,
2024-07-22 12:04:05 +02:00
headers,
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
binary_quantized: binary_quantize,
2024-06-12 14:03:40 +02:00
};
match reindex_action {
Some(action) => Self::Reindex {
action,
updated_settings,
quantize: binary_quantize_changed,
},
None => Self::UpdateWithoutReindex {
updated_settings,
quantize: binary_quantize_changed,
},
2024-06-12 14:03:40 +02:00
}
}
Setting::Reset => Self::Remove,
Setting::NotSet => {
Self::UpdateWithoutReindex { updated_settings: old, quantize: false }
}
};
Ok(ret)
2024-06-12 14:03:40 +02:00
}
}
impl ReindexAction {
fn push_action(this: &mut Option<Self>, other: Self) {
*this = match (*this, other) {
(_, ReindexAction::FullReindex) => Some(ReindexAction::FullReindex),
(Some(ReindexAction::FullReindex), _) => Some(ReindexAction::FullReindex),
(_, ReindexAction::RegeneratePrompts) => Some(ReindexAction::RegeneratePrompts),
}
}
}
#[allow(clippy::too_many_arguments)] // private function
fn apply_default_for_source(
source: &Setting<EmbedderSource>,
model: &mut Setting<String>,
revision: &mut Setting<String>,
dimensions: &mut Setting<usize>,
url: &mut Setting<String>,
2024-07-16 16:00:21 +02:00
request: &mut Setting<serde_json::Value>,
response: &mut Setting<serde_json::Value>,
2024-06-12 14:03:40 +02:00
document_template: &mut Setting<String>,
2024-08-27 17:52:09 +02:00
document_template_max_bytes: &mut Setting<usize>,
2024-07-22 12:04:05 +02:00
headers: &mut Setting<BTreeMap<String, String>>,
2024-06-12 14:03:40 +02:00
) {
match source {
Setting::Set(EmbedderSource::HuggingFace) => {
*model = Setting::Reset;
*revision = Setting::Reset;
*dimensions = Setting::NotSet;
*url = Setting::NotSet;
2024-07-16 16:00:21 +02:00
*request = Setting::NotSet;
*response = Setting::NotSet;
2024-07-22 12:04:05 +02:00
*headers = Setting::NotSet;
2024-06-12 14:03:40 +02:00
}
Setting::Set(EmbedderSource::Ollama) => {
*model = Setting::Reset;
*revision = Setting::NotSet;
*dimensions = Setting::Reset;
*url = Setting::NotSet;
2024-07-16 16:00:21 +02:00
*request = Setting::NotSet;
*response = Setting::NotSet;
2024-07-22 12:04:05 +02:00
*headers = Setting::NotSet;
2024-06-12 14:03:40 +02:00
}
Setting::Set(EmbedderSource::OpenAi) | Setting::Reset => {
*model = Setting::Reset;
*revision = Setting::NotSet;
*dimensions = Setting::NotSet;
2024-07-15 16:20:19 +02:00
*url = Setting::Reset;
2024-07-16 16:00:21 +02:00
*request = Setting::NotSet;
*response = Setting::NotSet;
2024-07-22 12:04:05 +02:00
*headers = Setting::NotSet;
2024-06-12 14:03:40 +02:00
}
Setting::Set(EmbedderSource::Rest) => {
*model = Setting::NotSet;
*revision = Setting::NotSet;
*dimensions = Setting::Reset;
*url = Setting::Reset;
2024-07-16 16:00:21 +02:00
*request = Setting::Reset;
*response = Setting::Reset;
2024-07-22 12:04:05 +02:00
*headers = Setting::Reset;
2024-06-12 14:03:40 +02:00
}
Setting::Set(EmbedderSource::UserProvided) => {
*model = Setting::NotSet;
*revision = Setting::NotSet;
*dimensions = Setting::Reset;
*url = Setting::NotSet;
2024-07-16 16:00:21 +02:00
*request = Setting::NotSet;
*response = Setting::NotSet;
2024-06-12 14:03:40 +02:00
*document_template = Setting::NotSet;
2024-08-27 17:52:09 +02:00
*document_template_max_bytes = Setting::NotSet;
2024-07-22 12:04:05 +02:00
*headers = Setting::NotSet;
2024-06-12 14:03:40 +02:00
}
Setting::NotSet => {}
}
}
2023-12-20 17:08:32 +01:00
pub fn check_set<T>(
key: &Setting<T>,
field: &'static str,
source: EmbedderSource,
embedder_name: &str,
) -> Result<(), UserError> {
if matches!(key, Setting::Set(_)) {
Ok(())
} else {
Err(UserError::MissingFieldForSource {
field,
source_: source,
embedder_name: embedder_name.to_owned(),
})
}
}
2023-12-20 17:08:32 +01:00
impl EmbeddingSettings {
2023-12-20 17:48:09 +01:00
pub const SOURCE: &'static str = "source";
pub const MODEL: &'static str = "model";
pub const REVISION: &'static str = "revision";
pub const API_KEY: &'static str = "apiKey";
pub const DIMENSIONS: &'static str = "dimensions";
pub const DOCUMENT_TEMPLATE: &'static str = "documentTemplate";
2024-08-27 17:52:09 +02:00
pub const DOCUMENT_TEMPLATE_MAX_BYTES: &'static str = "documentTemplateMaxBytes";
2023-12-20 17:08:32 +01:00
2024-03-25 10:05:38 +01:00
pub const URL: &'static str = "url";
2024-07-16 16:00:21 +02:00
pub const REQUEST: &'static str = "request";
pub const RESPONSE: &'static str = "response";
2024-07-22 12:04:05 +02:00
pub const HEADERS: &'static str = "headers";
2024-03-25 10:05:38 +01:00
2024-03-27 11:51:04 +01:00
pub const DISTRIBUTION: &'static str = "distribution";
pub const BINARY_QUANTIZED: &'static str = "binaryQuantized";
2023-12-20 17:08:32 +01:00
pub fn allowed_sources_for_field(field: &'static str) -> &'static [EmbedderSource] {
match field {
2024-03-25 10:05:38 +01:00
Self::SOURCE => &[
EmbedderSource::HuggingFace,
EmbedderSource::OpenAi,
EmbedderSource::UserProvided,
EmbedderSource::Rest,
EmbedderSource::Ollama,
],
Self::MODEL => {
&[EmbedderSource::HuggingFace, EmbedderSource::OpenAi, EmbedderSource::Ollama]
}
2023-12-20 17:08:32 +01:00
Self::REVISION => &[EmbedderSource::HuggingFace],
2024-03-25 11:50:00 +01:00
Self::API_KEY => {
&[EmbedderSource::OpenAi, EmbedderSource::Ollama, EmbedderSource::Rest]
}
2024-07-22 12:09:52 +02:00
Self::DIMENSIONS => &[
EmbedderSource::OpenAi,
EmbedderSource::UserProvided,
EmbedderSource::Ollama,
EmbedderSource::Rest,
],
2024-03-25 10:05:38 +01:00
Self::DOCUMENT_TEMPLATE => &[
EmbedderSource::HuggingFace,
EmbedderSource::OpenAi,
EmbedderSource::Ollama,
EmbedderSource::Rest,
],
2024-07-15 16:20:19 +02:00
Self::URL => &[EmbedderSource::Ollama, EmbedderSource::Rest, EmbedderSource::OpenAi],
2024-07-16 16:00:21 +02:00
Self::REQUEST => &[EmbedderSource::Rest],
Self::RESPONSE => &[EmbedderSource::Rest],
2024-07-22 12:04:05 +02:00
Self::HEADERS => &[EmbedderSource::Rest],
2024-03-27 11:51:04 +01:00
Self::DISTRIBUTION => &[
EmbedderSource::HuggingFace,
EmbedderSource::Ollama,
EmbedderSource::OpenAi,
EmbedderSource::Rest,
EmbedderSource::UserProvided,
],
Self::BINARY_QUANTIZED => &[
EmbedderSource::HuggingFace,
EmbedderSource::Ollama,
EmbedderSource::OpenAi,
EmbedderSource::Rest,
EmbedderSource::UserProvided,
],
2023-12-20 17:08:32 +01:00
_other => unreachable!("unknown field"),
}
}
2023-12-20 17:08:32 +01:00
pub fn allowed_fields_for_source(source: EmbedderSource) -> &'static [&'static str] {
match source {
EmbedderSource::OpenAi => &[
Self::SOURCE,
Self::MODEL,
Self::API_KEY,
Self::DOCUMENT_TEMPLATE,
Self::DIMENSIONS,
2024-03-27 11:51:04 +01:00
Self::DISTRIBUTION,
2024-07-15 16:20:19 +02:00
Self::URL,
Self::BINARY_QUANTIZED,
],
2024-03-27 11:51:04 +01:00
EmbedderSource::HuggingFace => &[
Self::SOURCE,
Self::MODEL,
Self::REVISION,
Self::DOCUMENT_TEMPLATE,
Self::DISTRIBUTION,
Self::BINARY_QUANTIZED,
2024-03-27 11:51:04 +01:00
],
EmbedderSource::Ollama => &[
Self::SOURCE,
Self::MODEL,
Self::DOCUMENT_TEMPLATE,
Self::URL,
Self::API_KEY,
2024-07-22 12:09:52 +02:00
Self::DIMENSIONS,
2024-03-27 11:51:04 +01:00
Self::DISTRIBUTION,
Self::BINARY_QUANTIZED,
2024-03-27 11:51:04 +01:00
],
EmbedderSource::UserProvided => {
&[Self::SOURCE, Self::DIMENSIONS, Self::DISTRIBUTION, Self::BINARY_QUANTIZED]
}
2024-03-25 10:05:38 +01:00
EmbedderSource::Rest => &[
Self::SOURCE,
Self::API_KEY,
Self::DIMENSIONS,
Self::DOCUMENT_TEMPLATE,
Self::URL,
2024-07-16 16:00:21 +02:00
Self::REQUEST,
Self::RESPONSE,
2024-07-22 12:04:05 +02:00
Self::HEADERS,
2024-03-27 11:51:04 +01:00
Self::DISTRIBUTION,
Self::BINARY_QUANTIZED,
2024-03-25 10:05:38 +01:00
],
}
}
2023-12-20 17:08:32 +01:00
pub(crate) fn apply_default_source(setting: &mut Setting<EmbeddingSettings>) {
if let Setting::Set(EmbeddingSettings {
source: source @ (Setting::NotSet | Setting::Reset),
..
}) = setting
{
*source = Setting::Set(EmbedderSource::default())
}
}
pub(crate) fn apply_default_openai_model(setting: &mut Setting<EmbeddingSettings>) {
if let Setting::Set(EmbeddingSettings {
source: Setting::Set(EmbedderSource::OpenAi),
model: model @ (Setting::NotSet | Setting::Reset),
..
}) = setting
{
*model = Setting::Set(openai::EmbeddingModel::default().name().to_owned())
}
}
}
2023-12-20 17:08:32 +01:00
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, Deserr)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
#[deserr(rename_all = camelCase, deny_unknown_fields)]
2023-12-20 17:08:32 +01:00
pub enum EmbedderSource {
#[default]
OpenAi,
HuggingFace,
Ollama,
2023-12-20 17:08:32 +01:00
UserProvided,
2024-03-25 10:05:38 +01:00
Rest,
}
2023-12-20 17:08:32 +01:00
impl std::fmt::Display for EmbedderSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
EmbedderSource::OpenAi => "openAi",
EmbedderSource::HuggingFace => "huggingFace",
EmbedderSource::UserProvided => "userProvided",
EmbedderSource::Ollama => "ollama",
2024-03-25 10:05:38 +01:00
EmbedderSource::Rest => "rest",
2023-12-20 17:08:32 +01:00
};
f.write_str(s)
}
}
2023-12-20 17:08:32 +01:00
impl From<EmbeddingConfig> for EmbeddingSettings {
fn from(value: EmbeddingConfig) -> Self {
let EmbeddingConfig { embedder_options, prompt, quantized } = value;
2024-08-27 17:52:09 +02:00
let document_template_max_bytes =
Setting::Set(prompt.max_bytes.unwrap_or(default_max_bytes()).get());
2023-12-20 17:08:32 +01:00
match embedder_options {
super::EmbedderOptions::HuggingFace(super::hf::EmbedderOptions {
model,
revision,
distribution,
}) => Self {
2023-12-20 17:08:32 +01:00
source: Setting::Set(EmbedderSource::HuggingFace),
model: Setting::Set(model),
2024-07-22 12:40:04 +02:00
revision: Setting::some_or_not_set(revision),
2023-12-20 17:08:32 +01:00
api_key: Setting::NotSet,
dimensions: Setting::NotSet,
document_template: Setting::Set(prompt.template),
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
2024-03-25 10:05:38 +01:00
url: Setting::NotSet,
2024-07-16 16:00:21 +02:00
request: Setting::NotSet,
response: Setting::NotSet,
2024-07-22 12:04:05 +02:00
headers: Setting::NotSet,
2024-07-22 12:40:04 +02:00
distribution: Setting::some_or_not_set(distribution),
binary_quantized: Setting::some_or_not_set(quantized),
2023-12-20 17:08:32 +01:00
},
super::EmbedderOptions::OpenAi(super::openai::EmbedderOptions {
2024-07-15 16:20:19 +02:00
url,
api_key,
embedding_model,
dimensions,
distribution,
}) => Self {
2023-12-20 17:08:32 +01:00
source: Setting::Set(EmbedderSource::OpenAi),
model: Setting::Set(embedding_model.name().to_owned()),
2023-12-20 17:08:32 +01:00
revision: Setting::NotSet,
2024-07-22 12:40:04 +02:00
api_key: Setting::some_or_not_set(api_key),
dimensions: Setting::some_or_not_set(dimensions),
document_template: Setting::Set(prompt.template),
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
2024-07-22 12:40:04 +02:00
url: Setting::some_or_not_set(url),
2024-07-16 16:00:21 +02:00
request: Setting::NotSet,
response: Setting::NotSet,
2024-07-22 12:04:05 +02:00
headers: Setting::NotSet,
2024-07-22 12:40:04 +02:00
distribution: Setting::some_or_not_set(distribution),
binary_quantized: Setting::some_or_not_set(quantized),
},
super::EmbedderOptions::Ollama(super::ollama::EmbedderOptions {
embedding_model,
url,
api_key,
distribution,
2024-07-22 12:09:52 +02:00
dimensions,
}) => Self {
source: Setting::Set(EmbedderSource::Ollama),
model: Setting::Set(embedding_model),
revision: Setting::NotSet,
2024-07-22 12:40:04 +02:00
api_key: Setting::some_or_not_set(api_key),
dimensions: Setting::some_or_not_set(dimensions),
document_template: Setting::Set(prompt.template),
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
2024-07-22 12:40:04 +02:00
url: Setting::some_or_not_set(url),
2024-07-16 16:00:21 +02:00
request: Setting::NotSet,
response: Setting::NotSet,
2024-07-22 12:04:05 +02:00
headers: Setting::NotSet,
2024-07-22 12:40:04 +02:00
distribution: Setting::some_or_not_set(distribution),
binary_quantized: Setting::some_or_not_set(quantized),
},
super::EmbedderOptions::UserProvided(super::manual::EmbedderOptions {
dimensions,
distribution,
}) => Self {
2023-12-20 17:08:32 +01:00
source: Setting::Set(EmbedderSource::UserProvided),
model: Setting::NotSet,
revision: Setting::NotSet,
api_key: Setting::NotSet,
dimensions: Setting::Set(dimensions),
2023-12-20 17:08:32 +01:00
document_template: Setting::NotSet,
2024-08-27 17:52:09 +02:00
document_template_max_bytes: Setting::NotSet,
2024-03-25 10:05:38 +01:00
url: Setting::NotSet,
2024-07-16 16:00:21 +02:00
request: Setting::NotSet,
response: Setting::NotSet,
2024-07-22 12:04:05 +02:00
headers: Setting::NotSet,
2024-07-22 12:40:04 +02:00
distribution: Setting::some_or_not_set(distribution),
binary_quantized: Setting::some_or_not_set(quantized),
2024-03-25 10:05:38 +01:00
},
super::EmbedderOptions::Rest(super::rest::EmbedderOptions {
api_key,
dimensions,
url,
2024-07-16 16:00:21 +02:00
request,
response,
2024-03-27 11:51:04 +01:00
distribution,
2024-07-22 12:04:05 +02:00
headers,
2024-03-25 10:05:38 +01:00
}) => Self {
source: Setting::Set(EmbedderSource::Rest),
model: Setting::NotSet,
revision: Setting::NotSet,
2024-07-22 12:40:04 +02:00
api_key: Setting::some_or_not_set(api_key),
dimensions: Setting::some_or_not_set(dimensions),
2024-03-25 10:05:38 +01:00
document_template: Setting::Set(prompt.template),
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
2024-03-25 10:05:38 +01:00
url: Setting::Set(url),
2024-07-16 16:00:21 +02:00
request: Setting::Set(request),
response: Setting::Set(response),
2024-07-22 12:40:04 +02:00
distribution: Setting::some_or_not_set(distribution),
2024-07-22 12:04:05 +02:00
headers: Setting::Set(headers),
binary_quantized: Setting::some_or_not_set(quantized),
2023-12-20 17:08:32 +01:00
},
}
}
}
2023-12-20 17:08:32 +01:00
impl From<EmbeddingSettings> for EmbeddingConfig {
fn from(value: EmbeddingSettings) -> Self {
let mut this = Self::default();
2024-03-25 10:05:38 +01:00
let EmbeddingSettings {
source,
model,
revision,
api_key,
dimensions,
document_template,
2024-08-27 17:52:09 +02:00
document_template_max_bytes,
2024-03-25 10:05:38 +01:00
url,
2024-07-16 16:00:21 +02:00
request,
response,
2024-03-27 11:51:04 +01:00
distribution,
2024-07-22 12:04:05 +02:00
headers,
binary_quantized,
2024-03-25 10:05:38 +01:00
} = value;
2024-03-27 11:51:04 +01:00
this.quantized = binary_quantized.set();
2023-12-20 17:08:32 +01:00
if let Some(source) = source.set() {
match source {
EmbedderSource::OpenAi => {
let mut options = super::openai::EmbedderOptions::with_default_model(None);
if let Some(model) = model.set() {
if let Some(model) = super::openai::EmbeddingModel::from_name(&model) {
options.embedding_model = model;
}
}
2024-07-15 16:20:19 +02:00
if let Some(url) = url.set() {
options.url = Some(url);
}
2023-12-20 17:08:32 +01:00
if let Some(api_key) = api_key.set() {
options.api_key = Some(api_key);
}
if let Some(dimensions) = dimensions.set() {
options.dimensions = Some(dimensions);
}
2024-03-27 11:51:04 +01:00
options.distribution = distribution.set();
2023-12-20 17:08:32 +01:00
this.embedder_options = super::EmbedderOptions::OpenAi(options);
}
EmbedderSource::Ollama => {
let mut options: ollama::EmbedderOptions =
2024-03-25 11:50:00 +01:00
super::ollama::EmbedderOptions::with_default_model(
api_key.set(),
url.set(),
2024-07-22 12:09:52 +02:00
dimensions.set(),
2024-03-25 11:50:00 +01:00
);
if let Some(model) = model.set() {
options.embedding_model = model;
}
2024-03-27 11:51:04 +01:00
options.distribution = distribution.set();
this.embedder_options = super::EmbedderOptions::Ollama(options);
}
2023-12-20 17:08:32 +01:00
EmbedderSource::HuggingFace => {
let mut options = super::hf::EmbedderOptions::default();
if let Some(model) = model.set() {
options.model = model;
// Reset the revision if we are setting the model.
// This allows the following:
// "huggingFace": {} -> default model with default revision
// "huggingFace": { "model": "name-of-the-default-model" } -> default model without a revision
// "huggingFace": { "model": "some-other-model" } -> most importantly, other model without a revision
options.revision = None;
}
if let Some(revision) = revision.set() {
options.revision = Some(revision);
}
2024-03-27 11:51:04 +01:00
options.distribution = distribution.set();
2023-12-20 17:08:32 +01:00
this.embedder_options = super::EmbedderOptions::HuggingFace(options);
}
EmbedderSource::UserProvided => {
this.embedder_options =
super::EmbedderOptions::UserProvided(super::manual::EmbedderOptions {
dimensions: dimensions.set().unwrap(),
2024-03-27 11:51:04 +01:00
distribution: distribution.set(),
2023-12-20 17:08:32 +01:00
});
}
2024-03-25 10:05:38 +01:00
EmbedderSource::Rest => {
this.embedder_options =
super::EmbedderOptions::Rest(super::rest::EmbedderOptions {
api_key: api_key.set(),
dimensions: dimensions.set(),
url: url.set().unwrap(),
2024-07-16 16:00:21 +02:00
request: request.set().unwrap(),
response: response.set().unwrap(),
2024-03-27 11:51:04 +01:00
distribution: distribution.set(),
2024-07-22 12:04:05 +02:00
headers: headers.set().unwrap_or_default(),
2024-03-25 10:05:38 +01:00
})
}
2023-12-20 17:08:32 +01:00
}
}
2023-12-20 17:08:32 +01:00
if let Setting::Set(template) = document_template {
2024-08-27 17:52:09 +02:00
let max_bytes = document_template_max_bytes
.set()
.and_then(NonZeroUsize::new)
.unwrap_or(default_max_bytes());
this.prompt = PromptData { template, max_bytes: Some(max_bytes) }
2023-12-20 17:08:32 +01:00
}
2023-12-20 17:08:32 +01:00
this
}
}