ИИ-ассистент с памятью и агентами: гайд по Ollama + RAG + pgvector | AiManual
AiManual Logo Ai / Manual.
22 Июн 2026 Гайд

Создание ИИ-ассистента с долговременной памятью и агентами: полный гайд по реализации на Ollama и RAG

Полное руководство по созданию локального ИИ-ассистента с долговременной памятью на RAG и агентами с tool calling. Используем Ollama, pgvector, мультиагентский

Реклама
cliv2

Ваш ассистент не помнит, о чем вы говорили вчера? Лечим склероз LLM

Вы сидели вечером, настраивали своего ИИ-помощника. Он идеально отвечал на вопросы, напоминал о задачах, шутил в меру. А наутро — будто его перезагрузили. Новый диалог, чистый лист. Никаких воспоминаний о ваших предпочтениях, проектах, даже о том, что вы просили не упоминать.

Знакомо? Это не злая воля модели — это архитектурное ограничение. LLM живут в моменте. Их контекстное окно — как оперативная память: всё, что выходит за пределы 128K токенов, испаряется. А ещё они путают факты, если не подсунуть им правильный контекст.

Рынок облачных решений предлагает OpenAI с GPT-4o, но каждый запрос стоит денег, а данные утекают на чужие серверы. Многие уже перешли на локальные модели через Ollama, как я описывал в статье «Развёртывание ИИ-агента за один день: Ollama, n8n и локальная языковая модель». Но там мы обходились без персистентной памяти. Сегодня исправляем это.

К июню 2026 года стек созрел: Ollama стабильно держит tool calling, pgvector интегрирован в PostgreSQL, а локальные модели уровня Qwen 3.1, DeepSeek-Coder V3 или Llama 4 Scout работают на обычных игровых видеокартах. Я покажу, как собрать ассистента, который помнит всё, может вызывать инструменты и даже смотреть на картинки. Всё локально, без единого API-ключа.

Архитектура, которая не развалится под грузом памяти

Забудьте про монолитный промпт, который растёт как снежный ком. Проектируем систему из трех слоёв:

  • LLM-ядро — Ollama с моделью общего назначения (рекомендую Qwen 3.1 7B Q4_K_M для CPU или 14B для GPU). Она отвечает за генерацию, рассуждения и принятие решений.
  • Долговременная память — RAG на pgvector. Каждое сообщение, факт, документ превращается в векторное представление и хранится в PostgreSQL. По запросу извлекаем релевантные куски.
  • Агентный слой — набор инструментов (tool calling), которые модель может вызвать: поиск по памяти, добавление факта, обработка изображения, отправка email. Плюс оркестратор, который решает, какой инструмент использовать.

Если вам нужна более сложная организация навыков — взгляните на мой подход Agent Skills. Там каждый навык — это отдельный модуль с собственными инструкциями и памятью. Мы сейчас построим упрощённую версию, но принцип тот же.

Почему pgvector, а не FAISS или Milvus?

Короткий ответ: потому что вы уже используете PostgreSQL. Зачем тащить ещё одну базу? pgvector (актуальная версия 0.8.0) добавляет тип данных vector и индексы IVFFlat или HNSW. Это даёт точный поиск по косинусной близости без лишних движений. На миллионе векторов запрос занимает десятки миллисекунд — для ассистента более чем достаточно.

FAISS быстрее, но требует отдельного сервиса и сложнее в управлении. Для дома или стартапа — pgvector побеждает удобством. Docker-образ PostgreSQL с pgvector есть в официальном реестре.

Пошаговая сборка: от установки до работающего ассистента

1 Поднимаем Ollama и модель

Устанавливаете Ollama (на 22.06.2026 последняя стабильная версия — 0.6.0). Команда для Linux/Mac:

curl -fsSL https://ollama.com/install.sh | sh

Качаем модель. Для ассистента с памятью советую Qwen 3.1 7B — в ней улучшена работа с длинным контекстом и tool calling.

ollama pull qwen3.1:7b-q4_K_M

Проверяем:

ollama run qwen3.1:7b-q4_K_M

2 Разворачиваем PostgreSQL + pgvector

Проще всего через Docker:

docker run -d --name pgvector -e POSTGRES_PASSWORD=mysecret \
  -p 5432:5432 pgvector/pgvector:0.8.0-pg16

Создаём базу и таблицу для памяти:

CREATE DATABASE assistant;
\c assistant
CREATE EXTENSION vector;

CREATE TABLE memory (
  id SERIAL PRIMARY KEY,
  content TEXT,
  embedding vector(768),  -- для эмбеддингов модели BAAI/bge-small-en-v1.5
  metadata JSONB,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX ON memory USING hnsw (embedding vector_cosine_ops);

Важно: Размерность вектора должна совпадать с эмбеддером. Для bge-small-en-v1.5 — 384, для intfloat/multilingual-e5-large — 1024. Уточните модель, которую используете.

3 Пишем Python-приложение на FastAPI

Создаём виртуальное окружение, ставим зависимости:

mkdir assistant && cd assistant
python -m venv venv && source venv/bin/activate
pip install fastapi uvicorn ollama psycopg2-binary sqlalchemy sentence-transformers

Базовая структура: один файл main.py. Подключаемся к Ollama и PostgreSQL.

4 Слой памяти: RAG-запросы

Эмбеддинги будем получать через отдельную модель (не через саму LLM). Для русского текста хорош intfloat/multilingual-e5-large. Загружаем один раз.

from sentence_transformers import SentenceTransformer
embedder = SentenceTransformer('intfloat/multilingual-e5-large')  # 1024

def add_memory(content, metadata={}):
    vec = embedder.encode(content).tolist()
    conn.execute("INSERT INTO memory (content, embedding, metadata) VALUES (%s, %s, %s)",
                 (content, vec, json.dumps(metadata)))
    conn.commit()

def search_memory(query, top_k=5):
    vec = embedder.encode(query).tolist()
    rows = conn.execute("""
        SELECT content, 1 - (embedding <=> %s::vector) AS score
        FROM memory
        ORDER BY embedding <=> %s::vector
        LIMIT %s
    """, (vec, vec, top_k)).fetchall()
    return [r[0] for r in rows]

5 Tool calling: как научить модель пользоваться инструментами

Ollama поддерживает функции (tools) с версии 0.4.0. Мы опишем инструменты в формате JSON Schema и передадим их в запросе. Модель сама решит, какой вызвать.

import ollama

tools = [
  {
    "type": "function",
    "function": {
      "name": "search_memory",
      "description": "Ищет похожие факты в долговременной памяти",
      "parameters": {
        "type": "object",
        "properties": {
          "query": {"type": "string", "description": "Запрос"}
        },
        "required": ["query"]
      }
    }
  },
  {
    "type": "function",
    "function": {
      "name": "add_memory",
      "description": "Сохраняет новый факт в память",
      "parameters": {
        "type": "object",
        "properties": {
          "content": {"type": "string"},
          "tags": {"type": "string"}
        },
        "required": ["content"]
      }
    }
  },
  {
    "type": "function",
    "function": {
      "name": "describe_image",
      "description": "Распознаёт содержимое изображения",
      "parameters": {
        "type": "object",
        "properties": {
          "image_path": {"type": "string"}
        },
        "required": ["image_path"]
      }
    }
  }
]

response = ollama.chat(
  model='qwen3.1:7b-q4_K_M',
  messages=[{"role": "user", "content": "Что я говорил про Java в прошлом разговоре?"}],
  tools=tools
)

Обрабатываем вызов инструмента в ответе — response.message.tool_calls. После выполнения результат возвращаем модели, чтобы она сформировала финальный ответ.

6 Бинго: Vision-возможности (ассистент видит)

Ollama поддерживает мультимодальные модели. Например, llama4-vision:11b или более лёгкий phi-4-vision:4b. Устанавливаем:

ollama pull llama4-vision:11b

В tool calling добавляем функцию:

response = ollama.chat(
  model='llama4-vision:11b',
  messages=[{"role": "user", "content": "Опиши это изображение", "images": ["base64_string"]}]
)

Теперь ассистент может анализировать скриншоты, мемы, документы. Результат сохраняем в память.

Запускаем и тестируем

Соберите всё вместе: FastAPI endpoint принимает вопрос, вызывает LLM с инструментами, обрабатывает tool calls, возвращает ответ. Пример curl:

curl -X POST http://localhost:8000/ask \
  -H "Content-Type: application/json" \
  -d '{"message": "Напомни, что я просил купить", "session_id": "user1"}'

Ассистент сначала ищет в памяти, потом, если ничего нет, спрашивает или сохраняет новое.

Грабли, о которые я споткнулся

  • Модель для эмбеддингов vs LLM. Не пытайтесь использовать ту же модель для эмбеддингов — она не для этого. Берите BGE или E5. Загружайте её в Python, а не в Ollama, чтобы не смешивать.
  • Осторожно с размером контекста. Если в память скинуть слишком много фактов, модель начнёт их игнорировать. Ограничивайте top_k до 5-10.
  • Tool calling на маленьких моделях. Phi-4-mini и подобные могут путать параметры. Qwen 3.1 7B справляется отлично. Llama 4 Scout 8B — тоже хорош.
  • Скорость. На CPU Qwen 3.1 7B выдаёт 5-10 токенов/с. На RTX 3060 — 50+. Если нет GPU, берите Phi-4-mini 4B.
  • Безопасность. Если даёте инструмент «отправить email» — проверяйте адрес и содержимое. LLM может написать глупость.
💡
Для тех, кто хочет сразу перейти к мультиагентским сценариям, советую прочитать «Полное руководство: как собрать Agentic RAG систему полностью локально». Там описана похожая архитектура, но с акцентом на несколько взаимодействующих агентов.

Что дальше? Превращаем поделку в продукт

Наш ассистент уже умеет:

  • Помнить всё, что вы ему сказали (и возвращать это при необходимости)
  • Вызывать функции: поиск, сохранение, распознавание изображений
  • Работать полностью локально, без интернета

Но это ещё не полноценный Agent с планированием. Если хотите добавить оркестратор, который сам разбивает задачу на шаги — читайте «Как спроектировать современного AI-агента: от planner/executor до stateful memory». А для круглосуточного дежурства в Telegram — «AI-агент, который не спит: почта, Telegram, systemd и LLM под одной крышей».

Ваш ассистент с долговременной памятью и агентами — это не игрушка. Это замена облачным помощникам, которые стоят денег и воруют данные. Соберите один раз, и он будет служить годами, помня каждый ваш запрос.

Пробуйте, ломайте, улучшайте. И помните: лучший AI — тот, который работает на вас, а не на облачного провайдера.

Подписаться на канал