Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 47 additions & 67 deletions backends/candle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,38 @@ use crate::models::{
FlashQwen2Model, FlashQwen3Model,
};

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FlashAttn {
V1,
V2,
}

#[allow(unused)]
fn use_flash_attn(supported: &[FlashAttn]) -> bool {
#[cfg(not(feature = "cuda"))]
{
tracing::warn!("Flash Attention is not supported on CPU yet");
false
}
#[cfg(feature = "cuda")]
{
if std::env::var("USE_FLASH_ATTENTION")
.unwrap_or_else(|_| "True".to_string())
.to_lowercase()
!= "true"
{
false
} else {
supported.iter().any(|v| match v {
FlashAttn::V1 => cfg!(feature = "flash-attn-v1"),
FlashAttn::V2 => {
cfg!(feature = "flash-attn") && get_runtime_compute_cap().is_ok_and(|x| x >= 80)
}
})
}
}
}

/// This enum is needed to be able to differentiate between jina models that also use
/// the `bert` model type and valid Bert models.
#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -332,12 +364,7 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::Bert(config), Device::Cuda(_)) => {
if cfg!(any(feature = "flash-attn", feature = "flash-attn-v1"))
&& dtype == DType::F16
// Allow disabling because of flash attention v1 precision problems
// See: https://github.com/huggingface/text-embeddings-inference/issues/37
&& &std::env::var("USE_FLASH_ATTENTION").unwrap_or("True".to_string()).to_lowercase() == "true"
{
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V1, FlashAttn::V2]) {
match config {
BertConfigWrapper::JinaBert(config) => {
tracing::info!("Starting FlashJinaBert model on {:?}", device);
Expand Down Expand Up @@ -380,12 +407,7 @@ impl CandleBackend {
Config::Camembert(config) | Config::Roberta(config) | Config::XlmRoberta(config),
Device::Cuda(_),
) => {
if cfg!(any(feature = "flash-attn", feature = "flash-attn-v1"))
&& dtype == DType::F16
// Allow disabling because of flash attention v1 precision problems
// See: https://github.com/huggingface/text-embeddings-inference/issues/37
&& &std::env::var("USE_FLASH_ATTENTION").unwrap_or("True".to_string()).to_lowercase() == "true"
{
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V1, FlashAttn::V2]) {
tracing::info!("Starting FlashBert model on {:?}", device);
Ok(Box::new(
FlashBertModel::load_roberta(vb, &config, model_type).s()?,
Expand All @@ -404,13 +426,7 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::DistilBert(config), Device::Cuda(_)) => {
if cfg!(feature = "flash-attn")
&& dtype == DType::F16
&& &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
== "true"
{
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V2]) {
tracing::info!("Starting FlashDistilBert model on {:?}", device);
Ok(Box::new(
FlashDistilBertModel::load(vb, &config, model_type).s()?,
Expand All @@ -435,30 +451,17 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::Gte(config), Device::Cuda(_)) => {
if dtype != DType::F16
|| !cfg!(any(feature = "flash-attn", feature = "flash-attn-v1"))
|| &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
!= "true"
{
tracing::info!("Starting GTE model on {:?}", device);
Ok(Box::new(GTEModel::load(vb, &config, model_type).s()?))
} else {
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V1, FlashAttn::V2]) {
tracing::info!("Starting FlashGTE model on {:?}", device);
Ok(Box::new(FlashGTEModel::load(vb, &config, model_type).s()?))
} else {
tracing::info!("Starting GTE model on {:?}", device);
Ok(Box::new(GTEModel::load(vb, &config, model_type).s()?))
}
}
#[cfg(feature = "cuda")]
(Config::Mistral(config), Device::Cuda(_)) => {
if dtype != DType::F16
|| !cfg!(feature = "flash-attn")
|| get_runtime_compute_cap().unwrap() < 80
|| &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
!= "true"
{
if !(dtype == DType::F16 && use_flash_attn(&[FlashAttn::V2])) {
return Err(BackendError::Start("Mistral is only supported on Cuda devices in fp16 with flash attention v2 enabled".to_string()));
}
tracing::info!("Starting FlashMistral model on {:?}", device);
Expand All @@ -468,12 +471,7 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::ModernBert(config), Device::Cuda(_)) => {
if cfg!(feature = "flash-attn")
&& dtype == DType::F16
// Allow disabling because of flash attention v1 precision problems
// See: https://github.com/huggingface/text-embeddings-inference/issues/37
&& &std::env::var("USE_FLASH_ATTENTION").unwrap_or("True".to_string()).to_lowercase() == "true"
{
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V2]) {
tracing::info!("Starting FlashModernBert model on {:?}", device);
Ok(Box::new(
FlashModernBertModel::load(vb, &config, model_type).s()?,
Expand All @@ -489,13 +487,7 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::NomicBert(config), Device::Cuda(_)) => {
if cfg!(feature = "flash-attn")
&& dtype == DType::F16
&& &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
== "true"
{
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V2]) {
tracing::info!("Starting FlashNomicBert model on {:?}", device);
Ok(Box::new(
FlashNomicBertModel::load(vb, &config, model_type).s()?,
Expand All @@ -507,13 +499,7 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::Qwen2(config), Device::Cuda(_)) => {
if dtype != DType::F16
|| !cfg!(any(feature = "flash-attn", feature = "flash-attn-v1"))
|| &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
!= "true"
{
if !(dtype == DType::F16 && use_flash_attn(&[FlashAttn::V1, FlashAttn::V2])) {
return Err(BackendError::Start("Qwen2 is only supported on Cuda devices in fp16 with flash attention v2 enabled".to_string()));
}
tracing::info!("Starting FlashQwen2 model on {:?}", device);
Expand All @@ -523,20 +509,14 @@ impl CandleBackend {
}
#[cfg(feature = "cuda")]
(Config::Qwen3(config), Device::Cuda(_)) => {
if dtype != DType::F16
|| !cfg!(any(feature = "flash-attn", feature = "flash-attn-v1"))
|| &std::env::var("USE_FLASH_ATTENTION")
.unwrap_or("True".to_string())
.to_lowercase()
!= "true"
{
tracing::info!("Starting Qwen3 model on {:?}", device);
Ok(Box::new(Qwen3Model::load(vb, &config, model_type).s()?))
} else {
if dtype == DType::F16 && use_flash_attn(&[FlashAttn::V1, FlashAttn::V2]) {
tracing::info!("Starting FlashQwen3 model on {:?}", device);
Ok(Box::new(
FlashQwen3Model::load(vb, &config, model_type).s()?,
))
} else {
tracing::info!("Starting Qwen3 model on {:?}", device);
Ok(Box::new(Qwen3Model::load(vb, &config, model_type).s()?))
}
}
#[cfg(feature = "cuda")]
Expand Down
Loading