TECH PLAY

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

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

546

こんにちは!安藤 浩です。11/22(金) に NexTech Week 2024【秋】に参加してきましたので、レポートします。 NexTech Week 2024【秋】 とは AI、ブロックチェーン、量子コンピュータ の最新テクノロジーとデジタル人材を育成するサービスが出展する4つの展示会で構成されます。 出展数は以下の通りです。 AI・人工知能 Expo :130社 ブロックチェーン Expo :41社 量子コンピューティング:20社 ブースの紹介 ブロックチェーン EXPOを中心に回ってきましたのでそちらのブースと講演の紹介をします。 connectiv NFT Garden  という企業向けのNFT生成プラットフォームを開発されています。 Web画面や API でNFT生成が可能とのことでした。 NFT をどう活用しようかというところで​  Snapshot  というリアルイベントの参加の記録、特典の利用などができるサービスを紹介されていました。 ダイナミック NFTで参加者がイベントでの条件をクリアするごとに、ビジュアルが変化し、達成度が分かる仕組みがありました。 株式会社クリプトリエ ミントモンスター  という NFTマーケティング・プラットフォーム でNFTを簡単に作成し、QRコードで配布できる仕組みです。 NFTの配布時にユーザにミッションを設ける、クーポンなどの特典を付与することができます。 NFTの配布で終わらない仕組みづくりがされていると思いました。 また、NFTをマーケティング活動としても利用できる機能も備えています。 内部的にウォレットの生成には NTT Digital の scramberry WALLET SUITE  が利用されているとのことでした。 参考:  クリプトリエ、NTT Digitalと「scramberry WALLET SUITE」の導入とNFTのビジネス活用におけるユースケースの協創について基本合意書を締結 ガイアックス 既存・新規事業DAO、採用系のDAO、自治体系のDAO などDAOの立ち上げ、運用支援をされており、立ち上げまで3カ月程度とのことでした。 DAOX  というサービスでDAOの立ち上げ、運用を行っているとのことです。海外のサービスとしては、  CharmVerse(チャームバース)  、  アラゴン  などがあります。実際、DAOという組織の運用においてリーダー的な立ち位置の人がいないと継続は難しそうという話もお聞きしました。 福岡県未来ITイニシアティブ 福岡県未来ITイニシアティブ  という福岡県の新産業振興課で実施している取り組みで、福岡県内のIT産業の発展を目指して、環境づくり、人材の育成を行っているとのことでした。そちらのブースにて共同出展されていたのは4社あり、 九州NFTラボ 、株式会社INTLEIR、  合同会社 暗号屋 、 株式会社ワーキングハセガワ  が出展されていました。 ちなみに、 福岡県未来ITイニシアティブ  主催の 福岡県ブロックチェーンフォーラム2024  が11/28に開催されるとのことです。 九州NFTラボ COMMUN  というスマホアプリ、プラットフォームを開発しており、訪問の証明としてNFTを配布サービスを提供しています。 企業がイベントを開催するときに イベント会場にIC カードを設置して、ユーザにNFC(ICカード)やQRコードでNFTを配布するということでした。 それらのNFTを活用して、訪問証明やクーポンが利用できるとのことです。訪問者限定のコンテンツ提供につなげようとしているとのことでした。 ブース内でQRコードを読み取り、 NFT を配布いただきました。 JPYC 株式会社 Ethereum、Polygon、Avalanche、Astarなどで発行しており、1JPYC=1円として利用できるERC20規格のステーブルコインです。  SDK  を利用してもよいし、Openzeppelinなどでも開発できるとのことでした。 JPYC のビジネスモデルについて疑問があったのでお聞きしたら、JPYCを発行し、その裏付け資産として国債を購入して、その運用益と関連事業の手数料収入などを収益にしているとのことでした。 N.Avenue株式会社 CoinDesk Japan を運用している会社です。費用は掛かりますが、「 N.Avenue Club 」で企業間のコラボレーションやネットワーキング出来るとのことでした。 参加企業は  こちら に記載されていました。 アーリーワークス GLS (Grid Ledger System) という世界最高水準の速度を誇る高速ブロックチェーンということで、1取引約0.2秒で完了するとのことです。 ブース内ではブロックチェーンを使って何ができるのかが記載された「ブロックチェーン活用事例集50」が紹介されていました。  実績  としてGLSを利用した不動産プラットフォームや要件定義を担当された MetaMe  が紹介されていました。 株式会社 シーエーシー KOUKA  という社内や組織間での貢献や称賛を表現するためにNFTを送ることができるシステムが紹介されていました。 貢献や称賛を可視化し、貢献度の高い社員を見つけられるということができるようです。 組織間(例:会社間)でも利用したいという用途を踏まえ、ブロックチェーンを利用しているとのことでした。 大手金融機関、損保系向けにCorda、EnterPrise Ethereum 、Hyperledger 系での開発経験があり、特にCordaの要員は多そうでした。 また、Japan Open Chain のバリデータでもあります。 マネックスグループ 株式会社 Monex Web3 ID(MID)  は最近オープンベータ版としてリリースされ、メールアドレスを使用した登録により自動的にウォレットが発行される仕組みです。 MIDは Polygon 上で発行されたNFTで、別ユーザに移転することができない Soulbound Token(SBT)とのことでした。 MIDに対してクエストのようなものを設定し、クリアすることでスコアとして表現することができるとのことでした。 今後の展望として、個人の属性情報の取得や行動履歴の証明につなげていきたいとのことでした。 旭化成株式会社 Akliteia  という偽造防止するラベルとサプライチェーン上の製品の流通をブロックチェーン上に記録するソリューションを紹介していました。 ラベルは複製が困難でめちゃめちゃ細かいパターンが印刷されていて専用のデバイスで真贋を判定するとのことでした。今までサプライチェーン上の製品をトラッキングするにはどうしたら良いのだろうと思っていましたが、こういう感じでするのだと興味を持ちました。 キリフダ株式会社 LINEでウォレットを自動生成しLINE内でNFTの配布、閲覧ができるサービスを提供しているとのことでした。 また、QRコードを読み取り、NFTを保有を認証する仕組みもあるようです。( NFTauth ) NEMTUS Symbol とSymbolを利用したサービスの普及をしているNPO法人です。周辺のブースの方は、Symbolと関連がある方が多かった印象です。 ボードで紹介されているのは個人で開発されたものが多めとのことでした。 株式会社NFTDrive NFTDrive  というフルオンチェーンを実現するサービスを提供しています。 画像、動画、圧縮ファイルなどをすべてSymbolのブロックチェーン上に保管する取り組みをされています。プライベートネットワークにも対応できるとのことでした。 Atomos-Seed合同会社 トークンの形・量・質の向上を図る トークンデザイン という考えをご説明いただきました。  Heartlog  というフルオンチェーン保存するNFTのサービスを紹介されていました。 こちらは先ほど紹介したNFTDriveを利用しているとのことです。 その他、紹介しきれませんでしたが、 株式会社Pacif i c Meta 、  株式会社SARAH  、  SUSHI TOP MARKETING株式会社  、  GCC  などを拝見させていただきました。 講演について 以下の2件聴講させていただきました。 1.「Web3の社会実装を実現する新規事業ノウハウについて」 主に  Grid Ledger System (GLS)  と  MetaMe  を題材にして話されていました。 MetaMe  は共通の価値観を持つ人と関われるコミュニケーション空間を提供するサービスです。 NFT レコメンド機能、トークングラフを利用して、ファンの熱量などの可視化できなかった部分を可視化できるようになるとのことでした。 また、ユーザにNFTを利用しているということを感じさせない作りを意識しているように思いました。 DAOのような組織だったり、特別誰が担当という決まっていないような作業に対して、貢献度や報酬を可視化することでユーザにメリットがあるのではないかという話が上がっていました。 2.「NFT活用によるメディアイベントの新たな価値創出」 みんなのあしあと を事例にお話しされていました。コンテンツを送るだけではなく、ユーザとの永続的なつながりを意識しユーザのコミュニティを意識してイベントやSNS、配信などでクロスセルを行っていく戦略についてのお話しをされていました。スポーツだったらスポーツ番組、イベント、大会、ボランティア、アウェイツーリズム などで経済活動を活性化するというところ進めると良さそうというお話しでした。 まとめ エンドユーザやブロックチェーンの仕組みでマーケティングしたい、イベント開催したいというサービスを提供しているところが多かった印象。 NFTの配布や所有などによってどうユーザが活用、メリットを生み出すかというところを各企業さんが注力されているように思いました。 AI の企業も数社お聞きしましたが、よりプロンプトや操作が簡単なもので精度高く期待のデータが得られることに注力しているような印象でした。 NexTech Week 2025【春】は2025年4月15日(火)~17日(木)に 東京ビッグサイト(東展示棟)で開催されるようです。ぜひ参加されてはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【イベントレポート】NexTech Week 2024 秋 – ブロックチェーン Expo – に参加してきました! first appeared on SIOS Tech. Lab .
アバター
こんにちは!安藤 浩です。今回はAzure AI Studio でのプロンプトフローの構築とプロンプトフローの評価についてご説明します。 Azure AI Studio とは Azure で提供される AI 関連のサービスを 1 つのプラットフォームにまとめたものです。 AI関連のサービスを一元管理でき、簡単にアプリ開発や AI モデルの構築、評価ができます。 プロンプトフロー とは プロンプトフローとはLLMを含むAI アプリケーションの開発を実現できる開発ツールです。 GUIで処理と処理のつながりを可視化でき、評価も実施できます。 フローの種類には標準フロー、チャットフロー、評価フローなどがあります。 以下では、プロンプトフロー の基本的な使い方を紹介します。 プロンプトフローの実行方法 AI Studio を開き、ツール > プロンプト フローを押下します。 作成ボタンを押下します。 ローカルからアップロード の アップロードボタンを押下し、右側にアップロード画面が開くので、フォルダを参照して、アップロードします。 ここではもっとも  簡易的なチャットフロー のサンプル  を例にアップロードしてみます。 また、フローの種類の選択は Chat Flow を選択します。 アップロードが完了すると、以下の画面が表示され、左側にフローが表示されます。 ここで接続の箇所で既にDeploy済のGPTを指定します。 「コンピューティング セッションを開始」を押下して、コンピューティング セッションを開始します。 コンピューティング セッションの開始は数分かかります。 コンピューティング セッション実行中のとなりのチャットボタンでチャットをすることができます。 プロンプトフローの評価方法 続いて、プロンプトフローの評価方法を説明します。 ツール > 評価 を押下します。 「+New evaluation」ボタンを押下します。 Prompt flow を選択します。 「評価するフローを選択する」で上記で作成したプロンプトフローを選択します。 「評価するデータを選択する」の箇所で「データセットの追加」で「ファイルをアップロードする」ボタンを押下して以下のdata.jsonl をアップロードします。 {"query":"What is the capital of France?", "ground_truth": "Paris","response": "","context": "","history": "[]"} {"query":"What is the capital of Japan?", "ground_truth": "Tokyo","response": "","context": "","history": "[]"} {"query":"What is ChatGPT?","ground_truth":"ChatGPT is a form of generative AI -- a tool that lets users enter prompts to receive humanlike images, text or videos that are created by AI.","response":"","context":"","history": "[]"} {"query":"What is Machine learning (ML)?","ground_truth":"Machine learning (ML) is a branch of and computer science that focuses on the using data and algorithms to enable AI to imitate the way that humans learn, gradually improving its accuracy.","response":"","context":"","history": "[]"} ※Machine Learning のGround Truth は  https://www.ibm.com/topics/machine-learning  より引用。 プロンプトフローのデータセットマッピングで、以下のようにマッピングします。 設定したら、次へを押下します。 AI品質の箇所、マッピングは以下のように設定します。 ここではコンテキストは利用しないので、根拠性、関連性はチェックしません。 設定出来たら、次へを押下します。 内容を確認して「送信」を押下すると評価が開始されます。 実行結果が出るまで時間がかかりますが、以下のような結果が表示されます。 メトリックス AI Studio でのプロンプトフローの評価では以下のようなメトリックスがあります。 メトリックス 説明 コヒーレンス 生成されたテキストの一貫性と自然性を評価する。言語モデルが、スムーズに流れ、自然に読み取られ、人間のような言語に似た出力を生成できる程度を測定する。 流暢性 モデルの回答の言語能力を評価するために使用されるメトリック。生成されたテキストが文法規則、構文構造、ボキャブラリの適切な使用方法にどの程度準拠しているかを評価し、言語的に正しく自然に聞こえる応答であるかを評価する。 類似性 正解の文 (またはドキュメント) と AI モデルによって生成された予測文の類似性を測定する。 F1スコア モデルの予測とソース データ (グラウンド トゥルース) の間で共有される単語の数の比率を測定する。 グランド度 モデルの生成された回答が入力ソースからの情報とどの程度整合しているかを評価する。 関連性 モデルの生成された応答がソースのデータからの情報とどの程度関連するかを測定する。 メトリックスとその説明 評価結果の結果の解釈 上記の結果のインデックス:0,1 でコヒーレンス、流暢性、類似性はいずれも5で高い値です。Ground Truth(人間が入力した値) と一致しています。 インデックス:2,3 についてはコヒーレンス、流暢性は高いですが、上記に比べると類似性はやや少し低くなっていますが、Ground Truth(人間が入力した値)の入力よりも回答のほうがより詳細な説明になっているのでこのような値になったのだと思います。F1の値は回答のほうがより詳細な説明なので低い値になっていると推測します。 インデックス:2 の回答の冒頭の内容(翻訳済)は以下のようになっています。Ground Truth をもう少しより詳細にしたほうが良かったのではと思います。 ChatGPT は OpenAI が開発した会話型 AI モデルで、GPT (Generative Pre-trained Transformer) ファミリーの一部です。入力に基づいて人間のようなテキストを理解して生成するように設計されています。ChatGPT は会話に参加したり、質問に答えたり、説明を提供したり、自然言語を処理することで幅広いトピックを支援したりすることができます。 インデックス:3 の回答の冒頭の内容(翻訳済)は以下のようになっています。インデックス: 2と同様により詳細な説明がなされています。 機械学習 (ML) は人工知能 (AI) のサブセットであり、コンピューターがデータから学習し、特定のタスクごとに明示的にプログラムすることなく予測や決定を行えるようにするアルゴリズムとモデルの開発を伴います。 ML システムは、静的な一連のルールに従うのではなく、より多くのデータにさらされるにつれて時間の経過とともにパフォーマンスが向上します。 ### 機械学習の主要な概念: 1. **学習の種類:** - **教師あり学習:** モデルはラベル付きデータでトレーニングされます。つまり、各トレーニング例は出力ラベルとペアになっています。目標は、入力から出力へのマッピングを学習することです。 まとめ 簡単なチャットの例でしたが、Azure AI Studio でのプロンプトフローの実行とプロンプトフローの評価の方法について説明しました。 AI Studio でのプロンプトフローの評価はプレビュー版ですが、作成したプロンプトフローの妥当性を測るために有用なツールなので利用してみてはいかがでしょうか。 参考URL Azure AI Studio でのプロンプト フロー Azure AI Studio を使用して生成 AI アプリを評価する方法 生成 AI の評価と監視メトリック Prompt flow ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure AI Studioによるプロンプトフローの構築と評価入門 first appeared on SIOS Tech. Lab .
アバター
以前の記事 では、CI 部分を担う OpenShift Pipelines の構築を行いました。続いて、本記事では実際に CD 部分となる OpenShift GitOps を構築して デプロイ先の状態変化を検知してマニフェストファイルの状態を保ち続ける pull 型のデプロイを実装してみたいとおもいます。 構築の概要 前回構築したCIパイプラインと組み合わせて図のような CI/CD パイプラインを OpenShift 上に構築します。 OpenShift GitOps ハンズオン の一部を参考にしています。前回と同様にチュートリアルではパブリックリポジトリを利用していますが、実際構築する際はプライベートリポジトリであるケースが多いため、プライベートリポジトリで構築してみます。CD 部分の動作については OpenShift GitOps がクラスター内のリソースとマニフェストリポジトリを監視しており、マニフェストを正として常にクラスター内のリソースとの同期をとります。必要な作業としては OpenShift GitOps のインストール、マニフェストリポジトリの登録、マニフェストを OpenShift 上にデプロイするためのアプリケーション設定になります。 事前準備 下記構成のプライベートなマニフェスト用Git リポジトリを用意します。アプリケーションをデプロイするためのマニフェストファイルが格納されています。 app ├── deployment.yaml ├── kustomization.yaml ├── route.yaml └── service.yaml deployment.yaml 内の image tag には アプリケーションGitリポジトリ側のコミットIDを参照します。コミットIDは git側でも確認が可能ですが、CI パイプライン実行後に下記コマンドを実行して image stream の tag を参照する方が簡単です。 $ oc get imagestream -n pipelines-tutorial NAME IMAGE REPOSITORY TAGS UPDATED ocp-cicd-appli-ui image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/ocp-cicd-appli-ui 974d59ed90012de8d19e47a5e74807018d08c5ae 26 minutes ago deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   replicas: 1   selector:     matchLabels:       app: ocp-cicd-appli-ui   template:     metadata:       labels:         app: ocp-cicd-appli-ui     spec:       containers:         - image: image-registry.openshift-image-registry.svc:5000/ci-pipeline/ocp-cicd-appli-ui:<image tag>           imagePullPolicy: Always           name: ocp-cicd-appli-ui           ports:             - containerPort: 8080               protocol: TCP kustomization.yaml resources: - deployment.yaml - service.yaml - route.yaml route.yaml apiVersion: route.openshift.io/v1 kind: Route metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   port:     targetPort: 8080-tcp   to:     kind: Service     name: ocp-cicd-appli-ui     weight: 100 service.yaml apiVersion: v1 kind: Service metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   type: NodePort   ports:     - name: 8080-tcp       port: 8080       targetPort: 8080       protocol: TCP   selector:     app: ocp-cicd-appli-ui 前提条件 OpenShift クラスターが構築済みであること oc CLI がインストール済みであること 前回の記事 でCIパイプラインが実行されており、imageがopenshift-image-registryにプッシュされていること OpenShift GitOps をインストール OpenShift OperatorHub で Administrator のパースペクティブにいることを確認します。 Web コンソールで[Operators] > [OperatorHub]に移動します。 検索バーに「OpenShift GitOps」と入力して、 OpenShift GitOps をクリックして Install をクリックします。 デフォルトのまま Install をクリックします。 OpenShift GitOps のログイン 下記コマンドを実行してArgo CD へアクセスする URLを確認します。 $ oc get route openshift-gitops-server -o jsonpath='{.spec.host}' -n openshift-gitops 取得した URL に Web ブラウザからアクセスします。 下記コマンドを実行して admin ユーザでログインするためのパスワードを確認します。 $ oc extract secret/openshift-gitops-cluster --to=- -n openshift-gitops # admin.password <password> Usernameに admin と Password に上記のコマンドで取得したパスワードを入力し、Argo CD にログインします。 ArgoCD の ホーム画面が表示されれば完了です。 OpenShift GitOps 構築 Argo CD へのデプロイ権限の付与 下記コマンドを実行して Argo CD の Service Account (openshift-gitops-argocd-application-controller) に対して、対象の Project に対する edit 権限を付与します。 $ oc adm policy add-cluster-role-to-user edit system:serviceaccount:openshift-gitops:openshift-gitops-argocd-application-controller プライベートリポジトリの登録 Github で Personal access token の発行をします。 Settings -> Developer Settings -> Personal access tokens にいき、Generate new token をクリック(Personal access tokens (classic) を選択)します。 Personal access tokenが発行されるのでそれをメモしておきます。 ArgoCD ダッシュボードから Settings -> Repositories にいき、Connect Repo をクリックします。 下記パラメータを入力して [CONNECT] をクリックします。 登録したリポジトリに対する CONNECTION STATUS が Successful になったら完了です。 Choose your connection method: VIA HTTPS Project: default Repository URL: GitHubリポジトリのURL(末尾が .git で終わるURL) Username: 任意 Password:上記でメモしたPersonal access token アプリケーションのデプロイ(GUI操作) GUI か CLI いずれかでアプリケーションのデプロイを行います。 Argo CD ダッシュボードから [+ NEW APP] ボタンをクリックし、以下の内容を入力し Argo CD アプリケーションを作成します。 Application Name: sample-app Project: default Sync Policy: Automatic Repository URL: GitHubリポジトリのURL(末尾が .git で終わるURL) Revision: HEAD Path: app Destination: https://kubernetes.default.svc Namespace: pipelines-tutorial Sync Policy は Manual と Automatic を選択できます。今回はクラスターへのマニフェストリポジトリの反映を自動で行うために Automatic に設定します。クラスターへの反映にワンクッション(SYNCボタンを押す動作を)挟みたい本番環境などのユースケースでは Manual を選択します。 ダッシュボードにアプリケーションが作成されていれば成功です。 アプリケーションのデプロイ(CLI操作) 下記コマンドを実行してアプリケーションのデプロイを行います。ダッシュボードにアプリケーションが作成されていれば成功です。   $ oc apply -f application.yaml application.argoproj.io/sample-app created application.yaml application.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata:   name: sample-app   namespace: openshift-gitops spec:   project: default   source:     repoURL: GitHubリポジトリのURL(末尾が .git で終わるURL)     path: app     targetRevision: HEAD   destination:     server: https://kubernetes.default.svc     namespace: pipelines-tutorial # Sync Policy を Manual にする場合は下記を削除   syncPolicy:     automated: {} 動作テスト マニフェストの変更とデプロイ マニフェストファイルを編集します。 deployment.yaml のレプリカ数を変更 (1->3) します。 deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   # replicas: 1   replicas: 3   selector:     matchLabels:       app: ocp-cicd-appli-ui   template:     metadata:       labels:         app: ocp-cicd-appli-ui     spec:       containers:         - image: image-registry.openshift-image-registry.svc:5000/ci-pipeline/ocp-cicd-appli-ui:<image tag>           imagePullPolicy: Always           name: ocp-cicd-appli-ui           ports:             - containerPort: 8080               protocol: TCP ダッシュボード上を確認して、Pod が3つデプロイされていれば成功です。 OpenShift 上のリソースが削除された場合のセルフヒーリングの確認 下記コマンドを実行して、OpenShift 上のリソースを削除します。  $ oc delete route ocp-cicd-appli-ui -n pipelines-tutorial route.route.openshift.io "ocp-cicd-appli-ui" deleted [DETAILS] ボタンより [SYNC POLICY] > [SELF HEAL] の [ENABLE] ボタンを押します。 Argo CD が Git リポジトリと OpenShift の状態の差異を検知し、自動的にリソースが復旧されることを確認します。 他にも以下のコマンドを実行して、OpenShift 上のリソースが自動的に復元されることをダッシュボード上で確認します。 $ oc delete svc ocp-cicd-appli-ui -n pipelines-tutorial service "ocp-cicd-appli-ui" deleted $ oc delete deployment ocp-cicd-appli-ui -n pipelines-tutorial deployment.apps "ocp-cicd-appli-ui" deleted リソース削除時の挙動の確認 Git リポジトリから route.yaml ファイルを削除し、kustomization.yaml から route.yaml の行をコメントアウトします。 kustomization.yaml resources: - deployment.yaml - service.yaml # - route.yaml [DETAILS] ボタンより [SYNC POLICY] > [PRUNE RESOURCES] の [ENABLE] ボタンをおします。 Route のリソースが OpenShift 上から削除されることを確認します。 まとめ 本記事では実際に OpenShift GitOps のハンズオンを参考にしてOpenShift Pipelines の CI 部分に連携する CD 部分を構築してみました。これでビルドの自動化からアプリケーションのデプロイまでの CI/CD パイプラインを実現できました。 参考文献 https://github.com/mamoru1112/openshift-gitops-handson         ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift GitOps を構築してみた first appeared on SIOS Tech. Lab .
アバター
本ハンズオンでは、Azure OpenAI Serviceを活用したRAG(Retrieval-Augmented Generation)の導入から本格的なシステム構築までを段階的に学べます。 上級編では、Azure OpenAIとサーバーレステクノロジーを組み合わせ、本番環境での運用に対応できる実践的なRAGシステムの構築手法を学びます。生成AI技術の理解を深め、応用力を高めたい方に最適な内容です。 ご興味がある方はお早めにお申し込みください。 【上級編】Azure OpenAIとサーバーレステクノロジーを駆使したRAGシステム構築ハンズオン 〜本番環境での運用に対応できる実践的なRAGシステムの構築〜 <概要> Azure OpenAI Serviceと生成AIの概要 RAGの基礎概念 生成AIに特化した検索手法 AzureでRAGを実現するために必要なサービス ハンズオン <日時> 2024年12月5日(木)10:00~17:00(受付9: 30~) <場所> 〒106-0047 東京都港区南麻布2-12-3 サイオスビル3F <得られるスキル> Azure OpenAI Serviceの基礎 Azure OpenAI Serviceがどのようなサービスであり、どのように利用するのかを学ぶことができます。これにより、クラウドベースのAIサービスの活用方法を理解し、自身のプロジェクトに適用するための基礎を築くことができます。 本番でRAGを動かすために必要なアーキテクチャの習得 本番環境での運用に対応できる実践的なRAGシステムのアーキテクチャを学びます。Azure FunctionsやAzure Static Web Apps、Azure AI Document Intelligenceなどの最新サーバーレス技術を活用し、柔軟かつスケーラブルなシステムを設計するための知識を習得します。 RAG構築方法 実際にRAGを構築するための基本的な手順を学びます。 ハンズオンを通じて、 独自データの準備から外部データベースへの登録、 そして生成AIを用いた回答生成までの流れを体験し、 実践的なスキルを身につけることができます。 <費用> 有料 <定員> 24名(先着順) <対象者> 本番環境での運用に対応できる実践的なRAGシステムの構築を検討される方   【有償】支援サービス 上級テクニカルトレーニング Azureの最先端技術を駆使したRAGハンズオンです。 このハンズオンでは、最新の検索手法である「 セマンティックハイブリッド検索」、Azure Static Web Apps、Azure Functionsによるフルサーバーレス構成など、 最新技術を用いたRAGの構築方法をお伝えします。 業務委託・技術支援 当社では、AIだけでなく、 クラウドネイティブなアプリケーション開発、 既存システムのクラウド移行・モダナイゼーション、 システムの基盤構築など、 クラウドを中心としたシステム開発あるいは技術支援なども行って おります。システムでの困り事がありましたら、 ぜひご相談ください。 チャットボット作成 (RAGツール開発) RAG(Retrieval-Augmented Generation)を中心に、 話題の生成AIを活用した業務の効率化、 DX化をお手伝いいたします。社内ノウハウの見える化、 カスタマーサポートの省力化、 チャットボットアプリケーションの導入など、 社内資源の有効活用をお考えの場合は、ぜひご相談ください。 AI関連アプリ開発 既存のアプリ・システムを、もっと便利に・ 楽にできないかお考えですか?RAGやLangChain などにより生成AIを活用すれば、 今まで以上により業務効率を上げるのに効率的なアプリの開発を行 うことができます。 まずはコンサルティングという形からご相談いただくことも可能で す。AIで迷われたら、ぜひご相談ください。 Azure CSP販売・技術支援 Azureのライセンス販売を通じてお客様のビジネスをご支援し ています。 Azureライセンスの提供からAI技術のコンサルティングまで 全て当社にお任せください。​​​​ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【12/5開催:上級編】Azure OpenAIとサーバーレステクノロジーを駆使したRAGシステム構築ハンズオン 〜本番環境での運用に対応できる実践的なRAGシステムの構築〜 first appeared on SIOS Tech. Lab .
アバター
サイオステクノロジーの菊地啓哉です。今回は、Solidity のプログラムを開発・実行できるWeb IDE の Remix で、MetaMask が使えなくなるという現象が発生して、解決できたので、その情報の共有です。 「こうしたら解決できた」というだけの内容なので、とっても薄い内容になってます。 環境 Google Chrome Chrome の拡張機能の MetaMask 起こったこと ある時、検証のために Remix で SmartContract を開発し、Remix VM ではなく実際のチェーン上で実行したかったので、ENVIRONMENT で Injected Provider - MetaMask を選ぼうとしたところ、反応が、、無い…!? ここで選択しても、切り替わらない 解決のためにやったこと 早速結論です。 MetaMask のアクセス許可リストから、Remix を一度削除しました。 Remix上で次に操作した際にアクセス許可が求められ、正常に利用できるようになりました。 ということで、もう少し詳細を。 MetaMask の拡張機能の右上の3点リーダーで開かれるメニューから、「すべてのアクセス許可」を選択 Remix(remix.ethereum.org)を選択 最後に「すべてのアカウントを接続解除」から接続を解除します。 先に書いた通り、ここで接続を解除しても、また使おうとすると許可を求められて、許可すれば以前と同様に利用できました。 最後に 原因は何だったんでしょう? MetaMask側のセキュリティアップデートか、Remix側のアップデートかはわからないですが、少し様子を見てもネット上で問題になっているようなことも見受けられなかったので、個人の環境の問題だろうという推測はたっていました。 MetaMask を入れなおしたりする手間に比べると格段に手軽にできるので、Remix に限らず、MetaMask が使えていたはずなのに急に使えなくなった際には試してみても良いかもしれません。 今回は薄っぺらいですが、以上になります。 またかきます またね ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Remix で MetaMask が使えなくなったけど解決できた話 first appeared on SIOS Tech. Lab .
アバター
生成AIの分野でもRAGは特に注目を集めており急成長している分野です。あまりに多くの情報に溢れており、各手法をどう捉えてよいか分かりにくい状況にあります。このブログではRAGがどのように成長し、どのような改善が試みられているのかを整理して、包括的で体系的に理解できるような説明を試みました。読んでいただいた方の理解の助けになれば幸いです。 RAGの概要 LLMは非常に優れた効果を発揮したものの、嘘を答えてしまうハルシネーションや古い知識での応答、回答の根拠の分からない不明瞭な推論といった問題を抱えています。RAGはこれらの課題に対し外部データベースを取り入れるというアプローチで解決を試みており、特に注目を集めている分野であり急速に進化しています。また、外部データベースを取り入れるという特性からドメイン固有の知識とLLMを組み合わせることができるため、企業からも大きな注目をされており研究・開発を実施されています。 基本的なRAGシステムのシナリオは図1のようになります。まず、ユーザがシステムに対して質問を投げかけます。システムは質問を元にデータベースに関連するドキュメントを問い合わせます。そのドキュメントを元にLLMが回答を生成しユーザに提供します。これによりユーザは従来の単純な検索システムよりもLLMを介することによって柔軟な質問でデータにアクセスしたり、的確な回答を得ることを期待できます。 (図1: 基本的なRAGの動作。 Retrieval-Augmented Generation for Large Language Models: A Survey [ 1 ]より引用) しかし、単純な方法では期待されたほどの効果は得られないことが分かってきており、現在は様々な改善が試みられているという状況です。その改善について説明していきます。 RAGの進化とパラダイム RAGのパラダイムはNaive RAG、Advanced RAGを経て、Modular RAGへと進化しています。Naive RAGは最も基本的なRAGでシンプルですが多くの課題を抱えています。Advanced RAGはNaive RAGのフローをベースとして各処理の改善したものとなっています。さらに、Modular RAGでは、RAGで必要な各処理をモジュール化し、それらを組み替えることで新たなパターンを生み出して大きな性能の改善を試みています。 Naive RAG (Baseline RAG) Naive RAG(Baseline RAGと呼ばれることもあります)は最も素朴なRAGのことです。インデクシングではPDFやWord、Markdownの文書データをプレーンテキストに直した後に固定のトークンの長さ(100, 256, 512など)でチャンクに分割。チャンクごとのベクトル表現を計算し、ベクトルデータベースに格納します。検索ではユーザの質問をベクトル表現に変換し、データベースから類似度の高いコンテンツを検索して、ドキュメントから回答を生成します。 このRAGは大きなの欠点を抱えていると指摘されています[ 1 ]。 検索の課題: 検索の再現性や精度が悪く、不揃いで無関係なチャンクがヒットし、重要な情報が欠落してしまうという。 回答生成の困難: RAGでも単にLLMを利用する場合と同様に ハルシネーションを起こすことがあり、無関係であったり、有害であったり、バイアスのある情報を出力しうる。 検索結果の統合のハードル: 検索さらた複数の結果をうまく統合できずに適切な応答ができないことがある。多くの文書から関連性や重要性を判断し、統合して、一貫性のある回答を引き出すことは困難である。これらには一度の検索処理では不十分である。 1度でもRAGを構築されたことがある方なら頷ける内容ではないかと思います。RAGは基本的にこれらの課題を解決しようと進化を続けています。 Advanced RAG Advanced RAGはNaive RAGの基本的な処理フローを踏襲しつつ、検索や回答生成など各処理の品質の向上に着目し、回答の精度の改善をしようとしています。 (図2: Naive RAGとAdvanced RAGとModular RAGの処理イメージ。 Retrieval-Augmented Generation for Large Language Models: A Survey [ 1 ]より引用) 図2のAdvanced RAGのオレンジ部分がNaive RAGに対し追加されているテクニックです。Advanced RAGのテクニックはもう少し複雑であったり他のオプションを含むものなので、この図で完全に表されている訳ではありませんが、インデックス化、検索手法、回答生成のそれぞれに対して改善しているのがAdvance RAGです。これらの改善については 改善手法 のセクションで紹介します。 Modular RAG 単純にRAGの質問、検索、回答生成という線形なプロセスの工程をそれぞれ改善するだけでは限界がみえてきました。そこで、Modular RAGはNaive RAGやAdvanced RAGを基本としつつ、RAGの機能のモジュール化により適応性と再利用性を向上しようとしています。図2のようにModular RAGではRAGの各機能がモジュールとなり、それらを組み合わせた「パターン」をちょうどLEGOブロックのように組み上げていくという方法をとります。 より具体的にModular RAGの内容を見ていきます。Modular RAGは次の3層に分かれたアーキテクチャを持ちます。 モジュールタイプ (Module Type) モジュール (Module) 演算子 (Operator) モジュールタイプは最上位のレイヤーで、RAGのインデックス作成や検索、生成といった工程を表します。モジュールは中間のレイヤーで、各工程で実施する機能でチャンク化やクエリルーティングなどのより具体的な機能を表します。最後に演算子は最下位のレイヤーで、構造化インデックスやHyDEなど具体的な実装を表します。 このような3層の抽象化を用いることで自在な組み合わせを実現します。図3はモジュール、サブモジュール、演算子の具体例です。 (図3: Modular RAGのモジュールの一覧。 Modular RAG: Transforming RAG Systems into LEGO-like Reconfigurable Frameworks [ 2 ]より引用) インデックス作成 (Indexing)、検索 (Retrieval)、検索事前処理 (Pre-Retrieval)、検索事後処理 (Post-Retrieval)、回答生成 (Generation)という従来のRAGの機能をモジュールしたもののほかに、オーケストレーション (Orchestration)が存在します。オーケストレーションはModule RAGの重要なモジュールタイプで、異なるモジュール間の調整役を担います。データやクエリに基づいて適切なモジュールを選択してフローを制御することで、より多くのデータやクエリに対して適応できるようになります。 Modular RAGはツールやフレームワークを利用することで実現することができます。Modular RAGを実現するツールやフレームワークをいくつかご紹介します。 Cognita は Langchain/LlamaIndex のラッパーのように動作し、RAGで必要なモジュールを提供し、 Langchain/LlamaIndex を単体で用いるよりも再利用性が高まります。 Advanced RAGが構築可能な Haystack と軽量なAI/機械学習の構成管理フレームワークである Hypster を組み合わせることで実装することもできます[ 3 ]。 AutoRAG はモジュールの組み合わせを自動的に選択できるという特徴を持つツールです[ 4 ]。G-EvalやRAGAsといった評価ツールを用いて、自動評価を実施し適切なパターンを走査してくれます。 まだ、この領域は発展途上であり成熟したツールは存在していませんが、注目度が高く変化が激しい状況です。今後さらに発展する領域と考えられ注視していく必要があります。 RAGの進化の過程 ここまでみたようにRAGはNaive RAG、Advanced RAG、Modular RAGという変遷を辿っています。これらのパラダイムは全く別ものではなく、前のパラダイムを拡張・改善する形で進んできています。Advanced RAGはNaive RAGの各処理をより洗練させ、Modular RAGはAdvanced RAGの処理をモジュール化し、その組み合わせのパターンによるより柔軟なアーキテクチャで非常に大きな工夫の余地を与えてくれています。また、最新のModular RAGというパラダイムが出たので、Advanced RAGは終わったかというとそういう訳ではなく、Advanced RAGにおける改善手法は現在でも進化を続けており、それがModular RAGのモジュールとなり進化していくという流れは続いています。そういう意味で今後しばらくの間は特定のパラダイムだけでなく全体を追っていく必要があります。 RAGとファインチューニング RAGとファインチューニング(追加学習)は類似した技術であるためしばしば比較されます。ここではRAGとファインチューニングの関連について説明します。 RAGとファインチューニングの違い RAGとファインチューニングはどちらもモデルがもともと持っていない情報をモデルに取り扱わせるという意味で同じですが、両者の方法はそれぞれことなります。RAGは前述の通りで外部のデータベースから情報を参照し、その情報を元に回答を生成します。通常、RAGでは事前学習されたモデルをそのまま使います。一方で、ファインチューニングはモデル自体にさらに追加の学習を行わせるという方法で、モデル自体(LLMのニューラルネットワークのパラメータ自体)が更新されて新しい情報を取り込みます。ファインチューニングは質問とそれに対する回答のセットである「学習データ」を用いてモデルを調整します。OpenAIなどのプラットフォームではこのような学習データをアップロードするだけで、ファインチューニングできる仕組みが提供されています[ 5 ]。 ファインチューニングは特定用途のタスクに対して効果的な能力を発揮します。例えば、特定ドメインの思考方法やより厳格な推論能力を向上などに効果が発揮されています[ 7 ]。しかし、多くの学習を行うと以前に学習したことを忘れてしまうといった「破壊的忘却」をしたり、学習した情報を回答できるようになってもその根拠を示せなかったり、新しいデータが更新されるたびにファインチューニングの手間がかかるといった課題があります。 RAGはファインチューニングがブラックボックス化してしまうのに対し、インデックス作成や検索・回答生成などの段階が見える形で存在しているためカスタマイズしやすかったり、データベースを更新すること情報が更新できるので最新を保ちやすいという特徴があります。しかし、RAGの回答は検索の品質に大きく依存しているため、RAGの構築は検索の工夫がどれだけできるかにかかっているとも言えます。 RAGとファインチューニングの性能 Microsoft Researchによる論文ではファインチューニングに対して、RAGの方が性能が高いと報告されています[ 6 ]。 (図4: Oren Elisha, Fine-Tuning or Retrieval? Comparing Knowledge Injection in LLMs [ 6 ]より引用。) この検証ではRAG単体が最も性能が良く、次にRAGとファインチューニングの組み合わせ、最後にファインチューニングという順で性能が高いという結果になりました。Llama2に関してはファインチューニングとRAGの組み合わせが最も高い結果となりました。したがって、検索という観点ではRAGが優れているでしょう。 RAGとファインチューニングの融合 検索ではRAGが優れていたからといってRAGだけを用いるだけでなく、RAGとファインチューニングは両方を活かすことができます。 前セクションの論文では知識を正しく取り出せるかに着目しており、それ以外のタスクに関する検証は行なっていないので、単純にファインチューニングがRAGより一般的に劣っていると判断する材料にはなりません。例えば、専門分野における推論能力の向上では専門分野のコーパスを用いてファインチューニングさせることで性能が向上されたことが報告されています[ 7 ]。このようなタスクに関しては原理的にRAGで対応することは難しいでしょう。 つまり、図5のように外部知識が必要となるタスク(External Knowledge Required)ではRAGが有効で、モデル適応が必要となるタスク(Model Adaptation Required)ではファインチューニングがより有効です。Moduler RAGではファインチューニングされたモデルを組み合わされる方法が使われてきています。 (図5: Retrieval-Augmented Generation for Large Language Models: A Survey [ 1 ]より引用) 改善手法 RAGで提案されている改善を次の3つに分けて紹介していきます。 インデックス 検索 回答生成 インデックス チャンク化戦略 チャンク手法はRAGに取り込む大きな文書の塊を小さく分割する手法です。分割されたチャンクごとにインデックスが作成されるため、チャンクは検索の品質に大きな影響を与えます。ここの内容は 「 Chunking Strategies for LLM Applications 」[ 8 ]の内容を参考に説明します。 固定サイズチャンク 最も単純でNaive RAGで用いる方法が固定のチャンクサイズで機械的に分割する手法です。固定サイズのチャンクではチャンクサイズにはトークン数が用いられます。トークンとはTokenizerによって分割される単位です。通常は単語数や文字数ではないです。どのようにトークン分割されるかは Tokenizer – OpenAI Platform などを使って試すことができます。また、単純に固定のチャンクサイズで切ってしまうと文章の前後の繋がりの情報が失われてしまうため、隣り合ったチャンクで同じトークンを重複してもつ「オーバーラップ」を設ける必要があります。 この方法は自然言語処理(NLP)を必要としないため、計算量が小さいというメリットがありますが、全く文章の意味が考慮されないため、チャンクの質は悪くなりがちというデメリットがあります。 コンテンツ認識チャンク 固定サイズのチャンクは機械的で意味が考慮されないという点で、チャンクの質が悪いという問題点がありました。それに対し、コンテンツをきちんと認識した上で、より有効なチャンク化しようという方法もあります。その方法をいくつか紹介していきます。 (表1: 5つのコンテンツ認識チャンク。下の行ほど高度に意味を認識して分割するチャンク化方式。) チャンク方法 説明 文の分割 (Sentence splitting) 区切り文字などを利用して文に分割してチャンクとして扱う非常に簡単な方法です。実装は単に「。」などの句点で分けるコードを自作する方法 (Naive splitting) があります。だた、そのような方法では例外的なパターンなどでは分離できないので、NLTKやspaCyなどのPythonのライブラリによって文を分割という方法も用いられます。ライブラリを用いることでより適切に文を分離することができます。 再帰的チャンク化 (Recursive Chunking) 大きな文章をいくつかの文書に分割し、さらにその文書を分割するという処理を繰り返し、階層的かつ反復的に小さいチャンクに分割する方法です。再帰は指定されたチャンクサイズになるまで繰り返されます。分割には複数の区切り文字を使用します。再帰が繰り返される中で使用される区切り文字が変わり、目的のチャンクサイズになるように処理されます。実装はLangChainのRecursiveCharacterTextSplitterを用いる方法があります。 ドキュメント固有のチャンク化 (Specialized chunking) MarkdownやLaTexなどといった文書は構造化されていて、見出し、リスト、コードブロックなどの情報を用いることで、より正確にコンテキストを理解したチャンクを得ることができます。実装はLangChainのMarkdownTextSplitterやLatexTextSplitterを用いる方法があります。その他のドキュメントでも形式が明確なものであれば正規表現等を用いて、Splitterを自作することも可能でしょう。 意味的チャンク化 (Semantic Chunking) Greg Kamradtによって導入された手法です。その名の通りで文章の意味によってチャンクに分解します。文章を文に分割し、文の意味が近いものを同じトピック、遠いものがあれば別トピックに切り替わったと判断して、チャンクに分解します。上記の文章の表面的な形式で分割していたのに対し、より踏み込んだチャンク化です。実装はLangChainのSemanticChunkerを用いる方法があります。 エージェントによるチャンク化 (Agentic Splitting) さらに先進的な手法として実験的ではありますが、AIエージェントによる分割も提案されています[ 10 ]。 ベクトル化 分割されたチャンクは埋め込みモデル (Embedding Model) によってベクトル化されます。モデルの選定やチューニングについてご紹介します。 埋め込みモデルの選定 ベクトル化では意味の近いベクトルは類似度が近く、意味が遠いものは類似度が遠くなる分類性能の高いベクトル化されることが望ましいです。そのため、埋め込みモデルの選定はインデックスの品質に影響します。多くの場合では、OpenAI社の ada v2などのモデルを利用することが多いですが、 モデルの選択はリーダーボードを確認し、指標を比較して独自にモデルを選ぶことができます。リーダーボードでは多くのモデルに対しベンチマークを実施してその結果が公開されています。例えば、有名なリーダーボードとしては MTEB Leaderboard や Nejumi Leaderboard などがあります。特にNejumi Leaderboardは日本語での性能を評価したもので、日本語を扱う際のモデル選定では参考になります。 埋め込みモデルのファインチューニング 医療や法律など専門用語などは一般的な語用とは異なる場合があり、意図したベクトル化がされないことがあります。そのような場合には埋め込みモデルのファインチューニングが有効なケースがあります。 LLamaIndex などではファインチューニングが可能です。 構造インデックス インデックスの構造によっても検索の精度が変わります。ここではいくつかのインデックスの方法について「 Advanced rag techniques: an illustrated overview 」[ 9 ]を中心にご紹介します。 ベクトルストアインデックス (Vector store index) 最も単純に質問と回答のベクトルの類似度の近いものを検索する方法です。Naive RAGで使われる最初のアイデアです。ベクトル類似度と近傍探索のアルゴリズムは複数あります。 まず、ベクトルの類似度の計算についてElasticSearchでよく次の演算が使われています[ 11 ]。これらはElasticSearch固有の概念ではなく、数学や物理、情報工学で広く使われています。 マンハッタン距離 (L1距離) ユークリッド距離 (L2距離) コサイン類似度 ドット積 (内積、点乗積) 意味ベクトルは方向によって意味が表される性質があるので、RAGの文脈ではコサイン類似度やドット積といった「点」ではなく「ベクトル」として扱われる演算が相性がよく比較的精度がよいといえます。また、コサイン類似度はベクトルの角度のみが考慮されますが、ドット積はベクトルの長さも考慮されるのでより多くの情報を持ちます。しかし、情報が多ければよいというわけでもなく、長さがノイズになる場合もあるため比較して検討が必要となります。 次に近傍探索についてみていきます。近傍探索とは周辺にあるベクトルを探すためのアルゴリズムです。その方法には主に次の2つが存在します。 k最近傍法 ( k-Nearest Neighbor: kNN ) 近似最近傍法 (Approximate Nearest Neighbor: ANN) kNNはすべてのデータを比較して近いベクトルを見つけ出すアルゴリズムで、正確にベクトルを見つけ出すことができます。しかし、単純に全てのベクトル同士の距離を比較してしまうと、すべてのデータを探索することになり検索に非常に大きな時間がかかってしまうことになります。ちょうどリレーショナルデータベースでインデックスのないカラムに線形検索するようなものです。そのため、データベースとしては小規模〜中規模程度のデータベース向けで、大規模の場合にはRAGの応答性を犠牲にしても正確性を求める場合に利用します。 ANNは多少正確さを犠牲にして素早く近傍のベクトルを見つけるためのアルゴリズム全体の総称です。現在はその主流のアルゴリズムとしてHierarchical Navigable Small World (HNSW)が使われています。HNSWのアルゴリズムを簡単に説明します。図6のようにベクトルの近さをグラフとして表現し、グラフの詳細度で複数のグラフを構築します。この際に各グラフに対応するノードを設けます。このグラフを粗い方からたどり、クエリのベクトルに近いノードを探します。次にそのノードに対応する1段詳細度の高いグラフに移動し、もう一度探索します。最後は実際のベクトルと対応したグラフに移動し、最も近い(可能性が高い)ノードを発見します。イメージ的には札幌・仙台・東京・名古屋・大阪・福岡くらいしか書いていない広域の地図から場所を探して、次に関東周辺の地図から神奈川あたりが近そうだと分かり、神奈川県の地図から横浜みなとみらいを探し当てる感じといったところかと思います。 (図6: Hierarchical Navigable Small Worlds (HNSW) [ 12 ]より引用) HNSWでもかなり正確な結果が得られることが一般に知られています。そのため、アルゴリズム選択にあたってはANN近傍探索はまずANNから検討を始め、どうしてもそれでは検索精度が悪い場合にはkNNを選択するという進め方がよいでしょう。 多くのデータベースでは計算方法や近傍探索アルゴリズムを変更できるパラメータが用意されています。サポートされている計算方法・近傍探索はデータベースにより異なりますので、ドキュメントをご確認ください。 チャンクのメタデータ チャンクにページ番号やファイル名、カテゴリ、タイムスタンプなどのメタデータを付与する方法があります。チャンク生成時にデータベースにこれらのメタ情報を一緒に保存するように実装します。このメタデータで検索範囲の絞り込みをしたり、タイムスタンプでの絞り込みで古い情報を排除するなどして検索の精度を高めることができます[ 1 ]。 階層的インデックス (Hierarchical indices) (図7: Advanced rag techniques: an illustrated overview [ 9 ]より引用) 大規模なドキュメントを検索する際に細切れの小さなチャンクでは適切にコンテキストを保持できないという欠点がありました。そこで階層的インデックスのアプローチでは図7のように要約のチャンクに対して検索を実施し、さらに要約に関連づけられたより小さなチャンクを検索するという方法をとります。階層は要約の単位を変えることで複数に増やすことができます。これにより関連性の高いドキュメントを発見したり、要約の階層のドキュメントを回答に使うことができるなどのメリットがあります[ 13 ]。 実装についてはNirDiamant氏により参考となる Hierarchical Indices in Document Retrieval が公開されています。 想定質問(Hypothetical Questions) Naive RAGではユーザからのクエリをベクトル化することで検索を行いますが、質問のベクトルから内容のベクトルを検索するという動きになり、それらは必ずしもベクトルが類似するとは限りません。そこで、質問のベクトルから質問を検索したり、回答のベクトルから回答を検索するといった方法が提案されました。 想定質問(またはReverse HyDE)は質問のベクトルから質問を検索する方法で、インデックスの作成時点で内容に対する想定質問をLLMに生成させ、その質問をベクトル化したものをデータベースに格納します。例えば、「富士山の標高は3,776mです」というチャンクに対して、その文章そのもののベクトルでなく、LLMで質問「富士山の標高は?」という想定質問を生成します。この文章に対するベクトルをベクトルストアに保管します。するとユーザが質問した「富士山の高さはどのくらい?」との類似度が高くなる可能性が高く精度が高くなると予想できます。 Reverse HyDEと呼ばれている理由はHyDE(後述)が質問に対する「想定回答」で検索するというアプローチをとっており、その逆のアプローチであることからそのように呼ばれています。 周辺コンテキスト拡充 (Context enrichment) インデックス作成時にチャンクに周辺の文章を付与してLLMに推論させる方法です。LLMは検索したチャンクだけでなく周辺の文章を用いることができるので、文脈をよりよく理解して回答を生成することが期待できます。センテンスウィンドウ検索と自動マージ検索の2つの方法があります。 センテンスウィンドウ検索 (Sentence Window Retrieval)は単純に検索されたチャンクの周辺の文章をLLMに送る方法です。下図の緑の部分が検索で引っかかったチャンクであり、拡大して黒の文章を付与します。 (図8: Advanced rag techniques: an illustrated overview [ 9 ]より引用) 自動マージ検索 (Auto-merging Retriever (別名 Parent Document Retriever))はチャンクを親と子に分けて検索する方法です。まずは通常通り小さいチャンク(これを「子チャンク」という)に対して検索を行い、ヒットした子チャンクの属する親のチャンクを取得し、より大きな親チャンクの方をLLMに送る手法です。 (図9: 自動マージ検索のイメージ。 Advanced rag techniques: an illustrated overview [ 9 ]より引用) 具体的な実装については例えばLlamaIndexを使った方法で Recursive Retriever + Node References を参照ください。 ナレッジグラフ (Knowledge Graph) これまでのところはクエリに対していかに近い文章を取得したり、いかに周辺の文章も含んでコンテキストを保持するかがメインのテクニックでした。しかし、これだけでは不十分でクエリとは直接関連しなくとも、検索された文書とは関連して回答したい内容については取得できず、十分な回答が生成されなかったり、ハルシネーションを起こすという欠点がありました。 ナレッジグラフはそのような欠点を解決するために知識と知識を関連付けたグラフ型のデータベースを構築し、ベクトルストアデータベースよりも関連した情報を包括的に検索できるように考えられています。 ナレッジグラフの動作について簡単に説明します。ナレッジグラフとは図10のようなノード(丸)とエッジ(線)からなっており、ノードで対象となるオブジェクトを表し、エッジでそれらの関係性を表すグラフとなっています。RAGではノードに対してチャンクを割り当て、チャンク間の関連をエッジで表します。これによりベクトルストアインデックスで表現できなかった関連性を表現することができます。 (図10: LangChainのLLMGraphTransformerで構築したナレッジグラフをNeo4jで表示した例。 Enhancing RAG-based application accuracy by constructing and leveraging knowledge graphs [ 14 ]より引用) 検索は多くの場合ベクトルストアインデックスと併用で実装されるケースが多いです。手順としてはまず質問に対してベクトルストアからチャンクを取得し、そのチャンクに関連する情報をナレッジグラフから検索するという方法です。 (図11: ベクトルストアインデックスとナレッジグラフの併用。 Enhancing RAG-based application accuracy by constructing and leveraging knowledge graphs [ 14 ]より引用) 実装についてはLangChainのLLMGraphTransformerを用いる他に、現在注目されているのが、Microsoft Researchにより提案されている GraphRAG です。Graph RAGは2段階のナレッジグラフを用いて、部分的な知識の要約を1段階目で生成し、2段階目でその要約全体を用いて質問するため、従来手法より回答精度が高いとされています[ 15 ]。 検索 複合検索とハイブリット検索 (Fusion retrieval or hybrid search) 複数の検索手法を用いることで検索精度を向上させようとする方法は多く用いられています。基本的にはベクトル検索がベースとしてもちいられ、ベクトル検索の弱点を補う形で用いられることが多いです。特に代表的なものをご紹介します。 キーワード検索 ハイブリッド検索では多くの場合、ベクトル検索とキーワード検索の両方を用いることをいいます。キーワード検索とは単語や語句から文書を検索することを言います。RAGでは質問に含まれる単語や語句を自然言語処理によって抜き出してきて、一致したキーワードを含む文書を見つけ出します。 これはベクトル検索が意味として近い文章を見つけ出すのが得意なものの、同じキーワードが含まれていたとしてもベクトルの類似度が低ければ検索にヒットしないという弱点を克服するために用いられる方法です。 セマンティック検索 セマンティック検索は語句や単語の「意味」を基に検索をする検索方法です。例えば、「携帯」という単語から「ケータイ」「電話」や「iPhone」など似た意味の単語もヒットします。 これもキーワード検索との併用の効果と同じく、類似度が低くても近い意味合いの単語が使われているチャンクを取得することができます。 タグ検索 前述の チャンクのメタデータ で紹介した通り、あらかじめチャンクにメタデータを付与しておくことで、データを絞り込み検索精度を向上することができます。 グラフ検索 前述の ナレッジグラフ で紹介したとおり、ナレッジグラフを用いることで関連する文書より包括的に取得できるようになり、検索精度を向上することができます。 クエリ ユーザから提示された質問は必ずしも検索に対して最適とは限らず、クエリに対し何らかの工夫を施した方が検索精度が上がるといわれています。 クエリ拡張 単一のクエリだけを用いるのではなく、複数のクエリを使ったり、1つのクエリをより簡単なクエリに分割する検索の精度を上げる手法です。クエリ拡張には次の種類があります。 マルチクエリ (Multi-Query) サブクエリ (Sub-Query) マルチクエリ (Multi-Query)はユーザからのクエリを別の観点を取り入れて複数のクエリを生成する手法です。これにより単一のクエリだけでは取得できなかった結果を取得することができます。ユーザからのクエリの微妙なニュアンスの違いでベクトル検索にヒットしないような内容も取得できるといった効果が期待できます。実装では MultiQueryRetriever を使う方法があります。実際にMultiQueryRetrieverを使ってクエリを生成すると次のようになります。 元のクエリ: What are the approaches to Task Decomposition? (和訳: タスク分解へのアプローチは何ですか?) 質問1: How can Task Decomposition be achieved through different methods? (和訳: さまざまな方法でタスク分解を実現するにはどうすればよいでしょうか?) 質問2: What strategies are commonly used for Task Decomposition? (翻訳: タスク分解に一般的に使用される戦略は何ですか?) 質問3: What are the various ways to break down tasks in Task Decomposition? (和訳: タスク分解でタスクを細分化するさまざまな方法は何ですか? ) ( MultiQueryRetriever より引用・改変) このようにさまざまな聞き方の質問に変換されていることがわかります。これにより多くの情報を得られる可能性が高まります。 サブクエリ (Sub-Query)はユーザからのクエリを複数のクエリにより簡単なクエリに分割して検索する手法です。ユーザからの質問は複数の質問が関連したものであることがあり、そのようなケースでは一度のクエリでは解決できず、単純な質問に分割して検索することで的確な情報を取得できる効果が期待できます。実装はプロンプトエンジニアリングを使用して、質問を分割するようにLLMに指示します。実装例は Part 7: Decomposition – Rag From Scratch: Query Transformations に示されていますので参考としてください。実際にクエリを生成すると次のようになります。 元のクエリ: how to use multi-modal models in a chain and turn chain into a rest api (和訳: チェーン内でマルチモーダル モデルを使用し、チェーンを REST API に変換する方法) 質問1: How to use multi-modal models in a chain?  (和訳: チェーン内でマルチモーダル モデルを使用するにはどうすればよいでしょうか?) 質問2: How to turn a chain into a REST API? (和訳: チェーンを REST API に変換するにはどうすればいいですか?) ( Decomposition より引用・改変) このように複数のトピックが含まれているような質問が分割されていることがわかります。 クエリ変換 クエリ変換は元のクエリを変換することで、検索の精度を上げる手法です。よくある方法としては次があります。 HyDE Step Back HyDEは回答のベクトルから回答を検索する方法で、質問に対する回答を検索なしでLLMに作成させ、その質問をベクトル化したものでデータベースから検索します。検索なしで回答させるという点について不思議に思われるかもしれませんが、これは検索しなくともニュアンスの似た回答が得られるはずだという仮説に基づきます。例えば、元のクエリが「日本で一番高い山は何ですか?」であった場合に検索を用いずにLLMから「日本で一番高い山は高尾山です」という仮の回答を得ます。これは当然ハルシネーションですが、チャンクに「日本で一番高い山は富士山です。」という文章が含まれていれば、仮の回答とチャンクのベクトルは近いはずです。実際にBM25やContrieverと比較して精度が高いことが報告されています[ 16 ]。実装については Part 9: HyDE – Rag From Scratch: Query Transformations に示されていますので参考としてください。 Step Backは元のクエリをより抽象的な質問にLLMで変換させ、元のクエリと抽象的な質問の両方を使って検索を実施する手法です。これにより主に複数の情報源から結果を導き出すマルチホップ推論が必要な場面での精度が向上されたと報告されています[ 17 ]。実装については Part 8: Step Back – Rag From Scratch: Query Transformations に示されていますので参考としてください。 ルーティング 検索は1回だけではなく、複数回実施するのも有効な手段です。 (図12: 反復検索と再帰検索と適応検索のフローチャート。 Retrieval-Augmented Generation for Large Language Models: A Survey  [ 1 ]より引用。) 単一検索 Naive RAGで使われる単純な検索方法で、一度の検索で得られた結果を用いて回答を生成する方法です。シンプルな手法で応答性も高いものの、一度の検索では適切な回答を得られないことが多いという課題があります。 反復検索 反復検索は以前の検索結果を用いて、関連する文書を繰り返し取得する方法です。これにより周辺のコンテキストを補うことが期待できます。ただし、ノイズとなる情報が増えてしまうこともあります。 再帰検索 再帰検索は以前の検索結果を用いて、Chain-of-Thought (CoT) を用いてクエリを改善し、繰り返し検索をする方法です。この方法では検索結果のフィードバックを受けて、徐々に関連性の高い文書を探し当てることができます。 適応検索(AIエージェント) 適応検索とはLLMが次の検索をどのようにするかの次のアクション自体を考えさせるという方法です。最近特に注目を集めているのは適応検索の領域です。Flare、Self-RAG、AutoRAG、Toolformer、 Graph-Toolformerなどのツールが提案されていますが、ここでは より注目度の高いAIエージェントを用いたマルチドキュメントエージェント型の手法について簡単に説明します。   (図13: マルチエージェント型のアーキテクチャ例。 Advanced rag techniques: an illustrated overview [9]より引用) 図13のようにエージェントは担当するインデックスごとのドキュメントエージェントが配置され、ドキュメントエージェントを総括するトップエージェントの構造からなります。ドキュメントエージェントはトップエージェントに指示に合わせて、ベクトルストアインデックスと要約のインデックスなどデータベースへの問い合わせを自立して判断し実施します。トップエージェントはクエリをどのように分割して、各ドキュメントエージェントに引き渡したり、回答を統合したりについて判断します。これにより異なるドキュメントからの情報を統合した高度で洗練された回答得ることが可能になります。しかし、この手法はエージェント間の多段で複雑なクエリと回答の段階を踏むため、応答に時間がかかるというデメリットもあります。実装はLlamaIndexの Multi-Document Agents を用いることができます。 回答生成 再順位付けとフィルタリング 検索では必ずしも関連性の高い文書だけがヒットするわけではなく、関連性が薄くノイズとなるものも混在します。検索で得られた結果を改めて関連性の高い順番に並べ替えたり、フィルタリングするという方法がよくとられます。LlamaIndexの調査では再順位付けを実施することで精度が高くなるといわれています[ 18 ]。 LLMのファインチューニング RAGとファインチューニングの有効 で述べた通り、単純な知識の検索ではRAGが優れるものの、RAGとファインチューニングは両方を用いることができます。GPT-3.5-Turboをファインチューニングし、RAGAsでの評価を行った結果、回答の関連性や忠実性が向上したと報告されています[ 19 ]。 レスポンスシンセサイザー 最終的な応答生成は複数のチャンクを用いて回答を生成することになります。要約だけを示すような回答に調整したり、詳細まで説明を加えたり、精度を少々犠牲にしてLLMのトークン消費を節約するなどのケースが考えられます。LlamaIndexでは Response Synthesizer という機能を提供しており、その中で回答生成方法のオプションをいくつか用意されています。 まとめ RAGのパラダイムはNaive RAG、Advanced RAG、Modular RAGに進化している。 Advanced RAGではインデックス化、検索、回答生成のそれぞれに改善が提案されている。 Modular RAGでは多くの手法をモジュール化し、組み合わせパターンを柔軟に作り出す。 最後までお読みいただきありがとうございます。お気付きの点などありましたら、ぜひコメントください。 【宣伝】生成AI ネクストテックソリューションのご紹介 弊社サイオステクノロジーでは生成AIを用いたトレーニング、コンサルティング、アプリケーション開発のソリューションを提供しています。ご興味のある方はぜひお問い合わせください! https://nextech-solutions.sios.jp/genai/ 参考文献 Yunfan Gao, Yun Xiong, Xinyu Gao, Kangxiang Jia, Jinliu Pan, Yuxi Bi, Yi Dai, Jiawei Sun, Meng Wang, Haofen Wang, Retrieval-Augmented Generation for Large Language Models: A Survey , 2024. Yunfan Gao, Yun Xiong, Meng Wang, Haofen Wang, Modular RAG: Transforming RAG Systems into LEGO-like Reconfigurable Frameworks , 2024. Gilad Rubin, Implementing “Modular RAG” with Haystack and Hypster , 2024. Dongkyu Kim, Byoungwook Kim, Donggeon Han, Matouš Eibich, AutoRAG: Automated Framework for optimization of Retrieval Augmented Generation Pipeline , 2024. OpenAI, Fine-tuning Fine-tune models for better results and efficiency . Oded Ovadia, Menachem Brief, Moshik Mishaeli, Oren Elisha, Fine-Tuning or Retrieval? Comparing Knowledge Injection in LLMs , 2024. 森下皓文, 山口 篤季, 森尾 学 , 今一 修 , 十河 泰弘, 日立製作所 研究開発グループ, シェフィールド大学, 帰納的に多様な巨大論理推論コーパスによりLLMの汎用論理推論能力を向上させる , 2024. Roie Schwaber-Cohen, Chunking Strategies for LLM Applications , 2023. IVAN ILIN , Advanced rag techniques: an illustrated overview ,  2023. Greg Kamradt, 5 Levels Of Text Splitting , 2024. Valentin Crettaz, Vector similarity techniques and scoring , 2024. Pinecone, Hierarchical Navigable Small Worlds (HNSW) . Nirdiamant, Hierarchical Indices: Enhancing RAG Systems , 2024. LangChain, Enhancing RAG-based application accuracy by constructing and leveraging knowledge graphs , 2024. Darren Edge, Ha Trinh, Newman Cheng, Joshua Bradley, Alex Chao, Apurva Mody, Steven Truitt, Jonathan Larson, From Local to Global: A Graph RAG Approach to Query-Focused Summarization , 2024. Luyu Gao, Xueguang Ma, Jimmy Lin, Jamie Callan, Precise Zero-Shot Dense Retrieval without Relevance Labels , 2022. Huaixiu Steven Zheng, Swaroop Mishra, Xinyun Chen, Heng-Tze Cheng, Ed H. Chi, Quoc V Le, Denny Zhou, Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models , 2024. Ravi Theja, Boosting RAG: Picking the Best Embedding & Reranker models , 2023. LlamaIndex, Fine Tuning GPT-3.5-Turbo . ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post RAGはどのように進化しているのか?RAGのパラダイムと改善手法を体系的にご紹介! first appeared on SIOS Tech. Lab .
アバター
はじめに CPチームの木下です。 今回はKubernetes(K8s)の運用は複雑で、クラスタ管理に多くの知識と労力が必要となりますが、そのKubernetes管理を大幅に簡素化するOSSのRancherについて記載していきます。 Rancherはマルチクラウドやハイブリッドクラウド環境における効率的な運用を支援するプラットフォームです。本記事では、Rancherの特徴やメリットについて分かりやすく解説します。 Rancherの主な特徴について   1. マルチクラスタ管理 Rancherは、複数のKubernetesクラスタを一元管理できるOSSです。オンプレミスのKubernetesから、Amazon EKS、Azure AKS、Google GKEといったクラウドのマネージドKubernetesまで、さまざまな環境のクラスタを一つの管理画面で操作できます。 メリット: 運用者は、分散したクラスタを一元的に監視・管理できるため、オペレーションの効率が向上し、複数のKubernetes環境を持つ運用者や企業に最適です。 ユースケース: マルチクラウド戦略を採用している企業や、オンプレとクラウドを組み合わせたハイブリッド環境の運用を行う企業・プロジェクトに適しています。 2. 直感的なユーザーインターフェース Rancherのダッシュボードは、Kubernetesを扱ったことがない人でも分かりやすく設計されています。ワンクリックでクラスタの作成や管理、リソースのデプロイが可能です。 ビジュアル化された管理画面: クラスタの状態、ノードやポッドのリソース使用量、ログなどを簡単に可視化できます。 初心者でも使いやすい: GUIベースで提供されるRancherの操作画面は、Kubernetesの専門知識が少ない人でも利用しやすく、学習コストを大幅に削減できます。 3. RBAC(Role-Based Access Control)機能 Rancherは、KubernetesのRBACをさらに強化し、ユーザーごとに細かい権限設定が可能です。開発者や運用者に応じたアクセス権限の付与や、部署ごとのリソース制限など、きめ細やかなセキュリティ管理が行えます。 メリット: セキュリティポリシーに沿ったアクセス管理が可能で、コンプライアンス要件にも対応できます。 ユースケース: 大規模な開発チームや、セキュリティが厳しい業界でのKubernetes運用に最適です。 4. CICDと統合しやすい Rancherは、CI/CDツール(例:Jenkins、GitLab CI、ArgoCDなど)との統合が容易です。デプロイメントの自動化や、アプリケーションのライフサイクル管理を効率化できます。 開発者にとってのメリット: 新しいコードのデプロイがスムーズになり、継続的なデリバリーが実現します。 ユースケース: DevOps環境の整備を目指す企業や、継続的なデプロイメントが求められるプロジェクトに適しています。 5. 高可用性とスケーラビリティ Rancherは、高可用性構成が可能で、障害が発生しても運用を続けられる設計です。Rancher自体を複数のノードで構成することで、障害に強く、スケールアウトに対応します。 メリット: クラスタのダウンタイムを最小限に抑えつつ、リソースのスケールを容易に実現できます。 ユースケース: ミッションクリティカルなアプリケーションを運用する企業にとって、信頼性の高いプラットフォームとして役立ちます。 6. プラグインとカスタマイズ性 Rancherは、さまざまなプラグインやカスタム設定をサポートし、個々のニーズに合わせた柔軟な運用が可能です。HelmチャートやYAMLファイルを用いたカスタマイズも簡単に行えます。 メリット: Kubernetesエコシステムとの互換性が高く、ユーザーのニーズに合わせて拡張可能です。 ユースケース: 特定のワークロードやビジネス要件に応じたカスタマイズが必要な場合に適しています。   Rancher導入のメリット オペレーションの効率化: マルチクラウドやハイブリッドクラウド環境での一元管理により、オペレーションの手間を大幅に軽減。 セキュリティの向上: RBAC機能やセキュリティポリシーの統合で、安全なクラスタ運用が可能。 コスト削減: 管理工数の削減と最適化されたリソース管理により、インフラコストを効率的に削減。   まとめ Rancherは、Kubernetesクラスタを簡単に管理できるだけでなく、マルチクラウド対応、直感的なUI、強化されたセキュリティ機能など、商用環境でのKubernetes運用を最適化する数々のメリットを提供します。Kubernetesの複雑さに悩む運用者にとって、Rancherは心強いツールとなるはずです。 また、OSSのRancherを商用環境で導入するための、エンタープライズサポートなどもSUSE社などから提供されています。OSS単体での導入は難しい場合などでもこれらのサポートを基に検討してみてはいかがでしょうか。 今後も数回に渡りRancherに関する技術ブログを執筆予定です。 今回は初回のため概要レベルからの特徴を説明しましたが、次回以降は実際の構築時のポイントやマルチクラウドでの利用ポイントをまとめていきますので是非見ていただければ幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Rancher入門:マルチクラウド対応のKubernetes管理ツールとは? first appeared on SIOS Tech. Lab .
アバター
はじめに こんにちはサイオステクノロジーの小野です。 前回 はOpenShiftでGPUを利用するための設定方法について解説しました。今回はいよいよOpenShift AIを導入してJupyterNotebookを起動するところまでを解説します。 OpenShift AIの4つの主な機能 OpenShift AIのトップ画面は以下のようになります。 OpenShift AIのトップ画面 OpenShift AIには大きく4つの機能があります。 Data Science Projects データサイエンスのプロジェクトを作成することができます。プロジェクト内ではワークベンチの作成、パイプラインの作成(MLOps)、モデルのデプロイ、ストレージの作成、データ接続の設定、権限設定が行えます。 Data Science Pipelines パイプラインの管理、設定を行います。ここでMLOpsにおけるデータの収集からモデルの評価までを自動化できます。 Distributed Workload Metrics 分散ワークロードの管理、設定を行います。分散ワークロードとはモデルの学習や推論を行う際に、複数のマシンやクラスターに分散して処理を行うことです。これによって大規模なモデルでも高速な処理が可能になります。 Model Serving モデルのサービングの管理、設定を行います。推論用にモデルをデプロイ、​管理、​公開し、​未知のデータに対して推論サービスとして使用できるようにします。 OpenShift AI構築方法 前提条件 バージョン OpenShift:4.17 OpenShift AI:2.13.1 構築に必要なもの 1 リソース ノード数:2つ CPU:8CPU RAM:32GiB 今回はAWSのインスタンスタイプm6a.2xlargeを2つ使用 サブスクリプション Red Hat OpenShift AI Self-Managed のサブスクリプション ※検証ではRed Hat Developer Subscriptionを利用可能 機能に応じて利用するもの GPUノード(AIの学習や推論に使用) IDP設定(セキュリティ管理に使用) S3互換のオブジェクトストレージ(モデルの保存やパイプラインの作成に使用) モデルサービング用のOperator Red Hat OpenShift Service Mesh Red Hat OpenShift Serverless 導入手順 OpenShift AI オペレータインストール 最初にOperator > OperatorHubで「OpenShift AI」と検索します。 OperatorHubで「OpenShift AI」と検索 「Red Hat OpenShift AI」を選択してインストールを押します。 「Red Hat OpenShift AI」のインストールを押す インストール時の設定はデフォルトと同じく以下のように設定します。設定したらインストールを押します。 更新チャネル stable バージョン 2.13.1 インストールモード クラスターのすべてのnamespace インストール済みのnamespace Operator推奨のnamespace:redhat-ods-operator 更新の承認 自動 インストールの設定を行う インストール済みのOperatorでRed Hat OpenShift AIのステータスがSuccessedになっていたらインストール完了です。 Red Hat OpenShift AIのインストール確認 CR(DataScienceCluster)設定 OpenShift AIオペレータの詳細画面に移動し、「DataScienceCluster」のインスタンスを作成します。 DataScienceClusterの作成 公式ドキュメント 2 に従い、必要なコンポーネントをManagedに設定します。 コンポーネントは以下の10種類あります。 codeflare 分散ワークロードに利用されます。rayがManagedになっている必要があります。 kserve 大規模モデルのサービングに利用されます。OpenShift Service MeshとOpenShift Serverlessをインストールしている必要があります。 trustyai モデルのモニタリングを行います。OpenShift AI 2.7以降は削除されました。 ray 分散ワークロードに利用されます。 kueue 分散ワークロードに利用されます。 workbenches ワークベンチの作成に利用されます。 dashboard ダッシュボードを使用可能にするために利用されます。 modelmeshserving 中小規模モデルのサービングに利用されます。 datasciencepipelines MLOpsのパイプラインを作成するために利用されます。 trainingoperator 分散ワークロードに利用されます。 今回はYAMLビューを選択し、以下のように設定しました。 spec: components: codeflare: managementState: Managed kserve: serving: ingressGateway: certificate: type: OpenshiftDefaultIngress managementState: Managed name: knative-serving managementState: Removed trustyai: managementState: Removed ray: managementState: Managed kueue: managementState: Managed workbenches: managementState: Managed dashboard: managementState: Managed modelmeshserving: managementState: Managed datasciencepipelines: managementState: Managed trainingoperator: managementState: Removed DataScienceClusterの設定 Red Hat OpenShift AI の詳細画面のData Science Clusterタブに移動して、作成したインスタンスのステータスが「Phase:Ready」になっていれば作成完了です。 DataScienceCluster作成確認 正常性確認 OpenShift AIの正常性確認としてWebログイン、プロジェクトを作成、ワークベンチ作成、JupyterNotebookを起動するまでを行います。 webログイン OpenShiftコンソール画面の右上の格子状のアイコンを選択し、Red Hat OpenShift AIを開きます。 OpenShift AIの開き方 ログインを求められるのでKubeadmin or IDP設定したuserでログインします。 Data Science Projects作成 OpenShift AIコンソール画面の左のData Science Projectsを開きます。 右上のCreate data science projectを押します。 プロジェクト作成 プロジェクトの名前を記入してCreateを押せばプロジェクトを作成できます。 プロジェクトの名前設定 プロジェクトの詳細画面 ワークベンチ作成 作成したプロジェクトの画面から、Workbenchesタブに移動します。 Create workbenchを選択します。 ワークベンチの作成 以下の項目を設定して、Create Workbenchを選択します。 Name ワークベンチ名 Image selection ノートブックで扱いたいライブラリを選択 3 Container size ワークベンチのサイズ Accelerator GPUを用いる場合:NVIDIA GPU Cluster storage 新しく作るか既存のものを選択 ワークベンチの設定➀ ワークベンチの設定② 作成したワークベンチのStatusがRunning になって、Openのリンクが押せるようになったらワークベンチ作成完了です。 ワークベンチの作成を確認 JupyterNotebook起動 作成したワークベンチのOpenのリンクを開きます。 ログインを求められるのでログインします。 Authorize Accessという画面が出てくるので、Allow selected permissionsを押します。 JupyterNotebookにログインするときの認証 JupyterLabの画面が表示されればJupyterNotebookの起動が完了です。 JupyterLabの画面 最後に 以上の手順によりJupyterNotebookを起動することができました。これによりOpenShift上で機械学習を行うことができます。しかしながら、ここまではMLOpsの前半にすぎません。次回からはMLOpsで重要なパイプラインの設定やサービングの設定について解説する予定なので楽しみにしてください。 参考 OpenShift AIの要件: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.13/html/installing_and_uninstalling_openshift_ai_self-managed/installing-and-deploying-openshift-ai_install#installing-and-deploying-openshift-ai_install コンポーネント設定: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.13/html/installing_and_uninstalling_openshift_ai_self-managed/installing-and-managing-openshift-ai-components_component-install ノートブックのライブラリ: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.13/html/working_on_data_science_projects/using-project-workbenches_projects#creating-a-workbench-select-ide_projects OpenShiftのGPU設定の方法について: https://tech-lab.sios.jp/archives/44040 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift AI を導入してみた first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 今回はAzureのネットワーク周りの話です。 Azure Bastionを利用して、プライベートIPを介したセキュアなVM接続を実現する方法をご紹介します。 はじめに この記事に至った背景ですが、こちらをご参照ください。 【Azure】閉域化されたリソースに対して自分のPCからアクセスする方法を紹介 こちらの記事で、「閉域化されたリソースに対して自PCからVMを経由してアクセスする方法」をご紹介しました。 しかし、経由するためのVMがPublicIPを持っているためどこからでもアクセスできてしまい、セキュリティ面での不安が残ります。 そこで今回はこの不安を解消するため、プライベートIPを経由して接続できる Azure Bastion のご紹介をしたいと思います。 Azure Bastionとは Azure Bastionとは、Azureが提供するフルマネージドなPaaSであり、プライベートIPを介してVMに接続することを可能とするためのサービスです。 また後述しますが、このAzure Bastionに対する認証/認可としてはRBACの仕組みを利用することが可能です。 そのため結果として、RBACで設定されたユーザーのみが、Bastionを経由してVMにアクセスることが出来るようになります。 価格 Bastionを利用する際の価格に関しては、SKUや利用料に依存します。 以前はBasic以上のSKUしか存在しなく、最低金額でも月額2万円近い金額を支払う必要がありました。 ただ、前回の記事の中で取り上げた KeyVaultのシークレット情報書き換えたい CosmosDBの中身をデータエクスプローラーで見たい といったライトなユースケースだけであれば、それに対して月2万払うのは少しためらってしまいます。 しかし、最近 Developer SKU という新たな価格帯が登場しました!! 基本料金はなんと無料! 上記したような、ちょっとしたユースケースであれば無料で使うことができます。 まさに今回のようなユースケースに適したSKUです。 Basic以上のプラン比べて色々機能の制限はありますが、非常にライトに使えるようになっているため使い勝手は良いです。 今回影響する制限事項に関しては、以下のような点があります。 リージョン 接続できるVMの種別 Bastionへの接続方法 影響範囲に関しては、この後の記事の中でも言及していきます。 使ってみる では実際に、Bastionを使ってプライベートIPを介したVMの接続を試み、そこから閉域化されたKeyVaultにアクセスしてみたいと思います。 リソース作成 まずはリソースの事前準備です。 KeyVault 今回も検証用にKeyVaultを使っていきます。 前回の記事と同様になるため省略しますが、Azure KeyVaultを作成し RBACの設定やサンプルのシークレットを追加しておいてもらえるとよいかと思います。 Bastion&VNet 次に、早速Bastionを作っていきます。 Azure PortalからBastionのリソースを選択し、作成していきます。 ここでDeveloper SKUの制限1つ目、リージョンです。 Developer SKUでは現在以下のリージョンのみに対応しており、日本のリージョンに対応していません。 米国中部 EUAP 米国東部 2 EUAP 米国中西部 米国中北部 米国西部 北ヨーロッパ そのため今回は米国西部(WestUS)にて作成することにします。 そして、インスタンスのレベルとしては、 Developer を選択します。 次に、仮想ネットワークです。 これはAzure Bastionが接続する先の仮想ネットワークであり、VMが含まれるネットワークを指します。 前回の記事で作ったものを使い回すそうかと思ったのですが 今回BastionではWestUSのリージョンにデプロイしており、仮想ネットワークも同リージョンで作成する必要があるため、このタイミングでVNetを作り直します。 これでBastionの作成はOKです。 VM ではVMも作成していきます。 前回の記事とほぼ同じ流れですが、気を付ける点が3点あります。 上記で作成したWestUSのVNetに対してデプロイすること PublicIPを なし にすること RDPポート(3389)を開けておくこと なお、制限事項の2つ目としてBastionの接続先のVMに対する制限があり、以下の通りとなっています。 接続方法 判定 RDPを利用したWindowsVMへの接続 〇 SSHを利用したLinuxVMへの接続 〇 RDPを利用したLinuxVMへの接続 × SSHを利用したWindowsVMへの接続 × 今回はRDPを利用してWindowsVMへの接続を行おうとしていたので、影響はありません。 また下2つのケースは、そもそもそんなに発生しないなとも思いますが、利用するBasic以上のプランをご検討ください。 ということで、今回はこのまま作成していきます。 作成完了後、RDP接続しようとしても接続できないことが確認できます。 (PublicIPが存在していないため) これで必要なリソースは作成完了です。 これまでの流れをやっていただくと、以下7リソースが出来上がっているかと思います。 Bastion VNet VM Network Interface Network Security Group Disc KeyVault 権限付与 では、BastionからVMにアクセスするための権限割り当てを行います。 権限として必要なものは以下2つです。 仮想マシンに対する 閲覧者 ロール。 仮想マシンのプライベート IP を使用する NIC に対する 閲覧者 ロール。 対象のリソースとしては以下のものです。 なお、ここで割り当てるのはBastionのManagedIDではなくて、アクセスするユーザー(EntraID)のServicePrincipalとなります。 つまり、あくまでBastionは接続するためのツールであって、アクセスするのはAzureテナントにログインしているユーザーであることが、この点から分かります。 サービスエンドポイント設定 既にやっているよ、っていう方は読み飛ばしてもらってOKです。 先程VNetなどを作り直したので、KeyVaultに対するサービスエンドポイントの設定なども忘れず行っておきましょう。 接続 ここまでできれば準備ばっちりです。 あとはBastionを使って接続していきますが、ここで制限事項の3つ目です。 Basic以上のプランだとAzure CLIからなども接続できるようなのですが、DeveloperSKUだとAzure Portal上からの接続のみとなります。 とはいいつつ、今回の要件程度であれば大きな問題ではありません。 Azure PortalからVMを選択し、Bastionのブレードを選択します。 すると、デプロイしているBastionが選択されて居ることが確認できます。 ここでVMに対する認証情報を追加し、「接続」のボタンを押します。 そうすると、ブラウザ上でいつも通りのVMへの接続が始まり、操作が可能となることが分かります。 そして、前回同様VM内のブラウザからAzurePortalを開き、KeyVaultに接続を試みます。 格納しているシークレット情報が確認できました。 (もちろん自分のPCから直接閲覧した場合は見えないかと思います。) これで、 プライベートIPを介してVMに接続し、そこからサービスエンドポイント経由で閉域化されたリソースに対してアクセスできる ことが確認できました! まとめ 今回は、Azure Bastionを利用して、プライベートIPを介したVM接続を試してみました。 前回の記事ではパブリックIPを持った状態であったため、セキュリティに不安が残りましたが、今回のようなケースであればセキュリティも強固になったといえるかと思います。 また、DeveloperSKUを採用することでコストも抑えられますし、アクセス管理に関してもRBACで行えるため非常にスマートですね。 是非閉域化されたリソースに対して管理・運用する場合はBastionの採用を検討してみてください。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】Bastionを利用してプライベートIPを介したセキュアなVM接続を実現する【基本無料】 first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 今回はAzureのネットワーク周りの話です。 閉域なネットワーク環境にあるKeyVaultやCosmosDBに対して、自分のPCからアクセスする方法をご紹介します。 はじめに Azureでシステムを構築するにあたって、閉域網として実現することはめずらしくないかと思います。 なお閉域網とは、外部のインターネットと接続せずに、特定の範囲内でのみアクセス可能なネットワークのことを指します。 KeyVaultや、CosmosDBなどのリソースをこの閉域網の中に閉じ込めることによって セキュリティやプライバシーを強化し、データの漏洩リスクを低減することができます。 この時、アプリを構築するうえでAzure上のAppServiceやAzure Functionsなどのコンピューティングリソースからはアクセスする必要がありますが そういった手段はもちろん用意されています。 (VNet統合) ただ、エンジニアが保守運用の際にアクセスしたいケースも往々にあります。 KeyVaultに格納されているシークレット情報を更新したい CosmosDBに蓄積されたデータを確認したい こういった際に、閉域とされているリソースに自分のPCからアクセスする方法を今回ご紹介します。 なお、Azure上で閉域網を実現するための方法として、様々な方法がありますが今回はサービスエンドポイントを使った方法をご紹介します。 事前準備 まずはKeyVaultを用意します。 KeyVaultのリソースを作成し、検証用にシークレットもひとつ追加しておきます。 まだこの時は閉域としていないため、自由にアクセスできるかと思います。 (アクセスポリシーや、RBACの設定は必要なのでそのあたりは適宜行ってください。) このKeyVaultを閉域化していきます。 KeyVaultのリソースの ネットワーク のブレードから設定を行います。 今回はサービスエンドポイントを利用するため 「ファイアーウォールと仮想ネットワーク」のタブから「特定の仮想ネットワークとIPアドレスからのパブリックアクセスを許可する」を選択します。 そうすると、仮想ネットワークの選択画面が出てくるかと思います。 まだ仮想ネットワークは作成していないため、設定を行わずにこのまま「適用」ボタンを押して終了します。 そして、この状態で再度シークレットを閲覧しに行ってみます。 すると ファイアウォールがオンになっており、クライアントの IP アドレスはこのキー コンテナーにアクセスする権限がありません と表示され、シークレットの中身が見えない事が確認できます。 もちろん作成なども行えません。 これでKeyVualtを閉域化することに成功しました!! 閉域化したリソースへのアクセス これで話は最初に戻りますが、この状態ではシークレットの追加や更新などが行えません。 「編集する時だけ閉域化を解除する…?」 と考える人もいるかと思いますが それがアンチパターンであることは、何となく察しがつきます。 それではどうするのかというと、Azure上に用意したVMを経由して閉域化されたリソースにアクセスします。 先程のKeyVaultのネットワーク設定の項目にもありましたが、アクセス元の仮想ネットワーク(VNet)を指定することができます。 以下の手順で接続を試みます。 VNet,Subnetを作成します。 Subnetに対してサービスエンドポイントの設定を有効にします。 Subnetに対してVMをデプロイします。 KeyVualtに対するアクセスを許可します。 RDP接続したVMを経由してKeyVaultへアクセスします。 VNet, Subnetの作成 まずはVNet, Subnetを作成します。 Subnet作成時にサービスエンドポイントの設定を行い、 Microsoft.KeyVault のサービスを追加します。 その他の項目はデフォルトのままでOKです。 SubnetへのVMデプロイ 今作成したサブネットの中にVMをデプロイします。 以下の内容でデプロイしました。 ポイントとしては以下2つです。 イメージをWindowsにする もちろんLinuxでも構いませんが、分かりやすさ優先で今回はWindowsとしています。 先程作成したサブネットに対してデプロイする KeyVaultに対するアクセスを許可する 先程作成したKeyVaultの ネットワーク ブレードから、上記で作成したサブネットからのアクセスを有効にします。 仮想ネットワークを追加したら[適用]を押して閉じます。 RDP接続したVMを経由してアクセス これで準備が整ったので、実際に自分のPCからRDPを利用してVMにアクセスします。 RDPでアクセスしたVM上でブラウザを開き、AzurePortalからのKeyVaultにアクセスします。 すると、以下のように先程格納したシークレットが閲覧できていることが確認できます。 振り返り 上記したステップを踏むことで閉域化のリソースにアクセスできることが確認できました。 今回はKeyVaultを題材にしましたが、CosmosDBや他のリソースに関しても同様の方法を取ることでアクセスが可能となります。 また、今回はサービスエンドポイントを利用しましたが、プライベートエンドポイントを利用した場合も同様の方法を取ることができます。 ただ、この時気になるのが「VM自体は外部のインターネットからアクセスできてるけどいいの?」といったところかと思います。 確かにKeyVaultに対しては外部のインターネットからのアクセスは遮断されていますが、 そこにアクセスするためのVMが、外部のインターネットからアクセスできてしまっている点について、不安が残ります。 この問題を解消する方法として、Azureには Azure Bastion というサービスが用意されています。 このBastionを使うことによって、VMのプライベートIPを介して自分のPCからセキュアに接続することが可能となります。 Bastionを利用した方法は以下の記事にまとめましたのでこちらもご覧ください。 【Azure】Bastionを利用してプライベートIPを介したセキュアなVM接続を実現する【基本無料】 まとめ 今回は、閉域化されたリソースに対して自分のPCからアクセスする方法をご紹介しました。 これで保守・運用についても自分のPCから問題なく行えなくなりそうです。 一方で、VMに対して外部インターネットからのアクセスが許可されているという課題もあります。 これを解消するBastionについても別記事にてご紹介しているため、こちらも併せてご覧ください。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】閉域化されたリソースに対して自分のPCからアクセスする方法を紹介 first appeared on SIOS Tech. Lab .
アバター
はじめに 皆さんこんにちは!エンジニアの細川です。 皆さんは環境変数を扱うときに型付けをどのように行っていますか? いろいろ方法はあると思いますが、今回はNestJSでt3envというパッケージを利用する方法について紹介したいと思います! t3envはESMOnlyのパッケージになりますので、NestJSでESMOnlyパッケージを利用したい方の参考にもなれば幸いです! 注意点 今回紹介する方法はNode.JSのver.が22以上でないと利用できません。 前提 今回の各パッケージなどのバージョンは以下になります。 パッケージ バージョン Node.js v22.9.0 NestJS v10.0.0 t3env 0.11.1 t3envとは? t3env は環境変数を型安全に利用できるパッケージです。 皆さん、ご存知の通り通常環境変数は process.env などで取得すると思います。型が string | undefined であり、使いにくかったり、設定し忘れていることに気づけなかったりなど皆さんも環境変数に悩まされることは多いのではないでしょうか? t3envを利用するとzodで環境変数にvalidationをつけることができます。 また、以下のようにサジェストをしてくれたり説明を付けられたりと、ちょっとした定義をするだけで、かなり環境変数を使いやすくなります! また、NestJSで利用する場合、環境変数が設定されていないと、以下のように環境変数がセットされていないエラーを出してくれてサーバーを起動できないため、設定し忘れを防ぐこともできます。 t3envの導入 以下のコマンドを叩いて、t3envを導入します。NextやNuxtで使う場合はそれぞれ用のパッケージを導入すれば良さそうですが、今回はNestで利用するので、coreのパッケージを導入します。 npm install @t3-oss/env-nextjs zod pnpmの場合は以下コマンドを叩いてください。 pnpm add @t3-oss/env-nextjs zod NextやNuxtの場合はそれぞれの導入の仕方を 公式ドキュメント に記載してくれているので、そちらを参考にしてください。 定義ファイルの作成 t3envでは環境変数の定義用のファイルを作成する必要があるので、公式ドキュメントに従って、以下のように src/env.ts を作成します。 import { createEnv } from "@t3-oss/env-nextjs"; import { z } from "zod"; export const env = createEnv({ server: { /** * DB接続情報 <- このように環境変数の説明も書けます。 */ DATABASE_URL: z.string().url(), OPEN_AI_API_KEY: z.string().min(1), }, /** * The prefix that client-side variables must have. This is enforced both at * a type-level and at runtime. */ clientPrefix: "PUBLIC_", client: { PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1), }, /** * What object holds the environment variables at runtime. This is usually * `process.env` or `import.meta.env`. */ runtimeEnv: process.env, /** * By default, this library will feed the environment variables directly to * the Zod validator. * * This means that if you have an empty string for a value that is supposed * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag * it as a type mismatch violation. Additionally, if you have an empty string * for a value that is supposed to be a string with a default value (e.g. * `DOMAIN=` in an ".env" file), the default value will never be applied. * * In order to solve these issues, we recommend that all new projects * explicitly specify this option as true. */ emptyStringAsUndefined: true, }); このようにserverとclientで利用する環境変数を分けて定義できたり、zodのschemaによるvalidationも行うことができます。 より細かい定義方法は公式ドキュメントなどを参照してみてください。 こちら の記事でも分かりやすく書いてくれていました。 NestJSでESMOnlyパッケージを利用する方法 通常ではこれだけで利用することができるのですが、実はt3envはESMOnlyのパッケージであり、commonJSを採用しているNestJSではそのままでは利用することができません。NestJSをESM化する方法などもありますが、既存のコードがある状態だと変更に不安があるうえに、変更量も多くなってしまい、大変です。そこで、今回はNode.jsの --experimental-require-module オプションを利用します。こちらのオプションはNode.jsのver.22でリリースされたものののようですので、22以下の方は利用できないかもしれません( 参考 )。 package.jsonのNestの起動コマンドに --experimental-require-module オプションを追加します。 // package.json "build": "NODE_OPTIONS='--experimental-require-module' nest build", "start": "NODE_OPTIONS='--experimental-require-module' nest start", "start:dev": "NODE_OPTIONS='--experimental-require-module' nest start --watch", "start:debug": "NODE_OPTIONS='--experimental-require-module' NODE_ENV=development DEBUG=true nest start --debug --watch", "start:prod": "NODE_OPTIONS='--experimental-require-module' node dist/main", ...その他のコマンド これを追記するとNestJSのサーバーが立ち上げられるようになります。 他のESMOnlyのパッケージを導入する際もこの手順で使えるようになるはずです。 moduleResolutionエラーの対処 サーバー自体は先ほどのオプションを追加すれば立ち上がるようになるのですが、 src/env.ts のファイルを見ると以下のようなエラーが出ていると思います。 エラーをそのまま読むと、 moduleResolution という項目を node16 もしくは、 nodenext 、もしくは bundler にすればいいとのことですが、この設定にするためにはtsconfig.jsonの module も commonjs ではなく nodenext などにする必要があります。 moduleResolution はパス解決のための設定のようなので( 参考 )、 moduleResolution を設定するのではなく、t3envのパスを直接解決してあげることでこの問題に対処します。 具体的には、tsconfig.jsonに以下の記述を追記します。 { "compilerOptions": { "module": "commonjs", // 他の記述 "paths": { "@t3-oss/env-core": [ "../../node_modules/@t3-oss/env-core/dist/index.d.ts" // t3envのパッケージの実体へのパス ] } }, "include": [ "src/**/*.ts", "../../node_modules/@t3-oss/env-core/dist/index.d.ts" // <- こちらも追記 ] } 念のため全文も掲載しておきます。 もし追記して動作しないようでしたら、他の設定項目も確認してみてください。 { "compilerOptions": { "module": "commonjs", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, "target": "ES2021", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "incremental": true, "skipLibCheck": true, "strictNullChecks": true, "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false, "paths": { "@t3-oss/env-core": [ "../../node_modules/@t3-oss/env-core/dist/index.d.ts" ] } }, "include": [ "src/**/*.ts", "../../node_modules/@t3-oss/env-core/dist/index.d.ts" ] } 利用方法 以上で準備完了です。 利用する際は、まず通常と同じ通り、 .env などに実際の値を記載しておきます。 そして以下のように src/env.ts からimportを記述することで利用することができます。 import { env } from "./env"; const dbUrl = env.DATABASE_URL 型やサジェストも正しく機能していることが確認できるかと思います。 テストについて 今回の方法を試したところ、僕の環境ではJestでtestが動きませんでした。ちょうどvitestに切り替えるタイミングでしたので、Jestで動くようにする対応は行いませんでした。 vitestでは特に設定しなくてもESMも扱えるので、vitestでは問題なく動作しました。もしJestで動作しない方はvitestの導入も検討してみてください。NestJSでVitestを導入する際は こちら の記事を参考にさせていただきました。 まとめ t3envを利用することで、環境変数をサジェストしてくれたり、型安全に利用できたり、定義し忘れを防止することができる! NestJSでESMOnlyパッケージを利用する際には、 --experimental-require-module オプションを利用する "build": "NODE_OPTIONS='--experimental-require-module' nest build", "start": "NODE_OPTIONS='--experimental-require-module' nest start", "start:dev": "NODE_OPTIONS='--experimental-require-module' nest start --watch", "start:debug": "NODE_OPTIONS='--experimental-require-module' NODE_ENV=development DEBUG=true nest start --debug --watch", "start:prod": "NODE_OPTIONS='--experimental-require-module' node dist/main", t3envの型定義のパス解決のために、tsconfig.jsonに以下を追記する。 { "compilerOptions": { "module": "commonjs", // 他の記述 "paths": { "@t3-oss/env-core": [ "../../node_modules/@t3-oss/env-core/dist/index.d.ts" // t3envのパッケージの実体へのパス ] } }, "include": [ "src/**/*.ts", "../../node_modules/@t3-oss/env-core/dist/index.d.ts" // <- こちらも追記 ] testはvitestだと楽! おわりに 今回はNestJSで環境変数を型安全に利用する手段としてt3envを採用しました。 --experimental-require-module オプションのおかげで、NestJSでもESMOnlyのパッケージでも導入しやすくなったと思うので、ぜひ皆さんもt3envや他のESMパッケージの利用を検討してみてください。 他にもTypeScriptのあれこれを 記事 にしているので、良かったら読んでみてください! 参考にさせていただいた記事 https://zenn.dev/ptna/articles/28b20f303a3cfb https://zenn.dev/hayato94087/articles/3e4128feddffb9 https://env.t3.gg/docs/core   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post NestJSで環境変数を型安全に使おう! t3env first appeared on SIOS Tech. Lab .
アバター
以前の記事 では、CI 部分を担う OpenShift Pipelines について解説しました。続いて、本記事では実際に OpenShift Pipelines の CI 部分 を構築したいと思います。 構築の概要 Red Hat のチュートリアル を参考にして図のような CI フローを OpenShift 上に構築します。チュートリアルではパブリックリポジトリを利用していますが、実際構築する際はプライベートリポジトリであるケースが多いため、プライベートリポジトリで構築してみます。CI フローの流れとしては、まず初めにプライベートな Git リポジトリに変更をプッシュした際に EventListener への Webhook がトリガーされます。EventListener は受け取った情報から指定されたパラメータを Trigger Template にバインディングして PipelineRun を実行させます。PipelineRun では最初にリポジトリからソースコードの取得をします。次にソースコードのimage をビルドし、image registry にプッシュしたらフロー終了です。 事前準備 下記構成のプライベートなアプリケーション用Git リポジトリを用意します。アプリケーションの設定や定義をDockerfileとindex.phpで設定し、Kubernetesのリソースはk8sディレクトリ配下にまとめています。 . ├── Dockerfile ├── index.php └── k8s  ├── deployment.yaml  ├── route.yaml  └── service.yaml Dockerfile FROM image-registry.openshift-image-registry.svc:5000/openshift/php:latest ADD ./index.php /var/www/html/ CMD ["php","-S","0.0.0.0:8080","-t","/var/www/html"] index.php Hello world! k8s/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   replicas: 1   selector:     matchLabels:       app: ocp-cicd-appli-ui   template:     metadata:       labels:         app: ocp-cicd-appli-ui     spec:       containers:         - image: image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/ocp-cicd-appli-ui           imagePullPolicy: Always           name: ocp-cicd-appli-ui           ports:             - containerPort: 8080               protocol: TCP k8s/route.yaml apiVersion: route.openshift.io/v1 kind: Route metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   port:     targetPort: 8080-tcp   to:     kind: Service     name: ocp-cicd-appli-ui     weight: 100 k8s/service.yaml apiVersion: v1 kind: Service metadata:   labels:     app: ocp-cicd-appli-ui   name: ocp-cicd-appli-ui spec:   type: NodePort   ports:     - name: 8080-tcp       port: 8080       targetPort: 8080       protocol: TCP   selector:     app: ocp-cicd-appli-ui 前提条件 OpenShift クラスターが構築済みであること oc CLI がインストール済みであること tkn CLI がインストール済みであること プライベートな Git リポジトリにssh設定がされており、対となる秘密鍵を持っていること リポジトリ名に”_”が含まれていないこと( “_”が含まれているとPipelineRunリソースが正常に作成できない点に注意 ) OpenShift Pipelines をインストール OpenShift OperatorHub で Administrator のパースペクティブにいることを確認します。 Web コンソールで[Operators] > [OperatorHub]に移動します。 検索バーに「OpenShift Pipelines」と入力して、 OpenShift Pipelines をクリックして Install をクリックします。 デフォルトのまま Install をクリックします。 パイプラインを作成 図の赤枠部分を作成していきます。 サンプルアプリケーションをデプロイ 新規プロジェクトを作成します。 $ oc new-project pipelines-tutorial Now using project "pipelines-tutorial" on server "URL". You can add applications to this project with the 'new-app' command. For example, try: oc new-app rails-postgresql-example to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application: kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname ssh接続情報の作成 プライベートな Git リポジトリに接続するためのシークレットを作成します。 $ oc apply -f secret.yaml secret/ssh-credential created secret.yaml apiVersion: v1 kind: Secret metadata:   name: ssh-credential data:   id_rsa: # cat ~/.ssh/id_rsa | base64 で表示された内容を記入(一行で記述すること) pipeline サービスアカウントを確認 パイプラインを実行するサービスアカウントが存在しているか確認します。 $ oc get serviceaccount pipeline NAME SECRETS AGE pipeline 1 102s タスクをインストール(実行確認のためのCD部分のタスク) タスクを作成します。これは実行確認のための CD 部分のタスクとなり、続編のCD部分を実装する際は実行しないでください。 $ oc create -f apply_manifest_task.yaml task.tekton.dev/apply-manifests created $ oc create -f update_deployment_task.yaml task.tekton.dev/update-deployment created apply_manifest_task.yaml apiVersion: tekton.dev/v1 kind: Task metadata:   name: apply-manifests spec:   workspaces:   - name: source   params:     - name: manifest_dir       description: The directory in source that contains yaml manifests       type: string       default: "k8s"   steps:     - name: apply       image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest       workingDir: /workspace/source       command: ["/bin/bash", "-c"]       args:         - |-           echo Applying manifests in $(inputs.params.manifest_dir) directory           oc apply -f $(inputs.params.manifest_dir)           echo ----------------------------------- update_deployment_task.yaml apiVersion: tekton.dev/v1 kind: Task metadata:   name: update-deployment spec:   params:     - name: deployment       description: The name of the deployment patch the image       type: string     - name: IMAGE       description: Location of image to be patched with       type: string   steps:     - name: patch       image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest       command: ["/bin/bash", "-c"]       args:         - |-           oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"spec":{             "containers":[{               "name": "$(inputs.params.deployment)",               "image":"$(inputs.params.IMAGE)"             }]           }}}}'           patched_at_timestamp=`date +%s`           oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"metadata":{             "labels":{               "patched_at": '\"$patched_at_timestamp\"'             }           }}}}' 作成したタスクを確認 タスクが作成されていることを確認します。 $ tkn task ls NAME DESCRIPTION AGE apply-manifests 6 minutes ago update-deployment 6 minutes ago パイプラインを作成 パイプラインを作成します。 $ oc create -f pipeline.yaml pipeline.tekton.dev/build-and-deploy created pipeline.yaml apiVersion: tekton.dev/v1 kind: Pipeline metadata:   name: build-and-deploy spec:   workspaces:   - name: shared-workspace   - name: ssh-creds   params:   - name: deployment-name     type: string     description: name of the deployment to be patched   - name: git-url     type: string     description: url of the git repo for the code of deployment   - name: git-revision     type: string     description: revision to be used from repo of the code for deployment     default: main   - name: IMAGE     type: string     description: image to be build from the code     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       value: $(params.git-url)     - name: subdirectory       value: ""     - name: deleteExisting       value: "true"     - name: revision       value: $(params.git-revision)   - name: build-image     taskRef:       name: buildah       kind: ClusterTask     params:     - name: IMAGE       value: $(params.IMAGE)     workspaces:     - name: source       workspace: shared-workspace     runAfter:     - fetch-repository # 以下CD部分のタスクのため、続編のCD部分を実装する際は記入しないこと   - name: apply-manifests     taskRef:       name: apply-manifests     workspaces:     - name: source       workspace: shared-workspace     runAfter:     - build-image   - name: update-deployment     taskRef:       name: update-deployment     params:     - name: deployment       value: $(params.deployment-name)     - name: IMAGE       value: $(params.IMAGE)     runAfter:     - apply-manifests 作成したパイプラインを確認 パイプラインが作成されていることを確認します。 $ tkn pipeline ls NAME AGE LAST RUN STARTED DURATION STATUS build-and-deploy 2 minutes ago --- --- --- --- パイプラインを手動実行 作成したパイプラインを手動で実行して動作を確認します。 $ tkn pipeline start build-and-deploy \ --prefix-name build-deploy-ui-pipelinerun \ -w name=shared-workspace,volumeClaimTemplateFile=persistent_volume_claim.yaml \ -w name=ssh-creds,secret=ssh-credential \ -p deployment-name=ocp-cicd-appli-ui \ -p git-url=<リポジトリ名:git@xxx:xxx/xxx.gitの形式> \ -p IMAGE=image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/ocp-cicd-appli-ui \ --use-param-defaults PipelineRun started: build-deploy-ui-pipelinerun-ngnjn In order to track the PipelineRun progress run: tkn pipelinerun logs build-deploy-ui-pipelinerun-ngnjn -f -n pipelines-tutorial persistent_volume_claim.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata:   name: source-pvc spec:   accessModes:     - ReadWriteOnce   resources:     requests:       storage: 500Mi Pipelinesを確認するとPipelineが実行中になっています。 Pipeline run を確認するとパイプラインの実行ログなどを確認することが出来ます。Succeeded になっていることを確認します。 アプリケーションのルートを取得 デプロイしたアプリケーションのルートを取得して正しくデプロイされていることを確認します。 $ oc get route ocp-cicd-appli-ui --template='http://{{.spec.host}}' <アプリケーションのURL> トリガーを作成 図の赤枠部分を作成していきます。 テンプレートの適用 トリガーテンプレートを作成します。 $ oc create -f triggertemplate.yaml triggertemplate.triggers.tekton.dev/sample-app created triggertemplate.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerTemplate metadata:   name: sample-app spec:   params:   - name: git-repo-url     description: The git repository url   - name: git-revision     description: The git revision     default: main   - name: git-repo-name     description: The name of the deployment to be created / patched   resourcetemplates:   - apiVersion: tekton.dev/v1     kind: PipelineRun     metadata:       generateName: build-deploy-$(tt.params.git-repo-name)     spec:       taskRunTemplate:         serviceAccountName: pipeline       pipelineRef:         name: build-and-deploy       params:       - name: deployment-name         value: $(tt.params.git-repo-name)       - name: git-url         value: $(tt.params.git-repo-url)       - name: git-revision         value: $(tt.params.git-revision)       - name: IMAGE value: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(tt.params.git-repo-name):$(tt.params.git-revision)       # Pipelineで実行結果確認のCD部分を実装する場合はコミットIDを参照しないため下記に置き換える         # value: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(tt.params.git-repo-name)       workspaces:       - name: shared-workspace         volumeClaimTemplate:           spec:             accessModes:               - ReadWriteOnce             resources:               requests:                 storage: 500Mi       - name: ssh-creds         secret:           secretName: ssh-credential バインディングの適用 トリガーバインディングを作成します。 $ oc create -f triggerbinding.yaml triggerbinding.triggers.tekton.dev/sample-app created triggerbinding.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerBinding metadata:   name: sample-app spec:   params:   - name: git-repo-url     # privateリポジトリのためssh_urlを参照     value: $(body.repository.ssh_url)   - name: git-repo-name     value: $(body.repository.name)   - name: git-revision     value: $(body.head_commit.id) トリガーの適用 トリガーを適用します。webhookのsecretも作成するため、後程トークンの値を使います。 $ oc create -f trigger.yaml trigger.triggers.tekton.dev/sample-trigger created secret/github-secret created trigger.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: Trigger metadata:   # event_listenerで参照するTrigger名   name: sample-trigger spec:   serviceAccountName: pipeline   interceptors:     - ref:         name: "github"       params:         - name: "secretRef"           value:             secretName: github-secret             secretKey: secretToken         - name: "eventTypes"           value: ["push"]   bindings:     - ref: sample-app   template:     ref: sample-app --- apiVersion: v1 kind: Secret metadata:   name: github-secret type: Opaque stringData: # webhookのシークレット   secretToken: "1234567" EventListenerの作成 EventListenerを作成します。 $ oc create -f event_listener.yaml eventlistener.triggers.tekton.dev/sample-app created event_listener.yaml apiVersion: triggers.tekton.dev/v1beta1 kind: EventListener metadata:   name: sample-app spec:   serviceAccountName: pipeline   triggers:     # webhookをインターセプトするTrigger名を参照     - triggerRef: sample-trigger EventListener サービスをルートとして公開 EventListener サービスをルートとして公開します。 $ oc expose svc el-sample-app route.route.openshift.io/el-sample-app exposed webhook-url を取得 webhook-url を取得を取得します。取得したURLはGit リポジトリのwebhook設定に使用します。 $ echo "URL: $(oc get route el-sample-app --template='http://{{.spec.host}}')" URL: <webhook-url> Webhookを手動設定する Git リポジトリにWebhookを設定します。 GitHubのリポジトリを開きます。 Settings > Hook > Add Webhook をクリックします。 payload URL に webhook-url を追加 > コンテンツタイプをapplication/jsonに選択 > シークレットを追加 例:1234567 > Add Webhook をクリックして設定完了です。 パイプライン実行テスト Git リポジトリの index.php に適当な変更を加え、コミットを Git リポジトリにプッシュします。 git add . git commit -m "hogehoge" git push OpenShift WebConsole Developer パースペクティブを見ると、PipelineRun が自動的に作成されます。 Succeeded になっていることを確認します。 続いて、アプリケーションに加えた変更が反映されていることを確認して完了です。 まとめ 本記事では実際に Red Hat のチュートリアルを参考にしてOpenShift Pipelines の CI 部分を構築してみました。実行確認のために CD 部分を実装しましたが、これはマニフェストファイルを適用しただけの push 型のデプロイでした。次回は CD 部分となる OpenShift GitOps を構築して デプロイ先の状態変化を検知してマニフェストファイルの状態を保ち続ける pull 型のデプロイを実装してみます。 参考文献 https://github.com/openshift/pipelines-tutorial/tree/master ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Openshift Pipelines を構築してみた first appeared on SIOS Tech. Lab .
アバター
概要 こんにちは、サイオステクノロジーの安藤 浩です。 Bicepは、Azureリソースを宣言的にデプロイするためのドメイン固有言語(DSL)であり、ARMテンプレートの記述を簡素化することを目的としています。ARM テンプレートは、JSON または Bicep の使用という 2 つの異なる方法で記述できますが、JSONの場合は複雑な記法が必要になります。 私自身ARM テンプレート は書いたことないですが、ARM テンプレート自体複雑な印象で記述が困難なように思います。 JSON と Bicep の比較は Bicep プレイグラウンド で確認することができます。 以下のAzure のLearning があるのでそちらを参照するとBicep に関して学習できます。 Bicep に関する Learn モジュール 前提条件 以下をインストールします。 ツール Version Visual Studio Code Version: 1.94.2 Visual Studio Code 用の Bicep 拡張機能 0.30.23 最新の Azure CLI ツールまたは最新の Azure PowerShell バージョン 2.65.0 構成要素 今は例として以下の構成要素でBicep によるAzure のインフラ構築をしてみます。 Azure Function Blob Storage Application Insights LogAnalytics Workspace App Service Plan ソースコード ソースコードは以下にあります。 https://github.com/Hiroshi-Ando-sti/introduction-bicep 実装方法 まずは、  main.bicep  を用意し、以下を記載します。 targetScope = 'resourceGroup' param location string = resourceGroup().location @description('The environment designator for the deployment. Replaces {env} in namingConvention.') @allowed([ 'dev' //Develop 'stg' //Staging 'prd' //Production ]) param enviromentName string = 'dev' var enviromentResourceNameWithoutHyphen = replace(enviromentName, '-', '') @allowed(['northeurope', 'southeastasia', 'eastasia', 'eastus2', 'southcentralus', 'australiaeast', 'eastus', 'westus2', 'uksouth', 'eastus2euap', 'westus3', 'swedencentral']) param hostingPlanLocation string = 'eastus2' @description('The workload name. Replaces {workloadName} in namingConvention.') param workloadName string = 'pj' param deploymentStorageContainerName string = 'app-pkg-func' @description('secretName') param secretName1 string @secure() @description('secretValue') param secretValue1 string var suffixResourceName = '-${workloadName}' var suffixResourceNameWithoutHyphen = replace(suffixResourceName, '-', '') var uniqueStr = uniqueString(resourceGroup().id, enviromentName, workloadName, suffixResourceNameWithoutHyphen) param convertedEpoch int = dateTimeToEpoch(dateTimeAdd(utcNow(), 'P1Y')) var abbrs = json(loadTextContent('abbreviations.json')) var tags = { workload: workloadName environment: enviromentName } 記述方法 主要なBicep の記述方法について説明します。 param(パラメータ) param は、実行時に値をBicepテンプレートに渡すためのパラメータを定義するために使用されます。これにより、テンプレートの再利用が可能になり、値のハードコーディングを避けられます。 例: @allowed([ 'dev' //Develop 'stg' //Staging 'prd' //Production ]) param enviromentName string = 'dev' ここでは、 enviromentName という名前の string 型のパラメータが定義されており、デフォルト値: dev が設定されています。 型 :  string 、 int 、 bool 、 array 、 object  などの型を指定できます。 デフォルト値 : パラメータにデフォルト値を設定することも可能です。 description description は、パラメータや変数の説明を提供するために使用されます。 allowed allowed は、パラメータの許可された値を制限するために使用されます。これにより、指定値以外の不正な値を設定することを防ぐことができます。 var(変数) var は、テンプレート内で中間的な値や計算結果を保持するための変数を定義するために使用されます。 例: var uniqueStr = uniqueString(resourceGroup().id, enviromentName, workloadName, suffixResourceNameWithoutHyphen) この例では、 uniqueStr  という変数に、リソースグループのID, enviromentName などに基づいて生成された一意の文字列が設定されています。 式 : 変数は、式や文字列の連結、計算などを保持できます。 スコープ : 変数はテンプレート内でのみ使用可能で、外部には公開されません。 secure(セキュアパラメータ) Bicepでは、パスワードやAPIキーのような機密情報を取り扱う場合、セキュアなパラメータを定義できます。ログや出力には表示されず、デプロイメント中に値が安全に処理されます。 例: @secure() @description('secretValue') param secretValue1 string module(モジュール) module  は、他のBicepテンプレートを参照して再利用するために使用されます。テンプレートを分割して、管理しやすくなります。例えば、Azure Function や AppService などのリソースに対するStorage Accountを作成する際に再利用可能なモジュールを作成できます。 例: ./main.bicep var storageAccountName = '${abbrs.storageStorageAccounts}${enviromentResourceNameWithoutHyphen}${uniqueStr}' module storage 'modules/storage/storage.bicep' = { name: 'storage' params: { storageAccountName: storageAccountName location: location tags: tags storageAccountType: 'Standard_LRS' containerNames: [deploymentStorageContainerName] } } ./modules/storage/storage.bicep @description('Storage Account type') @allowed([ 'Premium_LRS' 'Premium_ZRS' 'Standard_GRS' 'Standard_GZRS' 'Standard_LRS' 'Standard_RAGRS' 'Standard_RAGZRS' 'Standard_ZRS' ]) param storageAccountType string = 'Standard_LRS' @description('The storage account location.') param location string = resourceGroup().location param tags object = {} @description('The name of the storage account') param storageAccountName string param containerNames array resource sa 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location tags: tags sku: { name: storageAccountType } kind: 'StorageV2' properties: {} } resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = { parent: sa name: 'default' } resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = [for containerName in containerNames: { parent: blobServices name: containerName }] output storageAccountName string = storageAccountName output storageAccountId string = sa.id この例では、module を利用し、  ./modules/storage/storage.bicep  をインポートして再利用しています。 モジュール化 : 複雑なインフラを整理し、リソースをモジュールにグループ化するのに役立ちます。 再利用 : モジュールは、異なるデプロイメントで再利用可能です。 resource(リソース) resource  は、Azureリソースを定義するために使用されます。リソースの種類、プロパティ、依存関係など、リソースの詳細を定義します。 リソースの定義は、 Microsoft.Storage/storageAccounts@2023-01-01  という形式で指定します。リソースの種類とAPIバージョンを指定しています。 詳しくは、 リソースの Bicep を使った宣言  を参照ください。 Storage Accountの場合は、以下を参照して詳細なプロパティなどを指定します。 https://learn.microsoft.com/ja-jp/azure/templates/microsoft.storage/storageaccounts output(出力) output  は、デプロイメントが完了した後に値を返すために使用されます。リソースIDや接続文字列のような情報をデプロイ後に返す場合に便利です。 上記の例では、作成されたストレージアカウントのリソースIDを返します。 データの返却 : 出力された値は、後続のデプロイメントや追加のアクションで使用できます。 複数の出力 : 1つのBicepファイルに複数の  output  ステートメントを含めることができます。 その他 Best practice  の記載があるのでこちらを参考にしてBest Practice を実践しましょう。 パラメーター ファイルを使用して値を指定する Bicep では、パラメーター ファイルを使用して、Bicep テンプレートに渡す値を指定することができます。 パラメーター ファイルは、JSON 形式のファイルで、Bicep テンプレートのパラメータ(param)に渡す値を定義します。 main.parameters.dev.json  を  main.bicep  と同階層に作成します。 { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "location": { "value": "eastus2" }, "enviromentName": { "value": "dev" }, "hostingPlanLocation": { "value": "eastus2" }, "workloadName": { "value": "pj-bicep" }, "deploymentStorageContainerName": { "value": "app-pkg-func" }, "secretName1": { "value": "secretName1" }, "secretValue1": { "value": "secretValue1" } } } 新規作成 リソースグループ作成 リソースグループを作成します。 az group create --name rg-dev-pj-bicep --location japaneast デプロイ 上記で作成したリソースグループへリソースをデプロイします。 az deployment group create \ --name rg-dev-pj-bicep-deploy \ --resource-group rg-dev-pj-bicep \ --mode Complete \ --confirm-with-what-if \ --template-file main.bicep \ --parameters ./main.parameters.dev.json ここでは  mode  にComplete と指定して、完全モードでDeployしています。 完全モードは、 Bicep コードに 定義されているリソースのみをデプロイするモードです。Bicep コードに存在しない既存のリソースが存在する場合は、削除されます。 もう一方、インクリメントモードがあり、Bicep コードに存在しない既存のリソースが存在してもリソースの影響は受けません。 更新 リソースの作成が完了したら、もう一度同じコマンドを実行すると変更箇所の差分が確認できます。 az deployment group create \ --name rg-dev-pj-bicep-deploy \ --resource-group rg-dev-pj-bicep \ --mode Complete \ --confirm-with-what-if \ --template-file main.bicep \ --parameters ./main.parameters.dev.json 実行すると以下のように変更箇所を教えてくれます。 確認方法 コマンドの結果でも確認できますが、リソースグループの「概要」の「要点」の箇所のデプロイのところを確認することも可能です。 リンクを押下すると以下のようになります。 リンクの function, appInsights, storage などは  main.bicep  の  module  で指定した name に対応します。より詳細は各リンクを押下すると確認できます。 参考URL Bicep とは Bicep のドキュメント Bicep の基礎 Bicep に関するベスト プラクティス サンプルコード まとめ Bicep を利用して、簡単に Azure のインフラ構築をしてみました。割と簡単な記述でリソース作成ができるので、ぜひ使ってはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Bicep によるAzure のインフラ構築入門 first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 先日Ragasの大きめなアップデート(0.2.x)があり、色々と変更点が見られました。 今回はそのアップデート内容をチェックしていきたいと思います。 Ragasって何? 今Ragas使ってるけど、どんな変更があったの? 公式ドキュメント読んでもよくわからないからサクっと教えて! といった方は最後までご覧ください! はじめに Ragasって何?という方は以下の記事をご覧ください! こちらの記事は前のバージョン(0.1.x)での紹介にはなりますが、概念的な部分は変わっていないので 一度読んでいただくことで、今回のアップデート内容も理解しやすいかと思います。 【初心者向け】RAG評価フレームワーク Ragasを必要最低限で使ってみる 今回このRagasにバージョンアップがあり、0.1.xから0.2.xになりました。 そのアップデート内容の確認と、サンプルコードを交えて挙動の確認をしていきたいと思います。 なお、手元の環境では ragas==0.2.3 のバージョンを利用して検証行っています。 何が変わったのか? 公式 にもまとめられていました。 変更点の概要としては以下の通りです。 評価用に与えるデータセットのクラス変更 メトリクスの追加および、利用方法の変更 テストセット生成のコスト効率改善 プロンプトオブジェクトの変更 もう少し細かく見ていきたいと思います。 データセットの型変更 Ragasには以下の4つの値を渡すことで評価を行うことができます。 そしてそれらの名前にも変更がありました。 新名称 何? 旧称 user_input ユーザーからの質問内容 question response RAGから返された回答内容 answer retrieved_contexts RAGが外部DBから取得し、参考にした内容 contexts reference user_inputに対する真の回答内容 ground_truth これらの値をデータセットとして評価関数に渡し、評価を行ってもらいます。 そして、0.2.xへのアップデートによってこのデータセットのクラスにも変更がありました。 以前はHuggingFaceというライブラリの Datasets というものを利用していましたが、0.2.xでは独自の EvaluationDataset というクラスを利用しています。 このデータセットの用意の仕方を3つご紹介します。 Datasetsからの変換 前バージョンで利用していたDatasetsからEvaluationDatasetの変換方法が提供されています。 以下のような形で簡単に変換することが可能です。 from datasets import load_dataset from ragas import EvaluationDataset dataset = load_dataset("explodinggradients/amnesty_qa","english_v3") eval_dataset = EvaluationDataset.from_hf_dataset(dataset["eval"]) CSVからの変換 EvaluationDataset->csvの変換の処理に関しても紹介されていました。 # load eva dataset eval_dataset = EvaluationDataset.from_csv("path/to/save/dataset.csv") Evaluation Sampleを利用した生成 ここが大きな変更点です。 恐らく0.2.x系からだと思うのですが、 Evaluation Sample という概念が出てきました。 Evaluation Sample の定義を見てみると An evaluation sample is a single structured data instance that is used to asses and measure the performance of your LLM application in specific scenarios. とあり、翻訳すると以下の感じです。 評価サンプルは、特定のシナリオにおけるLLMアプリケーションのパフォーマンスを評価・測定するために使用される単一の構造化データインスタンスです。 要は、評価・測定するために使うデータの入れ物という事をいってます。 使い方としては以下のような感じです。 sample1 = SingleTurnSample(     user_input="日本の首都はどこですか?", #質問     retrieved_contexts=["東京(とうきょう、英: Tokyo)は、関東平野の南部に位置し、東京湾に面する都市。日本の首都である."], #RAGが外部DBから取得し、参考にした内容     response="日本の首都は東京です.", #RAGから返された回答内容     reference="東京", #user_inputに対する真の答え ) 「ん?さっき話に出してた EvaluationDataset はどこいった?」という感じなのですが Evaluation Datasetの定義を見てみると An evaluation dataset is a homogeneous collection of data samples とあり、Evaluation Sampleのコレクションである事がわかります。 実際サンプルコードなどを見ると以下のような感じで、コレクションの関係があることが分かります。 dataset = EvaluationDataset(samples=[sample1, sample2, sample3]) メトリクスの追加 これまで使われていたメトリクス(評価指標)は引き続き使えることに加えて、いくつか新たなメトリクスも加わっています。 ドキュメント を見ると、RAGの評価にとどまらずAgentや、自然言語の評価も行えるようになってますね。  RAG以外のメトリクスも非常に気になりますが、今回はひとまずRAGの評価の言及にとどめたいと思います。 このメトリクスの追加に合わせて、メトリクスの設定方法も若干変わっています。 メトリクスの設定方法の変更 以前は以下のような形で、利用するメトリクスを設定していました。(必要な部分のみ抜粋) # import from ragas.metrics import faithfulness # list of metrics we're going to use metrics = [     faithfulness ] これが0.2.xのバージョンでは以下のように実装します。 メトリクスを選択する段階で利用するLLMを指定することを推奨するようです。 from ragas.metrics import Faithfulness faithfulness_metric = Faithfulness(llm=your_evaluator_llm) これにより、 どのメトリクスで、どのLLMを使うのかを明確にすることができる ようになりました。 評価方法の変更 また評価を行う部分の関数にも、いくつか変更が見られました。 今回はAzure OpenAI Serviceにデプロイしたモデルを使用する想定で実装します。 evaluate関数 まず、以前は以下のようにevaluate関数を使って評価を行っていました。 # import from ragas.metrics import faithfulness # list of metrics we're going to use metrics = [     faithfulness ] 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") generator_llm = AzureChatOpenAI(     azure_deployment="gpt-35-turbo-16k", ) embeddings = AzureOpenAIEmbeddings(     azure_deployment="text-embedding-ada-002" ) result = evaluate(     ds, metrics=metrics, llm=chat_llm, embeddings=embeddings ) ただ先程述べたように metrics の生成方法が変わってるので、そのあたりの影響を受けてきます。 0.2.x系では以下のように書きます。 from ragas.metrics import Faithfulness os.environ["OPENAI_API_KEY"] = os.getenv("AZURE_OPENAI_API_KEY") #なぜかAZURE_OPENAI_API_KEYという環境変数名にすると反応してくれなかった。 os.environ["AZURE_OPENAI_ENDPOINT"] = os.getenv("AZURE_OPENAI_ENDPOINT") os.environ["OPENAI_API_VERSION"] = os.getenv("OPENAI_API_VERSION") evaluator_llm = LangchainLLMWrapper(AzureChatOpenAI(     azure_deployment="gpt-4o-mini",     temperature=0, )) metrics = [     Faithfulness(llm=evaluator_llm) ] results = evaluate(dataset=eval_dataset, metrics=metrics) df = results.to_pandas() もう少し深掘りしてみていきたいと思います。 0.2.x系でのevaluate()のソースコードは以下のようになっています。 def evaluate(     dataset: t.Union[Dataset, EvaluationDataset],     metrics: list[Metric] | None = None,     llm: t.Optional[BaseRagasLLM | LangchainLLM] = None,     embeddings: t.Optional[BaseRagasEmbeddings | LangchainEmbeddings] = None,     callbacks: Callbacks = None,     in_ci: bool = False,     run_config: RunConfig = RunConfig(),     token_usage_parser: t.Optional[TokenUsageParser] = None,     raise_exceptions: bool = False,     column_map: t.Optional[t.Dict[str, str]] = None,     show_progress: bool = True, 主な変更点としては datasetとして EvaluationDataset が追加されている metricsの中身の Metrics の中身が変更されている llm, embeddingsに関してBaseRagasLLM, BaseRagasEmbeddingsというものが追加されている といった点が挙げられるかと思います。 先程Metricsごとに利用するLLMを指定できるといった説明をしましたが、仮に指定しない場合はevaluate関数で指定したLLMが使われるようです。 なお、優先度としてはevaluate関数の指定よりもMetricsの指定が高く、MetricsのLLMで上書きされるようです。 余談 なぜか0.2.x系になってからAzureOpenAIServiceにおける利活用方法がドキュメントから抹消されていました。(Bedrockはあるのに…) 「まぁでもLangchainLLMWrapperを挟んで使うし、LangcainでAOAIが使えれば問題ないだろう」と思って試してみたのですが なぜか[“AZURE_OPENAI_API_KEY”]という環境変数を読み込んでくれませんでした。 それで[“OPENAI_API_KEY”]という環境変数にAOAIのAPI KEYを入れたら動いてくれたので、今回はそういった実装にしてます。 ライブラリ側の問題なのか、自分のソースコードが問題なのか分からないですが、今回はそんなワークアラウンドで実装してます。 ascore関数 ascoreと呼ばれる関数にも変更が見られました。 Second is that metrics.ascore is now being deprecated in favor of metrics.single_score . You can make the transition as such とあるので、 ascore というメソッドが非推奨となり、そのかわり single_score を使ってくれ。ということです。 何のことかというと、以前書いたRagasの記事では、先程のようにevaluate()という関数を使って、複数のmetricsを一気に評価していました。 一方で、ascoreといったメソッドを使うことで、1つのデータに対して評価する方法も存在します。 このascoreという関数が0.2.xでは推奨されなくなり、 single_turn_ascore や multi_turn_ascore といった関数の使用が推奨されています。 このSingleやらMultiやらの話は後ほどしますので、とりあえず一旦使ってみます。 以下に実装のサンプルを載せます。 こちらのサンプルはとりあえず同期処理として single_turn_score を使っています。 os.environ["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") evaluator_llm = LangchainLLMWrapper(AzureChatOpenAI(     azure_deployment="gpt-4o-mini",     temperature=0, )) single_turn_sample = SingleTurnSample(     user_input="日本の首都はどこですか?", #質問     retrieved_contexts=["東京(とうきょう、英: Tokyo)は、関東平野の南部に位置し、東京湾に面する都市。日本の首都である."], #RAGが外部DBから取得し、参考にした内容     response="日本の首都は東京です.", #RAGから返された回答内容     reference="東京" #user_inputに対する真の答え ) faithfulness = Faithfulness(llm=evaluator_llm) metrics = [     Faithfulness(llm=evaluator_llm) ] result = faithfulness.single_turn_score(single_turn_sample) # score = 1.0 メトリクスの分類 先程single_turnやmulti_turnといったものが出てきましたので、これについて見ていきたいと思います。 そもそも今回メトリクスは 評価にLLMを利用するか SingleTurnか、MultiTurnか の2軸で分類され、合計4パターンで分類されます。 Ragasの 公式 にもメトリクスの分類が分かりやすくまとめてありました。 この分類に合わせ、実装を切り替える必要があります。 Faithfulnessのメトリクスを例に、定義を見てみたいと思います。 @dataclass class Faithfulness(MetricWithLLM, SingleTurnMetric):     name: str = "faithfulness"  # type: ignore と書かれています。 MetricWithLLMを継承しているため、このFaithfulnessの評価にはLLMが利用されることが分かります。 そのため、Faithfulnessのコンストラクタ引数としてはLLMを与えてあげる必要があります。 他にはMetricWithEmbeddingsを継承しているメトリクスもありますが これは評価の際にEmbeddingsモデルを利用することを表します。 また、FaithfulnessのはSingleTurnMetricというクラスも継承しています。 これはユーザーとAI間の1回のやり取り(Interaction)に基づき評価を行うことを表します。 SingleTurnMetricを継承しているMetricsに関しては single_turn_ascore や、 single_turn_score のメソッドを利用して評価を行います。 Agentの評価に用いるMetricsだとMulti Turnなものが多いかもしれないですね。 テストセット生成のコスト効率改善 テストセットの仕組みが変わったようなのですが、すいません、正直まだ理解しきれていません…。 どうやらKnowledge Graphを使うようになったりして、大幅にコスト削減できるようになったようです。 このあたりは別の機会にまた試してみたいと思います。 プロンプトオブジェクトの変更 最後、プロンプトオブジェクトの変更についてです。 まず、変更点を先に述べると0.1.xでは Prompt というオブジェクトが利用されていましたが  0.2.xでは PydanticPrompt というオブジェクトが使われるようになりました。 ただ恥ずかしながら、自分もこの変更点見るまではRagasにおける「プロンプト」といったものを認識しておらず 「Ragasの中でそんなプロンプトを意識するところあるの?」といった感じでした。 それでソースコードを見てみると、色々なところで使われてたので少しご紹介します。 先程のFaithfulnessの例を挙げます。 Faithfulnessのコンストラクタの中に PydanticPrompt で定義されたプロンプトオブジェクトが含まれていました。 class Faithfulness(MetricWithLLM, SingleTurnMetric):     name: str = "faithfulness"  # type: ignore     _required_columns: t.Dict[MetricType, t.Set[str]] = field(         default_factory=lambda: {             MetricType.SINGLE_TURN: {                 "user_input",                 "response",                 "retrieved_contexts",             }         }     )     nli_statements_message: PydanticPrompt = field(default_factory=NLIStatementPrompt) #←ここ!!     statement_prompt: PydanticPrompt = field(default_factory=LongFormAnswerPrompt) #←ここ!!     sentence_segmenter: t.Optional[HasSegmentMethod] = None     max_retries: int = 1     _reproducibility: int = 1 今回デフォルトで使われている NLIStatementPrompt と LongFormAnswerPrompt の2つについて、それぞれの中身を確認してみました。 英語かつ少々長いですが、一番分かりやすい点として instruction の文章を確認してみます。 instructionはいわばAIへの命令文です。 まずはNLIStatementPromptのほうから。 Your task is to judge the faithfulness of a series of statements based on a given context. For each statement you must return verdict as 1 if the statement can be directly inferred based on the context or 0 if the statement can not be directly inferred based on the context. 翻訳すると以下の感じです あなたの仕事は、与えられた文脈に基づいて一連の声明の忠実さを判断することです。各声明に対して、文脈に基づいて直接推論できる場合は1、文脈に基づいて直接推論できない場合は0の判決を返さなければなりません。 次に、LongFormAnswerPromptの方は以下の内容でした。 Given a question, an answer, and sentences from the answer analyze the complexity of each sentence given under ‘sentences’ and break down each sentence into one or more fully understandable statements while also ensuring no pronouns are used in each statement. Format the outputs in JSON. “質問、回答、および回答からの文が与えられた場合、’sentences’ にある各文の複雑さを分析し、各文を一つ以上の完全に理解可能なステートメントに分解してください。また、各ステートメントには代名詞を使用しないようにしてください。出力はJSON形式でフォーマットしてください。 これを見てると、Faithfulnessの算出方法が頭をよぎります。 Faithfulnessのスコア算出方法は、以下の2ステップです。 得られた回答(response)を分解 分解された回答のなかで外部から取得した情報(retrieved_contexts)から導かれた個数/step1で分解された数 まさに、STEP1に該当するのが LongFormAnswerPromp で、STEP2に該当するのが NLIStatementPrompt と分かります。 つまり、最終的なFaithfulnessの算出に必要な要素を、これらのプロンプトを使って算出していることが読み取れました。 このようにRagasの内部で評価を行う際にも、プロンプトエンジニアリングのテクニックは活用されていることが分かりました。 そして、もちろんこのプロンプトの内容を自分で書き換えること(=新たなPydanticPromptを作成し、置き換えること)も可能です。 ただ、LLMを評価するためのRagasの中で、評価するためのプロンプトを書き直すとなってくると、そのプロンプトが適切か、かみたいな話にもなってきますね… 一般的なソフトウェアのテストにおいても、「テストコードが正しいことはどうやって証明しますか?」といった議題が上がりますが それに似た、もしくはそれ以上にややこしい問題な気もします。 まとめ 今回はRagasの0.2.x系のバージョンアップ内容をさらっとおさらいしてみました。 おさらいする中で知らなかった事も多々あったので、そのあたりは改めて勉強して記事にしていきたいと思います。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【v0.2】Ragasのバージョンアップ内容のおさらい【Azure OpenAI Service】 first appeared on SIOS Tech. Lab .
アバター
はじめに こんにちはサイオステクノロジーの小野です。 前回 はOpenShiftにGPUを追加する方法について解説しました。今回はそのGPUをクラスタ内で利用する設定の方法を解説します。 また、GPUはいくつかの会社が作成していますが、多くのAI開発ライブラリが対応しているNVIDIA製のGPUの設定を行います。 OpenshiftでGPUを利用するためのオペレータ Node Feature Discovery (NFD) オペレータ クラスター内のノードのハードウェア機能やカーネル機能を自動的に検出し、それらの機能をラベルとしてノードに追加するオペレータです。これによりノードにGPUがあることを検出できます。NVIDIA GPUオペレータを利用するために必要なオペレータです。 NVIDIA GPU オペレータ NVIDIA GPUを搭載したサーバーでGPUリソースを管理し、活用できるようにするためのオペレータです。 Intel Device Plugins オペレータ Intelのハードウェア機能をOpenshiftクラスタに認識させるために使用されるオペレータです。IntelのGPUを利用する際はこのオペレータを使用してください。 AWSにおけるGPU利用設定手順 設定手順概要 これからAWSに構築したOpenshiftでNVIDIAのGPUを利用する方法を解説します。手順は以下の流れで進んでいきます。 NFDオペレータの設定 NFDオペレータの正常性確認 NVIDIA GPU オペレータの設定 NVIDIA GPU オペレータの正常性確認 GPUモニタリングの設定 前 提条件 OpenShift:4.17 構築する環境:AWS(amd64) リージョン:us-east-2 クラスター名:ocp-test AWSにNVIDIAのGPUノードを追加済み NFDオペレータの設定 NodeFeatureDiscoveryオペレータのインストール 最初にOperator > OperatorHubでNFDと検索します。 OperatorHubでNFDと検索 Node Feature Discovery Operatorが2つ存在するのでRed Hatと書かれている方を選択して、インストールを押します。 NFD Operatorの説明 インストール時の設定は何も変更せず、インストールを押します。 NFDのインストール設定 インストールが完了するまで待ちます。 ステータスがSucceededになったらインストール完了です。 NFDのステータスがSucceededになったらインストール完了 CRの設定 (NodeFeatureDiscovery) 続いてカスタムリソースの設定を行います。インストール済みOperatorの画面からNFDオペレータをクリックします。 NFDオペレータの詳細画面に遷移するので、提供されるAPIからNodeFeatureDiscoveryのインスタンスの作成を押します。 NFDの詳細 NFDの設定は何も変更せず、作成を押します。 NFDのカスタムリソース編集 作成が完了するまで待ちます。 ステータスが「Conditions: Available Upgradeable」となっていれば作成完了です。 カスタムリソースのステータスがConditions: Available Upgradeableなら作成完了 NFDオペレータ正常性確認 NFDオペレータの導入によって、GPUノードにGPUのラベルが付与されていることを確認します。 以下のコマンドを入力します。 $ oc describe node | egrep 'Roles|pci' | grep -v master Roles:              worker                     feature.node.kubernetes.io/pci-1d0f.present=true Roles:              worker                     feature.node.kubernetes.io/pci-10de.present=true                     feature.node.kubernetes.io/pci-1d0f.present=true Roles:              worker                     feature.node.kubernetes.io/pci-1d0f.present=true Roles:              worker                    feature.node.kubernetes.io/pci-1d0f.present=true NFDオペレータの導入が正常に行われたら、GPUが搭載されたノードに「pci-10de」というラベルが付与されていることが確認できます。 NVIDIA GPU オペレータの設定 NVIDIA GPU オペレータのインストール 次にNVIDIA GPU オペレータのインストールを行います。Operator > OperatorHubでNVIDIAと検索します。 OperatorHubでNVIDIAと検索 NVIDIA GPU Operatorを選択してインストールを押します。 NVIDIA GPU Operatorの説明 インストール時の設定は何も変更せず、インストールを押します。 NVIDIA GPU オペレータのインストール設定 インストールが完了するまで待ちます。 ステータスがSucceededになったらインストール完了です。 NVIDIA GPU オペレータのステータスがSucceededになったらインストール完了 CRの設定 (ClusterPolicy) 続いてカスタムリソースの設定を行います。インストール済みOperatorの画面からNVIDIA GPU オペレータをクリックします。 NVIDIA GPUオペレータの詳細画面に遷移するので、提供されるAPIからClusterPolicyのインスタンスの作成を押します。 NVIDIA GPU オペレータの詳細 ClusterPolicyの設定は何も変更せず、作成を押します。 ClusterPolicyのカスタムリソース編集 作成が完了するまで待ちます。少し時間がかかるので注意してください(10分前後)。 ステータスが「State: ready」となっていれば作成完了です。 カスタムリソースのステータスがState: readyなら作成完了 NVIDIA GPU オペレータの正常性確認 GPUが動作するかの正常性の確認を行います。今回は2種類の正常性確認を行います。 サンプルアプリ実行 GPUを利用してベクトルの加算を行うサンプルアプリを実行します。(参考: https://docs.nvidia.com/datacenter/cloud-native/openshift/latest/install-gpu-ocp.html#running-a-sample-gpu-application ) 以下のコマンドを実行してpodを作成します。 $ cat << EOF | oc create -f - apiVersion: v1 kind: Pod metadata: name: cuda-vectoradd spec: restartPolicy: OnFailure containers: - name: cuda-vectoradd image: "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0-ubi8" resources: limits: nvidia.com/gpu: 1 EOF pod/cuda-vectoradd created コンテナのログでサンプルアプリが動作していることを確認します。 $ oc logs cuda-vectoradd [Vector addition of 50000 elements] Copy input data from the host memory to the CUDA device CUDA kernel launch with 196 blocks of 256 threads Copy output data from the CUDA device to the host memory Test PASSED Done GPUの状態確認 GPUの状態を表示するコマンドを実行します。(参考: https://docs.nvidia.com/datacenter/cloud-native/openshift/latest/install-gpu-ocp.html#getting-information-about-the-gpu ) nvidia-gpu-operator プロジェクトに変更します。 $ oc project nvidia-gpu-operator Now using project "nvidia-gpu-operator" on server " https://api.ocp-test.cpawstest.ps.staging-test.sios.jp:6443 ". pod名を取得します。 $ oc get pod -owide -lopenshift.driver-toolkit=true NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nvidia-driver-daemonset-417.94.202410090854-0-n7xjw 2/2 Running 0 28m 10.130.2.9 ip-10-0-18-161.us-east-2.compute.internal <none> <none> 取得したpod内でnvidia-smiコマンドを実行します。GPUのメモリ使用量、使用率、温度が確認できます。 $ oc exec -it nvidia-driver-daemonset-417.94.202410090854-0-n7xjw -- nvidia-smi Mon Oct 28 08:36:36 2024 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 550.90.07 Driver Version: 550.90.07 CUDA Version: 12.4 | |-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 Tesla T4 On | 00000000:00:1E.0 Off | 0 | | N/A 26C P8 14W / 70W | 1MiB / 15360MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | No running processes found | +-----------------------------------------------------------------------------------------+ GPU のモニタリング設定 GPUの管理に必要なモニタリングの設定方法について説明します(参考: https://docs.nvidia.com/datacenter/cloud-native/openshift/latest/enable-gpu-monitoring-dashboard.html )。 GitHub の DCGM エクスポーター リポジトリから最新の NVIDIA DCGM エクスポーター ダッシュボードをダウンロードします。 $ curl -LfO https://github.com/NVIDIA/dcgm-exporter/raw/main/grafana/dcgm-exporter-dashboard.json % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 18114 100 18114 0 0 19498 0 --:--:-- --:--:-- --:--:-- 19498 namespaceにダウンロードしたファイルからconfigmapを作成します。 $ oc create configmap nvidia-dcgm-exporter-dashboard -n openshift-config-managed --from-file=dcgm-exporter-dashboard.json configmap/nvidia-dcgm-exporter-dashboard created configmapにラベルをつけて、管理者のコンソールでGPUのダッシュボードを確認できるようにします。 $ oc label configmap nvidia-dcgm-exporter-dashboard -n openshift-config-managed "console.openshift.io/dashboard=true" configmap/nvidia-dcgm-exporter-dashboard labeled 同様に開発者のコンソールでGPUのダッシュボードを確認できるようにします。 $ oc label configmap nvidia-dcgm-exporter-dashboard -n openshift-config-managed "console.openshift.io/odc-dashboard=true" configmap/nvidia-dcgm-exporter-dashboard labeled 作成されたリソースを表示し、ラベルがつけられていることを確認します。 $ oc -n openshift-config-managed get cm nvidia-dcgm-exporter-dashboard --show-labels NAME DATA AGE LABELS nvidia-dcgm-exporter-dashboard 1 90s console.openshift.io/dashboard=true,console.openshift.io/odc-dashboard=true コンソール画面のモニタリング > ダッシュボードに移動し、ダッシュボードのリストから「NVIDIA DCGM Exporter Dashboard」を選択します。 GPUの各種情報をコンソール画面でモニタリングできるようになりました。 GPUのモニタリング画面 最後に NFDオペレータとNVIDIAオペレータを導入することで、OpenShiftでGPUを取り扱えるようになりました。 これでようやくOpenShift AIを導入するための準備が完了しました。次回はいよいよOpenShift AIを導入する方法について解説したいと思います。 参考 NVIDIA GPU オペレータ: https://docs.nvidia.com/datacenter/cloud-native/openshift/latest/index.html Intel Device Plugins オペレータ: https://intel.github.io/intel-technology-enabling-for-openshift/development/device_plugins/README.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShiftのGPU設定の方法について first appeared on SIOS Tech. Lab .
アバター
こんにちは、 PS-SL アプリチーム新卒 1 年目の織田です。 今回はLLM開発向けのフレームワークであるLangChainのサンプルコードを作成してみました。 コチラ から参照できますので、よろしければご活用ください。 サンプルコードを作成した理由 LangChainは非常に多種多様な機能を提供しており、どこから触れば良いのか分からず困ってしまう方もいらっしゃると思います。 また、ネット上には既に多くの方がLangChainのサンプルコードをまとめていますが、その多くが古いバージョンのもので2024年現在は使えない、あるいは非推奨の機能を用いている場合があります。 また、私は業務上AzureOpenAIを利用することが多いのですが、サンプルコードの多くにOpenAI APIが用いられています。名前はほぼ同じなのですが、実際に利用する際には細かい違いがあり、修正の手間がとても煩わしいです。 そこで、今回はAzureOpenAIユーザ向けに2024年10月時点で利用可能な基本的な機能をサンプルコード化しました。 使用方法 今回はGithub上でコードを公開しているので、直接ダウンローしていただくかgit cloneをしてご利用ください。言語はPythonを用いているので、必要に応じてインストールをお願いします。(インストール手順もReadmeに記載済みです) また、先述の通りAzureOpenAI(AOAI)リソースが必要になりますので、アカウント発行やリソース作成なども必要に応じて実施してください。 GPTのバージョンによって使用できる機能に制限がありますが、その点も調査・補足してあります。 試用可能な機能 今回サンプルコード化した機能は各種AOAIリソースを呼び出すための初歩的なものや、 OSC広島 の際にキャッチアップを進めたコードなどが中心になります。 これらの機能は今後のバージョンアップに伴ってなるべく更新をかけていきたいと思います。また、より多くの機能をサンプルコード化できるよう頑張ります。   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post LangChainのサンプルコードを作ってみた first appeared on SIOS Tech. Lab .
アバター
こんにちは。サイオステクノロジー OSS サポート担当 山本 です。 今回も solr のお話です。 今回は前回まで使っていた demo をベースにして、フィールドの内容を変更した新しいコアを作ってみることで、コアを作る手順を確認しようかと思います。 ■おさらい:コア?フィールド? コアを作っていく前に、solr の基本的な部分の用語を再確認しておきましょう。 今回見る必要な範囲でいうと、大まかに以下のような感じです。 コア : 箱 (空間) のようなもの。一連の 設定の適用範囲 であり、また検索の際にはコアを指定して検索します。 ドキュメント :ユーザが登録したデータ。その コア の スキーマ で定義された フィールド に合わせた、 一連のデータの組 を1つの単位として登録されます。 フィールド : ドキュメント の構造を決定する要素。型 (数値か文字列か) や、必須であるかどうか、 解析を行うかどうか (また、その解析方法) などをフィールド毎に決定します。 スキーマ で設定します。 スキーマ : フィールド の名前や型や 解析方法 、フィールドで使用される型などの定義を行うための設定ファイル。 …これだけ言われてもピンと来ないかもしれませんので、この先やってみながら確認していきましょう。 ■コアを作る ということで新しいコアを作ってみます。 一つの solr で複数のコアを作ることができる ので、今回は前回までにも使用していたデモ用の環境にコアを追加してみます。 …と軽く言ってはみますが、 solr のコアを作るには準備が必要 です。コマンド一つでお手軽簡単!!とはいきません。 用意するファイルの数もそこそこあるので、今回はフィールドの内容を決定する スキーマファイル のみ作成し、他の必要なファイルはデモ用環境のコア “demo” のものを流用してコアを作っていきます。 ■デモ環境 (コンテナ) の起動 まずはベースとなる solr 環境として、公式コンテナイメージからデモ用の環境を作ります。 これは前回まででやったのと同じです。podman を導入して以下のコマンドを実行すれば OK ですね。 ## 前回の環境を消してしまっている場合 $ podman run -dt --name test-solr -p 8984:8983 solr solr-demo ## 前回の環境から続けて試す場合 $ podman start test-solr ブラウザを開いて以下の URL にアクセスし、管理画面が開けることを確認できたら一旦 OK です。 http://(IPアドレス or ホスト名):8984/solr ■スキーマファイルの作成 続いて、 今回のお話のキー である スキーマ を作成します。 スキーマは、 “managed-schema.xml” (または “schema.xml”) という名前の xml ファイル で定義していきます。 今回は日本語を扱う 2つのフィールド “test_1” “test_2” と、managed-schema.xml で最低限必要になるフィールドだけを持ったスキーマファイルを作ってみます。 適当なテキストエディタ (vi など) を使って、以下のような内容を持つ “ managed-schema.xml ” を作成してください。 <?xml version="1.0" encoding="UTF-8"?> <schema name="default-config" version="1.6"> <types> <fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/> <fieldType name="pdates" class="solr.DatePointField" docValues="true" multiValued="true"/> <fieldType name="plongs" class="solr.LongPointField" docValues="true" multiValued="true"/> <fieldType name="pdoubles" class="solr.DoublePointField" docValues="true" multiValued="true"/> <fieldType name="pint" class="solr.IntPointField" docValues="true"/> <fieldType name="plong" class="solr.LongPointField" docValues="true"/> <fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true"/> <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true"> <analyzer type="index"> <tokenizer name="standard"/> <filter ignoreCase="true" words="stopwords.txt" name="stop"/> <filter name="lowercase"/> </analyzer> <analyzer type="query"> <tokenizer name="standard"/> <filter ignoreCase="true" words="stopwords.txt" name="stop"/> <filter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> <filter name="lowercase"/> </analyzer> </fieldType> <!-- ここまで必須分 --> <!-- ここから独自フィールド用の設定 --> <fieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> <analyzer> <tokenizer mode="search" name="japanese"/> <filter name="japaneseBaseForm"/> <filter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> <filter name="cjkWidth"/> <filter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> <filter name="japaneseKatakanaStem" minimumLength="4"/> <filter name="lowercase"/> </analyzer> </fieldType> </types> <fields> <field name="_version_" type="plong" indexed="false" stored="false"/> <field name="id" type="string" multiValued="false" required="true" stored="true"/> <!-- ここまで必須分 --> <!-- ここから独自フィールド用の設定 --> <field name="test_1" type="text_ja"/> <field name="test_2" type="text_ja"/> </fields> <uniqueKey>id</uniqueKey> </schema> これでスキーマファイルの準備は OK です。 ■スキーマファイルの中身の基本的な見方 折角なので、今回のスキーマファイルの設定内容についても一部確認してみましょう。 まずざっくり見ると、 “<field>” と “<fieldType>” という要素を大量に定義してるなー、というのがわかるかと思います。 “<field>” 要素の方から確認してみましょう。 <fields> <field name="_version_" type="plong" indexed="false" stored="false"/> <field name="id" type="string" multiValued="false" required="true" stored="true"/> <!-- ここまで必須分 --> <!-- ここから独自フィールド用の設定 --> <field name="test_1" type="text_ja"/> <field name="test_2" type="text_ja"/> </fields> よくよく見てみると、 name 属性に今回作ると宣言していたフィールド名 “test_1” “test_2” を含むものがありますね。 お察しのとおり、 “<field>” 要素こそがこのスキーマの、つまりはこのスキーマを使うコアで扱えるフィールド を定義するための要素になります。 例えば、この行は “_version_” という名前のフィールドを定義しています。 <field name="_version_" type="plong" indexed="false" stored="false"/> ところで、<field> 要素の設定には name 属性の他に type 属性 が必ず含まれているのに気づくかと思います。 この “_version_” フィールドでは type は “plong” ですね。 ここで “<fieldType>” 要素に目を向けてみましょう。 <fieldType name="plong" class="solr.LongPointField" docValues="true"/> 探してみると、<fieldType> の中にはこのように name 属性が先の “plong” と同じ名前になっているものが存在しているはずです。 これは勿論偶然などではなく、”_version_” フィールドで使用される “plong” type がどんなものなのかを定義 するものになります。 実際にどんなものなのかはこの <fieldType> 要素の各属性を確認する必要がありますが、特に重要なのは class 属性です。 基本的に使用される class 属性の値については、 こちらのドキュメント を確認してください。例えば、ここで使用されている “solr.LongPointField” なら Long 値 (64bit 符号なし整数) ということになります。 もう一つ見てみましょう。”test_1″ “test_2” フィールドの設定部分です。 <field name="test_1" type="text_ja"/> <field name="test_2" type="text_ja"/> これらのフィールドで使用している type “text_ja” の定義を確認してみます。 <fieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> <analyzer> <tokenizer mode="search" name="japanese"/> <filter name="japaneseBaseForm"/> <filter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> <filter name="cjkWidth"/> <filter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> <filter name="japaneseKatakanaStem" minimumLength="4"/> <filter name="lowercase"/> </analyzer> </fieldType> ちょっと長いですが、これ全部で fieldType “text_ja” の定義になります。 これは 前回 に長々とお話しした、solr の 文字列解析 を行うための設定をしたものになります。 class 属性に “solr.TextField”、子要素に <analyzer> を設定することで、この fieldType が解析処理を行う対象であることを定義 できます。 解析時の処理内容としては、<analyzer> の子要素として処理の内容を上から順番に書いていきます。 上記の例の場合だと、tokenizer の後に “japaneseBaseForm”、”japanesePartOfSpeechStop”、……という順番でフィルタ処理を行う形になります。 <analyzer> の中身についての詳細は、 こちらのドキュメント を確認してください。 なお、今回作ったスキーマファイルは非常にコンパクトな内容です。 色々と設定されている例が見たい場合は、デモ環境のデフォルトコア demo のスキーマファイルを覗いてみるといいかもしれません。 ■必要になるディレクトリ作成とファイル配置 ではコア作成の準備の仕上げとして、ディレクトリを作成してファイルを配置していきます。 とりあえず今回はデモ環境のコンテナ内に入って操作していきます。 $ podman exec -it test-solr /bin/bash まず、 環境変数 “ SOLR_HOME ” で設定されている solr のホームディレクトリ (デモ環境では “/var/solr/data/” になっているはずです) に、新しいコア用のディレクトリを作成します。 ここで作成する ディレクトリ名 がそのまま 新しいコアのコア名 になります。今回は “test-new-core” というコア名にしてみます。 (※コンテナ内での操作) $ mkdir /var/solr/data/test-new-core 続いて、必要になるファイルをこのディレクトリに配置していきます。 先述のとおり、今回は managed-schema.xml 以外はデモ環境 “demo” から流用するので、流用するファイルをコピーしていきます。 (実際に運用する環境を構築する際には、これらのファイルもコピーではなくちゃんと確認して設定しましょう。特に solrconfig.xml や solr.xml など) (※コンテナ内での操作) $ mkdir /var/solr/data/test-new-core/data $ mkdir /var/solr/data/test-new-core/conf $ mkdir /var/solr/data/test-new-core/conf/lang $ cp /var/solr/data/demo/core.properties /var/solr/data/test-new-core/ $ cp /var/solr/data/demo/conf/solrconfig.xml /var/solr/data/test-new-core/conf/ $ cp /var/solr/data/demo/conf/stopwords.txt /var/solr/data/test-new-core/conf/ $ cp /var/solr/data/demo/conf/synonyms.txt /var/solr/data/test-new-core/conf/ $ cp /var/solr/data/demo/conf/lang/stoptags_ja.txt /var/solr/data/test-new-core/conf/lang/ $ cp /var/solr/data/demo/conf/lang/stopwords_ja.txt /var/solr/data/test-new-core/conf/lang/ (※ コンテナ内の操作終わり) $ exit 最後に、作成した managed-schema.xml を配置すればファイルの配置は完了です。 $ podman cp ./managed-schema.xml test-solr:/var/solr/data/test-new-core/conf/managed-schema.xml ■コア作成の実行 必要な各種ファイルの配置ができたら、コア作成を実行します。 コマンドからでも Web の管理画面からでもコアは作成できます が、今回は Web の管理画面で追加する方法を見ていきます。 まずは適当なブラウザから管理画面にアクセスします。今回のコンテナの実行方法なら以下のアドレスですね。 http://(IPアドレス or ホスト名):8984/solr 管理画面にアクセスできたら、画面左メニューから “ Core-Admin ” を開きます。 “Add Core” から、”name” と “instanceDir” に 先の手順で作成した コア用のディレクトリと同じ名前 に変更して “Add Core” ボタンで… 新しいコアが登録できました。 画面左メニューの “Core Selector” プルダウンにも、新しいコアが出てくるようになっているはずです。 ■ドキュメントの登録と検索 新しくコアを作れたので、このコアを使って基本的なドキュメントの登録や検索の方法も確認しましょう。 ■ドキュメントの登録 ドキュメントの登録は、 Web 管理画面 または curl などを用いた直接のリクエスト により、 xml や JSON などの形式の ファイル または文字列の直接入力によって行うことができます。 今回は管理画面から xml ファイルを使って登録する方法を確認していきます。 まずは以下のような xml ファイルを作りましょう。(“<field> ” の中身はお好みの内容で OK です。) <add> <doc> <field name="test_1">サイオステクノロジー株式会社</field> <field name="test_2">SIOS Tech.Lab</field> </doc> <doc> <field name="test_1">OSSのsolrを試しています</field> <field name="test_2">ドキュメントの登録</field> </doc> <doc> <field name="test_1">これらの "doc" 内の "field" 要素は</field> <field name="test_2">スキーマで定義したフィールドに合わせて作りましょう</field> </doc> <doc> <field name="test_1">サンプルドキュメント</field> <field name="test_2">サンプルのドキュメント</field> </doc> <doc> <field name="test_1">OSSよろず相談室</field> <field name="test_2">some document</field> </doc> </add> 続いて、管理画面を開いて画面左メニューの “Core Selector” プルダウンから先ほど作ったコア名を選択し、” Documents ” を開きます。 “ Document Type ” で “ File Upload ” を選択したら、” Document(s) ” で先に作った xml ファイルを選択して “ Submit Document ” を押下すれば OK です。 ■ドキュメントの検索 続いて登録したドキュメントを検索してみましょう。 前々回もやった内容なので、ざっくりいきます。 まずは管理画面から登録に成功しているか確認してみます。 画面左メニュー “Core Selector” で先ほどのコア名を選択した状態で “ Query ” 画面を開き、 画面下 の “ Execute Query ” ボタンを押下します。 すると、登録したドキュメントが表示されるはずです。 この画面の “ q ” に、例えば “test_2:ドキュメント” や “test_2:ドキュメント AND test_1:OSS” などのように “ (フィールド名) : (検索文字列) ” という形式で条件を指定することで、検索条件を指定してドキュメントを表示させることもできます。 また、以下のような形式でアドレスに直接リクエストを行うことで、ドキュメントを取得することもできます。 http://(IPアドレス or ホスト名):(ポート)/solr/(コア名)/select?q=(条件) 例えば、curl を使って今回作った環境のドキュメントを取得すると以下のようになります。 ※ 記号や全角文字は URL エンコードする必要があります 。 $ curl 'http://(IP アドレス or ホスト名):8984/solr/test-new-core/select?q=test_1%3AOSS%20AND%20test_2%3Asome' { "responseHeader":{ "status":0, "QTime":2, "params":{ "q":"test_1:OSS AND test_2:some" } }, "response":{ "numFound":1, "start":0, "numFoundExact":true, "docs":[{ "id":"0fa6bbf2-b548-4933-b2de-107eebaea887", "test_1":"OSSよろず相談室", "test_2":"some document", "_version_":1814150309105106944 }] } } ■最後に 今回は solr に新しいコアを追加する手順を確認してみました。 今回はスキーマファイルのみ自作し、他の必要ファイルはデモ環境から流用するという実験用の手順大幅削減アプローチでやってみましたが、それでも確認すべきことは結構ありましたね。 勿論、今回流用した部分や見なかった部分にも確認すべき内容は多数あり、気軽に使うにはやや敷居が高いと感じるところはあります。 ただ、solr には活用することでより検索の利便性を向上させる機能がまだまだありますので、次回はそのうちの一つを紹介してみたいと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Solr って何者?③:コアを作ってみる first appeared on SIOS Tech. Lab .
アバター
はじめに こんにちはサイオステクノロジーの小野です。 前回 はOpenShift AIの概要について簡単に説明しました。今回はOpenShiftのノードの追加方法について解説します。OpenShift AIを利用するためには、GPUノードを追加する必要があるのでしっかりと操作を覚えましょう。 OpenShift(AWS)について OpenShiftはAmazon Web Services、Google Cloud Platform、IBM Cloud、Microsoft Azure のクラウド、vSphereなど多くのプラットフォーム上に簡単に構築することができます。AWS上で構築する際はEC2にノードがデプロイされるので、幅広いスペックを選べたり、簡単にサーバー移行が可能であったりといったメリットがあります。したがって、今回はAWS上にOpenShiftを構築してノードを追加します。 ノードの種類 マスターノード(コントロールプレーンノード) Kubernetesクラスターの管理と制御を行う役割を持つノードです。Kubernetesの特徴である負荷分散や高可用性はマスターノードによって管理されます。 ワーカーノード コンテナ化されたアプリケーションが動作するノードです。 インフラノード ルーティングやロギング、モニタリングなどのインフラストラクチャサービスを実行するために専用で用意するノードです。ワーカーノードと分けることでワーカーノードが落ちた場合やアップデートする場合にインフラを保つことができます。ちなみにインフラノードという用語はOpenShiftのドキュメントではよく出てきますが、Kubernetesのドキュメントには登場しません。 ノードの管理 マシンセット (MachineSet) 定義された数の同一のマシン(ノード)を保持し、管理するためのリソースです。マシンセットは、特定の設定を持つマシン(ノード)のレプリカを作成し、所望のレプリカ数を維持します。マシンセットは、ノードのスケーリングや自動修復(失敗したノードの置き換え)を行うために使用されます。 マシンコンフィグ(MachineConfig) マシンコンフィグはマシンの構成を定義します。 マシンコンフィグを使用することでクラスター内のノードに対して一貫した構成を適用できます。 マシンコンフィグプール (MachineConfigPool) マシンコンフィグプールは、特定のマシンコンフィグを適用するノードのグループを定義します。 マシンコンフィグプールを使用すると、異なるタイプや設定を持つノードの集まりをより簡単に管理できます。例えば、一部のノードはGPUを搭載しているが、他のノードは搭載していない、といった場合に便利です。 AWSでのノードの追加手順 OpenShiftのノード追加の方法についてこれから解説します。マシンセットを設定することで簡単にノードの追加が可能です。なお、今回行う手順(高いインスタンス等を設定)では高額な利用料金が発生する場合があるのでご注意ください。 前提条件 OpenShiftをIPIで構築した直後の状態から操作します。 OpenShift:4.17.1 構築する環境:AWS(amd64) リージョン:us-east-2 クラスター名:ocp-test cluster-admin権限があるユーザ操作 マシンセットの確認 コンソール画面のコンピュート > MachineSetsに移動します。 3つのマシンセットが存在することを確認します。 新規マシンセットの作成 MachineSetの作成を押します。 Red Hatのドキュメントに載っている サンプル を用いてマシンセットを作成します。 apiVersion: machine.openshift.io/v1beta1 kind: MachineSet metadata: labels: machine.openshift.io/cluster-api-cluster: <infrastructure_id> name: <infrastructure_id>-<role>-<zone> namespace: openshift-machine-api spec: replicas: 1 selector: matchLabels: machine.openshift.io/cluster-api-cluster: <infrastructure_id> machine.openshift.io/cluster-api-machineset: <infrastructure_id>-<role>-<zone> template: metadata: labels: machine.openshift.io/cluster-api-cluster: <infrastructure_id> machine.openshift.io/cluster-api-machine-role: <role> machine.openshift.io/cluster-api-machine-type: <role> machine.openshift.io/cluster-api-machineset: <infrastructure_id>-<role>-<zone> spec: metadata: labels: node-role.kubernetes.io/<role>: "" providerSpec: value: ami: id: ami-046fe691f52a953f9 apiVersion: machine.openshift.io/v1beta1 blockDevices: - ebs: iops: 0 volumeSize: 120 volumeType: gp2 credentialsSecret: name: aws-cloud-credentials deviceIndex: 0 iamInstanceProfile: id: <infrastructure_id>-worker-profile instanceType: m6i.large kind: AWSMachineProviderConfig placement: availabilityZone: <zone> region: <region> securityGroups: - filters: - name: tag:Name values: - <infrastructure_id>-worker-sg subnet: filters: - name: tag:Name values: - <infrastructure_id>-private-<zone> tags: - name: kubernetes.io/cluster/<infrastructure_id> value: owned - name: <custom_tag_name> value: <custom_tag_value> userDataSecret: name: worker-user-dataname: worker-user-data サンプルの変更点 基本的には既存のマシンセットを参考にして入力してください。 <infrastructure_id>:<クラスター名>-<ランダム文字列> infrastructure_idは以下のコマンドで確認するか、既存のマシンセットのyamlを見て確認してください。 $ oc get infrastructure cluster -o jsonpath='{.status.infrastructureName}' ocp-test-sp9lv <role>:worker <region>:us-east-2 <zone>:us-east-2a(リージョンとは別なので注意) metadata.name:マシンセットの名前(サンプルの通りに設定すると既存のマシンセットの名前と被ってエラーが出るので注意) instanceType:g4dn.xlarge(今回はGPUノードを追加することを考えるのでGPU用のインスタンスタイプを選択) securityGroupsのfliters:’tag:Name’ securityGroupsのvalues:<infrastructure_id>-node, <infrastructure_id>-lb(2つ設定する) ami.id:ami-048d893cb41cbd3cf(インスタンスタイプに対応したAMI) subnetのvalues:<infrastructure_id>-subnet-private-<zone> 変更後のyaml apiVersion: machine.openshift.io/v1beta1 kind: MachineSet metadata: labels: machine.openshift.io/cluster-api-cluster: ocp-test-sp9lv name: ocp-test-sp9lv-worker-us-east-2a-gpu namespace: openshift-machine-api spec: replicas: 1 selector: matchLabels: machine.openshift.io/cluster-api-cluster: ocp-test-sp9lv machine.openshift.io/cluster-api-machineset: ocp-test-sp9lv-worker-us-east-2a template: metadata: labels: machine.openshift.io/cluster-api-cluster: ocp-test-sp9lv machine.openshift.io/cluster-api-machine-role: worker machine.openshift.io/cluster-api-machine-type: worker machine.openshift.io/cluster-api-machineset: ocp-test-sp9lv-worker-us-east-2a spec: metadata: labels: node-role.kubernetes.io/<role>: "" providerSpec: value: ami: id: ami-048d893cb41cbd3cf apiVersion: awsproviderconfig.openshift.io/v1beta1 blockDevices: - ebs: iops: 0 volumeSize: 120 volumeType: gp2 credentialsSecret: name: aws-cloud-credentials deviceIndex: 0 iamInstanceProfile: id: ocp-test-sp9lv-worker-profile instanceType: g4dn.xlarge kind: AWSMachineProviderConfig placement: availabilityZone: us-east-2a region: us-east-2 securityGroups: - filters: - name: 'tag:Name' values: - ocp-test-sp9lv-node - filters: - name: 'tag:Name' values: - ocp-test-sp9lv-lb subnet: filters: - name: tag:Name values: - ocp-test-sp9lv-subnet-private-us-east-2a tags: - name: kubernetes.io/cluster/ocp-test-sp9lv value: owned userDataSecret: name: worker-user-data マシンセットの作成 サンプルの変更が完了したものを入力して作成を押します。 マシンセットが作成されたら、マシンの作成が始まるのでしばらく待ちます。 マシンセットのデプロイ 作成したMachineSetのMachineのメッセージで「Machine successfully created」が表示されたらマシン作成完了です。 作成したMachineSetのMachinesタブに移動して作成したMachineの欄にノードが表示されていて、ノードのステータスがReadyになっていればノードの追加完了です。 AWS画面での確認 AWSコンソールにログインし、リージョンをus-east-2に設定した後、EC2 > インスタンスのページを開きます。 OpenShiftのマシンセットを作成することで、 自動的にEC2のインスタンスが作成されていることが確認できます。 [画像] 注意事項 AMIのアーキテクチャがx86_64であるかarm64であるかによって使えるインスタンスタイプが変わるので注意してください。 AMIのアーキテクチャ確認 $ aws ec2 describe-images --image-ids ami-048d893cb41cbd3cf --query "Images[*].{Architecture:Architecture}" [ { "Architecture": "x86_64" } ] インスタンスタイプが対応しているアーキテクチャ確認 $ aws ec2 describe-instance-types --region us-east-2 --instance-types g4dn.xlarge --query "InstanceTypes[*].ProcessorInfo.SupportedArchitectures" [ [ "x86_64" ] ] AMIの起動モードがUEFIであるかlegacy-biosであるかによっても使えるインスタンスタイプが変わるので注意してください。 AMIの起動モード確認 $ aws ec2 describe-images --image-ids ami-048d893cb41cbd3cf --query "Images[*].BootMode" [ "legacy-bios" ] インスタンスタイプの対応している起動モード確認 $ aws ec2 describe-instance-types --region us-east-2 --instance-types g4dn.xlarge --query "InstanceTypes[*].SupportedBootModes" [ [ "legacy-bios", "uefi" ] ] 最後に AWS上にOpenShiftを構築してマシンセットを作成することで、GPUノードの追加ができました。以上の手順を参考にしてノード追加を行ってみてください。 最後に重要な注意事項として、GPUノードを追加しましたが、今の段階だとまだGPUがノードに認識されていません。したがってGPUを用いて機械学習を行うことができません。次回はノードにGPUを認識させるためにNode Feature Discovery OperatorとNVIDIA Operatorを導入する方法について解説します。お楽しみに。 参考 AWSインスタンスの料金表: https://aws.amazon.com/jp/ec2/instance-types/ アーキテクチャごとのAMIの設定: https://github.com/openshift/openshift-docs/blob/main/modules/installation-aws-user-infra-rhcos-ami.adoc https://b.chiroito.dev/entry/2020/04/23/173356 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift(AWS)へのノード追加 first appeared on SIOS Tech. Lab .
アバター
CI/CD の導入は現代のアプリケーション開発において不可欠な要素となっています。 前回の記事 では、CI 部分を担う OpenShift Pipelines について解説しました。続いて、本記事では CD 部分を担う OpenShift GitOps について解説します。 CI/CD について 再度の記載になりますが、Continuous Integration / Continuous Delivery の略称で、継続的インテグレーション&継続的デリバリーという意味です。具体的に CI と CD が何を指すかというと以下の通りです。 CI は、ビルドとテスト等を自動化させることを指します。コード変更がメインブランチにマージされるたびに自動ビルドとテストが行われ、問題を早期に検出して対処することができます。 CD は、CI のプロセスをさらに拡張し、アプリケーションを自動的にリリース準備段階まで(継続的デリバリー)または本番環境にデプロイ(継続的デプロイメント)することを目指します。 前回の記事で解説した OpenShift Pipelines は CI 部分を担っていました。OpenShift Pipelines でも CD 部分は実装が可能ですが、Push 型のデプロイになってしまいました。OpenShift GitOps では開発環境や本番環境の状態を検知して、あるべき状態に変更する Pull 型の実装が可能なため、CI と CD は分離して CD 部分は OpenShift GitOps で実装すると様々なパターンに対して柔軟に対応できます。分離した構成図の例が下記になります。CI と CD が独立していますが、一つの CI/CD パイプラインとして動作可能です。 GitOps とは? GitOps とは、DevOps の概念をインフラ管理に適用した考え方です。Git リポジトリ内のマニフェストを正の状態としてインフラとアプリの状態を Git リポジトリと同期させる手法で、インフラストラクチャのコード化(Infrastructure as Code)と CI/CD を組み合わせたものになります。マニフェストを正の状態とすることで、 OpenShift 上のリソースが誤って削除された場合などに、Git リポジトリと同期してリソースを復元できたりもします。GitOps は大規模な共同作業が可能ですが万能なものではなく、直接環境を編集する場合に比べると、プルリクエストの作成やその承認などのプロセスは増えてしまいます。 OpenShift GitOps とは? Argo CD をベースにしており、Git リポジトリに格納されたマニフェストファイルを元に OpenShift のリソースを管理します。クラスタの状態を更新したい時は Git リポジトリに変更を加えるだけで自動的に更新することが出来ます。これによって、開発、ステージング、本番環境など異なる環境のクラスターへアプリケーションをデプロイする際に、一貫性を保ちながら効率化を図ることが出来ます。CD 部分以外にもデプロイメントと Kubernetes リソースの可視化などを実現できる点も利点となっています。 ベースとなっている Argo CD については 初心者でもわかる!Argo CDとは? という記事でデモまで行っているので、読んでもらえると動作のイメージをつかめると思います。 その他の CD ソリューションについて Spinnaker Spinnaker は、マルチクラウド環境でのアプリケーションデプロイが可能です。AWS、Google Cloud Platform、Azure など様々なクラウドプラットフォームに対応しており、柔軟なパイプライン構築や複雑なデプロイメント戦略にも対応しています。しかし、GUI で更新差分を見ることが出来ないため、直感的な見やすさでは ArgoCD に劣ります。 GitLab CI/CD GitLab リポジトリに統合されたCD ソリューションです。コードの変更をトリガーとして自動的にビルド、テスト、デプロイを行います。セルフホスト型とクラウド型の両方が利用可能で、多様な運用環境に対応しています。ArgoCD とは異なり、ソース管理と CI/CD が統合されており、一貫した管理が可能です。GitLab 以外のソース管理システムとの統合が難しい点が ArgoCD との違いになります。 まとめ CI/CD の導入は現代のアプリケーション開発において不可欠な要素となっており、更に関連技術で GitOps などの様々な概念も生まれています。本記事では CI/CD の振り返りと GitOps、 OpenShift GitOps について解説しました。次の記事では実際に OpenShift Pipelines の導入を行っていきたいと思います。 参考文献 https://www.redhat.com/ja/technologies/cloud-computing/openshift/gitops https://www.redhat.com/ja/topics/devops/what-is-gitops https://github.com/mamoru1112/openshift-gitops-handson https://spinnaker.io/ https://media.colorfulpalette.co.jp/n/n934459568564 https://gitlab-docs.creationline.com/ee/ci/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Red Hat OpenShift GitOps とは? first appeared on SIOS Tech. Lab .
アバター
はじめに 皆さんこんにちは。エンジニアの細川です。 皆さんはTypeScriptで開発を行っていたときに、型の特定のプロパティだけ必須にしたいと思ったことはありませんか? 例えば以下のようなHuman型を考えてみます。 type Human = { name: string; age: number; phoneNumber?: number email?: string; } このHuman型のphoneNumberを必須にした型をが欲しいときに、いちいち以下のように全プロパティを定義しなおすのは面倒です。 type HumanRequiredPhoneNumber = { name: string; age: number; phoneNumber: number email?: string; } このような場合に利用できるUtility型の作り方を紹介します。 指定したプロパティを必須にするユーティリティ型を作成 ある型の特定のプロパティを必須にするには以下のようなユーティリティ型を用意します。 /** * Tのうち、Kで指定されたプロパティを必須にする */ type MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>; 使い方は以下の通りです。 先ほどと同じようにHuman型のphoneNumberを必須にしたい場合は以下のように書きます。 type HumanRequiredPhoneNumber = MakeRequired<Human, "phoneNumber"> このように第1引数に型名、第2引数に必須化したいプロパティ名を書くことで、以下のようにphoneNumberが必須になっていることを確認できます。 また、emailも必須にしたい場合は以下のように定義すればOKです。 type HumanRequired = MakeRequired<Human, "phoneNumber" | "email"> こうすると、phoneNumberに加えてemailも必須にすることができます。 null許容も除外したい場合 上記の型を利用すればoptionalなプロパティを必須にできるのですが、場合によってはnull許容のプロパティを必須にしたい場合もあるかと思います。 以下のような Human 型から HumanRequiredNotNull 型を作るような場合を考えます。 type Human = { name: string; age: number; phoneNumber?: number | null; email?: string | null; } ↓ type HumanRequiredNotNull = { name: string; age: number; phoneNumber: number; email: string } この場合は以下のようなユーティリティ型を用意します。 /** * Tのうち、Kで指定されたプロパティを必須にし、nullを除去する */ type MakeRequiredNonNullable<T, K extends keyof T> = Omit<T, K> & Required<{ [P in K]: NonNullable<T[P]> }>; 使い方は先ほどと同様に一つもしくは複数のプロパティを指定して、必須かつnull許容では無いプロパティにすることができます。 type HumanRequiredNotNull = MakeRequiredNonNullable<Human, "phoneNumber" | "email"> 実装してみると以下のようにエラーが出るようになります。 まとめ オプショナルなプロパティを必須にしたい場合は以下 /** * Tのうち、Kで指定されたプロパティを必須にする */ type MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>; // 利用する場合 type HumanRequired = MakeRequired<Human, "phoneNumber" | "email"> const taro: HumanRequired = { name: "taro", age: 20, phoneNumber: 00000000000, email: "xxx@xxx.com" } null許容かつオプショナルなプロパティを必須にし、nullを除外したい場合は以下 /** * Tのうち、Kで指定されたプロパティを必須にし、nullを除去する */ type MakeRequiredNonNullable<T, K extends keyof T> = Omit<T, K> & Required<{ [P in K]: NonNullable<T[P]> }>; // 利用する場合 type HumanRequiredNotNull = MakeRequiredNonNullable<Human, "phoneNumber" | "email"> const taro: HumanRequiredNotNull = { name: "taro", age: 20, phoneNumber: 00000000000, email: "xxx@xxx.com" } おわりに 今回は既存の型の特定のプロパティのみを必須にする型を紹介しました。 パッケージなどによって作られる型などは特に再定義するのが面倒なことも多いと思うので少しでも皆さんの役に立てば幸いです。 ちなみに紹介した型の中で利用している、OmitやRequiredなどは事前にTypeScriptに用意されているユーティリティ型です。便利なものも多いので気になる方は こちら でどんな型があるか調べてみてください。 他にもTypeScriptのあれこれを紹介していますので、ぜひ 他の記事 も見てみてください!     ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post TypeScriptのあれこれ⑦ 型の特定のプロパティだけ必須化したい! first appeared on SIOS Tech. Lab .
アバター