はじめに
IBMの企業向けAIプラットフォーム「watsonx.ai」と、オープンソースのリレーショナルデータベース「PostgreSQL」を組み合わせたRAG (Retrieval-Augmented Generation) システムの構築事例を紹介します。
単にドキュメントを検索して回答するのではなく、「脆弱性レポートを自社のシステム構成に照らし合わせて自動的に影響分析を行い、その結果を加味して回答する」 という、より実践的なRAGシステムを目指しました。
今回の構成
本記事で構築したシステムの全体像は以下の通りです。
- データソース: 脆弱性情報 (CVE) を格納したPostgreSQLデータベース
- AI基盤: IBM watsonx.ai (LLM: Granite / Llama 3, Embedding: Slate)
- AIエージェント: LangChain (Python)
-
ベクトルストア: PostgreSQL (
pgvector拡張を使用)
特徴的な機能のダイジェスト
-
脆弱性DB: 脆弱性レポート情報を格納したPostgres DBを活用。
pgvectorでベクトル検索機能を追加 - 影響分析: RAG検索の前に、watsonx.aiを使って「この脆弱性は自社に影響があるか?」を自動判定し、解析結果を新規列としてDBに保存
- ベクトル検索とRAG: 検索時に、脆弱性レポートのテキストや 「影響スコア (Impact Score)」 と 「分析理由 (Analysis Reason)」 を考慮して検索
実装のステップ
1. 環境構築と依存関係
Python 3.12環境を使用し、必要なライブラリをインストールします。
pip install langchain langchain-community langchain-ibm langchain-postgres psycopg2-binary pgvector
2. データベースの準備 (PostgreSQL)
架空のCVE情報を用意し、CVEおよび脆弱性レポートを格納したPostgreSQLデータベースを準備します。
注意
これらのCVE, 脆弱性レポートは、実際の脆弱性情報ではなく、ダミーデータとして作成されたものです。
3. watsonx.ai による「自動影響分析」
次にPostgreSQLの脆弱性レポートデータに対して、watsonx.aiのLLMを使って各脆弱性を分析します。
「自社はPython/Djangoを使用しているが、Javaは使用していない」といった企業プロファイルをプロンプトに含めることで、自社に関連しそうな脆弱性に対する分析が可能になります。
COMPANY_PROFILE = """
Our company uses the following technology stack:
- Web Framework: Python (Django)
- Database: PostgreSQL
- OS: Linux (Ubuntu)
- We do NOT use Java or Ruby.
"""
prompt = f"""
You are a security analyst. Analyze the following vulnerability report against our company profile.
[Company Profile]
{COMPANY_PROFILE}
[Vulnerability Report]
CVE ID: {cve_id}
Content: {text}
Task:
1. Determine if this vulnerability impacts our company (High/Medium/Low/None).
2. Provide a brief reason.
Output format:
Impact: [High/Medium/Low/None]
Reason: [Reason]
"""
このプロンプトを用いてLLMに推論させると、DB内の脆弱性情報に対してAIが「影響なし(Javaを使っていないため)」などの判断を下してくれます。
4. ベクトル化と保存
分析済みのデータをベクトル化して保存します。
検索時には「分析結果(Impact: Highなど)」もコンテキストに含まれるため、RAGの回答精度が向上します。
IBM Slateモデルはエンコーダー型のモデルで、テキストのEmbeddingタスクに最適なモデルです。
embeddings = WatsonxEmbeddings(
model_id="ibm/slate-30m-english-rtrvr-v2",
url=url,
apikey=api_key,
project_id=project_id
)
vectorstore = PGVector(
embeddings=embeddings,
collection_name="vulnerability_vectors",
connection=connection_string,
use_jsonb=True,
)
vectorstore.add_documents(docs)
実行すると以下のようになり、ベクトル化したものはPostgresDBに保存されていることが確認できました。

5. RAGアプリの実装
最後に、ユーザーからの質問に答えるRAGアプリを作成していきます。
LangChainを用いて実装していきましたが、従来の RetrievalQA チェーンは非推奨となったため、最新の create_retrieval_chain を使用して実装しました。
# rag_app.py (抜粋)
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
# プロンプト定義
prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:
<context>
{context}
</context>
Question: {input}""")
# チェーンの構築
document_chain = create_stuff_documents_chain(llm, prompt)
retriever = vectorstore.as_retriever()
retrieval_chain = create_retrieval_chain(retriever, document_chain)
# 実行
query = "CVE-2023-12345の影響は何ですか?"
result = retrieval_chain.invoke({"input": query})
print(f"Answer: {result['answer']}")
実行結果
実際に動かしてみると、以下のような回答が得られます。
質問: "CVE-2023-12345の影響は何ですか?"
回答: "CVE-2023-12345の影響は、認証されていない攻撃者がデータベース内の機密情報にアクセスしたり、データを改ざんしたりする可能性があることです。"
また、影響分析の結果(「自社には影響あり」など)もコンテキストに含まれているため、自組織に関するより踏み込んだ回答を生成させることも可能です。
まとめ
watsonx.ai と PostgreSQL を組み合わせることで、自組織向けにカスタマイズ可能な拡張性の高いRAGシステムを構築できました。
特に、「LLMを使ってデータを事前にリッチにする(影響分析)」 というアプローチは、RAGの回答品質を底上げする有効な手段です。
今後は、このシステムをAPI化したり、フロントエンドを構築してチャットボットとして利用しやすくするなどの展開が考えられます。
by 高橋哲也(Takahashi Tetsuya)


