Главная / Статьи

Создайте чат-ассистента для Википедии на основе технологии RAG с использованием LlamaIndex и ReAct

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

Издатель: REACTAPP.TOP6 мин чтения1383 слов

Источники: **I Built a ChatGPT-Like Wikipedia Assistant Using RAG, ReAct Agents, and LlamaIndex in Under 300 Lines of Python**

Введение

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

Практический чат-ассистент на основе Википедии с технологией RAG устраняет этот недостаток, сочетая индексацию страниц по запросу, семантический поиск, сбор доказательств, агента ReAct, который решает, когда проводить поиск, и интерфейс для общения, отвечающий на вопросы на основе найденного текста. Исходные материалы для создания этого решения доступны в разделе agentic-ai wiki RAG sample на репозитории GitHub data-etl-ml.

Почему RAG?

Без механизма поиска путь к информации короткий, но хрупкий:

  User Question
      ↓
      LLM
      ↓
    Answer

Всё зависит от того, что модель запомнила во время обучения.

С использованием RAG доказательства поступают до генерации ответа:

User Question
      ↓
    Retriever
      ↓
Relevant Documents
      ↓
     LLM
      ↓
Grounded Answer

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

Цель проекта

Создать чат-ассистента, который отвечает на вопросы на основе страниц Википедии, которые пользователь выбрал для индексации. Пример запроса:

Please index:
2023 United States banking crisis

Затем задать вопрос:

Which bank experienced the fastest bank run
in US history during 2023?

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

Обзор архитектуры

В общих чертах система выглядит следующим образом:

Wikipedia Pages
        │
        ▼
 WikipediaReader
        │
        ▼
 SentenceSplitter
        │
        ▼
 Embeddings
 BAAI/bge-small-en
        │
        ▼
 VectorStoreIndex
        │
        ▼
 Query Engine
        │
        ▼
 QueryEngineTool
        │
        ▼
 ReAct Agent
        │
        ▼
 Chainlit UI

Важны два потока обработки: поток индексации, создающий поисковый векторный хранилище, и поток запросов, извлекающий фрагменты текста и генерирующий ответы.

Шаг 1: Загрузка ключа API OpenAI

Учетные данные не должны находиться в исходном коде. Избегайте их жесткой привязки:

api_key = "xxxxx"

Вместо этого загружайте данные из файла конфигурации:

def get_apikey():
    with open("apikeys.yml") as file:
        config = yaml.safe_load(file)

    return config["OPENAI_API_KEY"]

Секретные данные остаются отдельно от логики приложения.

Шаг 2: Понимание структуры кода

Проект состоит из трех модулей на Python:

utils.py
index_wikipages.py
chat_agent.py

utils.py загружает ключи API и настройки. index_wikipages.py обрабатывает запросы к страницам, загружает текст Википедии, встраивает его фрагменты и создаёт индексы. chat_agent.py связывает агента ReAct, инструменты для обработки запросов и интерфейс Chainlit.

Шаг 3: Извлечение страниц Википедии с использованием структурированного вывода

Пользователи могут вводить списки в свободной форме:

Please index:
London, Birmingham, New York

Для индексации требуется чистый массив:

[
 "London",
 "Birmingham",
 "New York"
]

Вместо нестабильного разделения строк с помощью операторов разделения, модель Pydantic фиксирует структурированный вывод:

class WikiPageList(BaseModel):
    pages: List[str]

Модель автоматически преобразует естественный язык в список страниц с указанием типов.

Шаг 4: Загрузка страниц Википедии

LlamaIndex поставляет удобный загрузчик:

WikipediaReader

Загрузка данных занимает несколько строк:

loader = WikipediaReader()

documents = loader.load_data(
    pages=["2023 United States banking crisis"]
)

На этом этапе в работу включаются сырые документы страниц.

Шаг 5: Разбиение документов на фрагменты

Модели плохо справляются с большими страницами в виде единого целого. Их необходимо разделить на перекрывающиеся фрагменты:

SentenceSplitter(
    chunk_size=150,
    chunk_overlap=45
)

Перекрытие позволяет сохранить идеи, расположенные на границах между фрагментами:

Chunk A:
---------------------
Paragraph 1
Paragraph 2

Chunk B:
---------------------
Paragraph 2
Paragraph 3

Шаг 6: Создание эмбеддингов

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

BAAI/bge-small-en

Запрос вроде:

"What is Databricks?"

преобразуется в плотный вектор:

[0.21, -0.44, 0.87 ...]

Фрагменты, имеющие семантическую связь, сгруппируются рядом в этом пространстве.

Шаг 7: Создание векторного индекса

LlamaIndex обеспечивает создание структуры хранения:

index = VectorStoreIndex(nodes)

Результатом является векторный индекс в памяти, который может выполнять поиск сходства в следующем формате:

Find chunks similar to:
"fastest bank run in history"

Шаг 8: Создание поисковой системы

Обеспечьте доступ к индексу через движок запросов:

query_engine = index.as_query_engine(
    response_mode="compact",
    similarity_top_k=10,
    verbose=True
)
similarity_top_k = 10

Return 10 most relevant chunks

similarity_top_k определяет, сколько соседних фрагментов будут использоваться для формирования ответа.

Шаг 9: Создание агента ReAct

ReAct означает:

Reason + Act

Примитивный бот сразу переходит от вопроса к ответу:

Question
→ Answer

Агент ReAct включает в свою работу процессы рассуждения и использование инструментов:

Question
↓
Reason
↓
Choose Tool
↓
Observe Output
↓
Answer

Поиск становится динамическим, а не постоянно активным или полностью отключенным.

Создание инструментов

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

QueryEngineTool(
    query_engine=query_engine,
    metadata=ToolMetadata(
        name="Wikipedia"
    )
)

Тогда агент будет знать о наличии возможности поиска в Википедии.

ReAct Loop

The agent internally performs:

Внутри цикл выглядит следующим образом:

Thought:
Need information about the banking crisis.

Action:
Wikipedia Tool

Observation:
Found relevant passages.

Answer:
Grounded response.

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

Шаг 10: Создание интерфейса с помощью Chainlit

Chainlit предоставляет чат-интерфейс с минимальным количеством шаблонного кода. Панель настроек позволяет задавать:

Model
Wikipedia Pages

Пример конфигурации:

MODEL:
gpt-5-nano

Wikipedia Pages:
Please index:
2023 United States banking crisis

Настройки инициализируют векторный индекс до начала диалога.

Демонстрация

После индексации:

2023 United States banking crisis

вопрос вроде:

Which bank experienced the fastest
bank run in US history?

приводит к ответу вроде:

Silicon Valley Bank (SVB)

Approximately $42 billion
was withdrawn in 10 hours.

Цифры берутся из полученных данных, а не являются вымыслом.

Уроки, извлеченные

Что сработало хорошо

LlamaIndex сокращает длину пути индексации:

Documents
→ Nodes
→ Index

Агенты ReAct улучшают принятие решений о моменте получения данных, благодаря чему поиск выполняется только тогда, когда это необходимо. Chainlit по-прежнему остается одним из самых быстрых способов создания рабочего интерфейса чата с ИИ.

Проблемы

Совместимость с Python 3.13 создала проблемы для нескольких комплексов технологий — комбинации Chainlit, Pydantic и LlamaIndex оказались нестабильными. Использование фиксированных версий:

Python 3.11

было гораздо надежнее.

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

Будущие улучшения

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

Keyword Search
+
Semantic Search

Переупорядочивание результатов после первого этапа поиска — получение:

Top 50

Затем сократите их до наилучших вариантов. Цитаты, указывающие на абзацы, стоящие за каждым утверждением. А также постоянная база данных векторов вместо временной:

VectorStoreIndex

с такими вариантами, как Chroma, Pinecone, Weaviate или Milvus.

Заключительные мысли

Этот проект представляет собой краткий обзор современных паттернов агентного программирования: RAG, эмбеддинги, поиск векторов, инструменты ReAct, интерфейс Chainlit и оркестрация LlamaIndex. Стратегическая ценность заключается не в отдельной библиотеке, а в сочетании моделей с механизмами поиска информации, инструментами и циклами рассуждений — а не в стремлении к увеличению количества параметров. Клонируйте пример 6_wiki_rag_react_project из папки agentic-ai проекта data-etl-ml на GitHub, чтобы попробовать всю структуру.