From a626a4ee371ad5247bb889cde35b8c91b3d09790 Mon Sep 17 00:00:00 2001 From: Ronald Hecker Date: Wed, 5 Mar 2025 08:42:32 +0100 Subject: [PATCH 01/10] Big refactor for project WIP The problem is that I need to change project.json I could do it ugly and just add npuEnabled as bool or null. However I want to do a clean up and a migration anyway. This commit lays the ground work: - Migrate to new project is either PublicProject or GetiProject - Add migration test for 1.0.0 to 25.0.1 Tests are broken as is. so WIP --- assets/manifest.json | 42 ++-- lib/deployment_processor.dart | 1 + lib/importers/geti_deployment.dart | 2 +- lib/importers/manifest_importer.dart | 114 +-------- lib/importers/model_manifest.dart | 87 +++++++ .../computer_vision/computer_vision.dart | 4 +- lib/pages/computer_vision/live_inference.dart | 2 +- .../widgets/model_properties.dart | 2 +- lib/pages/home/home.dart | 15 +- lib/pages/home/widgets/featured_card.dart | 8 +- lib/pages/import/huggingface.dart | 4 +- lib/pages/import/import.dart | 13 +- .../import/providers/import_provider.dart | 9 +- lib/pages/import/widgets/model_card.dart | 6 +- lib/pages/models/inference.dart | 2 +- lib/pages/models/widgets/model_card.dart | 5 +- lib/pages/models/widgets/model_property.dart | 3 +- lib/pages/text_to_image/playground.dart | 4 +- .../widgets/model_properties.dart | 87 ------- .../transcription/performance_metrics.dart | 2 +- lib/pages/transcription/playground.dart | 2 +- lib/pages/vlm/live_inference_pane.dart | 4 +- lib/pages/vlm/widgets/model_properties.dart | 87 ------- lib/project.dart | 154 +++++++------ lib/providers/image_inference_provider.dart | 2 +- lib/providers/project_filter_provider.dart | 18 +- lib/public_model_info.dart | 65 ------ lib/public_models.dart | 21 +- lib/utils/image_graph_builder.dart | 2 +- lib/widgets/model_properties.dart | 69 ++++++ test/migration_test.dart | 217 ++++++++++++++++++ 31 files changed, 553 insertions(+), 500 deletions(-) create mode 100644 lib/importers/model_manifest.dart delete mode 100644 lib/pages/text_to_image/widgets/model_properties.dart delete mode 100644 lib/pages/vlm/widgets/model_properties.dart create mode 100644 lib/widgets/model_properties.dart create mode 100644 test/migration_test.dart diff --git a/assets/manifest.json b/assets/manifest.json index a6bfe172..bb36ea1e 100644 --- a/assets/manifest.json +++ b/assets/manifest.json @@ -31,7 +31,8 @@ "description": "We make it easy to connect with people: Use Whisper to transcribe videos", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "LCM Dreamshaper V7", @@ -55,7 +56,8 @@ "description": "Transcribe video with Whisper Large V3", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Large V3", @@ -66,7 +68,8 @@ "description": "Transcribe video with Whisper Large V3", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Openai Whisper Large V3", @@ -77,7 +80,8 @@ "description": "Transcribe video with Openai Whisper Large V3", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Tiny", @@ -88,7 +92,8 @@ "description": "Transcribe video with Whisper Tiny", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Base", @@ -99,7 +104,8 @@ "description": "Transcribe video with Whisper Base", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Medium", @@ -110,7 +116,8 @@ "description": "Transcribe video with Whisper Medium", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Medium", @@ -121,7 +128,8 @@ "description": "Transcribe video with Whisper Medium", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Tiny", @@ -132,7 +140,8 @@ "description": "Transcribe video with Whisper Tiny", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Base", @@ -143,7 +152,8 @@ "description": "Transcribe video with Whisper Base", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Large V3", @@ -154,7 +164,8 @@ "description": "Transcribe video with Whisper Large V3", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Medium", @@ -165,7 +176,8 @@ "description": "Transcribe video with Whisper Medium", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Tiny", @@ -176,7 +188,8 @@ "description": "Transcribe video with Whisper Tiny", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "Whisper Base", @@ -187,7 +200,8 @@ "description": "We make it easy to connect with people: Use Whisper to transcribe videos", "task": "speech", "author": "OpenVINO", - "collection": "speech-to-text-672321d5c070537a178a8aeb" + "collection": "speech-to-text-672321d5c070537a178a8aeb", + "npuEnabled": true }, { "name": "InternVL2 1B", diff --git a/lib/deployment_processor.dart b/lib/deployment_processor.dart index 2ea05420..09374845 100644 --- a/lib/deployment_processor.dart +++ b/lib/deployment_processor.dart @@ -40,6 +40,7 @@ Future> loadProjectsFromStorage() async { try { final content = File(platformContext.join(projectFolder.path, "project.json")).readAsStringSync(); final project = Project.fromJson(jsonDecode(content), projectFolder.path); + print(project.id); //if (!project.verify()) { // throw Exception("project not valid. removing"); //} diff --git a/lib/importers/geti_deployment.dart b/lib/importers/geti_deployment.dart index f15d5ad9..a3b7ae73 100644 --- a/lib/importers/geti_deployment.dart +++ b/lib/importers/geti_deployment.dart @@ -32,7 +32,7 @@ final platformContext = Context(style: Style.platform); class GetiDeploymentProcessor extends Importer { final String zipPath; Archive archive; - Project? project; + GetiProject? project; GetiDeploymentProcessor(this.zipPath, this.archive); diff --git a/lib/importers/manifest_importer.dart b/lib/importers/manifest_importer.dart index ea8e7914..3ce0956f 100644 --- a/lib/importers/manifest_importer.dart +++ b/lib/importers/manifest_importer.dart @@ -3,114 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 import 'dart:convert'; -import 'dart:io'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; -import 'package:inference/project.dart'; -import 'package:inference/public_model_info.dart'; -import 'package:inference/utils/get_public_thumbnail.dart'; -import 'package:inference/utils.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:uuid/uuid.dart'; - -class Model { - final String name; - final String id; - final int fileSize; - final String optimizationPrecision; - final int contextWindow; - final String description; - final String task; - - Model({ - required this.name, - required this.id, - required this.fileSize, - required this.optimizationPrecision, - required this.contextWindow, - required this.description, - required this.task, - }); - - Image get thumbnail { - return getThumbnail(id); - } - - String get kind { - if (task == 'text-generation'){ - return 'llm'; - } else if (task == 'speech'){ - return 'speech to text'; - } else if (task == 'text-to-image'){ - return 'image generation'; - } - return 'other'; - } - - String get readableFileSize { - return fileSize.toDouble().readableFileSize(); - } - - factory Model.fromJson(Map json) { - return Model( - name: json['name'], - id: json['id'], - fileSize: json['fileSize'], - optimizationPrecision: json['optimizationPrecision'], - contextWindow: json['contextWindow'], - description: json['description'], - task: json['task'], - ); - } - - Future convertToProject() async { - final directory = await getApplicationSupportDirectory(); - final projectId = const Uuid().v4(); - final storagePath = platformContext.join(directory.path, projectId.toString()); - await Directory(storagePath).create(recursive: true); - final projectType = parseProjectType(task); - - final project = PublicProject( - projectId, - "OpenVINO/$id", - "1.0.0", - name, - DateTime.now().toIso8601String(), - projectType, - storagePath, - thumbnail, - PublicModelInfo( - id, - DateTime.now().toIso8601String(), - 0, - 0, - task, - const Collection("https://huggingface.co/api/collections/OpenVINO/llm-6687aaa2abca3bbcec71a9bd", "", "text"), - ), - ); - - project.tasks.add( - Task( - genUUID(), - task, - task, - [], - null, - [], - "", - "", - ), - ); - - return project; - } -} +import 'package:inference/importers/model_manifest.dart'; class ManifestImporter { final String manifestPath; - List popularModels = []; - List allModels = []; + List popularModels = []; + List allModels = []; ManifestImporter(this.manifestPath); @@ -119,19 +19,19 @@ class ManifestImporter { final jsonData = jsonDecode(contents); popularModels = (jsonData['popular_models'] as List) - .map((modelJson) => Model.fromJson(modelJson)) + .map((modelJson) => ModelManifest.fromJson(modelJson)) .toList(); allModels = (jsonData['all_models'] as List) - .map((modelJson) => Model.fromJson(modelJson)) + .map((modelJson) => ModelManifest.fromJson(modelJson)) .toList(); } - List getPopularModels() { + List getPopularModels() { return popularModels; } - List getAllModels() { + List getAllModels() { return allModels; } } diff --git a/lib/importers/model_manifest.dart b/lib/importers/model_manifest.dart new file mode 100644 index 00000000..e60ff678 --- /dev/null +++ b/lib/importers/model_manifest.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2024 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/widgets.dart'; +import 'package:inference/utils.dart'; +import 'package:inference/utils/get_public_thumbnail.dart'; + +class ModelManifest { + final String name; + final String id; + final int fileSize; + final String optimizationPrecision; + final int contextWindow; + final String collection; + final String description; + final String task; + final String author; + final bool npuEnabled; + String? architecture; + + ModelManifest({ + required this.name, + required this.id, + required this.fileSize, + required this.optimizationPrecision, + required this.contextWindow, + required this.collection, + required this.description, + required this.task, + required this.author, + required this.npuEnabled, + this.architecture, + }); + + String get kind { + if (task == 'text-generation'){ + return 'llm'; + } else if (task == 'speech'){ + return 'speech to text'; + } else if (task == 'text-to-image'){ + return 'image generation'; + } + return 'other'; + } + + String get readableFileSize { + return fileSize.toDouble().readableFileSize(); + } + + factory ModelManifest.fromJson(Map json) { + return ModelManifest( + name: json['name'], + id: json['id'], + fileSize: json['fileSize'], + optimizationPrecision: json['optimizationPrecision'], + collection: json['collection'], + contextWindow: json['contextWindow'], + description: json['description'], + task: json['task'], + author: json['author'], + architecture: json['architecture'] ?? "unknown", + npuEnabled: json['npuEnabled'] ?? false, + ); + } + + Map toJson() { + return { + "name": name, + "id": id, + "fileSize": fileSize, + "optimizationPrecision": optimizationPrecision, + "contextWindow": contextWindow, + "description": description, + "collection": collection, + "task": task, + "author": author, + "architecture": architecture, + "npuEnabled": npuEnabled + }; + } + + Image get thumbnail { + return getThumbnail(id); + } + +} diff --git a/lib/pages/computer_vision/computer_vision.dart b/lib/pages/computer_vision/computer_vision.dart index 969307e8..9085209d 100644 --- a/lib/pages/computer_vision/computer_vision.dart +++ b/lib/pages/computer_vision/computer_vision.dart @@ -13,7 +13,7 @@ import 'package:inference/widgets/controls/close_model_button.dart'; import 'package:provider/provider.dart'; class ComputerVisionPage extends StatefulWidget { - final Project project; + final GetiProject project; const ComputerVisionPage(this.project, {super.key}); @override @@ -93,7 +93,7 @@ class _ComputerVisionPageState extends State { PaneItem( icon: const Icon(FluentIcons.processing), title: const Text("Live Inference"), - body: LiveInference(project: widget.project), + body: LiveInference(project: widget.project as GetiProject), ), PaneItem( icon: const Icon(FluentIcons.project_collection), diff --git a/lib/pages/computer_vision/live_inference.dart b/lib/pages/computer_vision/live_inference.dart index 2e557e92..ccadde1c 100644 --- a/lib/pages/computer_vision/live_inference.dart +++ b/lib/pages/computer_vision/live_inference.dart @@ -28,7 +28,7 @@ import 'dart:ui' as ui; enum LiveInferenceMode { camera, image } class LiveInference extends StatefulWidget { - final Project project; + final GetiProject project; const LiveInference({required this.project, super.key}); diff --git a/lib/pages/computer_vision/widgets/model_properties.dart b/lib/pages/computer_vision/widgets/model_properties.dart index 4ee57915..04b8e1d2 100644 --- a/lib/pages/computer_vision/widgets/model_properties.dart +++ b/lib/pages/computer_vision/widgets/model_properties.dart @@ -10,7 +10,7 @@ import 'package:intl/intl.dart'; import 'package:inference/utils.dart'; class ModelProperties extends StatelessWidget { - final Project project; + final GetiProject project; const ModelProperties({super.key, required this.project}); @override diff --git a/lib/pages/home/home.dart b/lib/pages/home/home.dart index 878b5ba1..47afd5fd 100644 --- a/lib/pages/home/home.dart +++ b/lib/pages/home/home.dart @@ -5,6 +5,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; +import 'package:inference/importers/model_manifest.dart'; import 'package:inference/pages/home/widgets/featured_card.dart'; import 'package:inference/pages/models/widgets/model_card.dart'; import 'package:inference/importers/manifest_importer.dart'; @@ -23,7 +24,7 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State { - late Future> popularModelsFuture; + late Future> popularModelsFuture; bool orderAscend = false; Map projectModelMap = {}; // Map to hold modelId and a corresponding project @@ -41,24 +42,24 @@ class _HomePageState extends State { }; } - Project? getProjectWithModel(Model model) { + Project? getProjectWithModel(ModelManifest model) { // Retrieve a project given the modelId return projectModelMap[model.id] ?? projectModelMap["OpenVINO/${model.id}"]; } - bool projectExistsWithModel(Model model){ + bool projectExistsWithModel(ModelManifest model){ return getProjectWithModel(model) != null; } - void downloadFeaturedModel(Model model){ - model.convertToProject().then((project) { + void downloadFeaturedModel(ModelManifest model){ + PublicProject.fromModelManifest(model).then((project) { if (mounted) { GoRouter.of(context).push('/models/download', extra: project); } }); } - void openFeaturedModel(Model model){ + void openFeaturedModel(ModelManifest model){ var project = getProjectWithModel(model); if (project != null){ GoRouter.of(context).push("/models/inference", extra: project); @@ -105,7 +106,7 @@ class _HomePageState extends State { ], ), ), - FutureBuilder>( + FutureBuilder>( future: popularModelsFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { diff --git a/lib/pages/home/widgets/featured_card.dart b/lib/pages/home/widgets/featured_card.dart index 3b8d02fd..e8d35a93 100644 --- a/lib/pages/home/widgets/featured_card.dart +++ b/lib/pages/home/widgets/featured_card.dart @@ -3,13 +3,13 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/importers/manifest_importer.dart'; +import 'package:inference/importers/model_manifest.dart'; import 'package:inference/widgets/elevation.dart'; class FeaturedCard extends StatelessWidget { - final Model model; - final void Function(Model) onDownload; - final void Function(Model) onOpen; + final ModelManifest model; + final void Function(ModelManifest) onDownload; + final void Function(ModelManifest) onOpen; final bool downloaded; const FeaturedCard( diff --git a/lib/pages/import/huggingface.dart b/lib/pages/import/huggingface.dart index 5cddaa01..11b981da 100644 --- a/lib/pages/import/huggingface.dart +++ b/lib/pages/import/huggingface.dart @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/importers/manifest_importer.dart'; +import 'package:inference/importers/model_manifest.dart'; import 'package:inference/pages/import/providers/import_provider.dart'; import 'package:inference/pages/import/widgets/badge.dart'; import 'package:inference/pages/import/widgets/model_card.dart'; @@ -125,7 +125,7 @@ class Huggingface extends StatelessWidget { ), Expanded( child: SingleChildScrollView( - child: FutureBuilder>( + child: FutureBuilder>( future: importProvider.allModelsFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { diff --git a/lib/pages/import/import.dart b/lib/pages/import/import.dart index 53feb7c8..4a259ae5 100644 --- a/lib/pages/import/import.dart +++ b/lib/pages/import/import.dart @@ -8,6 +8,7 @@ import 'package:go_router/go_router.dart'; import 'package:inference/pages/import/huggingface.dart'; import 'package:inference/pages/import/providers/import_provider.dart'; import 'package:inference/pages/import/widgets/import_geti_model_dialog.dart'; +import 'package:inference/project.dart'; import 'package:inference/providers/project_filter_provider.dart'; import 'package:inference/theme_fluent.dart'; import 'package:inference/widgets/controls/close_model_button.dart'; @@ -96,11 +97,13 @@ class _ImportPageState extends State { onPressed: (importProvider.selectedModel == null ? null : () { - importProvider.selectedModel?.convertToProject().then((project) { - if (context.mounted){ - GoRouter.of(context).push('/models/download', extra: project); - } - }); + if (importProvider.selectedModel != null) { + PublicProject.fromModelManifest(importProvider.selectedModel!).then((project) { + if (context.mounted){ + GoRouter.of(context).push('/models/download', extra: project); + } + }); + } } ), child: const Text("Import selected model"), diff --git a/lib/pages/import/providers/import_provider.dart b/lib/pages/import/providers/import_provider.dart index a45efd96..9bea9ca9 100644 --- a/lib/pages/import/providers/import_provider.dart +++ b/lib/pages/import/providers/import_provider.dart @@ -4,12 +4,13 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:inference/importers/manifest_importer.dart'; +import 'package:inference/importers/model_manifest.dart'; class ImportProvider extends ChangeNotifier { - Future>? allModelsFuture; - Model? _selectedModel; - Model? get selectedModel => _selectedModel; - set selectedModel(Model? model) { + Future>? allModelsFuture; + ModelManifest? _selectedModel; + ModelManifest? get selectedModel => _selectedModel; + set selectedModel(ModelManifest? model) { _selectedModel = model; notifyListeners(); } diff --git a/lib/pages/import/widgets/model_card.dart b/lib/pages/import/widgets/model_card.dart index 3a913f1d..2e7acb5e 100644 --- a/lib/pages/import/widgets/model_card.dart +++ b/lib/pages/import/widgets/model_card.dart @@ -3,12 +3,12 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/importers/manifest_importer.dart'; +import 'package:inference/importers/model_manifest.dart'; import 'package:inference/pages/models/widgets/model_property.dart'; import 'package:inference/widgets/elevation.dart'; class ModelCard extends StatelessWidget { - final Model model; + final ModelManifest model; final bool checked; final ValueChanged onChecked; @@ -88,6 +88,8 @@ class ModelCard extends StatelessWidget { ModelProperty(name: "Optimization", value: model.optimizationPrecision), ModelProperty(name: "Size", value: model.readableFileSize), ModelProperty(name: "Task", value: model.task), + if (model.npuEnabled) + const ModelProperty(name: "", value: "NPU"), ], ), ), diff --git a/lib/pages/models/inference.dart b/lib/pages/models/inference.dart index 00859504..246988a0 100644 --- a/lib/pages/models/inference.dart +++ b/lib/pages/models/inference.dart @@ -18,7 +18,7 @@ class InferencePage extends StatelessWidget { Widget build(BuildContext context) { switch(project.type){ case ProjectType.image: - return ComputerVisionPage(project); + return ComputerVisionPage(project as GetiProject); case ProjectType.text: return TextGenerationPage(project); case ProjectType.speech: diff --git a/lib/pages/models/widgets/model_card.dart b/lib/pages/models/widgets/model_card.dart index a81a7bad..c7472633 100644 --- a/lib/pages/models/widgets/model_card.dart +++ b/lib/pages/models/widgets/model_card.dart @@ -128,12 +128,13 @@ class _ModelCardState extends State{ ModelProperty(name: "Size", value: widget.project.size?.readableFileSize() ?? ""), Builder( builder: (context) { - if (widget.project is GetiProject && widget.project.tasks.first.performance != null) { + final project = widget.project; + if (project is GetiProject && project.tasks.first.performance != null) { Locale locale = Localizations.localeOf(context); final formatter = NumberFormat.percentPattern(locale.languageCode); return ModelProperty( name: "Accuracy", - value: formatter.format(widget.project.tasks.first.performance!.score)); + value: formatter.format(project.tasks.first.performance!.score)); } return Container(); } diff --git a/lib/pages/models/widgets/model_property.dart b/lib/pages/models/widgets/model_property.dart index f771f095..626213eb 100644 --- a/lib/pages/models/widgets/model_property.dart +++ b/lib/pages/models/widgets/model_property.dart @@ -37,7 +37,8 @@ class ModelProperty extends StatelessWidget { text: TextSpan( style: DefaultTextStyle.of(context).style.apply(fontSizeDelta: -2), children: [ - TextSpan(text: "$name: "), + if (name.isNotEmpty) + TextSpan(text: "$name: "), TextSpan(text: value, style: const TextStyle(fontWeight: FontWeight.w500)), ], ), diff --git a/lib/pages/text_to_image/playground.dart b/lib/pages/text_to_image/playground.dart index 7564f0c1..f81ad45a 100644 --- a/lib/pages/text_to_image/playground.dart +++ b/lib/pages/text_to_image/playground.dart @@ -8,7 +8,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter/services.dart'; import 'package:inference/pages/text_to_image/widgets/assistant_message.dart'; import 'package:inference/pages/text_to_image/widgets/user_message.dart'; -import 'package:inference/pages/text_to_image/widgets/model_properties.dart'; +import 'package:inference/widgets/model_properties.dart'; import 'package:inference/widgets/grid_container.dart'; import 'package:inference/project.dart'; import 'package:inference/providers/text_to_image_inference_provider.dart'; @@ -290,7 +290,7 @@ class _TTIPlaygroundState extends State { )), ], ))), - const ModelProperties(), + ModelProperties(project: widget.project), ], ); } diff --git a/lib/pages/text_to_image/widgets/model_properties.dart b/lib/pages/text_to_image/widgets/model_properties.dart deleted file mode 100644 index 93fa7757..00000000 --- a/lib/pages/text_to_image/widgets/model_properties.dart +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2024 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 - -import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/providers/text_to_image_inference_provider.dart'; -import 'package:inference/utils.dart'; -import 'package:inference/widgets/grid_container.dart'; -import 'package:inference/widgets/horizontal_rule.dart'; -import 'package:inference/widgets/model_propery.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class ModelProperties extends StatelessWidget { - const ModelProperties({super.key}); - - @override - Widget build(BuildContext context) { - return Consumer(builder: (context, inference, child) { - Locale locale = Localizations.localeOf(context); - final formatter = NumberFormat.percentPattern(locale.languageCode); - - return SizedBox( - width: 280, - child: GridContainer( - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text("Model parameters", style: TextStyle( - fontSize: 20, - )), - Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ModelProperty( - title: "Model name", - value: inference.project!.name, - ), - ModelProperty( - title: "Task", - value: inference.project!.taskName(), - ), - ModelProperty( - title: "Architecture", - value: inference.project!.architecture, - ), - ModelProperty( - title: "Size", - value: inference.project!.size?.readableFileSize() ?? "", - ), - Builder( - builder: (context) { - if (inference.project!.tasks.first.performance == null) { - return Container(); - } - return ModelProperty( - title: "Accuracy", - value: formatter.format(inference.project!.tasks.first.performance!.score) - ); - } - ), - if (inference.project!.isPublic) Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const HorizontalRule(), - const Text('External links', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), - HyperlinkButton( - child: const Text("Model on Hugging Face"), onPressed: () { launchUrl(Uri.parse('https://huggingface.co/${inference.project!.modelId}')); } - ), - ], - ), - ], - ), - ) - ], - ) - ), - ); - } - ); - } -} - diff --git a/lib/pages/transcription/performance_metrics.dart b/lib/pages/transcription/performance_metrics.dart index 81f031e1..da0bfcc1 100644 --- a/lib/pages/transcription/performance_metrics.dart +++ b/lib/pages/transcription/performance_metrics.dart @@ -4,7 +4,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:inference/widgets/horizontal_rule.dart'; -import 'package:inference/pages/computer_vision/widgets/model_properties.dart'; +import 'package:inference/widgets/model_properties.dart'; import 'package:inference/widgets/grid_container.dart'; import 'package:inference/pages/transcription/providers/speech_inference_provider.dart'; import 'package:inference/project.dart'; diff --git a/lib/pages/transcription/playground.dart b/lib/pages/transcription/playground.dart index d292d09c..ca21b755 100644 --- a/lib/pages/transcription/playground.dart +++ b/lib/pages/transcription/playground.dart @@ -6,7 +6,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/pages/computer_vision/widgets/model_properties.dart'; +import 'package:inference/widgets/model_properties.dart'; import 'package:inference/pages/transcription/utils/media_player_controller.dart'; import 'package:inference/widgets/grid_container.dart'; import 'package:inference/pages/transcription/widgets/language_selector.dart'; diff --git a/lib/pages/vlm/live_inference_pane.dart b/lib/pages/vlm/live_inference_pane.dart index c1fbdac6..fd3eaf27 100644 --- a/lib/pages/vlm/live_inference_pane.dart +++ b/lib/pages/vlm/live_inference_pane.dart @@ -8,7 +8,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter/services.dart'; import 'package:inference/pages/vlm/widgets/assistant_message.dart'; import 'package:inference/pages/vlm/widgets/image_grid.dart'; -import 'package:inference/pages/vlm/widgets/model_properties.dart'; +import 'package:inference/widgets/model_properties.dart'; import 'package:inference/widgets/toolbar_text_input.dart'; import 'package:inference/pages/vlm/widgets/user_message.dart'; import 'package:inference/project.dart'; @@ -292,7 +292,7 @@ class _VLMPlaygroundState extends State { )), ], ))), - const ModelProperties(), + ModelProperties(project: widget.project), ], ); } diff --git a/lib/pages/vlm/widgets/model_properties.dart b/lib/pages/vlm/widgets/model_properties.dart deleted file mode 100644 index 275fb11b..00000000 --- a/lib/pages/vlm/widgets/model_properties.dart +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2024 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 - -import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/providers/vlm_inference_provider.dart'; -import 'package:inference/utils.dart'; -import 'package:inference/widgets/grid_container.dart'; -import 'package:inference/widgets/horizontal_rule.dart'; -import 'package:inference/widgets/model_propery.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class ModelProperties extends StatelessWidget { - const ModelProperties({super.key}); - - @override - Widget build(BuildContext context) { - return Consumer(builder: (context, inference, child) { - Locale locale = Localizations.localeOf(context); - final formatter = NumberFormat.percentPattern(locale.languageCode); - - return SizedBox( - width: 280, - child: GridContainer( - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text("Model parameters", style: TextStyle( - fontSize: 20, - )), - Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ModelProperty( - title: "Model name", - value: inference.project!.name, - ), - ModelProperty( - title: "Task", - value: inference.project!.taskName(), - ), - ModelProperty( - title: "Architecture", - value: inference.project!.architecture, - ), - ModelProperty( - title: "Size", - value: inference.project!.size?.readableFileSize() ?? "", - ), - Builder( - builder: (context) { - if (inference.project!.tasks.first.performance == null) { - return Container(); - } - return ModelProperty( - title: "Accuracy", - value: formatter.format(inference.project!.tasks.first.performance!.score) - ); - } - ), - if (inference.project!.isPublic) Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const HorizontalRule(), - const Text('External links', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), - HyperlinkButton( - child: const Text("Model on Hugging Face"), onPressed: () { launchUrl(Uri.parse('https://huggingface.co/${inference.project!.modelId}')); } - ), - ], - ), - ], - ), - ) - ], - ) - ), - ); - } - ); - } -} - diff --git a/lib/project.dart b/lib/project.dart index 09e124ba..09fc87c6 100644 --- a/lib/project.dart +++ b/lib/project.dart @@ -6,18 +6,18 @@ import 'dart:async'; import 'dart:io'; import 'package:fluent_ui/fluent_ui.dart'; -import 'package:inference/public_model_info.dart'; +import 'package:inference/importers/model_manifest.dart'; import 'package:inference/utils/get_public_thumbnail.dart'; import 'package:path/path.dart'; import 'package:collection/collection.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:uuid/uuid.dart'; const uuid = Uuid(); String genUUID() => uuid.v4().toString(); final platformContext = Context(style: Style.platform); -const currentApplicationVersion = "1.0.0"; - +const currentApplicationVersion = "25.0.1"; class Score { double score = 0.0; @@ -54,10 +54,8 @@ class Label { "is_empty": isEmpty }; } - } - class Task { String id; String name; @@ -157,7 +155,6 @@ class Project { String creationTime; ProjectType type; String storagePath; - List tasks = []; Completer loaded = Completer(); bool isPublic; bool hasSample = false; @@ -165,30 +162,16 @@ class Project { int? size; String get architecture { - if (tasks.length > 1) { - return "Task Chain"; - } - return tasks.first.architecture; + //if (tasks.length > 1) { + // return "Task Chain"; + //} + //return tasks.first.architecture; + return ""; } - List