男もすなる生成AIといふものを、自分もしてみむとてするなり。で、生成AIを会社の中で使用するとしたら、社内のデータを如何に活用するかという事になりRAGが必要となり、RAGが必要となればそれに適したベクトルデータベースが必要になる訳ですね。
ベクトルデータベースも百花繚乱ですが、以前Difyを試しに触ってみたことがあり、そのDifyの内部で使われているWeaviateを、aws上に作ったk3s上に入れてみることにしました。Difyもいいのですが、DB内のデータの持ち方をいろいろ工夫したいとなると、お仕着せのDifyでなくLlamaindex+Weaviateを試したくなったという経緯があったので。
導入
実際の導入は、公式に書かれているので慣れてる方にとっては難しくないと思います。英語に慣れてない私には時間がかかりましたが。
helmを使う
helmが用意されているので、それを使います。
helm repo add weaviate https://weaviate.github.io/weaviate-helm
helm show values weaviate/weaviate > weaviate_values.yaml
weaviate_value.yamlのカスタマイズ
自分の環境に合わせてweaviate_values.yamlをカスタマイズします。私の場合は以下のようにしました。
・自分のk3sクラスタにはLonghornが入っているので、storageClassNameには"longhorn"を指定しておきます。
# The Persistent Volume Claim settings for Weaviate. If there's a
# storage.fullnameOverride field set, then the default pvc will not be
# created, instead the one defined in fullnameOverride will be used
storage:
size: 32Gi
storageClassName: "longhorn"
・今回、AWS Bedrockのcohere.embed-multilingual-v3でembeddingをすることにしました。weaviateデータベースにデータが挿入されるとき、自動的にembeddingできるよう以下設定しました。
modules:
text2vec-aws:
# enable if you want to use AWS module
enabled: true
# For Weaviate to be able to use AWS Bedrock service it needs a user credentials to authenticate to AWS.
# The User must have permissions to use AWS Bedrock service AI.
# You can pass the User credentials (access-key id and access-secret-key) in 2 ways:
# 1. by setting the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY plain values in the `secrets` section below
# this chart will create a kubernetes secret for you with these key-values pairs
# 2. create Kubernetes secret/s with AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY keys and their respective values
# Set the Key and the secret where it is set in `envSecrets` section below
secrets: {AWS_ACCESS_KEY_ID: 'ここにAWSアクセスキーを入れる' ,
AWS_SECRET_ACCESS_KEY: 'ここにAWSシークレットアクセスキーを入れる'}
# If one has already defined secrets with AWS credentials one can pass them using
# this setting:
envSecrets: {}
# AWS_ACCESS_KEY_ID: name-of-the-k8s-secret-containing-the-key-id
# AWS_SECRET_ACCESS_KEY: name-of-the-k8s-secret-containing-the-key
本来はkubenetes secretを使って設定してあげるのが正式だと思いますが。
・なお、私はk3sクラスタにVPNを使ってアクセスするので特にWeaviateにユーザーを設定などはせず、anonymous_accessを有効にしたまま使っていますが、環境、使途によっては注意が必要です。
authentication:
anonymous_access:
enabled: true
デプロイ
ここまで来ると、あとはデプロイします。
# Create a Weaviate namespace
kubectl create namespace weaviate
# Deploy
helm upgrade --install "weaviate" \
weaviate/weaviate \
--namespace "weaviate" \
--values ./values.yaml
ポートの確認
私のk3sクラスタの場合、ロードバランサーが無い(そもそもロードバランサーの設定が分からない)ので、このままではクラスタ外部から一切Weaviateにアクセスできません。まず、httpとgRPCがポートの何番で走ることになっているのか確認しましょう。
command: ["/bin/weaviate"]
args:
- '--host'
- '0.0.0.0'
- '--port'
- '8080'
- '--scheme'
- 'http'
- '--config-file'
- '/weaviate-config/conf.yaml'
- --read-timeout=60s
- --write-timeout=60s
grpcService:
enabled: true
name: weaviate-grpc
ports:
- name: grpc
protocol: TCP
port: 50051
# Target port is going to be the same for every port
type: LoadBalancer
loadBalancerSourceRanges: []
# optionally set cluster IP if you want to set a static IP
clusterIP:
annotations: {}
ここからhttp(httpsに非ず)が8080、gRPCが50051で動いてるらしいことが分かります。
Nodeportの設定
先程ポート番号を調べたので、クラスタ外部からアクセスできるように比較的簡単なNodePortの設定をしてあげるようにしました。これも、私が単純にVPNで繋げるだけだからこうしたのであって、目的、使途で変わる部分だと思います。
apiVersion: v1
kind: Service
metadata:
name: weaviate-http-nodeport
namespace: weaviate
spec:
selector:
app: weaviate
type: NodePort
ports:
- name: weaviate-http
protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30020 # 30000-32767の範囲で任意のポート番号を指定できます
---
apiVersion: v1
kind: Service
metadata:
name: weaviate-grpc-nodeport
namespace: weaviate
spec:
selector:
app: weaviate
type: NodePort
ports:
- name: weaviate-grpc
protocol: TCP
port: 50051
targetPort: 50051
nodePort: 30021 # 30000-32767の範囲で任意のポート番号を指定できます
あとはkubectl apply
するだけです。
kubectl apply -f nginx-dep.yml
疎通確認
ここまで来たら、接続確認したいところです。簡単なPythonスクリプトで確認を取りたいと思います。まずは、Pythonクライエントのインストール。
pip install weaviate-client
k3sクラスタまで疎通がとれている状態にして(=VPN接続を行って)以下のスクリプトを走らせます。
import weaviate
client = weaviate.connect_to_custom(
http_host="172.31.42.76", # URL only, no http prefix
http_port=30020,
http_secure=False, # Set to True if https
grpc_host="172.31.42.76",
grpc_port=30021, # Default is 50051, WCD uses 443
grpc_secure=False, # Edit as needed
)
print(client.is_ready())
client.close()
うまくいけば単にTrue
と返ってくるだけです。