1
- use crate :: error:: AIProxyError ;
2
1
use crate :: AHNLICH_AI_RESERVED_META_KEY ;
3
- use ahnlich_types:: ai:: AIModel ;
4
- use ahnlich_types:: ai:: AIStoreInfo ;
2
+ use crate :: { engine:: ai:: AIModelManager , error:: AIProxyError } ;
3
+ use ahnlich_types:: ai:: {
4
+ AIModel , AIStoreInfo , AIStoreInputType , ImageAction , PreprocessAction , StringAction ,
5
+ } ;
5
6
use ahnlich_types:: keyval:: StoreInput ;
6
7
use ahnlich_types:: keyval:: StoreKey ;
7
8
use ahnlich_types:: keyval:: StoreName ;
@@ -57,14 +58,18 @@ impl AIStoreHandler {
57
58
pub ( crate ) fn create_store (
58
59
& self ,
59
60
store_name : StoreName ,
60
-
61
- model : AIModel ,
61
+ query_model : AIModel ,
62
+ index_model : AIModel ,
62
63
) -> Result < ( ) , AIProxyError > {
63
64
if self
64
65
. stores
65
66
. try_insert (
66
67
store_name. clone ( ) ,
67
- Arc :: new ( AIStore :: create ( store_name. clone ( ) , model. clone ( ) ) ) ,
68
+ Arc :: new ( AIStore :: create (
69
+ store_name. clone ( ) ,
70
+ query_model,
71
+ index_model,
72
+ ) ) ,
68
73
& self . stores . guard ( ) ,
69
74
)
70
75
. is_err ( )
@@ -82,8 +87,9 @@ impl AIStoreHandler {
82
87
. iter ( & self . stores . guard ( ) )
83
88
. map ( |( store_name, store) | AIStoreInfo {
84
89
name : store_name. clone ( ) ,
85
- model : store. model . clone ( ) ,
86
- embedding_size : store. model . embedding_size ( ) . into ( ) ,
90
+ query_model : store. query_model . clone ( ) ,
91
+ index_model : store. index_model . clone ( ) ,
92
+ embedding_size : store. index_model . embedding_size ( ) . into ( ) ,
87
93
} )
88
94
. collect ( )
89
95
}
@@ -100,28 +106,58 @@ impl AIStoreHandler {
100
106
}
101
107
102
108
/// Converts storeinput into a tuple of storekey and storevalue.
103
- /// Fails if the type of storeinput does not match the store type
109
+ /// Fails if the store input type does not match the store index_type
104
110
#[ tracing:: instrument( skip( self ) ) ]
105
111
pub ( crate ) fn store_input_to_store_key_val (
106
112
& self ,
107
113
store_name : & StoreName ,
108
114
store_input : StoreInput ,
109
- store_value : & StoreValue ,
115
+ store_value : StoreValue ,
116
+ preprocess_action : & PreprocessAction ,
110
117
) -> Result < ( StoreKey , StoreValue ) , AIProxyError > {
111
118
let metadata_key = & * AHNLICH_AI_RESERVED_META_KEY ;
112
119
if store_value. contains_key ( metadata_key) {
113
120
return Err ( AIProxyError :: ReservedError ( metadata_key. to_string ( ) ) ) ;
114
121
}
115
122
let store = self . get ( store_name) ?;
116
123
117
- let store_key = store. model . model_ndarray ( & store_input) ;
118
- let metadata_value: MetadataValue = store_input. into ( ) ;
124
+ let store_input_type: AIStoreInputType = ( & store_input) . into ( ) ;
125
+ let store_index_model_info = store. index_model . model_info ( ) ;
126
+
127
+ if store_input_type != store_index_model_info. input_type {
128
+ return Err ( AIProxyError :: StoreSetTypeMismatchError {
129
+ store_index_model_type : store_index_model_info. input_type ,
130
+ storeinput_type : store_input_type,
131
+ } ) ;
132
+ }
133
+
134
+ let metadata_value: MetadataValue = store_input. clone ( ) . into ( ) ;
119
135
let mut final_store_value: StdHashMap < MetadataKey , MetadataValue > =
120
136
store_value. clone ( ) . into_iter ( ) . collect ( ) ;
121
137
final_store_value. insert ( metadata_key. clone ( ) , metadata_value) ;
138
+
139
+ let store_key =
140
+ self . create_store_key ( store_input, & store. index_model , preprocess_action) ?;
122
141
return Ok ( ( store_key, final_store_value) ) ;
123
142
}
124
143
144
+ /// Converts storeinput into a tuple of storekey and storevalue.
145
+ /// Fails if the store input type does not match the store index_type
146
+ #[ tracing:: instrument( skip( self ) ) ]
147
+ pub ( crate ) fn create_store_key (
148
+ & self ,
149
+ store_input : StoreInput ,
150
+ index_store_model : & AIModel ,
151
+ preprocess_action : & PreprocessAction ,
152
+ ) -> Result < StoreKey , AIProxyError > {
153
+ // Process the inner value of a store input and convert it into a ndarray by passing
154
+ // it into index model. Create a storekey from ndarray
155
+ let processed_input =
156
+ self . preprocess_store_input ( preprocess_action, store_input, index_store_model) ?;
157
+ let store_key = index_store_model. model_ndarray ( & processed_input) ;
158
+ Ok ( store_key)
159
+ }
160
+
125
161
/// Converts (storekey, storevalue) into (storeinput, storevalue)
126
162
/// by removing the reserved_key from storevalue
127
163
#[ tracing:: instrument( skip( self ) ) ]
@@ -153,7 +189,7 @@ impl AIStoreHandler {
153
189
store_input : & StoreInput ,
154
190
) -> Result < StoreKey , AIProxyError > {
155
191
let store = self . get ( store_name) ?;
156
- Ok ( store. model . model_ndarray ( store_input) )
192
+ Ok ( store. index_model . model_ndarray ( store_input) )
157
193
}
158
194
159
195
/// Matches DROPSTORE - Drops a store if exist, else returns an error
@@ -185,20 +221,105 @@ impl AIStoreHandler {
185
221
self . stores . clear ( & guard) ;
186
222
store_length
187
223
}
224
+
225
+ #[ tracing:: instrument( skip( self ) ) ]
226
+ pub ( crate ) fn preprocess_store_input (
227
+ & self ,
228
+ process_action : & PreprocessAction ,
229
+ input : StoreInput ,
230
+ index_model : & AIModel ,
231
+ ) -> Result < StoreInput , AIProxyError > {
232
+ match ( process_action, input) {
233
+ ( PreprocessAction :: Image ( image_action) , StoreInput :: Image ( image_input) ) => {
234
+ // resize image and edit
235
+ let output = self . process_image ( image_input, index_model, image_action) ?;
236
+ Ok ( output)
237
+ }
238
+ ( PreprocessAction :: RawString ( string_action) , StoreInput :: RawString ( string_input) ) => {
239
+ let output =
240
+ self . preprocess_raw_string ( string_input, index_model, string_action) ?;
241
+ Ok ( output)
242
+ }
243
+ ( PreprocessAction :: RawString ( _) , StoreInput :: Image ( _) ) => {
244
+ Err ( AIProxyError :: PreprocessingMismatchError {
245
+ input_type : AIStoreInputType :: Image ,
246
+ preprocess_action : process_action. clone ( ) ,
247
+ } )
248
+ }
249
+
250
+ ( PreprocessAction :: Image ( _) , StoreInput :: RawString ( _) ) => {
251
+ Err ( AIProxyError :: PreprocessingMismatchError {
252
+ input_type : AIStoreInputType :: RawString ,
253
+ preprocess_action : process_action. clone ( ) ,
254
+ } )
255
+ }
256
+ }
257
+ }
258
+ fn preprocess_raw_string (
259
+ & self ,
260
+ input : String ,
261
+ index_model : & AIModel ,
262
+ string_action : & StringAction ,
263
+ ) -> Result < StoreInput , AIProxyError > {
264
+ // tokenize string, return error if max token
265
+ //let tokenized_input;
266
+ let model_embedding_dim = index_model. model_info ( ) . embedding_size ;
267
+ if input. len ( ) > model_embedding_dim. into ( ) {
268
+ if let StringAction :: ErrorIfTokensExceed = string_action {
269
+ return Err ( AIProxyError :: TokenExceededError {
270
+ input_token_size : input. len ( ) ,
271
+ model_embedding_size : model_embedding_dim. into ( ) ,
272
+ } ) ;
273
+ } else {
274
+ // truncate raw string
275
+ // let tokenized_input;
276
+ let _input = input. as_str ( ) [ ..model_embedding_dim. into ( ) ] . to_string ( ) ;
277
+ }
278
+ }
279
+ Ok ( StoreInput :: RawString ( input) )
280
+ }
281
+
282
+ fn process_image (
283
+ & self ,
284
+ input : Vec < u8 > ,
285
+ index_model : & AIModel ,
286
+ image_action : & ImageAction ,
287
+ ) -> Result < StoreInput , AIProxyError > {
288
+ // process image, return error if max dimensions exceeded
289
+ // let image_data;
290
+ let model_embedding_dim = index_model. embedding_size ( ) . into ( ) ;
291
+ if input. len ( ) > model_embedding_dim {
292
+ if let ImageAction :: ErrorIfDimensionsMismatch = image_action {
293
+ return Err ( AIProxyError :: ImageDimensionsMismatchError {
294
+ image_dimensions : input. len ( ) ,
295
+ max_dimensions : model_embedding_dim,
296
+ } ) ;
297
+ } else {
298
+ // resize image
299
+ }
300
+ }
301
+ Ok ( StoreInput :: Image ( input) )
302
+ }
188
303
}
189
304
190
305
#[ derive( Debug , Serialize , Deserialize ) ]
191
306
pub struct AIStore {
192
307
name : StoreName ,
193
308
/// Making use of a concurrent hashmap, we should be able to create an engine that manages stores
194
- model : AIModel ,
309
+ query_model : AIModel ,
310
+ index_model : AIModel ,
195
311
}
196
312
197
313
impl AIStore {
198
- pub ( super ) fn create ( store_name : StoreName , model : AIModel ) -> Self {
314
+ pub ( super ) fn create (
315
+ store_name : StoreName ,
316
+ query_model : AIModel ,
317
+ index_model : AIModel ,
318
+ ) -> Self {
199
319
Self {
200
320
name : store_name,
201
- model,
321
+ query_model,
322
+ index_model,
202
323
}
203
324
}
204
325
}
0 commit comments