TECH PLAY

サイオステクノロジー(Tech.Lab)

サイオステクノロジー(Tech.Lab) の技術ブログ

546

はじめに 前回の記事では、Terraformを使用してAWS上にEC2インスタンスを構築し、RKE2を用いてKubernetesクラスターとRancher Serverをセットアップする手順を解説しました。 今回の記事では、前回構築したRancherを活用して、複数のKubernetesクラスターを管理する方法を紹介します。 本記事の内容 RancherからEKSクラスターを作成する方法 既存のKubernetesクラスターをRancherにインポートする方法 RancherでNode数を管理する方法 RancherからKubernetesクラスターをアップグレードする方法 RancherのGUIからnginxをデプロイする方法 概要 本記事では、Rancherのダッシュボードを活用して、複数クラスターの構築・管理を行う手順を説明します。 前提条件 Rancher Serverが構築済みであること Rancherのダッシュボードにログインできていること 構築イメージ 複数クラスターの構築イメージは以下のようになります。管理対象クラスターのセットアップ方法は後ほど解説します。 管理対象クラスターの追加 RancherからEKSクラスターを作成 Rancher Serverにログインし、ホーム画面のサイドバーからクラスター管理画面( Cluster Management )に移動します。 まずはRancherからAWS環境にアクセスできるよう、AWSの認証情報を登録します。 Cloud Credentialsを選択して、クラウドの認証情報を管理する画面に遷移します。 Createを選択し、クラウドプロバイダーの選択画面に遷移します。 Amazonを選択し、AWSのクレデンシャル情報を入力します。なお、今回使用するAWSのIAMユーザーにはAdministrator Access権限をアタッチしています。 Credential Name: 任意の名称 Access Key: アクセスキー Sercret Key: シークレットキー AWSの認証情報を保存します。これでRancherからAWSアカウント上のリソースを操作できるようになりました。 続いて、クラスター作成メニュー画面でAmazon EKSを選択します。 クラスター初期設定画面で必要な項目を入力し、Createを押下します。 クラスター名 リージョン:us-east-1を選択 Kubernetes Version: 1.30 ※1 Instance Type: t3.medium スケール設定 Desired ASG Size: 2 Minimum ASG Size: 2 Maximum ASG Size: 2 ※1: あとでRancherのダッシュボードからクラスターのアップグレードをするため、最新よりひとつ前のバージョンを選択しています。 クラスターの作成が完了したら、サイドバーからEKSクラスターのダッシュボードに遷移します。 Nodeを選択すると、クラスター内のNodeの情報を閲覧できます。 これでEKSクラスターの構築が完了しました。このように、Rancherのダッシュボードから簡単にEKSクラスターを構築することができます。また、構築後もRancherの画面UIからNodeを操作することができます。 既存のKubernetesクラスターをRancherにインポートする クラスターの概要 今回は、以下の構成でKubernetesクラスターを構築し、Rancherにインポートします: Control Plane:3台 Worker Node:2台 既存のKubernetesクラスターをRancherにインポートすることで、Rancherの管理下で監視・操作が可能になります。 前提条件 Terraformを利用して、以下の設定を含むEC2インスタンスを5台デプロイします: OS:Ubuntu 24.04 各インスタンスのセキュリティグループ設定が完了していること(ポート443, 9345などが開放済み) Terraformのコードは こちら を使用します。 Kubernetesディストリビューションは前回同様RKE2を使用します。 Terraformを実行し、AWS上にリソースを作成します: $ terraform init $ terraform apply 1. Control Planeの構築 Control Planeの構築手順は前回の記事で詳しく説明しています。 以下をご参照ください: RKE2でControl Planeを構築する方法 2. Worker Nodeの構築 ここでは、Worker Nodeを追加する手順を解説します。 参考: 公式ドキュメント(Linux Agent (Worker) Node Installation) Worker Node用にデプロイしたEC2インスタンスにSSHでログインします: IPアドレスはTerraformのoutput「worker_node_public_ips」に出力されます。 $ ssh -i <YOUR_INSTANCE_KEY> ubuntu@<WORKER_NODE_PUBIC_IP> RKE2エージェントのインストール 以下のコマンドを実行して、RKE2エージェントをインストールします: $ curl -sfL https://get.rke2.io | sudo INSTALL_RKE2_TYPE="agent" sh - $ sudo systemctl enable rke2-agent.service RKE2エージェントの設定 設定ファイルを作成し、Control Planeと接続するための情報を記述します: $ sudo mkdir -p /etc/rancher/rke2/ $ sudo vi /etc/rancher/rke2/config.yaml 設定内容(例): server: https://<NLB_DNS_NAME>:9345 token: <TOKEN_FROM_SERVER> ※TOKEN_FROM_SERVERはControl Planeで設定したtokenと同じ Worker Nodeを起動します。 $ sudo systemctl start rke2-agent.service ノードの状態確認 Control Plane用のインスタンスにSSHでログインし、ノードの状態を確認します。 $ kubectl get nodes Worker Nodeが正常に表示されれば、クラスターの構築は完了です。 3. Rancherにクラスターをインポートする 構築したKubernetesクラスターをRancherにインポートします。 Rancher UIにアクセスし、サイドバーからクラスター管理画面に遷移します。 Import Existingを選択します。 Cluster Import画面で「Generic」を選択します。 クラスター名を入力し、Createボタンを押下します。 クラスターを構築したEC2インスタンスにSSHでログインし、RancherのUI画面に表示されたkubectl applyコマンドを実行してください。 $ kubectl apply -f <AUTO_GENERATED_MANIFEST> Rancherは管理対象クラスターを識別するために、cluster-agentというエージェントを利用します。このエージェントは、RancherのUIで自動生成されるマニフェストを対象クラスターに適用することで起動します。 cluster-agentが正常に起動すると、Rancherはcluster-agentを通じてクラスターを認識します。Rancherのサイドバーからクラスターの詳細画面に遷移できるようになります。 Nodesを選択すると、事前に作成した通り、Control Planeが3台、Worker Nodeが2台稼働していることを確認できます。これで、KubernetesクラスターをRancherにインポートして、クラスターを管理できるようになりました。 Rancherを使ったクラスター管理 Node数の調整 連携したKubernetesクラスターをRancherの画面上から操作してみます。 サイドバーからクラスター管理画面に遷移し、先ほど作成したEKSクラスターを選択します。 Edit Configを選択してクラスター設定の編集画面に遷移します。 Node Groupsのgroup1でAutoScalingGroupのスケール数を引き上げて保存します。すると、クラスターの更新が開始されます。 Desired ASG Size: 5 Maximum ASG Size: 5 クラスター更新完了後、全てのNodeがActive状態になったことを確認します。 これで、Rancherの操作画面からクラスターのNode数を増やすことができました。 続いて、増やしたNode数を減らしてみます。 先ほどと同じ手順でEKSクラスターのクラスター設定編集画面に遷移し、今度はASGのスケール数を引き下げます。 Desired ASG Size: 3 クラスター更新完了後、指定したDesired Sizeの数までNode数が減少したことを確認します。 このように、Rancherからクラスター内で稼働するNode数を調整することが可能です。 ※Node数の調整はRancherのUIから作成したクラスターのみ利用可能です。インポートしたクラスターはRancherから操作できないため、Node数を増減させることができません。 公式ドキュメント: Node Options Available for Each Cluster Creation Option クラスターのアップグレード EKSクラスターのアップグレード RancherからKubernetesクラスターのバージョンをアップグレードすることができます。 サイドバーからクラスター管理画面に遷移し、EKSクラスターのEdit Configを選択します。 編集画面内のプルダウンからKubernetesの新しいバージョンを指定して保存します。 クラスターの更新が開始されます。バージョンアップ完了までおよそ10分ほどかかります。 AWSのマネジメントコンソールでEKSの画面に遷移すると、EKSクラスターが更新状態になっていることを確認できます。 クラスターの更新が完了すると、EKSクラスターのバージョンが1.31に更新されていることが確認できます。 インポートしたクラスターのアップグレード 続いて、先ほどインポートしたクラスターもアップグレードしてみます。 EKSクラスターの時と同じ手順で、クラスター管理画面のEdit Configからクラスター設定情報の編集画面に遷移します。 編集画面でKubernetesの新しいバージョン(今回は1.31)を選択して保存します。 クラスターの更新が完了すると、Kubernetes Versionの表示が指定したバージョンに更新されていることが確認できます。これで、インポートしたクラスターのアップグレードは完了です。 このように、Rancherを利用すれば、Kubernetesクラスターのバージョンアップを簡単かつ効率的に実施できます。また、クラスター一覧画面で各クラスターのバージョンが一目で確認できるため、どのクラスターに更新が必要かを即座に把握することができます。これにより、複数クラスターのバージョン管理がシンプルになり、運用負荷を軽減することができます。 ワークロード管理 RancherのWeb UIから管理対象クラスター内にPodをデプロイしてみます。 サイドバーからインポートしたクラスターのダッシュボードに遷移します。 Workloads内のDeploymentsを選択し、Deployments画面内でCreateを選択します。 Deploymentの設定画面でnginxのPodを6つ起動する設定を入力します。 Createボタンを押下し、しばらくするとnginxのPodが6つ起動します。 今度はnginxのPodのレプリカ数を減らしてみましょう。 Deployment一覧画面で先ほど作成したnginx-demo-deploymentを選択し、Edit Configで設定編集画面に遷移します。 編集画面でreplicasを3に変更して保存します。 Deploymentの更新が完了すると、nginxのPod数が指定した数まで減少します。 RancherのGUIを活用すれば、Kubernetesクラスター内のリソース設定を直感的に管理できます。マニフェストファイルを一から作成する必要がなく、UI画面上で簡単にリソースの作成や編集が可能です。また、GUIでの操作に加え、必要に応じてYAMLファイルを直接編集して詳細な設定を行うこともできます。 まとめ Rancherを導入することで、ブラウザ上から複数のKubernetesクラスターを効率的に管理できます。特にマルチクラスター環境の運用を効率化するため、Rancherは強力なツールとなります。 次回の記事では、Rancherのモニタリング機能について詳しく解説しますので、ご期待ください。 参考 Rancher公式ドキュメント ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Rancher入門:Rancherを用いたKubernetesクラスター管理 first appeared on SIOS Tech. Lab .
アバター
挨拶 ども!過去のデモを執筆する元気を奮い立たせている龍ちゃんです。今季は、【生成AI】という大きなキーワードで取り組みを行ってきました。その過程で【Streamlit】【Qumcum】【AIエージェント】の3つを掛け合わせて、ロボットをAIエージェントで操作するデモをいろいろなところで使用してきたので技術的な内容について解説していきます。 システムの概要については、 こちらでラフ に紹介しています。 2024-10-03 「Qumcum×生成AI」ロボットで試すAIエージェント:Python システム概要 内容としては、「人間の入力をAIエージェントが解釈してロボット制御」を行います。 エージェントをロボット制御に活用することで、以下のようなメリットが存在します。 ユーザの入力がロボットの複合的な動作も判断して処理 ユーザのあいまいな表現に関してもロボットの制御として処理 それでは、作成の話に入っていこうと思います。 設計 システムはすべてPython上で動作しています。ロボットは、 CRETARIA社 が発売している Qumcum を使用しています。こちらもPythonで制御することができるAPIが出ています。 コア 使用しているサービスについては、以下の内容です。 サービス・製品名 説明 Qumcum PRO Bluetoothで接続することで、API経由で遠隔でロボット制御を実現できる モーターの角度を調整することができれば様々な表現をが可能 Azure OpenAI Service Azureが提供しているAIサービス エージェントの作成には、langchainを使用しています。langchainはバージョンが非常に大切になるので、ライブラリはバージョンを含めて記載しておきます。 langchain==0.2.16 langchain-community==0.2.16 langchain-core==0.2.39 langchain-openai==0.1.23 streamlit==1.38.0 Streamlit上での処理フロー Streamlit上でデモアプリを管理するために、Qumcumとの接続処理やLangchainを用いたエージェントの処理フローをしっかり構成しました。 流れとしては、大きく分けて二つです。 Streamlit上でQumcumとの接続処理(エージェントページへのアクセス許可) StreamlitからLangchainを介してAzure OpenAI Serviceへのアクセス LangchainからQumcumの動作を制御するため、エージェントへアクセスする際にはQumcumとの接続を確約している必要があります。そのため、Streamlit上の制御でQumcumとの接続処理が実行されるまでエージェントのページにはアクセスできないように構成します。 ページ構成としては、トップページとエージェント処理ページの二つ作成します。 ページ名 説明 トップページ:/ Qumcumとの接続を管理する エージェントページ:/agent Langchain(エージェント)のアクセスを管理する Qumcumとの接続が確約されるまでアクセスできない 実装 今回の実装は、ロボットの動作作成からエージェントの実装まで多岐にわたります。また、デモとしてまとめるためにStremlitからアクセスできるように作成しています。分割して解説を書いていきます。 Qumcum処理 ここでは、ロボットとの接続処理と立ち姿リセット処理をまとめています。QumcumとのAPI接続には、 公式が提供しているAPI をダウンロードして構成する必要があります。 環境変数として ROBOT_ID を取得して接続を処理しています。 import os from dotenv import load_dotenv import qumcum_ble as qumcum load_dotenv() def robot_connection(): ROBOT_ID = os.getenv("ROBOT_ID") [err, _] = qumcum.get_info() if err == -1: qumcum.connect(ROBOT_ID) [err, _] = qumcum.get_info() if err == -1: return False else: robot_reset() return True else: return True def robot_disconnect(): qumcum.motor_power_off() qumcum.end() def robot_reset(): qumcum.motor_power_on(500) qumcum.motor_angle_multi_time(0, 90, 90, 90, 90, 90, 180, 600) qumcum.motor_start(True) qumcum.motor_power_off() Qumcumはサーボモータを調整すればいろんな動作を作成することができます。Qumcumをポージングさせるなんてこともできたりします。Qumcumの動作は結構長くなるので「こんな感じで書くよ~」ってイメージのために、気を付けの姿勢制御のみ記載しています。 こちらは、別の機会に「 Qumcum動き集 」として執筆していきたいと思います。 Langcahin:エージェント処理 ここでは、langchain v0.2でのtool callingの書き方について説明しています。デコレーターとして @tool を付けることでエージェントに受け渡すことができます。 import os from langchain_openai import AzureChatOpenAI from langchain.agents import tool from langchain_core.prompts import MessagesPlaceholder, ChatPromptTemplate from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain.memory import ConversationBufferWindowMemory from dotenv import load_dotenv load_dotenv(verbose=True) # Azure OpenAI Serviceの設定 AOAI_ENDPOINT = os.environ.get("AOAI_ENDPOINT") # Azure OpenAI Serviceのエンドポイント AOAI_API_VERSION = os.environ.get("AOAI_API_VERSION") # Azure OpenAI ServiceのAPIバージョン AOAI_API_KEY = os.environ.get("AOAI_API_KEY") # Azure OpenAI ServiceのAPIキー AOAI_CHAT_MODEL_NAME = os.environ.get("AOAI_CHAT_MODEL_NAME") # Azure OpenAI Serviceのデプロイモデル名 CUSTOM_SYSTEM_PROMPT = """ あなたは、指定された指示に従って、クムクムを操作するアシスタントです。 操作するためのツールは、以下の通りです。 以下のツールを呼び出す回数は、最大20回までです。 - banzai: クムクムが両腕を上げます。 - all_up_dance_tool: クムクムが両手足を上げ下げするダンスを踊ります。引数には、踊る回数とスピード(デフォルトで1000)を入れてください。 - walk_right: クムクムが右に曲がって一歩歩きます。 - walk_left: クムクムが左に曲がって一歩歩きます。 - walk_forward: クムクムがまっすぐ前に一歩歩きます。 - denied: クムクムが拒否動作をします。 - talk: クムクムが引数に入れた言葉を喋ります。 上記のどれにも当てはまらない場合は、以下のツールを使ってその旨を伝えてください。 - impossible_move: クムクムが不可能な動きを指示された時に断るためのツールです。引数にその旨を入れてください。 """ # LLMの初期化 llm = AzureChatOpenAI( azure_endpoint=AOAI_ENDPOINT, api_key=AOAI_API_KEY, api_version=AOAI_API_VERSION, openai_api_type="azure", azure_deployment=AOAI_CHAT_MODEL_NAME, ) @tool def banzai(): """ クムクムが両腕を上げるためのツールです。 """ # クムクムに両腕を上げる指示を記述 return "バンザイ" @tool def all_up_dance_tool(num, speed): """ クムクムが両手足を上げ下げするダンスを踊るためのツールです。 """ # クムクムにダンスを踊る指示を記述 return "ダンスを踊りました。" @tool def walk_right(): """ クムクムが右に90度曲がるためのツールです。 """ # クムクムの右に曲がる処理を記述 return "一歩右に曲がりました。" @tool def walk_left(): """ クムクムが左に90度曲がるためのツールです。 """ # クムクムの左に曲がる処理を記述 return "一歩左に曲がりました。" @tool def walk_forward(): """ クムクムがまっすぐ前に一歩進むためのツールです。 """ # クムクムが一歩進む処理を記述 return "一歩進みました。" @tool def denied(): """ クムクムが動作拒否をするツールです。 """ # クムクムの拒否動作を記述 return "首を振りました。" @tool def talk(word): """ クムクムに喋らせるためのツールです。 """ # クムクムに喋らせる指示を記述 return "「" + word + "」" @tool def impossible_move(message): """ クムクムが不可能な動きを指示された時に断るためのツールです。 """ # クムクムの不可能であることを動作または音声で通知 return message tools = [ banzai, all_up_dance_tool, walk_right, walk_left, walk_forward, denied, talk, impossible_move, ] prompt = ChatPromptTemplate.from_messages( [ ("system", CUSTOM_SYSTEM_PROMPT), MessagesPlaceholder(variable_name="chat_history"), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ] ) agent = create_tool_calling_agent(llm, tools, prompt) exucutor = AgentExecutor( agent=agent, tools=tools, verbose=True, memory=ConversationBufferWindowMemory( return_messages=True, memory_key="chat_history", k=0 ), ) all_up_dance_tool ・ talk ・ impossible_move では、引数を受け取っています。こちらに関しての説明もプロンプト内で行うことでエージェントが判断して代入した状態で実行をしてくれます。 Streamlit:ページ制御 まずはディレクトリ構成について記載しておきます。Streamlitでマルチページを作成する方法は二つあります。今回は状態によって利用制御を行いたいので、プログラムでページを管理する方法を採用しています。 ./ ├── contents # Streamlit ページ用ディレクトリ ├── utils # Python処理をまとめる ├── main.py # Streamlit起点ページ ├── qumcum_ble.py # Qumcum APIライブラリ └── requirements.txt contents の内部には、 top_page.py (ロボットの接続処理)と robot_move_agent_page.py (ロボットのエージェント制御)の2つ用意します。 main.py でページとメニューバーの制御を行います。 import streamlit as st def main(): # 各Stateの初期化 if "robot_connection" not in st.session_state: st.session_state.robot_connection = False # ページの設定 top_page = st.Page( page="contents/top_page.py", title="ロボットとの接続", icon=":material/home:", default=True ) robot_move_page = st.Page( page="contents/robot_move_agent_page.py", title="ロボットを動かす", icon=":material/apps:", ) # 接続が成功している場合は全てのページを表示 if st.session_state.robot_connection: pg = st.navigation( { "INFO": [top_page], "AIエージェント": [robot_move_page], } ) # 接続が失敗している場合はTopページのみ表示 else: pg = st.navigation( { "INFO": [top_page], } ) pg.run() if __name__ == "__main__": main() StreamlitのSession State を利用して状態の管理を行います。ロボットの接続状態によって表示されるメニューが変更されます。引数として default を渡すことで、特定のページをトップページにすることができます。 top_page.py:Streamlit・Qumcum接続処理 ここでは、ボタンを押したらロボットとの接続を管理することができるページとなっています。ロボットの接続は session state の robot_connection で管理しています。接続に成功するとTrueを代入します。 import streamlit as st from utils.robot_connection import robot_connection, robot_disconnect from dotenv import load_dotenv load_dotenv() st.title("ロボットとの接続の確立") if st.session_state.robot_connection: st.success("Connected to the robot") if st.button("Disconnect"): robot_disconnect() st.session_state.robot_connection = False st.success("Disconnected from the robot") st.rerun() else: st.error("ロボットと接続されていません。") if st.button("Try to connect"): connection = robot_connection() if not connection: st.error("やはり接続が確立することができません。実機の確認をしてください。") else: st.success("接続が確立されました。") st.session_state.robot_connection = True st.rerun() robot_move_agent_page.py:Streamlit・Langchain接続処理 こちらでは、単純な入力フォームとチャット形式で入出力を表示しています。ユーザーの入力を起点にlangchainのエージェントを実行しています。 # chatbot.py import streamlit as st from langchain.schema import HumanMessage, AIMessage from dotenv import load_dotenv import utils.aiagent_qumcum_control as agent load_dotenv() # ページの設定 st.set_page_config(page_title="ロボットを動かす", page_icon="😆") st.header("ロボットを動かす") # チャット履歴の初期化 robot_messages = [] # ユーザーの入力を監視 if user_input := st.chat_input("聞きたいことを入力してね!"): robot_messages.append(HumanMessage(content=user_input)) with st.spinner("GPT is typing ..."): response = agent.exucutor.invoke({"input": user_input, "chat_history": []}) output = response["output"] robot_messages.append(AIMessage(content=output)) # チャット履歴の表示 for message in robot_messages: if isinstance(message, AIMessage): with st.chat_message("assistant"): st.markdown(message.content) elif isinstance(message, HumanMessage): with st.chat_message("user"): st.markdown(message.content) デモ 課題 今回の実装における問題点についてまとめていきます。 Streamlitでの動作が同期処理 Streamlitの表現はすべて同期処理になっています。そのため、Langchainの処理が完了するまで結果を取得することができていません。長い処理をエージェントが実行している場合は、事項中は画面がフリーズします。デモとしては気まずい時間が流れますね。 デモ画面がチャットだけだと味気ない 現行のデモの場合だと、実行結果のテキスト表示と入力フォームしかありません。口頭で一から説明するのもなかなか大変だと感じています。ここは見せ方をもっと工夫する必要がありそうです。 この問題を解決するために、LangchainとStremlitについてもっと深堀していく必要がありそうです。 終わり 今回は、LangchainとQumcumを組み合わせてAIエージェントでロボットを制御するデモの実装について解説しました。Streamlitを使用することで、ユーザーフレンドリーなインターフェースを実現することができました。 課題として挙げた同期処理の問題や、UIの改善点については今後も継続的に取り組んでいく予定です。このデモを通じて、AIエージェントとロボットの組み合わせの可能性を示すことができたと思います。 今後も新しい技術を積極的に取り入れながら、より良いデモの開発に取り組んでいきたいと思います。最後までお読みいただき、ありがとうございました! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AIエージェントでロボットを制御する【langchain・Streamlit】 first appeared on SIOS Tech. Lab .
アバター
構築したRAGの性能を評価はどうしたらよいでしょうか。RAGを使ったシステムを改善のサイクルを回すには評価が重要になります。RAGの評価はRAGAsをはじめとして複数の方法が提案されています。それらの方法を整理して包括的で体系的に理解できるような説明を試みました。読んでいただいた方の理解の助けになれば幸いです。 自然言語生成 (NLG) の評価の難しさ 自然言語生成 (NLG) の評価は従来のシステムのテストとは大きく異なるものです。自然言語の表現は多様で同じ内容であっても表現方法が複数あります。当然、LLMの性能評価はプログラムの関数をユニットテストするようにはできません。 例えば、「世界一高い山は?」という質問を考えます。例えば、次のような回答のパターンが考えられます。 「世界一番でエベレストで。」 という回答はエベレストであることは正解ですが日本語がおかしいため、適切な回答とはいえません。 「世界で一番高い山はエベレストの可能性があります。」 答えは正しいものの曖昧な回答となっており、これも適切な回答ではありません。 「世界で一番高い山はエベレストで、標高は3,776mです。」 答えは正解ですが、補足情報が間違っています。 「世界で一番高い山は富士山です。」 これは完全に誤答です。このような誤答をあたかも正解のように回答することは特にハルシネーションと呼ばれています。正解ではあるものの不適切な表現を含む有害な回答が混ざる可能性もあります。 当然このようなモデルの生成した文章に対して評価するのは、従来の単純な文字列のようなテストではうまくいきません。回答の文章を認識して判断する必要があります。また、このような文章での回答は正解か不正解かに単純に分類できず、悪い回答から良い回答までグラデーションがあるともいえます。簡潔に回答して欲しい時もあれば、補足情報をたくさん含んで欲しいこともあります。 評価者はNLGについて再現性があり納得のいく方法で評価し提示しなくてはなりません。 NLGの評価方法 この章では、RAGに限らずLLMの自然言語生成 (NLG) をどう評価するのかについて説明します。 評価のアプローチ NLGの評価のアプローチは大きく分けて3つあります。 人手評価 模範解答ありの自動評価 模範解答なしの自動評価 (LLM as a judge) 人手評価 人手評価は文字通り人がモデルの回答を評価する方法です。人間が直接テキストをみて判断するため、適切な回答であるかを直感的に判断できます。その一方で評価は人間が行うためテストの作業規模が増大します。主に小規模なシステムで実施するのがよいといえます。 模範回答(注釈)ありの自動評価 人間が用意した模範回答とLLMの回答の一致度を測定して評価する方法です。テキスト中の単語の一致度を計算するなどの方法で評価されます。この方法ではLLMがある程度決まった回答をしてくれるかどうかを比較的確実に評価することができ、再現性が高い評価が可能です。しかし、模範解答のデータセットを準備するコストが高かったり、回答の自由度が高いようなバラつきが大きくなる質問ではスコアが低くなってしまい適切に評価できないという課題があります。 模範回答(注釈)なしの自動評価 (LLM as a judge) 模範解答を用意せず、LLMに回答の評価を評価する方法もあります。このような方法はLLM as a judge [ 1 ] と呼ばれています。LLMによる評価は人手評価に近い評価ができると言われています。一方で、実行ごとに評価が変わってしまうなど再現性がやや低いといった課題もあります。 評価アプローチの比較 上記の評価指標を表1で比較しました。 (表1: 評価アプローチの比較) 評価アプローチ テスト実施コスト テスト実装コスト テストの再現性 回答のバラつきの許容度 人手評価 大きい なし 低い 高い 模範回答ありの自動評価 小さい 大きい 高い 低い 模範解答なしの自動評価 小さい 中程度 中程度 高い 模範回答ありの自動評価では、汎用的なモデルに対しては既存のデータセットが存在するため、評価指標を用いた自動評価が可能ですが、RAGの場合は独自のデータを用いた回答が期待されるため、データセットの準備にはコストがかかります。一方で、模範解答なしの自動評価は注釈(模範解答)をつける労力はかからないもののテストの再現性がやや低かったり、本当に人が期待している回答とは比較しないので乖離が発生する可能性があるというトレードオフがあります。現在、主流のRAGの評価では模範回答ありの自動評価のアプローチが提案されています。詳しくは後述しますが、RAGではコンテキスト(検索された文書)が利用できるため、なるべく注釈をつけないで評価できるような方法も提案されています。 評価のタイミング 評価方法は評価タイミングによっても2つに分けることができます。 オンライン評価 オフライン評価 オフライン評価 予め用意されたテストデータを使ってモデルの性能をテストする方法です。単体テストや結合テストにあたる本番運用前にテストします。今回はこのオフライン評価について主に説明します。 オンライン評価 本番運用段階で実際のユーザの入力やフィードバックを使った評価です。例えば、OpenAIのChatGPTでユーザに対しLLMの回答に や を付けるように促しているのもその一例です。 RAGの評価手法 ここではRAGの評価はNLGの評価に加えて、検索された文章 (コンテキスト) を使うことでより多角的な評価が可能となります。RAGの評価手法ではこのコンテキストも含めて、総合的に評価する手法が提案されています。 RAG評価に必要なパラメータ RAGの評価では次の4つのをパラメータ用いて評価が行われます。 質問 (ユーザの質問。クエリ。) コンテキスト (検索された文書。チャンク。) 回答 (モデルの回答。実際の回答。レスポンス。) Ground Truth (模範回答。注釈。リファレンス。期待する回答。GT。) 質問はユーザがRAGに対して質問する文章のことです。 コンテキストはLLMが検索ツールでクエリを実行した結果得られた文章(チャンクとして分割された文書の断片)のことです。コンテキストは通常は複数取得され、それらのコンテキスト全てが評価に利用されます。 回答はコンテキストをもとにLLMが生成した回答の文章です。 Ground TruthはRAGに期待する回答で、質問に対して回答すべき内容を正確に記述した文章です。Ground Truthは人が作成したり、LLMにより自動生成する方法があります。 RAGAsによる質問・文書・評価を使った評価 現在、RAGの評価として最も有名なのがRAGAs (Retrieval Augmented Generation Assessment) [ 2 ] です。現在のRAGの評価手法の基本的な考え方となっています。RAGAsの評価指標をベースとして改善や派生の指標が提案されています。この章ではRAGAsを説明します。 RAGAsの考え方 RAGAsは3つの指標を使うことでGround Truth不要で評価できるように設計されています。まずは、その核となる次の3つ指標を用いて説明します。 Context Relevance (文脈の関連性) Faithfulness (忠実性) Answer Relevance (回答の関連性) Context Relevance (文脈の関連性) は質問とコンテキストの間にどれだけが関連性があるか確認する指標です。RAGでは質問に対して関連性が高いコンテキストが取得できれば、LLMが適切に回答できる可能性が高まります。 Faithfulness (忠実性) はコンテキストに基づいて回答が生成されているかどうかを確認する指標です。これはコンテキストが回答に役立つものが取得できているかやコンテキストに基づかない回答をしてハルシネーションしていないかを判断に有効な指標です。 Answer Relevance (回答の関連性) は最終的な質問と回答が関連しているかについて確認する指標です。質問に対して回答の情報が不足していたり、逆に不必要な情報を含んでいないかを確認することができます。 図1に各指標とRAGの入出力(質問・文書・回答)との関連を示します。 図1: RAGAsの3つの指標の関係。RAGへの入出力に対して互いに関連を評価する。[ 3 ]より引用・改変。 このように入出力を互いに評価することでGround Truthなしで評価できる方法となっています。このような評価では人手評価と近い評価が実現できると報告されています [ 2 ] 。 RAGAsの指標 RAGAsの指標について説明します。ここの指標には論文に説明されている指標以外にも Ragas として公開されているOSSで実装されているもの説明します。Ground Truthを使った評価も含まれており、そのような指標を用いてより精緻に評価することができます。Ragasの指標はかなり頻繁に見直しされており、指標は今後も変更がある可能性があります。 Context Relevance (コンテキストの関連性) Context Relevance (Context Relevancy) は RAGAsの考え方 で説明した通り、RAGAsにより最初に提案された基本的な指標の1つです。Context Relevanceは検索により取得されたコンテキストが質問とどの程度関連するかを測る指標です。取得したコンテキストを文単位に分割し、各文が質問と関連しているかをLLMに判定させ、その中で関連すると判断された文章の割合です。従って、Context Relevanceは0から1の値をとり、0は関連のある回答が存在せず、1が全ての文において質問と関連があると判定されたことになります。1に近いほど良好です。 ただし、現在、この指標はRagasから削除され、Context Precision (文脈の精度) に置き換えられました。 Context Precision (コンテキストの精度) Context Precision はコンテキストが質問とどの程度適合するかを測る指標です。質問と関連性が高いコンテキストが取得できていれば、この指標は1に近くなります。一方で、関連性が低いコンテキストばかりの場合は指標は0に近くなります。 Context Relevanceと似ていますが、少し評価方法が異なります。Context Relevanceはどの文も均して評価されますが、Context Precisionは検索されたチャンクごとに精度を一度計算し、最後にチャンクごとの精度の平均をとります。Context Relevanceは削除されContext Precision (文脈の精度) に置き換えられました。おそらくContext Precisionの方が適切に評価できると判断されたことが理由だと思われます。 【補足1】精度99%の判別器で陽性である場合に「本当に」陽性であるのは99%でしょうか?実はこれだけの情報では簡単に答えられません。データが概ね陽性と陰性が半分ずつに別れている場合はそのようになりますが、データがどちらかに偏っている場合は全く異なります。ウイルス感染を調べる検査を無作為に行った場合に「陽性判断を受け本当に陽性である」確率は数学的に相当に低いことが知られています (参考: 精度99%の検査で陽性だったら、その病気である確率は99%?? →大間違い! ) 。例えば、100万人の病気でない人と100人の病気の人という偏りがあった場合は、陽性判定を受けた人のうち実際に病気である人はたった6%にすぎません。これを「検査陽性のパラドックス」といいます。RAGでもテストデータとして、質問と関連性の高い情報をたくさん取り込んでテストした場合と関連性の低い情報をたくさん取り込んだ場合では結果が異なることがあるでしょう。このようにテストデータの偏りも精度をどう捉えるかという判断にとても重要です。数字に騙されず多くの指標を取り入れて多角的に判断するようにしましょう。 Context Recall (コンテキストの再現率) Context Recall は回答に必要な情報(クレーム)がコンテキストに「もれなく」含まれているかを測る指標です。Context RecallではGround Truthに含まれる情報のうちがどれだけコンテキストに含まれるかの割合を算出します。包括的に取得できているほど1に近く、取得できていないほど0に近い値となります。1であればLLMはGround Truthと同等の内容を回答できるだけの情報を取得できたことになります。逆に0に近ければ回答に必要な情報が不足しているということになり、LLMが期待している回答をできる可能性が低くなります。 【補足2】精度 (Precision) と再現率 (Recall) についての補足説明です。これらの言葉は陽性 (Positive) と陰性 (Negative) を判定するシステムの良し悪しを判定するために使う言葉です。例えば、検査による病気の判定や異常検知システムなどが代表的な例です。このようなシステムの出力と本来の結果については4つのパターンが考えられます。 1. 検査結果が陽性で本当に陽性 (True Positive、TP、真陽性)。 2. 検査結果が陽性で本当は陰性 (False Positive、FP、偽陽性)。 3. 検査結果が陰性で本当に陰性 (True Negative、TN、真陰性)。 4. 検査結果が陰性で本当は陽性 (False Negative、FN、偽陰性)。 このとき、精度は陽性と判定され本当に陽性である割合を表します。つまり、誤って陰性のものを拾ってきてしまっていないかが分かります。精度は適合率ということもあります。 再現率は本当に陽性であるもののうち、陽性と判断されたものの割合を表します。つまり、陽性を取りこぼさずに拾ってこれたかが分かる指標です。 日常で「精度」という言葉は比較的ラフに使われがちですが、機械学習やAIの領域ではきちんとした定義があり、よく出てくる言葉なので覚えておくと役立ちます。 Context Entities Recall (コンテキストのキーワードの再現率) Context Entities Recall は回答に必要な「エンティティ」がコンテキストにもれなく含まれているかを測る指標です。エンティティとは文章におけるキーワードのことです。例えば、「日本で一番高い山は富士山で、標高は3,776mです。」という文章では、「日本」「富士山」「3,776m」などがキーワードとなります。Context Entities RecallではGround Truthに出現するキーワードのうち、コンテキストに出現するキーワードがどれだけあったかの割合を算出します。1に近いほど、Ground Truthに出現するキーワードがコンテキストにも出現していることになり、Ground Truthに近い回答ができる可能性が高まります。逆に0に近いとGround Truthに出現するキーワードが存在せず、LLMへ与える情報が不足していることになります。 Context Recallは「情報(クレーム)」をベースとした再現率を計算しますが、Context Entities Recallは「キーワード (エンティティ) 」をベースとした再現率を計算するという違いがあります。観光案内デスクや歴史的な質問応答などの固有名詞の扱いが重要なユースケースでの評価で有効とされています。 Noise Sensitivity (ノイズへの敏感性) Noise Sensitivity はコンテキストに含まれる誤った情報 (クレーム) を取り込んでしまっているかを測る指標です。コンテキストに含まれているが、Ground Truthに含まれていない情報を回答には必要がない情報なので「ノイズ」と定義します。その上で、回答に含まれる情報のうち、ノイズの割合を算出します。0に近いほどLLMはノイズをひろっていないので良好と言えます。逆に1に近いほど、回答にノイズを取り込んでしまっているということになります。 Answer Relevance (回答の関連性) Answer Relevance (Response Relevancy) は RAGAsの考え方 で説明した通り、RAGAsにより最初に提案された基本的な指標の1つです。質問に対する回答として関連が見られるかを測る指標です。この指標により最終的にきちんと質問に対して回答したかを確認することができます。 Answer Relevanceの計算は少し特殊です。例えば、「日本の最高峰は?」と質問をし「日本で一番高い山は富士山で、標高は3,776mです。」という回答を得られた状況を考えます。評価は、まず、LLMにこの回答に対する質問は何かを逆に生成させます。その結果、「日本で一番高い山は?」と「日本で標高が最も高い山は?」などが得られます。これらを疑似質問といいます。これらの疑似質問を本来の質問とコサイン類似度を計算します。それぞれ類似度を計算すると類似度(「日本の最高峰は?」,「日本で一番高い山は?」 ) = 0.9、類似度(「日本の最高峰は?」,「日本で標高が最も高い山は?」 ) = 0.7(値は例です)となったときその平均の0.8が回答の関連性となります。 Answer Faithfulness (回答の忠実性) Answer Faithfulness (Faithfulness) は RAGAsの考え方 で説明した通り、RAGAsにより最初に提案された基本的な指標の1つです。Answer FaithfulnessはLLMがコンテキストに忠実に回答を生成したかどうかを表す0から1をとる指標です。単にFaithfulnessとも呼ばれることがあります。回答をシンプルな情報を含む複数の文章に分割します。この分割された文章のそれぞれがコンテキストから回答可能なのか判定します。コンテキストから回答可能であると判定された文章の割合がAnswer Faithfulnessの値となります。 コンテキストからだけ導かれた回答であるほど1に近い値となり、コンテキスト以外の情報が回答に含まれるほど0に近い値となります。そのため、この値が低いとハルシネーションを起こしている可能性があると判断できます。ただし、モデルが事前に学習している知識で正しく回答している可能性もあるため、結果の吟味には注意が必要です。 RAGAsによるテスト実装 基本的には Ragas を用いることでテストを実装することができます。さらに、RagasはRAGの評価で広く使われているため、多くのフレームワークにも取り入れられています。例えば、LangChain社によるLangSmithや Confident AI社の DeepEvalでも指標が実装されており実装にあたっては複数のアプローチがとれます。 RAGCheckerによるクレームベースの評価 Amazon AWS AI、上海交通大学、西湖大学のグループにより提案された RAGChecker はクレームと呼ばれる単一の情報のレベルで分解して算出することができる評価指標です [ 4 ] 。クレームレベルに分解することでより複雑な文書、回答であってもより正しく評価できることを目指しています。 RAGCheckerではRAGAs等の既存の評価手法に比べて、人間の評価とより高い相関が見られると報告されています [ 4 ] 。比較的新しい手法ですが、注目を集めつつあります。 RAGCheckerの考え方 図2のように模範解答、モデルの回答、チャンクに含まれる正しい/誤った/喪失した/関連のないクレームの数をベースとして指標が算出されます。RAGCheckerの指標は体系的に整理され、粒度が揃っているという特徴があります。また、RAGCheckerではこれらの指標の傾向から どのように改善すべきかの方針 も示しており参考になります。 RAGAsとRAGChekcerは類似点も多いですが、考え方の点では次が異なります。 RAGAsでは質問を評価に使うが、RAGCheckerでは質問は評価に使わない。 RAGAsでは文章/文/キーワード/クレーム単位の評価方法が混在するが、RAGCheckerではクレーム単位で統一されている。 RAGAsではGround Truthなしでも評価できるよう設計されているが、RAGCheckerでは模範解答をベースに評価を行う。 RAGCheckerの指標 RAGCheckerの指標には図2のようなものがあります。 Overall Metricsは最終的な回答を評価する指標です。RAGシステムとして最終的な結果がどうかという観点を確認します。 Retriever Metricsは検索ツールの検索結果を評価する指標です。うまく検索できているかという観点を確認します。 Generator MetricsはLLMの回答を評価する指標です。LLMがうまく回答を生成できているかという観点を確認します。 これらの指標をそれぞれ説明していきます。 図2: RAGCheckerの指標一覧。すべての文章はクレームレベルに分解され、クレームの数をベースに指標を組み立てる。 RAGChecker より引用。 Precision (精度) モデルからの回答にGround Truthのクレーム「だけ」を含むか測る指標です。モデルの回答にGround Truthに含まれないクレームが少ないほど良好な数値となります。数値が高いほど良好です。 Recall (再現率) モデルからの回答にGround Truthのクレームを「網羅的に」含むか測る指標です。モデルの回答にGround Truthのクレームが含まれているほど良好な数値となります。数値が高いほど良好です。 Context precision  (文書の精度) 全てのチャンクのうち、文書にGround Truthのクレームを含むチャンクがどれだけあるかを測る指標です。この指標に関してはクレームではなくチャンクの数が使われます。数値が高いほど良好です。1つでも関連のあるクレームが含まれていれば、関連のあるチャンクとみなされます。 RAGAsのContext precisionはチャンクごとに集約された精度を平均しますが、RAGCheckerはチャンクの数で割合を計算するという点で異なります。 Claim Recall (クレームの再現率) モデルからの回答にGround Truthのクレームを「網羅的に」含むか測る指標です。RAGAsのContext Recallと同等の指標です。 Context utilization (文脈の利用率) コンテキストとして取得できている必要なクレームのうちどれだけが利用されたかを測る指標です。この割合が高いとLLMはコンテキストを活用できていることがわかります。 Noise Sensitivity (ノイズへの敏感性) Noise SensitivityはRagasのものと同じ評価指標です。RagasのドキュメントにはRAGCheckerにNoise Sensitivityが導入されたと記載があり、持ち込まれた指標ということのようです。 Credits: Noise senstivity was introduced in  RAGChecker ( https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/noise_sensitivity/ より引用) Hallucination (ハルシネーション) モデルの回答のクレームのうちで、コンテキストに含まれない誤ったクレームの割合です。つまり、モデルが勝手に誤った情報を回答に出力した割合を表します。0に近いほど良好で、0を超える値で何らかのハルシネーションを起こしていることを表します。 Self-knowledge (自己知識) モデルの回答のクレームのうちで、コンテキストに含まれない正しいクレームの割合です。つまり、モデルがコンテキストにない情報を補った割合を表します。0から1の値をとりますが、どの値が良好かはユーザ次第です。根拠がある回答のみを求めている場合はこの値は低い方がよく、根拠がなくとも正しい情報であれば提示して欲しければ高い値がよいということになります。 Faithfulness (忠実性) モデルの回答のうちで、コンテキストに含まれるクレームが利用された割合です。Context utilizationと異なり、誤ったクレームも割合に含まれます。1に近いほどコンテキストに忠実に回答したことになり良好です。 RAGCheckerによるテスト実装 RAGChecker を用いることでテストを実装することができます。現在のところ普及度はあまり高くないので、公式以外のツールにはサポートされていないようです。今後の動きとして、AWSの標準的なRAG評価機能として、取り入れられる可能性は考えられます。 RAGの構成要素としてのLLMの評価 (RGB) RGBの考え方 RAGの全体的で外部的な挙動についての評価以外にもRAGを構成するコンポーネントごとの性能を評価するという考え方も存在します。RAGは検索ツールやLLMといった複数のコンポーネントからできているシステムであり、そのコンポーネントの単体を評価するという考え方です。 とりわけその中でもLLMの存在は中核となります。RGB (Retrieval-Augmented Generation Benchmark) [ 5 ] では「RAGの構成要素として」のLLMの能力を測る4つの指標を提案しています。その指標をご紹介します。 【補足3】これらの指標のうち、既存のLLMはNoise Robustnessはある程度能力を備えていますが、それ以外の3つの指標については改善の余地が大きいことが報告されています [ 5 ] 。 これらの能力はプロンプトエンジニアリングやファインチューニングで多少改善の余地があると思われますが、本質的にはLLMの根本の性能の改善される必要でしょう。一部の企業を除けば、LLMを一から学習させることは大きなコストがかかるため、LLMそのものの性能を向上させようと考えるのは現時点で得策ではありません。一方で、これらの課題を外付けのソリューションで解決する方法がよく検討されています。例えば、反事実への頑健性についてはGoogleによって提案されているファクトチェックツールの DataGemma や Retrieval Interleaved Generation ( RIG) [ 8 ] などの方法が提案されています。 RGBの指標 RGBでは図3の4つの指標を提案しています。これらについて説明します。 図3: RGBのLLM能力評価の観点4つ。[ 5 ]より引用。 Noise Robustness (ノイズへの頑健性) Noise Robustnessはコンテキストの中に回答に不必要な情報(ノイズ)が含まれている場合に、回答に必要な文書のみを参考に回答を生成できるかの能力を測ります。検索ツールは通常チューニングしても一定のノイズが含まれるため、LLMが情報を取捨選択する能力が必要となります。例えば、次のような関係のないコンテキストが検索結果に含まれていても適切に回答できる能力です。 ★質問 Who was awarded the 2022 Nobel prize in literature? (和訳: 2022 年のノーベル文学賞の受賞者は誰ですか?) ★コンテキスト 【関連するコンテキスト】The Novel Prize in Literature for 2022 is awarded to the Franch author Annie Ernaux, … (和訳: 2022年のノーベル文学賞はフランスの作家アニー・エルノーに授与される、・・・ ) 【関連しないコンテキスト】The Novel Prize in Literature for 2021 is awarded to the Franch author Abdulrazak Gurnah, … (和訳: 2021年のノーベル文学賞はフランスの作家アブドゥルラザク・グルナに授与される、・・・ ) ★回答 Annie Ernaux ([ 5 ]より引用、改変。) 類似の指標として既に紹介しているRagasやRAGCheckerもNoise Sensitivity (ノイズへの敏感性) という同様の指標を持っています。Noise SensitivityとNoise Robustnessは逆の指標となっていて、Noise Sensitivityは低く、Noise Robustnessは高い方が良好です。 Negative Rejection (回答不能な質問の却下) Negative Rejectionは検索された文書の中に回答に必要な情報が含まれていない場合に、回答を拒否する能力を測ります。通常、検索ツールは回答に無関係なコンテキストしか取得できない場合やそもそもコンテキストを取得できない場合があり、そのような場合にハルシネーションを起こすことなく回答を拒否できる必要があります。例えば、次のようなコンテキストにノイズのみが含まれている場合は回答できないと出力する能力のことです。 ★質問 Who was awarded the 2022 Nobel prize in literature? (和訳: 2022 年のノーベル文学賞の受賞者は誰ですか?) ★コンテキスト 【ノイス】The Novel Prize in Literature for 2022 is awarded to the Franch author Annie Ernaux, … (和訳: 2022年のノーベル文学賞はフランスの作家アニー・エルノーに授与される、・・・ ) 【ノイズ】The 2020 Nobel Laureate in Literature, poet Louise Gluck, … (和訳: 2020年ノーベル文学賞受賞者、詩人ルイーズ・グラック氏 、・・・ ) ★回答 I can not answer the question because of the insufficient information in documents (和訳: 資料の情報が不足しているため、質問にはお答えできません ) ([ 5 ]より引用、改変。) Information Integration (情報の統合) Information Integrationは回答に必要なコンテキストが複数ある場合にそれらの回答を統合して回答する能力を測ります。複数の情報を加味した上で回答しなくてならない複雑な質問では重要は指標となります。例えば、次のようにそれぞれのコンテキストに回答に必要な情報が含まれている場合にそれらを統合する能力です。 ★質問 When were the ChatGPT app for iOS and ChatGPT api launched? (和訳: iOS 用 ChatGPT アプリと ChatGPT API はいつリリースされましたか?) ★コンテキスト On May 18th, 2023, OpenAI introduced its own ChatGPT app for iOS… (和訳: 2023 年 5 月 18 日、OpenAI は iOS 用の独自の ChatGPT アプリを導入しました ・・・ ) That changed on March 1, when OpenAI announced the release of API access to ChatGPT and Whisper, … (和訳: OpenAI が ChatGPT と Whisper への API アクセスのリリースを発表した 3 月 1 日に状況は変わりました 、・・・ ) ★回答 May 18 and March 1. (和訳: 5月18日と3月1日。) ([ 5 ]より引用、改変。) Counterfactual Robustness (反事実への頑健性) Counterfactual Robustnessは検索されたコンテキストに事実と反する情報が含まれていた場合に、LLMがそのことを検知し提示する能力を測ります。情報源となる文書の品質が悪い場合には特に重要な指標となります。例えば、次のようにコンテキストの内容が事実誤認がある旨を報告できる能力のことです。 ★質問 Which city hosted the Olympic games in 2004? (和訳: 2004 年にオリンピックを開催した都市はどこですか? ) ★コンテキスト 【反事実】The 2004 Olympic Games returned home to New York, birthplace of the … (和訳: 2004 年のオリンピックは、ニューヨークに戻ってきました、・・・ ) 【反事実】After leading all voting rounds, New York easily defeated Rome in the fifth and vote … (和訳: すべての投票ラウンドでリードした後、ニューヨークは5位でローマを簡単に破り、投票しました… 、・・・ ) ★回答 There are factual errors in the provided documents. The answer should be Athens. (和訳: 提供された文書には事実誤認があります。答えはアテネでしょう。 ) ([ 5 ]より引用、改変。) G-EvalによるCoTを用いた評価 G-Eval [ 6 ] はCoT (Chain-of-Thoughts) を用いた評価手法で、NLGの評価全体に使える手法です。多くのユースケースに適用できる汎用性が高さが特徴です。RAG限定ではないですが、RAGの文脈でもよく登場します。G-Evalでは評価のステップについてLLMに指示し指標を定義します。LLMはその指示に従って、質問、コンテキスト、回答、Ground Truthなどのを使って評価をすることができます。RAGの評価においてもしばしば使われます。評価の自由度が高いため、RAGAs等に含まれていない指標をチェックしたいときに、独自にチェックしたい指標を追加することができます。 例えば、G-Evalによる評価指標の定義は次のようになります。Correctness(正確さ)という指標を定義しています。 (コード: DeepEvalによるG-Evalの実装例。 https://docs.confident-ai.com/docs/metrics-llm-evals より引用) from deepeval.metrics import GEval from deepeval.test_case import LLMTestCaseParams correctness_metric = GEval( name="Correctness", criteria="Determine whether the actual output is factually correct based on the expected output.", # NOTE: you can only provide either criteria or evaluation_steps, and not both evaluation_steps=[ "Check whether the facts in 'actual output' contradicts any facts in 'expected output'", "You should also heavily penalize omission of detail", "Vague language, or contradicting OPINIONS, are OK" ], evaluation_params=[LLMTestCaseParams.INPUT, LLMTestCaseParams.ACTUAL_OUTPUT, LLMTestCaseParams.EXPECTED_OUTPUT], ) 【補足4】CoTとはプロンプトエンジニアリングの一種で、LLMに複雑な推論をする際に複数のステップに分けて実行させることで、推論能力を向上させるテクニックです。予め、推論のステップについて、プロンプトで指示しておくことで実現します。 RAGのテストデータ生成手法 質問やGround Truthを人手で用意するには非常に手間がかかるため、自動生成したり、少数の注釈のみで評価が可能となるような手法も提案されています。例えば、Ragasでは コーパスを使ったテストデータの生成機能 を提供しています。 ARES (An Automated Evaluation Framework for Retrieval-Augmented Generation Systems) は少数の注釈のみでRAGを評価できる方法を提案しています [ 7 ] 。 LLMのテストフレームワーク RAGAs、RAGChecker、RGB、G-Evalなどの手法はそれぞれ論文と共に実装も提供されているので、個別のツールを使うことも可能ですが、テストフレームワークも使うことができます。サポーツされている指標には制約がありますが、テストツールとしてテストの管理がしやすいというメリットがあります。 LangSmith LangChain社が提供するLLMOpsのためのツールであり、有料(無料プランあり)のWebサービスとして提供されています。無料の場合は1ユーザのみでの利用が可能です。一部の機能に制約がありますが、ほとんどの機能は利用可能です。チーム開発では複数人での利用が前提となるので、ライセンスを購入して利用する必要があります。LangChainとの統合が容易であるという特徴があります。 DeepEval DeepEvalはConfident AI社が提供するLLMのテスト用のOSSのフレームワークです。Pytestと同じようなユニットテスト風にテスト実装ができ、テストケースの管理、データセットの生成、モデルの評価のLLMにおけるテスト全般をカバーしているのが特徴です。幅広い評価指標を取り込んでおり、Ragasを中心としてRAGの評価指標も実装されています。本番環境におけるオンライン評価も可能です。 SaaSとして提供されているLLM評価プラットフォームであるConfident AIとの統合によって評価や回帰テスト、監視が可能になります。 まとめ 今回は次のような内容をご紹介しました。 NLGの評価のアプローチ 人手評価 模範解答ありの自動評価 模範解答なしの自動評価 (LLM as a judge) NLGの評価のタイミング オフライン評価 オンライン評価 RAGの評価手法 RAGAs RAGChecker RGB G-Eval LLMのテストフレームワーク LangSmith DeepEval 現在までにRAGの評価では多くの手法が提案されており、RAGAsなどある程度の信頼がおける手法も出てきており、それらの手法を用いてRAGの評価を定量的にできるようになってきました。一方で、既存手法は少なくない課題が指摘されており、現時点で高いレベルで信用できる手法が存在しないのも事実です。評価の課題を解決するために頻繁に手法の提案や改善がされている状況であり、今後成熟していくことが期待される領域です。 最後までお読みいただきありがとうございました。このブログがお役に立てば幸いです。 RAGの改善手法については⇩のブログにご紹介していますので、こちらもぜひご覧になってください。 RAGはどのように進化しているのか?RAGのパラダイムと改善手法を体系的にご紹介! 【宣伝】生成AI ネクストテックソリューションのご紹介 弊社サイオステクノロジーでは生成AIを用いたトレーニング、コンサルティング、アプリケーション開発のソリューションを提供しています。ご興味のある方はぜひお問い合わせください! https://nextech-solutions.sios.jp/genai/ 参考文献 Lianmin Zheng ,  Wei-Lin Chiang ,  Ying Sheng ,  Siyuan Zhuang ,  Zhanghao Wu ,  Yonghao Zhuang ,  Zi Lin ,  Zhuohan Li ,  Dacheng Li ,  Eric P. Xing ,  Hao Zhang ,  Joseph E. Gonzalez ,  Ion Stoica, Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena , 2023. Shahul Es, Jithin James, Luis Espinosa-Anke, Steven Schockaert, RAGAS: Automated Evaluation of Retrieval Augmented Generation , 2023. 山田 育矢, 鈴木 正敏, 西川 荘介, 藤井 一喜, 山田 康輔, 李 凌寒, 大規模言語モデル入門Ⅱ 生成型LLMの実装と評価 , 技術評論社, 2024. Dongyu Ru, Lin Qiu, Xiangkun Hu, Tianhang Zhang, Peng Shi, Shuaichen Chang, Jiayang Cheng, Cunxiang Wang, Shichao Sun, Huanyu Li, Zizhao Zhang, Binjie Wang, Jiarong Jiang, Tong He, Zhiguo Wang, Pengfei Liu, Yue Zhang, Zheng Zhang, RAGChecker: A Fine-grained Framework for Diagnosing Retrieval-Augmented Generation , 2024. Jiawei Chen, Hongyu Lin, Xianpei Han, Le Sun, Benchmarking Large Language Models in Retrieval-Augmented Generation , 2023. Yang Liu, Dan Iter, Yichong Xu, Shuohang Wang, Ruochen Xu, Chenguang Zhu, G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment , 2023. Jon Saad-Falcon, Omar Khattab, Christopher Potts, Matei Zaharia, ARES: An Automated Evaluation Framework for Retrieval-Augmented Generation Systems , 2024. Sirui Xia, Xintao Wang, Jiaqing Liang, Yifei Zhang, Weikang Zhou, Jiaji Deng, Fei Yu, Yanghua Xiao, Ground Every Sentence: Improving Retrieval-Augmented LLMs with Interleaved Reference-Claim Generation , 2024. ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【RAG評価手法】評価できないものは改善できない!?体系的に評価指標をご紹介! first appeared on SIOS Tech. Lab .
アバター
OpenShift GitOps (ArgoCD) は、OpenShift 上で GitOps を実現するためのツールです。前回の記事では CI/CD における CI 部分の OpenShift Pipelines (Tekton) のエラー通知機能を構築しました。同様に CD 部分である OpenShift GitOps にもエラー通知機能を実装したいと思います。OpenShift GitOps には ArgoCD Notifications という通知機能が用意されているため、 こちら を参考に実装してみました。 ArgoCD Notifications について ArgoCD Notifications  は ArgoCD アプリケーションを監視し、状態の変更についての通知を管理するカスタムリソース(CR)です。下記のようなテンプレート、トリガー、サービス、サブスクリプションといったリソースを設定します。 テンプレート 通知テンプレートメッセージを定義します。 トリガー ユーザーに通知が送信される条件と、メッセージを生成するために必要なテンプレートのリストを定義します。 サービス メッセージをどこに配信するなどの設定を定義します。 サブスクリプション   通知送信先などの設定をします。例えば Slack だと、どのチャンネルにどのトリガーを適用させるといった設定を定義します。Argo CD のアプリケーションの Annotations に定義します。 OpenShift GitOps では、通知を有効にして Red Hat OpenShift GitOps でクラスターを作成すると、デフォルトで default-notifications-configuration という名前の NotificationsConfiguration CR が作成されます。Argo CD では argocd-notifications-cm ConfigMap にリソースを定義しますが、OpenShift GitOps では default-notifications-configuration にカスタムリソース設定を記入します。ここに加えられた設定は Argo CD の Config Map に反映されますが、直接 Argo CD の Config Map を変更しても default-notifications-configuration で上書きされてしまう点に注意が必要です。 前提条件 OpenShift 4 クラスターが構築済みであること OpenShift GitOps Operator がインストールされていること oc CLI がインストール済みであること Slack に通知を送信するワークスペース、チャンネルが用意されていること 事前準備 Gitリポジトリの用意 下記構成のプライベートなマニフェスト用 Git リポジトリを用意します。アプリケーションをデプロイするためのマニフェストファイルが格納されています。 app ├── deployment.yaml ├── kustomization.yaml ├── route.yaml └── service.yaml deployment .yaml apiVersion: apps/v1 kind: Deployment metadata:   name: busybox-deployment spec:   replicas: 1   selector:     matchLabels:       app: busybox   template:     metadata:       labels:         app: busybox     spec:       containers:       - name: busybox         image: busybox         args:         - /bin/sh         - -c         - "while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; echo 'Hello from BusyBox'; } | nc -l -p 8080; done"         ports:         - containerPort: 8080 kustomization .yaml resources: - deployment.yaml - service.yaml - route.yaml route.yaml apiVersion: route.openshift.io/v1 kind: Route metadata:   name: busybox-route   labels:     app: busybox spec:   to:     kind: Service     name: busybox-service   port:     targetPort: 80 service.yaml apiVersion: v1 kind: Service metadata:   name: busybox-service spec:   selector:     app: busybox   ports:     - protocol: TCP       port: 8080       targetPort: 8080   type: LoadBalancer ArgoCD のデプロイ設定 OpenShift GitOps を構築してみた を参考にして下記手順を実施します。 OpenShift GitOps のログイン Argo CD へのデプロイ権限の付与 プライベートリポジトリの登録 Slack Web App の準備 通知をSlack に送信するためには、Slack App を作成し、適切な権限を付与する必要があります。 前回の記事 で Slack App を作成している場合は使いまわすことが出来るので、作成パートは飛ばしてもらって問題ありません。ややこしいのですが、OpenShift Pipelines (Tekton) では Webhook を使用しましたが、OpenShift GitOps ではSlack の OAuth Token を使用します。 Slack App のページから Create New App をクリックします。 From scratch をクリックします。 App Name を入力して、Slack App を追加するワークスペースを選択します。  Basic Information が表示されれば完了です。OAuth & PermissionsをクリックしてScopesを追加します。 Add an OAuth Scope をクリックして chat:write を追加します。 Install to ワークスペースをクリックしてワークスペースにアクセスする権限を許可します。 Slack に移動して通知を送信したいチャンネル名をクリックして、インテグレーションタブからアプリを追加します。 アプリ名を検索してアプリを追加します。 Slack のチャンネルにアプリが追加された旨のメッセージが表示されていることを確認して完了です。 OpenShift GitOps 通知設定 Argo CD インスタンスの通知を有効化 下記コマンドを実行して通知を有効化します。  $ oc patch argocd openshift-gitops -n openshift-gitops --type merge --patch '{"spec": {"notifications": {"enabled": true}}}' argocd.argoproj.io/openshift-gitops patched Slack App のトークンを持つシークレットを作成します。 $ oc apply -f secret.yaml Bot User OAuth Token は Slack App の OAuth & Permissions から確認できます。 secret.yaml apiVersion: v1 kind: Secret metadata:   name: argocd-notifications-secret   namespace: openshift-gitops stringData:   slack-token: <Bot User OAuth Token> 下記コマンドを実行して spec.notifications.enabled フィールドの値が true になっていることを確認します。 $ oc get argocd openshift-gitops -n openshift-gitops -o yaml apiVersion: argoproj.io/v1beta1 kind: ArgoCD metadata:   creationTimestamp: "2024-11-21T01:26:00Z"   finalizers:   - argoproj.io/finalizer   generation: 2   name: openshift-gitops   namespace: openshift-gitops ︙ spec: ︙   notifications:     enabled: true ︙ Argo CD インスタンスの通知設定の追加 下記コマンドを実行してArgo CD インスタンスの通知設定の追加を行います。 $ oc edit notificationsconfiguration default-notifications-configuration -n openshift-gitops テキストエディタが開いたら、spec以下に下記のようなservicesを追記します。templates,triggersはデフォルトのままで大丈夫です。 ︙ spec:   services:     service.slack: |       token: $slack-token   templates:  ︙ アプリケーションの作成 プロジェクトの作成 $ oc new-project sample-app 下記コマンドを実行してArgoCDの通知先が設定されたアプリケーションを作成します。 $ oc apply -f application.yaml application .yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata:   name: sample-app   namespace: openshift-gitops   annotations:     notifications.argoproj.io/subscribe.on-deployed.slack: webhook_test     notifications.argoproj.io/subscribe.on-sync-failed.slack: webhook_test     notifications.argoproj.io/subscribe.on-sync-succeeded.slack: webhook_test     notifications.argoproj.io/subscribe.on-health-degraded.slack: webhook_test     notifications.argoproj.io/subscribe.on-created.slack: webhook_test     notifications.argoproj.io/subscribe.on-sync-running.slack: webhook_test     notifications.argoproj.io/subscribe.on-deleted.slack: webhook_test spec:   project: default   source:     repoURL: < マニフェスト用 Git リポジトリ (.gitで終わるURL)>     path: app     targetRevision: main   destination:     server: https://kubernetes.default.svc     namespace: sample-app   syncPolicy:     automated:       prune: true       selfHeal: true アプリケーションがデプロイされていることを確認します。 動作確認 Slack の指定したチャンネルに通知が届いていることを確認して完了です。 まとめ OpenShift GitOps のエラー通知を Slack に送信する機能を構築し、その手順をまとめました。O penShift GitOps では、 ArgoCD Notifications  という既存の機能を有効にして通知を送信してみました。 ArgoCD Notifications のハンズオンとしても参考になれば幸いです。 参考文献 https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/#notifications-overview https://docs.redhat.com/ja/documentation/red_hat_openshift_gitops/1.13/html/argo_cd_instance/notifications-configuration-custom-resource-properties_argo-cd-cr-component-properties#notifications-configuration-custom-resource-properties_argo-cd-cr-component-properties ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift GitOps のエラー通知を Slack に送信してみた first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 アドベントカレンダー4回目の登場です。 今日はAzure FunctionsでNo HTTP triggers foundのエラーが発生した時の調査方法のお話です。 根本的な解決策ではないのですが、エラー解消の手がかりになればいいなと思い 備忘録の意味も込めて、記事を書いていこうと思います。 はじめに pythonの実行環境でAzureFunctionsにアプリをデプロイした際に 「デプロイが失敗しているわけでもないのに、何故か関数が表示されない!!」 といったことが結構起こります。 具体的には以下のようなケースです。 ・デプロイ時にエラーメッセージは発生しない(がエンドポイントのURLは表示されない) デプロイ実行 func azure functionapp publish func-hogehoge --python 結果 Resetting all workers for func-hogehoge.azurewebsites.net Deployment successful. deployer = Push-Deployer deploymentPath = Functions App ZipDeploy. Extract zip. Remote build. Remote build succeeded! [2024-12-02T04:03:16.963Z] Syncing triggers... Functions in func-hogehoge: //ここで本当はデプロイされるURLが表示されるはず C:\hogehoge ・VSCodeの拡張機能のデプロイ機能からやってみるとNo HTTP triggers found.と表示される 12:05:49 func-hogehoge: Removing existing manifest file 12:05:49 func-hogehoge: Running pip install... 12:06:01 func-hogehoge: Syncing triggers... 12:06:02 func-hogehoge: Querying triggers... 12:06:06 func-hogehoge: No HTTP triggers found. ・Azure Portalから見た時に関数が表示されない ・ソースコードのファイル自体はアップロードされているように見える こんな問題が起きた際の調査方法を今日は書き記していこうと思います。 調査方法 まずは皆が通る道として以下のような感じでググるかと思います。 Azure Functions No HTTP trigger Azure Functions 関数 表示されない そうすると結構な数がヒットするので、困っている人は多そうです。 例えばこちらの stackoverflow なんかを見てみると、まさに同じような現象が起きている人も見受けられます。 そして、このエラーに対する回答として多種多様な回答が来ています。 つまり、様々な要因によってこのエラーは引き起こされているようです。 自分と同じ現象の人にたどり着くのはなかなか難しそうで、しらみつぶしに試していくのは骨が折れます。 ちなみに色々ググって見つけた解決方法としては 環境変数の値が正しく設定されていない 環境変数に余計な値が登録されている インストールしているパッケージに依存して起きるもの といった内容が多かった気がします。 話は戻り やみくもに試すのではなく、自分の環境に基づいて調査を行う場合にどこを見ればいいかというと 今回の場合はAzure Portal上の、該当するFunctions Appの「問題の診断と解決」でした。 そして今回は、その中でも Python関数 という指標を選択します。 すると以下のような形で、例外一覧が表示されています。 やたらめったらデプロイしていたので、例外がたくさん発生しています。 いくつか例外が発生している中で、今回原因となっていたのは以下の例外でした。 Timestamp : 12/2/2024 7:15:18 AM Inner Exception Type: Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException Total Occurrences: 44 Latest Exception Message: Worker failed to index functions Result: Failure Exception: TypeError: Client.__init__() got an unexpected keyword argument 'proxies' Stack: File '/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py', line 469, in _handle__functions_metadata_request self.load_function_metadata( File '/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py', line 449, in load_function_metadata self.index_functions(function_path, function_app_directory)) \ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File '/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py', line 822, in index_functions indexed_functions = loader.index_function_app(function_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File '/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/utils/wrappers.py', line 44, in call return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File '/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/loader.py', line 244, in index_function_app imported_module = importlib.import_module(module_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File '/usr/local/lib/python3.11/importlib/__init__.py', line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File '', line 1204, in _gcd_import File '', line 1176, in _find_and_load File '', line 1147, in _find_and_load_unlocked File '', line 690, in _load_unlocked File '', line 940, in exec_module File '', line 241, in _call_with_frames_removed File '/home/site/wwwroot/function_app.py', line 47, in openai_client = AzureOpenAI( ^^^^^^^^^^^^ File '/home/site/wwwroot/.python_packages/lib/site-packages/openai/lib/azure.py', line 205, in __init__ super().__init__( File '/home/site/wwwroot/.python_packages/lib/site-packages/openai/_client.py', line 112, in __init__ super().__init__( File '/home/site/wwwroot/.python_packages/lib/site-packages/openai/_base_client.py', line 793, in __init__ self._client = http_client or SyncHttpxClientWrapper( ^^^^^^^^^^^^^^^^^^^^^^^ どうやらAzureOpenAIを呼び出すクライアントに余分な引数が渡されているようです。 このエラーを解消し、再度デプロイしたところ正常にアプリがデプロイされ、関数も表示されました。 めでたし! 正直これまでAzure Portalの「問題の診断と解決」についてはあまり見てこなかったのですが、 今後はこちらの内容もしっかり押さえて、エラー解消などに役立てたいところです。 Application Insightsとの違いは? ちなみに「Application Insightsでは分からないの?」と思われる方もいると思うのですが あれはどちらかというとアプリが正常に起動した後のフェーズの監視ツールのイメージです。 実際、今回のエラーに関してはApplication Insightsの方には何も表示されていませんでした。 今回はそもそもアプリ起動時の処理でコケてしまっていたため、Application Insightsの監視範囲外だったのではないかと思います。 redditに こんな 回答もあり、自分としても同じ認識を持っています。 診断設定は、リソース自体からログ/メトリックを取得します。また、診断設定を通じてサービス/OS 自体からどのログ/メトリックが公開されるかは、MS のリソースによって決定されます。 Application Insightsは、Azureリソース上で実行されるコードを通じてこのタイプのデータを取得します。これは、独自の診断コードを挿入することによって行われます。 (日本語訳) そして今回も「Azure Functions」といった リソース の起動エラーであったため、「問題の診断と解決」の方に記録されたのではないかと思いました。 (もしApplication Insightsの方でも確認する方法などありましたら是非コメントなどで教えてください。) 「問題の診断と解決」の機能に関しては他にも色々と機能があるようなので 必要に応じてしっかり使い分けていきたいところです。 参考: Azure App Service 診断の概要 まとめ 今回はAzure Functionsの関数が正しくデプロイされない場合のケースについての調査方法の備忘録でした。 このようなケースにおいては、Azure Portalの「問題の診断と解決」にエラー内容が記載されている ことがある 、ということが分かりました 必ずしも記載があるわけではないと思うのですが、一度目を向けてみるとエラー解消の手がかりがあるかもしれません。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure Functions】No HTTP triggers found発生時の調査方法 first appeared on SIOS Tech. Lab .
アバター
こんにちはPS/SLの佐々木です。 今回はバージョン管理ツールasdfを使ってみようと思います https://asdf-vm.com/guide/introduction.html asdfとは asdfとはツールのバージョンマネージャーです。 従来は言語ごとにnvmやrenv pyenvなどバージョン管理ツールを使用していたと思います。 しかしasdfを使用するとこれらのバージョン管理ツールは不要になり全てasdfで管理できるようになります。 私もnode.jsのバージョン管理にnodenv, n, nvmなど一つの言語で複数のバージョン管理ツールが共存していると言う非常にカオスなローカル環境が出来上がっていたり、久しぶりに触る言語で何のバージョン管理ツールを使用していたのか調べるのが面倒だったりと色々悩まされていましたが、asdfで全て解決されそうな予感。。。 インストール方法 https://asdf-vm.com/guide/getting-started.html#_1-install-dependencies 今回はMacbookを使用したInstall方法を紹介します。 そのほかのインストール方法は上記のリンクを参考にinstallしてみてください。 brew install asdf 今回はzshにhomebrewでinstallしているので以下のコマンドを実行します echo -e "\\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc 基本的な使い方 特定のバージョンの言語を使えるようにするまでに以下のようなステップを踏みます pluginのインストール 利用可能なバージョンのチェック 使用したいバージョンのインストール 現在使用されているバージョンの確認 ローカルのバージョン設定 グローバルでのバージョン設定 今回はgoを使えるようにします。 まず使用できるpluginの一覧を調べます。 一覧を全て表示すると非常に多いのでgrepしています。 asdf plugin list all | grep golang golang *<https://github.com/asdf-community/asdf-golang.git> golangci-lint <https://github.com/hypnoglow/asdf-golangci-lint.git> golangのプラグインを導入します asdf plugin add nodejs h[ttps://github.com/asdf-community/asdf-golang.git](<https://github.com/asdf-community/asdf-golang.git>) installすることができるgoのバージョンを調べます asdf list all golang とりあえず最新バージョンのgoをinstallしてみましょう asdf install golang latest installできました! asdf list golang *1.23.3 goのバージョンを確認してみたのですが、go command not foundということでどうやらパスが通ってないっぽいので以下のコマンドを実行します export PATH="$HOME/.asdf/shims:$PATH" これで再度goのバージョンを確認します go version go version go1.23.3 darwin/amd64 うまくいきました! go version go version go1.23.3 darwin/amd64 ではバージョンを切り替えてみます。 少し古いバージョンのgolangをinstallします asdf install golang 1.19.4 installできました asdf list golang 1.19.4 *1.23.3 まだバージョンはlatestのままですね。 go version go version go1.23.3 darwin/amd64 バージョンを切り替えます asdf global golang 1.19.4 go version go version go1.19.4 darwin/amd64 かわっていますね! 応用 複数のプロジェクトを並行して行なっている場合にプロジェクトに応じでバージョンを切り替えたいですよね。 そのような場合にasdfではディレクトリ単位でバージョンを管理することができます。 適当にディレクトリを作ってバージョンをセットしてみます。 mkdir gopj && cd gopj asdf local golang latest go version このようにすると .tool-versions というファイルが作成されます。 このファイルにはツールのバージョンが記載されています。 ls -la -rw-r--r--@ 1 kantasasaki staff 14 Nov 29 15:44 .tool-versions cat .tool-versions golang 1.23.3 ディレクトリを元に戻すとgoのバージョンがglobalに設定していたものに戻っています。 ちゃんとプロジェクトごとにシームレスにバージョン管理がされていることが確認できました。 cd ../ go version go version go1.19.4 darwin/amd64 まとめ 今回はasdfの簡単な使い方について解説しました。 複数のツールのバージョンを一括で管理することができ、さらにプロジェクトごとに使用したいバージョンをシームレスに管理できるのは非常に素晴らしいですね。 これからの人生asdfと共に歩んでいこうと思いました。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post バージョン管理ツールasdfを使ってみた first appeared on SIOS Tech. Lab .
アバター
ご挨拶 ども!弊社もアドベントカレンダーを開催中です。タグから「2024アドベントカレンダー」を選んでもらえれば今年分が覗けるかと思います。温泉行幸旅行から帰宅して、肌つやが最高によい龍ちゃんです。 さて、今回は頭の整理も含めて、Firestoreについて整理をしていこうと思います。Firestoreは個人開発の強い味方だと思っています。フロントエンドエンジニアからすると、手軽に認証とデータベースを追加できるという二点において神ツールです。実際に僕がプロト開発でDBを扱う場合だと、真っ先に選定されます。 今回の記事は、こんな方に読んでほしいです! firestoreのデータ構造がいまいちつかめない Firestoreを触ったことないけど、どんなもんなん? サブコレクションを使いだしたら混乱してきた では、失敗談も含めてお話していきたいと思います。 僕がしていた勘違いとミス まずは、僕がしていた勘違いとミスについて書いておこうと思います。 おそらく、クスっと笑ってもらえたかと思います。そんなことあるわけないですよね?やはり導入の手ごろさが癖になって、どんどんノリで開発をしていていました。そして、クエリ混沌を生み出していたわけです。 ここからは反省して改心した僕が書いています。 実際にRDBよりは、ガチガチとした設計を必要としません。特に型定義は、ソースコードで挿入する際に入ってきたデータで構造が決定されます。クエリを使用する場合では、実現したいシナリオにデータ構造を寄せておいた方が良いです。シナリオベースでデータ構造を決める作業を一つ設計として導入するべきですね。 ちょうど、今日の業務内容のメモにあったので共有しておきます。 この整理があるのとないのでは、だいぶ違います。 さて….ここまではポエムなので、そろそろ本題に入っていきます。 ここから本題:Firestoreの図解 Firestoreのイメージは、公式だと以下のイメージで図解されています。 参考 Firestore  |  Firebase Firebase 確かに端的に表現しており、良い図ですね。Firestoreを使えるようになってから見ると、この図のイメージで問題はありません。はい!「使えるようになってから」って部分が難しいところですよね。ここに落とし穴があるんです。これだけでも理解できる方向けに、各項目の説明をラフに書いておきます。 コレクション:フォルダのようなイメージで、ドキュメントを複数保存する ドキュメント:ファイルのようなイメージで、データまたはフォルダを保存する データ:key-valueで値を保存する では、図解していきます。 図解:ルートフォルダとコレクションの関係 まずは、一番トップのイメージになります。実際の画面だと、【コレクションを開始】と書かれている列ですね。 これは、【ディレクトリしか保存することができないディレクトリ】が一番イメージが近いと思います。 すべてはコレクションから始まります。すべてを飛ばしてドキュメントを作成することはできないことを押さえておきましょう。 図解:コレクション内部にあるドキュメント 次にコレクションの内部に保存するドキュメントとデータについて図解していきます。画面だとこの部分です。 先ほどの資料では、ドキュメントは一枚の紙のイラスト(もしくはGoogle Doc)で表現されていました。ここが落とし穴です。ドキュメントは、関連してサブコレクションを持つことができます。つまり、一枚のドキュメントと関連するフォルダーからなるグループ群がドキュメントとなります。 ドキュメントでは、サブコレクションとフィールド(データ)を保存することができます。フィールドでは、Key-Value型で情報を保存することができます。サブコレクションの内部では、また同一にこの世界が広がっていきます。 単一の構造で済む場合は、ドキュメントに情報を保存することで公式が出しているスタイルで済みます。ですが、サブコレクションを導入した途端に複雑な構造になってしまいます。 データの取り出し方(クエリを書く前) ドキュメントやデータの検索の方法について解説しておきます。基本的にDBが欲しい時は、データを保存したい時ですよね。(これは当たり前か) データの特定方法は、ざっくりと三通り紹介します。 単一ドキュメント:ドキュメントのIDを指定して取得 複数ドキュメント:コレクションを指定して一括取得 複数ドキュメント:コレクショングループを指定して一括取得 各内容について図解していきます。 単一ドキュメント:ドキュメントIDを指定して取得 取得するドキュメントに関する情報がすべてわかっている場合では、こちらの方法を使用して取得することができます。 単一ドキュメントの取得は、どの位置のドキュメントか特定する必要があります。一階層の場合は、コレクションIDとドキュメントIDの二つでドキュメントを取得することができます。 サブコレクション内に存在するドキュメントの場合は、大元のコレクションからすべてのパスを取得する必要があります。二階層の場合は、コレクションIDとドキュメントIDを用いて、所属するサブコレクションを特定します。サブコレクションIDとドキュメントIDを用いてドキュメントを取得することができます。 この手法では、階層が深くなるほどドキュメント取得に必要な情報が多くなります。 複数ドキュメント:コレクションを指定して一括取得 こちらは、複数ドキュメントを取得・検索するときに使用します。単一階層の場合では、コレクションIDと条件(where)を指定しない場合は、所属するドキュメントすべてを取得します。サブコレクションを対象とする倍は、コレクションIDとドキュメントID・サブコレクションIDの三つが必要になります。 ドキュメント取得には、 条件や並び替え を指定することができます。ドキュメントに含まれるデータによって検索することができます。こちらの検索条件を含めてクエリと呼んでいますが、クエリの条件に関しては、次の章で解説を入れておきます。 複数ドキュメント:コレクショングループを指定して一括取得 こちらも、複数ドキュメントを取得・検索するときに使用します。先ほどの『コレクションを指定して一括取得』とほぼ同等ですが、コレクションの指定の仕方が異なります。 コレクショングループ を指定して取得します。 こちらは、シナリオベースで理解するほうが早いです。コレクションIDは自動でIDを振る方法と自分で任意の名前を付ける方法があります。「ユーザーコレクション内にそれぞれTODOを保存しているサブコレクション」があると仮定します。先ほどの方法では、何度もクエリを叩く必要があります。取得のイメージは以下になります。 コレクショングループで、『todo』を指定します。すべてのドキュメントのサブコレクション(todo)からドキュメントを取得します。一致するコレクションIDすべてから、ドキュメント群をすべて取得します。 もし、ほかのコレクションやサブコレクションにtodoがあった場合は、そこからも情報が取得されます。そのため、コレクショングループを使用する場合は、コレクションIDを付けるのは注意して行いましょう。 クエリの制限 基本的な情報はすべて 公式リファレンス に記載があります。開発の際に詰まった内容としては、コレクションに対しては、単純にwhere句を使用することができます。ですが、コレクショングループを使用する場合は、indexを作成する必要があります。 エラーメッセージが出てきて、URLが出てきた場合はアクセスするだけでビルドしてくれます。3~10分程度待てばビルドされるのでおとなしく待ちましょう。 Firestoreでは配列をそのままデータとして保存することができます。配列に対しては、[array-contains/array-contains-any/in/not-in]( ここです )といったメソッドを使用することができます。 こちらのメソッドすべてに共通することですが、配列にはオブジェクトを保存することができます。検索系のメソッドの場合はオブジェクトが完全一致するなどの処理でしかできません。いい説明が思いつかないので、コードで表現してみます。 const string_array = ["A","B","C","D","E"] as string [] // Aを検索 // string_arrayには含まれる const object_array = [{label:"A", value:1},{label:"B", value:2}, {label:"C", value:3}] // {label "A"}といった検索はできない // objectの場合は、すべての情報が一致しなければいけない そのため、オブジェクト配列を使用する際は考えて実装する必要があります。 また、配列の長さに関してはクエリを発行することができません。解決策としては、 こちらの情報 が参考になります。日本語訳にすると、配列の長さを保存するKey-Valueを保存してそちらをキーにして情報を精査します。 どのように開発していくと良いか? とりあえず必要な話は、全て図解しました。自分の失敗談を含めて、今後開発をするためにはどのような手順を踏むべきかについて書いていこうと思います。 実現したい内容をシナリオベースで言語化する 仕様が変わるときは、DBの構造自体を変更することを厭わない 色々なシナリオで失敗パターンを経験しておく 一番大事なのは、『シナリオ化』になります。詳細に言語化することが一番大切だと思います。このシナリオ化の程度は、メモレベルでも十分だと思います。コードレベルで構造を決定することもあり、走り出して作り上げることが可能です。その一方で、仕様変更に耐えることができるのか?という疑問があります。経験則ですが、勢いで作り上げたFirestoreは特殊な構造になったいると思います。後から、構造や仕様を変更しようとすると迷子になるのでメモは取っておきましょう。 次の『仕様が変わるときは、DBの構造自体を変更することも厭わない』と『いろいろなシナリオで失敗パターンを経験しておく』は関係深いと思います。Firestoreでは、できること・できないこと・できるけど実装しにくいことの三つがあります。そういったパターンを網羅することは、難しいですし、自分の実装パターンを持っておくことが大切だと思います。先ほども「作り上げることができる」とは書きましたが、これにはできるけど実装しにくいことが含まれる場合は、いっそのことDBを一から構築しなおしましょう。案外、構造を変えることですっきりするかもしれません。 終わり 最後まで読んでいただき、ありがとうございます。本記事がFirestoreの理解の一助になれば幸いです。特に個人開発やプロトタイプ開発では、Firestoreの柔軟性と使いやすさは大きな武器となります。 次回は、実際のプロジェクトでの具体的な実装例についても触れていければと思います。もし質問やご意見がありましたら、コメント欄でお待ちしています。 それでは、また次回の記事でお会いしましょう! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Firestoreの使い方を改めて図解しておく first appeared on SIOS Tech. Lab .
アバター
こんにちは。サイオステクノロジーの木村です。 サーバーのメンテナンス作業などを行う際に、サイトにアクセスしてきたユーザーに通常の画面を表示せずに「メンテナンス中画面」を表示する方法について記載します。 通常の画面表示とメンテナンス画面の表示を簡単に切り替えられるよう、maintenance.html というファイルが存在すればメンテナンス画面を表示し、すべてのアクセスに対して maintenance.html を返すようにします。 環境 Apache/2.4.62 (Rocky Linux) 手順 1. メンテナンス画面のHTMLファイルを maintenance.html.off というファイル名で作成します。 ・ maintenance.html.off <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>メンテナンス中</title> <style> body { text-align: center; } </style> </head> <body> <h1>ただいまメンテナンス中です。</h1> <p>しばらくお待ちください。</p> </body> </html> 2. 作成したhtmlを、 /var/www/html 配下におきます。 3. /etc/httpd/conf.d/maintenance.conf を作成し以下を記載します。 ・ maintenance.conf ErrorDocument 503 /maintenance.html <IfModule mod_rewrite.c> RewriteEngine On ## メンテナンス画面表示を除外したいIPアドレスがある場合はこちらに記載 RewriteCond %{REMOTE_ADDR} !=123.456.789.000 # メンテナンスページが存在する場合の処理 RewriteCond %{DOCUMENT_ROOT}/maintenance.html -f RewriteCond %{REQUEST_URI} !^/maintenance\.html$ RewriteRule ^.*$ /maintenance.html [R=503,L] </IfModule> 4. SSLでアクセスする場合は、 /etc/httpd/conf.d/ssl.conf に以下の記載を追加します。 ・ ssl.conf <VirtualHost _default_:443> ・・・(省略)・・・ Include conf.d/maintenance.conf ・・・(省略)・・・ </VirtualHost> 4. 上記設定を反映させるためリロードします。 systemctl reload httpd 以上で設定は完了です。 5. メンテナンス画面を表示したいときは、ファイル名を maintenance.html に変更します。 mv /var/www/html/maintenance.html.off /var/www/html/maintenance.html 6. メンテナンス画面の表示をやめたいときは、ファイル名を maintenance.html.off に戻します。 mv /var/www/html/maintenance.html /var/www/html/maintenance.html.off ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Apache でメンテナンス中画面を表示する first appeared on SIOS Tech. Lab .
アバター
挨拶 ども!ちょっと休暇をとって温泉地に移動中の龍ちゃんです。2泊3日で温泉を堪能する予定です。 今回は、だいぶ特殊な要件:「Tailwindを純粋なCSS Styleのみに変換したい」を満たす内容でニッチすぎる内容になっています。僕はHTMLメールをTailwindから書きたいという部分から始まりました。 mailwind Tailwindで表現したHTMLをstyleに変換して出力してくれるライブラリが「 mailwind 」になります。こちらのライブラリは、HTMLファイルを解析して以下のことができます。 CSSファイル出力 Inline-CSS形式で記述されたHTML形式ファイル出力 参考 GitHub – soheilpro/mailwind: Use Tailwind CSS to design HTML emails. GitHub 環境構築 すでにHTML + Tailwindでコーディングをできる環境は整っている前提で進めていきます。もし整っていない方は、以下の記事を参考にして自分なりの環境を整えてください。 2022-10-21 Tailwind環境をシンプルに構築 :Tailwind 2022-10-25 シンプルなTailwind環境構築を効率的に改革 Browsery Sync mailwind Setup 環境のセットアップはとても簡単に完了します。 npm install mailwind こちらのコマンドだけでインストールは終了です。次に実行コマンドについて記載しています。mailwindでは、入力として二つのファイルを受け取ることができます。 入力 解説 —input-html Tailwindで記載されているHTMLファイル ※必須 —tailwind-config Tailwindの設定ファイル(デフォルトでtailiwnd.config.jsになっている) 出力としては、以下の二つになります。 出力 解説 —output-html 入力で受け取ったHTMLファイルにinline-style形式で追記されたファイル —output-css 入力で受け取ったHTMLファイルで定義されているTailwindクラスのCSSファイル 出力はどちらか一方でも、両方でも値として渡すことができます。両方渡してもあんまり意味ないですけどね。 参考のコマンドです。 # inline cssのみ mailwind --input-html public/input.html --output-html output.html # CSS ファイルのみ生成 mailwind --input-html public/input.html --output-css style.css # inline-style:html css両方作成 mailwind --input-html public/mail.html --output-html output.html --output-css style.css Example:before → after 出力の結果をサンプルとして置いています。 こちらをtailwind形式で記載したファイルが以下になります。 <div class="flex flex-row items-center justify-start gap-4 w-full p-10 flex-wrap"> <div class="inline-flex w-52 flex-col gap-2 p-2 rounded-md bg-white shadow"> <h2 class="text-lg font-bold">まっすぐ歩く</h2> <p class="text-green-500">実行中</p> </div> <div class="font-bold text-2xl">→</div> <div class="inline-flex w-52 flex-col gap-2 p-2 rounded-md bg-white shadow"> <h2 class="text-lg font-bold">右に曲がる</h2> <p class="text-red-500">実行終了</p> </div> </div> こちらをmailwindを用いてinline-style形式に変換したのが以下になります。 <div class="flex flex-row items-center justify-start gap-4 w-full p-10 flex-wrap" style="display: flex; width: 100%; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 16px; padding: 40px;"> <div class="inline-flex w-52 flex-col gap-2 p-2 rounded-md bg-white shadow" style="display: inline-flex; width: 208px; flex-direction: column; gap: 8px; border-radius: 0.375rem; background-color: #fff; padding: 8px; --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);"> <h2 class="text-lg font-bold" style="font-size: 18px; font-weight: 700;">まっすぐ歩く</h2> <p class="text-green-500" style="color: #22c55e;">実行中</p> </div> <div class="font-bold text-2xl" style="font-size: 24px; font-weight: 700;">→</div> <div class="inline-flex w-52 flex-col gap-2 p-2 rounded-md bg-white shadow" style="display: inline-flex; width: 208px; flex-direction: column; gap: 8px; border-radius: 0.375rem; background-color: #fff; padding: 8px; --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);"> <h2 class="text-lg font-bold" style="font-size: 18px; font-weight: 700;">右に曲がる</h2> <p class="text-red-500" style="color: #ef4444;">実行終了</p> </div> </div> ファイルを見ていただいたらわかる通り、必要な情報がすべてHTMLに乗っています。 試したけどできなかったこと tailwind.configで記載しているGoogle Fontsの情報はロードされませんでした。ただ、定義した追加・自作のTailwindに関しては反映されていました。 どうしても使用したい場合は、HTML側に記載しておくなどの対応が必要そうです おわり ども!今回の要望はだいぶニッチだったなと我ながら思います。そんなニッチの要望も世界のどこかで需要があってライブラリが開発されているのってすごいですよね。 ちなみに僕は社内メールをTailwindを書きたかったので、今回のライブラリを発見しました。そこから発展してStremlitでHTMLでデザインをするときも利用できそうということで、次回のブログのネタにしておきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Tailwindをstyle属性へ変換【mailwind】 first appeared on SIOS Tech. Lab .
アバター
element. --> こんにちは、サイオステクノロジーの佐藤です。 満を持して2024年アドベントカレンダー3回目の登場です! 今回はCosmosDBのパーティションについてご紹介します。 パーティション は、前回ご紹介したRUと同じくCosmosDBにおいて非常に重要な概念となります。 コンテナ作るときにPartitionKey設定するけどこれって何の値? どんな値をパーティションキーに設定すればいいの? 論理パーティションと物理パーティションキーって何? といった方は、是非最後までご覧ください! はじめに 今回は、CosmosDBのパーティションについて勉強したことをアウトプットしていきます。 パーティションとは何か 論理パーティションと物理パーティションの違い 分割方法はどういったものがあるか 良いパーティションキーの設定とは? といった点について紹介していきたいと思います。 ただパーティション分割の設計ノウハウまで突っ込めるほどまだ精通できていないので あくまで概要の紹介にとどまりますが、ぜひ最後までご覧ください! パーティションとは そもそもパーティションとはなんでしょうか? CosmosDBにおけるパーティションについては、以下2つのものが存在します。 論理パーティション(Logical Partition) 物理パーティション(Physical Partition) これらは似て非なるものであるため、 文脈や会話の中で「パーティション」と出てきた際は、どちらを指しているかを正しく把握しておきましょう。 論理パーティション 論理パーティション(Logical Partition)は、コンテナがパーティションキーによって分割されたサブセットの単位になります。 “論理”という名がついている通り、ハードウェア的に分離されてはいません。 あくまでCosmosDB上でソフトウェア的に分離されているサブセットになります。 では パーティションキー とはなんでしょうか? CosmosDBでコンテナを作成する際に、指定が必須の項目でもあります。 これはコンテナを論理パーティションに分割し、水平方向にスケーリングするために使われる値です。 コンテナがどのように論理パーティションに分割されるかを見ていきたいと思います。 例として、以下のようなデータベース・コンテナを考えます。 Property Name Database Restaurants Container Foods Partition Key /country そして、以下のようなアイテム群が Foods コンテナに格納されているとします。   [     {         "foodId": "001",         "name": "寿司",         "country": "日本",  //partition key         "price": "2000",         "category": "米類"     },     {         "foodId": "002",         "name": "うどん",         "country": "日本",  //partition key         "price": "500",         "category": "麺類"     },     {         "foodId": "003",         "name": "パスタ",         "country": "イタリア",  //partition key         "price": "1000",         "category": "麺類"     },     {         "foodId": "004",         "name": "餃子",         "country": "中国",  //partition key         "price": "300",         "category": "点心類"     } ] この場合、以下の図ような形で論理パーティションに分割され、その論理パーティションの中に該当アイテムが格納されます。 なお、この論理パーティションの数には制限はありませんが、ストレージ容量に関しては制限があります。 いち論理パーティションあたり20GBまでのデータしか格納することが出来ません。 そのため膨大なデータを格納する場合は、より論理パーティションを分割するために パーティションキーの値を見直す 合成パーティションキー(後述)を採用する 階層パーティションキー(後述)を採用する といった対応を検討します。 なお、一度作成した論理パーティションの内容は変更できません。 新規のパーティションキーを設定して、新たにコンテナを作り直し、データを移行する必要があります。 物理パーティション 論理パーティションと双璧をなしているのが 物理パーティション(Physical Partition) です。 ただし、CosmosDBを利用するエンジニアがこの物理パーティションの分割を考慮する必要はありません。 そこはCosmosDB側で完全に管理してくれます。 論理パーティションとの関係性を見てみたいと思います。 1つ、または複数の論理パーティションが単一の物理パーティションに割り当てられます。 逆に1つの論理パーティションが、複数の物理パーティションに割り当てられることはありません。 先程の例に照らし合わせると、以下のような感じです。 物理パーティションの容量も50GBといったように制限はありますが、これを超過しそうになった場合でも CosmosDB側で、物理パーティションを分割して論理パーティションの割り当てを入れ替えることによってこれを回避します。 インパーティションクエリとクロスパーティションクエリ 論理パーティションと物理パーティションの概要が分かったところで 適切にパーティション分割が行われることによるメリットについてお話したいと思います。 先程、論理パーティションを分割をすることで20GBのデータ許容量を超えないようにすることが可能であると述べましたが データ容量の観点の他にも、スループットの面で恩恵を受けることができます。 例えばFoodsコンテナに対して、以下のようなクエリを実行します。 select * from c where c.country = "日本" このクエリを実行した際、コンテナ全体(全ての物理パーティション)に対して検索がかかるのではなく 日本 の論理パーティション内、正確にはその論理パーティションと対応する 物理パーティションA でのみ検索が行われます。 このように検索範囲が絞られることにより検索速度も向上しますし、利用されるRU数も少なく済みます。 このように、ひとつの物理パーティション内でのみ検索が行われるものを、 インパーティションクエリ と呼びます。 一方で select * from c where c.category = "麺類" といったクエリの場合は、論理パーティションを跨いだ検索が行われます。 つまり、該当するアイテムがどこの物理パーティションに存在するかが不明であるため、**全ての物理パーティションごとに**検索が行われます。 これを クロスパーティションクエリ と呼び、インパーティションクエリに比ると検索速度が劣化します。 とはいいつつ、実際のところ完全にインパーティションクエリだけでアプリケーションを実装することは不可能に近いと思います。 CosmosDB側もクロスパーティションクエリが行われることを想定しており、このクエリを並列化し、高速化するような最適化の手段がSDKなどには提供されています。 以下のようなケースを除いて、そこまで必死に回避する問題ではないとMSのドキュメントにも書かれていました。 30,000 より多くの RU をプロビジョニングする予定 100 GB を超えるデータを格納する予定 スループットの分散 ここからが重要なポイントなのですが コンテナーに対してプロビジョニングされたスループットは、 物理パーティション間 で均等に分割されます。 例えばFoodsコンテナに4000RU/sのスループットが割当たっている場合 上記の図においては、物理パーティションA,Bそれぞれに2000RU/sのスループットが割り当たります。 そして、選択したパーティションキーによって データとアクセスが均等に分散されるようにパーティション分割が行われている事 ことが非常に重要です。 このパーティション分割が正しく行われない場合、 ホットパーティション と呼ばれる現象が発生することが懸念されます。 ホットパーティション ホットパーティションは、特定のパーティションにデータやアクセスが集中していることを指します。 例えば先程のデータベースの例で、以下のような状況だとします。 日本食がとても有名なレストラン 日本食のメニューがとても多い お客さんの大半が日本食を注文する すると、データベースの状況としては以下のようなことが起こりえます。 先程も述べたように 物理パーティションは与えられたスループットを平等に分割して利用する ひとつの論理パーティションを複数の物理パーティションに分割することはできない といった事情があるため、このひとつの物理パーティションにデータ・アクセスが集中することは避けられません。 このような状況では 物理パーティションA 1000RU/sのスループットでは処理しきれない 物理パーティションB 1000RU/sのスループットを持て余す(コストの無駄) といった状況が起こりえます。 また、ストレージの面でも同様のことが言えます。 最初に述べたように、1つの論理パーティションの最大容量は20GBです。 そのため、1つの論理パーティションにデータが集中してしまうと、すぐにデータ許容量を超えてしまいます。 そのため、各物理・論理パーティションにデータやアクセスが分散されるように、パーティション分割を行うことが非常に重要です。 なお、ホットパーティションは開発時はデータが少なくて気づかないことが多く、**本番運用の際に大量のデータが入って初めて発覚するケースも多い**ため注意が必要です。 各パーティションにおける利用率はAzureMonitorにて確認が可能です。 例えば、 PartitionKeyRUConsumption の指標を見ることで、パーティションキーあたりのRU/s使用率を確認できます。 また、 PartitionKeyStatistics の指標を見ることで、各パーティションの容量を確認することができます。 これらの値を参照しながら、適切にデータ・アクセスが分散しているかを確認しましょう。 パーティションキーの設定 適切なパーティション分割を行うために、パーティションキーの設定が重要であることが分かりました。 ここでは、パーティションキー設定に関する方法をご紹介します。 まず、大前提としてCosmosDBが顧客(アプリ)によってどのように使われるかを検討することがとても大切です。 全く同じデータを格納する場合でも、使われ方によってパーティションキーの選択は変わってきます。 例えば先程のRestaurantデータベースの例においては 読み取りのアクセスが多いのか、書き込みのアクセスが多いのか 何をフィルターとして検索することが多いのか 値段 カテゴリ 国情報 など、まずはどのようにアプリが使われるかをしっかりと把握します。 パーティションキーの設定の基本 アプリの使われ方を把握したら、次にパーティションキーの検討を始めます。 まず、パーティションキーの設定を設定するうえで、以下のことに気を付けます。 パーティションキーの値が更新されないこと Stringの型であること パーティションキーの値の種類が広範囲に広がること(=カーディナリが高いこと) 各論理パーティションに対してデータ・アクセスが均等に分割されること パーティションキーの値の長さを最大でも2KB以内とすること これらの点を踏まて、パーティションキーを設定します。 そのうえで、「アイテム要素1つだけだとうまく均等に分散させれなさそう」といった場合に 合成パーティションキー 階層パーティションキー といったパーティションキー設定の方法を検討します。 合成パーティションキー 合成パーティションキーは、複数の要素を組み合わせをキーとする方法です。 これまで扱ったデータベースを題材とすると、 "country + category" といった形の合成キーを考えます。 コンテナ作成時のPartition keyの値としては /partitionKey といったものを追加し アイテムをアップロードする際に、以下のような値を追加します。 {     "foodId": "001",     "name": "寿司",     "country": "日本",     "price": "2000",     "category": "米類",     "partitionKey":"日本-米類" //countryとcategoryを組み合わせた文字列を生成 } 他のアイテムに関しても同様に値を追加します。 {     ...     "partitionKey":"日本-麺類"     ... }, {     ...     "partitionKey":"イタリア-麺類"     ... }, {     ...     "partitionKey":"中国-点心類"     ... } これにより、論理パーティションが4つ作成されることが想定されます。 論理パーティションが3つ→4つに増えたことにより、先程起きていたホットパーティションを多少回避できそうです。 ただし、合成パーティションキーを実施することによるデメリットも発生します。 先ほどインパーティションクエリの例で挙げた以下のクエリですが select * from c where c.country = `日本` 合成パーティションキーを使用した場合は、country単体ではパーティションキーは設定していないため、クロスパーティションクエリが発生します。 また、そもそもPartitionKeyを設定するためだけに、無駄な結合字列を追加するのもあまり気持ちいいものではありません。 これらのメリット・デメリットを踏まえて合成パーティションキーの採用を検討する必要がありそうです。 階層パーティションキー 階層パーティションキー(HPK)は、階層的にパーティションキーを設定する方法です。 コンテナ作成時に Add hierarchical partition key を選択することで、3階層まで設定が可能です。 例えば、上記の例だと "country/category" といった2階層のパーティションキーを設定しています。 この時、countryのパーティションキーによって論理パーティションに分割され、 更に2階層目 category によって サブバーティション と呼ばれるものに分割されます。 こちらも先程の合成パーティションキーと同じく、データやアクセスを論理パーティションで分散できるものです。 では合成パーティションキー比べて何が違うというと、 そもそも無駄な情報( partitionKey )を追加しなくていい 上位のパーティションキーのみでの検索が可能 といったメリット点があります。 このサブセットを有効活用するようなクエリとしては以下のような形となります。 select * from c where c.country = `日本` and c.category = `麺類` この場合、サブセットパーティション単位でのクエリとなるため、インパーティションクエリとして実行が行われます。 また、以下のような上位のパーティションキーのみをフィルタに用いたクエリでも効率的に検索が行えます。 select * from c where c.country = `日本` 「以下のクエリでも効率的に検索が行えます。」と曖昧に書いたのですが、理由としてはその仕組みにあり 日本/麺類 と 日本/米類 といったサブセットがある場合、これらがそれぞれ別の物理パーティションに割り当てられる可能性があります。 つまり、 日本(category) というレベルで見た場合は、別々の物理パーティションに分かれる事があるのです。 そのため、どこの物理パーティションにアイテムが存在しているか分からず、全ての物理パーティションに対して検索がかかるのかな… と思ったのですが、実際のところはそうではないみたいです。 ここはMSのドキュメントを引用しますが、どうやらいい感じにルーティングを行ってくれるようです。 完全またはプレフィックスのサブパーティション分割されたパーティション キー パスを指定することで、完全なファンアウト クエリを効率的に回避できます。 たとえば、コンテナーに 1000 個の物理パーティションがあり、特定の TenantId 値がそのうちの 5 つにしかない場合、クエリは少数の関連する物理パーティションにのみルーティングされます。 ※ここで書かれている TenantId は上記最上位のPartitionKeyを指しており、上記の例でいうcountryと同列。 ※ファンアウトクエリ=全ての物理パーティションごとにクエリを実行すること。 ということで、詳細までつかめていないので「効率的に検索が行えます」といった曖昧な書き方にとどめました。 このあたりしっかり分かったらまた追記修正します。 それで話は少し戻るのですが 今回、 country/category のサブパーティションの単位でストレージ20GBの制限が設けられます。 つまり、 country のレベルで見た場合、20GB以上のデータを保持することが可能になるのです。 これが単一の country をパーティションキーとした比較した場合のメリットになります。 これまでの情報をまとめると、階層パーティションキーを利用することで データ・アクセスを分散させることが出来る 上位のパーティションキーだけでも20GB以上のデータを保持できる 上位のパーティションキーだけでも効率的な検索が行える といったメリットがあることがうかがえます。 ただ、この効率の良い検索もあくまで上位パーティションキーのみが対象で select * from c where c.category = `麺類` といった、下位のパーティションキーで検索をかけた場合はクロスパーティションクエリとして扱われるので注意が必要です。 パーティションキーにアイテムIDを設定する 最後に、パーティションキーの値にアイテムID(=”/id)”を採用することについてご紹介します。 この”/id”とはCosmosDBにアイテムを追加した場合に自動で割り当てられる値です。 例えば以下のようなデータを追加した場合でも このような値が登録され、 id というGUIDのような値が割当たっています。 (もしくはidの値を自分でも設定することが可能ですが、ここでは「アイテムごとに異なる値である」という前提で話を進めます。) この値をパーティションキーとすることで、全データを全て異なる論理パーティションに分散させることができます。 分散の極みであり、ホットパーティションとは無縁ですね。 なおかつ、この id 値が分かっている場合は非常に高速で、低いRUで検索が行うことができます。 「え、そんなに何十万、何百万っていう個数の論理パーティション作っていいの…?」 と不安になる方もいるかもしれませんが、心配ありません。 MSのドキュメントにも以下のように書かれていました。 ID をパーティション キーにした場合、顧客の数だけ論理パーティションが存在し、各論理パーティションに 1 つのドキュメントしか格納されていない状態になるのでは、と不安になるかもしれません。 何百万人もの顧客がいれば、何百万個もの論理パーティションができることになります。 ただし、これはまったく問題ありません。 論理パーティションは仮想的な概念であり、持てる論理パーティション数に制限はありません。 Azure Cosmos DB により、同じ物理パーティション上に複数の論理パーティションが併置されます。 論理パーティションの数またはサイズが大きくなると、Cosmos DB により、必要に応じて新しい物理パーティションに移動されます。 参考: https://learn.microsoft.com/ja-jp/training/modules/implement-non-relational-data-model/6-choose-partition-key そのため、遠慮なく必要であれば id の値をパーティションキーとして設定しましょう。 まとめ 今回はCosmosDBのパーティションについてまとめてみました。 論理パーティションと物理パーティションの違いや、パーティションキーの設定についてなんとなく分かっていただけたのではないでしょうか? パーティションキーの設定に関しては色々と奥が深そうなので、また触っていくうちにアウトプットしていきたいと思います。 引き続きCosmosDBの学習を続けていきたいと思うので、また読んでいただけると幸いです。 ではまた! 参考 https://learn.microsoft.com/ja-jp/azure/cosmos-db https://learn.microsoft.com/ja-jp/training/modules/implement-non-relational-data-model/6-choose-partition-key おまけ 前回の記事でも紹介しましたが、2024年のMicrosoft Ignite でCosmosDBのベーシックな内容が紹介されていました。 Partition Keyの設定に関しても触れられていたので、是非こちらも見ていただければと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 1人がこの投稿は役に立ったと言っています。 The post 【Azure】CosmosDBにおけるパーティション入門ガイド【初心者向け】 first appeared on SIOS Tech. Lab .
アバター
この記事では、複数のAIモデルを無料で簡単に比較できる便利なAI比較サイト「 天秤AI 」について、魅力と活用方法をご紹介します。 天秤AIを使うことで、各社のAIモデルを同時に利用・比較でき、どのAIが自分のニーズに最適かを手軽に見極めることができます。 天秤AIで何ができる? 「天秤AI」は、無料で複数のAIモデルを同時に利用できるサービスです。以下の3つの特徴を持っています: 無料 (1日に利用できる制限あり) 複数のAIに同時に質問を投げて、それぞれの回答を比較することが可能 GPTやGeminiなど、異なる企業のAIモデルを一度に利用可能 みてもらったほうがわかりやすいので、早速画面をお見せします。   このように、質問を入力すると、各AIが同時に回答してくれます。   左のメニューで使用するモデルを選び、右側に追加していく形で設定します。 1つのモデルからでも利用でき、 最大で6つのAIモデルを同時に利用可能 です。 無料で利用できますが、1日あたりの利用量に上限が設けられており、利用量に応じて制限がかかります。 天秤AIの利用ケース 天秤AIは、以下のような場面で役立ちます。 AIの性能比較 : この利用法だとGPTとGeminiどっちが良いかな?というときに、さっと試すことができます。 AIの検証 : 新しいプロンプトエンジニアリングの手法を試してみる際に、1回で複数の結果が得られるので、効率的に試すことができます。このモデルだとうまくいくけど、このモデルだとダメみたいなこともちょくちょくあります。 無料で簡単に試す : 新しいAIモデルを試したいけれど費用が気になるという場合でも、各社のAIを無料で試せます。 利用制限時の代替手段 : ChatGPT-4.0を利用していたが利用制限に引っかかった場合、制限中は天秤AIで同じモデルを使うことで解決できます。 実際に使ってみる 実際に天秤AIを使ってみましょう。 天秤AIで利用可能な中で、各社の代表的なモデルである、GPT-4.0、Gemini 1.5 Pro、Claude 3.5 Sonnetを利用して、「使っていると頭が良く思われそうな語彙を教えて」と質問してみます。 拡大->   GPTは語彙を列挙すると同時に意味を簡潔に説明してくれ、端的な回答をしています。 Geminiはブログのようにタイトルから始まり、注意点を述べた後、カテゴリごとに語彙を列挙し詳細な説明を加えています。他のモデルと比べて回答量が2〜3倍あります。 Claudeは実践的な言い換え表現を教えてくれており、他のモデルとは異なり語彙の説明はありません。 このようにシンプルな質問でも、各モデルの回答に意外な差が出ることがあります。   次に、ちょっとした検証として、AIに意地悪な質問をしてみます。 「音楽バンド、ミスターイエローポテトは何人組だっけ?」   1人だけ、すごく嘘をついてくる人がいます:   「嘘はつかないで!」と加えてみます。 嘘をつかなくなりました。 こちらは以前検証してみたので、詳しくはこちらをご覧ください: chatGPTに「ハルシネーションしないで」とお願いしたら効果がある?   この、「嘘の回答をしてくるモデルに対して、嘘つかないで!というとどうなる?」という検証では、まず「嘘の回答をしてくるモデル」を探す必要がありますが、これを3つのモデルに対して一気に質問することで、効率的に検証を進めています。 このように、プロンプトの検証を複数のAIで一気に行うことで、試行回数を減らし効率的に検証を進めることができます。 天秤AIのデメリット 天秤AIでは、ClaudeのArtifactsや、最近GPTでリリースされたCanvasなどの高度な機能を利用することはできず、基本的なモデルの比較や利用に限定されています。 これらの新機能は非常に強力であり、天秤AIのシンプルな機能では物足りなく感じるかもしれません。 あくまで天秤AIは、これらの高度な機能を必要としないシンプルなモデル比較やプロンプトの試行に適したツールです   まとめ 天秤AIは、複数のAIモデルを無料で手軽に比較できる便利なツールです。 ちょっとAIの性能を比較したい、プロンプトを効率的に検証したい、そんな方におすすめです。 興味がある方はぜひチェックしてみてください! 天秤AI ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post どのAIが最強?最適なAIモデルを探せる「天秤AI」の紹介 first appeared on SIOS Tech. Lab .
アバター
ども!寒さが本格的になってきてタイプミスが随分と増えてきている龍ちゃんです。 こちらの記事は依然執筆した、「LINEミニアプリで作るチャットゲーム」の開発の際に気を付けていたポイントについてまとめています。 2024-09-17 LINE×生成AI:チャットバトルゲームを作る! これからLINEミニアプリを作る人の助けになったらうれしいなと考えています。 開発に関して 開発の構成としては、フロントエンドとバックエンド分割した形で開発を進めていきました。フロントエンドをReactで、バックエンドをnest.jsで構成しています。 画面は2画面で、作成したAPIとしては3つになります。APIのざっくりとした役割としては、以下のよう内容です。 対戦相手取得:データベースからランダムに一名の情報を取得 戦績取得:LINEログインしているユーザーの情報を取得 審判AIによる判定:AOAIにアクセスして戦闘描写と勝敗を返答する 開発の際に詰まったポイント・注意点 開発の際には、いろいろ詰まった点があるのですがLIFFアプリだからこそ詰まった点に注目して大きく3点に分割してみました。 リファレンスでも「 LIFFアプリ開発ガイドライン 」というページがあるので、是非ご一読ください。 トークンの取り扱い・LINE登録情報の取得 これは、セキュリティにも関係してくるので一番気にした方が良いですね。今回の構成は、バックエンド側でAPIとして処理をするのでフロントエンドで取得した情報をバックエンドに送信する必要があります。ユーザー特定のために固有のIDを取得する必要がありました。 参考 LIFFアプリを開発する リファレンスでは、以下の二パターンでユーザー情報の取得が紹介されてます。 フロントのみで扱う場合 LIFF SDKからデコード済みのIDTokenを取得する サーバーに送信して扱う場合 AccessTokenをサーバーに送信しサーバー側でトークン検証・ユーザー情報を取得する 今回はAPIを作成したので、フロント側で取得したAccessTokenをHeaderに付与してサーバー側で情報を取得する構成で実装しました。ガイドとして公開されていたのでこちらに沿って開発をしています。 参考 LIFFアプリおよびサーバーでユーザー情報を使用する フロントエンドでLINEからのアクセスか確認 LIFFアプリは、LINE内から専用のURLを開いた際に実行されます。静的アプリとしてデプロイしている場合は、普通にアクセスができますが、LIFF SDKの初期化に失敗します。こんな時に便利な関数として、 liff.isInClient(); があります。こちらは、実行環境を判定することができます。LIFFアプリ外からのアクセスの際にはアプリとは別の画面を表示して、LINEの友達登録誘導なんてこともできるかと思います。 参考 LIFF v2 APIリファレンス 動作確認 LINEを使って開発するときは、いつでも直面する問題ですね。HTTPS化したURLしか受け付けてもらえません。さすがに開発期間中に、毎回動作確認のためにデプロイはやってられないです。そこで活躍するのが、 ngrok さんですね。お手軽に手元でHTTPS化したURLを取得することができます。 終わり 今年は、様々な形態のデモを準備していました。デモも来場される方の属性によって注目を集めれたりなかったりと様々です。LINE関連のデモの場合は、若い世代の方に好評でした。これからもひっそりと開発を進めていきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post LINE LIFFアプリを開発する際にはまったポイント first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 アドベントカレンダー登場2回目です。 今日はRagasのv0.2における日本語のテストセット生成方法についてご紹介します。 すぐに利用できるソースコードも載せてますので、「最新のRagas使ってテストセットを自動生成したい!」という方は是非最後までご覧ください。 はじめに 本日紹介するのは、現状最新バージョンであるv0.2のRagasを使ったテストセット生成方法です。 テストセットとは、Ragasの評価時に利用される質問と回答のペアのデータになります。 このRagasでは、与えた文章に基づいて質問(question)と回答(reference)のペアを自動で作成してくれます。 例えば「社内規約」の文章を与えた時には、その文章に基づき 質問:有給休暇は何日取れますか? 回答:繰越すことで最大で40日まで取得可能です といったペアを生成します。 今回のケースであれば、「社内規約」をよく知る人間がテストセットを生成するのが一番間違いはないのですが 人力で膨大なテストセットを作成するのも大変なので、Ragasの機能で自動生成してもらうのも一つの手段かとは思います。 公式ドキュメントにテストセット生成に関するチュートリアルがあるのですが、 チュートリアルをそのまま行うと日本語のドキュメントを読み込んでも、英語の内容でテストセットが生成されてしまいます。 そのため本記事では、日本語でテストセットを紹介する方法をご紹介したいと思います。 なお、本記事はv0.2.6のバージョンにおける内容であり、今後変更の可能性があります。 最新の情報に関しては公式のドキュメントを参照してください。 現状の把握 v0.1の時からもテストセットの生成方法の機能は用意されていました。 ただ、v0.1から大きなリファクタリングが実施され、利用方法が異なっています。 とはいいつつ、丁寧な チュートリアル が提供されているのでその通りやれば問題なくテストセットが生成されます。 ただ、この通りに実施すると、日本語の文章を読み込ませたとしても質問と回答のペアが英語で出力されてしまいます。 この理由としては、テスト生成に利用するためのプロンプトが英語で書かれているためです。 これに対して、「多言語に対応どうやるの?」といった内容の Issue も挙がっていました。 Issueに対する実装としては既にマージ済みなのですが、ドキュメントには現状書かれていないようです。 こちらの Issue に、「TODOリストとしてドキュメントを作成する」というタスクは追記してあるので、順次対応予定のようです。 ただ、そこを一歩先取りして本ブログで紹介してしまおう!というのが本記事の目的です。 ということで、将来的には既に公式ドキュメントに記載されているかもしれませんし、もしかしたら実装方法が変更になっている可能性もあります。 まだまだRagasも変化も多い状況だと思うので、その点踏まえて読んでいただきたいと思います。 多言語対応の仕組み まず初めに多言語対応の仕組みについて紹介します。 その方法はずばり、 構築済みのプロンプトに日本語を適用する です。 そしてこの方法が「 Adapting metrics to target language 」として公式の記事にも紹介されています。 またこれはテストセット生成に限った話ではなく、 FaithfulnessやContextRecallの評価といった通常の評価フェーズの際にも利用できる仕組みです。 adapt_prompts というメソッドを利用し、既に用意されているプロンプトに対して指定した言語を適用させます。 そしてこのメソッドは PromptMixin というクラスで定義されており、このクラスは以下のように定義されています。 Mixin class for classes that have prompts. つまり、これを継承する「プロンプトを扱うようなクラス」は adapt_prompts を利用できることになります。 この仕組みを利用し、テストセットを生成するプロンプトに対して日本語を適用し、日本語のテストセットを作成していきます。 実装 チュートリアルの確認 まずは チュートリアル にあるテストセット生成の流れを確認します。 なお今回はAzure OpenAI Serviceを利用してテストセット生成を行います。 ChatとEmbeddingsのモデルをそれぞれデプロイしておいてください。 チュートリアルの内容に沿って以下のソースコードを作成しました。 なお、エンドポイントやAPIキーなどは.envファイルに格納しているため、適宜作成してください。 import os import asyncio from dotenv import load_dotenv from ragas.llms import LangchainLLMWrapper from ragas.embeddings import LangchainEmbeddingsWrapper from ragas.testset import TestsetGenerator from langchain_openai import AzureChatOpenAI, AzureOpenAIEmbeddings from langchain_community.document_loaders import DirectoryLoader #.envファイル変数読み込み load_dotenv() # 環境変数に値をセット os.environ["AZURE_OPENAI_API_KEY"] = os.getenv("AZURE_OPENAI_API_KEY") os.environ["AZURE_OPENAI_ENDPOINT"] = os.getenv("AZURE_OPENAI_ENDPOINT") os.environ["OPENAI_API_VERSION"] = os.getenv("OPENAI_API_VERSION") async def main(): # ChatModel定義     generator_llm = LangchainLLMWrapper(AzureChatOpenAI(         azure_deployment="gpt-4o-mini-deploy",         temperature=0.8,     ))     # EmbeddingsModel定義 generator_embeddings = LangchainEmbeddingsWrapper(AzureOpenAIEmbeddings(         azure_deployment="text-embedding-3-small-deploy"     )) # Generatorの生成     generator = TestsetGenerator(llm=generator_llm, embedding_model=generator_embeddings) # テストセット生成のベースとなる文章をロード     path = "Sample_Docs_Markdown/"     loader = DirectoryLoader(path, glob="**/*.md")     docs = loader.load()     # テストセット生成 testset = generator.generate_with_langchain_docs(docs, testset_size=3)     df = testset.to_pandas()     # データフレームをCSVファイルとして保存     csv_file_path = "generated_testset.csv"     df.to_csv(csv_file_path, index=False) asyncio.run(main()) 今回は読み込むドキュメントとしては、サイオステクノロジーに関する Wikipedia の内容をDocumentIntteligenceでmd化したものとします。 sios.mdというファイルでSample_Docs_Markdownの配下に保存します。 Smaple_Docs_Markdown/sios.md では上記のプログラムを実行します。 すると以下のようなテストセットが出力されました。(一部省略) なぜか、2つ目の質問だけは日本語で回答されましたが、他は見事に英語です。   user_input reference_contexts reference synthesizer_name What historical developments have shaped our current understanding of the subject? [‘1 沿革\n\n’] The historical developments that have shaped our current understanding of the subject are not detailed in the provided context. AbstractQuerySynthesizer How do the technological offerings and solutions of サイオステクノロジー compare with those of other companies in the fields of open source software, business continuity solutions, and cloud integration, particularly in relation to Linux and Gluegent Apps? [‘サイオステクノロジー株式会社は、オープンソースソフトウェアとJavaを基盤にしたシステムやソフトウェアの開発、販売、サポートを行う企業で、2017年に設立されました。主な製品には、事業継続ソリューションの「LifeKeeper」やデータ複製ソフト「DataKeeper」があります。また、Google Appsとの連携を提供するクラウドソリューションや、業務プロセスを簡素化するワークフローシステム「Gluegent Flow」なども展開しています。さらに、セキュリティソリューションやオープンソースに関するサポートも行っています。’] サイオステクノロジーは、オープンソースソフトウェアやJavaを基盤にしたシステムの開発、事業継続ソリューションの提供、Google Appsとの連携を含むクラウドソリューションを展開しており、特にLinuxやGluegent Appsに関連する技術的な提供やソリューションは、他社と比較して独自の製品群を持っています。 ComparativeAbstractQuerySynthesizer What functionalities do Gluegent Apps provide for companies using Google Workspace or Microsoft 365? [‘7 外部リンク\n\n☐目次の表示・非表’] Gluegent Apps provide functionalities such as a shared address book for searching and selecting personnel within a company, a group scheduler for visualizing schedules by department or team, and gadgets that can be embedded in corporate portal sites, all designed for companies using Google Workspace or Microsoft 365. SpecificQuerySynthesizer 2つ目の回答が日本語だったことに関しては 「サイオステクノロジー」が重要な単語であると推察され、質問文作成時に翻訳されなかった 質問文に日本語が入っているため、回答としても日本語で返された といったことではないかな、と考察しました。 ちなみに内容としてはそれなりにいい感じです。 なので、テストセット生成としては問題ないのですが、英語に精通していない人間が評価内容をチェックするのが大変です。 では、いよいよここから日本語対応していきます。 日本語化対応 先程述べた adapt_prompts を利用していきます。 こちらの プルリクエスト にて以下のサンプルコードが書かれていたのですが これだけだと全体が把握できなかったのでこれを踏まえて手探りでやっていきます。 synthesizer = AbstractQuerySynthesizer() adapted_prompts = await synthesizer.adapt_prompts("dutch", llm) synthesizer.set_prompts(**adapted_prompts) どうやら、 QuerySynthesizer というのが肝のようです。 これについては公式のドキュメントにも定義があり、シナリオを作成するための役割を持ちます。 「シナリオって何?」と思われるかと思うのですが、テストセット生成の仕組みに関しては別途記事にしたいと思うので、ここでは割愛させていただきます。 簡単に書くと、様々な質問文を生成するために必要な情報(質問の長さ、使用する情報)をまとめたものになります。 そしてこのシナリオを元に質問文(=question=Query)や回答のペアを生成します。 つまり、このQuerySynthesizerがテストセットを作成する親玉であり、ここに対して日本語を適用していきます。 なお、このQuerySynthesizerの元になっているBaseSynthesizerというクラスを見ると、 PromptMixin クラスを継承していることも確認できます。 つまり adapt_prompts のメソッドも使えることが分かりますね。 そして、この日本語を適用したQuerySynthesizerをどこで反映させるかというと テストセットを作成する generate_with_langchain_docs の引数として与えることができます。 なのでステップとしては QuerySynthesizerに対して日本語を適用(adapt_prompts) 日本語が適用されたQuerySynthesizerを利用してテストセット生成 といった感じです。 流れが分かったところで早速これらを反映したソースコードを見てみます。 import os import asyncio from dotenv import load_dotenv from ragas.llms import LangchainLLMWrapper from ragas.embeddings import LangchainEmbeddingsWrapper from ragas.testset import TestsetGenerator from langchain_openai import AzureChatOpenAI, AzureOpenAIEmbeddings from langchain_community.document_loaders import DirectoryLoader from ragas.testset.synthesizers import AbstractQuerySynthesizer load_dotenv() os.environ["AZURE_OPENAI_API_KEY"] = os.getenv("AZURE_OPENAI_API_KEY") os.environ["AZURE_OPENAI_ENDPOINT"] = os.getenv("AZURE_OPENAI_ENDPOINT") os.environ["OPENAI_API_VERSION"] = os.getenv("OPENAI_API_VERSION") async def main():     generator_llm = LangchainLLMWrapper(AzureChatOpenAI(         azure_deployment="gpt-4o-mini-deploy",         temperature=0.8,     ))     generator_embeddings = LangchainEmbeddingsWrapper(AzureOpenAIEmbeddings(         azure_deployment="text-embedding-3-small-deploy"     ))     generator = TestsetGenerator(llm=generator_llm, embedding_model=generator_embeddings)     path = "Sample_Docs_Markdown/"     loader = DirectoryLoader(path, glob="**/*.md")     docs = loader.load()     #Synthesizerのインスタンスを生成     synthesizer = AbstractQuerySynthesizer(llm=generator_llm)     #シンセサイザーのプロンプトに日本語を適用     adapted_prompts = await synthesizer.adapt_prompts("japanese", generator_llm)     #プロンプトをセット     synthesizer.set_prompts(**adapted_prompts)     #generate_with_langchain_docsに引き渡すためのデータ整備     query_distribution = [         (synthesizer, 1.0) #1.0は割合を表し、今回はこのSynthesizerを100%利用することを表す。他のSynthesizerと組み合わせる事も可能。     ]   # テストセット生成     testaset = generator.generate_with_langchain_docs(docs, testset_size=3, query_distribution=query_distribution) #query_distributionを引数としてあたえる       df = testset.to_pandas()     # データフレームをCSVファイルとして保存     csv_file_path = "generated_testset.csv"     df.to_csv(csv_file_path, index=False) asyncio.run(main()) このプログラムを実行すると以下の結果が得られました。 全ての質問および回答が日本語で生成されている ことが分かります。 user_input reference_contexts reference synthesizer_name 沿革の重要性は何ですか? [‘1 沿革\n\n’] 沿革の重要性は、歴史的な背景や発展の過程を理解することで、現在の状況や未来の方向性を把握する手助けとなることです。 AbstractQuerySynthesizer 企業名の由来はどう企業のアイデンティティや価値反映するの? [‘2 社名の由来\n\n’] 企業名の由来は、企業のアイデンティティや価値を反映する重要な要素です。 AbstractQuerySynthesizer 主な製品・サービスはどのように相互に関連し、ビジネス戦略に寄与するのか? [‘3 主な製品・サービス\n\n’] 主な製品・サービスの相互関連性とビジネス戦略への寄与についての具体的な情報は提供されていません。 AbstractQuerySynthesizer なお、今回はPRのusageを例にAbstractQuerySynthesizerを採用したため非常に抽象的なテストセットとなりました。 もちろん他のSynthesizerを利用しても問題ありません。 試しに ComparativeAbstractQuerySynthesizer を使うため、以下の部分の書き換えを行います。 synthesizer = ComparativeAbstractQuerySynthesizer(llm=generator_llm) # 対象のSynthesizerを変更 adapted_prompts = await synthesizer.adapt_prompts("japanese", generator_llm) synthesizer.set_prompts(**adapted_prompts) すると以下のような結果が得られ、回答内容がガラッと変わることも分かります。 user_input reference_contexts reference synthesizer_name サイオステクノロジー オープンソースソフトウェア 事業継続ソリューション Linux クラウドソリューション 技術 特性 機能 比較 評価 レポート [‘サイオステクノロジー株式会社は、オープンソースソフトウェアとJavaを基盤にしたシステムやソフトウェアの設計、開発、販売、サポートを行う企業で、2017年に設立されました。主な製品には、事業継続ソリューションの「LifeKeeper」やデータ複製ソフト「DataKeeper」があります。また、Google Appsとの連携を提供するクラウドソリューションや、業務プロセスを簡素化するワークフローシステム「Gluegent Flow」なども展開しています。さらに、オープンソースに関するサポートやトレーニングも行っており、セキュリティソリューションとして「i-FILTER」や「m-FILTER」も提供しています。’] サイオステクノロジー株式会社は、オープンソースソフトウェアを基盤にした事業継続ソリューションやクラウドソリューションを提供しており、主な製品には「LifeKeeper」や「DataKeeper」があります。 ComparativeAbstractQuerySynthesizer サイオスのオープンソースソフトウェアと事業継続ソリューションはどう違うの? [‘サイオステクノロジー株式会社は、オープンソースソフトウェアとJavaを基盤にしたシステムやソフトウェアの設計、開発、販売、サポートを行う企業で、2017年に設立されました。主な製品には、事業継続ソリューションの「LifeKeeper」やデータ複製ソフト「DataKeeper」があります。また、Google Appsとの連携を提供するクラウドソリューションや、業務プロセスを簡素化するワークフローシステム「Gluegent Flow」なども展開しています。さらに、オープンソースに関するサポートやトレーニングも行っており、セキュリティソリューションとして「i-FILTER」や「m-FILTER」も提供しています。’] サイオスのオープンソースソフトウェアは、主にソフトウェアの設計、開発、販売、サポートを行うものであり、事業継続ソリューションは「LifeKeeper」などの特定の製品を指します。 ComparativeAbstractQuerySynthesizer サイオステクノロジーの事業継続ソリューションオープンソースソフトウェアクラウドソリューション他のビジネスソリューション比較利点特長は? [‘サイオステクノロジー株式会社は、オープンソースソフトウェアとJavaを基盤にしたシステムやソフトウェアの設計、開発、販売、サポートを行う企業で、2017年に設立されました。主な製品には、事業継続ソリューションの「LifeKeeper」やデータ複製ソフト「DataKeeper」があります。また、Google Appsとの連携を提供するクラウドソリューションや、業務プロセスを簡素化するワークフローシステム「Gluegent Flow」なども展開しています。さらに、オープンソースに関するサポートやトレーニングも行っており、セキュリティソリューションとして「i-FILTER」や「m-FILTER」も提供しています。’] サイオステクノロジーの事業継続ソリューション「LifeKeeper」やデータ複製ソフト「DataKeeper」、クラウドソリューション、業務プロセスを簡素化するワークフローシステム「Gluegent Flow」などは、オープンソースソフトウェアを基盤にした利点や特長を持っています。 ComparativeAbstractQuerySynthesizer ちなみにデフォルトだと query_distribution の値としては (AbstractQuerySynthesizer(llm=llm), 0.25), #25% (ComparativeAbstractQuerySynthesizer(llm=llm), 0.25), #25% (SpecificQuerySynthesizer(llm=llm), 0.5), #50% という割合となっています。 このあたりも、どういった質問事項を作成したいかに合わせて設計していきたいところです。 まとめ 今回はRagas v0.2における日本語のデータセット生成の方法を紹介しました。 近いうちにドキュメントも整備されるとのことですが、一足お先に紹介してみました。 もしかしたら、公式のドキュメントでの起債が紹介した方法と全然違うかもしれませんが、その際は改めて修正したいと思います。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Ragas】日本語テストセットの生成方法のご紹介【v0.2】 first appeared on SIOS Tech. Lab .
アバター
伊藤です。 今回は、Shibboleth IdPの属性配信同意情報をデータベースに格納する方法を紹介します。 端末に属性配信同意情報を保存した場合は、異なる端末でログインする際に再度同意が必要になりますが、属性配信同意情報をサーバに保存することで、異なる端末でログインした場合でも同意が不要になります。 Shibboleth IdPの構築 学認(以下のサイト)が提供する手順にしたがいShibboleth IdPを構築します。構築の詳細については、割愛します。 https://meatwiki.nii.ac.jp/confluence/display/GakuNinShibInstall/Home データベースのインストール データベース(MariaDB)のインストール・起動と設定を実施します。 # dnf install mariadb mariadb-server # systemctl enable mariadb # systemctl start mariadb # mysql_secure_installation <略> Enter current password for root (enter for none): ← そのままEnterを入力 OK, successfully used password, moving on... <略> Change the root password? [Y/n] ← Yを入力 New password: rootpassword ← rootパスワードを設定 Re-enter new password: rootpassword Password updated successfully! Reloading privilege tables.. ... Success! <略> Remove anonymous users? [Y/n] ← そのままEnterを入力 ... Success! <略> Disallow root login remotely? [Y/n] ← そのままEnterを入力 ... Success! <略> Remove test database and access to it? [Y/n] ← そのままEnterを入力 - Dropping test database... ... Success! - Removing privileges on test database... ... Success! <略> Reload privilege tables now? [Y/n] ← そのままEnterを入力 ... Success! <略> Thanks for using MariaDB! データベースにテーブルを作成 MariaDB上にデータベース shibboleth を作成し、テーブル StorageRecords を追加します。 # mysql -u root -p Enter password: rootpassword ← 設定したrootパスワードを入力 MariaDB [(none)]> CREATE DATABASE shibboleth; MariaDB [(none)]> CONNECT shibboleth MariaDB [shibboleth]> CREATE TABLE StorageRecords ( context varchar(255) NOT NULL, id varchar(255) NOT NULL, expires bigint DEFAULT NULL, value text NOT NULL, version bigint NOT NULL, PRIMARY KEY (context, id) ); ※ここで、context列と id列は、大文字と小文字を区別して処理および比較されていることを確認する必要があります。今回は照合順序にutf8mb4_binを設定します。 MariaDB [(none)]> ALTER TABLE StorageRecords COLLATE 'utf8mb4_bin'; テーブルにアクセスするためのデータベースユーザ(shibbolethuser)を新規作成します。パスワードを databasepassword の部分に設定します。ユーザとパスワードは、後述のデータベース接続設定で使用します。 MariaDB [shibboleth]> CREATE USER 'shibbolethuser'@'localhost' IDENTIFIED BY ' databasepassword '; MariaDB [shibboleth]> GRANT INSERT, SELECT, UPDATE, DELETE ON shibboleth.* TO 'shibbolethuser'@'localhost'; MariaDB [shibboleth]> FLUSH PRIVILEGES; MariaDB [shibboleth]> quit JDBCプラグインのインストール JDBCプラグインをインストールします。 # /opt/shibboleth-idp/bin/plugin.sh -I net.shibboleth.plugin.storage.jdbc JDBCドライバーをインストール JDBCドライバー(mysql-connector-javaパッケージ)をインストールします。 ダウンロードページは以下です。今回はmysql-connector-j-9.0.0をインストールします。 https://dev.mysql.com/downloads/connector/j/   # curl -O https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-9.0.0.tar.gz # tar zxv -C /usr/share/java/ -f mysql-connector-j-9.0.0.tar.gz 以降はJARファイルが /usr/share/java/mysql-connector-j-9.0.0/mysql-connector-java.jar にインストールされていることを想定します。 edit-webapp/WEB-INF/lib/ にシンボリックリンクを作成したあとビルドスクリプトを実行しidp.warを再生成します。 # ln -s /usr/share/java/mysql-connector-j-9.0.0/mysql-connector-java.jar /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/ # /opt/shibboleth-idp/bin/build.sh Installation Directory: [/opt/shibboleth-idp] [Enter] ←入力なし Rebuilding /opt/shibboleth-idp/war/idp.war ... ...done BUILD SUCCESSFUL Total time: 3 seconds ※JDBCドライバーは以下のコマンドでインストールを実施し、シンボリックリンクを作成することも可能です。 # dnf install mariadb-java-client # ln -s /usr/lib/java/mariadb-java-client.jar /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/ データベース接続設定 /opt/shibboleth-idp/conf/global.xml を設定します。 <bean id="mydataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" lazy-init="true" p:driverClassName="com.mysql.cj.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/shibboleth" p:username="shibbolethuser" p:retryableErrors="4001, 4002" p:password=" databasepassword "    /> <bean id="JDBCStorageService" parent="shibboleth.JDBCStorageService" p:dataSource-ref="mydataSource" p:transactionIsolation="4" p:retryableErrors="40001" /> ※driverClassNameはJDBCドライバのバージョンが8以降の場合はcom.mysql.cj.jdbc.Driver、以前のバージョンの場合はcom.mysql.jdbc.Driverを指定します。また、接続プールを提供するデータソースであるCommons DBCP 2 ライブラリはデフォルトで IdP に含まれています。 IdPの設定 idp.propertiesのStorageServiceで、データベース接続設定のbean idを指定します。 idp.session.StorageService = JDBCStorageService jettyを再起動します。 # systemctl restart jetty まとめ Shibboleth IdPの属性配信同意情報をデータベースに格納する方法をまとめました。何か少しでも参考になれば幸いです。 参考 https://meatwiki.nii.ac.jp/confluence/display/GakuNinShibInstall/Home https://shibboleth.atlassian.net/wiki/spaces/IDPPLUGINS/pages/2989096970/JDBCStorageService   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Shibboleth IdPの属性配信同意情報をデータベースに格納する first appeared on SIOS Tech. Lab .
アバター
PS/SLの佐々木です。 2024年9月にHyperledger FabricのメジャーアップデートがありVersion3がリリースされました。 今回はリリースノートからHyperledger Fabric V3で新しくどのような機能か登場したのか紹介したいと思います。 Hyperlerger Fabric V3 新機能紹介 1. Byzantine Fault Tolerant (BFT) Ordering Service 概要 BFTとは? BFTは、単なるクラッシュ障害(Crash Fault Tolerance, CFT)に留まらず、一部のノードが悪意を持った行動をしてもシステム全体が正常に機能することを保証する仕組みです。 悪意あるノードやハッキングによる障害に強い信頼性を提供します。 背景 Fabric v1.4.1 以降、Raft ベースの CFT が主流。 Fabric v3 で初めて SmartBFT ライブラリを用いた BFT コンセンサスが導入される。 分散システムにおける真の非中央集権性 を実現するために設計されている。 利用条件 Channel Capability V3_0 を有効にする必要があります。 従来の CFT (Crash Fault Tolerance) Ordering Service 実装 : Fabric v1.4.1 以降、Raft プロトコルが採用されており、これは CFT(クラッシュ障害耐性)のみを提供。 動作原理 : ノードがクラッシュ(停止)した場合でも耐性あり。 ただし、悪意ある行動(データ改ざんや不正なリーダー選出)には耐えられない。 制約 : Raft は分散ノード間の信頼性が前提であり、ノード運営者が「信頼できる」ことを前提としている。 新しい BFT Ordering Service 実装 : SmartBFT ライブラリを活用。 動作原理 : 最大でノードの 1/3 未満が悪意ある行動をしてもシステムが正常に動作。 各ノードが異なる主体によって運営されている場合でも、完全な分散と信頼性を実現可能。 利点 開発者視点 高い耐障害性 : システムが最大でノードの 1/3 未満の悪意ある行動や障害に耐えられる。 柔軟性 : 信頼できない運営者(ノード間の異種運営)を含むシステムを構築可能。 実験的試行 : テストネットワークで簡単に試すことができ、初期設定もチュートリアルが整備されている。 ユーザー視点 データの安全性 : ネットワーク上の悪意あるノードや妨害行動がシステム全体の整合性を崩さない。 信頼性の向上 : ノード運営者が分散化され、特定の主体に依存しない。 比較まとめ 特徴 CFT (Raft) BFT (SmartBFT) 耐障害性 クラッシュ障害に耐える クラッシュ+悪意あるノードの行動にも耐える 運営ノード間の信頼性 信頼が前提 信頼が不要、最大1/3までの不正行為を許容 適用ユースケース 信頼された環境(例: 同一企業内) 信頼できない環境(例: 複数企業間の連携) 2. Ed25519 暗号アルゴリズムのサポート 概要 Ed25519とは? Ed25519 は、従来の楕円曲線暗号(ECDSA)よりも高速かつ安全なデジタル署名アルゴリズム。 Fabric の MSP(Membership Service Provider)機能で、署名や検証に利用可能になりました。 利用条件 Channel Capability V3_0 を有効にする必要があります。 従来の ECDSA(楕円曲線デジタル署名アルゴリズム) 性能 : トランザクション署名と検証で利用。 パフォーマンスは十分だが、Ed25519 と比較すると若干の処理遅延がある。 セキュリティ : 楕円曲線暗号は安全だが、Ed25519 と比べると一部の最新攻撃に対する耐性がやや劣る可能性が指摘されている。 新しい Ed25519 性能 : ECDSA に比べて署名・検証が高速。 トランザクション処理のスループット向上が期待できる。 セキュリティ : より新しいアルゴリズムであり、高度な攻撃に対しても強い耐性を持つ。 鍵サイズが短く、署名もコンパクト。 利点 開発者視点 高速性 : 署名や検証が効率化され、大規模なトランザクション処理においてパフォーマンス向上。 セキュリティ向上 : より強力な署名アルゴリズムで、攻撃に対する耐性が強化。 ユーザー視点 トランザクション処理速度の向上 : Ed25519 を採用することで取引の処理速度が改善され、ユーザー体験が向上。 長期的なセキュリティ対応 : 将来の暗号技術的脅威に対する準備。 比較まとめ 特徴 ECDSA Ed25519 署名・検証速度 標準的 高速 鍵サイズ やや大きい 小さい セキュリティ 十分安全 最新の脅威に対するより強い耐性 適用場面 既存システムとの互換性を重視 パフォーマンスと将来的なセキュリティを重視 3. 追加の改善点 全ての承認済みチェーンコードのクエリ 新コマンド : peer lifecycle chaincode queryapproved チャネル名を指定するだけで、そのチャネルに承認された全チェーンコードを取得可能。 利点 開発者視点 : 承認済みチェーンコードの管理が簡素化され、ネットワークのデバッグや監視がしやすくなる。 ユーザー視点 : 安全なチェーンコード管理による運用の信頼性向上。 変更点 peer.gossip.pvtData.transientstoreMaxBlockRetention のデフォルト値変更 変更点 : 保持ブロック数が 1000 → 20000 に増加。 目的 : 未コミットのプライベートデータをトランジェントストアに長期間保持し、コミット遅延に対する耐性を向上。 Proposal のタイムスタンプ検証 新機能 : TimeWindowCheck フィルターが追加され、提案リクエストのタイムスタンプをピア時間と比較して検証。 目的 : 不正確なタイムスタンプの提案が承認されるリスクを軽減。 peer.deliveryclient.blockGossipEnabled のデフォルト値が false に変更 背景 : Gossip を介したブロック配信が非推奨に。将来的に削除される可能性があり、デフォルトで無効化。 推奨設定 : ピアはオーダリングサービスノードから直接ブロックを受信する構成を採用。 削除機能 システムチャネルのサポート削除 概要 : システムチャネルが削除され、チャンネル作成は Channel Participation API 経由に移行。 利点 : プライバシー、スケーラビリティ、運用性の向上。 Solo および Kafka コンセンサスの削除 概要 : Solo はテスト用として設計されており、Kafka は Raft の導入以降非推奨だった。Fabric v3.0 では完全に削除。 対応 : Raft への移行が必要。 レガシーチェーンコードライフサイクルの削除 概要 : Fabric v1.x のチェーンコードライフサイクルは削除され、v2.x の新しいライフサイクルに統一。 対応 : 全チェーンコードを再デプロイし、チャネルアプリケーション機能を V2_0 または V2_5 に設定する必要あり。 非推奨機能 Gossip によるブロック配信 非推奨理由 : Gossip は複雑さと非効率性のため、オーダリングサービスノードから直接ブロックを受け取る構成が推奨される。 今後の変更 : 将来のリリースで削除される可能性が高い。 まとめ Hyperledger Fabric v3 の新機能は、分散型ネットワークの安全性、性能、柔軟性を向上させるために設計されています。 BFT オーダリングサービスは、より信頼性の高い分散システムを構築したい組織にとって理想的な選択肢です。 Ed25519 のサポートは、高速かつ安全な取引処理を可能にします。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Hyperleger Fabric v3.0の解説! first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジー 佐藤 陽です。 今回はSIOSのアドベントカレンダーの記念すべき1日目の記事です。 今年のアドベントカレンダーのテーマは「サイオス社員が今年一年で新たに学んだ技術」です! そして私は絶賛学習中のAzure CosmosDBについて紹介していきたいと思います。 偉そうに書いていきますが、自分自身も入門したてなので、もし誤ってる点あったらコメントで指摘いただけると幸いです。 はじめに 冒頭でも述べましたが、Azure CosmosDBについて書いていきたいと思います。 私自身、ほとんどRDBMSしか触ったことがなく、NoSQLに関してはまったくの素人です。 「なんかJSONのままデータ保管しておけるんでしょ?」くらいの理解です。 ただ、先日のMicrosoft IgniteでもCosmosDBでハイブリット検索が行えるようになったという発表があり、生成AI関連でもCosmosDBの活用が注目されています。 それに、そもそもアプリケーションのDBとしてNoSQLはよく選択肢として挙がる部分なので、知っておかなくては…という思いから学習を始めました。 というところで、今回は基礎の基礎というところで、CosmosDBにおいて重要な概念である RU(Request Unit) について超入門していきたいと思います。 RUとは? スループット(RU/s)の制限 RUと料金体系 など基本的なところを抑えていこうと思うのでぜひ最後までご覧ください。 RUとは RUはRequest Unitの略称であり、CosmosDBにおいては非常に重要な指標です。 CosmosDBのデータベースの操作を行うにあたってはCPU, メモリ, IOPSなどの様々システムリソースが必要になりますが それらが全て抽象化され、RUというメトリクスひとつに集約化されています。 そして、このRUの単位はスループット(RU/s)や利用料金にもかかわってきます。 つまり、ユーザーはRUだけを考えればいいという非常にシンプルな仕組みとなっています。 では「1RUで出来る操作はどのくらいか?」なんですが、公式ドキュメントには以下のように記載がありました。 1RU = 1 KB 項目の読み取り 5RU = 1 KB 項目の書き込み これをベースとして膨大なデータ量の読み取りを行ったり、複雑なクエリを実行することでRUが増加していくことになります。 RUを計算する上で影響する要素としては以下のようなものがあります。 アイテムのサイズ アイテムのインデックス付け アイテム プロパティの数 インデックス付きプロパティ データの一貫性 読み取りの種類 クエリのパターン スクリプトの使用 なお、また別の記事でも触れたいと思いますが、 CosmosDBのコンテナ設計を優れたものにすることで、同じデータの取り出しでも必要となるRUを小さくすることが可能です。 そのため、データモデリングやパーティションキーの設定が検索性能やコストにも直結します。 RUとCosmosDBの設定項目 では実際にCosmosDBのリソースを作成・利用していくうえで、このRUがどのように関わっていくかを見ていきたいと思います。 リソース作成画面をみてみます。 今回のポイントとしては、以下2点です。 容量モード 合計アカウント スループットを制限する なお、これから色々検証の方していきますが、Global distributionの設定に関して無効 / 無効で設定したうえで検証の方進めていきます。 マルチリージョンにすると、プロビジョニングされるRU数が2倍になったりするのでその点注意です。 容量モード CosmosDBをデプロイする際、容量モードというプロパティが存在しています。 選択肢としては2つ存在しています。 プロビジョニングされたスループット Serverless プロビジョニングされたスループット 「プロビジョニングされたスループット」に関しては、事前に使用可能な 1秒あたりのRU(=RU/s=スループット) を設定する方法になります。 例えば1000RU/sと設定した場合は、1秒間に1000回のみ「1 KB 項目のポイント読み取り」を行えるといった形になります。 なお、この設定したRU/sの値を超えてしまった場合はCosmosDBから429のエラーが返されます。 ただしCosmosDB SDKを利用している場合は、自動で再送処理の方が行われるようです。 また、このプロビジョニングされたスループットについては更に2つのプロパティを持ちます。 Manual Auto Scale Manual 「Manual」は完全にRU/sを決め打ちするような設定になります。 例えばスループットを 1000 RU/s と設定した場合は、常にRU/sは1000に固定されます。 もちろんAzure Portal上などからこの値を手動で変更することは可能ですが、アプリの使用量などによって動的に変化することはありません。 AutoScale 「Auto Scale」は設定した範囲内で、アプリの使用量に応じてスループットが変動する設定となります。 例えば上限のスループットを 1000 RU/sとした場合、以下のレンジの間でスループットは変動します。 100 RU/s ~ 1000 RU/s なお、この下限の値は上限のスループットの1/10の値となっています。 スループット制限のスコープ このスループットを制限する対象ですが アカウント データベース コンテナ それぞれで設定することが可能です。 アカウント CosmosDBアカウント全体へのスループット制限については、Cost Managementブレードから確認できます。 現在、1000RU/sとして設定されており、このアカウント全体で1000RU/sまでのスループットをプロビジョニングすることが可能となります。 この後話していくなかで、データベースやコンテナに対してそれぞれスループットを割り当てますが、それらの合計がここで設定した値以下となる必要があります。 なお、選択肢を見ていただいても分かるように「制限無し」という設定も可能で この場合は上限無くスループットを割り当てることが可能となります。 データベース まずデータベースのスコープを確認します。 まず、サンプルのデータベースを作成していきましょう。 データエクスプローラからコンテナの作成を行います。 まだデータベースが存在していないので、データベースから作成していきます。 今回は restaurant_db というDBを作ることにします。 そして、 Share throughput across containers にチェックボックスを入れます。 このチェックボックスを入れることで、このデータベースに含まれるコンテナ群でスループット量を共有するようになります。 そしてスループットの設定として、先程述べたAuto scaleからManualかを選択し、RU/sの値を設定します。 今回はAuto scaleを選択しており、値としては1000 RU/sを設定しました。 この時、先程紹介したようなレンジでRU/sが設定されていることが読み取れます。 ちなみにここで2000 RU/sを設定しようとすると怒られます。 これは、先ほどアカウント全体のスループットを1000RU/sに制限したためです。 そのため今回はデータベースのMAX RU/sの値を1000RU/sのままにして進めます。 続いてコンテナ(food_container)も作成していきます。 作成完了後、restaurant_dbに更にコンテナ(drink_container)を1つ追加します。 これでrestaurantというデータベースに対して、foodとdrinkという2つのコンテナが作成できました。 この状態でAzurePortalのCosmosDBのリソースから、Cost Managementのメニューを確認します。 この内容から以下のことが読み取れます。 restaurantのデータベースには最大1000RU/sのスループットが割り当てられている foodとdrinkのコンテナでこの1000RU/sを共有している イメージとしてはこんな感じです。 これがデータベースをスコープとしたスループットの制限となります。 コンテナ 次にコンテナをスコープとしたスループットの制限を確認します。 まず、事前準備としてCosmos DBアカウント全体のスループット許容量を増やしておきます。 ひとまず4000RU/s位にしておけば大丈夫です。 そして、新規にデータベースとコンテナを作成していきます。 この時のポイントとしては** Share throughput across containers にチェックボックスを入れません。** そして、コンテナ(employee)に対してスループットの設定を行います。 作成が完了したら、もう一つcompanyのデータベースに対してコンテナ(department)を追加しておきます。 2つのコンテナの作成が完了したら、Cost Managementを見てみましょう。 ここからから以下のことが読み取れます。 companyが持つコンテナそれぞれに対して1000RU/sが割り当てられている companyのデータベースとしては最大スループットが2000RU/sである イメージとしてはこんな感じです。 このように、最大スループットに関してはデータベースに対しても割り当てられますし、コンテナに対しても割り当てられます。 データベースとコンテナ混合 これまでデータベースとコンテナそれぞれにスループットを割り当てる方法をご紹介しました。 これに加えて、データベースに対して割り当てつつ、さらにコンテナに対してもスループットを割り当てることも可能です。 実際やってみましょう。 先程作成した restaurant のデータベースにコンテナを追加します。 そして、 Provision dedicated throughput for this container にチェックボックスを入れ、コンテナに対してスループットの設定を行います。 ではCostManagementを見てみましょう。 以下の内容が読み取れます。 restaurantのデータベースとしては最大スループットが2000 RU/sである dessertコンテナに対してだけ1000RU/sが割り当てられているである。 イメージとしてはこんな感じです。 この時気になることとしては、 「restaurantのデータベースには1000 RU/sが割り当てられてるんだし、そのデータベースに含まれるdessertのコンテナにもスループットは割り当てられる?」 といった点かと思います。 結論から言うと、そういった割り当ては行われず、 dessert のコンテナが利用できるのは1000RU/sまでとなります。 これは公式のドキュメントにも記載がありました。 参照: データベースとコンテナーでスループットを設定する 以上の内容から、プロビジョニングされたスループットの容量モードを選択した場合は 「どのスコープに対して」「どれだけのスループットを割り当てるべきか」が設計時のポイントとなりそうです。 スループットの変更 一度設定したスループットに関しても簡単に変更できます。 データエクスプローラの Scale という項目を選ぶと、AutoscaleかManualかの選択や、その設定における値も変更可能です。 アプリの利用状況などに合わせて柔軟に変更しましょう Serverless 「Serverless」に関しては、事前に使用するRU/sを設定しません。 使用量に伴って自動でスケーリングされ、最大のスループットとしては 20,000 RU/sまで増加します。 つまり、サーバーレスを利用する場合は、これまで プロビジョニングされたスループット で述べてきたようなスループットの割り当てを考慮する必要がありません。 全てCosmosDB側で自動で行ってくれます。らくちんです。 そして料金体系に関しては、利用したRUの量に依存します。 つまり何RUを利用したかによって、料金が従量課金制のように増えていきます。 ただこの時、 プロビジョニングされたスループット と Serverless で同じ量のRUを利用した場合は、Serverlessの方が使用料は高くなる傾向です。 (プロビジョニングされたスループットの設定値が適切である前提) とはいいつつ、スループットを正確に見定めるのは難しいですし、アプリの新規開発時やアプリの利用量の予測が困難な場合はひとまずServerlessを選択するのが良いかと思います。 RUの計算 自分の作ってるアプリがどれだけRUを使うか分からない!!といった方も多いかと思います。 これについては以下2つの方法が用意されています。 実測で計算する 計算ツールによる予想 実測での計算 こちらは実際にクエリを実行して、その実行に対するRUを確認する方法です。 まず、先程作成した food_container にアイテムを1つ追加します。 このコンテナー対して、データエクスプローラから以下のクエリを実行します。 SELECT * FROM c すると、結果が得られると思うのですが、 Query Stats の Request Charge の値を確認します。 これが今回のクエリ実行にかかったRUの数です。 このように実際にクエリを実行してみて、どの程度のRU数になるかを実際確認してみましょう。 計算ツールによる予測 Azureには Capacity Calculator といった計算ツールが用意されており、これを利用することでおおよそのRU数を見積もることが可能です。 料金体系 CosmosDBの利用料金は主にRUとストレージ容量によって決まります。 プロビジョニングされたスループットの場合であれば、設定したRU/sに応じて時間単位で課金が行われます。 Serverlessの場合であれば、先程述べたように、利用したRU数とストレージ容量に応じて課金が行われます。 まとめ 今回は、CosmosDBを利用するうえで重要な指標であるRequest Unitについてご紹介しました。 メモリや、CPUなどのシステムリソースを抽象化した値であり、利用する側からしたらRUのみを考えればいいので非常にシンプルですね。 ただ、プロビジョニングされたスループットの設定においてはどのスコープに対して、どれだけの値を設定するかをしっかりと考える必要があります。 性能や価格などを考えるうえで肝となる指標であるため、しっかり理解していきたいところです。 まだまだCosmosDB深掘りしていきたいと思うので次もぜひ読んでいただければと思います。 ではまた! おまけ 2024年のMicrosoft Ignite でCosmosDBのベーシックな内容が紹介されていました。 RUとは?といった部分も紹介されていたので、是非こちらも見ていただければと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】CosmosDBにおけるRU入門ガイド【初心者向け】 first appeared on SIOS Tech. Lab .
アバター
OpenShift Pipelines (Tekton) は、OpenShift 上で CI/CD パイプラインを構築するためのツールです。開発者としては、パイプラインのエラーや失敗が発生したら困るので、リアルタイムで知りたいと思います。そこで、 Tekton Catalog を参考にしてエラー通知を Slack に送信する仕組みを構築してみました。 前提条件 OpenShift 4 クラスターが構築済みであること OpenShift Pipelines Operator がインストールされていること oc CLI がインストール済みであること OpenShift Pipelines でパイプラインが構築済みであること パイプラインの構築については 以前の記事 を参考 Slack に通知を送信するワークスペース、チャンネルが用意されていること CloudEvents について CloudEvents は、イベントデータの標準化を目的とした CNCF のプロジェクトです。OpenShift Pipelines は CloudEvents をサポートしており、パイプラインの状態をイベントとして発行することができます。OpenShift Pipelines の CloudEvents は下記リンクのようになっています。 https://tekton.dev/docs/pipelines/events/ https://tekton.dev/docs/pipelines/additional-configs/#configuring-cloudevents-notifications CloudEvents の HTTP ヘッダーの一部は下記のような形で送られてきます。PipelineRun が Failed の時、”Ce-Type” が “dev.tekton.event.pipelinerun.failed.v1” で送られてくる仕様なので、これを利用したいと思います。 "Ce-Id": "77f78ae7-ff6d-4e39-9d05-b9a0b7850527", "Ce-Source": "/apis/tekton.dev/v1beta1/namespaces/default/taskruns/curl-run-6gplk", "Ce-Specversion": "1.0", "Ce-Subject": "curl-run-6gplk", "Ce-Time": "2021-01-29T14:47:58.157819Z", "Ce-Type": "dev.tekton.event.taskrun.unknown.v1", 構築の概要 図のような構成を構築したいと思います。まず初めに、Pipeline Run からの CloudEvents を EventListener で受け取ります。次に EventListener は Pipeline Run が失敗したことを検知して TriggerBinding と TriggerTemplate から Slack に Webhook を送信するような Task Run を動作させます。Slack の指定したチャンネルに Pipeline Run 失敗通知が届けば動作完了です。 Slack App の準備 Slackに通知を送信するためには、 Slack App を作成し、適切な権限を付与する必要があります。Slack App の Webhook URL を取得し、OpenShift Pipelines で使用できるようにします。 Slack App のページから Create New App をクリックします。 From scratch をクリックします。 App Name を入力して、Slack App を追加するワークスペースを選択します。  Basic Information が表示されれば完了です。次に Incoming Webhooks をクリックします。 デフォルトでは Activate Incoming Webhooks は Off になっているので、クリックして On にします。 On になれば完了です。Add New Webhook to Workspace をクリックします。 Slack App が Slack ワークスペースに投稿する権限を与えます。投稿することのできる投稿先チャンネルを指定して許可します。 Webhook URL が作成されれば完了です。この Webhook URL は後に使うので Copy して保存しておきます。   Slack の通知を送信したいチャンネルに作成した Slack App が追加されていることを確認します。 Task の作成 Tekton Catalog を参考に Slack にメッセージを送信するための Task を作成します。この Task はシンプルなもので、Slack の Webhook URL に対して POST リクエストを送信します。 Secret を作成します。stringData の url に前項で保存した Slack API の Webhook URLを入力します。 webhook-url.yaml kind: Secret apiVersion: v1 metadata:   name: webhook-secret stringData: # 下記に前項で保存した Slack API の Webhook URLを入力   url: https://hooks.slack.com/services/ 下記コマンドを実行してWebhook URLを持つシークレットを作成します。 $ oc apply -f  webhook-url.yaml secret/webhook-secret created 下記コマンドを実行してシークレットが作成されていることを確認します。 $ oc get secret NAME                       TYPE                      DATA   AGE ︙ webhook-secret             Opaque                    1      17s Task の編集をします。params の中の bot-name の default を作成した Slack App の名前に置き換えます。 send-to-webhook-slack.yaml apiVersion: tekton.dev/v1beta1 kind: Task metadata:   name: send-to-webhook-slack   labels:     app.kubernetes.io/version: "0.1"   annotations:     tekton.dev/pipelines.minVersion: "0.12.1"     tekton.dev/categories: Messaging     tekton.dev/tags: messaging     tekton.dev/displayName: "Send message to Slack Channel"     tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le" spec:   description: >-     These tasks post a simple message to a slack channel.     This task uses Incoming Webhooks of slack to send the message.   params:   - name: webhook-secret     type: string     description: secret name of the slack app webhook URL (key is url)   - name: message     type: string     description: plain text message     default: 'Webhook-test'   - name: bot-name     type: string     description: plain text message   # 下記を作成した Slack App の名前に変更     default: 'sample app'   - name: icon-emoji     type: string     description: plain text message     default: ':ロボット:'   steps:   - name: post     image: docker.io/curlimages/curl:7.70.0@sha256:031df77a11e5edded840bc761a845eab6e3c2edee22669fb8ad6d59484b6a1c4 #tag: 7.70.0     script: |       #!/usr/bin/env sh       MESSAGE=$(echo "${MESSAGE}" | sed -e 's/\"/\\\\"/g')       BOTNAME=$(echo "${BOTNAME}" | sed -e 's/\"/\\\\"/g')       JSON="{\"text\": \"${MESSAGE}\", \"username\": \"${BOTNAME}\", \"icon_emoji\": \"${EMOJI}\"}"       curl -X POST -H 'Content-Type: application/json' --data "${JSON}" "${URL}"     env:     - name: URL       valueFrom:         secretKeyRef:           name: $(params.webhook-secret)           key: url     - name: MESSAGE       value: $(params.message)     - name: BOTNAME       value: $(params.bot-name)     - name: EMOJI       value: $(params.icon-emoji) 下記コマンドを実行してタスクを作成します。 $ oc create -f  send-to-webhook-slack.yaml task.tekton.dev/send-to-webhook-slack created 下記コマンドを実行してタスクが作成されていることを確認します。 $ tkn task ls NAME                    DESCRIPTION              AGE send-to-webhook-slack   These tasks post a ...   43 seconds ago TriggerBinding の作成 TriggerBinding は、イベントデータを Task に渡すための設定です。パイプラインのエラー情報を Task に渡すための TriggerBinding を作成します。 下記コマンドを実行して TriggerBinding を作成します。 $ oc apply -f trigger_binding.yaml triggerbinding.triggers.tekton.dev/failure-trigger-binding created trigger_binding.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerBinding metadata:   name: failure-trigger-binding spec:   params:   - name: message     value: "Failed pipeline $(body.pipelineRun.metadata.name)" 下記コマンドを実行して TriggerBinding が作成されていることを確認します。 $ tkn triggerbinding ls NAME                      AGE failure-trigger-binding   3 minutes ago TriggerTemplate の作成 TriggerTemplate は、イベントに応じて実行するリソースのテンプレートです。Task を実行するための TriggerTemplate を作成します。 下記コマンドを実行して TriggerTemplare を作成します。 $ oc apply -f trigger_template.yaml triggertemplate.triggers.tekton.dev/failure-trigger-template created trigger_template.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerTemplate metadata:   name: failure-trigger-template spec:   params:     - name: message     - name: bot-name   resourcetemplates:   - apiVersion: tekton.dev/v1beta1     kind: TaskRun     metadata:       generateName: failure-handler     spec:       params:       - name: webhook-secret         value: webhook-secret       - name: message         value: $(tt.params.message)       - name: bot-name         value: $(tt.params.bot-name)       taskRef:         name: send-to-webhook-slack 下記コマンドを実行して TriggerTemplate が作成されていることを確認します。 $ tkn triggertemplate  ls NAME                       AGE failure-trigger-template   4 minutes ago EventListener の作成 OpenShift Pipelines で発生した CloudEvents を受け取るための EventListener を作成します。この EventListener は、interceptors の cel を利用して CloudEvents の内容を判別し、 HTTP ヘッダーの ”Ce-Type” が “dev.tekton.event.pipelinerun.failed.v1”  の場合に Slack にメッセージを送信する Task を実行します。 下記コマンドを実行して EventListener を作成します。 $ oc apply -f failure-event-listener.yaml eventlistener.triggers.tekton.dev/failure-event-listener created failure-event-listener.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: EventListener metadata:   name: failure-event-listener spec:   serviceAccountName: pipeline   triggers:     - name: failure-trigger       interceptors:         - ref:             name: cel           params:           - name: "filter"             value: "header.match('ce-type', 'dev.tekton.event.pipelinerun.failed.v1')"       bindings:       - ref: failure-trigger-binding       template:         ref: failure-trigger-template   resources:        kubernetesResource:          spec:            template:              spec:                serviceAccountName: pipeline                containers:                - resources:                    requests:                      cpu: "250m"                      memory: "64Mi"                    limits:                      cpu: "500m"                      memory: "128Mi" 下記コマンドを実行して EventListener が作成されていることを確認します。 $ tkn eventlistener ls NAME                     AGE            URL                                                                   AVAILABLE failure-event-listener   1 minute ago   http://el-failure-event-listener.ci-pipeline.svc.cluster.local:8080   True 下記コマンドを実行して EventListener をルートとして公開します。 $ oc expose svc el-failure-event-listener route.route.openshift.io/el-failure-event-listener exposed 下記コマンドを実行して EventListener がルートとして公開されていることを確認します。 $ oc get route NAME                        HOST/PORT                                               PATH   SERVICES                    PORT            TERMINATION   WILDCARD el-failure-event-listener   el-failure-event-listener-ci-pipeline.apps.xxx          el-failure-event-listener   http-listener                 None 下記コマンドを実行して EventListener の webhook-url を確認します。この webhook-url は次項の CloudEvents の設定で使用します。 $ echo "URL: $(oc  get route el-failure-event-listener --template='http://{{.spec.host}}')" URL: http://el-failure-event-listener-ci-pipeline.apps.xxx CloudEvents の設定 cloud_events_config.yaml の data.sink パラメータに前項で取得した EventListener の webhook-url を入力します。 cloud_events_config.yaml apiVersion: v1 kind: ConfigMap metadata:   name: config-events   namespace: openshift-pipelines   labels:     app.kubernetes.io/instance: default     app.kubernetes.io/part-of: openshift-pipelines data:   formats: tektonv1 # ここに前項で取得した EventListener の webhook-url を入力   sink: http://el-failure-event-listener-ci-pipeline.apps.xxx 下記コマンドを実行して CloudEvents 設定をします。 $ oc apply -f config-events.yaml configmap/config-events configured 下記コマンドを実行して CloudEvents 設定が反映されていることを確認します。 $ oc describe configmaps config-events -n openshift-pipelines Name: config-events Namespace: openshift-pipelines ︙ formats: ---- tektonv1 sink: ---- http://el-failure-event-listener-ci-pipeline.apps.cp-test.cpawstest.ps.staging-test.sios.jp 動作確認 最後に、実際にパイプラインを実行して、エラーが発生した場合に Slack に通知が届くことを確認します。 以前の記事 のようにアプリケーションリポジトリに空のコミットを push します。 $ git commit -m "empty-commit" --allow-empty $ git push このままだと成功してしまうのでメッセージは送信されません。 パイプラインを少し編集してパイプラインが失敗するようにしてみます。 パイプラインの定義が記述されている pipeline.yaml 内の fetch-repository タスクの params を下記のように編集してこのタスクが失敗するようにします。 pipeline.yaml の詳細は 以前の記事 を参照してください。 tasks:   - name: fetch-repository     taskRef:       name: git-clone       kind: ClusterTask     workspaces:     - name: output       workspace: shared-workspace     - name: ssh-directory       workspace: ssh-creds     params:     - name: url # URL を適当な文字列に変更       value: "test"     - name: subdirectory 下記コマンドを実行して編集を反映させます。 $ oc apply -f pipeline.yaml 空のコミットをもう一度pushします。 $ git commit -m "empty-commit" --allow-empty $ git push 少し経った後、OpenShift コンソール上でパイプラインが失敗したことを確認します。 webhookを許可したSlackのチャンネルを確認してメッセージが送信されていれば完了です。   まとめ OpenShift Pipelines にエラー通知をSlackに送信する仕組みを Tekton Catalog  を参考にして構築してみました。OpenShift Pipelines では OpenShift コンソール上の GUI で通知機能を設定するような実装はありませんが、CloudEvents と EventListener を組み合わせて実装することが出来ました。次回は CD 部分である OpenShift GitOps のエラー通知機能を実装してみたいと思います。 参考文献 https://github.com/tektoncd/catalog/blob/main/task/send-to-webhook-slack/0.1/README.md https://tekton.dev/docs/pipelines/events/ https://tekton.dev/docs/pipelines/additional-configs/#configuring-cloudevents-notifications https://tech-lab.sios.jp/archives/44104 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Pipelines のエラー通知を Slack に送信してみた first appeared on SIOS Tech. Lab .
アバター
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 2024/11/8、ウエルシア薬局は外部からの不正アクセスで個人情報が流出した可能性があると発表しました。 「ウエルシアドットコム」から約4万人分の個人情報漏えいのおそれ 従業員がサポート詐欺に https://www.itmedia.co.jp/news/articles/2411/08/news186.html 2024/11/18、オープンソースのコンピューター支援設計 (CAD) ツールである FreeCAD がリリースされました。 開発が開始されてから、実に 20年もの時間をかけて公開されることとなりました。 20年以上にわたり開発されてきた「FreeCAD」がv1.0として公開 ~長年の課題2つを克服 https://forest.watch.impress.co.jp/docs/news/1641700.html 2024/11/19、Microsoft は Windows Subsystem for Linux (WSL) の公式ディストリビューションに RHEL を採用したことを発表しました。 WSLにRed Hat Enterprise Linuxの公式ディストリビューション登場 https://news.biglobe.ne.jp/it/1122/mnn_241122_2370227770.html#google_vignette ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2024年11月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
アバター
今号も、前号の「 パッケージマネージャについて 」の続きになります! 今回は Red Hat 系システムの yum/dnf で、以前紹介できなかったサブコマンドについてご紹介します。 なお、前回と同様に dnf コマンドの実行例のみ掲載しています。 yum/dnf の便利なサブコマンド パッケージの情報を表示 dnf info コマンドを実行すると、特定のパッケージの詳細な情報を表示します。 例えば、git というパッケージの情報を表示する場合は、下記の様なコマンドになります。 # dnf info git … Available Packages Name : git Version : 2.43.5 Release : 1.el9_4 Architecture : x86_64 Size : 54 k Source : git-2.43.5-1.el9_4.src.rpm Repository : rhel-9-appstream-rhui-rpms Summary : Fast Version Control System URL : https://git-scm.com/ License : GPLv2 Description : Git is a fast, scalable, distributed revision control system with an : unusually rich command set that provides both high-level operations : and full access to internals. : : The git rpm installs common set of tools which are usually using with : small amount of dependencies. To install all git packages, including : tools for integrating with other SCMs, install the git-all meta-package. この時、結果には パッケージバージョン、ライセンス、要約 (説明文) など 、様々な情報が表示されます。 なお、上記のコマンドはネットワーク上のリポジトリから情報を取得してくるため、 対象のパッケージがインストールされていなくても情報が表示されます。 yum コマンドの場合は、下記の様になります。 # yum info git dnf/yum の実行履歴を表示 dnf history コマンドを実行すると、dnf コマンドの実行履歴を表示します。 # dnf history … ID | Command line | Date and time | Action(s) | Altered ------------------------------------------------------------------------------------------------------------------------ 8 | install git | 2024-11-14 01:44 | Install | 67 7 | install httpd | 2024-11-01 03:35 | Install | 12 6 | install tomcat | 2024-11-01 03:34 | Install | 17 5 | install wget | 2024-10-31 05:33 | Install | 1 4 | install net-tools | 2024-10-09 05:02 | Install | 1 3 | install telnet | 2024-09-20 04:55 | Install | 1 2 | -q -y --disablerepo=* --enablerepo=rhui-client-config* update | 2024-09-20 04:27 | Upgrade | 1 EE 1 | install postfix | 2024-09-20 03:05 | Install | 2 この時、結果には実際に実行したコマンド、実行した日時などが表示されます。 また、各操作には ID が割り振られており、 ID の数字が小さいほど古く、大きいほど新しい実行履歴となります。 yum コマンドの場合は、下記の様になります。 # yum history パッケージのリストを表示 dnf list コマンドを実行すると、特定の条件に合致するパッケージのリストを表示します。 例えば、git という文字列から始まるパッケージのリスト (一覧) を表示する場合は、下記の様なコマンドになります。 # dnf list git* … Available Packages git.x86_64 2.43.5-1.el9_4 rhel-9-appstream-rhui-rpms git-all.noarch 2.43.5-1.el9_4 rhel-9-appstream-rhui-rpms git-clang-format.x86_64 18.1.8-3.el9 rhel-9-appstream-rhui-rpms … (長いため省略) 上記は、ご利用環境で 有効になっているリポジトリから、指定した条件でパッケージを検索しています。 また、上記の条件に併せてインストール済みパッケージのみ、利用可能なパッケージのみ、などの条件に一致するリストを表示することができます。 例えば、git という文字列から始まるパッケージのうち、インストール済みのパッケージのみを表示する場合は、下記の様なコマンドになります。 # dnf list installed git* 反対に、git という文字列から始まるパッケージのうち、利用可能な (インストールされていない) パッケージのみを表示する場合は、下記の様なコマンドになります。 # dnf list available git* yum コマンドの場合は、それぞれ下記の様になります。 # yum list git* # yum list installed git* # yum list available git* ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!パッケージマネージャについて3 ~RedHat 系システム編・続き~ first appeared on SIOS Tech. Lab .
アバター
はじめに サイオステクノロジーの塚田です。Rancher入門ブログシリーズとして、 前回 はRancherの概要について説明しました。今回はAWS上にRancherを構築する方法について解説します。この記事では、Terraform、RKE2、Helmといったツールを使用して、AWS環境にRancherを簡単に構築する方法をステップバイステップで紹介します。 構築する環境のアーキテクチャは以下の通りです: 構成要素 リージョン: us-east-1 VPC: CIDR範囲: 10.0.0.0/16 Public Subnet: 10.0.0.0/24 10.0.1.0/24 10.0.2.0/24 Network Load Balancer (NLB): Rancherへの外部アクセスを負荷分散します。 EC2インスタンス: Control Planeノードとして3台を構成し、それぞれRKE2を使用したKubernetesとRancherをホストします。 OS: Ubuntu 24.04 LTS インスタンスタイプ: t3.xlarge ※1 セキュリティグループ: ノード間通信が行えるよう必要なポートを開放します。 ※1: 最低要件はt3.medium相当ですが、本記事では余裕を持たせて最低要件から2倍程度のインスタンスタイプを採用しています。 本記事のゴール AWS環境の準備: Terraformを用いて、AWS上に必要なリソース(VPC、サブネット、NLB、EC2インスタンスなど)を自動的に構築します。 Kubernetesクラスターの構築: RKE2 ※2 を使用して、高可用性を備えたKubernetesクラスターをセットアップします。 今回構築するのは検証用なので、Control PlaneとWorker Nodeを兼用します。 Rancherのインストール: Helmを利用してRancherをデプロイし、Kubernetesクラスター管理用のダッシュボードを利用できるようにします。 ※2 RKE2とは: Rancher Labsが開発したKubernetesディストリビューション https://docs.rke2.io/ 事前準備 構築を始める前に、以下の要件を満たしていることを確認してください: AWSアカウント: 適切な権限を持つIAMユーザーを用意してください。 本記事ではAdministratorAccessを利用しています。 ローカル環境にインストールが必要なツール: Terraform: v1.5.0以上 前提条件 KubernetesおよびRancherのバージョン 本記事で使用するソフトウェアのバージョンは以下の通りです: Kubernetes (RKE2): v1.30.6+rke2r1 Rancher Server: v2.10 ※3 cert-manager: v1.16.1(SSL証明書管理用) ※4 ※3: 本記事執筆時点での最新バージョン ※4: RancherはHTTPSを使用して動作するため、SSL証明書を管理するツールとしてcert-managerが必要です。 ハードウェア要件 EC2インスタンス最低スペック: CPU: 2コア以上 メモリ: 4GB以上 ストレージ: 20GB以上の空き容量 構築手順  AWSリソースの作成 まずはterraformを利用して、Kubernetesクラスター構築に必要なリソースをAWS環境上に作成します。 デモ用リポジトリ からterraformのコードをクローンします。 $ git clone git@github.com:Eiji-Tsukada-sti/rancher_demo.git $ cd rancher_demo terraformを実行します。 # terraformを初期化 $ terraform init # terraformで作成するリソースを確認 $ terraform plan # AWSにデプロイ $ terraform apply terraformのoutputより、以下の情報を確認してください。 initial_server_public_ip: 初回構築用インスタンスのIPアドレス instance_public_ips: 全インスタンスのIPアドレスリスト nlb_dns_name: NLBのDNS名 Kubernetesクラスターの構築(RKE2) 上記の手順で作成した各インスタンスにログインし、RKE2を利用してKubernetesクラスターを構築していきます。 初期サーバーの構築 RKE2公式ドキュメントの「 High Avalilability 」の内容に基づき、Control Plane3台構成で冗長化した構築を行います。設定ファイルの内容が1台目と2台目以降で異なるため、分けて記載します。 EC2インスタンスにSSH接続します。 秘密鍵はterraform実行時にterraformのコードと同じ階層に作成されます。 また、接続先のIPアドレスはterraformデプロイ完了時に出力されるinitial_server_public_ipの値を使用してください。 $ ssh -i rancher_demo_instance_key.pem ubuntu@<INITIAL_SERVER_PUBLIC_IP> 冗長構成用の設定ファイルを作成します。 $ sudo mkdir -p /etc/rancher/rke2 $ sudo vi /etc/rancher/rke2/config.yaml config.yamlに以下の内容を記載します。 YOUR_TOKENは任意の文字列を使用可能です。 /etc/rancher/rke2/config.yaml token: <YOUR_TOKEN> tls-san:   - <INITIAL_SERVER_PUBLIC_IP> RKE2をインストールします。 $ curl -sfL https://get.rke2.io | sudo sh - RKE2のサービスを起動します。 $ sudo systemctl enable rke2-server.service $ sudo systemctl start rke2-server.service RKE2のサービスの状態がActiveになっていることを確認します。 $ sudo systemctl status rke2-server.service インスタンス内でkubectlコマンドを実行できるよう設定します。kubectl自体はRKE2のインストール内容に含まれています。 $ sudo chown ubuntu:ubuntu /etc/rancher/rke2/rke2.yaml $ sudo chmod 644 /etc/rancher/rke2/rke2.yaml $ sudo ln -s /var/lib/rancher/rke2/bin/kubectl /usr/local/bin/ $ sudo mkdir ~/.kube $ sudo ln -s /etc/rancher/rke2/rke2.yaml ~/.kube/config kubectlコマンドでノード情報を取得し、ノードのステータスがReadyになっていることを確認します。 $ kubectl get nodes 残りのサーバーの構築 続いて、残りのインスタンスにRKE2を導入します。基本的な手順は1台目と同じですが、/etc/rancher/rke2/config.yamlの記載内容が1台目と異なります。 EC2インスタンスにSSH接続します。 秘密鍵はterraform実行時にterraformのコードと同じ階層上に生成されます。 接続先のIPアドレスはterraformデプロイ完了時に出力されるisntance_public_ipsの値のうち、残りの2つを使用してください。 $ ssh -i rancher_demo_instance_key.pem ubuntu@<INSTANCE_PUBLIC_IP> 冗長構成用の設定ファイルを作成します。 $ sudo mkdir -p /etc/rancher/rke2 $ sudo vi /etc/rancher/rke2/config.yaml config.yamlに以下の内容を記述します。2台目以降は”server”を追加します。 server: https://<INITIAL_SERVER_PUBLIC_IP>:9345 token: <YOUR_TOKEN> tls-san: - <INITIAL_SERVER_PUBLIC_IP> 初期サーバーと同じ手順でRKE2をインストール・設定します。 すべてのNodeのステータスがReadyで、RoleがControl Planeになっていることを確認します。 $ kubectl get nodes 3台のノードがControl Planeとして起動していることを確認したら、クラスターの構築は完了です。 config.yaml について config.yaml は、RKE2の動作を設定するためのファイルです。このファイルには、ノード間の通信や認証に必要な情報、クラスターの冗長構成を実現するための設定が含まれます。 具体的には以下の内容を設定します: server:クラスターに参加するために使用される接続先サーバー。 token:クラスター内でノードを認証するためのトークン。全てのノードで共通。 tls-san:サーバーのTLS証明書に追加のホスト名またはIPv4/IPv6アドレスをSubject Alternative Namesとして追加する。 Rancherのインストール 構築したクラスターにRancherをデプロイします。インストールする方法は様々な手段がありますが、本記事ではもっとも簡単な Helmを利用してインストールする方法 を採用しています。なお、この手順は3台のインスタンスの内、いずれか1つに実施すれば問題ありませんが、本記事では最初の1台目で実施します。 cert-managerのインストール Rancherは、クラスターへのセキュアなアクセスを確保するためHTTPSが必須です。そのため、SSL証明書を簡単に管理できるcert-managerを事前にインストールします。 EC2インスタンスにSSH接続します。 $ ssh -i rancher_demo_instance_key.pem ubuntu@<INITIAL_SERVER_PUBLIC_IP> Helmをインストールします。 $ sudo curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash cert-managerのHelmリポジトリを追加します。 $ helm repo add jetstack https://charts.jetstack.io $ helm repo update cert-managerをインストールします。 $ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true --version v1.16.1 cert-managerのPodが正常に起動しているか確認します。 $ kubectl get pod -n cert-manager Rancherのインストール cert-managerの準備が完了したら、Rancherをインストールします。 RancherのHelmリポジトリを追加 $ helm repo add rancher-latest https://releases.rancher.com/server-charts/latest $ helm repo update Rancherをインストールします。 $ helm install rancher rancher-latest/rancher \ --namespace cattle-system \ --create-namespace \ --set hostname=<NLB_DNS_NAME> \ --set replicas=3 \ --set bootstrapPassword=<YOUR_INITIAL_PASSWORD> \ --set ingress.tls.source=letsEncrypt \ --set letsEncrypt.email=<YOUR_EMAIL> RancherのPodが起動していることを確認します。起動が完了するまで数分程度かかります。 $ kubectl get pod -n cattle-system ブラウザにNLBのドメインを入力してアクセスします。もし、アクセスできない場合はrancherのPodの起動が完了していない可能性があるので、Podのステータスを確認してください。 RancherのUIに初回アクセスすると、初回パスワードの入力を要求されます。Helmのvalueとして設定したbootstrapPasswordの値を入力します。2回目以降のログインではRancherが自動生成した「New Password」を使うので、控えておいてください。 初回ログイン時はユーザーネームを要求されませんが、2回目以降のログイン時はユーザーネームの入力が必要です。デフォルトのユーザーネームは「admin」です。 利用規約に同意する(By checking the box~…の箇所)にチェックを入れて、「Continue」を押下します。 Rancherのホーム画面に遷移したことを確認します。構築が正常に完了していると、Rancherが稼働しているクラスター自身(画面内のlocalという名称のクラスター)が管理対象として登録されています。 サイドバーからlocalクラスターを選択すると、クラスターの詳細情報を見ることができます。 これでRancherの構築は完了です。RancherのUI画面から、クラスターや各種リソースの管理を開始できます。 構築時のトラブルシューティング RKE2のサービスが起動しない RKE2のサービス (rke2-server.service) が正常に起動しない場合、以下の点を確認してください。 必要なポートが開放されていない RKE2クラスターが正常に稼働するには、必要なポートが開放されている必要があります。ポートが開放されていない場合、サービスの起動が失敗します。 例:サービス起動失敗時のログ Nov 18 02:45:11 ip-10-1-2-193 rke2[66864]: time=”2024-11-18T02:45:11Z” level=fatal msg=”etcd cluster join failed: duplicate node name found, please use a unique name for this node” Nov 18 02:45:11 ip-10-1-2-193 systemd[1]: rke2-server.service: Main process exited, code=exited, status=1/FAILURE 対処方法: セキュリティグループの設定を見直し、RKE2の稼働に必要なポートが開放されているか確認してください。 Rancherの稼働に必要なポート要件については、公式ドキュメントPort Requirementsページの Ports for Rancher Server Nodes on RKE2 を参照してください。 ※RKE2だけではなく、Rancherの起動時にも利用するポート開放の設定は影響します。また、RKE2以外のディストリビューションでRancher用のKubernetesクラスターを構築した場合は、必要なポートが異なります。詳しくは、公式ドキュメント「Port Requirements」の Rancher Nodes の項目を参照してください。 config.yamlの設定ミス /etc/rancher/rke2/config.yaml の設定に誤りがあると、RKE2が正常に接続できず、サービスの起動に失敗する場合があります。特に、server パラメーターの設定ミスが原因で接続に失敗するケースがよく見られます。 対処方法: config.yaml に記載されている server パラメーターの記述が正しいか確認してください。特に、初期サーバーのIPアドレスやポート番号(9345)を間違えないように注意してください。 token がクラスター全体で一致していることを確認してください。 まとめ 今回の記事では、公式ドキュメントを参考に、AWS環境上にRKE2を利用してKubernetesクラスターを構築し、その上にRancher Serverを導入する手順を解説しました。Rancherを活用することで、クラスターの管理や運用を効率的に行える基盤を構築することができます。また、RancherはRKE2だけではなく、EKSなどのマネージドKubernetesサービスを含む他のKubernetesクラスターにも導入が可能なので、多様な運用要件に柔軟に対応することができます。 次回の記事では、今回構築したRancher Serverを活用して、マルチクラスターを管理する方法について解説します。複数のKubernetesクラスターを一元管理し、より高度な運用を行うための手法をご紹介しますので、ぜひご期待ください。 参考文献 RKE2のインストール(冗長構成) Rancher Serverのインストール ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Rancher入門:Rancher Serverの構築 first appeared on SIOS Tech. Lab .
アバター