Большинство команд .NET, которые сегодня добавляют функции ИИ, в конечном итоге пишут одинаковый «трубопровод»: HTTP‑клиент, политику повторных попыток, управление секретами для API‑ключа и строку биллинга за каждый токен на чьей‑то кредитной карте. Aspose.LLM выбирает другой путь. Это пакет NuGet, который выполняет вывод больших языковых моделей внутри вашего собственного процесса — без вызова сервиса, без вращения ключа и без запросов, покидающих машину.
Эта статья знакомит с библиотекой, объясняет три концепции, на которых построен её API, и проводит вас через работающее чат‑приложение. Если вы можете добавить ссылку на пакет, вы сможете отправлять запросы всего в нескольких десятках строк.
Почему локальная модель имеет значение
Запуск модели в процессе меняет то, что вы можете создавать.
- Данные остаются на месте. Запросы никогда не покидают хост, что важно, когда вы работаете с контрактами, медицинскими записями, исходным кодом или любыми другими данными, подпадающими под политику резидентности данных.
- Отсутствие стоимости за токен. Как только модель находится на диске, вывод происходит за счёт CPU или GPU, которые у вас уже есть, а не за счёт измеряемого API‑вызова.
- Отсутствие сетевой зависимости во время выполнения. Настольные инструменты, локальные сервисы и изолированные среды работают одинаково.
- Один артефакт развертывания. Конфигурация модели поставляется вместе с вашим приложением, а не живёт в отдельной панели управления аккаунтом.
Компромисс честный и стоит озвучить сразу: вы предоставляете оборудование. Модель, работающая локально, требует локальной памяти, а при первом запуске необходимо загрузить несколько гигабайт.
Aspose.LLM for .NET в трех концепциях
Поверхность намеренно небольшая. Почти всё, что вы делаете с Aspose.LLM, включает эти три типа.
| Концепция | Тип | Роль |
|---|---|---|
| License | Aspose.LLM.License | Активирует библиотеку. Вызовите SetLicense перед любым другим использованием API. |
| Preset | e.g. Qwen25Preset | Объединяет файлы модели с параметрами генерации, такими как температура сэмплера. |
| API instance | AsposeLLMApi | Точка входа. Создаётся из пресета, хранит разговор, предоставляет SendMessageAsync. |
Предустановка — это интересный вариант. Вместо того чтобы вручную настраивать пути к моделям, параметры токенизатора и значения сэмплера, предустановка упаковывает проверенную комбинацию. Qwen25Preset — это точка отсчёта по умолчанию, и вы можете изменить её параметры или позже заменить её другой предустановкой, не трогая остальной код.
Требования
Перед написанием любого кода:
- Установите пакет -
Install-Package Aspose.LLM - Поместите лицензию - поместите
Aspose.LLM.licгде‑то, чтобы исполняемый файл мог прочитать её во время выполнения. - Проверьте ваш бюджет памяти - предустановка Qwen25 требует как минимум 8 ГБ свободной ОЗУ.
Для получения подробной информации о продукте, см. страница продукта Aspose.LLM for .NET.
Ваш первый чат
Вот самая короткая программа, которая поддерживает реальный разговор. Обратите внимание на второй и третий вызовы: экземпляр API самостоятельно отслеживает контекст, поэтому модель всё ещё знает, кто такая Алиса.
Что делает код
- Создает
Licenseи указывает на ваш файл лицензии. - Создает экземпляр
Qwen25Presetс его конфигурацией по умолчанию. - Создает один экземпляр
AsposeLLMApiиз этого пресета. - Отправляет несколько
prompt‑ов, все они используют одну и ту же беседу.
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 и не были выполнены в песочнице. Проверьте их в своей среде перед выпуском.
Настройка поведения для одного запроса
Ответы в режиме диалога выигрывают от некоторой случайности. Арифметика — нет. Вместо переустановки экземпляра создайте второй набор параметров и передайте его в единственный вызов, которому он нужен.
Что делает код
- Создает предустановку по умолчанию и экземпляр API, как обычно.
- Создает
strictPresetс низкой температурой сэмплера. - Передаёт его в
SendMessageAsyncчерез аргументpreset. - Оставляет последующие вызовы на оригинальном значении по умолчанию.
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, поэтому передайте ему один.
Что делает код
- Создаёт
CancellationTokenSourceс бюджетом в 30 секунд. - Передаёт
cts.TokenвSendMessageAsync. - Перехватывает
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, который поддерживает одну сессию живой в течение всего процесса и восстанавливается после ошибок в отдельных сообщениях.
Что делает код
- Устанавливает лицензию и предустановку по умолчанию один раз при запуске.
- Создаёт единственный экземпляр
AsposeLLMApiдля всей программы. - Циклически запрашивает ввод пользователя, пока он не вводит
quit. - Отправляет каждую строку и выводит ответ.
- Перехватывает исключения для каждого сообщения, чтобы одна ошибка не завершала сеанс.
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 | Два экземпляра живут одновременно, часто из фабрики, создаваемой per‑request | Зарегистрируйте экземпляр как 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 ГБ для Qwen25.
4. Как изменить поведение модели для одного запроса?
Создайте второй набор предустановок, отрегулируйте его параметры (например, SamplerParameters.Temperature), и передайте его в SendMessageAsync через аргумент preset. Позднее вызовы вернутся к предустановке по умолчанию экземпляра.
5. Как остановить генерацию, которая занимает слишком много времени?
Передайте CancellationToken в SendMessageAsync и перехватите OperationCanceledException. Состояние сеанса сохраняется после отмены, поэтому разговор продолжается нормально.
6. Почему первый ответ такой медленный?
Первый вызов Create загружает нативные бинарные файлы и веса модели, что может занять от 5 до 15 минут на чистой машине. Подготовьте экземпляр при запуске приложения, а не при первом запросе пользователя.
