0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで最も簡単なRAG入門 (PostgreSQL + pgvector)

Last updated at Posted at 2025-08-30

LLMのRAGとは、Retrieval-Augmented Generation(検索拡張生成)の略称で、大規模言語モデル(LLM)の応答精度を向上させるための技術です🤖

RAGは、LLMが学習データにない最新情報や特定の知識を必要とする質問に答える際に特に役立ちます。

この記事では、Ubuntu22.04 + PostgreSQL(pgvector)でベクトルDBを簡単に構築する手順と、そのベクトルDBを活用して、Pythonで最も簡単なRAGを試したいと思います。

RAG処理の全体の流れ

  1. 外部知識をベクトル化してベクトルDBに保存
    文書や FAQ、ナレッジ記事を embedding(数値ベクトル)化
  2. ユーザー入力をベクトル化する
    クエリも embedding に変換
  3. 類似検索(ベクトルDB)で関連文書を取得
    pgvectorで近い文書を検索
    コサイン類似度や L2 距離で上位 N 件を取得
  4. 取得した文書を Transformer に入力
目次

1. PostgreSQL + pgvectorでベクトルDBの構築
2. PythonでベクトルDBを利用してRAGを実行

1.PostgreSQL + pgvectorでベクトルDBの構築

1-1.pgvector をインストール

$ make --version
GNU Make 4.3
$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
$ sudo systemctl status postgresql
$ psql --version
psql (PostgreSQL) 14.15 (Ubuntu 14.15-0ubuntu0.22.04.1)
$ sudo apt install postgresql-server-dev-14

$ git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git
$ cd pgvector
$ make
$ sudo make install

1-2.PostgreSQL にログインして拡張を有効化

$ sudo -u postgres psql

postgres=# CREATE EXTENSION vector;
CREATE EXTENSION

1-3.ベクトル型のテーブル作成

3次元ベクトルのテーブルを作成する。※OpenAIだと1536次元

CREATE TABLE items (
    id SERIAL PRIMARY KEY,
    name TEXT,
    embedding VECTOR(3)
);

1-4.データ挿入

postgres=# INSERT INTO items (name, embedding) VALUES
('猫', '[0.1, 0.2, 0.3]'),
('犬', '[0.2, 0.1, 0.4]'),
('車', '[0.9, 0.8, 0.7]');

このベクトルの数値は、

  • 1つの次元が「動物 vs. 乗り物」軸
  • 別の次元が「猫っぽさ vs. 犬っぽさ」軸
  • もう1つの次元が「かわいい度合い」
    などのように特徴軸を表します

1-5.類似検索

postgres=# SELECT id, name, embedding
FROM items
ORDER BY embedding <=> '[0.1, 0.2, 0.25]'   -- クエリベクトル
LIMIT 2;

id | name | embedding
----+------+---------------
1 | 猫 | [0.1,0.2,0.3]
2 | 犬 | [0.2,0.1,0.4]
(2 rows)

猫が最も近いと出てきてますね。いい感じです。

2.PythonでベクトルDBを利用してRAGを実行

2-1.psql側の準備

OpenAIの1536次元ベクトルで作成します。

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT NOT NULL,
    embedding VECTOR(1536) 
);

2-2.Pythonで実行

import os
import psycopg2
from openai import OpenAI

DB_CONFIG = {
    "dbname": os.getenv("DB_NAME"),
    "user": os.getenv("DB_USER"),
    "password": os.getenv("DB_PASSWORD"),
    "host": os.getenv("DB_HOST", "localhost"),
    "port": os.getenv("DB_PORT", 5432)
}

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

def embed_text(text):
    resp = client.embeddings.create(
        model="text-embedding-ada-002",
        input=text
    )
    return resp.data[0].embedding

def insert_document(content):
    """文書をベクトル化して DB に保存"""
    vector = embed_text(content)
    conn = psycopg2.connect(**DB_CONFIG)
    cur = conn.cursor()
    cur.execute(
        "INSERT INTO documents (content, embedding) VALUES (%s, %s)",
        (content, vector)
    )
    conn.commit()
    cur.close()
    conn.close()

def search_documents(query, top_k=3):
    """クエリ embedding でベクトルDB検索"""
    q_vector = embed_text(query)
    conn = psycopg2.connect(**DB_CONFIG)
    cur = conn.cursor()
    cur.execute(f"""
        SELECT content
        FROM documents
        ORDER BY embedding <=> %s::vector
        LIMIT %s
    """, (q_vector, top_k))
    results = [r[0] for r in cur.fetchall()]
    cur.close()
    conn.close()
    return results

def generate_answer(query):
    related_docs = search_documents(query)
    context = "\n".join(related_docs)
    prompt = f"以下の文脈を参考にして質問に答えてください。\n\n文脈:\n{context}\n\n質問: {query}\n回答:"

    completion = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": prompt}
        ]
    )
    return completion.choices[0].message.content

if __name__ == "__main__":
    # 文書の挿入例
    insert_document("Pythonは高水準のプログラミング言語です。")
    insert_document("PostgreSQLはオープンソースのリレーショナルデータベースです。")
    insert_document("OpenAIはAI研究と展開を行う企業です。")

    # 質問応答の例
    question = "Pythonとは何ですか?"
    answer = generate_answer(question)
    print("質問:", question)
    print("回答:", answer)

実行結果
$ python3 rag.py
質問: Pythonとは何ですか?
回答: Pythonは高水準のプログラミング言語です。

おおおお、いい感じ!

まとめ

今回は、psqlにpgvectorでvectorを拡張して、PythonでRAGを実行する手順を紹介しました。

なお、LangChainを使うことで、RAGを簡単に実装することもできます。参考までにLangChainを使ったRAGのサンプルも載せておきます。

import os
from dotenv import load_dotenv
from langchain_openai import OpenAI
from langchain.chains import RetrievalQA
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings

load_dotenv()

api_key = os.getenv("OPENAI_API_KEY")

embeddings = OpenAIEmbeddings(api_key=api_key)

docs = [
    "LangChainは、LLMを活用したアプリ開発を効率化するフレームワークです。",
    "RAGは、外部の知識を検索してLLMに渡すことで精度の高い応答を生成する手法です。",
    "FAISSはベクトル検索用の高速ライブラリで、LangChainでRAGを実装する際によく使われます。"
]

vectorstore = FAISS.from_texts(docs, embeddings)

llm = OpenAI(temperature=0.7, api_key=api_key)

qa = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever()
)

question = "RAGとは何ですか?"
answer = qa.run(question)
print("質問:", question)
print("回答:", answer)
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?