3939class OpenAiAPIService {
4040 private IClient $ client ;
4141 private ?array $ modelsMemoryCache = null ;
42- private ?bool $ areCredsValid = null ;
4342
4443 public function __construct (
4544 private LoggerInterface $ logger ,
@@ -111,68 +110,80 @@ private function isModelListValid($models): bool {
111110
112111 /**
113112 * @param ?string $userId
113+ * @param bool $refresh
114114 * @return array|string[]
115115 * @throws Exception
116116 */
117- public function getModels (?string $ userId ): array {
118- // caching against 'getModelEnumValues' calls from all the providers
119- if ($ this ->areCredsValid === false ) {
120- $ this ->logger ->info ('Cannot get OpenAI models without an API key ' );
121- return [];
122- } elseif ($ this ->areCredsValid === null ) {
123- if ($ this ->isUsingOpenAi () && $ this ->openAiSettingsService ->getUserApiKey ($ userId , true ) === '' ) {
124- $ this ->areCredsValid = false ;
125- $ this ->logger ->info ('Cannot get OpenAI models without an API key ' );
126- return [];
127- }
128- $ this ->areCredsValid = true ;
129- }
130-
131- if ($ this ->modelsMemoryCache !== null ) {
132- $ this ->logger ->debug ('Getting OpenAI models from the memory cache ' );
133- return $ this ->modelsMemoryCache ;
134- }
135-
117+ public function getModels (?string $ userId , bool $ refresh = false ): array {
118+ $ cache = $ this ->cacheFactory ->createDistributed (Application::APP_ID );
136119 $ userCacheKey = Application::MODELS_CACHE_KEY . '_ ' . ($ userId ?? '' );
137120 $ adminCacheKey = Application::MODELS_CACHE_KEY . '-main ' ;
138- $ cache = $ this ->cacheFactory ->createDistributed (Application::APP_ID );
139121
140- // try to get models from the user cache first
141- if ($ userId !== null ) {
142- $ userCachedModels = $ cache ->get ($ userCacheKey );
143- if ($ userCachedModels ) {
144- $ this ->logger ->debug ('Getting OpenAI models from user cache for user ' . $ userId );
145- return $ userCachedModels ;
122+ if (!$ refresh ) {
123+ if ($ this ->modelsMemoryCache !== null ) {
124+ $ this ->logger ->debug ('Getting OpenAI models from the memory cache ' );
125+ return $ this ->modelsMemoryCache ;
146126 }
147- }
148127
149- // if the user has an API key or uses basic auth, skip the admin cache
150- if (!(
151- $ this ->openAiSettingsService ->getUserApiKey ($ userId , false ) !== ''
152- || (
153- $ this ->openAiSettingsService ->getUseBasicAuth ()
154- && $ this ->openAiSettingsService ->getUserBasicUser ($ userId ) !== ''
155- && $ this ->openAiSettingsService ->getUserBasicPassword ($ userId ) !== ''
156- )
157- )) {
158- // if no user cache or userId is null, try to get from the admin cache
159- if ($ adminCachedModels = $ cache ->get ($ adminCacheKey )) {
160- $ this ->logger ->debug ('Getting OpenAI models from the main distributed cache ' );
161- return $ adminCachedModels ;
128+ // try to get models from the user cache first
129+ if ($ userId !== null ) {
130+ $ userCachedModels = $ cache ->get ($ userCacheKey );
131+ if ($ userCachedModels ) {
132+ $ this ->logger ->debug ('Getting OpenAI models from user cache for user ' . $ userId );
133+ $ this ->modelsMemoryCache = $ userCachedModels ;
134+ return $ userCachedModels ;
135+ }
162136 }
137+
138+ // if the user has an API key or uses basic auth, skip the admin cache
139+ if ($ userId === null || (
140+ $ this ->openAiSettingsService ->getUserApiKey ($ userId , false ) === ''
141+ && (
142+ !$ this ->openAiSettingsService ->getUseBasicAuth ()
143+ || $ this ->openAiSettingsService ->getUserBasicUser ($ userId ) === ''
144+ || $ this ->openAiSettingsService ->getUserBasicPassword ($ userId ) === ''
145+ )
146+ )) {
147+ // here we know there is either no user cache or userId is null
148+ // so if there is no user-defined service credentials
149+ // we try to get the models from the admin cache
150+ if ($ adminCachedModels = $ cache ->get ($ adminCacheKey )) {
151+ $ this ->logger ->debug ('Getting OpenAI models from the main distributed cache ' );
152+ $ this ->modelsMemoryCache = $ adminCachedModels ;
153+ return $ adminCachedModels ;
154+ }
155+ }
156+
157+ // if we don't need to refresh to model list and it's not been found in the cache, it is obtained from the DB
158+ $ modelsObjectString = $ this ->appConfig ->getValueString (Application::APP_ID , 'models ' , '{"data":[],"object":"list"} ' );
159+ $ fallbackModels = [
160+ 'data ' => [],
161+ 'object ' => 'list ' ,
162+ ];
163+ try {
164+ $ newCache = json_decode ($ modelsObjectString , true ) ?? $ fallbackModels ;
165+ } catch (Throwable $ e ) {
166+ $ this ->logger ->warning ('Could not decode the model JSON string ' , ['model_string ' , $ modelsObjectString , 'exception ' => $ e ]);
167+ $ newCache = $ fallbackModels ;
168+ }
169+ $ cache ->set ($ userId !== null ? $ userCacheKey : $ adminCacheKey , $ newCache , Application::MODELS_CACHE_TTL );
170+ $ this ->modelsMemoryCache = $ newCache ;
171+ return $ newCache ;
163172 }
164173
174+ // we know we are refreshing so we clear the caches and make the network request
175+ $ cache ->remove ($ adminCacheKey );
176+ $ cache ->remove ($ userCacheKey );
177+
165178 try {
166179 $ this ->logger ->debug ('Actually getting OpenAI models with a network request ' );
167180 $ modelsResponse = $ this ->request ($ userId , 'models ' );
168181 } catch (Exception $ e ) {
169182 $ this ->logger ->warning ('Error retrieving models (exc): ' . $ e ->getMessage ());
170- $ this ->areCredsValid = false ;
171183 throw $ e ;
172184 }
173185 if (isset ($ modelsResponse ['error ' ])) {
174186 $ this ->logger ->warning ('Error retrieving models: ' . json_encode ($ modelsResponse ));
175- $ this ->areCredsValid = false ;
176187 throw new Exception ($ modelsResponse ['error ' ], Http::STATUS_INTERNAL_SERVER_ERROR );
177188 }
178189 if (!isset ($ modelsResponse ['data ' ])) {
@@ -182,13 +193,14 @@ public function getModels(?string $userId): array {
182193
183194 if (!$ this ->isModelListValid ($ modelsResponse ['data ' ])) {
184195 $ this ->logger ->warning ('Invalid models response: ' . json_encode ($ modelsResponse ));
185- $ this ->areCredsValid = false ;
186196 throw new Exception ($ this ->l10n ->t ('Invalid models response received ' ), Http::STATUS_INTERNAL_SERVER_ERROR );
187197 }
188198
189199 $ cache ->set ($ userId !== null ? $ userCacheKey : $ adminCacheKey , $ modelsResponse , Application::MODELS_CACHE_TTL );
190200 $ this ->modelsMemoryCache = $ modelsResponse ;
191- $ this ->areCredsValid = true ;
201+ // we always store the model list after getting it
202+ $ modelsObjectString = json_encode ($ modelsResponse );
203+ $ this ->appConfig ->setValueString (Application::APP_ID , 'models ' , $ modelsObjectString );
192204 return $ modelsResponse ;
193205 }
194206
0 commit comments