
Лаборатория исследований безопасности: воспроизведение CVE-2025-52467 (выполнение кода в workflow pull_request_target pgai / эксфильтрация GITHUB_TOKEN) — снимок timescale/pgai
Автоматизированный исследовательский артефакт — не вышестоящий проект.
Этот репозиторий — одноразовая лаборатория, созданная автоматизированным конвейером для магистерской диссертации в Université Laval по воспроизведению опубликованных уязвимостей в рабочих процессах GitHub Actions. Это точный снимок
timescale/pgaiна коммите2a209b058c60823b57e8b7775b10244ff340eb8b(2025-05-14), перераспределённый под собственной лицензией этого проекта, файл которой включён без изменений в этот снимок.Вышестоящий проект не участвует, никогда не является целью, а изучаемая здесь уязвимость уже публична. Каждый секрет и переменная в этом репозитории — случайно сгенерированное фиктивное значение — никаких реальных учётных данных здесь нет. Ссылки на действия и образы раннеров закреплены на те значения, которым они соответствовали на 2025-05-14; см.
pinning.mdв выводе конвейера для каждого изменения, внесённого в снимок.Вопросы или возражения: [email protected]
Библиотека на Python, которая превращает PostgreSQL в надёжный, готовый к продакшену механизм поиска для RAG и агентных приложений.
🔄 Автоматическое создание и синхронизация векторных эмбеддингов из данных PostgreSQL и документов S3. Эмбеддинги обновляются автоматически по мере изменения данных.
🔍 Мощный векторный и семантический поиск с помощью pgvector и pgvectorscale.
🛡️ Готовность к продакшену из коробки: поддержка пакетной обработки для эффективной генерации эмбеддингов со встроенной обработкой сбоев моделей, ограничений скорости и скачков задержки.
🐘 Работает с любой базой данных PostgreSQL, включая Timescale Cloud, Amazon RDS, Supabase и другие.
Базовая архитектура: Система состоит из приложения, которое вы пишете, базы данных PostgreSQL и векторных рабочих процессов (vectorizer workers) без сохранения состояния. Приложение определяет конфигурацию векторизатора для встраивания данных из таких источников, как PostgreSQL или S3. Рабочие процессы читают эту конфигурацию, обрабатывают очередь данных в эмбеддинги и разбитый на фрагменты текст, а затем записывают результаты обратно. После этого приложение запрашивает эти данные для обеспечения работы RAG и семантического поиска.
Ключевая сила этой архитектуры — в её устойчивости: изменения данных, вносимые приложением, отделены от процесса создания эмбеддингов, что гарантирует, что сбои в сервисе эмбеддингов не повлияют на основные операции с данными.
Сначала установите пакет pgai.``` pip install pgai
Затем установите компоненты базы данных pgai. Это можно сделать из терминала с помощью CLI или в коде вашего Python-приложения, используя Python-пакет pgai.```
# from the cli
pgai install -d <database-url>
# or from the python package, often done as part of your application setup
import pgai
pgai.install(DB_URL)
Этот краткий обзор демонстрирует, как pgai Vectorizer обеспечивает семантический поиск и RAG по данным PostgreSQL, автоматически создавая и синхронизируя эмбеддинги по мере изменения данных.
Ключевой «секретный ингредиент» pgai Vectorizer — это декларативный подход к генерации эмбеддингов. Просто определите свой конвейер, и Vectorizer возьмёт на себя операционную сложность поддержания эмбеддингов в синхронизированном состоянии, даже когда эндпоинты эмбеддингов ненадёжны. Простую версию конвейера можно определить следующим образом:```sql CREATE TABLE IF NOT EXISTS wiki ( id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, url TEXT NOT NULL, title TEXT NOT NULL, text TEXT NOT NULL )
SELECT ai.create_vectorizer( 'wiki'::regclass, loading => ai.loading_column(column_name=>'text'), destination => ai.destination_table(target_table=>'wiki_embedding_storage'), embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536') )
Векторизатор автоматически создаст эмбеддинги для всех строк в таблице
`wiki` и, что более важно, будет поддерживать эмбеддинги синхронизированными с
базовыми данными по мере их изменения. **Думайте об этом почти как об объявлении индекса** для
таблицы `wiki`, но вместо того, чтобы база данных управляла структурой данных индекса
за вас, эмбеддингами управляет Vectorizer.
## Запуск краткого руководства
**Предварительные требования:**
- База данных PostgreSQL ([инструкции по Docker](https://docs.timescale.com/self-hosted/latest/install/installation-docker/)).
- Ключ API OpenAI (в кратком руководстве мы используем openai для эмбеддинга, но вы можете использовать [несколько провайдеров](#supported-embedding-models)).
Создайте файл `.env` со следующим содержимым:```
OPENAI_API_KEY=<your-openai-api-key>
DB_URL=<your-database-url>
Вы можете скачать полный python-код и requirements.txt из примера быстрого старта и запустить его в той же директории, где находится файл .env.
Pgai требует установки в базу данных нескольких таблиц каталога и функций. Это выполняется с помощью функции pgai.install, которая устанавливает необходимые компоненты в схему ai базы данных.```python
pgai.install(DB_URL)
### Создание векторизатора
Это определяет векторизатор, который сообщает системе, как создавать эмбеддинги из столбца `text` в таблице `wiki`. Векторизатор создает представление `wiki_embedding`, которое мы можем запрашивать для получения эмбеддингов (как мы увидим ниже).```python
async def create_vectorizer(conn: psycopg.AsyncConnection):
async with conn.cursor() as cur:
await cur.execute("""
SELECT ai.create_vectorizer(
'wiki'::regclass,
if_not_exists => true,
loading => ai.loading_column(column_name=>'text'),
embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536'),
destination => ai.destination_table(view_name=>'wiki_embedding')
)
""")
await conn.commit()
В этом примере мы запускаем воркер векторизатора один раз, чтобы создать эмбеддинги для существующих данных.```python worker = Worker(DB_URL, once=True) worker.run()
В реальном приложении мы не вызывали бы воркер вручную каждый раз, когда нужно создать эмбеддинги. Вместо этого мы запускали бы воркер в фоновом режиме, и он работал бы непрерывно, опрашивая вектортайзер на предмет новых задач.
Вы можете запустить воркер в фоновом режиме из приложения, через CLI или Docker. Подробнее см. в документации [vectorizer worker](https://github.com/pvharmo2/gha-lab-e8902eccd3/blob/main/docs/vectorizer/worker.md).
### Поиск статей вики с помощью семантического поиска
Это стандартный семантический поиск pgvector в PostgreSQL. Поиск выполняется по представлению `wiki_embedding`, которое создаётся вектортайзером и включает все столбцы из таблицы `wiki`, а также столбец `embedding` и текст чанков. Эта функция возвращает как весь столбец `text` из таблицы `wiki`, так и более мелкие фрагменты текста, наиболее релевантные запросу.```python
@dataclass
class WikiSearchResult:
id: int
url: str
title: str
text: str
chunk: str
distance: float
async def _find_relevant_chunks(client: AsyncOpenAI, query: str, limit: int = 1) -> List[WikiSearchResult]:
# Generate embedding for the query using OpenAI's API
response = await client.embeddings.create(
model="text-embedding-ada-002",
input=query,
encoding_format="float",
)
embedding = np.array(response.data[0].embedding)
# Query the database for the most similar chunks using pgvector's cosine distance operator (<=>)
async with pool.connection() as conn:
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
SELECT w.id, w.url, w.title, w.text, w.chunk, w.embedding <=> %s as distance
FROM wiki_embedding w
ORDER BY distance
LIMIT %s
""", (embedding, limit))
return await cur.fetchall()
Этот код примечателен тем, чего он не делает. Это простое добавление новой статьи в таблицу wiki. Нам не нужно было делать ничего особенного для создания эмбеддингов — воркер-векторизатор позаботится об обновлении эмбеддингов по мере изменения данных.```python
def insert_article_about_pgai(conn: psycopg.AsyncConnection):
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
INSERT INTO wiki (url, title, text) VALUES
('https://en.wikipedia.org/wiki/pgai', 'pgai', 'pgai is a Python library that turns PostgreSQL into the retrieval engine behind robust, production-ready RAG and Agentic applications. It does this by automatically creating vector embeddings for your data based on the vectorizer you define.')
""")
await conn.commit()
### Выполнение RAG с помощью LLM
Этот код выполняет RAG с помощью LLM. Он использует функцию `_find_relevant_chunks`, определённую выше, для поиска наиболее релевантных фрагментов текста из таблицы `wiki`, а затем использует LLM для генерации ответа.```python
query = "What is the main thing pgai does right now?"
relevant_chunks = await _find_relevant_chunks(client, query)
context = "\n\n".join(
f"{chunk.title}:\n{chunk.text}"
for chunk in relevant_chunks
)
prompt = f"""Question: {query}
Please use the following context to provide an accurate response:
{context}
Answer:"""
response = await client.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: prompt }],
})
print("RAG response:")
print(response.choices[0].message.content)
Ознакомьтесь с другими краткими руководствами:
Узнайте больше о векторизаторе:
Наша библиотека pgai Python позволяет работать с эмбеддингами, созданными из ваших данных:
Вы можете использовать векторные эмбеддинги для:
Мы также предлагаем расширение PostgreSQL, которое может выполнять вызовы LLM-моделей непосредственно из SQL. Это часто полезно для таких случаев, как классификация, суммаризация и обогащение данных на ваших существующих данных.
Векторизатор спроектирован гибким и настраиваемым. Каждый векторизатор определяет конвейер для создания эмбеддингов из ваших данных. Конвейер определяется серией компонентов, которые последовательно применяются к данным:
Для встраивания поддерживаются следующие модели:
Простое создание векторных эмбеддингов — это легко и просто. Сложность в том, что LLM несколько ненадёжны, а конечные точки демонстрируют периодические сбои и/или сниженную производительность. Критически важная часть правильной обработки сбоев заключается в том, что ваши основные операции модификации данных (INSERT, UPDATE, DELETE) не должны зависеть от операции встраивания. В противном случае ваше приложение будет недоступно каждый раз, когда конечная точка медленная или выходит из строя, и ваш пользовательский опыт пострадает.
Обычно для правильной обработки сбоев конечных точек вам потребуется реализовать собственный конвейер MLOps. Это часто включает систему очередей, такую как Kafka, специализированные рабочие процессы и другую инфраструктуру для обработки очереди и повторных попыток неудачных запросов. Это много работы, и легко ошибиться.
С pgai вы можете пропустить всё это и сосредоточиться на создании своего приложения, потому что векторизатор управляет эмбеддингами за вас. Мы встроили логику очередей и повторных попыток для обработки различных режимов сбоев, с которыми вы можете столкнуться. Поскольку мы выполняем эту работу в фоновом режиме, основные операции модификации данных не зависят от операции встраивания. Именно поэтому pgai готов к продакшену из коробки.
Многие специализированные векторные базы данных создают эмбеддинги за вас. Однако они обычно выходят из строя, когда конечные точки встраивания недоступны или деградируют, перекладывая бремя обработки ошибок и повторных попыток обратно на вас.
Мы приветствуем вклад в pgai! См. страницу Вклад в проект для получения дополнительной информации.
pgai всё ещё находится на ранней стадии. Сейчас отличное время, чтобы помочь сформировать направление этого проекта; мы в настоящее время определяем приоритеты. Посмотрите на список функций, над которыми мы думаем работать. Не стесняйтесь комментировать, расширять список или присоединяться к форуму Discussions.
Чтобы начать, ознакомьтесь с тем, как внести вклад и тем, как настроить среду разработки/тестирования.
Timescale — это компания, занимающаяся базами данных PostgreSQL. Чтобы узнать больше, посетите timescale.com.
Timescale Cloud — это высокопроизводительная, ориентированная на разработчиков облачная платформа, которая предоставляет сервисы PostgreSQL для самых требовательных нагрузок AI, временных рядов, аналитики и событий. Timescale Cloud идеально подходит для производственных приложений и обеспечивает высокую доступность, потоковые резервные копии, обновления с течением времени, роли и разрешения, а также отличную безопасность.