RAG(Retrieval-Augmented Generation)は、自社ドキュメントや DB のデータを AI に参照させて回答させる技術です。
「ChatGPT は自社の製品情報を知らない」という問題を解決できます。
本記事では Rails + PostgreSQL(pgvector 拡張)+ RubyLLM を使った RAG 実装を解説します。
RAG とは
RAG の流れはシンプルです。
ユーザーの質問
→ 質問をベクトル化(Embedding)
→ DB で類似ドキュメントを検索
→ 検索結果 + 質問を LLM に渡す
→ AI が回答を生成LLM のファインチューニングが不要で、データを追加・更新するだけで最新情報に対応できます。
pgvector のセットアップ
まず PostgreSQL に pgvector 拡張を追加します。
# Gemfile
gem 'neighbor'
gem 'ruby_llm'bundle install
bin/rails generate neighbor:vectorドキュメントテーブルのマイグレーションを作成します。
bin/rails generate migration CreateDocuments title:string content:text# db/migrate/XXXXXX_create_documents.rb
class CreateDocuments < ActiveRecord::Migration[8.0]
def change
create_table :documents do |t|
t.string :title
t.text :content
t.vector :embedding, limit: 1536 # OpenAI text-embedding-3-small の次元数
t.timestamps
end
add_index :documents, :embedding, using: :ivfflat,
opclass: :vector_l2_ops
end
endbin/rails db:migrateモデルに Embedding を組み込む
ドキュメント保存時に自動でベクトルを生成します。
class Document < ApplicationRecord
has_neighbors :embedding
before_save :generate_embedding
private
def generate_embedding
return if content.blank?
result = RubyLLM.embed(content, model: 'text-embedding-3-small')
self.embedding = result.vectors
end
end類似ドキュメント検索
ユーザーの質問をベクトル化して、近いドキュメントを取得します。
def find_relevant_docs(query, limit: 3)
query_embedding = RubyLLM.embed(query, model: 'text-embedding-3-small').vectors
Document.nearest_neighbors(:embedding, query_embedding, distance: 'cosine').limit(limit)
endRAG で回答を生成
取得したドキュメントをコンテキストとして LLM に渡します。
def ask_with_rag(question)
docs = find_relevant_docs(question)
context = docs.map { |d| "#{d.title}:
#{d.content}" }.join("
")
prompt = <<~TEXT
以下の情報を参考に質問に答えてください。
#{context}
質問: #{question}
TEXT
chat = RubyLLM.chat(model: 'claude-sonnet-4-6')
chat.ask(prompt).content
endまとめ
pgvector + RubyLLM の組み合わせで、完全にオンプレ・自社データで動く AI チャットが実装できます。
ドキュメントを DB に追加するだけで AI の知識が更新されるので、社内 FAQ や製品マニュアルへの Q&A 機能として非常に実用的です。