OceanBaseデータベースは、ベクトル型データの格納、ベクトルインデックス、そしてembeddingベクトル検索機能を提供します。これにより、ベクトル化したデータをOceanBaseデータベースに保存し、次の検索処理で利用できるようになります。
Firecrawl は、開発者があらゆるウェブサイトから高品質なデータを取得し、AIアプリケーションの構築に活用できるツールです。このツールは、高度なWebスクレイピング、クローラー、データ抽出機能を備えており、ウェブコンテンツを効率的にクリーンなマークアップ言語や構造化データに変換し、下流のAIワークフローの要件を満たせます。
本チュートリアルでは、OceanBaseとFirecrawlを使用して検索拡張型生成(RAG)パイプラインを構築する方法を紹介します。このパイプラインは、ネットワークデータのスクレイピングにFirecrawl、ベクトルストレージにOceanBase、洞察に富んだ文脈認識型応答の生成にJina AIを統合したものです。
前提条件
OceanBaseデータベースV4.4.0以降のバージョンをデプロイし、MySQLモードのテナントを作成していること。テナントの作成後、以下の手順を参照して操作してください。
環境に使用可能なMySQLテナント、MySQLデータベース、およびデータベースアカウントが既に存在し、データベースアカウントに読み書き権限が付与されていること。
Python 3.11以降のバージョンをインストールしていること。
依存関係をインストールしていること。
python3 -m pip install firecrawl-py pyobvector requests tqdmインスタンスで
ob_vector_memory_limit_percentageパラメータを設定し、ベクトル検索機能を有効にしていることを確認してください。推奨設定値は30です。このパラメータをより正確に設定する必要がある場合は、ob_vector_memory_limit_percentageを参照してこの値を計算してください。
ステップ1:データベース接続情報を取得する
OceanBaseデータベースのデプロイ担当者または管理者から、該当するデータベース接続文字列を取得します。例:
obclient -h$host -P$port -u$user_name -p$password -D$database_name
パラメータ説明:
$host:OceanBaseデータベースへの接続IPアドレス。OceanBaseデータベースプロキシ(OceanBase Database Proxy、ODP)接続方式ではODPアドレスを使用し、直接接続方式ではOBServerノードのIPアドレスを使用します。$port:OceanBaseデータベースへの接続ポート。ODP接続方式のデフォルトポートは2883で、ODPデプロイ時にカスタマイズ可能です。直接接続方式のデフォルトポートは2881で、OceanBaseデータベースのデプロイ時にカスタマイズ可能です。$database_name:アクセス対象のデータベース名。注意
テナントに接続するユーザーは、データベースに対する
CREATE、INSERT、DROP、およびSELECT権限が付与されていなければなりません。その他のユーザー権限の詳細については、MySQLモードの権限分類を参照してください。$user_name:テナントの接続アカウント。ODP接続の一般的な形式:ユーザー名@テナント名#クラスタ名またはクラスタ名:テナント名:ユーザー名。直接接続方式の形式:ユーザー名@テナント名。$password:アカウントのパスワード。
その他の接続文字列の詳細については、OBClientを使用したOceanBaseテナントへの接続を参照してください。
ステップ2:AIアシスタントを構築する
Firecrawlを使用してウェブページの情報を取得し、OceanBase Vectorに保存して検索を実行します。
環境変数の設定
Firecrawl APIキーを取得し、OceanBaseの接続情報と共に環境変数に設定します。
export OCEANBASE_DATABASE_URL=YOUR_OCEANBASE_DATABASE_URL
export OCEANBASE_DATABASE_USER=YOUR_OCEANBASE_DATABASE_USER
export OCEANBASE_DATABASE_DB_NAME=YOUR_OCEANBASE_DATABASE_DB_NAME
export OCEANBASE_DATABASE_PASSWORD=YOUR_OCEANBASE_DATABASE_PASSWORD
export FIRECRAWL_API_KEY=YOUR_FIRECRAWL_API_KEY
export JINAAI_API_KEY=YOUR_JINAAI_API_KEY
サンプルコード
FirecrawlによるOceanBase公式Webサイトのクロール
import os ,requests
from firecrawl import FirecrawlApp
from sqlalchemy import Column, Integer, String
from pyobvector import ObVecClient, VECTOR, IndexParam, cosine_distance
from tqdm import tqdm
def split_markdown_content(content):
return [section.strip() for section in content.split("# ") if section.strip()]
app = FirecrawlApp(api_key=os.environ["FIRECRAWL_API_KEY"])
# Scrape a website:
scrape_status = app.scrape(
url="https://en.oceanbase.com/docs/common-oceanbase-database-10000000001970957",
formats=["markdown"]
)
markdown_content = scrape_status.markdown
# Process the scraped markdown content
sections = split_markdown_content(markdown_content)
Jina AIのベクトルを取得する
Jina AIはさまざまなモデルを提供しており、ユーザーは自身のニーズに応じて対応するモデルの利用を選択できます。 ここでは、jina-embeddings-v3を例に、Jina AIのAPIを呼び出すための補助関数generate_embeddingsを定義します。
JINAAI_API_KEY = os.getenv('JINAAI_API_KEY')
def generate_embeddings(text: str):
JINAAI_API_URL = 'https://api.jina.ai/v1/embeddings'
JINAAI_HEADERS = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {JINAAI_API_KEY}'
}
JINAAI_REQUEST_DATA = {
'input': [text],
'model': 'jina-embeddings-v3' # with dimension 1024.
}
response = requests.post(JINAAI_API_URL, headers=JINAAI_HEADERS, json=JINAAI_REQUEST_DATA)
return response.json()['data'][0]['embedding']
data = []
for i, section in enumerate(tqdm(sections, desc="Processing sections")):
try:
embedding = generate_embeddings(section)
truncated_content = section[:4900] if len(section) > 4900 else section
data.append({"content": truncated_content, "content_vec": embedding})
except Exception as e:
print(f"Error processing section {i}: {e}")
continue
ベクトルテーブル構造の定義とベクトルのOceanBaseへの格納
firecrawl_oceanbase_demo_documents という名前のテーブルを作成し、テキストを格納する content 列、ベクトルを格納する content_vec 列、およびベクトルインデックス情報を含めます。
OCEANBASE_DATABASE_URL = os.getenv('OCEANBASE_DATABASE_URL')
OCEANBASE_DATABASE_USER = os.getenv('OCEANBASE_DATABASE_USER')
OCEANBASE_DATABASE_DB_NAME = os.getenv('OCEANBASE_DATABASE_DB_NAME')
OCEANBASE_DATABASE_PASSWORD = os.getenv('OCEANBASE_DATABASE_PASSWORD')
client = ObVecClient(uri=OCEANBASE_DATABASE_URL, user=OCEANBASE_DATABASE_USER,password=OCEANBASE_DATABASE_PASSWORD,db_name=OCEANBASE_DATABASE_DB_NAME)
table_name = "firecrawl_oceanbase_demo_documents"
client.drop_table_if_exist(table_name)
cols = [
Column("id", Integer, primary_key=True, autoincrement=True),
Column("content", String(5000), nullable=False),
Column("content_vec", VECTOR(1024))
]
# Create vector index
vector_index_params = IndexParam(
index_name="idx_content_vec",
field_name="content_vec",
index_type="HNSW",
distance_metric="cosine"
)
client.create_table_with_index_params(
table_name=table_name,
columns=cols,
vidxs=[vector_index_params]
)
print('- Inserting Data to OceanBase...')
client.insert(table_name, data=data)
セマンティック検索
Jina AIのAPIを使用してクエリテキストのベクトルを生成し、その後、クエリテキストのベクトルとベクトルテーブル内の各ベクトルとのコサイン距離に基づいて、最も関連性の高いドキュメントを検索します。
query = 'what is OceanBase High compatibility'
# Generate the embedding for the query via Jina AI API.
query_embedding = generate_embeddings(query)
res = client.ann_search(
table_name,
vec_data=query_embedding,
vec_column_name="content_vec",
distance_func=cosine_distance, # コサイン距離関数を使用
with_dist=True,
topk=1,
output_column_names=["id", "content"],
)
print('- The Most Relevant Document and Its Distance to the Query:')
for row in res.fetchall():
print(f'- ID: {row[0]}\n'
f' content: {row[1]}\n'
f' distance: {row[2]}')
期待される結果
- ID: 5
content: High compatibility
OceanBase Database is highly compatible with most general features of Oracle and MySQL, and supports advanced features such as procedural language and triggers. OceanBase Migration Service (OMS), an automatic migration tool, is provided to support migration assessment and reverse synchronization to ensure data migration security when a core system is migrated to OceanBase Database in key industries such as finance, public governance, and communication service.
##
distance: 0.2341035693195166