TECH PLAY

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

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

621

こんにちは PS SLの佐々木です。 今回SBOMの導入ガイドをリリースしたので紹介させてください。 SBOM導入ガイドでは私のいるチームで1年間SBOMに関する調査検証をした中で、事前に整理をしておきたかったポイントや観点、導入にあたって悩ましかったポイントなどを整理し、スムーズにSBOMを導入するためのガイドになっています。 是非SBOMの導入を考えている方に読んでいただきたいと思います。 SBOMとは? 近年、ソフトウェアのサプライチェーン管理の重要性がますます高まっています。その中で注目されているのが SBOM(Software Bill of Materials) です。 SBOMは、ソフトウェアを構成するすべてのコンポーネントのリストを明示し、ソフトウェアの透明性を向上させる役割を果たします。特に、セキュリティリスクの特定やライセンス管理の観点で、多くの企業がSBOMの導入を進めています。 なぜSBOMが重要なのか? 脆弱性管理の強化 :使用しているソフトウェアコンポーネントの脆弱性を素早く把握できる。 ライセンスコンプライアンスの向上 :不適切なライセンス使用を防ぐために、すべてのコンポーネントのライセンスを確認可能。 ソフトウェアサプライチェーンの透明性 :外部提供ソフトウェアの構成を把握し、サイバー攻撃対策を強化。 SBOM導入ガイドの概要 今回、SBOMの基礎から導入方法までを詳しく解説した 「SBOM導入ガイド」 を無料でダウンロードできるようにしました! 本書は、以下のような方々に最適な内容となっています。 SBOMの基礎を学びたい方 ソフトウェアサプライチェーンの管理に関心がある方 実際にSBOMを導入しようと考えている開発者やセキュリティ担当者 本ガイドのポイント SBOMの基本概念を解説 SBOMの導入ステップを具体的に紹介 SBOMを運用する際の注意点やアンチパターンを解説 ダウンロードはこちら SBOM導入ガイドを読んで、ソフトウェアサプライチェーンの透明性とセキュリティを向上させましょう! [ダウンロードリンク] (https://mk.sios.jp/sbom-first-guide-form) [プレスリリース] (https://sios.jp/news/press/2025/20250408-sbom.html) ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post SBOM導入ガイド公開しました! first appeared on SIOS Tech. Lab .
はじめに こんにちはサイオステクノロジーの小野です。今回はOpenShift AIのモデルレジストリ機能について解説します。この機能を利用することで、モデルの各種情報を整理することができ、管理がしやすくなります。 モデルレジストリは2025年4月4日現在テクノロジープレビューです。この機能はサポート対象外であることと、製品版では変更される可能性があることに注意してください。 モデルレジストリ モデルレジストリはMLOpsにおける機械学習モデルの数々のメタデータを保持する機能です。この機能により、モデルのバージョン管理を行うことができるため、実験を再現したり、モデルの追跡を行ったり、簡単にモデルのデプロイを行えたりします。 以下の内容をモデルまたはそのバージョンごとに登録することが可能です モデルのS3ストレージ保管場所 モデルソースのフォーマット モデルのバージョン モデルの所有者 最終変更タイムスタンプ 説明文 ラベル プロパティ モデルレジストリ構築方法 前提条件 導入Operator Red Hat Authorino Operator Red Hat OpenShift Serverless Operator Red Hat OpenShift Servicemesh Operator Red Hat OpenShift AI Operator バージョン 2.14以上 S3ストレージにモデルを保存済み OpenShift AI構築済み OpenShift AIの構築は以前の記事を参考にしてください OpenShift AI を導入してみた DataScienceClusterを作成する際に、modelregistryコンポーネントをManagedにします。 DataScienceClusterのmodelregistryコンポーネントをManagedにする OpenShift AIの管理者権限を持つ OpenShift AI Operatorインストール時に作成されるグループにOpenShift AIにログインするユーザーを追加してください。 rhods-adminsグループに管理者権限を持たせるユーザーを追加する DB作成 モデルレジストリに登録するメタデータはDBに保存されます。そのため、最初にDBを作成します。 以下のyamlでリソースを作成してください。モデルレジストリ用のnamespaceのrhoai-model-registriesにMySQLのコンテナを作成します。MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORDの環境変数は各自設定してください。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: rhoai-model-registries spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: ConfigMap metadata: name: mysql-config namespace: rhoai-model-registries data: my.cnf: | [mysqld] default_authentication_plugin=mysql_native_password --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql namespace: rhoai-model-registries spec: selector: matchLabels: app: mysql replicas: 1 template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD value: <MySQLのルートパスワード> - name: MYSQL_DATABASE value: <MySQLのデータベース> - name: MYSQL_USER value: <MySQLのユーザー名> - name: MYSQL_PASSWORD value: <MySQLのパスワード> ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql - name: mysql-config-volume mountPath: /etc/mysql/my.cnf subPath: my.cnf volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pvc - name: mysql-config-volume configMap: name: mysql-config --- apiVersion: v1 kind: Service metadata: name: mysql namespace: rhoai-model-registries spec: ports: - port: 3306 targetPort: 3306 selector: app: mysql mysqlのリソースを作成する mysqlというDeploymentsによりpodがrhoai-model-registries内に作成されます。 リソースを作成するとmysqlのpodが作成される モデルレジストリ設定 DBの作成が完了したら、モデルレジストリの設定を行います。OpenShift AIに管理者権限を持っているアカウントでOpenShift AIにログインします。 Setting > Model Registry Settingsを開きます。 Setting > Model Registry Settingsを開く Create model registryを押下すると設定画面が表示されるので以下のように設定します: Name:モデルレジストリ名 Resource Name:モデルレジストリ名と同じ Connect to external MySQL database Host:mysqlのホスト名(yamlと同じ設定の場合mysql) DBが rhoai-model-registries とは異なる namespace で実行されている場合は、ホスト名を <host name>.<namespace>.svc.cluster.local 形式で入力します。 Port:mysqlのポート番号(yamlと同じ設定の場合3306) Username:MYSQL_USERに設定したユーザー名 Password:MYSQL_PASSWORDに設定したパスワード Database:MYSQL_DATABASEに設定したデータベース名 モデルレジストリを作成する モデルレジストリのStatusがAvailableになれば作成完了です。 StatusがAvailableになれば作成完了 モデルの登録 モデルレジストリの作成が完了すると、左のメニューのModel Registryからモデルの登録ができるようになります。 メニューのModel Registryからモデルの登録を行う Registry modelを押下するとモデルの登録ができます。各パラメータは以下のように設定します: Model details:モデル名 Version details:登録するモデルのバージョンとモデルの形式情報 Model location:モデルが保存されているS3オブジェクトストレージの接続情報 モデルの登録設定 登録が完了するとモデル名とVersionsの欄に登録したモデルのバージョンが表示されます。 登録するとモデルのバージョンが表示される 登録したバージョンを開くと登録した際に入力したメタデータが閲覧できます。 モデルのメタデータの閲覧 Description、Labels、Propertiesもここで編集できます。 Description、Labels、Propertiesも編集可能 新しいバージョンの登録 レジストリにモデルの新しいバージョンを登録するには、登録したモデルの画面からRegister new versionを押下します。 Register new versionから新しいバージョンの登録を行える モデルの登録したときと同じように新しいバージョン名と新しいモデルのS3の接続情報を入力します。 新しいバージョンのモデル情報を登録する 入力すると、モデルの新しいバージョンの登録ができます。 新しいバージョンが追加される モデルのデプロイ モデルレジストリを利用することで、登録したモデルのデプロイを行うことができます。 登録したモデルのバージョンの詳細画面のActionsからDeployを選択します。 ActionsのDeployからモデルデプロイを行える モデルをデプロイするデータサイエンスプロジェクトを選択して、デプロイ設定を行います。設定方法は以前の記事を参考にしてください。 OpenShift AIにLLMをデプロイしてみた モデルデプロイ設定 バージョンのDeplymentsの欄にデプロイしたモデル名が表示され、Statusに がつけばデプロイ完了です。 Statusに がつけばデプロイ完了。ここからモデルAPIのエンドポイントを取得できる。 モデルのアーカイブ モデルをアーカイブするには、バージョンの詳細画面のActionsからArchive model versionを選択します。 ActionsのArchive model versionからモデルのアーカイブができる バージョン名を入力すればアーカイブできます。 バージョン名を入力するとモデルをアーカイブできる アーカイブ完了 モデルの復元 アーカイブしたモデルを復元することが可能です。モデルのVersionsの三点メニューを開いて、View archived versionsを選択します。 三点メニューのView archived versionsからアーカイブしたモデルのバージョン一覧を表示できる アーカイブしたモデルバージョンの一覧が表示されるので、復元したいバージョンのモデルを開いて、Restore model versionを選択することでモデルの復元が実行されます。 アーカイブされたモデルのバージョン一覧 アーカイブされたモデルバージョンの詳細。Restore model versionにより復元できる。 モデル復元完了 バージョン単位ではなくモデル自体のアーカイブと復元も同様に行えます。 モデル単位でのアーカイブ、復元も可能 おわりに 以上により、モデルレジストリのDB作成、モデルレジストリの登録、モデルメタデータの登録、モデルのデプロイ、モデルのアーカイブ・復元について解説しました。 MLOpsにおいてAIモデルの更新が行われるため、その管理というのは非常に重要になってきます。ぜひモデルレジストリを活用することで、モデルの管理に役立ててください。 参考 モデルレジストリーの操作: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.16/html/working_with_model_registries/index モデルレジストリーの管理: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.16/html/managing_model_registries/index ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift AIのモデルレジストリ機能を使ってみた first appeared on SIOS Tech. Lab .
  こんにちは、サイオステクノロジーの佐藤 陽です。 相変わらずCosmosDBについての勉強しているので、引き続きアウトプットしていきたいと思います。 今回のテーマはCosmosDBでのベクトル検索についてです。 ベクトル検索って何? CosmosDBでどうベクトル検索を実装するの? RAGにCosmosDBを組み込みたい! といった方は是非最後までご覧ください! はじめに 2024年のMicrosoft IgniteにてCosmosDBのベクトル検索機能がGAとなることが発表されました。 同年のMicrosoft BuildではまだPublic Previewでしたが、これで本番環境でも安心して利用できます。 このベクトル検索ですが、昨今の生成AIのアプリケーションと非常に相性が良いです。 特にRAG(Retrieval Augmented Generation)ではベクトル検索がよく使われており、CosmosDBをRAGに導入するといったパターンが今後主流になってくるのではないかと思います。 そこで本記事では、「ベクトル検索とは?」といった点からCosmosDBでのベクトル検索の実装まで一通りご紹介したいと思います。 余談 本記事は JAZUG Shizuoka での登壇資料をベースとしているため、内容がやや静岡寄りのものとなっています。 そして是非、JAZUG Shizuokaが開催するイベントへも参加いただければと思います! ベクトル検索とは? ではまずベクトル検索についてご紹介します。 生成AIを活用するうえでベクトルは非常に重要な要素です。 高校生の時にベクトルとは「大きさ・向きを持つもの」として習い X,Y平面上に矢印を書いた図をたくさん見たかと思いますが、まさにあれです。 今回の記事においては、文章や画像などをベクトル化します。 例えば「犬」「猫」「花」の3つの単語をベクトル化すると、それぞれ以下のような値で表現されます。 (ベクトル値としては1000を超える次元数であるため一部のみ掲載します) 犬 猫 花 ベクトル値 [-0.019726261, -0.014364496, -0.011311122,…] [-0.013889334, -0.050191004, -0.03891719, …] [0.02033748, 0.027342353, 0.017839076, …] そしてこのベクトル値の特徴として、 似たような使われ方をする単語 は似たような値を取ることが言われています。 例えば 私は毎朝、犬にエサをあげる 私は毎朝、猫にエサをあげる といったような使い方はしますが 私は毎朝、花にエサをあげる といった使い方はしませんよね。 このように、同じような使われ方をする単語は、似たようなベクトル値を持ちます。 今回はこの「似たような値」を評価するためにコサイン類似度を利用します。 犬, 猫, 花の3つの単語のベクトルア値、それぞれの組み合わせでコサイン類似度を算出した値を以下に示します。 犬&猫 犬&花 猫&花 0.6180 0.4022 0.3522 この結果から、「犬」と「猫」のベクトル値の相関が高くなり、近しい意味を持つことを表しています。 人間の感覚からしたら明らかな結果ですが、コンピューターが定量的な値としてこの意味の近さを扱えることは大きなメリットです。 この仕組みを利用したのが ベクトル検索 です。 ベクトル検索は、ユーザーからの質問(クエリ)をベクトル化し、データベースなどから似たようなベクトル値を持つものを算出します。 これにより、キーワード的には一致していないとしても、意味的に近しいものをデータベースから取得することが可能となります。 CosmosDBでのベクトル検索 では実際にCosmosDBにおけるベクトル検索の例を見てみたいと思います。 まず初めに検索対象となるデータをCosmosDBに格納します。 今回は、静岡の観光地をテーマに格納するデータを用意しました。 観光地名 説明 富士山 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。 伊豆半島 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。 三島スカイウォーク 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。 熱海温泉 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。 日本平 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 静岡県立美術館 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。 清水エスパルスドリームプラザ 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。 浜松城公園 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。 久能山東照宮 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。 沼津港深海水族館 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。 この項目に対して以下の処理を行います。 ベクトル化 CosomosDBへの登録 ベクトル化 まずはそれぞれのコンテンツをベクトル化します。 今回は 観光地名 と 説明 の2列に分かれているものを、一つの文字列としてベクトル化していきます。 ベクトル化するにあたってはEmbeddingモデルが必要となるので事前にデプロイしておきましょう。 今回はAzure OpenAI Service上で、 text-embedding-3-small のモデルをデプロイしておきました。 そのうえで今回は以下のような実装を行いました。 url = "https://{AOAIのエンドポイント}/openai/deployments/{Embeddingのモデル名}/embeddings?api-version=2023-05-15" content = [ "富士山 - 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。", "伊豆半島 - 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。", "三島スカイウォーク - 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。", "熱海温泉 - 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。", "日本平 - 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。", "静岡県立美術館 - 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。", "清水エスパルスドリームプラザ - 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。", "浜松城公園 - 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。", "久能山東照宮 - 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。", "沼津港深海水族館 - 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。" ] headers = {   'Content-Type': 'application/json',   'api-key': '{api-key}' } results = [] for spot in content:     payload = json.dumps({       "input": spot     })     response = requests.request("POST", url, headers=headers, data=payload)     response_data = response.json()     embedding = response_data['data'][0]['embedding']     result = {         "content": spot,         "contentVector": embedding     }     results.append(result) ここでresultとして出力された内容を一つ見てみます。 {     "content": "富士山 - 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。",     "contentVector": [         0.015276342,         -0.04262919,         -0.010207734,         0.027943453,         0.033972893,         ...     ] } このように、元の情報(content)と、その値をベクトル化した値(contentVector)が用意できました。 CosmosDBへの登録 事前準備 ではこの用意出来た値をCosomosDBに登録してきます。 CosomosDBにベクトル値を登録するには事前準備が必要となるため、以下に手順を示します。 コンテナ作成時にベクトルポリシーを追加します。 以下が設定項目です。 パラメータ 概要 Path ベクトル値として扱うパラメータのパスです。今回は/contentVectorが対象となります。 Data データのタイプです。今回扱うEmbeddingモデルが float32で出力する ため、これに合わせてfloat32に設定します。 Distance function ベクトル間の距離を測るための関数です。こちらは先程ご紹介したコサイン類似度を利用します Dimensions ベクトルの次元数です。こちらは今回扱うEmbeddingモデルの次元数が1536となっているため、この値を設定します。 Index type インデックス方式です。このあたりは検索精度に関わってきますが、今回は詳細な説明は割愛します。diskANNとします コンテナ作成完了後、Settingsファイルを確認します。 先程設定した内容が正しくポリシーとして登録されていることが確認できます。 データアップロード 準備が出来たところで、こちらのコンテナに先程のデータを格納していきます。 今回は、先程のベクトル化の処理の最後に出力結果をjsonファイルとして出力しておき、その内容を以下のコードで改めてアップロードします。 # CosmosDBの接続情報 endpoint = "{CosnosDBのエンドポイント}" key = "{Key}" database_name = "sios-database" container_name = "vector-container" # CosmosDBクライアントの作成 client = CosmosClient(endpoint, key) database = client.get_database_client(database_name) container = database.get_container_client(container_name) # JSONファイルをアップロードする関数 def upload_json_to_cosmosdb(file_path):     with open(file_path, 'r', encoding='utf-8') as f:         data = json.load(f)         # idフィールドを追加         data['id'] = data['content']         container.upsert_item(data) # 先程出力したベクトル値を含むJSONファイルをアップロード # 今回は簡易的に`result_`から始まるファイルを指定 for file_name in os.listdir('.'):     if file_name.startswith('result_') and file_name.endswith('.json'):         upload_json_to_cosmosdb(file_name)         print(f"Uploaded {file_name} to CosmosDB") print("All files have been uploaded.") このコードを実行した後にCosmosDBのデータエクスプローラを見てみると、無事にデータが登録されていることが確認できました。 ベクトル検索 次に格納されたデータに対して検索を行っていきます。 今回は以下のような検索を行ってみたいと思います。 「景色が良い所は?」 まずは、この質問(クエリ)をベクトル化します。 先程と同様にEmbeddingモデルを利用してベクトル化したところ以下のような結果となりました。 [−0.01532, −0.02434, −0.05363, ...] この値を利用して検索を行います。 検索クエリとしては以下の通りです。 -- データベース内のコレクション "c" から、最も類似した10件のデータを取得するクエリ SELECT TOP 10     c.content, -- 各ドキュメントの "content" フィールドを取得     VectorDistance(        c.contentVector, -- ドキュメント内のベクトルデータ        [0.0015812921, -0.01822265, -0.011891554,...] -- クエリで指定したターゲットベクトル     ) AS SimilarityScore -- ベクトル間の距離を "SimilarityScore" として取得 FROM c -- ベクトル間の距離(類似度)で昇順に並べ替え ORDER BY VectorDistance(c.contentVector, [0.0015812921, -0.01822265, -0.011891554,...] ) これにより、CosmosDB上から最も類似したデータを検索することが可能です。 実行した結果を以下に示します。 順位 コンテンツ 類似度スコア 1 日本平 – 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 0.5055713624352297 2 伊豆半島 – 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。 0.3731433864334767 3 久能山東照宮 – 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。 0.3712187302734037 4 三島スカイウォーク – 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。 0.37086192839082927 5 熱海温泉 – 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。 0.34883694499412393 6 浜松城公園 – 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。 0.3407391717527575 7 富士山 – 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。 0.31416708979179037 8 静岡県立美術館 – 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。 0.30245339778589064 9 清水エスパルスドリームプラザ – 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。 0.2622979141244738 10 沼津港深海水族館 – 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。 0.17702736397602103 このように、各観光地の概要の中に、「景色が良い」といった直接的なワードは含まれていないにも関わらず、景色がよさそうな観光地が上位の検索結果に表れました。 これは以下に示すような 「コンテンツに含まれている文章のベクトル値」 と、 「”景色が良い所は?”の文章のベクトル値」 が近い値を取った結果であると予想されます。 富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 伊豆七島を望む絶景ポイントも多数存在する。 富士山の麓、久能山の山頂に鎮座する神社 これにてベクトル検索が完了です! 何となくイメージはつかめていただけたのではないでしょうか? 注意点 ベクトル検索で扱う ベクトル値 は、膨大な学習データに基づいて算出されています。 そのため、一般的な単語に対するベクトル値はある程度正確に算出することができますが、ユニークな単語などは苦手です。 例えば社内で「SIOS Innovation Program」といったオリジナルの制度があったとし、通称「SIP」と呼ばれているとします。 この場合、SIPの制度に関連した情報についてベクトル検索を行おうとした場合、期待した結果が得られない場合があります。 これは、SIPもしくはSIOS Innovation Programが一般的な単語ではなく、適切にベクトル化が行えないためです。 こういったケースはベクトル検索よりも、キーワード検索が適していると言われています。 このように必ずしもベクトル検索が優れているわけではなく、ケースに応じて検索方法を切り替える必要があります。 そして、このキーワード検索とベクトル検索を組み合わせたハイブリッド検索といった強力な検索手法も活用されているのですが 2025年のBuildにてCosmosDBでもベクトル検索の機能がGAされるとうわさされています。 また実際にGAされたら試してご紹介したいと思うので期待ください! おわり 本日はCosmosDBのベクトル検索の機能をご紹介しました。 CosmosDBでのベクトル検索機能がGAされたことにより、より生成AIソリューションとの親和性が高まり、今後の活用が期待されます。 また、ハイブリッド検索機能のGAも噂されていることにより、より一層の期待ができます。 これを機会にCosmosDBを是非活用してみてください! ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】CosmosDBにおけるベクトル検索入門ガイド【初心者向け】 first appeared on SIOS Tech. Lab .
こんにちは。サイオステクノロジーの橋本です。 皆さんは Ansible で環境構築をしているものの一回の実行時間がちょっと長くて… という事はありませんか 自動化してもやっぱり時間がかかるパッケージインストールをちょっと早くする方法を紹介します。 今回は以下の 4 回 dnf を実行している Playbook に関して、 1 回の dnf 実行に集約してます。 - name: "httpd のインストール"   ansible.builtin.dnf:     name: httpd   when:   - ansible_distribution_major_version == "9" - name: "DNS (bind) のバージョン指定" set_fact: bind_version: 9.16 - name: "DNS (bind) のインストール" ansible.builtin.dnf: name: "bind{{ bind_version }}" when: - ansible_distribution_major_version == "8" - name: "wget のインストール" ansible.builtin.dnf: name: wget - name: "sos のインストール" ansible.builtin.dnf: name: sos 上記 Playbook はわかりやすいというメリットは有るものの 4 回 dnf を実行しているため 都度都度 dnf モジュールを実行し毎回リポジトリのチェックなどが入りその分処理時間が長くなります。 そのため、dnf を可能な限り少ない回数にして、リポジトリチェックなどの回数 を抑えようという発想です。 Step 1 ドキュメント にもあるように dnf モジュールはパッケージ名を配列で渡すことができます。 まずは sos と wget を配列で渡しましょう。 Step 2 で活きてきますが配列は事前に定義します。 - name: "インストールパッケージの定義" ansible.builtin.set_fact: packages: - wget - sos - name: "必要パッケージのインストール" ansible.builtin.dnf: name: "{{ packages }}" ここまではよくある手順ですね。 Step 2 さて、問題は以下です。 OS や サーバの役割によってインストールパッケージが異なる運用はよくあるとおもいます。 そして、それが dnf の複数回実行になることもよくあるケースだと思います。 when 句で条件分岐していても、以下のように set_fact すれば同様の挙動をしてくれます。 - name: "インストールパッケージの定義" ansible.builtin.set_fact: packages: - wget - sos - name: "httpd を配列に追加" ansible.builtin.set_fact: packages: "{{ packages + \ ['httpd'] }}" when: - ansible_distribution_major_version == "9" - name: "DNS (bind) のバージョン指定" set_fact: bind_version: 9.16 - name: "bind を配列に追加" ansible.builtin.set_fact: packages: "{{ packages + \ ['bind{{ bind_version }}'] }}" when: - ansible_distribution_major_version == "8" - name: "必要パッケージのインストール" ansible.builtin.dnf: name: "{{ packages }}" 当初とインストールするパッケージに変わりはないですが、 dnf モジュールを呼び出す回数は 1 回になっているため処理時間も大幅に短くなります。 Ansible の処理速度が遅いとき、上記のようにパッケージのインストールを集約するのを検討してみてはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Ansible をちょっと早く実行する dnf (yum) tips first appeared on SIOS Tech. Lab .
こんにちは、OSSよろず相談室のSKです。 日々、多くのOSSに関するお問い合わせをいただいているのですが、今回は、そもそもOSS(オープンソースソフトウェア)とはどんなものなのかというお話です。 オープンソースとは まず、座学的な話になりますが、オープンソースとは、 主に オープンソース・イニシアティブ(OSI) によって推進される概念で、実用性や協調開発を重視しています。 重視されることは、透過性(公開されていること)実用性、協調開発されコミュニティがあることです。 逆に見た目やデザイン、UI(使い勝手)、利益などは軽視され、サポートはありません。 OSIに掲載された10個の定義はこちらです。 オープンソースの定義 上記オープンソースの定義は、主に以下の内容について定義しています。 ソースコードの公開 – プログラムが実行ファイルとともにソースコードも提供・公開されること。 改変と配布の許可 – 誰でも改変や配布ができること。 差別の禁止 – 特定の人や団体に対する差別的な制限を設けないこと。 ここで疑問に思うことは、「いわゆるフリーウェアと何が違うのだろう?」だと思います。 フリーウェアはOSSと同様に無償ですが、プログラムの中身は公開されていないことが多いです。 公開されていないので、改変もできません。 OSSとフリーウェアの大きな違いは、この 「ソースコードが公開されている」 ことと、 「改変できる」 という点です。 OSSは皆で使おう!という精神が強くあります。 「世界中皆で使う」ものであるはずなのに、2024年10月にLinuxカーネルのメンテナーからロシア人が削除されたことが物議となりました。 以下は Linuxカーネルのメーリングリストのアーカイブが公開されたもの の一部です。差分情報がdiffとして記録されていますが、ロシアのドメインを示す「.ru」のメンテナー「M」が「-」で削除されていることが分かります。 Linuxの生みの親である Linus Torvalds 氏自ら「 I’m Finnish. Did you think I’d be supporting Russian aggression? (フィンランド人の私がロシアの侵略を支持すると思いますか?)」と言及しています。 これは OSS の定義に反するのではないか?と物議を醸しました。 OSSライセンスの探し方 それでは、OSSライセンスが具体的にどのように表記されているのか、見てみましょう。 例えば、Tomcatを見てみます。 ソースコードはGitHubで公開されています。 Apache Tomcatのソースコード OSSライセンスの記載場所は以下の4か所です。 ソースコード群に同梱されているテキストファイル ソースコードファイルのヘッダ プロジェクト公式Webサイト 製品に組み込みのドキュメント 「1.ソースコード群に同梱されているテキストファイル」を見てみましょう。 以下はソースコード群の中身です。 OSSライセンスは、ソースコード群にテキストファイルで同梱されています。 LICENSEファイル を開くと以下のようになっています。 Apache License Version 2.0 であることが明記されています。 Apache LicenseはOSSライセンスの1つです。 ここに書かれた http://www.apache.org/licenses/ をクリックすると、ライセンスの内容を見ることができます。 OSSライセンスを適用する では、自分のソフトウェアにApacheライセンスを適用する方法を紹介します。 適用イメージ 自分のソフトウェアにApacheライセンス適用する方法 全ソースコードの各ファイルの冒頭に、指定されたライセンスの告知文(license notice)を追加する必要があります。 例えばApacheライセンスの場合、 Apacheライセンス に明記されています。 付録: Apache Licenseの適用の仕方 あなたの製作物にApache Licenseを適用するときは、次の定型文を添付してください。ただし、"[]"で囲まれている部分は、あなた自身の識別情報に置き換えてください(その際、角括弧は取り除きます)。また、この文言を該当するファイル形式に合ったコメント構文で囲んでください。さらに、第三者アーカイブ内での識別を容易にするため、ファイル名またはクラス名ならびに趣旨説明が著作権表示と同じ「印刷ページ」に現れるようにすることをお勧めします。 Copyright [yyyy] [著作権所有者の名前] Apache License Version 2.0(「本ライセンス」)に基づいてライセンスされます。あなたがこのファイルを使用するためには、本ライセンスに従わなければなりません。本ライセンスのコピーは下記の場所から入手できます。 http://www.apache.org/licenses/LICENSE-2.0 例えば、Tomcat も Apache ライセンスを適用したソフトウェアです。 ossライセンスの探し方 で紹介した Tomcat が公開された GitHub の中から、jav aのファイルを選んでみましょう。 全てのjavaのソースコードの先頭にライセンスが記載されていることが確認できます。 OSSライセンスソフトを同梱する方法 次に、自分のソフトウェアにApacheライセンスを適用したTomcatを同梱する方法をご案内します。 さきほどの 自分のソフトウェアにApacheライセンス適用する方法 では、全てのソースコードの先頭にライセンスを表記しないといけませんでしたが、同じことをしなければいけないでしょうか? 答えは No です。 Tomcat内にあるLICENSEファイルとNOTICEファイルを入れ、readmeファイルにTomcatが入っていることを明記すればよいだけです。 今日のオープンソースの話はここまでにします。 次回は コピーレフト オープンソースにまつわるリアルな事例 についてご紹介します。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post オープンソースライセンスとは 1 first appeared on SIOS Tech. Lab .
はじめに アプリケーションのコンテナ化が一般的になった現在、コンテナイメージをどこに保存し、どうやって配布・管理するかは非常に重要な課題となっています。 本記事では、コンテナプラットフォーム向けのコンテナレジストリ選択肢として Red Hat Quay・Harbor・パブリッククラウドのマネージドイメージレジストリそれぞれの特徴について解説します。 各コンテナレジストリソリューションの概要 Red Hat Quay Red Hat QuayはRed Hat社が提供する セルフホスト型 のオープンソースコンテナレジストリです。 オープンソース版と有償版が存在し、アプリケーションの特性に応じて選択できます。 特徴 GitHubなどソースリポジトリからのプッシュイベントをトリガーにした自動ビルド機能が充実 地理的レプリケーションな機能によりグローバルにイメージを分散させることで多拠点環境下における高可用性と高パフォーマンスを実現 Red Hat社が提供する信頼性ある有償サポート付き RH社製品であるOpenShiftとの統合のしやすさ 開発からコンテナプラットフォームへのデプロイを高度に自動化したい開発チームや 既にOpenShift環境を利用しているチームなどでの利用が特に見込まれます。 Harbor HarborはVMware社が開発した セルフホスト型 のオープンソース コンテナレジストリです。 CNCFプロジェクトとなっており、他ツールとの連携も考慮しながら選択できます。 特徴 Kubernetesとの連携を前提とした設計で、幅広いコンテナプラットフォームに導入しやすい オープンソースなので、コストを抑えて導入することが可能 マルチテナント対応:複数プロジェクトを1つのインスタンス内で分離管理可能 アクセス権限やセキュリティポリシーなどを細かく制御することが可能 プロジェクト単位の設定、プロジェクトごとの分離 コンテナに関する知識(Docker、Kubernetes、Helmなど)が豊富でオープンソースを好む文化を持つチームや 設定のカスタマイズ性の高さを重視するチームなどでの利用が見込まれます。 パブリッククラウドのマネージドイメージレジストリ Amazon Elastic Container Registry(ECR)、Azure Container Registry(ACR)、Google Artifact Registry(旧GCR)など、クラウドベンダーが提供する フルマネージド型 のコンテナレジストリです。 特徴 インフラの構築・運用・スケーリングが不要。高可用性・冗長化もベンダー側で担保 IAMやサービスアカウントでの権限管理が容易 クラウドプロバイダーが提供するCI/CDとの統合が容易 AWS: Code Pipelineなど パブリッククラウドが提供するコンテナプラットフォームを利用しているチームや レジストリ運用をマネージド化させて運用負荷を削減したいチームなどでの利用が見込まれます。 まとめ コンテナレジストリはセキュリティ面での考慮やCI/CDにおいても起点となる重要なコンポーネントです。 各パブリッククラウドでマネージドサービスとして提供される中でOSSや有償ソリューションとしても、セルフホスト型でのソリューションが選択肢として多く存在します。 他のコンポーネントとの連携や運用負荷等を考慮しながらコンテナレジストリについては選定していく事が大きなポイントとなってきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナレジストリを選ぶなら?Quay / Harbor / マネージドサービスそれぞれの概要解説 first appeared on SIOS Tech. Lab .
こんにちは、RAG StarterPackチームです。 日頃より多くの皆さまにご利用いただき、心より感謝申し上げます。 さて、本日2025年4月1日、私たちは重大な決断をいたしました。 「RAG スターターパック、Internet Explorerに完全対応いたしました。」 なぜIE対応なのか? 現代のブラウザは進化を遂げましたが、あの独特の青いeマークに懐かしさを感じる方も多いはず。  「RAG × レトロでエモい体験を!」という熱い思いから、  IE6〜IE11までの完全対応 に踏み切りました。 機能ハイライト Chat UIの“謎のズレ”を忠実に再現 ボタンの角丸が消滅するノスタルジー RAGの回答を3秒遅らせて、ダイヤルアップの気持ちに! ActiveX風の謎ポップアップも出るかも?(仕様です) 開発裏話 私がエンジニアになった5年前 Reactで開発中にChrome, Edgeのテストは通過して最後のIEで正常に動作せずとてもつらかった日々 「DOCTYPEを外したら動いた!」と歓喜したあの日 IEのおかげで進捗が出ず爆詰めされたあの日 実装をしているときには悩みの種でしたがいざいなくなると寂しいものです お問い合わせ方法 ブログを閲覧いただきありがとうございました。 もしRAGに興味のある方がいらっしゃいましたら こちら からご連絡お待ちしています! Happy April Fools! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【重要なお知らせ】RAG スターターパック、Internet Explorerに完全対応しました(IE6もOK) first appeared on SIOS Tech. Lab .
こんにちは、伊藤です。今回は、Application Gatewayのカスタムエラーページを構成する手順を紹介します。 Application Gatewayではデフォルトのエラーページが用意されていますが、エラー番号とエラー内容が簡易に表示されるにとどまっています。そこで、カスタムエラーページを構成していきます。 Application Gatewayの作成 Application Gatewayの解説は過去記事で紹介されているので、参考にしてみてください。 参考: https://tech-lab.sios.jp/archives/30628 Application Gatewayを作成します。今回は以下の設定とします。 基本 フロントエンド バックエンド 構成 ルーティング規則(リスナー) ルーティング規則(リスナー)ではカスタムエラーページを設定する項目があり、リスナーごとにカスタムエラーページを設定できます。今回は、Application Gateway全体(グローバルレベル)でカスタムエラーページを設定するため、ここでは未設定とします。 ルーティング規則(バックエンドターゲット) Application Gatewayの作成後、概要のフロントエンドパブリックIPアドレスを確認し、アクセスします。バックエンドターゲットが存在しないのでエラーとなり、デフォルトのエラーページが表示されます。 ストレージアカウントの作成 カスタムエラーページを配置するストレージアカウントを作成します。今回は以下の設定とします。 基本情報 詳細 ネットワーク データ保護 暗号化 ストレージアカウントの作成後、コンテナ―にてカスタムエラーページを配置します。 「errorpage」というコンテナーを匿名アクセスレベル「BLOB」で新規作成し、その中にhtmlファイル(502.html)を作成します。カスタムエラーページの条件は以下を参考にしてみてください。 参考: https://learn.microsoft.com/ja-jp/azure/application-gateway/custom-error 502.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>エラー 502 - 不正なゲートウェイ</title> </head> <body> <div class="error-container"> <h1>エラー 502 - 不正なゲートウェイ</h1> <p>申し訳ありませんが、サーバーへの接続に問題が発生しました。</p> </div> </body> </html> htmlファイルのプロパティを開いてURLを確認し、アクセスします。アクセスでき、エラーページが表示されることを確認します。 Application Gatewayのカスタムエラーページ設定 Azure PowerShell を使用して、カスタム エラー ページ(グローバルレベル)を設定します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Add-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 -CustomErrorPageUrl "https://testgwerrorpage.blob.core.windows.net/errorpage/502.html" Set-AzApplicationGateway -ApplicationGateway $appgw カスタムエラーページの確認は以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $appgw.CustomErrorConfigurations カスタムエラーページがすでに設定されており、設定変更したい場合は以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Set-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 -CustomErrorPageUrl "<errorpage-url>" Set-AzApplicationGateway -ApplicationGateway $appgw カスタムエラーページを削除する場合は、以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Remove-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 Set-AzApplicationGateway -ApplicationGateway $appgw 参考: https://learn.microsoft.com/ja-jp/powershell/module/az.network/?view=azps-13.3.0#application-gateway カスタムエラーページの設定後に、Application Gatewayにアクセスします。カスタムエラーページが表示されることを確認します。 ストレージアカウントのネットワーク設定 ここまでのストレージアカウントは、全てのパブリックネットワークアドレスからアクセスが許可されています。そのため、Application Gatewayのサブネットとカスタムエラーページを管理するクライアントPCからのみアクセスできるようにします。 ストレージアカウントの「ネットワーク」を選択すると、パブリックアクセスの設定が表示されます。「Manage」を選択して設定を変更します。 「Enable from selected networks」を選択して特定のネットワークからのアクセスを許可し、許可するネットワークとしてApplication GatewayのサブネットとクライアントPCのIPアドレスを設定し、設定保存します。 アクセス許可されていないIPアドレスからカスタムエラーページのURLにアクセスできないことを確認します。 Application Gatewayのカスタムエラーページ設定を変更する場合は、Azure PowerShell からカスタムエラーページのURLにアクセスできず設定変更に失敗するため、再度全てのパブリックネットワークアドレスからのアクセスを許可してから設定する必要があります。そのため、次のカスタムエラーページ設定を変更せずエラーページの内容を変更する方法が望ましいです。 カスタムエラーページ設定を変更せずエラーページの内容を変更したい場合は、ストレージアカウントにあるhtmlファイルのプロパティから編集することができます。 編集後のhtmlを反映するためには、Application Gatewayで任意の構成更新を実行して、ファイルのキャッシュを手動で更新します。 例えば、新しいリスナーを追加します。 まとめ 今回は、Application Gatewayのカスタムエラーページを構成する手順を紹介しました。 Application Gatewayの設定の参考になれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Application Gatewayのカスタムエラーページを構成する first appeared on SIOS Tech. Lab .
サイオステクノロジー武井です。Microsoftがグローバルで開催しているAIのイベント「Microsoft AI Tour」の東京バージョンに、Microsoft MVPとして、ブース対応とハンズオンのサポートスタッフ対応として参加いたしました。そのレポートになります。 東京ビッグサイトで行われたイベントなのですが、たくさんの来場者がいらっしゃって、熱気に包まれたイベントでした。 バッジのピックアップ 翌日の下見も兼ねて、前日にチェックインしてバッジを受け取りました。前日に受け取ることができるのは非常に助かりますね。 そしてその時に基調講演の優先席チケットもいただきました。これは非常にありがたいですね。 基調講演 そして、基調講演当日、Reservedと書いてある席に座ることができましたが、そこそこ後ろの方でした。最前列はおそらくメディアと、Microsoftのパートナー企業の方々が座っていたのだと思います。 豪華なライティングとスモークが炊かれていました。そんなかっこいいステージで、基調講演が行われました。そして、今回の本丸であるMicrosoftのCEO、Satya Nadella氏の登場です。 基調講演の内容はまさに、 AIエージェント 一色でした。AIエージェントで業務を革新していくぞーみたいな話から始まりました。 そしておなじみCopilot Stackですね。 一番上のCopilotはいわゆるユーザーインターフェースの層です。WordやPower PointなどのビジネスアプリケーションにCopilot(副操縦士)として、業務を補佐するためのUIが組み込まれているぞーみたいなお話。 そしてさらに、Resaercher agentを始めとした賢いエージェントがMicrosoft 365に搭載されるという話です。様々な業務データを分析して、より高度な推論を行うエージェントが業務の補佐を行うという話でした。 AgentsはMicrosoftが持っている様々なデータとシームレスに繋がりますという話です。Agentはもちろんデータなくして動かないので、このように様々なデータと繋がることができるのは非常に強力です。 そして、弊社が最も得意とする「Copilot & AI stack」です。 日本の東西リージョンが強化されるようです。これはよいことですね。Agentの利用に伴い、さらなるコンピューティングリソースの需要が増えることが予想されるため、リージョンの強化は非常に重要です。 そしてAzure AI Foundryです。これは、本イベントでもイチオシでありますし、私もワークショップを担当したAzure AI Agent Serviceの管理には欠かせないものです。今後、Azure AI Foundryの機能が強化されることが予想されます。 JALさんは、ローカルLLMをFine Tuningして、自社の業務に適用しているという話でした。これは非常に興味深いですね。ローコストで、高精度なAIモデルを構築するための手法として、ローカルLLMをFine Tuningするというのは非常に有用です。今後の動向に期待大です。 ということで、まさにAIエージェント一色の基調講演でした。   私が担当したブース 私は、Azure Application Platofromのブースを担当いたしました。Azure上でアプリケーションをどうっするための様々なプラットフォーム(Azure App Service、Azure Functions、Azure Container Appsなど)をご紹介するブースです。 他のブースに比べると、Copilot Stackでいうところの下の方に位置するレイヤーだったので、このブースにいらっしゃたお客様は非常にエンジニア寄りの方が多い印象でした。 やはり皆様、Azure上でAIアプリケーションを動作させるのに、どのようなプラットフォームがあるのか、どのような違いがあるのか、といったことに興味を持っていらっしゃいました。 Azureには、様々なアプリケーションプラットフォームがあるのですが、やはりAzure FunctionsがAIアプリケーションには非常に適しているということをお伝えしましたし、Azure Functionsをご検討されているお客様が多かったですね。私の推しも、Azure Functionsでした。やはり、Azure OpenAI ServiceのAPIのレスポンって非常に軽いリクエストとレスポンスのやり取りで、さらにステートレスなAPIなのでAzure Functionsが非常に適していると思います。 Azure AI Agent Serviceリリースの影響もあって、AIの基盤としてどれを選定したらよいのか、というご相談も多くありました。 AIは、そもそもそれを動かすためのアプリケーション基盤がないと動作しません。よって、AIアプリケーションを動かすためのアプリケーション基盤についての知識は非常に重要です。そのため、Azure Application Platformはこれからも重要な役割を担っていくと思います。   ごはん ウマウマなランチもいただけたので、とても満足でした。朝、昼、夜ともに食事が提供されました。 朝と夜は写真を取り忘れたのですが、昼の写真はあります。数種類のお弁当が提供されていました。 なんとその一つに、今半のすき焼き弁当がありました。これはすごい!!!と思い、早速いただきました。 ワークショップ 私は、以下のワークショップのサポーター(受講者の方のご質問に答える役割)を担当しました。 Azure AI エージェント サービスで最初のエージェントを構築する https://aitour.microsoft.com/ja-JP/sessions/a6cb7b8d-9f92-47e2-94dc-d58a0feb5d17 写真の通りワークショップは2回とも満席でした。 ワークショップではAzure AI Agent Serviceを使って、以下の役割を持つエージェントを構築するというものでした。 データベース(SQLite)からデータを取得するエージェント データベース(SQLite)から取得したデータをCode Interpreterでチャート図を作成するエージェント ベクトルデータベースから必要な情報を検索するエージェント Bingにアクセスして必要な情報を検索するエージェント 様々なユースケースに基づいて、エージェントを構築していき、その凄さを体感するものでした。 Azure AI Agent Serviceは、AIエージェントを開発するうえで非常に便利な以下の機能を提供しています。 スレッドという単位で会話履歴を永続化してくれる Bing SearchやCode Interpreterなどへのツールの利用が超簡単である OpenAPIなどを利用することで既存システムともシームレスに連携できる ワークショップの参加者の方々は、Azure AI Agent Serviceの簡単さに驚かれていました。これからも、Azure AI Agent Serviceは、AIエージェント開発の現場で非常に重要な役割を担っていくと思います。 ワークショップは大成功でした。(講師の本間咲来(さっくる)さん、Microsoft MVP河本さんと)   セッション セッションもたくさん開催されていました。私はブース担当とワークショップサポーターを担当していたので、多くのセッションには参加できませんでしたが、その中でも非常に気になったものを一つピックアップします。それは以下です。 Azure上でDifyを活用したAIアプリケーションの構築 https://aitour.microsoft.com/ja-JP/sessions/24da067e-6a85-437c-835d-8935467ba7cc Microsoft MVPとして、またLINE API Expertとしてご活躍されている平林さん(ひらりんさん)が登壇されていました。Azure上にDifyが稼働するためのアプリケーションインフラを構築するという内容でした。 DifyをAzure上に構築するための方法は、以下の3つがあります。 VM上に構築する Azure Kubernetes Service(AKS)上に構築する Azure Container Apps上に構築する このセッションでは、3の「Azure Container Apps上に構築する」をしていました。実は、Azure Container AppsでDifyを構築するためのTerraformは以下のGitHubリポジトリに公開されておるのですが、バージョンが古かったりして少々手を加えないと動きません。弊社でもそれは確認済みでした。 しかしながら、平林さんそれをBicepにリファクタリングして、Azure Container Apps上にDifyを構築する方法をご紹介されていました。スゴイです。以下のリポジトリでBicepのコードを公開されているとのことでした。 https://github.com/himanago/dify-azure-bicep 素晴らしいです!!   まとめ Microsoft AI Tour Tokyoは、AIエージェント一色のイベントでした。AIエージェントは、業務を効率化するための非常に強力なツールであり、今後ますますその重要性が高まっていくと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Microsoft AI Tourレポート first appeared on SIOS Tech. Lab .
概要 今までの回で、プラットフォーム上でコンテナとVMを統合管理することが出来るOCP-Virt, SUSE-Virt についてご紹介しました。 紹介の中でも、簡易的にその他仮想化基盤との比較も行ってきました。 今回は、今までにご紹介したOCP-Virt, SUSE-Virt, 加えてvSphereを含めて3製品の比較について記載します。 vSphereについても、今までの回で軽く触れていますが改めて概要と特徴について簡単に触れておきたいと思います。 OCP-Virt, SUSE-Virt の概要については下記の記事をご覧ください。 OCP-Virtの概要は こちら SUSE-Virtの概要は こちら vSphereの概要と特徴 vSphereは、仮想化基盤として提供され複数のVMを実行して管理することができます。 リソース使用率の最適化、スケーラビリティの向上のため企業環境での広範な採用実績を持っています。 主な機能としては、以下があります。 ESXiホスト 物理サーバー上で動作するハイパーバイザーで、仮想マシンの実行環境を提供します vCenter Server 複数のESXiホストを集中管理するためのサーバーで、VMの管理、リソースの最適化などを行います vMotion 実行中のVMをダウンタイムなしで他のESXiホストに移動する機能です。この機能によりシステムのダウンタイムを最小化することができます。 DRS(Distributed Resource Scheduler) VMのリソース需要に応じて、リソースの負荷を自動的に分散させる機能です vSphere HA ESXiホスト障害時にVMを自動的に他のホストに移動させ、可用性を高める機能です vSphere Replication VMのデータを別の場所に複製し、災害復旧を実現するための機能です。この機能により、データセンターの障害に対して迅速に復旧が可能になります 主な特徴は、以下があります。 柔軟性とスケーラビリティ vSphereは、小規模から大規模な環境までスケーリングが可能で、リソースの追加や削減が簡単に行えます また、ハイブリッドクラウド環境にも対応しており、クラウドとオンプレミス環境を柔軟に組み合わせて運用できます 効率的なリソース管理 VMごとにリソースの割り当てや優先順位を設定し、リソースの効率的な利用が可能です 高可用性とフォールトトレランス 自動フェイルオーバー用の vSphere HA や予測障害検出用の Proactive HA など信頼性の高い仮想化基盤環境を提供します 簡単な管理インターフェース 直感的な管理インターフェースを提供し、管理者がvSphere ClientやvCenter Serverなどを通じて、VMやリソースを簡単に管理できるように設計されています 前提情報 本記事では、現時点で以下のバージョンを対象としています。 OpenShift Virtualization OpenShift v 4.17 OpenShift Virtualization v4.17.3 SUSE Virtualization harvester v 1.4.0 VMware vSphere VMware vSphere 8.0 OCP-Virt、SUSE-Virt、vSphere の比較 OCP-Virt、SUSE-Virt、vSphere の主な機能の比較を記載します。 比較区分は以下の通りです。 〇:機能が存在するあるいは、他のソリューションと比較し優れている △:オプションの機能と組み合わせて実現が可能、また機能はあるが他のソリューションと比較すると制限や制約が大きい ✕:機能がない   表1:OCP-Virt、SUSE-Virt、vSphere の比較表 大項目 中項目 小項目 OCP-Virt SUSE-Virt vSphere VM基本機能 VM操作 VMの作成 〇 〇 〇 VMの編集 〇 〇 〇 VMの削除 〇 〇 〇 VMのクローン 〇 〇 〇 リソース拡張(CPU/メモリ/ボリューム) 〇 ボリュームの削減はできない リソース拡張はVMの再起動が伴う 〇 ボリュームの削減はできない リソース拡張はVMの再起動が伴う 〇 ボリュームの削減はできない リソース拡張はVM無停止で可能 VM/ノード管理 VMの可用性 VMの自動復旧機能 〇 runStrategyで、VMの自動復旧機能を実現 〇 runStrategyで、VMの自動復旧機能を実現 〇 VMのライブマイグレーション 〇 〇 〇 クラスターノードの可用性 クラスターノードの自動復旧機能 △ Workload Availability *1でクラスターノードの自動復旧を実現 ✕ 手動で障害ノードを復旧するか、新規ノードを用意 ✕ ホストの自動復旧機能は提供されていない VM管理 テンプレート機能 〇 〇 〇 クォータ(リソース制限)の設定 〇 △ Rancherとの統合でnamespaceのクォータ設定を実現 〇 CPU/メモリ/ストレージ I/Oの上限を指定可能 ホスト名の名前設定の可否 〇 〇 〇 VM内部からホスト名を変更することも可能 認証 認証基盤連携 ユーザー認証基盤との連携機能 〇 〇 Rancherとの統合で、ユーザー認証基盤との連携を実現 〇 ネットワーク 負荷分散 複数VMへのアクセスの負荷分散 〇 Routeを使用してL7の負荷分散を実現 Metal LBを使用して、L2,L3の負荷分散を実現 〇 組み込みのHarvester LBを利用して、L4の負荷分散を実現 △ アドオン、または外部ソリューションとの組み合わせで負荷分散を実現 DNS設定 DNS設定 〇 〇 〇 Pod/VMのIP固定化 Pod/VMの静的IP 〇 VMに付与した2つ目のネットワークで静的IP設定が可能 〇 VMに付与した2つ目のネットワークで静的IP設定が可能 〇 モニタリング&ロギング モニタリング VM/クラスターノードの標準モニタリング(CPU/メモリ/IOPS) 〇 〇 〇 VM / クラスターノードの死活監視 〇 〇 〇 ロギング VM / クラスターノード のロギング 〇 △ 外部のログサーバーとの統合でログデータの保存を実現 〇 データ管理 スナップショット スナップショット 〇 〇 〇 バックアップ バックアップ △ OADP Operatorインストールで実現 〇 △ ホストのバックアップは可能 VMのバックアップは、VADP *2を使用して別バックアップツールと連携することで実現 スケジューリング スナップショットのスケジューリング ✕ 〇 〇 バックアップのスケジューリング △ OADP Operatorインストールで実現 〇 ✕ セキュリティ マルチテナント 異なるテナントごとにリソースを論理的に分離する機能 〇 OCPのプロジェクト機能を使用して テナントごとにリソースの分離、セキュリティの強化を実現 △ Kubernetes標準の機能で簡易的なリソース分離が可能。Rancherと統合することで十分なマルチテナント機能を実現 ✕ アクセス制限 VM間または外部へのアクセス制限 〇 OCPのネットワークポリシーを利用してアクセス制御を実現 〇 〇 RBACでのVM操作・管理の制御 〇 OCPのRBACを利用して、プロジェクトに対するユーザーの権限制御を実現 △ Rancherと統合しRBAC機能を活用してユーザーの権限制御を実現 〇 ストレージ ボリューム 永続ボリューム 〇 〇 〇 分散ストレージ △ ODFをインストールして分散ストレージを実現 〇 △ Storage vMotionに相当する機能 ✕ ✕ 〇 ボリューム形式の種類 – ブロック ファイル – ブロック ファイル – ブロック ファイル ストレージ バックエンドのストレージ対応種類 〇 多くのストレージベンダーのCSIプラグインが提供 〇 多くのストレージベンダーのCSIプラグインが提供 〇 クラスター管理 バージョンアップ バージョンアップのプロセスの容易さ 〇 簡単にバージョンアップすることが可能 バージョンアップ中にVMを停止する必要はない 〇 UIから簡単にバージョンアップすることが可能 バージョンアップ中にVMを停止する必要はない △ 事前準備、バージョンアップ作業が入る 対応プラットフォーム 対応プラットフォーム 対応プラットフォーム – オンプレミス AWS – オンプレミス Equinix – オンプレミス 多くのクラウドベンダー *3 *1 Workload Availability:Workload Availability for Red Hat OpenShift *2 VADP:VMware vStorage API for Data Protection *3 多くのクラウドベンダー:VMware Cloud on AWS、Azure VMware Solution、Google Cloud VMware Engine、Oracle Cloud VMware Solution に対応している   各製品の利用ケース どの仮想化基盤も基本的な機能の共通点が多く、優れた環境を提供しますが、それぞれが特定の利用ケースに適している場合があります。 OCP-Virtの利用ケース OpenShift(OCP) の機能を利用した効率的な運用 OpenShift(OCP) 側のセキュリティ、モニタリング、ロギング、ユーザー管理などの様々な機能をOCP-Virtでも利用できます。既存のコンテナ運用と統合して管理することで効率的な運用を実現できます 基盤となるノードの復旧対応の効率化 Workload Availability for Red Hat OpenShift機能を用いて構成するノードの自動復旧・自動追加機能を活用して柔軟なノード管理ができます RHEL OSの利用 多くのRHEL OSのVMを構成するユーザーは、ライセンス費用低減のメリットを享受できます SUSE-Virt利用ケース 標準のデータ管理機能 Harvester標準に備わっているスナップショット機能、バックアップ機能およびそれらのスケジューリング機能を使用して、安定したデータ管理機能を素早く実現できます Rancherとの統合 既存のKubernetesクラスターがあり、KubernetesクラスターとHarvesterをRancherで統合管理することができます Rancherと統合することにより、ユーザー認証基盤の連携、テナント管理、RBACなどの機能を一元的に管理することができます コストを抑えた仮想化基盤の利用 OSSの性質から基本的に無償で利用でき、大きな投資をせずに堅牢な仮想化基盤を必要とするユーザーに適しています vSphere利用ケース シンプルなネットワーク構成 vCenterでの包括的なvSwitchの管理などを実現できます。また複数のネットワーク構成をする際もシンプルな方法での構成を提供しています より広範なストレージ機器の利用 ストレージ機器の選定の幅が広いため、他の仮想化基盤に対応していないストレージ機器を使用したいユーザーに適しています バージョンアップ運用の負担軽減 Kubernetes環境のリリースの速さに追従する必要がないため、バージョンアップに係る運用面の負担を軽減できます まとめ 今回は、今までご紹介したOCP-Virt, SUSE-Virtと vSphere を含めて3製品の比較をしてみました。 基本的な機能についてはどの製品も提供していますが、利用ケースに応じた選定の一要素として、いくつか比較ポイントが見えました。 仮想化基盤を比較する上でこの記事が比較の参考になれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Virtualization, SUSE Virtualization, VMware vSphere の比較 first appeared on SIOS Tech. Lab .
今号では、Linux におけるパーミッションについて説明します! パーミッションとは パーミッションとは、Linux におけるファイルやディレクトリに対する アクセス権限 のことです。 一般ユーザとして使用している場合、あまりパーミッションについて意識することは少ないかもしれませんが、普段利用しているすべてのファイルやディレクトリにパーミッションが設定されています。 「誰が」「どのような操作を」許可されているかを決める重要な仕組みであり、パーミッションが適切に設定されていないと 不正アクセス や データの改ざん 、 誤ってプログラムを実行してしまう 可能性があります。 なお、パーミッションはファイルを作成するごとに自分で設定する必要はなく、システム側の設定とアプリ側の設定を組み合わせた上で、それぞれデフォルトのパーミッションが割り振られます。 適宜、パーミッションを変更しながら運用していくことになります。 パーミッションの考え方 Linux では、ファイルやディレクトリのパーミッションは下記 3つのカテゴリに分けられます。 Owner (所有者) :ファイルを作成したユーザ Group (グループ) :Owner が所属するグループ Other (その他) :Owner 以外の全ユーザ また、各カテゴリに対して下記 3つの権限を設定できます。 r (読み取り) :ファイルの読み取り権限 w (書き込み) :ファイルの書き込み権限 x (実行) :ファイルの実行権限 (プログラムやスクリプトを実行する場合) パーミッションの確認方法 最も簡単なのは、 ls -l コマンドを実行してファイルの情報を表示する方法です。 $ ls -l test.txt -rw-r--r--. 1 ykaino ykaino-group 0 Mar 24 12:00 test.txt 出力された各内容を、それぞれ説明します。 -rw-r–r– :パーミッションを表す文字列 1 :リンク数。通常は 1となるが、ハードリンクがある場合は増加する ykaino :Owner。ファイルを作成したユーザ名 ykaino-group :group。Owner が所属するグループ名 1234 :ファイルサイズ (byte 単位) Mar 20 10:00 :ファイルの最終更新日時 example.txt :ファイル名 (ディレクトリの場合はディレクトリ名) 続いて、パーミッションを表す文字列について説明します。 上記で出力された文字列 ( -rw-r–r– ) を例にすると、 1文字目 (-):ファイルの種類。- は通常のファイル、d はディレクトリ、l はシンボリックリンクとなる 2~4文字目 (rw-):Owner (所有者) の権限。読み、書きは許可、実行は不可 5~7文字目 (r–):Owner がいるグループに所属する、他のユーザの権限。読みは許可、書き、実行は不可 8~10文字目 (r–):上記に該当しない他のユーザの権限。読みは許可、書き、実行は不可 なお、ls -l コマンドの他に、 getfacl コマンドを実行してファイルの情報を表示する方法もあります。 $ getfacl test.txt # file: test.txt # owner: ykaino # group: ykaino-group user::rw- group::r-- other::r-- デフォルトのパーミッション 上記の test.txt ファイルでは、ユーザに読み、書きの権限があり、グループおよびその他のユーザには読み取り権限のみが与えられていました。 これは、ファイルやディレクトリにデフォルトで設定されるパーミッションがあらかじめ決められているために上記のような結果となっています。 デフォルトのパーミッションは umask というパラメータで設定されます。 ls -l コマンドの実行結果では、各権限を r (読み取り)、w (書き込み)、x (実行) で表現しましたが、 umask では各権限を数値で表現します。 r (読み取り) :4 w (書き込み) :2 x (実行) :1 例えば、読み取りと書き込みの権限がある場合は 4 + 2 = 6 、読み取りと実行の権限がある場合は 4 + 1 = 5 のように考えます。 Linux ファイルシステムでは、ファイルの基本パーミッションが 666 (読み書きのみ、実行権限なし) 、ディレクトリの基本パーミッションが 777 (読み書き実行すべて可能) になっています。そこから umask の値を引き算して、最終的なパーミッションが決定します。 現在の umask の値は umask コマンドで確認できます。 # umask 0022 ファイルの場合は 666 から 022 を引いて 644 (Owner は読み、書き権限あり、グループおよびその他のユーザには読み取り権限あり) 、ディレクトリの場合は 777 から 022 を引いて 755 (Owner は読み、書き、実行権限あり、グループおよびその他のユーザには読み、実行権限あり) になります。 umask の値を一時的に変更する場合は umask コマンドを実行します。 $ umask 027 永続的に変更する場合は ~/.bashrc もしくは ~/.profile などのファイルに、下記の様な umask の設定を追加します。 umask 027 次号では、パーミッションの変更方法や、特殊なパーミッションについて説明します! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!ファイルのパーミッションについて1 first appeared on SIOS Tech. Lab .
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 Google は 3月の Pixel Feature Drop (Pixel 端末向けアップデート) で、Linux のネイティブアプリを導入しました。 グーグル、「Android」向けに「Linux」ターミナルを追加–まずは「Pixel」で導入 https://news.yahoo.co.jp/articles/d3473c2e2a2cd2d4e084b2e4b65d2d9953d0277f Google は、日本企業のサイバーセキュリティ意識の向上と専門人材の育成を支援する「Japan Cybersecurity Initiative」を立ち上げました。 日本のサイバーセキュリティの底上げに向けた産学官連携「Japan Cybersecurity Initiative」を設立 https://blog.google/intl/ja-jp/company-news/technology/cybersecurity-initiative/ 2025/3/19、FinOps Foundation の創始者が執筆した「クラウドFinOps 第2版 ー協調的でリアルタイムなクラウド価値の意思決定」の日本語書籍が出版されました。 国内初、Linux Foundation傘下のFinOps Foundationが公認した『クラウドFinOps 第2版 ー協調的でリアルタイムなクラウド価値の意思決定』の日本語書籍が本日出版 https://prtimes.jp/main/html/rd/p/000000133.000015260.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年3月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
サイオステクノロジーの菊地啓哉です。思ったより間が空いてしまったのですが、 前回 の記事の続きになります。 ECDSA や zk-STARK などでは有限体がベースにあるので、 前回 の体の話から、有限体の話に進んでいこうと思います。 自分が有限体について調べた時には、体の拡大に急に既約多項式が出てきて飲み込みにくいところがあったので、そのあたりに少しだけ間の内容を入れています。 数学に詳しくないエンジニアの体入門 数学に詳しくないエンジニアの有限体 巡回群 前回 も少し触れましたが、 巡回群 についてご紹介したいと思います。この群は、ただ1つの元で生成される群で、 mod n(nで割った余り)の中での足し算もこれの具体例の1つとなります。 例えば、単位元 e、生成元 g、要素数 4 の巡回群 G について考えると、 g ○ g = g 2 のように演算 ○ の繰り返しを累乗のように表現するなら G の元は のように表すことができます。これは整数の足し算の4で割った余りが元の数の4で割った余り同士の足し算(をさらに4で割った余り)と同じです。 13(4で割ると余り1)+ 22(4で割ると余り2) = 35(4で割ると余り3) 6(4で割ると余り2)+ 35(4で割ると余り3) = 41(4で割ると余り1) 有限体 有限体の性質 体のうち、元が有限個のものを 有限体(ゆうげんたい、Finite Field) と呼びます。話がとても難しくなってしまうので導出はしませんが以下のような性質を持ちます。 3点目については、有限群の性質から導けます。1点目と2点目は実力不足で分かりやすくまとめられなさそうなので諦めました(これは3点目のフェルマーの小定理にかけているわけではありません)。 有限体の例 mod 3 の足し算、掛け算で体を考えます。ここでは、mod 3 であることを忘れないように、下添え字の 3 をつけます。可換であることを踏まえて通常の計算と異なるのは、以下の3つです。 mod 3 だということを考えれば特に問題無いかと思います。 とても簡単ですが、「体の元から零元を除くと乗法に関して巡回群となる」について確認しておくと、 となるので、零元を除くと、乗法に関して元の数が2の巡回群となっていることがわかります。 なんで、こんな元の数が少ない体にしたかと言えば、後でこの体を拡大します。 有限体で方程式を解く 前回 の記事で、体の中で方程式を解くのが普通にやってるのと同じと書いたので、実数の世界で -2 と 1/2 が解の二次方程式を mod 3 の体で解いてみたいと思います。この二次方程式は次のように書けます。 これは、特に上に書いた計算を利用することで、1 3 + 2 3 = 0 3 、2 3 * 2 3 – 1 3 = 1 3 – 1 3 = 0 3 なので、 x = 1 3 , 2 3 と解くことができます。こういった具合に、有理数係数の方程式は割と有限体の方程式にそのまま考え直すことができます。ただし、0除算があってはいけないので、この mod 3 の体で考えるには分母が3の倍数の解があると上手くいきません。 この方程式の両辺を 2 3 倍して、式を展開してみましょう 当然と言えば当然ですが、最後の式を見ると、解と係数の関係が成り立っていることも見て取れると思います。 Bitcoin や Ethereum では、secp256k1 と呼ばれる楕円曲線(のパラメータ)を採用しているようで、そこでは有限体の元の数 p は 2 256 – 2 32 – 2 9 – 2 8 – 2 7 – 2 6 – 2 4 – 1 という、とても大きな値を使っています。 完全に余談ですが、ECDSAで楕円曲線上の点と点の足し算を定義して、その繰り返しとしてスカラー倍を定めているのに、表記によってはいつのまにか、スカラー倍の部分が分数で表現されていたりするのは、繰り返しの数を表す係数側が有限体の元であり、逆数は逆元を意味しているので、分数を計算すれば自然数になることなどを前提としていますね。 せっかく有限体の話を書いてきたので、要素数が素数の有限体を拡大するところに触れたいと思います。その前に少し寄り道をします。 有理数と平方根 前回の記事の群の例を見ていただくとわかると思いますが、群となれない理由としてありがちなのは、”逆元が存在すること”が満たされない、かなと思います。 中学で平方根(ルート)を学習された/されることと思いますが、そこで分母の有理化というものがあったと思います。逆元の存在とか、演算が閉じていることとか、そんなことと絡めて授業を受けたという方は恐らくいらっしゃらないとは思いますが、「2乗すると有理数になる」、「分母に平方根があっても分母を有理化できる」など、乗法について体となかなか相性の良い性質を持っています。有理数 a, b と素数 p で a +b√p で表されるような数について掛け算と割り算は以下のようになります。(ここでは素数である必要性はないのですが、 √p が確実に有理数でないようにわかりやすく素数としています) どちらの計算結果も「有理数 a, b と素数 p を用いて a +b√p で表される形」になっています。このことから、「なんか、平方根を使っていい感じの体を作れそうな空気」が出てきます。足し算引き算も問題無さそうなのはおわかりかと思いますのでスキップします。 mod 3 の体を拡大する 先ほどの mod 3 で考えていた体に √2 に相当する数 β を仲間に加えてみます。ここで、 β*β = β 2 = 2 3 です。また、 β 自体が mod 3 でどうなるかは考えず、その係数で mod 3 を考えます。別の表現をするなら、 1 3 + 2 3 = 0 3 の両辺に β を掛けて次の式が得られます。 この集合は、mod 3 の体の元 a, b を用いて、 a+bβ で表すことのできる 9個の元を作れることがわかります。また、この集合が体になることがわかります。 逆元がわかりにくいところだと、 となります。あと、有限体の性質のうち、零元を除いて乗法が巡回群となるということについて、ちょっと計算してみると、 のように、 1 3 + β を生成元にできることがわかります。(上の結果を見て想像できるように他にも生成元にできる元があります) ここでは、 mod 3 の有限体に β 2 = 2 3 となる元 β を加えて、新しい体を作りました。 これと同じように一般的には、既約多項式という「より低次の多項式で因数分解できない多項式」を使って、”既約多項式 = 0”で定義される新しい元( α とします)を定め、体を拡大します。また、その時、拡大前の体の元の数を p 、既約多項式の次数を n とすると、各 α k (k=0, 1, …, n-1) の係数が p 種類取り得るので、作られる体の元の数は p n となります。今回の例の β であれば、 β 2 = 2 3 の右辺が 0 になるように変形して既約多項式は β 2 + 1 3 となります。 先の例よりも次数が上の具体例として、これまで扱ってきた mod 3 の体に α 3 + 2 3 α + 1 3 = 0 3 で定められる α を追加すると、四則演算によって、 a + b α + cα 2 で表される 3 3 個の元ができ、それらによって、体が作られます。ここで、 a, b, c は mod 3の体の元で、1つ前の体と比べると、 cα 2 が増えた分、元の数が3倍になっています。 α の多項式の次数が2次以下となるのは α 3 = -2 3 α – 1 3 なので、 α の3次以上の項は次数を落とすことができることからわかります。 おわりに 前回同様、全く技術的なことには触れずに数学の体について書きました。駆け足ではありますが、有限体のがどのようなものか紹介しました。難しくならないようにできるだけ深入りせずにざっと書いてみましたが、いかがだったでしょうか。次はどのように有限体が使われているのか書ければ良いなと思っています。 ということで、今回はここで終わりとなります。 またかきます またね ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 数学に詳しくないエンジニアの 有限体 first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。今回はNext.js 15でApp Routerを利用した際のStatic Exportsについて整理します。 Static Exportsとは? Static Exportsは、build時に、アプリケーションを静的コンテンツとしてエクスポートできる機能です。Static Exportsを利用せずにNext.jsのアプリケーションを公開する場合はNode.jsランタイムが必要となりますが、Static Exportsを利用してbuildをかけた場合はクライアントサイドだけで動くコードが吐き出されるので、Node.js環境が必要なくなるのがメリットです。 Static Exportsのやり方 公式ガイド : https://nextjs.org/docs/app/building-your-application/deploying/static-exports next.config.jsにて output: ‘export’, の記述を追加すると、静的エクスポートを利用できるようになります。 import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "export", }; export default nextConfig; その後、 npm run build を実行すると、 out ディレクトリにHTML/CSS/JS assetsが作成されます。 Static ExportsでServer Componentsを利用した場合の挙動 名前にserverとついているためややこしいですが、Static ExportsでServer Componentsを使用することは可能です。ただ、注意点があり、ビルド時にServer Componentsが実行されて生成されたコンテンツに固定されます。 わかりやすく説明するために、ランダムに4桁の数字を返してくれるAPIのFetchのClient Components上で行った場合と、Server Components上で行った場合に分けて考えてみましょう。 通常のデプロイを利用してNode.jsサーバー上にデプロイ Client Components上で行った場合とServer Components上で行った場の両方でリクエストが来るたびにフェッチを行い、毎回ランダムな値(一回目 : 3592, 二回目 : 5285 …)を表示します。 Static Exportsを利用 Client Components上で行った場合 リクエストが来るたびにフェッチを行い、毎回ランダムな値(一回目 : 3592, 二回目 : 5285 …)を表示します。 Server Components上で行った場合 ビルド時にServer Componentsが実行されて一度フェッチが行われます。(値は6472)。サーバーを起動してリクエストを送ると以降6472だけ表示され続けられます。 Dynamic Routesの使用に制限がある Next.jsにはリクエストに応じて動的データからルートを作成してくれるDynamic Routesという機能があります。以下のように[slug]ディレクトリを作成することで使用することができます。 ルート URLの例 params app/blog/[slug]/page.js /blog/a { slug: 'a' } app/blog/[slug]/page.js /blog/b { slug: 'b' } app/blog/[slug]/page.js /blog/c { slug: 'c' } このDynamic Routesの機能ですが、リクエストごとにサーバーでルートを作成するといった機能のため、基本的にはStatic Exportsでは利用することが出来ません。 ただ、Dynamic Routesに、 generateStaticParams という関数を利用することで、ビルド時にfetchを行い、静的にルートを作成することができます。この機能を利用することで、Static Exportsを利用した場合でも静的にルートを作成したページに関してはアクセスできるようになります。 そのほかサポートされていない機能 Static Exportsではサーバーで動く機能は使用できないため、MiddlewareやServer Actionsといった機能を使用することが出来ません。2025/02の段階で使用できない機能は以下の機能です。 Dynamic Routes  with  dynamicParams: true Dynamic Routes  without  generateStaticParams() Route Handlers  that rely on Request Cookies Rewrites Redirects Headers Middleware Incremental Static Regeneration Image Optimization  with the default  loader Draft Mode Server Actions Intercepting Routes 公式ガイド : https://nextjs.org/docs/app/building-your-application/deploying/static-exports#unsupported-features まとめ 今回はNext.jsのStatic Exportsについてまとめました。特にServer Componentsについては曖昧な理解だったため今回実際にコードを書いて挙動を確認したことにより理解を確かにすることが出来ました。「Static ExportsでServer Componentsを利用しているのになぜbuildが通るんだろう?」といった疑問を持っていた方の助けになれば幸いです! ではまた~ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Next.js】App Routerを利用した際のStatic Exportsについて整理する first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの和田です。今回はEthereumのウォレットアドレス(EOA)の本人確認をMetaMaskの署名機能を使って試したので、実装方法などを書いていきたいと思います。 署名の検証方法 署名の検証を実装するために、以下のツールを使用しました。 フレームワーク Next ライブラリ React Web3 ethers ブラウザ拡張機能 MetaMask 署名の検証プロセスは以下の手順で行います。 MetaMaskでウォレットを接続する MetaMaskで署名を作成する 署名とメッセージをサーバーに送信する サーバー側で署名を検証する クライアント側で署名の検証結果を受け取る 実装 それでは実装していきたいと思います。以下に実際に試したソースコードを記載します。 app/components/Web3Auth.tsx "use client"; import { useState, useEffect } from "react"; import Web3 from "web3"; declare global { interface Window { ethereum?: any; } } const Web3AuthClient = () => { const [account, setAccount] = useState<string | null>(null); const [message, setMessage] = useState<string>("Sign this message to login."); const [web3, setWeb3] = useState<Web3 | null>(null); const [recoveredAddress, setRecoveredAddress] = useState<string>(""); useEffect(() => { if (window.ethereum) { setWeb3(new Web3(window.ethereum)); } }, []); const connectWallet = async () => { if (!web3) { alert("MetaMaskをインストールしてください。"); return; } try { const accounts = await window.ethereum.request({ method: "eth_requestAccounts", }); setAccount(accounts[0]); } catch (error) { console.error(error); } }; const signMessage = async () => { if (!web3 || !account) return; try { const signedMessage = await web3.eth.personal.sign(message, account, ""); // API に署名データを送信して検証 const response = await fetch("/api/verify-signature", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message, account, signature: signedMessage }), }); const result = await response.json(); if (result.verified) { alert("署名の検証に成功しました。"); setRecoveredAddress(result.recoveredAddress); } else { alert("署名の検証に失敗しました。"); } } catch (error) { console.error(error); } }; return ( <div className="p-4 border rounded shadow-md"> <h2 className="text-lg font-bold mb-2">Web3 認証</h2> {account ? ( <> <p> 接続したアカウント: <strong>{account}</strong> </p> <p> 復元されたアドレス: <strong>{recoveredAddress.toLowerCase()}</strong> </p> <button onClick={signMessage} className="px-4 py-2 bg-blue-500 text-white rounded mt-2"> 署名を検証する </button> </> ) : ( <button onClick={connectWallet} className="px-4 py-2 bg-green-500 text-white rounded"> ウォレットに接続する </button> )} </div> ); }; export default Web3AuthClient; app/api/verify-signature/route.ts import { NextRequest, NextResponse } from "next/server"; import { verifyMessage } from "ethers"; export async function POST(req: NextRequest) { try { const { message, account, signature } = await req.json(); if (!message || !account || !signature) { return NextResponse.json({ error: "Missing parameters" }, { status: 400 }); } const recoveredAddress = verifyMessage(message, signature); const isValid = recoveredAddress.toLowerCase() === account.toLowerCase(); return NextResponse.json({ verified: isValid, recoveredAddress }, { status: isValid ? 200 : 401 }); } catch (error) { console.error("Signature verification error:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } } app/page.tsx import Web3Auth from "./components/Web3Auth"; export default function Home() { return ( <div className="min-h-screen flex items-center justify-center bg-gray-100"> <Web3Auth /> </div> ); } 動作確認 上記で作成したアプリを動かしてみます。 npm run dev で起動し、 localhost:3000 にアクセスします。すると以下のような画面が表示されます。 ウォレットに接続するをクリックするとメタマスクのパスワードを聞かれるので入力してロック解除します。 すると以下のような画面が表示されます。メタマスクで選択されているアカウントが表示されています。 署名を検証するをクリックします。クリック後、以下のような署名要求のポップアップが表示されるので、確認をクリックします。 確認をクリック後、以下のように署名の検証結果が表示されます。 OKをクリックすると、以下のように復元されたアドレスが表示されます。サーバー側で署名から復元したアドレスと接続したアカウントのアドレスが一致していることが確認できました。 まとめ 今回は MetaMask の署名機能を利用して EOA の所有者を検証する簡単なアプリケーションを実装しました。署名の検証プロセスを通じて、EOA 所有者の本人確認を実現できることが確認できました。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Ethereumウォレットアドレスの署名検証試してみた first appeared on SIOS Tech. Lab .
こんにちは。サイオステクノロジー OSS サポート担当 山本 です。 今回も solr のお話です。 solr スキーマの数多ある “ フィルタ ” から、比較的効果が実感しやすいと思われる応用フィルタ Synonym (同義語・類義語) についてお話してみようと思います。 ■solr の Synonym ってどういうもの? Synonym は先述のとおり 同義語 または 類義語 を示す言葉です。 文字通り、同じような意味の言葉や似たような意味の言葉のことで、 例えば「青」と「ブルー」は同義語ですし、「お皿」と「プレート」は類義語と言えるでしょう。 ところで、改めてですが solr は インデックス という仕組みを使って 予め登録しておいた一連のデータ である ドキュメント から高速な 文字列検索 を行うことに特化した、全文検索 OSS です。 そう、solr はインデックスの 文字列検索 によってドキュメントを検索しています。 なので、当たり前と言えば当たり前ですがデフォルトでは 「 青 」で検索しても「 ブルー 」のドキュメントは 出てきません 。 でも、仮に自分が検索する側として考えてみてください。 例えばショッピングサイトで、「カーテン 青」で検索した場合と「カーテン ブルー」で検索した場合の検索結果が全く違っていたら? それらの検索結果で出てきたもの以外にも、「カーテン 藍色」「カーテン ネイビー」などで検索すると別の青色系カーテンのラインナップがあったりしたら? きっと不便と言うか機会損失というか、「いや、まとめて出してくれよ…」と思うことでしょう。 solr の Synonym は、こういった 同一の検索ワードとして扱ってほしい同義語・類義語の組 を 予め登録 しておくことで、検索ワードの同義語・類義語も一緒に検索できるようにする仕組みです。 Synonym はまた、「パソコン」と「PC」、「パーソナルコンピュータ」といったような 略記・略称・通称・正式名称 などが混在するドキュメント群をいい感じに検索できるようにするためなどにも使うことができます。 ■Synonym を使ってみる というわけで Synonym を試してみましょう。 今回も前回までで使用した環境 “test-new-core” に Synonym の設定を追加して試していきます。 (前回までの内容は省略するため、ベースとなるコアの作り方などのお話は以前の記事を参照してください。) Synonym を使うには、 Synonym 用の辞書 の作成をした上で、Synonym を使用するように スキーマファイルの設定を変更 する必要があります。 ■辞書の作成 まずは辞書を作ってみます。 例によってデモ用環境のコア “demo” にサンプルが入っているので、まずはこちらを確認してみましょう。 以下のコマンドで前回までに作成した環境を起動し、サンプルを手元の環境にコピーします。 ## (デモ用環境起動) $ podman start test-solr ## (Synonym 辞書サンプルのコピー) $ podman cp test-solr:/var/solr/data/demo/conf/synonyms.txt ./ 手元の環境にコピーした Synonym のサンプルファイル “ synonyms.txt ” を適当なテキストエディタで開き、まずは内容を確認してみます。 行頭が “#” の行はコメント行扱いとなるので、(ファイルの先頭のユーザ辞書の説明コメント部分を除くと) このファイルはこのような記述がされています。 #some test synonym mappings unlikely to appear in real input text aaafoo => aaabar bbbfoo => bbbfoo bbbbar cccfoo => cccbar cccbaz fooaaa,baraaa,bazaaa # Some synonym groups specific to this example GB,gib,gigabyte,gigabytes MB,mib,megabyte,megabytes Television, Televisions, TV, TVs #notice we use "gib" instead of "GiB" so any WordDelimiterGraphFilter coming #after us won't split it into two words. # Synonym mappings can be used for spelling correction too pixima => pixma ざっくりと 2種類の書式がありそうな、普通のテキストファイルであることがわかりますね。 それぞれの書式についてまず見ておきましょう。 [類義語A](,[類義語B],…) => [類義語C](,[類義語D],…) まず “=>” があるほうのこちらの書式ですが、 [類義語A] ( または [類義語B]…) を、[類義語C] ( および [類義語D]…) に変換する というものです。 例えば、上記のサンプルファイルの cccfoo => cccbar cccbaz は、「cccfoo」が「cccbar」+「cccbaz」に変換されるようにする記述です。(Synonym 処理後、 元の「cccfoo」は残りません 。) ※ 上記サンプルファイルの抜粋では 半角スペース 区切りで類義語を列挙していますが、 公式ドキュメント の Synonym の書式では “ , (カンマ) ” で分割するように記載されています。試したバージョンではいずれの記法でも機能しましたが、本記事では “ , (カンマ) ” 区切りで記載していきます。 つづいてもう片方の書式です。 [類義語E],[類義語F](,[類義語G],…) “, (カンマ)” 区切りでただ列挙するこちらの書式では、 列挙した類義語の いずれか が、列挙した類義語 全て に変換 されます。 例えば上記サンプルファイルの GB,gib,gigabyte,gigabytes は、「GB」「gib」「gigabyte」「gigabytes」のいずれも「GB」+「gib」+「gigabyte」+「gigabytes」に変換されるようにする記述になります。 さて、書き方はなんとなくわかったかと思いますので、試しに何か Synonym を追加してみましょう。 今回は果物の名前で試してみることにします。 今確認している、手元に持ってきた “synonyms.txt” の末尾に以下の記述を追加してみます。 ぶどう,葡萄,グレープ 林檎,アップル => りんご strawberry,苺 => ストロベリー,いちご 設定を追加したら、この “synonyms.txt” を “test-new-core” のディレクトリに配置します。 配置箇所はスキーマファイル “managed-schema.xml” から相対パスで指定できる場所なら大丈夫なはずですが、今回は “managed-schema.xml” と同じ conf 直下に配置しましょう。 $ podman cp ./synonyms.txt test-solr:/var/solr/data/test-new-core/conf/synonyms.txt これで Synonym 設定ファイルの準備は OK です。 ■Synonym フィルタの設定 次に、スキーマファイル “managed-schema.xml” に Synonym を使用する設定を追加します。 実験用コア “test-new-core” のスキーマファイル “managed-schema.xml” を一旦手元に持ってきて… (デモ用コンテナにはテキストエディタがないため) $ podman cp test-solr:/var/solr/data/test-new-core/conf/managed-schema.xml ./managed-schema.xml このスキーマで日本語解析の設定を行なっている部分の “<analyzer>” 要素の中に、Synonym を処理する “ synonymGraph ” の <filter> 要素を追加します。 ここで、この <filter> 要素を追加する位置は極めて重要 になりますが、今回は “cjkWidth” フィルタの後ろに置いてみましょう。 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &lt/fieldType> 設定を変更したら、この “managed-schema.xml” をコア “test-new-core” に戻します。 $ podman cp ./managed-schema.xml test-solr:/var/solr/data/test-new-core/conf/managed-schema.xml これで Synonym を使うように設定ができました。 ■設定の適用と Synonym 処理の確認 それでは、Synonym の処理を確認してみます。 変更したスキーマの設定を読み込むため、”test-new-core” をリロードします。 コマンドでリロードするなら以下のようなコマンドを $ curl -X POST http://(IP or ホスト名):8984/api/cores/test-new-core/reload 管理画面でリロードするなら “ Core Admin ” の画面から対象のコアを選択して、” Reload ” ボタンを押してください。 これで “test-new-core” で Synonym を処理する設定を適用できました。 早速、管理画面で試してみましょう。 “Core Selector” タブで test-new-core を選び、” Analysis ” を開いて、Synonym を適用した FieldType “text_ja” で先ほど追加した Synonym が処理されるのかを確認してみましょう。 ぶどう,葡萄,グレープ 「ぶどう」「グレープ」(と「葡萄」)のいずれを解析した場合でも、解析結果が「ぶどう」「葡萄」「グレープ」の3単語になることが確認できます。 林檎,アップル => りんご “=>” の左辺にある「林檎」(または「アップル」) を解析した場合、解析結果が “=>” 右辺の「りんご」になることが確認できます。 逆に、”=>” の右辺にある「りんご」を解析した場合は「りんご」のままです。 strawberry,苺 => ストロベリー,いちご “=>” の左辺にある「strawberry」(または「苺」) を解析した場合、解析結果は “=>” 右辺の「ストロベリー」「いちご」の2単語になることが確認できます。 逆に、”=>” の右辺にある「いちご」(または「ストロベリー」)を解析した場合は「いちご」(または「ストロベリー」)のままです。 このように、先にお話ししたとおりの結果になることが確認できるかと思います。 ということで、これで Synonym の設定方法は大丈夫そうですね。 ただし、 Synonym を追加した場合 (フィルタの追加などで解析方法を変更した場合)、当然ながら解析結果は変わります 。 そして、前回長々とお話ししたとおり、 solr の検索の要である インデックス は ドキュメントの登録時の解析結果 を元にしており、 後の設定変更には対応していません 。 このため、原則として Synonym を追加した場合 (勿論、他のフィルタを追加した場合などにも) は、登録済みのドキュメント・インデックスを一度削除して登録処理をやり直す 再インデックス が必要 になります。 ■Synonym とフィルタ順序 スキーマで “<filter>” 要素を追加する位置が重要 である、と先にお話ししましたが、こちらについて少し見てみましょう。 まず、今回行なった設定の状態で全角の「グレープ」と半角の「グレープ」をそれぞれ解析してみてください。 どちらも問題なく今回設定した Synonym により「ぶどう」「葡萄」「グレープ」の3単語に解析されるはずです。 では、”test-new-core” の “managed-schema.xml” で以下のように設定を変更してみてください。 (“synonymGraph” フィルタを、一行前の “cjkWidth” フィルタの前に持ってきます) #### 変更前 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &lt/fieldType> #### 変更後 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &lt/fieldType> 設定変更の後に “test-new-core” のリロードを行ったら、再度全角の「グレープ」と半角の「グレープ」をそれぞれ解析してみてください。 このとおり、半角の「グレープ」は今回設定した Synonym が適用されなくなっています。 なぜこのようなことになるかと言うと……  1. 解析処理は “managed-schema.xml” の 設定の上から順に 行われる  2. Synonym フィルタは日本語の半角文字と全角文字を区別している  3. 順序を入れ替えた “cjkWidth” フィルタが日本語の半角文字を全角文字に変換するフィルタだった ……からです。 このことからわかるように、 フィルタの設定順序は解析結果に大きく影響を与える 可能性があります。(これは即ち、検索結果がおかしくなる可能性があるということです。) そして、Synonym については Synonym フィルタを適用する時点での解析結果に合致させるように記述 しなければ効果がないということもわかるかと思います。 このため、Synonym を使いこなすには、もといフィルタを追加・変更する場合には、 事前に各フィルタの処理内容を把握しておくことが極めて重要 と言えます。 → Solr Reference Guide ■ちょっと高度な設定:インデックス登録時と検索時の解析方法を別々にする ここからは大分はみ出したお話しです。 まずは今回 Synonym に設定したこれをもう一度見てください。 ぶどう,葡萄,グレープ これは今回見てきたとおり「ぶどう」または「葡萄」「グレープ」を、これら3単語の全てを含むように変換する設定です。 ところで、solr は (解析結果で出てきた単語では) 原則 or 検索をします。 なので、よくよく考えてみると……  ・インデックス作成時にこの Synonym 処理をした場合、検索時には「ぶどう」「葡萄」「グレープ」のうちいずれか1つの単語が含まれていればよいため、検索時にはこの Synonym 処理をしなくても正常に意図したとおりの検索できる  ・検索時にこの Synonym 処理をしていれば、「ぶどう」「葡萄」「グレープ」のどれで検索しても、インデックスに「ぶどう」「葡萄」「グレープ」のいずれかを含むドキュメント全てに hit するため、インデックス作成時にこの Synonym 処理をしていなくても正常に意図したとおり検索できる ……ということで、実はインデックス時か検索時のどちらかでだけこの Synonym 処理をすれば事足りています。 特に、検索時だけ Synonym 処理をする場合は再インデックス処理の必要もなくなるので、Synonym 設定変更時の手間も減りそうです。(インデックスの容量削減も見込めます。) これを実現するための設定方法があるので、一応ここで紹介しておきます。 今回の設定変更を施した “test-new-core” の “managed-schema.xml” の変更例を見てみましょう。 #### 変更前 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &lt/fieldType> #### 変更後 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer type="index"> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &ltanalyzer type="query"> &lttokenizer mode="search" name="japanese" userDictionary="lang/userdict_ja.txt" /> &ltfilter name="japaneseBaseForm"/> &ltfilter tags="lang/stoptags_ja.txt" name="japanesePartOfSpeechStop"/> &ltfilter name="cjkWidth"/> &ltfilter ignoreCase="true" synonyms="synonyms.txt" name="synonymGraph" expand="true"/> &ltfilter ignoreCase="true" words="lang/stopwords_ja.txt" name="stop"/> &ltfilter name="japaneseKatakanaStem" minimumLength="4"/> &ltfilter name="lowercase"/> &lt/analyzer> &lt/fieldType> 大規模に変更しているように見えますが、概ね <analyzer> ~ </analyzer> をコピーして 2つにしただけです。 <analyzer> にはそれぞれ “type” オプションを設定します。 “index” はインデックス時、”query” のほうは検索時の解析方法を設定 します。 この例では更に、”query” 側にだけ “synonymGraph” フィルタを設定しています。 折角なのでこの設定も一応試してみましょう。 “managed-schema.xml” の配置と設定のリロードを行なったら、例によって “Analysis” ページで確認していきます。 実はこのページ、左側がインデックス時の解析、右側が検索時の解析となっているため、この変更のチェックに最適だったりします。 このとおり、設定どおりに検索時にのみ Synonym 処理がされていることが確認できるかと思います。 ただ、解析方法を変えるということは言うまでもなく解析結果も変わるということです。 solr はインデックス時と検索時それぞれの解析結果をもって検索を行うため、これはつまり下手をすれば検索が機能しなくなる危険性があるということです。 例えば今回のこの Synonym 設定です。 林檎,アップル => りんご このセクションでの “managed-schema.xml” の設定下では、  ・インデックス時は Synonym 処理がされないので、インデックスには「林檎」や「アップル」で登録される  ・検索時には Synonym 処理されるので、「林檎」で検索しても「りんご」のインデックスを持つドキュメントしか出てこない (「林檎」で検索しているのに「林檎」のインデックスを持つドキュメントが出てこない) というおかしなことになってしまいます。 この解析方法の分割設定を実施したい場合、自分が何をしようとしているのか、本当に設定しても大丈夫なのかを十分に検討した上で、細心の注意を払い、入念に検証を行なった上で取り掛かることをおすすめします。 ■最後に 今回は solr の Synonym とフィルタ設定についてお話ししてみました。 ここまで数回に渡って solr についてお話しして何となく察してもらえたかと思いますが、 solr は導入して適当にデータを入れれば即便利!というもの ではなく 、 入念な準備と工夫 をすることで 検索時 の利便性・快適さ を提供できるツールです。 なので、solr が力を発揮するのは例えばマニュアルサイトや EC サイトなど、不特定多数の人が検索を行い得る環境であると言えるでしょう。 今回の一連の記事で一通りの基本的な要素をお話しできたかとは思いますが、他にもあいまい検索や N-Gram 検索を実装したりなど様々な設定・フィルタがありますので、気になった方は是非一度試して自分なりの最強の検索環境を作ってみてはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Solr って何者?⑤:解析内容を調整する② (Synonym) first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。 前回はReact Router v7でMSWを利用する方法を整理しました。 2025-02-27 React Router v7のブラウザ開発環境でMSWを利用する方法 今回はNext.jsのApp routerでMSW(Mock Service Worker)を利用する方法について整理していきます。 はじめに 今回の内容は以下のDraft状態のmsw exampleのPull requestを参考に作成しています。 https://github.com/mswjs/examples/pull/101 記事執筆を行っている2025/03の段階ではDraftかつ、Next.js側の問題でブラウザ側でのHMR(Hot Module Replacement) の問題があることが以下のissueで言及されています。 https://github.com/mswjs/msw/issues/1644#issuecomment-2433234922 時間が経てば状況が変わることが予想されますので、そのときには本記事は参考程度にしていただき、上記のPull requestやissueの内容を確認していただければと思います。 MSWの準備を行う MSWを使用するために各種準備を行っていきます。Next.jsアプリは用意済みという前提で進めていきます。 MSWをインストールする 最初にMSWのインストールを行います。 npm install msw -D mockServiceWorker.jsをコピー MSWでは、worker scriptをアプリケーションのpulbicディレクトリに配置することでクライアント上でリクエストをキャッチできるようになります。こちらは以下の形でMSWのCLIを利用することで自分のディレクトリにworkerscriptである mockServiceWorker.jsがpublic直下に作成されます。 npx msw init ./public --save 統合モジュールを用意する server componentsとclient componentsで利用する統合モジュールを用意していきます。これらのファイルを配置するディレクトリとしてプロジェクトのrootディレクトリにmocksというディレクトリを用意してその中にファイルを配置していきます。 MSWのhandlersを定義する mockの内容となるMSWのhandlersをmocks/handlers.tsに定義します。 // mocks/handlers.ts import { graphql, http, HttpResponse } from "msw"; export type User = { firstName: string; lastName: string; }; export type Movie = { id: string; title: string; }; export const handlers = [ http.get<never, never, User>("<https://api.example.com/user>", () => { return HttpResponse.json({ firstName: "Sarah", lastName: "Maverick", }); }), graphql.query<{ movies: Array<Movie> }>("ListMovies", () => { return HttpResponse.json({ data: { movies: [ { id: "6c6dba95-e027-4fe2-acab-e8c155a7f0ff", title: "123 Lord of The Rings", }, { id: "a2ae7712-75a7-47bb-82a9-8ed668e00fe3", title: "The Matrix", }, { id: "916fa462-3903-4656-9e76-3f182b37c56f", title: "Star Wars: The Empire Strikes Back", }, ], }, }); }), ]; browser用の統合モジュールを作成する browser用(client component用)の統合モジュールをmocks/browser.tsに定義します。 // mocks/browser.ts import { setupWorker } from "msw/browser"; import { handlers } from "./handlers"; export const worker = setupWorker(...handlers); node.js用の統合モジュールを作成する node.js用(server component用)の統合モジュールをmocks/node.jsに定義します。 // mocks/node.ts import { setupServer } from "msw/node"; import { handlers } from "./handlers"; export const server = setupServer(...handlers); App routerでMSWを使用する ここからはapp以下で作業を進めていきます。 MSW用のProviderを作成する layout.tsxでMSW用のProviderをapp/mswProvider.tsxに定義します。このProviderで囲うことで、このProvider内のclient componentについてMSWを利用することが出来るようになります。 // app/mswProvider.tsx "use client"; import { handlers } from "@/mocks/handlers"; import { Suspense, use } from "react"; const mockingEnabledPromise = typeof window !== "undefined" && process.env.NODE_ENV === "development" ? import("@/mocks/browser").then(async ({ worker }) => { await worker.start({ onUnhandledRequest(request, print) { if (request.url.includes("_next")) { return; } print.warning(); }, }); worker.start(); console.log(worker.listHandlers()); }) : Promise.resolve(); export function MSWProvider({ children, }: Readonly<{ children: React.ReactNode; }>) { // If MSW is enabled, we need to wait for the worker to start, // so we wrap the children in a Suspense boundary until it's ready. return ( <Suspense fallback={null}> <MSWProviderWrapper>{children}</MSWProviderWrapper> </Suspense> ); } function MSWProviderWrapper({ children, }: Readonly<{ children: React.ReactNode; }>) { use(mockingEnabledPromise); return children; } layout.tsxでnode.js用の統合モジュールの呼び出しとmsw用のProviderでchildrenをラップする 続いてlayout.tsxにてserver側(Runtimeがnode.js)でMSWが利用できるようにします。また、先ほど作成したmsw用のProviderでchildrenをラップします。ここまで終われば準備完了です! // app/layout.tsx import type { Metadata } from "next"; import { Inter } from "next/font/google"; import { MSWProvider } from "./mswProvider"; if ( process.env.NEXT_RUNTIME === "nodejs" && process.env.NODE_ENV === "development" ) { const { server } = await import("@/mocks/node"); server.listen(); } const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en"> <body className={inter.className}> <MSWProvider>{children}</MSWProvider> </body> </html> ); } server component上でfetchを行ってみる ではまずはserver component上でfetchを行ってみましょう。app/page.tsxでhandlerで定義したapiを呼び出してみましょう。 // app/page.tsx import { User } from "@/mocks/handlers"; async function getUser() { const response = await fetch("<https://api.example.com/user>"); const user = (await response.json()) as User; return user; } export default async function Home() { const user = await getUser(); return ( <main> <p id="server-side-greeting">Hello, {user.firstName}!</p> </main> ); } 開発モードで起動して動作を確認してみると、handlerで定義したレスポンスが取れていることが確認できました! client component上でfetchを行ってみる 続いてclient component上でfetchを行ってみます。client componentとして実行されるように”use client”をつけてapp/movieList.tsxを作成します。 // app/movieList.tsx "use client"; import { Movie } from "@/mocks/handlers"; import { useState } from "react"; export function MovieList() { const [movies, setMovies] = useState<Array<Movie>>([]); const fetchMovies = () => { fetch("/graphql", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: ` query ListMovies { movies { id title } } `, }), }) .then((response) => response.json()) .then((response) => { setMovies(response.data.movies); }) .catch(() => setMovies([])); }; return ( <div> <button id="fetch-movies-button" onClick={fetchMovies}> Fetch movies </button> {movies.length > 0 ? ( <ul id="movies-list"> {movies.map((movie) => ( <li key={movie.id}>{movie.title}</li> ))} </ul> ) : null} </div> ); } page.tsxでmovieList.tsxを呼び出す そしたら作成したmovieList.tsxをpage.tsxに加えて動作を確認してみましょう。 // app/page.tsx import { User } from "@/mocks/handlers"; import { MovieList } from "./movieList"; async function getUser() { const response = await fetch("<https://api.example.com/user>"); const user = (await response.json()) as User; return user; } export default async function Home() { const user = await getUser(); return ( <main> <p id="server-side-greeting">Hello, {user.firstName}!</p> <MovieList /> </main> ); } ページを表示して 「Fetch movies」をクリックするとしっかりとclient component上でもfetch出来ていることを確認できました! まとめ 今回はNext.jsのApp routerでMSWを利用する方法についてまとめました。「はじめに」にも書きましたが、今回紹介した内容はDraftのPull requestを参考にさせていただいたものになっているので、本記事に関しては参考程度にしていただくのが良いかと思います。 ではまた~ 参考にさせていただいた記事 https://github.com/mswjs/msw/issues/1644 https://qiita.com/tarosuke777000/items/622e5ce3e3ace102560a ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Next.jsのApp routerでMSWをserver componentsとclient componentsで利用する方法 first appeared on SIOS Tech. Lab .
Entra Connectのパスワードの書き戻し(パスワードライトバック)とEntra IDのセルフサービスパスワードリセット(SSPR)を使用してEntra IDでユーザのパスワード変更、リセットを可能にする方法を紹介します。 Entra ConnectはActive Directory(AD)とEntra IDでユーザやグループ情報を同期するサービスです。 Entra IDでユーザのパスワード変更、リセットを可能にすることで、管理者への問い合わせやパスワードリセット作業が減り、人件コストを削減することができます。 今回紹介する方法により、Entra IDでユーザのパスワード変更、リセットを実施し、ADにパスワード情報を同期することができます。 使用環境 Image: Windows Server 2022 Datacenter – x64 Gen2 Size: Standard_D2as_v4 2vcpu 8GiB 前提 Active Directoryが構築済みであること (ドメイン名:example.com、管理者アカウント:EXAMPLE\azureuser) Active DirectoryにEntra ID同期対象のOUが含まれていること (OU名:Example Users) Entra Connectサーバが、ADサーバに対してドメイン参加済み (アカウント:EXAMPLE\exampleadmin)であること Entra IDのテナントが用意されていること Entra Connectのインストール インストール方法は過去の記事を参考にすることができます。当時はAzure Active Directory Connect (AADC)という名称でしたが、2025年2月現在はMicrosoft Entra Connect Sync (Entra Connect)となっています。また、Azure Active Directoryは、Microsoft Entra IDとなっています。 https://tech-lab.sios.jp/archives/21345 今回は以下の設定を実施します。 フォレスト(構成済みディレクトリ):example.com ドメインとOUのフィルタリングの同期OU:Example Users オプション機能にて、パスワードの書き戻しにチェックを入れて有効にします。 また、Entra IDでユーザの初回ログオン時にパスワード変更を必要としたい場合は、一時パスワードの同期を有効化する設定が必要です。設定方法は以下の記事を参考にしてみてください。 参考: https://blog.jbs.co.jp/entry/2024/09/30/115304 ユーザの確認 ADで以下のユーザを作成します。また、アカウントオプションで「ユーザーは次回ログオン時にパスワード変更が必要」とします。 UserPrincipalName 表示名 所属グループ 登録先OU 会社名 example_user01@example.com テスト ユーザ1 Group1 Example Users example.com example_user02@example.com テスト ユーザ2 Group1 Example Users example.com example_user03@example.com テスト ユーザ3 Group2 Example Users example.com example_user04@example.com テスト ユーザ4 Group2 Example Users example.com 過去記事 https://tech-lab.sios.jp/archives/21345 の「AADCの同期の方法」によりEntra IDとのアカウント同期を有効化します。 Microsoft Entra管理センターにログインし、ユーザが同期されることを確認します。 https://entra.microsoft.com/#home Entra IDからのSSPRは、「パスワードリセットのセルフサービスが有効」の項目で有効化することができます。 全てのユーザや特定のグループのユーザのみSSPRを有効にする設定が可能です。 参考: https://learn.microsoft.com/ja-jp/entra/identity/authentication/tutorial-enable-sspr SSPRの認証方法の設定は現在2通りの方法があります。 1: パスワードリセットの認証方法からリセットのために必要な方法の数および使用できる方法を設定する 2: 認証方法から、多要素認証(MFA)とSSPRの認証方法を構成する 1つ目の方法は、2025 年9月30日に非推奨となります。2025年2月現在は移行期間として、2通りの方法を選択できます。詳細は以下をご覧ください。 https://learn.microsoft.com/ja-jp/entra/identity/authentication/concept-authentication-methods-manage 今回は2つ目の方法で認証方法を構成します。Microsoft Authenticatorを使用できるように設定しています。 Entra IDからのパスワード変更を確認 テスト ユーザ1(example_user01)で https://www.microsoft365.com にサインインします。 ADおよびEntra IDではユーザの初回ログオン時にパスワード変更を必要とする設定にしているため、パスワードの更新が要求されます。パスワードを更新します。パスワードポリシーは、ADのパスワードポリシーに準拠します。 パスワードの更新後にADサーバのpowershellで以下のコマンドを実行します。distinguishedNameとPathが表示されると正しいパスワードが入力されていることになります。パスワードの変更がADに適用されていることを確認します。 参考: https://qiita.com/waokitsune/items/6dc37940095426485a57 > $de_ = New-Object System.DirectoryServices.DirectoryEntry( >> "LDAP://example.com", >> "example_user01", #ユーザID >> "NewPassword" #ユーザの更新後パスワード >> ) >> echo $de_ distinguishedName : {DC=example,DC=com} Path : LDAP://example.com Entra IDからのSSPRを確認する SSPRを確認するために、テスト ユーザ1(example_user01)で追加認証としてMicrosoft Authenticatorを設定しておきます。 Authenticatorの設定方法は以下の「Microsoft Authenticator の設定」を参考にしてみてください。 https://support.gluegent.com/hc/ja/articles/9434604489369–%E4%BB%98%E9%8C%B2-Microsoft-Authenticator-%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95 テスト ユーザ1(example_user01)のパスワード入力画面に戻り、パスワードを忘れた場合を選択します。 画面に従って、アカウントの回復のための認証を実施すると、パスワードリセット画面が表示されます。パスワードポリシーは、ADのパスワードポリシーに準拠します。 パスワードのリセットに成功すると、以下の画面が表示されます。 Entra IDからのパスワード変更を確認する手順と同様に、ADのpowershellで、パスワードの変更がADに適用されていることを確認します。 さいごに 今回は、Entra Connectのパスワードの書き戻し(パスワードライトバック)とEntra IDのセルフサービスパスワードリセット(SSPR)を使用してEntra IDでユーザのパスワード変更、リセットを可能にする方法を紹介しました。 Entra ConnectとEntra IDへの理解の一助になれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Entra Connect のパスワードライトバックとEntra IDのSSPRを使用してEntra IDでユーザのパスワード変更、リセットを可能にする first appeared on SIOS Tech. Lab .
はじめに こんにちはサイオステクノロジーの小野です。今回はOpenShift AIにデプロイしたLLMをVSCodeと連携させて、コード生成AIを利用する方法について解説します。また、VSCodeはOpenShift上で構築できるOpenShift Dev Spacesを利用します。これにより非接続環境でのコーディングでもAIによるコード支援を受けることができるようになります。 OpenShift Dev Spacesについて OpenShift上でアプリケーション開発を行う際に便利なツールとして、OpenShift Dev Spacesがあります。 OpenShift Dev SpacesはWeb ベースの統合開発環境 (IDE)です。クラウド上にデプロイされるので、利用するマシンに依存せずにどこでも利用できます。また、Devfileと呼ばれる開発環境を設定するファイルを利用してデプロイされるので、チーム内で開発環境の統合・共有がしやすくなります。 OpenShift Dev Spaces利用概要 本ブログの内容は下記章で構成されます: OpenShift Dev Spaces環境構築 OpenShift Dev Space利用手順 OpenShift Dev SpaceのVSCode拡張機能設定 OpenShift Dev SpacesとOpenShift AIの連携 最初にOpenShift Dev Spacesの構築手順について解説し、その操作方法について簡単に説明します。その後、Dev Spaces上のVSCodeにContinueという拡張機能を導入します。最後にContinueとOpenShift AIにデプロイしたLLMを連携させてコード支援機能が使えるようにする方法を解説します。 ローカルのVSCodeとOpenShift AIを連携させたい場合はDev Spacesの構築手順をスキップして、Continueの導入部分から参考にしてください。(リンク: Dev SpacesとOpenShift AIの連携 ) OpenShift Dev Space環境構築 OpenShift Dev Spacesの構築手順について説明します。 Openshift DevSpace前提条件 OpenShift:4.17 CPUアーキテクチャ:AMD64 OpenShift クラスターにサーバ証明書設定済み 参考: https://docs.redhat.com/ja/documentation/red_hat_openshift_dev_spaces/3.18/html/administration_guide/preparing-the-installation#supported-platforms Operatorインストール 最初にOpenShift Dev SpacesのOperatorをインストールします。 OperatorHubで「Dev Spaces」と検索してRed Hat OpenShift Dev Spacesをインストールします。 OpenShift Dev Spacesの詳細 インストール時の設定はデフォルトにします。 Operatorのインストール設定。今回はデフォルトでインストールする。 ステータスがSucceededになればインストール完了です。 ステータスがSucceededとなればOperatorインストール完了 CheCluster設定 次にDev spacesのCRを作成します。Red Hat OpenShift Dev Spaces instance Specificationのインスタンスを作成します。 Red Hat OpenShift Dev Spaces instance Specificationの作成 今回はデフォルトで設定します。設定の詳細は公式ドキュメントを参照してください。 https://docs.redhat.com/ja/documentation/red_hat_openshift_dev_spaces/3.18/html/administration_guide/configuring-devspaces#configuring-devspaces CheClusterの作成。今回はデフォルトで作成する。 管理コンソールアクセス CRが作成できたら、その詳細画面のRed Hat OpenShift Dev Spaces URLから管理コンソール画面に移動できます。 CheClusterの詳細画面から、Dev SpacesのWebコンソールへのURLを開く。 OpenShift Dev Spacesの管理コンソール画面 OpenShift Dev Space利用 ワークスペースの作成 VSCodeの環境を作成します。Select a SampleのEmpty Workspaceを選択します。 Select a SampleのEmpty Workspaceを選択する 作成が完了するまで待ちます。 作成完了まで待つ 作成が完了するとVSCodeの画面が表示されます。このVSCode上で作業を行います。 WorkSpaceの作成が完了するとVSCodeが表示される VSCode簡易操作 VSCodeの操作についてこれから簡単に説明します。すでに利用したことがある方は飛ばしてください。 Open Folderからフォルダを開けます。 Open Folderからフォルダが開ける 左上のメニューからFile > New Fileでファイル作成できます。 File > New Fileでファイル作成できる 左上のメニューからTeminal > New Terminalでターミナルを開くことができます。 Terminal > New Terminalからターミナルを開ける ターミナルが表示される VSCode拡張機能設定 普段私たちがデスクトップ上で利用しているVSCodeはMicrosoftがカスタマイズしたVSCodeになっています。しかし、Dev Spaces上のVSCodeはカスタマイズされていないVSCodeなのでいくつかの差異があります。一番の大きな違いとしてMicrosoft Marketplaceが入っていないので拡張機能を自分で導入する必要があります。 導入する手順としては最初に OpenVSXレジストリ から自分が利用したい拡張機能のVSIXファイルをダウンロードします。 OpenVSXに公開されているVSCodeの拡張機能 次にダウンロードしたVSIXファイルをワークスペースにアップロードします。 ダウンロードしたファイルをWorkspaceにアップロードする アップロードされた拡張機能ファイル アップロードしたら拡張機能のメニューの三点リーダーからInstall from VSIXを選択して、アップロードしたVSIXファイルを選択します。 Install from VSIXから拡張機能をインストール 選択するとアップロードした拡張機能が利用できるようになります。 利用できるようになった拡張機能 拡張機能を実際に利用した様子 Dev SpacesとOpenShift AIの連携 OpenShift AIにデプロイしたLLMを利用して、Dev Spacesにコードアシスタント機能を導入する方法を解説します。 以前の記事を参考にして、OpenShift AIにLLMをデプロイしておいてください。 OpenShift AIにLLMをデプロイしてみた Continueの導入 VSCode上でコードアシスタント機能を利用するにはContinue拡張機能をインストールする必要があります。Dev SpacesにはデフォルトでContinue拡張機能がインストールできるようになっているので、インストールします。なければ先ほどのようにOpenVSXレジストリからダウンロードしてください。 https://open-vsx.org/extension/Continue/continue Continue拡張機能をインストールする インストールすると左のメニューにContinueのアイコンが追加されます。 Continue拡張機能のメニュー ContinueとOpenShift AI連携 下の歯車マークを押すとContinueの設定ファイルが表示されます。 歯車マークから設定を行う この設定ファイルにOpenShift AIのLLMAPIの情報を記載します。まずmodelsに以下を上書きします。<タイトル名>にはContinueで表示される名前を入力し、<モデル名>にはOpenShift AIにデプロイしたLLMのモデル名を入力し、<APIのエンドポイント>はデプロイしたLLMのExtenalの方のエンドポイントを入力し、<APIのトークン>はデプロイしたLLMのAPIのトークンを入力してください。 { "title": "<タイトル名>", "model": "<モデル名>", "apiBase": "<APIのエンドポイント>/v1/", "provider": "openai", "apiKey": "<APIのトークン>" } また、tabAutocompleteModelに同様の設定を上書きすると、タブ補完でAIチャット機能を利用できるようになります。 modelsとtabAutocompleteModelを編集する 設定できたら、モデルとしてOpenShift AIにデプロイしたLLMが選択肢に出るようになります。 OpenShift AIにデプロイされたLLMが表示される 動作確認 動作確認としてPythonのHello Worldの書き方を聞いてみます。するとこのように回答してくれることが確認できます。 チャットボックスに質問してみた また、コード生成機能も試してみます。適当なファイルを作成して、Ctrl + Iを押して、どんなプログラムを書いてほしいか入力します。 素数を計算するコードを書いてもらうようにお願いしてみる すると自動的にコードを作成してくれることが確認できます。 コードを自動生成してくれる デプロイしたLLMが対応している場合、タブ補完機能も利用できます。 コードを書くと、自動的にコードの続きを提案してくれる タブ補完を続けると自動的にコードが完成する おわりに 以上の操作によりOpenShift Dev SpacesのVSCodeでAIによるコード支援を受けることができるようになりました。OpenShift AIにデプロイしたLLMはローカルLLMであるので、コード支援機能に対して秘密情報を入力したとしても外部に漏れる心配はありません。高いセキュリティを保ったままコード支援機能を利用できるのでぜひ構築してみてください。 参考 OpenShift Dev Spaces公式ドキュメント: https://docs.redhat.com/ja/documentation/red_hat_openshift_dev_spaces/3.18 https://developers.redhat.com/learn/openshift-ai/integrate-private-ai-coding-assistant-your-cde-using-ollama-continue-openshift-dev-spaces https://rheb.hatenablog.com/entry/2023/05/26/140300 https://ai-on-openshift.io/demos/codellama-continue/codellama-continue/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift AIとOpenShift Dev Spaces連携 ~コード生成AIで楽々開発~ first appeared on SIOS Tech. Lab .
こんにちは、OSSよろず相談室のSKです。 日々、多くのOSSに関するお問い合わせをいただく中で、今回は rsyslog に関するご相談がありました。 「特定のログファイルから ERROR を含むログだけを抜き出して、システムログ(/var/log/messages)に転送したい」 そんなニーズに対して、rsyslog の Ruleset 機能 を活用することで解決できました。 同じような要件でお困りの方もいるかもしれませんので、今回の対応内容を紹介します。 やりたいこと 以下のログファイルに記録されるログのうち “ERROR” という文字列を含むログが出力されたら、 /var/log/messages にも出力したい 常時 /var/log/messages に出力される OS や ネットワークなどシステム関連のログ出力はそのままにしたい。 対象のログファイル: /usr/local/share/oss-software/logs/system.log 実現方法 以下が ‘/etc/rsyslog.conf’ に追加した設定内容の全体です。 *.info;mail.none;authpriv.none;cron.none /var/log/messages module(load="imfile") input(type="imfile" File="/usr/local/share/oss-software/logs/system.log" Tag="oss-softError" Severity="info" Facility="local0" ruleset="extra-fileError") ruleset(name="extra-fileError") { if $msg contains 'ERROR' then { action(type="omfile" file="/var/log/messages") } } 1つずつ見ていきましょう。 /var/log/messages の既存設定は維持する *.info;mail.none;authpriv.none;cron.none /var/log/messages module ブロックで imfile モジュールのロード module(load="imfile") rsyslog には「モジュール」という概念があり、デフォルトではカーネルログや標準の syslog ログを処理する機能のみが有効になっています。 imfile は、ファイルを監視してログとして取り扱うためのモジュール です。 そのため、外部ログを rsyslog に取り込むためには、まずこのモジュールをロードする必要があります。 この行がないと、rsyslog は外部のログファイルを監視できません。 input ブロックで外部ログファイルの監視設定 テキストファイルを読み込む設定をします。ここで監視対象のログファイルを指定します。 どのログファイルを監視し、どのように処理するかを指定します。 input (type="imfile" …) typeに 2.でロードした imfile モジュールを指定します。 File="/usr/local/share/oss-software/logs/system.log" 監視対象のログファイルのパスです。 このファイルに新しいログが書き込まれると、rsyslogがその内容を取得して処理を行います。 Tag="oss-softError" ログのタグ(プレフィックス)を設定します。 このタグは、ログメッセージの識別に役立ちます。 ログメッセージの冒頭にこのタグが付加されて出力されます。 Severity="info" ログの重要度(Severity)を指定します。 rsyslogでは、ログの重要度(Severity)を指定することができます。 重要度には、 emerg, alert, crit, err. warning, notice, info, debug があります。 今回の設定では Severity=”info” となっているため、このログは「情報レベル」のログとして扱われます。 Facility="local0" ログの分類(Facility)を指定します。 この分類によって、ログを異なるファイルに振り分けたり、特定のフィルタを適用したりすることが可能になります。 今回の設定では、 local0 を使用しています。 これにより、local0.* のログを特定のファイルに保存したり、処理を分けたりすることができます。 ruleset="extra-fileError" 適用する Ruleset(処理ルール)を指定します。 ruleset は、特定のルールに基づいてログを処理するための仕組みです。 この設定では、 ruleset="extra-fileError" を指定しているため、このログは extra-fileError という名前のルールセットに従って処理されます。 extra-fileError というルールセットはこの後設定します。 Ruleset を定義 “ERROR” を含むログのみを /var/log/messages に出力するルールセットを定義します。 ruleset(name="extra-fileError") { if $msg contains 'ERROR' then { action(type="omfile" file="/var/log/messages") } } このルールセットでは、 if $msg contains 'ERROR' then という条件を設定し、ログメッセージに “ERROR” が含まれている場合に限り、 /var/log/messages に書き込むようにしています。 出力テスト /var/log/messages に、ERRORという文字を含むログだけが書き込まれるか、確認します。 echoコマンドで、/usr/local/share/oss-software/logs/system.logに書き込んでみます。 ERRORを含むログ出力   # echo "ERROR [Test] oss-software failed" | sudo tee -a /usr/local/share/oss-software/logs/system.log   →/var/log/messagesに以下が出力された 出力結果 Mar 13 09:52:31 ip-172-31-1-204 oss-softError ERROR [Test] oss-software failed Mar 13 09:52:31 : 日時 ip-172-31-1-204 : ホスト名 oss-softError : 2の(2)で設定したタグ ERROR [Test] oss-software failed : echoコマンドで指定した文字列 ERRORを含まないログ出力 # echo "$(date) INFO [Test] oss-software failed" | sudo tee -a /usr/local/share/oss-software/logs/system.log →/var/log/messagesに何も出力されない。 参考情報 Ruleset について詳しく知りたい方は、公式ドキュメントもご参照ください。 rsyslog / Multiple Rulesets in rsyslog RedHat社のロギング説明も合わせてご参照ください。 RedHat 8 / 第8章 ロギングの設定 まとめ 今回は、 rsyslog の Ruleset 機能 を活用することで、特定のログファイルから “ERROR” を含むログのみを抽出し、システムログ /var/log/messages に転送する方法をご紹介しました。 この設定を応用すれば、特定のエラーログだけをフィルタリングして通知したり、別のログファイルに転送したりすることも可能 です。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OSSサポートエンジニアの現場から!特定の条件のログを/var/logs/messagesにも出力したい first appeared on SIOS Tech. Lab .