自動化された研究アーティファクト — 上流プロジェクトではありません。
このリポジトリは、公開されているGitHub Actionsワークフローの脆弱性の再現に関するラヴァル大学の修士論文のために、自動化ハーネスによって構築された使い捨てのラボです。これは、コミット
2a209b058c60823b57e8b7775b10244ff340eb8b(2025-05-14)時点のtimescale/pgaiの逐語的なスナップショットであり、そのプロジェクト自身のライセンスの下で再配布されています。そのライセンスファイルは、このスナップショットに変更なしで含まれています。上流プロジェクトは関与しておらず、決して標的にはなりません。ここで研究されている脆弱性はすでに公開されています。このリポジトリ内のすべてのシークレットと変数は、ランダムに生成されたダミー値です — 実際の認証情報は存在しません。アクションの参照とランナーイメージは、2025-05-14時点で解決されたものに固定されています。スナップショットに加えられたすべての変更については、ハーネス出力内の
pinning.mdを参照してください。質問や異議がある場合: [email protected]
PostgreSQLを、RAGおよびAgenticアプリケーション向けの堅牢で本番環境対応の検索エンジンに変えるPythonライブラリです。
🔄 PostgreSQLデータとS3ドキュメントからベクトル埋め込みを自動的に作成・同期します。データが変更されると、埋め込みは自動的に更新されます。
🔍 pgvectorとpgvectorscaleによる強力なベクトル検索とセマンティック検索。
🛡️ すぐに本番環境で使用可能: 効率的な埋め込み生成のためのバッチ処理をサポートし、モデルの障害、レート制限、レイテンシの急上昇に対する組み込みの処理を備えています。
🐘 Timescale Cloud、Amazon RDS、Supabaseなどを含む、あらゆるPostgreSQLデータベースで動作します。
基本アーキテクチャ: このシステムは、ユーザーが作成するアプリケーション、PostgreSQLデータベース、およびステートレスなベクトライザーワーカーで構成されています。アプリケーションは、PostgreSQLやS3などのソースからのデータを埋め込むためのベクトライザー設定を定義します。ワーカーはこの設定を読み取り、データキューを埋め込みとチャンク化されたテキストに処理し、結果を書き戻します。その後、アプリケーションはこのデータをクエリして、RAGとセマンティック検索を強化します。
このアーキテクチャの主な強みは、その回復力にあります。アプリケーションによるデータ変更は埋め込みプロセスから分離されているため、埋め込みサービスの障害がコアなデータ操作に影響を与えることはありません。
まず、pgaiパッケージをインストールします。``` pip install pgai
次に、pgaiデータベースコンポーネントをインストールします。これは、ターミナルからCLIを使用して行うか、Pythonアプリケーションコード内でpgai Pythonパッケージを使用して行うことができます。```
# 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がデータの変更に応じて埋め込みを自動的に作成・同期することで、PostgreSQLデータに対するセマンティック検索とRAGをどのように実現するかを説明します。
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/))。
- OpenAI API キー(クイックスタートでは埋め込みに 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)
### ベクトライザーの作成
これはベクトライザーを定義するもので、システムに対して`wiki`テーブルの`text`列から埋め込みをどのように作成するかを指示します。ベクトライザーは`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からバックグラウンドで実行できます。詳細については、[ベクタライザーワーカー](https://github.com/pvharmo2/gha-lab-e8902eccd3/blob/main/docs/vectorizer/worker.md)のドキュメントを参照してください。
### セマンティック検索を使用してWiki記事を検索する
これは、PostgreSQLにおける標準的なpgvectorセマンティック検索です。検索は、ベクタライザーによって作成され、`wiki`テーブルのすべての列に加えて`embedding`列とチャンクテキストを含む`wiki_embedding`ビューに対して実行されます。この関数は、`wiki`テーブルの`text`列全体と、クエリに最も関連性の高いテキストの小さなチャンクの両方を返します。```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()
### LLM を使用した RAG の実行
このコードは、LLM を使用して RAG を実行します。上記で定義した `_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 ライブラリを使用すると、データから生成された埋め込みを操作できます:
ベクター埋め込みは次の用途に使用できます:
また、SQL から直接 LLM モデルを呼び出せる PostgreSQL 拡張機能も提供しています。これは、既存データに対する分類、要約、データ拡充などのユースケースでよく役立ちます。
ベクタライザーは柔軟性とカスタマイズ性を考慮して設計されています。各ベクタライザーは、データから埋め込みを作成するためのパイプラインを定義します。パイプラインは、データに順番に適用される一連のコンポーネントによって定義されます:
埋め込みでサポートされているモデルは次のとおりです:
ベクター埋め込みを作成するだけなら簡単で単純です。課題となるのは、 LLM はある程度信頼性が低く、エンドポイントが断続的な障害やパフォーマンス低下を 示すことです。障害を適切に処理するための重要な点は、主要なデータ変更操作 (INSERT、UPDATE、 DELETE) が埋め込み操作に依存しないようにすることです。そうしないと、エンドポイントが遅い、または失敗するたびに アプリケーションがダウンし、ユーザーエクスペリエンスが損なわれます。
通常、エンドポイントの障害を適切に処理するには、カスタムの MLops パイプラインを実装する必要があります。これには通常、Kafka のようなキューイングシステム、専用のワーカー、およびキューを処理して失敗したリクエストを再試行するためのその他のインフラストラクチャが含まれます。これは多くの作業であり、間違いを犯しやすいものです。
pgai を使用すると、ベクタライザーが埋め込みを管理してくれるため、これらすべてを省略してアプリケーションの構築に集中できます。遭遇する可能性のあるさまざまな障害モードを処理するためのキューイングと再試行ロジックが組み込まれています。この作業はバックグラウンドで行われるため、主要なデータ変更操作は埋め込み操作に依存しません。これが、pgai がそのまま本番環境で使用できる理由です。
多くの専用ベクターデータベースは、ユーザーに代わって埋め込みを作成します。ただし、埋め込みエンドポイントがダウンまたは劣化している場合、通常は失敗し、エラーハンドリングと再試行の負担がユーザーに戻ります。
pgai への貢献を歓迎します!詳細については、貢献ページをご覧ください。
pgai はまだ初期段階にあります。このプロジェクトの方向性を形作るのに今が絶好のタイミングです。 現在、優先順位を決定しているところです。検討中の機能リストをご覧ください。 コメント、リストの拡張、または Discussions フォーラムへの参加は自由です。
始めるには、貢献方法と開発/テスト環境のセットアップ方法をご覧ください。
Timescale は PostgreSQL データベース企業です。詳細については、timescale.com をご覧ください。
Timescale Cloud は、高性能で開発者向けのクラウドプラットフォームであり、最も要求の厳しい AI、時系列、分析、およびイベントワークロード向けの PostgreSQL サービスを提供します。Timescale Cloud は本番アプリケーションに最適で、高可用性、ストリーミングバックアップ、時間経過に伴うアップグレード、ロールと権限、および優れたセキュリティを提供します。