@@ -11,21 +11,6 @@ use rand::Rng;
1111use tokio:: sync:: { mpsc, oneshot, watch} ;
1212use tracing:: { instrument, Span } ;
1313
14- /// Handle for a model repository on the Hub, bundling the hf-hub repository handle with the
15- /// optional revision. The revision is now passed per-call in hf-hub 1.0, so we carry it
16- /// alongside the handle instead of baking it into a `Repo`.
17- #[ derive( Debug , Clone ) ]
18- pub struct ModelRepo {
19- pub repo : HFRepository < RepoTypeModel > ,
20- pub revision : Option < String > ,
21- }
22-
23- impl ModelRepo {
24- pub fn new ( repo : HFRepository < RepoTypeModel > , revision : Option < String > ) -> Self {
25- Self { repo, revision }
26- }
27- }
28-
2914use text_embeddings_backend_core:: { Backend as CoreBackend , Predictions } ;
3015pub use text_embeddings_backend_core:: {
3116 BackendError , Batch , Embedding , Embeddings , ModelType , Pool ,
@@ -106,7 +91,8 @@ impl Backend {
10691 #[ allow( clippy:: too_many_arguments) ]
10792 pub async fn new (
10893 model_path : PathBuf ,
109- api_repo : Option < ModelRepo > ,
94+ api_repo : Option < HFRepository < RepoTypeModel > > ,
95+ revision : Option < String > ,
11096 dtype : DType ,
11197 model_type : ModelType ,
11298 dense_path : Option < String > ,
@@ -119,6 +105,7 @@ impl Backend {
119105 let backend = init_backend (
120106 model_path,
121107 api_repo,
108+ revision,
122109 dtype,
123110 model_type. clone ( ) ,
124111 dense_path,
@@ -457,7 +444,8 @@ impl Backend {
457444#[ allow( unused, clippy:: too_many_arguments) ]
458445async fn init_backend (
459446 model_path : PathBuf ,
460- api_repo : Option < ModelRepo > ,
447+ api_repo : Option < HFRepository < RepoTypeModel > > ,
448+ revision : Option < String > ,
461449 dtype : DType ,
462450 model_type : ModelType ,
463451 dense_path : Option < String > ,
@@ -466,13 +454,12 @@ async fn init_backend(
466454 otlp_service_name : String ,
467455) -> Result < Box < dyn CoreBackend + Send > , BackendError > {
468456 let mut backend_start_failed = false ;
469- let api_repo = api_repo. map ( Arc :: new) ;
470457
471458 #[ cfg( feature = "ort" ) ]
472459 {
473460 if let Some ( api_repo) = api_repo. as_ref ( ) {
474461 let start = std:: time:: Instant :: now ( ) ;
475- let model_files = download_onnx ( api_repo. clone ( ) )
462+ let model_files = download_onnx ( api_repo, revision . as_deref ( ) )
476463 . await
477464 . map_err ( |err| BackendError :: WeightsNotFound ( err. to_string ( ) ) ) ?;
478465 match model_files. is_empty ( ) {
@@ -490,10 +477,9 @@ async fn init_backend(
490477 if let Some ( api_repo) = api_repo. as_ref ( ) {
491478 tracing:: info!( "Downloading `tokenizer_config.json`" ) ;
492479 match api_repo
493- . repo
494480 . download_file ( )
495481 . filename ( "tokenizer_config.json" )
496- . maybe_revision ( api_repo . revision . clone ( ) )
482+ . maybe_revision ( revision. clone ( ) )
497483 . send ( )
498484 . await
499485 {
@@ -517,14 +503,16 @@ async fn init_backend(
517503 if let Some ( api_repo) = api_repo. as_ref ( ) {
518504 if cfg ! ( feature = "python" ) || cfg ! ( feature = "candle" ) {
519505 let start = std:: time:: Instant :: now ( ) ;
520- if download_safetensors ( api_repo. clone ( ) ) . await . is_err ( ) {
506+ if download_safetensors ( api_repo, revision. as_deref ( ) )
507+ . await
508+ . is_err ( )
509+ {
521510 tracing:: warn!( "safetensors weights not found. Using `pytorch_model.bin` instead. Model loading will be significantly slower." ) ;
522511 tracing:: info!( "Downloading `pytorch_model.bin`" ) ;
523512 api_repo
524- . repo
525513 . download_file ( )
526514 . filename ( "pytorch_model.bin" )
527- . maybe_revision ( api_repo . revision . clone ( ) )
515+ . maybe_revision ( revision. clone ( ) )
528516 . send ( )
529517 . await
530518 . map_err ( |err| BackendError :: WeightsNotFound ( err. to_string ( ) ) ) ?;
@@ -539,7 +527,7 @@ async fn init_backend(
539527 {
540528 let dense_paths = if let Some ( api_repo) = api_repo. as_ref ( ) {
541529 let start = std:: time:: Instant :: now ( ) ;
542- let dense_paths = download_dense_modules ( api_repo, dense_path)
530+ let dense_paths = download_dense_modules ( api_repo, revision . as_deref ( ) , dense_path)
543531 . await
544532 . map_err ( |err| BackendError :: WeightsNotFound ( err. to_string ( ) ) ) ?;
545533 tracing:: info!( "Dense modules downloaded in {:?}" , start. elapsed( ) ) ;
@@ -693,14 +681,16 @@ enum BackendCommand {
693681 ) ,
694682}
695683
696- async fn download_safetensors ( api : Arc < ModelRepo > ) -> Result < Vec < PathBuf > , HFError > {
684+ async fn download_safetensors (
685+ repo : & HFRepository < RepoTypeModel > ,
686+ revision : Option < & str > ,
687+ ) -> Result < Vec < PathBuf > , HFError > {
697688 // Single file
698689 tracing:: info!( "Downloading `model.safetensors`" ) ;
699- match api
700- . repo
690+ match repo
701691 . download_file ( )
702692 . filename ( "model.safetensors" )
703- . maybe_revision ( api . revision . clone ( ) )
693+ . maybe_revision ( revision. map ( String :: from ) )
704694 . send ( )
705695 . await
706696 {
@@ -711,11 +701,10 @@ async fn download_safetensors(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFErr
711701 // Sharded weights
712702 // Download and parse index file
713703 tracing:: info!( "Downloading `model.safetensors.index.json`" ) ;
714- let index_file = api
715- . repo
704+ let index_file = repo
716705 . download_file ( )
717706 . filename ( "model.safetensors.index.json" )
718- . maybe_revision ( api . revision . clone ( ) )
707+ . maybe_revision ( revision. map ( String :: from ) )
719708 . send ( )
720709 . await ?;
721710 let index_file_string: String =
@@ -739,13 +728,13 @@ async fn download_safetensors(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFErr
739728 let handles: Vec < _ > = safetensors_filenames
740729 . into_iter ( )
741730 . map ( |n| {
742- let api = Arc :: clone ( & api) ;
731+ let repo = repo. clone ( ) ;
732+ let revision = revision. map ( String :: from) ;
743733 tokio:: spawn ( async move {
744734 tracing:: info!( "Downloading `{}`" , n) ;
745- api. repo
746- . download_file ( )
735+ repo. download_file ( )
747736 . filename ( n)
748- . maybe_revision ( api . revision . clone ( ) )
737+ . maybe_revision ( revision)
749738 . send ( )
750739 . await
751740 } )
@@ -755,7 +744,7 @@ async fn download_safetensors(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFErr
755744 let mut safetensors_files = Vec :: with_capacity ( handles. len ( ) ) ;
756745 for handle in handles {
757746 // Await the JoinHandle to get the result of the task,
758- // then unpack the inner result from api.repo.download_file()
747+ // then unpack the inner result from the download.
759748 let downloaded = handle
760749 . await
761750 . map_err ( |err| HFError :: Other ( format ! ( "safetensors download task failed: {err}" ) ) ) ?;
@@ -766,14 +755,16 @@ async fn download_safetensors(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFErr
766755}
767756
768757#[ cfg( feature = "ort" ) ]
769- async fn download_onnx ( api : Arc < ModelRepo > ) -> Result < Vec < PathBuf > , HFError > {
758+ async fn download_onnx (
759+ repo : & HFRepository < RepoTypeModel > ,
760+ revision : Option < & str > ,
761+ ) -> Result < Vec < PathBuf > , HFError > {
770762 // TODO: Most likely all the download functions could benefit from the information defined in
771763 // `info()` so that we just need to run the HTTP GET request once (and more efficiently
772764 // download the required and existing files only).
773- let filenames = match api
774- . repo
765+ let filenames = match repo
775766 . info ( )
776- . maybe_revision ( api . revision . clone ( ) )
767+ . maybe_revision ( revision. map ( String :: from ) )
777768 . send ( )
778769 . await
779770 {
@@ -800,15 +791,15 @@ async fn download_onnx(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFError> {
800791 let handles: Vec < _ > = files
801792 . into_iter ( )
802793 . map ( |file| {
803- let api = Arc :: clone ( & api) ;
794+ let repo = repo. clone ( ) ;
795+ let revision = revision. map ( String :: from) ;
804796 tokio:: spawn ( async move {
805797 tracing:: info!( "Downloading `{}`" , file) ;
806798 let time = std:: time:: Instant :: now ( ) ;
807- match api
808- . repo
799+ match repo
809800 . download_file ( )
810801 . filename ( file. clone ( ) )
811- . maybe_revision ( api . revision . clone ( ) )
802+ . maybe_revision ( revision)
812803 . send ( )
813804 . await
814805 {
@@ -842,11 +833,10 @@ async fn download_onnx(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFError> {
842833 let mut downloaded_files = Vec :: < PathBuf > :: new ( ) ;
843834
844835 tracing:: info!( "Downloading `onnx/model.onnx`" ) ;
845- match api
846- . repo
836+ match repo
847837 . download_file ( )
848838 . filename ( "onnx/model.onnx" )
849- . maybe_revision ( api . revision . clone ( ) )
839+ . maybe_revision ( revision. map ( String :: from ) )
850840 . send ( )
851841 . await
852842 {
@@ -855,11 +845,10 @@ async fn download_onnx(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFError> {
855845 tracing:: warn!( "Could not download `onnx/model.onnx`: {err}" ) ;
856846 tracing:: info!( "Downloading `model.onnx`" ) ;
857847
858- match api
859- . repo
848+ match repo
860849 . download_file ( )
861850 . filename ( "model.onnx" )
862- . maybe_revision ( api . revision . clone ( ) )
851+ . maybe_revision ( revision. map ( String :: from ) )
863852 . send ( )
864853 . await
865854 {
@@ -870,11 +859,10 @@ async fn download_onnx(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFError> {
870859 } ;
871860
872861 tracing:: info!( "Downloading `onnx/model.onnx_data`" ) ;
873- match api
874- . repo
862+ match repo
875863 . download_file ( )
876864 . filename ( "onnx/model.onnx_data" )
877- . maybe_revision ( api . revision . clone ( ) )
865+ . maybe_revision ( revision. map ( String :: from ) )
878866 . send ( )
879867 . await
880868 {
@@ -883,11 +871,10 @@ async fn download_onnx(api: Arc<ModelRepo>) -> Result<Vec<PathBuf>, HFError> {
883871 tracing:: warn!( "Could not download `onnx/model.onnx_data`: {err}" ) ;
884872 tracing:: info!( "Downloading `model.onnx_data`" ) ;
885873
886- match api
887- . repo
874+ match repo
888875 . download_file ( )
889876 . filename ( "model.onnx_data" )
890- . maybe_revision ( api . revision . clone ( ) )
877+ . maybe_revision ( revision. map ( String :: from ) )
891878 . send ( )
892879 . await
893880 {
@@ -928,12 +915,15 @@ struct ModuleConfig {
928915}
929916
930917#[ cfg( feature = "candle" ) ]
931- async fn download_file ( api : & ModelRepo , file_path : & str ) -> Result < PathBuf , HFError > {
918+ async fn download_file (
919+ repo : & HFRepository < RepoTypeModel > ,
920+ revision : Option < & str > ,
921+ file_path : & str ,
922+ ) -> Result < PathBuf , HFError > {
932923 tracing:: info!( "Downloading `{}`" , file_path) ;
933- api. repo
934- . download_file ( )
924+ repo. download_file ( )
935925 . filename ( file_path)
936- . maybe_revision ( api . revision . clone ( ) )
926+ . maybe_revision ( revision. map ( String :: from ) )
937927 . send ( )
938928 . await
939929}
@@ -956,10 +946,11 @@ async fn parse_dense_paths_from_modules(
956946#[ cfg( feature = "candle" ) ]
957947#[ instrument( skip_all) ]
958948pub async fn download_dense_modules (
959- api : & ModelRepo ,
949+ repo : & HFRepository < RepoTypeModel > ,
950+ revision : Option < & str > ,
960951 dense_path : Option < String > ,
961952) -> Result < Vec < String > , HFError > {
962- match download_file ( api , "modules.json" ) . await {
953+ match download_file ( repo , revision , "modules.json" ) . await {
963954 Ok ( modules_path) => {
964955 // If `modules.json` exists, then parse it to capture the Dense modules
965956 match parse_dense_paths_from_modules ( & modules_path) . await {
@@ -982,7 +973,7 @@ pub async fn download_dense_modules(
982973 module_paths[ 0 ] . clone ( )
983974 } ;
984975
985- download_dense_module ( api , & path_to_use)
976+ download_dense_module ( repo , revision , & path_to_use)
986977 . await
987978 . map_err ( |err| {
988979 tracing:: error!(
@@ -1005,7 +996,7 @@ pub async fn download_dense_modules(
1005996 // NOTE: since the Dense modules here are specified in the
1006997 // `modules.json` file, then fail if any of those cannot be
1007998 // downloaded
1008- download_dense_module ( api , module_path)
999+ download_dense_module ( repo , revision , module_path)
10091000 . await
10101001 . map_err ( |err| {
10111002 tracing:: error!(
@@ -1031,10 +1022,14 @@ pub async fn download_dense_modules(
10311022}
10321023
10331024#[ cfg( feature = "candle" ) ]
1034- async fn download_dense_module ( api : & ModelRepo , dense_path : & str ) -> Result < PathBuf , HFError > {
1025+ async fn download_dense_module (
1026+ repo : & HFRepository < RepoTypeModel > ,
1027+ revision : Option < & str > ,
1028+ dense_path : & str ,
1029+ ) -> Result < PathBuf , HFError > {
10351030 // Download `config.json` for the Dense module
10361031 let config_file = format ! ( "{}/config.json" , dense_path) ;
1037- let config_path = match download_file ( api , & config_file) . await {
1032+ let config_path = match download_file ( repo , revision , & config_file) . await {
10381033 Ok ( path) => path,
10391034 Err ( err) => {
10401035 tracing:: warn!( "Failed to download `{config_file}` file: {err}" ) ;
@@ -1044,11 +1039,11 @@ async fn download_dense_module(api: &ModelRepo, dense_path: &str) -> Result<Path
10441039
10451040 // Try to download the `model.safetensors` first
10461041 let safetensors_file = format ! ( "{}/model.safetensors" , dense_path) ;
1047- if let Err ( err) = download_file ( api , & safetensors_file) . await {
1042+ if let Err ( err) = download_file ( repo , revision , & safetensors_file) . await {
10481043 tracing:: warn!( "Failed to download `{safetensors_file}` file: {err}" ) ;
10491044 // Fallback to former `pytorch_model.bin`
10501045 let pytorch_file = format ! ( "{}/pytorch_model.bin" , dense_path) ;
1051- if let Err ( err) = download_file ( api , & pytorch_file) . await {
1046+ if let Err ( err) = download_file ( repo , revision , & pytorch_file) . await {
10521047 tracing:: warn!( "Failed to download `{pytorch_file}` file: {err}" ) ;
10531048 return Err ( err) ;
10541049 }
0 commit comments