2222
2323namespace App \Controller ;
2424
25- use App \Entity \Parameters \AbstractParameter ;
26- use App \Services \AI \AIPlatformRegistry ;
27- use App \Services \AI \AIPlatforms ;
28- use App \Settings \MiscSettings \IpnSuggestSettings ;
29- use Symfony \Component \Cache \Adapter \AdapterInterface ;
30- use Symfony \Component \HttpFoundation \Response ;
3125use App \Entity \Attachments \Attachment ;
32- use App \Entity \Parts \Category ;
33- use App \Entity \Parts \Footprint ;
26+ use App \Entity \Parameters \AbstractParameter ;
3427use App \Entity \Parameters \AttachmentTypeParameter ;
3528use App \Entity \Parameters \CategoryParameter ;
36- use App \Entity \Parameters \ProjectParameter ;
3729use App \Entity \Parameters \FootprintParameter ;
3830use App \Entity \Parameters \GroupParameter ;
3931use App \Entity \Parameters \ManufacturerParameter ;
4032use App \Entity \Parameters \MeasurementUnitParameter ;
4133use App \Entity \Parameters \PartParameter ;
34+ use App \Entity \Parameters \ProjectParameter ;
4235use App \Entity \Parameters \StorageLocationParameter ;
4336use App \Entity \Parameters \SupplierParameter ;
37+ use App \Entity \Parts \Category ;
38+ use App \Entity \Parts \Footprint ;
4439use App \Entity \Parts \Part ;
4540use App \Entity \PriceInformations \Currency ;
4641use App \Repository \ParameterRepository ;
42+ use App \Services \AI \AIPlatformRegistry ;
43+ use App \Services \AI \AIPlatforms ;
4744use App \Services \Attachments \AttachmentURLGenerator ;
4845use App \Services \Attachments \BuiltinAttachmentsFinder ;
4946use App \Services \Attachments \PartPreviewGenerator ;
5047use App \Services \Tools \TagFinder ;
48+ use App \Settings \MiscSettings \IpnSuggestSettings ;
5149use Doctrine \ORM \EntityManagerInterface ;
50+ use Symfony \AI \Platform \Capability ;
5251use Symfony \Bundle \FrameworkBundle \Controller \AbstractController ;
5352use Symfony \Component \Asset \Packages ;
5453use Symfony \Component \HttpFoundation \JsonResponse ;
5554use Symfony \Component \HttpFoundation \Request ;
55+ use Symfony \Component \HttpFoundation \Response ;
5656use Symfony \Component \Routing \Attribute \Route ;
5757use Symfony \Component \Serializer \Encoder \JsonEncoder ;
5858use Symfony \Component \Serializer \Normalizer \ObjectNormalizer ;
@@ -126,9 +126,12 @@ private function typeToParameterClass(string $type): string
126126 }
127127
128128 #[Route(path: '/parts/search/{query} ' , name: 'typeahead_parts ' )]
129- public function parts (EntityManagerInterface $ entityManager , PartPreviewGenerator $ previewGenerator ,
130- AttachmentURLGenerator $ attachmentURLGenerator , string $ query = "" ): JsonResponse
131- {
129+ public function parts (
130+ EntityManagerInterface $ entityManager ,
131+ PartPreviewGenerator $ previewGenerator ,
132+ AttachmentURLGenerator $ attachmentURLGenerator ,
133+ string $ query = ""
134+ ): JsonResponse {
132135 $ this ->denyAccessUnlessGranted ('@parts.read ' );
133136
134137 $ repo = $ entityManager ->getRepository (Part::class);
@@ -139,7 +142,7 @@ public function parts(EntityManagerInterface $entityManager, PartPreviewGenerato
139142 foreach ($ parts as $ part ) {
140143 //Determine the picture to show:
141144 $ preview_attachment = $ previewGenerator ->getTablePreviewAttachment ($ part );
142- if ($ preview_attachment instanceof Attachment) {
145+ if ($ preview_attachment instanceof Attachment) {
143146 $ preview_url = $ attachmentURLGenerator ->getThumbnailURL ($ preview_attachment , 'thumbnail_sm ' );
144147 } else {
145148 $ preview_url = '' ;
@@ -153,7 +156,7 @@ public function parts(EntityManagerInterface $entityManager, PartPreviewGenerato
153156 'footprint ' => $ part ->getFootprint () instanceof Footprint ? $ part ->getFootprint ()->getName () : '' ,
154157 'description ' => mb_strimwidth ($ part ->getDescription (), 0 , 127 , '... ' ),
155158 'image ' => $ preview_url ,
156- ];
159+ ];
157160 }
158161
159162 return new JsonResponse ($ data );
@@ -224,24 +227,35 @@ public function ipnSuggestions(
224227
225228
226229 $ partRepository = $ entityManager ->getRepository (Part::class);
227- $ ipnSuggestions = $ partRepository ->autoCompleteIpn ($ clonedPart , $ description , $ this ->ipnSuggestSettings ->suggestPartDigits );
230+ $ ipnSuggestions = $ partRepository ->autoCompleteIpn ($ clonedPart , $ description ,
231+ $ this ->ipnSuggestSettings ->suggestPartDigits );
228232
229233 return new JsonResponse ($ ipnSuggestions );
230234 }
231235
232236 #[Route(path: '/ai/{platform}/models ' , name: 'typeahead_ai_models ' , requirements: ['platform ' => '.+ ' ])]
233237 public function aiModels (
234238 AIPlatforms $ platform ,
239+ Request $ request ,
235240 AIPlatformRegistry $ platformRegistry ,
236241 CacheInterface $ cache ,
237242 ): JsonResponse {
238-
239243 $ this ->denyAccessUnlessGranted ('@config.change_system_settings ' );
240244
241- $ models = $ cache ->get ('ai_models_ ' .$ platform ->value , function (ItemInterface $ item ) use ($ platformRegistry , $ platform ) {
242- $ item ->expiresAfter (3600 ); //Cache for 1 hour
243- return $ platformRegistry ->getPlatform ($ platform )->getModelCatalog ()->getModels ();
244- });
245+ $ capability_filter = $ request ->query ->getEnum ('capability ' , Capability::class);
246+
247+ $ models = $ cache ->get ('ai_models_ ' .$ platform ->value .'_ ' .($ capability_filter ?->value ?? 'all ' ),
248+ function (ItemInterface $ item ) use ($ platformRegistry , $ platform , $ capability_filter ) {
249+ $ item ->expiresAfter (3600 ); //Cache for 1 hour
250+ if ($ capability_filter === null ) {
251+ return $ platformRegistry ->getPlatform ($ platform )->getModelCatalog ()->getModels ();
252+ }
253+
254+ //Otherwise filter the models by the capability
255+ return array_filter ($ platformRegistry ->getPlatform ($ platform )->getModelCatalog ()->getModels (),
256+ static fn (array $ model ) => in_array ($ capability_filter , $ model ['capabilities ' ] ?? [], true )
257+ );
258+ });
245259
246260 return new JsonResponse ($ models );
247261 }
0 commit comments