OpenAIは、人工知能企業であり、これまでに複数の大規模言語モデルを開発しています。これらのモデルは、自然言語の理解や生成において優れた性能を発揮し、テキストの生成、質問への回答、対話などを行うことができます。これらのモデルはAPIを介してアクセスすることが可能です。
OceanBaseデータベースは、バージョンV4.3.3からベクトル型データの格納、ベクトルインデックス、そして埋め込み(embedding)ベクトル検索機能をサポートしています。OpenAIのAPIを利用して、ベクトル化されたデータをOceanBaseデータベースに格納し、OceanBaseのベクトル検索機能を使用して関連するデータを検索します。
前提条件
OceanBaseデータベースV4.3.3以降のバージョンがデプロイ済みで、MySQLモードのテナントが作成されていること。テナントの作成の後、以下の手順を参照して操作します。
ご利用の環境には、既に利用可能なMySQLテナント、MySQLデータベース、およびアカウントが存在し、データベースアカウントには読み書き権限が付与されていること。
Python 3.9以降のバージョンと対応するpipをインストールします。
poetry、pyobvectorとDashScope SDKをインストールします。
python3 pip install poetry python3 pip install pyobvector python3 pip install openaiOpenAI APIキーを準備します。
ベクトル検索機能を有効にするには、テナントで
ob_vector_memory_limit_percentage構成パラメータが設定されていることを確認してください。V4.3.5 BP3より前のバージョンでは、この値を30に設定することを推奨します。V4.3.5 BP3以降のバージョンでは、デフォルト値である0のままにしておくことを推奨します。より正確にこのパラメータを設定する必要がある場合は、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テナントに接続するを参照してください。
例:
obclient -hxxx.xxx.xxx.xxx -P2881 -utest_user001@mysql001 -p****** -Dtest
ステップ2:OpenAIのアカウントに登録する
OpenAI APIキーを取得する:
OpenAIプラットフォームにログインします。
右上のAPI Keysをクリックします。
Create API Keyをクリックします。
関連情報を入力し、Create API Keyをクリックします。
OpenAI APIキーを環境変数に設定する:
Unix系のOS(Ubuntu、macOSなど)では、ターミナルで以下のコマンドを実行します。
export OPENAI_API_KEY='your-api-key'Windowsの場合、コマンドプロンプトで以下のコマンドを実行します。
set OPENAI_API_KEY=your-api-key
コマンド内のyour-api-keyの部分は、ご自身のQwen APIキーに置き換えてください。
ステップ3:OceanBaseデータベースにベクトルデータを保存する
OceanBaseデータベースにベクトルデータをストレージする
テストデータの準備
ベクトル化済みデータを含むテスト用のCSVファイルをダウンロードします。このCSVファイルには、1000件のグルメレビューが含まれており、最終列にはあらかじめ計算されたベクトルデータが格納されているため、通常はこのまま使用できます。ご自身でベクトルを生成したい場合は、以下のコードを使って
embedding列(ベクトル列)を再計算し、新しいCSVファイルを生成できます。from openai import OpenAI import pandas as pd input_datapath = "./fine_food_reviews.csv" client = OpenAI() ## ここでは、text_embedding_v1埋め込みモデルを使用しています。必要に応じて変更可能です。 def embedding_text(text, model="text-embedding-ada-002"): # ベクトル埋め込みの方法については、以下を参照してください:https://community.openai.com/t/embeddings-api-documentation-needs-to-updated/475663 res = client.embeddings.create(input=text, model=model) return res.data[0].embedding df = pd.read_csv(input_datapath, index_col=0) # 実際の生成には数分かかる場合があります。Qwen Embedding APIを1行ずつ呼び出します df["embedding"] = df.combined.apply(embedding_text) output_datapath = './fine_food_reviews_self_embeddings.csv' df.to_csv(output_datapath)以下のスクリプトを実行して、テストデータをOceanBaseデータベースに挿入します。このスクリプトは、上記で準備したCSVファイルと同じディレクトリに配置して実行してください。
import os
import sys
import csv
import json
from pyobvector import *
from sqlalchemy import Column, Integer, String
# pyobvectorを使用してOceanBaseに接続する際、ユーザー名やパスワードに「@」が含まれる場合は、「%40」に置き換えてください。
client = ObVecClient(uri="host:port", user="username",password="****",db_name="test")
# 事前に準備されたテストデータセットは、ベクトル化されており、デフォルトでPythonスクリプトと同じディレクトリ内に配置されています。ご自身で再度ベクトルを生成した場合は、対応するファイルに置き換える必要があります。
file_name = "fine_food_reviews.csv"
file_path = os.path.join("./", file_name)
# テーブルの列を定義します。ベクトルデータを含む'embedding'列は最後に配置します。
cols = [
Column('id', Integer, primary_key=True, autoincrement=False),
Column('product_id', String(256), nullable=True),
Column('user_id', String(256), nullable=True),
Column('score', Integer, nullable=True),
Column('summary', String(2048), nullable=True),
Column('text', String(8192), nullable=True),
Column('combined', String(8192), nullable=True),
Column('n_tokens', Integer, nullable=True),
Column('embedding', VECTOR(1536))
]
# テーブル名
table_name = 'fine_food_reviews'
# テーブルが存在しない場合、新規でテーブルを作成します
if not client.check_table_exists(table_name):
client.create_table(table_name,columns=cols)
# ベクトル列のインデックスを作成します
client.create_index(
table_name=table_name,
is_vec_index=True,
index_name='vidx',
column_names=['embedding'],
vidx_params='distance=l2, type=hnsw, lib=vsag',
)
## CSVファイルを開いてデータを読み込みます
with open(file_name, mode='r', newline='', encoding='utf-8') as csvfile:
csvreader = csv.reader(csvfile)
# ヘッダー行を読み込みます
headers = next(csvreader)
print("Headers:", headers)
batch = [] # データを保存し、10行ごとにまとめてデータベースに挿入します
for i, row in enumerate(csvreader):
# CSVファイルには9つのフィールドがあります:id,product_id,user_id,score,summary,text,combined,n_tokens,embedding
if not row:
break
food_review_line= {'id':row[0],'product_id':row[1],'user_id':row[2],'score':row[3],'summary':row[4],'text':row[5],\
'combined':row[6],'n_tokens':row[7],'embedding':json.loads(row[8])}
batch.append(food_review_line)
# 10行たまったら一括で挿入します。
if (i + 1) % 10 == 0:
client.insert(table_name,batch)
batch = [] # キャッシュをクリア
## 最後に、10行に満たない残りのデータを挿入します。
if batch:
client.insert(table_name,batch)
# テーブル内の総件数をカウントし、すべてのデータが正しく挿入されたことを確認します。
count_sql = f"select count(*) from {table_name};"
cursor = client.perform_raw_text_sql(count_sql)
result = cursor.fetchone()
print(f"インポートされたデータの総件数:{result[0]}")
OceanBaseデータベースのデータをクエリします
以下の内容で
openAIQuery.pyという名前のファイルを作成・保存します。import os import sys import csv import json from pyobvector import * from sqlalchemy import func from openai import OpenAI # コマンドライン引数を取得する if len(sys.argv) != 2: print("検索キーワードを入力してください。") sys.exit() queryStatement = sys.argv[1] # pyobvectorを使用してOceanBaseに接続する際、ユーザー名やパスワードに「@」が含まれる場合は、「%40」に置き換えてください。 client = ObVecClient(uri="host:port", user="usename",password="****",db_name="test") openAIclient = OpenAI() # テキストのベクトル表現を生成する関数を定義する def generate_embeddings(text, model="text-embedding-ada-002"): # ベクトル埋め込みの方法については、以下を参照してください:https://community.openai.com/t/embeddings-api-documentation-needs-to-updated/475663 res = openAIclient.embeddings.create(input=text, model=model) return res.data[0].embedding def query_ob(query, tableName, vector_name="embedding", top_k=1): embedding = generate_embeddings(query) ## 近似最近傍探索を実行する res = client.ann_search( table_name=tableName, vec_data=embedding, vec_column_name=vector_name, distance_func=func.l2_distance, topk=top_k, output_column_names=['combined'] ) for row in res: print(str(row[0]).replace("Title: ", "").replace("; Content: ", ": ")) # テーブル名 table_name = 'fine_food_reviews' query_ob(queryStatement,table_name,'embedding',1)質問を入力して、関連する回答を出力します。
python3 openAIQuery.py 'pet food'期待される結果は次のとおりです:
Crack for dogs.: These thing are like crack for dogs. I am not sure of the make-up but the doggies sure love them.