Создайте чат-ассистента для Википедии на основе технологии RAG с использованием LlamaIndex и ReAct
По запросу загружаются страницы Википедии, фрагменты встраиваются с помощью небольшого кодера, а агент ReAct вызывает инструмент поисковой системы, чтобы ответы Chainlit основывались на полученных доказательствах.
Введение
Большие языковые модели обладают высокой речевой плавностью, но эта плавность не означает способности определять, является ли ответ точным или актуальным. Они могут выдумывать правдоподобные ложи, когда вопрос выходит за рамки периода обучения или когда уверенность модели превышает наличие доказательств.
Практический чат-ассистент на основе Википедии с технологией 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, чтобы попробовать всю структуру.