Я в равной мере использовал как графовую базу данных, так и SQL-базу данных, а затем применял различные большие языковые модели (LLM) для ответов на вопросы о данных с помощью подхода, основанного на дополнении извлечения (RAG). Используя один и тот же набор данных и вопросы в обеих системах, я оценил, какая парадигма баз данных обеспечивает более точные и содержательные результаты.
Retrieval-Augmented Generation (RAG)
Retrieval-Augmented Generation (RAG) — это структура искусственного интеллекта, которая улучшает большие языковые модели (LLM), позволяя им извлекать соответствующую внешнюю информацию перед генерацией ответа. Вместо того чтобы полагаться исключительно на то, на чём была обучена модель, RAG динамически запрашивает источник знаний (в этой статье — SQL или графовая база данных) и интегрирует эти результаты в свой ответ. Введение в RAG можно найти здесь.
SQL-базы данных
SQL-базы данных организуют данные в таблицы, состоящие из строк и столбцов. Каждая строка представляет запись, а каждый столбец — атрибут. Отношения между таблицами определяются с помощью ключей и объединений, и все данные следуют фиксированной схеме. SQL-базы данных идеально подходят для структурированных транзакционных данных, где важны согласованность и точность — например, финансы, инвентаризация или записи пациентов.
Графовые базы данных
Графовые базы данных хранят данные в виде узлов (сущностей) и рёбер (отношений) с необязательными свойствами, прикреплёнными к обоим. Вместо объединения таблиц они напрямую представляют отношения, что позволяет быстро перемещаться по связанным данным. Графовые базы данных идеально подходят для моделирования сетей и отношений — таких как социальные графы, графы знаний или карты молекулярных взаимодействий — там, где связи так же важны, как и сами сущности.
Данные
Набор данных, который я использовал для сравнения производительности RAG, содержит результаты Формулы-1 с 1950 по 2024 год. Он включает подробные результаты гонок пилотов и конструкторов (команд), охватывающие квалификацию, спринтерскую гонку, основную гонку и даже время прохождения кругов и время пит-стопов. Также включены турнирные таблицы пилотов и конструкторов после каждой гонки.
Схема SQL
Этот набор данных уже структурирован в таблицах с ключами, так что можно легко настроить SQL-базу данных. Схема базы данных показана ниже:
Дизайн SQL-базы данных
Races — это центральная таблица, которая связана со всеми типами результатов, а также с дополнительной информацией, такой как сезон и трассы. Таблицы результатов также связаны с таблицами Drivers и Constructors, чтобы фиксировать их результаты в каждой гонке. Турнирные таблицы пилотов и конструкторов после каждой гонки хранятся в таблицах Driver_standings и Constructor_standings.
Схема графа
Схема графовой базы данных показана ниже:
Дизайн графовой базы данных
Поскольку графовые базы данных могут хранить информацию в узлах и отношениях, требуется всего шесть узлов по сравнению с 14 таблицами в SQL-базе данных. Узел Car является промежуточным узлом, который используется для моделирования того, что водитель управлял автомобилем конструктора на определённой гонке. Поскольку пары водитель — конструктор меняются со временем, это отношение необходимо определять для каждой гонки. Результаты гонки хранятся в отношениях, например, :RACED между Car и Race. В то время как отношения :STOOD_AFTER содержат турнирные таблицы пилотов и конструкторов после каждой гонки.
Запросы к базе данных
Я использовал LangChain для создания цепочки RAG для обоих типов баз данных, которая генерирует запрос на основе вопроса пользователя, выполняет запрос и преобразует результат запроса в ответ пользователю. Код можно найти в этом репозитории. Я определил общий системный запрос, который можно использовать для генерации запросов к любой SQL- или графовой базе данных. Единственная специфическая для данных информация была включена путём вставки автоматически сгенерированной схемы базы данных в запрос. Системные запросы можно найти здесь.
Вот пример того, как инициализировать модельную цепочку и задать вопрос: «Какой водитель выиграл Гран-при Бельгии 92 года?»
from langchain_community.utilities import SQLDatabase
from langchain_openai import ChatOpenAI
from qa_chain import GraphQAChain
from config import DATABASE_PATH
connection_string = f"sqlite:///{DATABASE_PATH}"
db = SQLDatabase.from_uri(connection_string)
llm = ChatOpenAI(temperature=0, model="gpt-5")
chain = GraphQAChain(llm, db, db_type='SQL', verbose=True)
chain.invoke("What driver won the 92 Grand Prix in Belgium?")
Что возвращает:
{'write_query': {'query': "SELECT d.forename, d.surname
FROM results r
JOIN races ra ON ra.raceId = r.raceId
JOIN drivers d ON d.driverId = r.driverId
WHERE ra.year = 1992
AND ra.name = 'Belgian Grand Prix'
AND r.positionOrder = 1
LIMIT 10;"}}
{'execute_query': {'result': "[('Michael', 'Schumacher')]"}}
{'generate_answer': {'answer': 'Michael Schumacher'}}
Оценка
Теперь вопрос, на который я хочу ответить, заключается в том, лучше ли LLM выполнять запросы к SQL или к графовой базе данных. Я определил три уровня сложности (лёгкий, средний и сложный), где лёгкими были вопросы, на которые можно было ответить, запросив данные только из одной таблицы или узла, средними были вопросы, которые требовали одной или двух ссылок между таблицами или узлами, а сложные вопросы требовали большего количества ссылок или подзапросов. Для каждого уровня сложности я определил по пять вопросов. Кроме того, я определил пять вопросов, на которые нельзя было ответить с помощью данных из базы данных.
Я ответил на каждый вопрос с помощью трёх моделей LLM (GPT-5, GPT-4 и GPT-3.5-turbo), чтобы проанализировать, нужны ли самые продвинутые модели или более старые и дешёвые модели могут также создавать удовлетворительные результаты. Если модель дала правильный ответ, она получала 1 балл, если она ответила, что не может ответить на вопрос, она получала 0 баллов, а в случае, если она дала неправильный ответ, она получала -1 балл.
| **Модель | Графовая БД | SQL БД** |
|---|---|---|
| GPT-3.5-turbo | -2 | 4 |
| GPT-4 | 7 | 9 |
| GPT-5 | 18 | 18 |
Модель — Оценка эффективности базы данных
Примечательно, как более продвинутые модели превосходят более простые: GPT-3-turbo допустила примерно вдвое меньше ошибок, GPT-4 допустила 2–3 ошибки, но не смогла ответить на 6–7 вопросов, а GPT-5 дала все ответы, кроме одного, правильно. Более простые модели, по-видимому, работают лучше с SQL, чем с графовой базой данных, в то время как GPT-5 достигла одинакового результата с любой базой данных.
Заключение
Это сравнение производительности RAG с использованием набора данных о результатах Формулы-1 показывает, что новейшие LLM работают исключительно хорошо, выдавая высокоточные и контекстуально обоснованные ответы без какого-либо дополнительного инженерного проектирования запросов. В то время как более простые модели испытывают трудности, новые, такие как GPT-5, справляются со сложными запросами с почти идеальной точностью. Важно отметить, что не было существенной разницы в производительности между графовым и SQL-подходами к базам данных — пользователи могут просто выбрать парадигму базы данных, которая лучше всего соответствует структуре их данных.
Набор данных, использованный здесь, служит лишь иллюстративным примером; результаты могут отличаться при использовании других наборов данных, особенно тех, которые требуют специализированных знаний в предметной области или доступа к непубличным источникам данных. В целом, эти результаты подчёркивают, как далеко продвинулись LLM с дополненным извлечением в интеграции структурированных данных с рассуждением на естественном языке.
