Більшість .NET команд, які сьогодні додають функції ШІ, в кінцевому підсумку пишуть однакову трубопровід: HTTP‑клієнт, політику повторних спроб, управління секретами для API‑ключа та рядок оплати за токен у кредитній картці когось. Aspose.LLM обирає інший шлях. Це пакет NuGet, який виконує інференс великих мовних моделей всередині вашого процесу - без виклику сервісу, без обертання ключа та без запитів, що залишають машину.

У цій статті представлено бібліотеку, пояснено три концепції, на яких побудовано її API, та показано, як створити працюючу чат‑аплікацію. Якщо ви можете додати посилання на пакет, ви зможете надсилати запити всього за кілька десятків рядків.

Чому локальна модель має значення

Запуск моделі в процесі змінює те, що ви можете створювати.

  • Дані залишаються на місці. Запити ніколи не залишають хост, що важливо, коли ви працюєте з контрактами, медичними нотатками, вихідним кодом або будь‑яким іншим матеріалом, що підпадає під політику резидентності даних.
  • Немає вартості за токен. Як тільки модель знаходиться на диску, інференція — це витрати на CPU або GPU, які ви вже маєте, а не вимірюваний виклик API.
  • Немає залежності від мережі під час виконання. Настільні інструменти, локальні сервіси та ізольовані середовища працюють однаково.
  • Один артефакт розгортання. Конфігурація моделі постачається разом з вашим застосунком, а не зберігається в окремій панелі управління облікового запису.

Компроміс є чесним і варто зазначити одразу: ви надаєте обладнання. Модель, яка працює локально, потребує локальної пам’яті, і при першому запуску потрібно завантажити кілька гігабайт.

Aspose.LLM for .NET у трьох концепціях

Площа поверхні навмисно мала. Майже все, що ви робите з Aspose.LLM, включає ці три типи.

КонцепціяТипРоль
ЛіцензіяAspose.LLM.LicenseАктивує бібліотеку. Викличте SetLicense перед будь‑яким іншим використанням API.
Пресетe.g. Qwen25PresetОб’єднує файли моделі з параметрами генерації, такими як температура семплера.
Екземпляр APIAsposeLLMApiТочка входу. Створюється з пресету, зберігає розмову, надає SendMessageAsync.

Пресет — це найцікавіше. Замість того, щоб вручну налаштовувати шляхи до моделей, параметри токенізатора та значення семплера, пресет упакує перевірену комбінацію. Qwen25Preset є точкою запуску за замовчуванням, і ви можете змінювати його параметри або пізніше замінити його іншим пресетом, не торкаючись решти коду.

Вимоги

Перш ніж писати код:

  1. Встановіть пакет - Install-Package Aspose.LLM
  2. Розмістіть вашу ліцензію - розмістіть Aspose.LLM.lic у місці, де виконуваний файл зможе його прочитати під час виконання.
  3. Перевірте ваш бюджет пам’яті - preset Qwen25 вимагає принаймні 8 ГБ вільної оперативної пам’яті.

Для отримання деталей про продукт, перегляньте сторінку продукту Aspose.LLM for .NET.

Ваш перший чат

Ось найкоротша програма, яка підтримує реальну розмову. Зауважте другий і третій виклики: екземпляр API самостійно відстежує контекст, тому модель все ще знає, хто така Аліса.

Що робить код

  1. Створює License і вказує його на ваш файл ліцензії.
  2. Створює екземпляр Qwen25Preset з його конфігурацією за замовчуванням.
  3. Створює один екземпляр AsposeLLMApi з цього пресету.
  4. Надсилає кілька підказок, усі вони спільно використовують одну розмову.
using Aspose.LLM;
using Aspose.LLM.Abstractions.Parameters.Presets;

var license = new Aspose.LLM.License();
license.SetLicense("Aspose.LLM.lic");

var preset = new Qwen25Preset();
using var api = AsposeLLMApi.Create(preset);

string reply = await api.SendMessageAsync("What is 2 + 2?");
Console.WriteLine(reply);
// Output: 2 + 2 equals 4.

await api.SendMessageAsync("My name is Alice.");
string reply2 = await api.SendMessageAsync("What is my name?");
Console.WriteLine(reply2);
// Output: Your name is Alice.

AsposeLLMApi.Create(preset) повертає клієнт, орієнтований на сесію. Кожний виклик SendMessageAsync додає підказку до поточної розмови, тому ви отримуєте багатокрокову взаємодію без необхідності керувати станом самостійно. Оголошення using має значення — екземпляр володіє нативними ресурсами і потребує вивільнення.

Примітка: Ці зразки відповідають офіційній документації Aspose і не були виконані у пісочниці. Перевірте їх у вашому середовищі перед випуском.

Налаштування поведінки для одного запиту

Відповіді у розмовному режимі виграють від певної випадковості. Арифметика — ні. Замість того, щоб переналаштовувати екземпляр, створіть друге пресет і передайте його у виклик, який його потребує.

Що робить код

  1. Створює стандартний пресет і екземпляр API, як зазвичай.
  2. Створює strictPreset з низькою температурою семплера.
  3. Передає його в SendMessageAsync через аргумент preset.
  4. Залишає подальші виклики на оригінальному стандартному пресеті.
using Aspose.LLM.Abstractions.Parameters.Presets;

// Default preset used by the API instance
var defaultPreset = new Qwen25Preset();
using var api = AsposeLLMApi.Create(defaultPreset);

// A more deterministic preset, for this question only
var strictPreset = new Qwen25Preset();
strictPreset.SamplerParameters.Temperature = 0.1f;

string reply = await api.SendMessageAsync(
    "What is the square root of 144?",
    preset: strictPreset);

Console.WriteLine(reply);
// Output: The square root of 144 is 12.

SamplerParameters.Temperature контролює, скільки випадковості вводить семплер. Значення, близькі до 0.1, дають майже детермінований результат; вищі значення створюють більш різноманітне формулювання. Оскільки пресет застосовується лише до виклику, перевизначення не поширюється на іншу частину розмови.

Скасування та тайм‑аути

Тривалість генерації не повністю передбачувана, і запит, який триває довго, буде блокувати все, що його очікує. SendMessageAsync приймає CancellationToken, тому передайте його.

Що робить код

  1. Створює CancellationTokenSource з бюджетом у 30 секунд.
  2. Передає cts.Token у SendMessageAsync.
  3. Перехоплює OperationCanceledException і плавно деградує.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

try
{
    string reply = await api.SendMessageAsync(
        "Write a 500-word essay about migration patterns of the Arctic tern.",
        cancellationToken: cts.Token);
    Console.WriteLine(reply);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Generation timed out.");
}

Скасування залишає стан сеансу незмінним, тому розмова продовжується нормально під час наступного виклику. У обробнику ASP.NET Core передайте тут же власний токен RequestAborted запиту — немає сенсу продовжувати генерувати для клієнта, який вже відключився.

Повна консольна програма

Об’єднуючи все разом: REPL, який підтримує одну сесію живою протягом усього процесу і відновлюється після помилок у окремих повідомленнях.

Що робить код

  1. Встановлює ліцензію та типові налаштування один раз під час запуску.
  2. Створює єдиний екземпляр AsposeLLMApi для всієї програми.
  3. Повторює запит користувача, доки користувач не введе quit.
  4. Надсилає кожен рядок і виводить відповідь.
  5. Обробляє виключення для кожного повідомлення, щоб одна помилка не завершувала сеанс.
using Aspose.LLM;
using Aspose.LLM.Abstractions.Parameters.Presets;

internal class SimpleChatDemo
{
    public static async Task Main()
    {
        var license = new Aspose.LLM.License();
        license.SetLicense("Aspose.LLM.lic");

var preset = new Qwen25Preset();
        using var api = AsposeLLMApi.Create(preset);

Console.WriteLine("Ask me anything. Type 'quit' to exit.");
        while (true)
        {
            Console.Write("> ");
            string? line = Console.ReadLine();
            if (line == null || line.Equals("quit", StringComparison.OrdinalIgnoreCase))
                break;

try
            {
                string reply = await api.SendMessageAsync(line);
                Console.WriteLine(reply);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
    }
}

Два дизайнерських пункту варто перенести у реальні застосунки. По‑першому, екземпляр створюється один раз і повторно використовується — створення дороговартісне, і, як пояснює наступний розділ, одночасні екземпляри не дозволені. По‑друге, try‑catch розташований всередині циклу, а не навколо нього, тому одне погане повідомлення коштує вам один хід замість усієї сесії.

Оцініть бібліотеку за допомогою тимчасової ліцензії зі сторінки тимчасової ліцензії Aspose.

Помилки, з якими ви, ймовірно, зіткнетеся першими

ПомилкаТипова причинаВирішення
Not licensed for this methodЛіцензійний файл відсутній або шлях неправильнийПереконайтеся, що Aspose.LLM.lic доступний для читання з робочого каталогу і що SetLicense виконується до будь‑якого іншого виклику API.
Only one AsposeLLMApi instance can be created at a timeДва екземпляри живі одночасно, часто через фабрику на запитЗареєструйте екземпляр як singleton, або звільніть попередній перед створенням нового.
First response takes minutesДвигун завантажує нативні бінарники та ваги моделіОчікуйте 5‑15 хвилин на чистій машині. Запустіть Create під час запуску, щоб користувач не сплачував за це.

Цей другий рядок заслуговує на акцент у сценаріях сервісу. Якщо ви підключаєте Aspose.LLM до DI‑контейнера, зареєструйте AsposeLLMApi як singleton і серіалізуйте доступ до нього — реєстрація зі scoped або transient завершиться помилкою, як тільки два запити перекриються.

Додаткові ресурси

Висновок

Aspose.LLM зводить “додати LLM до цього .NET застосунку” до трьох типів і одного методу. Ліцензія активує бібліотеку, пресет визначає модель і спосіб її генерації, а екземпляр AsposeLLMApi веде розмову. Далі SendMessageAsync обробляє одне запитання, багатократну сесію, перевизначення параметрів для кожного виклику та скасовану довготривалу генерацію.

Почніть з консольного прикладу, переконайтеся, що модель поводиться так, як потрібно вашій функції, а потім переходьте до роботи з багатосесійністю та збереженням, коли основи будуть закріплені.

Часті питання

1. Що таке Aspose.LLM for .NET?

Бібліотека NuGet, яка виконує інференс великих мовних моделей у вашому власному процесі .NET. Ви створюєте пресет, створюєте екземпляр API і надсилаєте підказки — без зовнішнього сервісу, без API‑ключа.

2. Чи потрібне підключення до інтернету, щоб його використовувати?

Лише під час першого запуску. Перший виклик Create завантажує нативний движок і файли моделей, визначені пресетом, а активи кешуються локально після цього.

3. Які передумови для прикладів коду?

Пакет NuGet Aspose.LLM, дійсний файл Aspose.LLM.lic та достатньо вільної оперативної пам’яті для обраного пресету — плануйте принаймні 8 GB для Qwen25.

4. Як змінити поведінку моделі для окремого запиту?

Створіть другий пресет, налаштуйте його параметри (наприклад SamplerParameters.Temperature), і передайте його в SendMessageAsync через аргумент preset. Пізніші виклики повертаються до пресету за замовчуванням інстанції.

5. Як зупинити генерацію, яка триває занадто довго?

Передайте CancellationToken у SendMessageAsync і перехопіть OperationCanceledException. Стан сеансу зберігається після скасування, тому розмова продовжується нормально.

6. Чому перша відповідь така повільна?

Перший виклик Create завантажує нативні бінарники та ваги моделі, що може зайняти 5‑15 хвилин на чистій машині. Розігрівайте екземпляр під час запуску програми, а не під час першого запиту користувача.

Читати далі