Что такое РАГ? Генерация с расширенным поиском, объясненная на рабочем примере

  1. Главная
  2. Блог
  3. Искусственный интеллект

Искусственный интеллект

Что такое РАГ? Генерация с расширенным поиском, объясненная на рабочем примере

RAG позволяет модели ИИ отвечать на основе ваших собственных документов, а не только по памяти. Узнайте, как работает конвейер, запустите небольшую версию на простом Python и узнайте, почему реальные системы выходят из строя и как их тестировать.

9 мин чтения
Что такое РАГ? Генерация с расширенным поиском объяснена на рабочем примере

Главное

  • RAG сначала находит соответствующую информацию, добавляет ее в подсказку, а затем просит модель ответить на ее основе.
  • Это обычный способ связать языковую модель с частными или часто меняющимися данными.
  • Большинство проблем с качеством возникают при поиске и подготовке данных, а не в модели.
  • RAG уменьшает выдуманные ответы, но не устраняет их, поэтому вам необходимо его протестировать.

Спросите обычного помощника по искусственному интеллекту о политике возврата средств в вашей компании, и он сможет только догадываться. Он никогда не видел ваших документов. RAG, short for retrieval-augmented generation, solves this by looking up the right information and handing it to the model along with the question.

Это руководство объясняет каждый этап простым языком, а затем создает небольшую версию, используя только стандартную библиотеку Python. Мы запустили этот код на Python 3.13, и показанные оценки получены в результате этого запуска. Он не использует языковую модель, поэтому демонстрирует поиск и построение подсказок, и мы не тестировали последний этап ответа.

Что такое РАГ?

Генерация с расширенным поиском — это метод, сочетающий этап поиска с языковой моделью. When a question arrives, the system searches a knowledge source, adds the best results to the prompt, and asks the model to answer based on that material.

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

Проблемы, которые решает RAG

Языковая модель сама по себе имеет три ограничения для использования в бизнесе:

  • Он не знает ваших личных данных. Ваши правила, билеты и контракты не были частью его обучения.
  • Его знания ограничены. Он не может знать о цене, которую вы изменили сегодня утром.
  • Он может придумывать ответы. Если он не уверен, он может выдать что-то правдоподобное, но ложное.

RAG обращается ко всем трем, и вам не придется ничего переучивать. Обновите документ, переиндексируйте его, и уже следующий ответ сможет его использовать.

Как работает RAG, шаг за шагом

Система RAG имеет два конвейера. Один заранее готовит ваши данные, а другой отвечает на каждый вопрос.

Индексирование: подготовка ваших данных

  1. Загрузка: собирайте контент из PDF-файлов, вики, баз данных или билетов.
  2. Очистка и фрагментирование: удалите ненужный мусор, а затем разбейте документы на небольшие отрывки.
  3. Встраивание: преобразование каждого отрывка в список чисел, называемый встраиванием, который отражает его смысл.
  4. Сохранение: сохранение вложений в индексе с возможностью поиска, часто в векторной базе данных.

Запрос: ответ на вопрос

  1. Извлечение: вставьте вопрос и найдите отрывки, наиболее близкие по смыслу.
  2. Дополнение: вставьте эти отрывки в подсказку.
  3. Сгенерировать: модель записывает ответ, используя этот контекст.

При поиске не обязательно использовать векторы. Это может быть поиск по ключевым словам или даже SQL-запрос, в зависимости от того, какой из них найдет нужную информацию для ваших данных.

Крошечный рабочий пример

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

import math, re
from collections import Counter

DOCS = {
    "refunds": "Refunds are paid within 7 days to the original payment method.",
    "shipping": "Standard shipping takes 3 to 5 working days across India.",
    "warranty": "All keyboards include a 2 year warranty against defects.",
}

def vectorize(text):
    return Counter(re.findall(r"[a-z0-9]+", text.lower()))

def similarity(a, b):
    dot = sum(a[word] * b[word] for word in a)
    size = math.sqrt(sum(v * v for v in a.values()))
    size *= math.sqrt(sum(v * v for v in b.values()))
    return dot / size if size else 0

def retrieve(question, k=1):
    q = vectorize(question)
    scored = [(similarity(q, vectorize(t)), name) for name, t in DOCS.items()]
    return sorted(scored, reverse=True)[:k]

def build_prompt(question):
    (score, name), = retrieve(question)
    return (
        "Answer using only the context. If it is not there, say you do not know.\n"
        f"Context: {DOCS[name]}\n"
        f"Question: {question}"
    )

Вопрос о возмещении средств находит правильный отрывок и создает такое приглашение:

print(retrieve("How many days until refunds are paid?"))
# [(0.4558..., 'refunds')]

print(build_prompt("How many days until refunds are paid?"))
# Answer using only the context. If it is not there, say you do not know.
# Context: Refunds are paid within 7 days to the original payment method.
# Question: How many days until refunds are paid?

В полноценной системе вы теперь должны отправить это приглашение в языковую модель. The important detail is the instruction to admit when the answer is missing, which you can learn more about in our guide to prompt engineering.

Чего не хватает в нашем примере

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

print(retrieve("When can I get my money back?", k=3))
# [(0.0, 'warranty'), (0.0, 'shipping'), (0.0, 'refunds')]

Каждый балл равен нулю, поскольку в вопросе нет общих слов с каким-либо документом. «Возврат денег» означает возврат денег человеку, но количество слов не может сказать точно. This single output explains why real systems use embeddings, which are designed so that text with similar meaning ends up with similar numbers, even with no words in common.

Но не думайте, что встраивания решают все. У них могут возникнуть проблемы с точными терминами, такими как коды продуктов и номера ошибок, с которыми поиск по ключевым словам справляется очень хорошо. Вот почему многие производственные системы используют гибридный поиск, сочетая два подхода.

Чанкинг: шаг, который люди недооценивают

Документы разбиваются на фрагменты, поскольку целые файлы слишком длинные и неточные для извлечения. Выбор размера предполагает реальный компромисс:

Размер чанка Преимущество Риск
Слишком маленький Точные совпадения Теряется контекст, например, к какому продукту применяется правило.
Слишком большой Сохраняет контекст Размывает смысл и использует больше подсказок
Разделить по структуре Соблюдает заголовки и разделы Нужны более чистые исходные документы

Несколько сотен слов с некоторым перекрытием между частями — обычная отправная точка, но воспринимайте это как первое предположение для проверки. По возможности разделяйте текст по естественным границам, например заголовкам. Прикрепите метаданные, такие как название документа, дата и отдел, чтобы можно было фильтровать результаты и ссылаться на источники.

Улучшение поиска

Если ответы плохие, стоит попробовать следующие обновления, примерно в следующем порядке:

  • Очистите данные. Сначала удалите устаревшие и повторяющиеся документы. Ни один алгоритм не исправляет противоречивые источники.
  • Используйте гибридный поиск. Объедините результаты, основанные на значении и ключевых словах.
  • Добавьте средство повторного ранжирования. Получите больше кандидатов, а затем используйте специализированную модель, чтобы переупорядочить их по релевантности.
  • Фильтровать по метаданным. Ограничивайте результаты по продукту, региону или дате перед поиском.
  • Перепишите запрос. Добавьте расплывчатое продолжение, например: «А как насчет второго?» в полный вопрос.

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

RAG против тонкой настройки

Вопрос ТРЯПКА Тонкая настройка
Что это добавляет? Знания во время вопросов Тренированное поведение или стиль
Обновление информации Переиндексировать документ Тренируйся снова
Можно ли ссылаться на источники? Да Не надежно
Лучшее для Факты, которые меняют Последовательный формат или тон

Они не являются взаимоисключающими. Наше сравнение RAG с точной настройкой и быстрым проектированием показывает, как сделать более глубокий выбор.

Как протестировать систему RAG

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

Этап Вопрос, который стоит задать Общее имя
Поиск Мы нашли правильный отрывок? Вызов контекста
Поиск Насколько из того, что мы получили, было полезно? Контекстная точность
Поколение Подтверждается ли ответ контекстом? Верность
Поколение Действительно ли это отвечает на вопрос? Актуальность ответа

Включите также неловкие случаи: вопросы, на которые нет ответа в ваших данных, вопросы, в которых используются разные формулировки, и вопросы с противоречивыми источниками. Повторно запускайте этот набор всякий раз, когда вы меняете фрагменты, модели или запросы, точно так же, как набор регрессии. В нашем руководстве по pytest показано, как запустить множество входных данных в рамках одного теста.

Почему системы RAG терпят неудачу

  • Ответ не содержится в данных. Модель все еще может попытаться это сделать, поэтому сообщите ей, как отказаться.
  • Не удалось получить нужный фрагмент. Часто это проблема с фрагментированием или поиском.
  • Слишком много контекста. Нерелевантные отрывки могут отвлекать модель и увеличивать затраты.
  • Устаревшие документы. Старый полис можно восстановить так же уверенно, как и текущий.
  • Таблицы и PDF-файлы анализируются плохо. Если при извлечении текст шифруется, извлечение никогда не восстанавливается.
  • Тестирование только с помощью демонстрационных вопросов. Реальные пользователи формулируют вещи совсем по-другому.

Безопасность и разрешения

RAG несет в себе два риска, которые легко не заметить. Во-первых, контроль доступа: если в индексе хранятся файлы HR, вопрос младшего сотрудника не должен их извлекать. Применяйте разрешения каждого пользователя во время извлечения, поскольку указание модели хранить секреты не является надежной защитой.

Во-вторых, быстрое введение. Полученная веб-страница или документ может содержать текст, например «игнорировать ваши инструкции». Рассматривайте полученный контент как ненадежные данные, ограничивайте действия, которые может выполнять модель, и требуйте от человека одобрения конфиденциальных действий.

Итоги

RAG — это простая идея с множеством практических деталей: найдите нужную информацию, а затем попросите модель ее использовать. Начните с небольшого чистого набора документов и примерно двадцати реальных вопросов. Прежде чем добавлять сложность, убедитесь, что извлечение работает хорошо, потому что скромный конвейер с хорошими данными обычно превосходит сложный конвейер с плохими данными.

Часто задаваемые вопросы

Что означает RAG в ИИ?

RAG означает генерацию с расширенным поиском. Система извлекает соответствующую информацию, добавляет ее в подсказку, а модель генерирует на ее основе ответ.

Остановит ли RAG галлюцинации ИИ?

Он уменьшает их, предоставляя модели реальные источники, но не удаляет их. Модель по-прежнему может неправильно интерпретировать контекст, поэтому проверяйте ответы и показывайте цитаты.

Нужна ли мне векторная база данных для RAG?

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

В чем разница между RAG и тонкой настройкой?

RAG предоставляет информацию во время вопросов, поэтому обновления происходят быстро. Точная настройка обучает модель изменению своего поведения или стиля и менее подходит для изменения фактов.

Что такое встраивание?

Вложение — это список чисел, представляющих значение текста. Отрывки со схожим значением имеют одинаковые номера, что делает возможным поиск по смыслу.

Продолжайте учиться

Работайте с Stack Quora

Нужна помощь с тестированием, WordPress или SEO?

Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.

Продолжайте читать

Больше руководств по тестирование, искусственный интеллект и современные разработки

Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.

Искусственный интеллект

Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить

Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…

Читать статью →
DevOps

Объяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация

Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…

Читать статью →
Разработка ПО

Объяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429

Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…

Читать статью →
Автоматизация тестирования

Издевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут

Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …

Читать статью →
Тестирование ПО

Объяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%

Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…

Читать статью →
Базы данных и SQL

DELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них

Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…

Читать статью →
Базы данных и SQL

Объяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами

Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…

Читать статью →
Разработка ПО

Интерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора

Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…

Читать статью →
Разработка ПО

Объяснение Python *args и **kwargs: гибкие функции с понятными примерами

Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…

Читать статью →
Разработка ПО

Лямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать

Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …

Читать статью →
Искусственный интеллект

Что такое ИИ-агенты? Как они работают: можно запустить простой цикл агента

Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…

Читать статью →
DevOps

Мониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками

Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…

Читать статью →
DevOps

Docker Volumes против Bind Mounts: правильное сохранение данных контейнера

Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…

Читать статью →
Автоматизация тестирования

TDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый

TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…

Читать статью →
Тестирование ПО

Пользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры

Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…

Читать статью →
Базы данных и SQL

Объяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать

Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…

Читать статью →
Базы данных и SQL

Оператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки

SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…

Читать статью →
Разработка ПО

Что такое JWT? Веб-токены JSON, объясненные на рабочем примере

Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…

Читать статью →
Разработка ПО

Объяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами

Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …

Читать статью →
Разработка ПО

Генераторы Python и объяснение доходности: экономьте память с помощью реальных примеров

Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…

Читать статью →
Искусственный интеллект

Что такое вложения? Простое объяснение векторов и косинусного сходства

Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…

Читать статью →
DevOps

Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…

Читать статью →
Автоматизация тестирования

Ненадежные тесты: что их вызывает и как их исправить навсегда

Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…

Читать статью →
Тестирование ПО

Нагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6

Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…

Читать статью →
Тестирование ПО

Тестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый

Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…

Читать статью →
Базы данных и SQL

Оптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени

Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…

Читать статью →
Базы данных и SQL

SQL UNION против UNION ALL: различия, примеры и проверка производительности

SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…

Читать статью →
Разработка ПО

Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты

Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…

Читать статью →
Разработка ПО

Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…

Читать статью →
Разработка ПО

Классы и объекты Python: учебник ООП с реальными примерами

Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…

Читать статью →
Искусственный интеллект

Что такое большая языковая модель? Как работают LLM, объяснено без шумихи

Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…

Читать статью →
DevOps

Команды Linux для начинающих: основное руководство по терминалу с примерами

Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…

Читать статью →
Автоматизация тестирования

Selenium vs Playwright: ключевые различия, сравнение кода и что выбрать

Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…

Читать статью →
Тестирование ПО

Разделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах

Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…

Читать статью →
Тестирование ПО

Серьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры

Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…

Читать статью →
Базы данных и SQL

Учебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами

Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…

Читать статью →
Базы данных и SQL

Объяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции

Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…

Читать статью →
Разработка ПО

Git Commands Cheat Sheet: The Commands You Actually Use, With Examples

Шпаргалка по командам Git, сгруппированная по задачам: настройка, промежуточный этап, ветки, удаленные устройства, тайник, история и исправление оши…

Читать статью →
Разработка ПО

Объяснение промисов в JavaScript: then, catch, Promise.all и распространенные ошибки

Обещания JavaScript, объясненные с помощью кода, который мы запускали: состояния, цепочки then и catch, обработка ошибок, Promise.all, allSettled, R…

Читать статью →
Разработка ПО

Учебное пособие по словарю Python: методы, примеры и общие шаблоны

Учебное пособие по словарю Python с кодом, который мы выполнили: создание, чтение и обновление словарей, ключевые методы, слияние, понимание, шаблон…

Читать статью →
Искусственный интеллект

Что такое РАГ? Генерация с расширенным поиском, объясненная на рабочем примере

Что такое РАГ? Retrieval-augmented generation explained step by step: indexing, chunking, embeddings, retrieval, a small working Python example, eva…

Читать статью →
DevOps

Учебное пособие по Terraform для начинающих: инфраструктура как код от первого файла до модулей

Учебное пособие по Terraform для начинающих: начните без облачной учетной записи, изучите инициализацию, планирование и применение, затем переменные…

Читать статью →
DevOps

Docker и Kubernetes: ключевые различия, как они работают вместе и что вам нужно

Объяснение Docker и Kubernetes: что делает каждый из них, одно и то же приложение работает с обоими, сравнение Docker Compose и Swarm, изменение doc…

Читать статью →
Автоматизация тестирования

Учебное пособие по Pytest для начинающих: фикстуры, параметризация и реальные примеры

Учебное пособие по pytest для начинающих с тестами, которые мы запускали на pytest 9.2: утверждения, фикстуры, параметризация, conftest, маркеры, tm…

Читать статью →
Тестирование ПО

Жизненный цикл тестирования программного обеспечения (STLC): 6 этапов, критерии входа и выхода, пример

Объясняется жизненный цикл тестирования программного обеспечения: шесть этапов STLC с критериями входа и выхода, результаты, пример проработанной фу…

Читать статью →
Разработка ПО

Git merge vs rebase: отличия, примеры и когда что использовать

Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.

Читать статью →
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.

Читать статью →
Базы данных и SQL

SQL JOIN: объяснение с примерами (Inner, Left, Right, Full)

Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…

Читать статью →