File size: 3,220 Bytes
233cefb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ad7fb07
 
 
233cefb
 
ad7fb07
 
 
233cefb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import 'package:flutter/services.dart';
import 'package:yaml/yaml.dart';

/// Represents a curated LLM model with metadata
class CuratedModel {
  final String modelId;
  final String displayName;
  final String numOfParameters;

  const CuratedModel({
    required this.modelId,
    required this.displayName,
    required this.numOfParameters,
  });

  /// Get speed category based on parameter count
  String get speedCategory {
    final paramValue = _parseParameters(numOfParameters);
    
    if (paramValue <= 1) return 'Fastest';
    if (paramValue <= 2) return 'Faster';
    if (paramValue <= 4) return 'Fast';
    if (paramValue < 8) return 'Normal';
    if (paramValue < 17) return 'Slow';
    if (paramValue < 32) return 'Slower';
    return 'Slowest';
  }

  /// Get speed emoji for visual representation
  String get speedEmoji {
    switch (speedCategory) {
      case 'Fastest':
        return 'πŸš€';
      case 'Faster':
        return '⚑';
      case 'Fast':
        return 'πŸƒ';
      case 'Normal':
        return '🚢';
      case 'Slow':
        return '🐌';
      case 'Slower':
        return '🐒';
      case 'Slowest':
        return 'πŸ¦₯';
      default:
        return '❓';
    }
  }

  /// Parse parameter string to numeric value (in billions)
  double _parseParameters(String params) {
    final numStr = params.replaceAll('B', '').trim();
    return double.tryParse(numStr) ?? 0.0;
  }

  /// Create from YAML map
  factory CuratedModel.fromYaml(YamlMap yaml) {
    return CuratedModel(
      modelId: yaml['model_id'] as String,
      displayName: yaml['display_name'] as String,
      numOfParameters: yaml['num_of_parameters'] as String,
    );
  }

  /// Load all curated models from assets
  static Future<List<CuratedModel>> loadFromAssets() async {
    try {
      final yamlString = await rootBundle.loadString('assets/config/curated_models.yaml');
      final yamlData = loadYaml(yamlString);
      
      final models = <CuratedModel>[];
      if (yamlData['models'] != null) {
        for (final modelYaml in yamlData['models']) {
          models.add(CuratedModel.fromYaml(modelYaml));
        }
      }
      
      // Sort by parameter count (smallest first)
      models.sort((a, b) => a._parseParameters(a.numOfParameters)
          .compareTo(b._parseParameters(b.numOfParameters)));
      
      return models;
    } catch (e) {
      // Return default models if loading fails
      return _defaultModels;
    }
  }

  /// Default models in case asset loading fails
  static const List<CuratedModel> _defaultModels = [
    CuratedModel(
      modelId: ' Qwen/Qwen3-0.6B',
      displayName: ' Qwen/Qwen 0.6B',
      numOfParameters: '0.6B',
    ),
    CuratedModel(
      modelId: 'Unbabel/Tower-Plus-2B',
      displayName: 'Tower-Plus-2B',
      numOfParameters: '2B',
    ),
  ];

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is CuratedModel &&
          runtimeType == other.runtimeType &&
          modelId == other.modelId;

  @override
  int get hashCode => modelId.hashCode;

  @override
  String toString() => 'CuratedModel(modelId: $modelId, displayName: $displayName, parameters: $numOfParameters)';
}