Эффективный ИИ симбиоз
Эффективный ИИ симбиоз

Если вы хотите создавать код по запросу, делать переводы текстов, генерировать резюме, и при этом всем не хотите чтобы данные уходили в сеть, то вы наверняка задумывались как развернуть свой ИИ(например deepseek) на локальном компьютере. Эта статья расскажет о том, как просто это сделать. Для этого нам понадобится небольшое знание C# и "docker" для ИИ моделей - Ollama.

Для того чтобы реализовать о чем сказано выше, мы воспользуемся обычным консольным приложением .Net, которое у нас будет выступать клиентом. Для создания клиента мы будем использовать относительно недавно появившуюся библиотеку от Microsoft - Microsoft.Extensions.AI. В качестве сервера запускающего ИИ будем использовать Ollama.

Шаг первый. Разворачиваем ИИ через Ollama

Ollama - это программа которая имеет кроссплатформенные реализации (можно запускать на Windows, Linux и Mac). Она создает контейнер для запуска ИИ модели. Доступных моделей очень много, их можно посмотреть на сайте - https://ollama.com/search

ИИ модели которые можно скачать - разные по размеру и по возможностям. Можно скачать модель на пару гигабайт, а можно на полтерабайта. Если хотите использовать "умную модель", придется раскошелиться на хорошее "железо".

Если вы сами создаете ИИ модели, то тоже можете подгрузить их в Ollama (в этой статье не будем рассматривать).

Итак, скачиваем и устанавливаем Ollama - https://ollama.com/

Жмем кнопку Download.
Жмем кнопку Download.

После установки проверим, что все работает. Должен появиться значок в трее.

Ollama работает.
Ollama работает.

Теперь установим какую-нибудь доступную на сайте модель. Выбираем модель по ссылке, и копируем строчку для установки в Ollama. Открываем командную строку и пишем:

ollama run phi4-mini

После скачивания модели, она запуститься. Проверим что все работает:

Можно написать что-нибудь оригинальнее.
Можно написать что-нибудь оригинальнее.

Кстати, чтобы просмотреть все доступные команды, достаточно ввести в командной строке:

ollama

Просмотреть список доступных локально моделей(скачанных) можно так:

ollama list

Если все что описано выше заработало, значит все отлично. Первую часть по разворачиванию сервера ИИ мы выполнили, осталось внедрить ИИ в наше приложение.

Шаг второй. Пишем клиента на .Net

Пространство имен Microsoft.Extensions.AI может работать не только с Ollama, но и с другими ИИ. Например с ChatGPT(мы в этой статье рассматривать не будем). И если вам нужно использовать в приложении несколько ИИ, то все это можно реализовать через общий интерфейс IChatClient.

Итак, создаем консольное Net приложение и устанавливаем nuget пакет Microsoft.Extensions.AI.Ollama.

Я набросал небольшой пример кода, отправляющего и получающего ответы от ИИ установленного в Ollama:

using Microsoft.Extensions.AI;

//Для запуска кода необходимо установить Ollama и модель ИИ - "ollama pull phi4-mini"
try
{
	//Создаем клиента для Ollama. По умолчанию Ollama запускается по адресу - "http://localhost:11434/"
	IChatClient client = new OllamaChatClient(new Uri("http://localhost:11434/"), "phi4-mini");
	
	//Для простоты создаем обертку при помощи паттерна Фасад
	using var facade = new ChatFacade(client);
	await facade.Run();
}
catch (Exception exception)
{
	//Если что-то пошло не так
	Console.WriteLine(exception.Message);
}

/// <summary>
/// Обертка для запуска программы
/// </summary>
public class ChatFacade : IDisposable
{
	private readonly IChatClient _client;
	private readonly RequestResponseService _requestResponseService;
	private readonly ConsoleService _consoleService;
	private readonly string _currentQuery = string.Empty;
	private const string ExitAi = "/exitAI";
	public ChatFacade(IChatClient client)
	{
		_client = client;
		_requestResponseService = new(_client);
		_consoleService = new();
	}
	
	public async Task Run()
	{
		//Запускаем в цикле запрос к ИИ - ответ от ИИ
		while (true)
		{
			//Получаем с консоли запрос
			var queryMessage = _consoleService.GetQueryFromConsole();
			
			//Если команда на выход, то завершаем
			if (queryMessage == ExitAi)
				break;
			
			//Получаем ответ от ИИ
			var response = _requestResponseService.GetMessageResponseStream(queryMessage);
			
			//Выводим ответ от ИИ на консоль
			await _consoleService.PrintResponseToConsoleAsync(response);
		}
	}
	
	public void Dispose()
	{
		//Не забываем чистить ресурсы при завершении
		_client.Dispose();
	}
}

/// <summary>
/// Непосредственно сервис для запросов клиента к ИИ
/// Самая главная часть программы
/// </summary>
public class RequestResponseService
{
	private readonly IChatClient _client;
	
	public RequestResponseService(IChatClient client)
	{
		_client = client;
	}
	
	/// <summary>
	/// Метод для запросов клиента к ИИ
	/// </summary>
	/// <param name="queryMessage">Запрос к ИИ</param>
	/// <returns>Ответ от ИИ</returns>
	public IAsyncEnumerable<ChatResponseUpdate> GetMessageResponseStream(string queryMessage)
	{
		//Посылаем наш запрос ИИ модели(то есть Ollama)
		// и получаем IAsyncEnumerable
		return _client.GetStreamingResponseAsync(queryMessage);
	}
}

/// <summary>
/// Сервис для работы с консолью
/// </summary>
public class ConsoleService
{
	/// <summary>
	/// Метод получения запроса с консоли
	/// </summary>
	/// <returns>Возвращает строку запроса</returns>
	public string GetQueryFromConsole()
	{
		var queryString = string.Empty;
		
		while (string.IsNullOrEmpty(queryString))
		{
			Console.Write("Напиши запрос к ИИ: ");
			
			queryString = Console.ReadLine();
		}
		
		return queryString;
	}
	
	/// <summary>
	/// Метод для печати ответа ИИ модели
	/// </summary>
	/// <param name="response">Ответ от ИИ для печати на консоль</param>
	public async Task PrintResponseToConsoleAsync(IAsyncEnumerable<ChatResponseUpdate> response)
	{
		//Так как используется IAsyncEnumerable, в коде пишем await foreach - асинхронный перебор
		//с ожиданием получения строки ответа, и вывод на консоль.
		await foreach (var item in response)
		{
			Console.Write(item);
		}
		
		Console.Write(Environment.NewLine);
	}
}

Попробуем запустить приложение и протестировать:

Все работает.
Все работает.

Некоторые пояснения. Этого примера должно хватить для старта. Сам запрос к Ollama выполняется в строчке _client.GetStreamingResponseAsync(queryMessage) На этот запрос возвращается IAsyncEnumerable с ответами от ИИ. Для тех, кто еще не имел дела с IAsyncEnumerable, это набор данных (по аналогии с IEnumerable), которые могут приходить с задержкой по времени (асинхронно).

Эпилог

Первое и важное, что хочу отметить в заключении, это то, что библиотека Microsoft.Extensions.AI.Ollama является устаревшей к моменту выходу статьи. И Microsoft рекомендует OllamaSharp вместо нее. Изменений в коде приведенном выше будет немного при переходе на OllamaSharp.

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

Также есть отличный туториал на английском по новой библиотеке Microsoft.Extensions.AI и ее возможностях, причем с примерами. Он лежит тут. Статья в блоге Microsoft, в которой описание этого туториала, лежит тут.

И наконец, пример проекта приведенного в статье лежит тут.

Комментарии (7)


  1. Ascar
    24.08.2025 19:05

    Диспозить client в "фасаде" не нужно.


    1. ZetaTetra
      24.08.2025 19:05

      Почему?


      1. Ascar
        24.08.2025 19:05

        1. using уже указан для него

        2. общепринятый дизайн


    1. vaddone Автор
      24.08.2025 19:05

      Спасибо за внимательность. Да, using можно было не писать. Поправил.


  1. Ikobolok
    24.08.2025 19:05

    А почему Ollama ? Я тоже делал, только без Microsoft.Extensions.AI. Подключался по API.
    Мне не хватало удобного перемещения по вопрос-ответ, и сделал простенькую форму и кнопки вверх-вниз для быстрого перемещения по чату. Но получается что это обертка над оберткой. И попробовал использовать LLamaSharp, что оказалось очень удобным.
    Кстати в Ollama можно легко грузить модельки с huggingface.co


  1. konopes
    24.08.2025 19:05

    Правильно ли я понял, что возможности модели ограничены лишь способностями разработчика? Т.е. я могу научить модель работать с информацией, находящейся в файлах word и excel, например? Количество токенов на входе и выходе будет зависеть только от железа или не только или вообще не от железа? Заранее благодарю за ответы.


  1. virex
    24.08.2025 19:05

    Можно вообще обойтись без Ollama: https://habr.com/ru/articles/914392/.