| 1 | using System.Runtime.InteropServices; |
| 2 | |
| 3 | namespace CascadeIDE.Services; |
| 4 | |
| 5 | /// <summary>Рекомендации моделей Ollama по конфигурации машины (RAM).</summary> |
| 6 | public static class MachineInfo |
| 7 | { |
| 8 | /// <summary>Объём физической памяти в МБ (0 если не удалось определить).</summary> |
| 9 | public static ulong GetTotalPhysicalMemoryMb() |
| 10 | { |
| 11 | if (OperatingSystem.IsWindows()) |
| 12 | return GetTotalPhysicalMemoryMbWindows(); |
| 13 | // Linux/macOS: можно добавить парсинг /proc/meminfo или sysctl |
| 14 | return 0; |
| 15 | } |
| 16 | |
| 17 | private static ulong GetTotalPhysicalMemoryMbWindows() |
| 18 | { |
| 19 | try |
| 20 | { |
| 21 | var mem = new MEMORYSTATUSEX { dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>() }; |
| 22 | if (GlobalMemoryStatusEx(ref mem)) |
| 23 | return mem.ullTotalPhys / (1024 * 1024); |
| 24 | } |
| 25 | catch |
| 26 | { |
| 27 | // ignore |
| 28 | } |
| 29 | return 0; |
| 30 | } |
| 31 | |
| 32 | [DllImport("kernel32.dll", SetLastError = true)] |
| 33 | private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer); |
| 34 | |
| 35 | [StructLayout(LayoutKind.Sequential)] |
| 36 | private struct MEMORYSTATUSEX |
| 37 | { |
| 38 | public uint dwLength; |
| 39 | public uint dwMemoryLoad; |
| 40 | public ulong ullTotalPhys; |
| 41 | public ulong ullAvailPhys; |
| 42 | public ulong ullTotalPageFile; |
| 43 | public ulong ullAvailPageFile; |
| 44 | public ulong ullTotalVirtual; |
| 45 | public ulong ullAvailVirtual; |
| 46 | public ulong ullAvailExtendedVirtual; |
| 47 | } |
| 48 | |
| 49 | /// <summary>Рекомендуемые модели для установки (под кодинг + MCP). Группа по RAM.</summary> |
| 50 | public static IReadOnlyList<Models.RecommendedModel> GetRecommendedModels() |
| 51 | { |
| 52 | var ramMb = GetTotalPhysicalMemoryMb(); |
| 53 | // Нет данных — считаем средний ПК (16 GB) |
| 54 | if (ramMb == 0) ramMb = 16 * 1024; |
| 55 | |
| 56 | return ramMb switch |
| 57 | { |
| 58 | < 10 * 1024 => LightTier, // < 10 GB |
| 59 | < 24 * 1024 => MediumTier, // 10–24 GB (ноутбук) |
| 60 | _ => HeavyTier // 24+ GB |
| 61 | }; |
| 62 | } |
| 63 | |
| 64 | private static readonly List<Models.RecommendedModel> LightTier = |
| 65 | [ |
| 66 | new("qwen2.5-coder:3b", "Лёгкая модель для кода (3B)"), |
| 67 | new("phi4:2.5b", "Компактная универсальная (2.5B)"), |
| 68 | new("qwen2.5:1.5b", "Минимальные требования (1.5B)") |
| 69 | ]; |
| 70 | |
| 71 | private static readonly List<Models.RecommendedModel> MediumTier = |
| 72 | [ |
| 73 | new("qwen2.5-coder:7b", "Для кода и MCP (7B) — рекомендуется"), |
| 74 | new("llama3.1:8b-instruct", "Универсальная, tool calling (8B)"), |
| 75 | new("qwen2.5-coder:3b", "Лёгкая для кода (3B)"), |
| 76 | new("mistral:7b-instruct", "Быстрая (7B)") |
| 77 | ]; |
| 78 | |
| 79 | private static readonly List<Models.RecommendedModel> HeavyTier = |
| 80 | [ |
| 81 | new("qwen2.5-coder:14b", "Мощная для кода (14B)"), |
| 82 | new("qwen2.5-coder:7b", "Для кода и MCP (7B)"), |
| 83 | new("llama3.1:8b-instruct", "Универсальная (8B)"), |
| 84 | new("qwen2.5-coder:32b", "Максимум качества (32B)") |
| 85 | ]; |
| 86 | } |
| 87 | |
| 88 | |