LLMeQueue: очередь запросов к локальной LLM на GPU через интернет | AiManual
AiManual Logo Ai / Manual.
03 Янв 2026 Инструмент

LLMeQueue: очередь запросов к локальной LLM, которую не сломает даже тысяча пользователей

Создайте микросервис для массовой обработки запросов к локальной LLM на GPU с поддержкой OpenAI API. Очередь, балансировка, удалённый доступ.

Представьте: у вас есть мощный домашний сервер с RTX 4090, на котором крутится Mistral 7B. Вы хотите дать доступ к нему команде из десяти человек. Они одновременно отправляют запросы на генерацию текста, создание эмбеддингов, анализ документов.

И что происходит? Правильно. Всё падает.

Ollama по умолчанию обрабатывает запросы последовательно. Два одновременных запроса — и один из них зависнет навечно. Три запроса — сервер может просто отказаться отвечать. Это не баг, это фича для одиночного использования.

LLMeQueue решает эту проблему радикально просто: ставит всё в очередь.

Что такое LLMeQueue и зачем он нужен

Это Python-микросервис, который садится между вашими приложениями и локальной LLM (через Ollama). Он принимает запросы в формате OpenAI API, складывает их в очередь и по одному отправляет на обработку. Когда модель на GPU закончила с одним запросом — сервис берёт следующий.

Ключевая фишка: LLMeQueue полностью совместим с OpenAI API. Ваши приложения, которые работают с ChatGPT, будут думать, что обращаются к OpenAI, но на самом деле запросы пойдут на ваш домашний GPU.

Зачем это нужно? Давайте посмотрим на реальные сценарии:

  • Массовая генерация эмбеддингов для документов (по 100-200 файлов за раз)
  • Параллельная работа нескольких пользователей через веб-интерфейс
  • Интеграция с существующими инструментами вроде LangChain, которые уже используют OpenAI API
  • Тестирование промптов с разными параметрами одновременно

Без очереди эти сценарии превращаются в кошмар. С очередью — работают как часы.

Как это работает под капотом

Архитектура до боли простая:

КомпонентЧто делает
FastAPI серверПринимает HTTP запросы в формате OpenAI API
Очередь (asyncio.Queue)Хранит запросы до обработки
ВоркерыБерут запросы из очереди и отправляют в Ollama
Ollama API клиентОбщается с локальной LLM

Когда приходит запрос на /v1/chat/completions, сервер не бежит сразу в Ollama. Он кладёт запрос в очередь и возвращает клиенту «принято, ждите». Воркеры в фоне забирают запросы по одному, отправляют в модель, ждут ответа и возвращают результат.

Вот как выглядит базовый код сервера:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import aiohttp
import asyncio
from typing import List

app = FastAPI()

# Простейшая очередь
request_queue = asyncio.Queue()

class ChatMessage(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    model: str
    messages: List[ChatMessage]
    max_tokens: int = 100

@app.post("/v1/chat/completions")
async def chat_completion(request: ChatCompletionRequest):
    """Принимаем запрос, кладём в очередь, ждём результата"""
    # Генерируем ID для отслеживания
    request_id = str(uuid.uuid4())
    
    # Кладём в очередь
    await request_queue.put({
        "id": request_id,
        "request": request.dict(),
        "event": asyncio.Event()
    })
    
    # Ждём, пока воркер обработает
    # ...
    
    return {"choices": [{"message": {"content": "Ответ от модели"}}]}

async def worker():
    """Воркер, который забирает запросы из очереди"""
    while True:
        task = await request_queue.get()
        
        try:
            # Отправляем в Ollama
            async with aiohttp.ClientSession() as session:
                async with session.post(
                    "http://localhost:11434/api/chat",
                    json={
                        "model": task["request"]["model"],
                        "messages": task["request"]["messages"],
                        "options": {"num_predict": task["request"]["max_tokens"]}
                    }
                ) as response:
                    result = await response.json()
                    
            # Сохраняем результат
            task["result"] = result
            task["event"].set()
            
        except Exception as e:
            task["error"] = str(e)
            task["event"].set()
        finally:
            request_queue.task_done()
💡
В реальном LLMeQueue код сложнее — там есть обработка ошибок, логирование, метрики, поддержка разных эндпоинтов (не только чат, но и эмбеддинги). Но суть остаётся той же: очередь + воркеры = стабильность.

Чем LLMeQueue лучше других решений

Давайте сравним с тем, что уже есть на рынке:

РешениеПлюсыМинусыКогда использовать
Прямой доступ к OllamaМаксимальная простотаНет очереди, падает при нагрузкеДля одного пользователя
LLMeQueueОчередь, OpenAI API форматНужно настраиватьДля команды или массовой обработки
Nginx как балансировщикМожно настроить очередиСложная конфигурация для LLMЕсли уже есть инфраструктура
Платное облако (OpenAI)Всё работает из коробкиДорого, данные уходят наружуКогда не жалко денег

Главное преимущество LLMeQueue — он решает конкретную проблему (очередь запросов) максимально простым способом. Не нужно изучать сложные системы кластеризации, не нужно настраивать балансировщики. Скачал, запустил, работает.

Внимание: LLMeQueue не делает распределённые вычисления на несколько GPU. Если вам нужно распределить модель между несколькими видеокартами, смотрите в сторону llama.cpp RPC-server или стратегий масштабирования.

Как запустить LLMeQueue за 5 минут

1Установите Ollama и модель

Если ещё не сделали:

curl -fsSL https://ollama.ai/install.sh | sh
ollama pull mistral:7b

2Клонируйте LLMeQueue

git clone https://github.com/ваш-репозиторий/LLMeQueue.git
cd LLMeQueue
pip install -r requirements.txt

3Настройте конфигурацию

# config.yaml
server:
  host: "0.0.0.0"  # слушаем все интерфейсы
  port: 8000

ollama:
  base_url: "http://localhost:11434"
  default_model: "mistral:7b"

queue:
  max_size: 100  # максимум запросов в очереди
  workers: 2     # два воркера для параллельной обработки

4Запустите сервер

python main.py --config config.yaml

Сервер запустится на порту 8000. Теперь можно отправлять запросы:

curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral:7b",
    "messages": [{"role": "user", "content": "Привет, как дела?"}]
  }'

Или использовать с Python-клиентом OpenAI:

import openai

client = openai.OpenAI(
    base_url="http://localhost:8000/v1",  # Ваш LLMeQueue
    api_key="not-needed"
)

response = client.chat.completions.create(
    model="mistral:7b",
    messages=[{"role": "user", "content": "Напиши стих про Python"}]
)

print(response.choices[0].message.content)

Реальные кейсы использования

Вот где LLMeQueue спасает жизнь:

Массовая генерация эмбеддингов

У вас есть 500 документов. Нужно создать эмбеддинги для каждого и положить в векторную базу. Без очереди это займёт вечность (или сломается). С LLMeQueue — отправляете все запросы разом, они обрабатываются по очереди, вы получаете все эмбеддинги.

# Пример массовой генерации эмбеддингов
documents = ["документ 1", "документ 2", ...]  # 500 документов

embeddings = []
for doc in documents:
    response = client.embeddings.create(
        model="nomic-embed-text",
        input=doc
    )
    embeddings.append(response.data[0].embedding)
    
# LLMeQueue сам разберётся с очередью

Веб-интерфейс для команды

Сделали простой чат-интерфейс на Streamlit для команды из 5 человек. Все пишут запросы одновременно. Без LLMeQueue интерфейс будет висеть и показывать ошибки. С LLMeQueue — запросы просто будут выполняться дольше, но всё заработает.

Интеграция с существующими инструментами

У вас уже есть код, который использует OpenAI API. Вы купили мощную станцию для локальных LLM и хотите перенести туда обработку. Меняете base_url с api.openai.com на localhost:8000 — и всё работает. Ничего переписывать не нужно.

Ограничения и подводные камни

LLMeQueue — не волшебная таблетка. У него есть свои ограничения:

  • Одна модель за раз: Очередь работает для одной запущенной модели. Если нужно переключаться между разными моделями, придётся дорабатывать.
  • Нет приоритизации: Запросы обрабатываются в порядке FIFO (первый пришёл — первый ушёл). Срочный запрос будет ждать своей очереди.
  • Зависит от Ollama: Если Ollama упадёт, LLMeQueue продолжит принимать запросы в очередь, но не сможет их обработать.
  • Только HTTP: Нет поддержки WebSockets для стриминга. Ответы приходят целиком.

Эти ограничения — осознанный выбор. LLMeQueue делает одну вещь (очередь запросов) и делает её хорошо. Для сложных сценариев придётся искать другие решения или дорабатывать.

Кому подойдёт LLMeQueue

Этот инструмент — для конкретных людей с конкретными проблемами:

Кто выВаша проблемаКак LLMeQueue поможет
Разработчик в маленькой компанииНет бюджета на OpenAI API, но нужно дать доступ команде к LLMПоставите на сервер с GPU, команда сможет работать одновременно
Исследователь данныхНужно обработать тысячи текстов для создания датасетаОтправите все запросы разом, они обработаются по очереди
Энтузиаст с домашним серверомХотите поделиться доступом к своей LLM с друзьямиНастроите за час, друзья смогут пользоваться через API
Разработчик готовых решенийИнтегрируете LLM в продукт, но клиенты шлют запросы пачкамиОчередь не даст серверу упасть под нагрузкой

Если вы один используете LLM для редких запросов — LLMeQueue вам не нужен. Если у вас команда или массовая обработка — он сэкономит нервы и время.

Что дальше? Развитие проекта

LLMeQueue в текущем виде решает базовую задачу. Но есть куда расти:

  • Приоритетная очередь: Чтобы срочные запросы обрабатывались первыми
  • Балансировка между несколькими GPU: Если у вас несколько видеокарт, можно распределять запросы между ними
  • Поддержка стриминга: Чтобы ответы приходили по мере генерации, как в ChatGPT
  • Мониторинг и метрики: Графики загрузки очереди, времени обработки, ошибок
  • Автоматическое масштабирование: Запуск дополнительных воркеров при высокой нагрузке

Пока это всё — задачи для сообщества. Базовая версия работает и решает 80% проблем. Остальные 20% — для тех, кому нужно больше.

Главный совет: не усложняйте раньше времени. Начните с простой очереди. Когда упрётесь в её ограничения — дорабатывайте. Часто оказывается, что простого решения хватает на годы.

А если нужна совсем простая настройка — посмотрите как запустить локальную LLM-инфраструктуру. Там тоже есть про очереди, но в более общем контексте.

LLMeQueue — это не про революцию. Это про то, чтобы перестать бояться давать доступ к своему GPU. Поставить очередь, открыть порт, работать. Всё просто. Как и должно быть.