本記事は日本オラクルが運営する下記Meetupで発表予定の内容になります。発表までに今後、内容は予告なく変更される可能性があることをあらかじめご了承ください。
はじめに
こちらは以前の記事AgentOpsで変わるAIエージェントの開発と運用の補足記事になります。OCI Generative AI Serviceでは、ユーザーが開発したエージェントを同サービスの中にデプロイすることでマネージド環境で運用することができます。
本サービスには、上図右側に示すように、AIエージェントの開発・運用を効率化するためのさまざまな機能が用意されています。これらのリソースはすべてクラウド上で提供されます。
つまり、ユーザーが開発したAIエージェントや関連リソースは、すべてクラウド側のマネージド環境で運用でき、AIエージェント開発に必要な機能や、煩雑なインフラ管理、運用基盤の実装をクラウドに任せられる点が大きなメリットです。
本記事では、同サービスの多数の機能の中でも「ベクトルストア」にフォーカスし、フルマネージドのRAG(Retrieval-Augmented Generation)を構築するサンプル実装をご紹介します。
構成概要
OCI Generative AI Serviceではフルマネージドのベクトルストアが簡単に作成できます。予め作成したベクトルストアにドキュメントをロードし、そのデータに対するセマンティック検索を実行する処理を作ればRAGの完成です。
この構成では、RAGに必要な下記全てのリソースがOCI Generative AI Serviceの中にマネージドとして実装されていることがポイントになります。これにより、開発コードが簡素化される点と、開発後のエージェントの運用管理がほぼクラウド任せになるという点が最大のメリットということになります。
- LLM : 同サービスで提供されるLLMを利用
- AIエージェント:開発したAIエージェントを同サービスにデプロイすることでマネージドで運用
- Tool : 同サービスで提供されている事前定義済みのセマンティック検索用ツール(file_search)を利用することで開発コードを簡素化
- ベクトルストア: 同サービスで提供されるフルマネージドのベクトルストアを利用することで運用管理を簡素化
サンプルドキュメントとしては下記のような架空の製品に関するPDFファイルを使います。RAGのシナリオとしては「OraBooster」という架空の製品についての質問に答えられるAIエージェントということになります。
繰り返しになりますが、この実装のポイントとしては、RAGに必要なリソース(ベクトルストア、セマンティック検索、LLM、開発したエージェント)が全て同サービスの中で稼働し、完全にマネージド環境で動作しているという点です。これにより、ユーザーはAIエージェントの運用をクラウド任せにすることができます。
実装
まず、こちらの手順でOCI GenAIにプロジェクトを作成し、そのproject idを取得します。このIDを使って、下記のようにGenerative AI ServiceのClientを定義します。
import os
from oci_openai import OciOpenAI, OciUserPrincipalAuth
dp_endpoint = "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130"
cp_endpoint = "https://generativeai.us-chicago-1.oci.oraclecloud.com/20231130"
profile = os.environ.get("OCI_PROFILE", "DEFAULT")
compartment_id = "ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
project_id = "ocid1.generativeaiproject.oc1.us-chicago-1.xxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth = OciUserPrincipalAuth(profile_name=profile)
dp_client = OciOpenAI(
service_endpoint=dp_endpoint,
auth=auth,
compartment_id=compartment_id,
default_headers={"opc-compartment-id": compartment_id},
project=project_id,
)
cp_client = OciOpenAI(
service_endpoint=cp_endpoint,
auth=auth,
compartment_id=compartment_id,
project=project_id,
)
次にベクトルストアを作成します。下記のコードでGenerative AI Serviceの中にフルマネージドのベクトルストアを作成することができます。フルマネージドなのでこのベクトルストアの運用管理はクラウド任せということになります。(この処理はOCIコンソールからWebUIでも実行できます。手順はこちら)
vs = cp_client.vector_stores.create(
name="a-demo-store",
description="Demo vector store",
#expires_after={"anchor": "last_active_at", "days": 30},
metadata={"created_by": "oci-samples"},
)
vector_store_id = vs.id
print(vector_store_id)
ベクトルストアを作成すると、下記のようなIDが付与されるので、このIDを使って後の工程でデータファイルをロードします。
vs_ord_6ugc06qyksh7qgte9d2mkupsc3p5t9j4ug9d3z6h8eznvqpd
ベクトルストアが作成されると、同サービスのクラウドコンソールからも下図のように確認することができます。
この後、ベクトルストアにデータをロードするのですが、その前にこのファイルをGenerative AI Serviceのファイルストレージに一旦アップロードする必要があります。下記コードでアップロードします。(この処理はOCIコンソールからWebUIでも実行できます。手順はこちら)
file_path = "./rocket.pdf"
with open(file_path, "rb") as file_stream:
uploaded_file = dp_client.files.create(
file=file_stream,
purpose="user_data",
extra_headers={
"OpenAI-Project": project_id
}
)
file_id = getattr(uploaded_file, "id", None)
print(file_id)
ファイルストレージにアップロードされたファイルには下記のようにIDが付与されます。このIDを使ってベクトルストアにファイルをロードします。
file-ord-c76224b3-650d-4a54-80db-db93227e90d6
上記のファイルIDとベクトルストアIDを指定し、ベクトルストアにドキュメントデータをロードします。
vs_file = dp_client.vector_stores.files.create(
vector_store_id=vector_store_id,
file_id=file_id
)
上記のコードを実行すると、データロードと共に、チャンキングとベクトル変換が自動的に行われていますので、下記のようにセマンティック検索を実行することができます。(この処理はOCIコンソールからWebUIでも実行できます。手順はこちら)
query = "OraBoosterとは何ですか?"
response = dp_client.vector_stores.search(
vector_store_id=vector_store_id,
query=query,
max_num_results=10,
rewrite_query=False
)
print(response)
「OraBoosterとは何ですか?」という検索に対して、下記のように関連したドキュメントが検索できていることがわかります。(今回はドキュメントが短文だったのでチャンクは一つしか作成されませんでした。)
SyncPage[VectorStoreSearchResponse](
data=[
VectorStoreSearchResponse(
attributes={},
content=[
Content(
text='当社が開発したロケットエンジンであるOraBoosterは、次世代の宇宙探査を支える
先進的な推進技術の象徴です。その独自の設計は、高性能と革新性を融合させ、人類の宇宙
進出を加速させるための革命的な一歩となります。このエンジンの核となるのは、量子ダイ
ナミックス・プラズマ・ブースターです。このブースターは、量子力学の原理に基づいてプ
ラズマを生成し、超高速で加速させます。その結果、従来の化学反応よりもはるかに高い推
力を発生し、遠く離れた惑星や星系への探査を可能にします。さらに、エンジンの外殻には
ナノファイバー製の超軽量かつ超強度の素材が使用されています。この素材は、宇宙空間の
過酷な環境に耐え、高速での飛行中に生じる熱や衝撃からロケットを守ります。また、ハイ
パーフォトン・ジャイロスコープが搭載されており、極めて高い精度でロケットの姿勢を維
持し、目標を追跡します。これにより、長時間にわたる宇宙飛行中でも安定した飛行軌道を
維持し、ミッションの成功を確保します。さらに、バイオニック・リアクション・レスポン
ダーが統合されています。このシステムは、人工知能と生体認識技術を組み合わせ、ロケッ
トの異常な振動や動きを検知し、自己修復機能を活性化します。総じて、この新開発のロケ
ットエンジンは、革新的な技術と未来志向の設計によって、宇宙探査の新たな時代を切り開
くことでしょう。その高い性能と信頼性は、人類の夢を実現するための力強い支援となるこ
とでしょう。',
type='text'
)
],
file_id='file-ord-c76224b3-650d-4a54-80db-db93227e90d6',
filename='rocket.pdf',
score=0.8863518,
additional_properties={
'vector_store_id': 'vs_ord_6ugc06qyksh7qgte9d2mkupsc3p5t9j4ug9d3z6h8eznvqpd',
'chunk_id': '0_ea40b7bc-5047-4d91-8a2b-d91ff1d91eb2',
'page_numbers': [1]
}
)
],
object='vector_store.search_results.page',
has_more=False,
search_query='OraBoosterとは何ですか?'
)
Generative AI ServiceのAPIにはこのセマンティック検索が事前定義された file_search というツールがあります。従って、RAGエージェントを作る際はこの事前定義済のツールを使うとセマンティック検索を用いたRAGが簡単に作れます。
ちょうど、下記のようなコードです。このコードではquery(質問文)、file_searchのツール、ベクトルストアのID、LLMのモデルを指定するだけでRAGを定義しています。
rag_response = dp_client.responses.create(
model="xai.grok-4-1-fast-reasoning",
input=query,
tools=[
{
"type": "file_search",
"vector_store_ids": [vector_store_id]
}
]
)
print(rag_response.output[1].content[0].text)
最終的に生成された応答テキストは下記の通り。
**OraBooster**は、当社が開発した次世代の宇宙探査を支える先進的なロケットエンジンです。高性能と革新性を融合させた独自設計により、人類の宇宙進出を加速させる革命的な推進技術の象徴です。
### 主な特徴:
- **量子ダイナミックス・プラズマ・ブースター**:量子力学の原理に基づきプラズマを生成・超高速加速し、従来の化学反応を上回る高い推力を発揮。遠くの惑星や星系への探査を可能にします。
- **ナノファイバー製外殻**:超軽量かつ超強度の素材で、宇宙空間の過酷な熱や衝撃からロケットを守ります。
- **ハイパーフォトン・ジャイロスコープ**:極めて高い精度で姿勢制御と目標追跡を実現し、長時間の安定飛行を確保。
- **バイオニック・リアクション・レスポンダー**:AIと生体認識技術を組み合わせ、異常振動を検知して自己修復機能を活性化。
これらの革新的技術により、OraBoosterは宇宙探査の新時代を切り開き、人類の夢を力強く支えます。
以上でRAGの完成しましたが、この状態ではこのコードは開発環境に配置されているただのノートブックです。この処理をOCI Generative AI Serviceにデプロイすることで、はじめて全ての処理をフルマネージドで運用することができます。
手順としては下記3ステップとなります。
①ここまでの処理のクライアントとRAGの定義部分だけを抜き出して、FastAPIでウェブサービス化
②コンテナイメージを作成
③コンテナイメージをGenerative AI Serviceにデプロイ
①の「FastAPIでウェブサービス化」のサンプルコードは下記のようになります。
import os
from fastapi import FastAPI, Request
from oci_openai import OciOpenAI, OciUserPrincipalAuth
app = FastAPI()
# ===== OCI設定 =====
dp_endpoint = "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130"
profile = os.environ.get("OCI_PROFILE", "DEFAULT")
compartment_id = "ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxx"
project_id = "ocid1.generativeaiproject.oc1.us-chicago-1.xxxxxxxxxxxxxxxxxxxxxxxxxxx"
vector_store_id = "vs_ord_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth = OciUserPrincipalAuth(profile_name=profile)
client = OciOpenAI(
service_endpoint=dp_endpoint,
auth=auth,
compartment_id=compartment_id,
default_headers={"opc-compartment-id": compartment_id},
project=project_id,
)
# ===== テキスト抽出 =====
def extract_text(response):
for item in response.output:
if item.type == "message":
for content in item.content:
if content.type == "output_text":
return content.text
# ===== エンドポイント =====
@app.post("/chat")
async def chat(request: Request):
body = await request.json()
query = body.get("query")
rag_response = client.responses.create(
model="xai.grok-4-1-fast-reasoning",
input=query,
tools=[
{
"type": "file_search",
"vector_store_ids": [vector_store_id]
}
]
)
answer = extract_text(rag_response)
return {
"query": query,
"answer": answer
}
②、③の具体的な手順は以前の記事AgentOpsで変わるAIエージェントの開発と運用と全く同じです。
以上です。



