11mod host;
2+ pub mod spin;
23
34use std:: collections:: { HashMap , HashSet } ;
45use std:: sync:: Arc ;
@@ -11,26 +12,28 @@ use spin_factors::{
1112use spin_locked_app:: MetadataKey ;
1213use spin_world:: v1:: llm:: { self as v1} ;
1314use spin_world:: v2:: llm:: { self as v2} ;
15+ use tokio:: sync:: Mutex ;
1416
1517pub const ALLOWED_MODELS_KEY : MetadataKey < Vec < String > > = MetadataKey :: new ( "ai_models" ) ;
1618
19+ /// The factor for LLMs.
1720pub struct LlmFactor {
18- create_engine : Box < dyn Fn ( ) -> Box < dyn LlmEngine > + Send + Sync > ,
21+ default_engine_creator : Box < dyn LlmEngineCreator > ,
1922}
2023
2124impl LlmFactor {
22- pub fn new < F > ( create_engine : F ) -> Self
23- where
24- F : Fn ( ) -> Box < dyn LlmEngine > + Send + Sync + ' static ,
25- {
25+ /// Creates a new LLM factor with the given default engine creator.
26+ ///
27+ /// The default engine creator is used to create the engine if no runtime configuration is provided.
28+ pub fn new < F : LlmEngineCreator + ' static > ( default_engine_creator : F ) -> Self {
2629 Self {
27- create_engine : Box :: new ( create_engine ) ,
30+ default_engine_creator : Box :: new ( default_engine_creator ) ,
2831 }
2932 }
3033}
3134
3235impl Factor for LlmFactor {
33- type RuntimeConfig = ( ) ;
36+ type RuntimeConfig = RuntimeConfig ;
3437 type AppState = AppState ;
3538 type InstanceBuilder = InstanceState ;
3639
@@ -45,7 +48,7 @@ impl Factor for LlmFactor {
4548
4649 fn configure_app < T : RuntimeFactors > (
4750 & self ,
48- ctx : ConfigureAppContext < T , Self > ,
51+ mut ctx : ConfigureAppContext < T , Self > ,
4952 ) -> anyhow:: Result < Self :: AppState > {
5053 let component_allowed_models = ctx
5154 . app ( )
@@ -62,7 +65,12 @@ impl Factor for LlmFactor {
6265 ) )
6366 } )
6467 . collect :: < anyhow:: Result < _ > > ( ) ?;
68+ let engine = ctx
69+ . take_runtime_config ( )
70+ . map ( |c| c. engine )
71+ . unwrap_or_else ( || self . default_engine_creator . create ( ) ) ;
6572 Ok ( AppState {
73+ engine,
6674 component_allowed_models,
6775 } )
6876 }
@@ -78,25 +86,35 @@ impl Factor for LlmFactor {
7886 . get ( ctx. app_component ( ) . id ( ) )
7987 . cloned ( )
8088 . unwrap_or_default ( ) ;
89+ let engine = ctx. app_state ( ) . engine . clone ( ) ;
8190
8291 Ok ( InstanceState {
83- engine : ( self . create_engine ) ( ) ,
92+ engine,
8493 allowed_models,
8594 } )
8695 }
8796}
8897
98+ /// The application state for the LLM factor.
8999pub struct AppState {
100+ engine : Arc < Mutex < dyn LlmEngine > > ,
90101 component_allowed_models : HashMap < String , Arc < HashSet < String > > > ,
91102}
92103
104+ /// The instance state for the LLM factor.
93105pub struct InstanceState {
94- engine : Box < dyn LlmEngine > ,
106+ engine : Arc < Mutex < dyn LlmEngine > > ,
95107 pub allowed_models : Arc < HashSet < String > > ,
96108}
97109
110+ /// The runtime configuration for the LLM factor.
111+ pub struct RuntimeConfig {
112+ engine : Arc < Mutex < dyn LlmEngine > > ,
113+ }
114+
98115impl SelfInstanceBuilder for InstanceState { }
99116
117+ /// The interface for a language model engine.
100118#[ async_trait]
101119pub trait LlmEngine : Send + Sync {
102120 async fn infer (
@@ -112,3 +130,17 @@ pub trait LlmEngine: Send + Sync {
112130 data : Vec < String > ,
113131 ) -> Result < v2:: EmbeddingsResult , v2:: Error > ;
114132}
133+
134+ /// A creator for an LLM engine.
135+ pub trait LlmEngineCreator : Send + Sync {
136+ fn create ( & self ) -> Arc < Mutex < dyn LlmEngine > > ;
137+ }
138+
139+ impl < F > LlmEngineCreator for F
140+ where
141+ F : Fn ( ) -> Arc < Mutex < dyn LlmEngine > > + Send + Sync ,
142+ {
143+ fn create ( & self ) -> Arc < Mutex < dyn LlmEngine > > {
144+ self ( )
145+ }
146+ }
0 commit comments