🧩 Как самому быстро собрать RAG-систему на локальной модели с vLLM
🚀 Введение
Retrieval-Augmented Generation (RAG) — это подход, при котором LLM не «выдумывает» ответ, а опирается на собственные документы или, иными словами, использует внутреннюю "Базу Знаний".
В этой статье мы шаг за шагом соберём простую RAG-систему:
- 📦 запустим локальную LLM через vLLM,
- 🔍 подключим векторный поиск (FAISS),
- 🧠 научим модель отвечать на основе собственных файлов.
1️⃣ Установка окружения
# Базовые зависимости pip install vllm faiss-cpu transformers accelerate sentence-transformers
2️⃣ Запуск локальной модели через vLLM
Допустим, у нас есть модель Qwen2.5-7B-Instruct (путь нужно проверить и заменить на существующий).
python -m vllm.entrypoints.openai.api_server \
--model ./models/Qwen2.5-7B-Instruct \
--tensor-parallel-size 1 \
--port 8000Теперь крутится сервер, полностью совместимый с API OpenAI на:
👉 http://localhost:8000/v1/chat/completions
3️⃣ Подготовка документов
Пусть у нас есть папка docs/ с текстовыми файлами вида .txt:
import os
import faiss
from sentence_transformers import SentenceTransformer
# Модель для эмбеддингов (лёгкая и быстрая), можно подобрать другую
embedder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
corpus, ids = [], []
for fname in os.listdir("docs"):
if not fname.endswith(".txt"): # например, работаем только с текстовыми файлами
continue
with open(f"docs/{fname}", "r", encoding="utf-8") as f:
text = f.read()
corpus.append(text)
ids.append(fname)
# Векторизация документов
embeddings = embedder.encode(corpus, convert_to_numpy=True)
# Индекс FAISS
dim = embeddings.shape[1]
index = faiss.IndexFlatL2(dim)
index.add(embeddings)
print(f"📄 Загружено документов: {len(corpus)}")
print(f"📊 Размерность эмбеддингов: {dim}")4️⃣ Запрос в стиле RAG
from openai import OpenAI
client = OpenAI(api_key="EMPTY", base_url="http://localhost:8000/v1")
CHAT_MODEL = "Qwen2.5-7B-Instruct" # для генерации ответов
def rag_query(question, top_k=2):
# 1. Векторизация запроса
q_emb = client.embeddings.create(
model=EMBED_MODEL,
input=question
).data[0].embedding
# 2. Поиск ближайших документов
D, I = index.search([q_emb], top_k)
context = "\n\n".join([corpus[i] for i in I[0]])
# 3. Промпт
messages = [
{"role": "system", "content": "Ты помощник, отвечай точно и по делу по загруженным данным."},
{"role": "user", "content": f"Вопрос: {question}\n\nКонтекст:\n{context}"}
]
# 4. Запрос к чатовой модели
resp = client.chat.completions.create(
model=CHAT_MODEL,
messages=messages,
temperature=0
)
return resp.choices[0].message.content
print(rag_query("Что такое accuracy?")))5️⃣ Что получилось
Теперь есть в простом исполнении:
- 🔍 поиск актуальной информации по загруженным документам,
- 🤖 запущенная на своем сервере LLM, которая использует этот контекст,
- 📡 всё работает локально без интернета (или в частном облаке) и без API-ключей.
🌍 Итог
- Весь пайплайн умещается в ~50-100 строк кода.
- Его можно расширить: добавить chunking, re-ranker, LangChain или LlamaIndex.
- И самое главное: в таком подходе мы полностью контролируем данные и инфраструктуру.
✨ Попробуйте сами — и вы увидите, что собрать RAG-систему не сложнее, чем настроить обычный поиск. А если будут вопросы по ходу установки библиотек и запуска кода, то смело можно обращаться за помощью к хорошо известным большим языковым моделям: DeepSeek, Qwen, ChatGPT, Gemini, Grok или к дргим привычным.