TECH PLAY

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

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

610

こんにちは、サイオステクノロジーの遠藤です。 今回は、生成AI開発でよく登場する「マルチモーダル」について解説します。このブログでは、まず概要を理解し、その後アプリケーションの作成を通じてより深い理解を目指していきます。それでは始めましょう! マルチモーダルとは? マルチモーダルとは 複数の形式(モード)を組み合わせて理解する仕組み のことです。 例えば、人間は普段からマルチモーダルな理解をしています。道を歩いていて信号機を見るとき、目で「赤信号だ」と認識し、同時に耳で信号機の音を聞いて、「今は渡っちゃダメだな」と判断します。これが「視覚」と「聴覚」という複数のモードを使った理解、つまりマルチモーダルな理解になります。 この考え方が生成AIにも使われています。 例えば、画像をアップロードして「これ何?」って質問すると、生成AIがその画像を見て説明してくれます。これは、生成AIが「画像」と「テキスト」という複数の情報を同時に扱うからこそできることとなっています。 マルチモーダルなアプリケーションを作成する 実際にマルチモーダルなアプリケーションを作成するには各社が出している生成AIモデルを利用することが必要となります。 生成AIのモデルは Google社が出しているGeminiやAnthropicが出しているClaudeなどなどいろいろな会社から出ていますが、今回はOpenAI社の提供するサービスを利用します。OpenAI社が出しているサービスのなかでも様々なモデルがあり、自然言語から画像を生成できるDALL・Eや音声からテキストへ変換できるWhisperなど、モデルごとにできることが大きく異なります。 今回のブログでは高性能なチャットモデルを利用できるChatGPTモデルを使用していきます。また、ChatGPTモデルは2022年から様々なバージョンが出ていて、進化を遂げてきています。 今回作成するアプリケーションの概要 概要 今回は以下の画像のようなアプリケーションの作成を行い、「テキスト」「画像」「動画」を理解して対話できるマルチモーダルアプリケーションを作成していきます。また、簡単にWebアプリケーションを構築できるStreamlitというフレームワークを利用して作成を行っていきます。   構築にあたって必要となるもの 今回、アプリケーションの構築をまでご自身で行いたい場合には、事前に以下の環境をご準備して頂く必要があります まずAzureが提供しているOpenAIのAPIを利用するため Azure Open AI のリソース GPT-4o-mini モデルのデプロイ が必要となります。 今回のブログで紹介するコードではAzure OpenAI用のクライアント作成するようなコードになっていますが、そこを書き換えていただければ、OpenAIが出しているAPIを叩く形にカスタマイズしていただくことも可能になっていると思われます。 また今回のコードはStremlitを利用していますので Python実行環境 が必要となります 段階を分けて理解する アプリケーションの実装をこれから行っていくのですが、 【STEP1】テキストを理解させる 【STEP2】画像を理解させる 【STEP3】動画を理解させる の三段階に分けて実装を行うことで理解を深めていきたいと思います。 【STEP1】テキストを理解させる テキストを理解させるための実装を行っていく前に、まずはAzure OpenAIのAPIを利用したリクエストの送り方について確認してみましょう。ChatGPTのAPIを使用するときには、生成AIに尋ねる内容をmessagesという配列に入れて上げる必要があります。 messagesは役割を表すroleと、具体的な尋ねる内容であるcontentから構成されています。生成AIにこちらの正しい意図を認識させるにはこのroleというものが大切になってきます。 roleにはsystem, user, assistantの3種類があります。 systemでは、モデルの振る舞いや性格を決定します。例えば、「タメ口で話して」とrole: systemで設定してあれば、タメ口で話すようになります。 今回のアプリケーションでは、例に設定してある「あなたは画像やテキストにも対応したアシスタントAIです」といった設定をrole : systemでしています。 userはユーザーからの指示や質問を表す役割があります。このroleで設定したcontentの中で尋ねたい内容を設定したり、画像を指定して渡したりといったことが出来ます。 assistantは今回はアプリケーションでは利用していませんが、モデルの応答を表す役割があります。使用方法としてはユーザーと生成AI間の対話履歴も理解させたい場合に、生成AI側の発言であることを示すために使用されます。   では実際に system: あなたは画像やテキストにも対応したチャットアシスタントです。すべての質問に日本語で返答してください。 user : マルチモーダルについて教えて を設定してリクエストを送ってみます。 そうするとレスポンスとして マルチモーダル(Multimodal)は、複数の種類のデータや入力方法を組み合わせて処理・解析・生成するアプローチを指します。 と返ってきました。これでテキストを理解できるアプリケーションの実装が完了しました。 【STEP2】画像を理解させる 続いて画像を扱えるようにアプリケーションを拡張していきます。ChatGPTAPIを利用して画像をリクエストとして送るには、 画像のリンクを渡す Base64でエンコードされた値を渡す の2つの方法があり、今回は2つ目の 「Base64でエンコードされた値を渡す」 を利用して実装していきます。 ここからはpythonコードベースで実装を確認していきます。具体的な実装は以下のようなコードになります。 # 画像をbase64にエンコードする def encode_image(image): return base64.b64encode(image.read()).decode("utf-8") ... # "type":"image_url"でbase64変換した画像を送信する base64_image = encode_image(uploaded_image) messages = [ {"role": "system", "content": "あなたは画像やテキストにも対応したチャットアシスタントです。すべての質問に日本語で返答してください。"}, {"role": "user", "content": [ {"type": "text", "text": user_input}, {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}} ]} 手順としては、まずは、画像をbase64形式に変換を行います。そしてmessages配列のなかに、base64のデータを入れて渡して上げることでAPIで画像を扱うことができるようになります。注意事項としては、先程までのテキストの扱いではcontentの中でそのままテキストを扱っていたのですが、画像を送る場合には type付けを行い、image_urlというtypeを指定する必要がある点 が注意点となります。 では画像を含めたリクエストについて確認してみましょう。以下のリクエストを送ってみます。 system : あなたは画像やテキストにも対応したチャットアシスタントです。すべての質問に日本語で返答してください。 role :user この画像をもとに物語を考えて + ファンタジーチックな空に浮いている島の画像 そうするとしっかりファンタジーチックな空に浮いている島を認識して以下のようなレスポンスが返ってきました! 物語: 空中の王国 かつて、 天空に浮かぶ壮大な王国 「アエリオン」 が存在しました。 この王国は、 雲の上に築かれた切り立った岩の上にあり、透き通る滝が流れ落ちる美しい景色が広がっています。 王国の人々は、その美しさを愛し、力強く繁栄していました。 しかし、彼らの幸せは、ある日突然の危機にさらされます。 ある夜、暗い影が空を覆い、不気味な雲が王国を包み込みました。 恐ろしいドラゴン、 「ヴォルクラ」が現れ、王国の秘宝を求めて攻撃を仕掛けました。 人々は恐怖に震え、 滝の音すら聞こえなくなりました。 王国の王子、アレンは、勇気を奮い立たせ、王国を救う決意をしました。 彼は祖父から授けられた古の剣を手に取り、ドラゴンに立ち向かうための旅に出ることにしました。 旅の途中で、アレンは不思議な生き物たちと出会い、彼らから知恵や力を授かります。 その中には、天空を舞う幻の鳥「フェアリーブレード」 がおり、 彼女はアレンに、ドラゴンの弱点を教えてくれました。ドラゴンは月の光を浴びると力を増し、昼間には眠っていることが多いという情報です。 アレンは仲間たちと共に、 計画を練り、 ドラゴンが月明かりで力を失う瞬間を狙うことにしまし た。夜が訪れ、彼は果敢に陰に隠れ、 ドラゴンが居る巣へと近づいていきます。 激しい戦いの末、アレンは見事にドラゴンを打ち倒しました。 平和が戻ったアエリオンでは、王子の勇気を称える祭りが開かれました。人々は再び笑顔を取り戻 し、空中の王国はさらなる繁栄を迎えました。 アレンは、自分の冒険を通じて友情や勇気の大切さを学び、未来の王として王国を支えていくことを誓いました。 そして、王国の上空には、いつまでも流れる壮麗な滝と青空が広がり、 アエリオンは永遠に美しく輝き続けるのでした。 【STEP3】動画を理解させる 動画をリクエストで扱う方法を…  と進んで行きたいのですが、実は今回使用しているGTP-4o-miniのAPIでは直接動画を扱うことが出来ません。だからと言って動画を理解させれないわけではありません。要素に分割することで生成AIに理解させることが出来ます。 動画を構成する要素 動画は、連続した静止画が高速で切り替わることで動いているように見える要素である「映像」と、環境音や話し声とした「音声」から構成されています。 より細かく分解していくと、映像は連続した静止画が高速で切り替わっていると言えるので、複数の画像に分割できると言えます。 また、音声についてですが例えば、人の話している内容等であれば、文字起こしでテキストにすることが出来ます。また環境音など文字起こしできないものであっても、一部の生成AIを利用すれば状況を書き起こし、シチュエーションをテキストにすることが出来ます。 このように動画を要素に分割させて行くことで生成AIに動画を理解させることができるようになります!ちなみにOpenAI社的には今後直接音声や動画をAPIで扱えるようにしていくつもりのようですので、このような分割したりの作業は将来的には必要なくなるかもしれません。 ここまで説明させていただきましたが、今回は準備の関係で音声をテキスト変換して渡す機能までは入れていません。ブログの最後にコードの紹介もするので、例えば、OpenAI社のWhisperモデルを使用して文字起こしを行ったものも渡す機能を追加する変更を加えるなどして音声も認識できるように対応箇所を広げるなどしてさらにマルチモーダルアプリケーションへの理解を深めていただければと思います。 実装を確認 では画像で行ったのと同じようにコードベースでの実装を確認してみましょう。 まず、extract_frames関数を利用してbase64変換したフレーム(静止画)の配列にしています。 そして、map関数で動画を200フレームごとに受け渡しするようにしています。 # 動画をフレームに分割する def extract_frames(video_bytes): with tempfile.NamedTemporaryFile(delete=False) as temp_video_file: temp_video_file.write(video_bytes) temp_video_file_path = temp_video_file.name video = cv2.VideoCapture(temp_video_file_path) base64_frames = [] while video.isOpened(): success, frame = video.read() if not success: break _, buffer = cv2.imencode(".jpg", frame) base64_frames.append(base64.b64encode(buffer).decode("utf-8")) video.release() print(len(base64_frames), "frames read.") return base64_frames ... # AOAIへ200フレームごとにbase64変換した画像を渡す base64_frames = extract_frames(uploaded_video.read()) messages = [ {"role": "system", "content": "あなたは画像やテキストにも対応したチャットアシスタントです。すべての質問に日本語で返答してください。"}, {"role": "user", "content": [ {"type": "text", "text": user_input}, *map(lambda x: {"image": x, "resize": 240}, base64_frames[0::200]), ]} ] ここで、動画や画像を扱うときの注意点です 生成AIを利用するときにはテキストを分割した最小単位であるトークン数に応じてお金がかかるようになるのですが、動画や画像を行っているbase64変換を行ったデータはデータ数が大きいためたくさんのトークンが必要となります。例えば、この後実際に送ってみる動画のリクエストには一リクエストあたり11.5円ほどかかります。コードの中で200フレームごとに受け渡しする処理を入れている理由は、このトークン数への対策になっていて、動画を理解させるためには必ずしも全てのフレームを送って理解させる必要はなく、少し飛ばし飛ばしで見ても生成AIは理解できるようなっています。 では実際に動画を含めたリクエストを送ってみます。 system : あなたは画像やテキストにも対応したチャットアシスタントです。すべての質問に日本語で返答してください。 user : この動画を説明してください + ゴールデンレトリバーが飼い主と遊んでいる動画 document.createElement('video'); https://tech-lab.sios.jp/wp-content/uploads/2025/01/dog.mp4   返ってきたレスポンス この動画では、緑豊かな公園の中で、犬と人間が一緒に散歩している様子が映し出されています。犬はゴールデンレトリバーのようで、飼い主のそばで楽しそうに歩いています。周囲の自然や明るい日差しが感じられ、ほのぼのとした雰囲気が伝わってきます。また、飼い主が犬とコミュニケーションをとりながら進んでいる様子も見られます。全体的に、愛情と絆を感じさせるシーンです。 無事にゴールデンレトリーバーを認識したりだとか、飼い主とコミュニケーションを取っているなど動画を認識できることが確認できました! 今回作成したアプリケーションのリポジトリ 今回作成したアプリケーションですが、以下のリポジトリで公開しております。 https://github.com/Fumiya-Endo-sti/multi-modal-application READMEに構築方法等が乗っているので自分で動かしてみたい方はその手順に沿って動かして見ていただければと思います。 まとめ 今回は、マルチモーダルを理解するために、アプリケーションの作成を通して理解を深めていきました。今後もマルチモーダルはより多くの場面で採用されて行くと思われますので、これらの進歩に注目し常に最新の情報を取り入れていくことが大切だと感じています。 最後に宣伝になりますが、弊社では生成AIのアプリケーションの開発や導入などのサポートを行っております。提供できるソリューションについて以下のサイトに記載されておりますので、ご興味がございましたらご一読いただければと思います。 https://nextech-solutions.sios.jp/genai/ ではまた~ 参考サイト https://platform.openai.com/docs/guides/vision https://cookbook.openai.com/examples/gpt_with_vision_for_video_understanding https://zenn.dev/headwaters/articles/a3f87b54c25743# ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【生成AI】マルチモーダルってなに?アプリケーションの作成を通じて理解しよう! first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。 今回はAzureのBicepを利用してCosmosDBとFunctionsのリソースを作成し、FunctionsのEntra IDに対してCosmosDBの操作が行えるロールを付与する方法について確認します。 Bicepにまだ慣れていない自分としてはいくつかハマったポイントがあったのでその部分に焦点を当てて解説していければと思います。 Azureのコントロール プレーンとデータ プレーン まず今回の本題に入る前にコントロール プレーンとデータ プレーンについて確認します。 Azureの操作は コントロール プレーン と データ プレーン の2つのカテゴリに分類することが出来ます。 まずコントロールプレーンについてですが、サブスクリプション内のリソースを管理するために使用します。 そしてデータ プレーンは、リソースの種類のインスタンスによって公開される機能を使用するために使用します。 Azureが掲載している例だと、 コントロール プレーンを使用して仮想マシンを作成します。 仮想マシンを作成した後は、リモート デスクトップ プロトコル (RDP) などのデータ プレーン操作を通じて、仮想マシンと対話します。 コントロール プレーンを使用してストレージ アカウントを作成します。 ストレージ アカウント内のデータの読み取りと書き込みを行うには、データ プレーンを使用します。 コントロール プレーンを使って Azure Cosmos DB データベースを作成します。 Azure Cosmos DB データベースのデータに対してクエリを実行するには、データ プレーンを使います。 といった形で、リソースの作成といった操作ではコントロールプレーンが必要になり、実際に作成したリソースに対してデータ更新をかけるといった操作を行うにはデータプレーンのロールが必要になります。 今回は、FunctionsのアプリケーションからCosmosDBに対してデータの書き込みを行うといったシチュエーションを考えているため、Functionsに対してCosmosDBの操作を行えるデータプレーンのロールを持たせるといったことを行おうとしています。 ここからが私が少しハマったポイントなのですが、コントロールプレーンはAzureポータル上のRBACで付与することが可能なのですが、少なくとも私が試した限りはCosmosDBのデータプレーンの権限をAzureポータル上から付与したり確認が出来なさそうといったところです。 Microsoft Entra ID を使用して Azure Cosmos DB アカウントのロールベースのアクセス制御を構成する  の公式ドキュメントでも Q. Azure portal からロールの定義とロールの割り当てを管理することはできますか。 A. ロール管理の Azure portal サポートはまだ利用できません。 となっているので、2025/01/30現在は出来なさそうです。 今回付与するロール CosmosDBで使用できる組み込みロールには以下の2つのロールが用意されています。 ID 名前 含まれるアクション 00000000-0000-0000-0000-000000000001 Cosmos DB 組み込みデータ リーダー Microsoft.DocumentDB/databaseAccounts/readMetadataMicrosoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/readMicrosoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQueryMicrosoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed 00000000-0000-0000-0000-000000000002 Cosmos DB 組み込みデータ共同作成者 Microsoft.DocumentDB/databaseAccounts/readMetadataMicrosoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* データベースの書き込みを行うためには2つ目の「Cosmos DB 組み込みデータ共同作成者」のロールが必要となります。 Bicepを作成する 今回は以下のような形のディレクトリ階層でbicepコードを作成しました。 bicep-sample ├── modules │ └── app │ └── func.bicep │ └── database │ └── cosmos.bicep └── main.bicep まずCosmosDBをデプロイするためのモジュールです。 modules/database/cosmos.bicep param location string param accountName string param databaseName string param containerName string resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2024-11-15' = { name: accountName location: location properties: { databaseAccountOfferType: 'Standard' locations: [ { locationName: location failoverPriority: 0 isZoneRedundant: false } ] capabilities: [ { name: 'EnableServerless' } ] } } resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2024-11-15' = { name: databaseName parent: cosmosDbAccount properties: { resource: { id: databaseName } } } resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2024-11-15' = { name: containerName parent: database properties: { resource: { id: containerName partitionKey: { paths: [ '/user_id' ] kind: 'Hash' } } } } output accountName string = cosmosDbAccount.name 次にfunctions用のモジュールですね。こちらは Functionsをデプロイするクイックスタート をベースに作成しました。 cosmosRoleDefinitionIds 以下からロールの付与処理を行っております。ロールを付与するには Microsoft.DocumentDB databaseAccounts/sqlRoleAssignments  を利用することで付与することが出来ます。このあたりもコントロールプレーンとは書き方が違い、最初は書き方がわからなかったりとハマりやすいポイントだと感じました。 modules/app/func.bicep param location string @description('The name of the function app that you wish to create.') param appName string = 'fnapp${uniqueString(resourceGroup().id)}' @description('Storage Account type') @allowed([ 'Standard_LRS' 'Standard_GRS' 'Standard_RAGRS' ]) param storageAccountType string = 'Standard_LRS' param cosmosDBAccountName string param runtime string = 'node' var functionAppName = appName var hostingPlanName = appName var storageAccountName = '${uniqueString(resourceGroup().id)}azfunctions' var functionWorkerRuntime = runtime resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' = { name: storageAccountName location: location sku: { name: storageAccountType } kind: 'Storage' properties: { supportsHttpsTrafficOnly: true defaultToOAuthAuthentication: true } } resource hostingPlan 'Microsoft.Web/serverfarms@2021-03-01' = { name: hostingPlanName location: location sku: { name: 'Y1' tier: 'Dynamic' } properties: {} } resource func 'Microsoft.Web/sites@2021-03-01' = { name: functionAppName location: location kind: 'functionapp' identity: { type: 'SystemAssigned' } properties: { serverFarmId: hostingPlan.id siteConfig: { appSettings: [ { name: 'AzureWebJobsStorage' value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}' } { name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}' } { name: 'WEBSITE_CONTENTSHARE' value: toLower(functionAppName) } { name: 'FUNCTIONS_EXTENSION_VERSION' value: '~4' } { name: 'WEBSITE_NODE_DEFAULT_VERSION' value: '~14' } { name: 'FUNCTIONS_WORKER_RUNTIME' value: functionWorkerRuntime } ] ftpsState: 'FtpsOnly' minTlsVersion: '1.2' } httpsOnly: true } } var cosmosRoleDefinitionIds = [ '00000000-0000-0000-0000-000000000002' ] var cosmosRoleAssignmentsToCreate = [for cosmosRoleDefinitionId in cosmosRoleDefinitionIds:{ name: guid(func.id, resourceGroup().id, cosmosRoleDefinitionId) roleDefinitionId: cosmosRoleDefinitionId }] resource cosmosDBAccount 'Microsoft.DocumentDB/databaseAccounts@2024-11-15' existing = { name: cosmosDBAccountName } resource cosmosDBRoleAssignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2023-04-15' = [for cosmosRoleAssignmentToCreate in cosmosRoleAssignmentsToCreate: { name: cosmosRoleAssignmentToCreate.name parent: cosmosDBAccount properties:{ principalId: func.identity.principalId roleDefinitionId: '/${subscription().id}/resourceGroups/${resourceGroup().name}/providers/Microsoft.DocumentDB/databaseAccounts/${cosmosDBAccount.name}/sqlRoleDefinitions/${cosmosRoleAssignmentToCreate.roleDefinitionId}' scope: cosmosDBAccount.id } }] 最後にmain.bicepですね。上記2つのモジュールを呼び出す処理を入れます。 param location string = resourceGroup().location param accountName string param databaseName string param containerName string module cosmosdb 'modules/database/cosmos.bicep' = { name: 'cosmosdbModule' params: { location: location accountName: accountName databaseName: databaseName containerName: containerName } } module api 'modules/app/func.bicep' ={ name: 'apiFunc' params: { location: location cosmosDBAccountName: cosmosdb.outputs.accountName } } 権限が付与できているかの確認方法 では実際にbicepを走らせてみて、デプロイされたFunctionsに対して正しい権限が付与されているかを確認しましょう。 ここも個人的なハマりポイントで、上のほうでも書いていますが私調べではCosmosDBのデータプレーンの権限をAzureポータル上から確認することが出来ませんでした。 以下のazコマンドを実行することでCosmosDBアカウントに対してどのマネージドIDにどのデータプレーンのロールが付与されているかの確認をすることができます。 az cosmosdb sql role assignment list --account-name <cosmosdbアカウント名>--resource-group <リソースグループ名> まとめ 今回はBicepを利用してCosmosDBとFunctionsのリソースを作成し、FunctionsのEntraIDに対してCosmosDBの操作が行えるロールを付与する方法を確認しました。ロールを付与するための書き方がデータプレーンのロール用にしたり、Azureポータル上からは権限の付与が確認ができないなどハマりやすいポイントが多い部分だと思いますので同じく躓いた方の参考になればと思います! Bicep自体は1コマンドでインフラ一式デプロイを行うことができ、非常に便利に感じているのでこれからも知見をためていきたいと思います。 ではまた~ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】BicepでFunctionsにComosDBの組み込みロールを付与する first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。 先日、AzureのAI資格であるAI-102に合格し、Azure AI Engineer Associateに認定されました! AI-102は比較的新し目の資格のためAZ-104などの鉄板Azure資格に比べて情報が少なく、どのような勉強方法が良いのかといったわからない方が多いと思います。今回はそういった方々に役立つようにまとめていきたいと思います。 はじめに 試験の内容についてですが、試験を受ける際にNDA(秘密保持契約)を結ぶことになるので記載することが出来ません。そのためふわっとした内容になってしまうこととご了承ください。 Azure AI Engineer Associateとは? Azure AI Engineer AssociateはAzureの認定試験の一つであり、Azure上で提供されているAI関連のサービスに対する知識が問われるAssociateレベルの資格になります。なお、AIに関するAzure試験はExpertレベルがないため、2025年1月の段階では一番難易度の高いAI資格となります。AI-102試験に合格することで認定を受けることが出来ます。 公式ページ : Azure AI Engineer Associate 私の経歴と受験理由 私の経歴としては、2023年にサイオステクノロジーに入社し、各種案件の中などでAzure上でのアプリ構築等に取り組んでおりました。入社する前には他のクラウドプラットフォームを少し使用したことがありましたが、Azureは仕事で初めて触った形ですね。2024年度は生成AIアプリケーション開発メインで取り組んでおりまして、その中でAzureの生成AI サービスを多く使用する経験を積ませていただきました。また、弊社でAzure資格取得を推奨されている流れもあり、自分が業務に関わっている内容のAzure資格を受けてみたいと思い、受験することとしました。ちなみにAzureの試験は初めてで、AIにはFundamentalsレベルのAI-900を飛ばしての受験となりました。 勉強方法と出題内容 弊社にはAzure資格自体に関してはExpertレベルまで取得されている方がたくさんいらっしゃるのですが、AI-102に関しては私が関わりのある方で取得されている方がいらっしゃらなかったので、探り探りの学習でした。最終的な学習方法としては、基本に忠実にということで最初から最後まで公式のMS Learnを利用して学習を進めました。 出題内容としては公式が出している「試験 AI-102: Microsoft Azure AI ソリューションの設計と実装に関する学習ガイド」に記載されていて Azure AI ソリューションを計画して管理する (15 から 20%) コンテンツ モデレーション ソリューションを実装する (10 – 15%) コンピューター ビジョン ソリューションを実装する (15 から 20%) 自然言語処理のソリューションを実装する (30 から 35%) ナレッジ マイニングとドキュメント インテリジェンス ソリューションを実装する (10 から 15%) 生成 AI ソリューションを実装する (10 から 15%) といった内容が出題されます。 ドキュメントインテリジェンスや、生成AIソリューションの実装といった内容は業務の中で進めているものだったため確認程度の学習で済んだのですが、個人的に難しかったと感じたのがコンピューター ビジョン ソリューションと自然言語処理のソリューションを実装するでした。この2つについては試験勉強前は触ったことがなかった+出題範囲が広く覚えることが多いのセットで学習が辛かったです… 学習方法に話を戻しますが、私が行った学習方法としてはラーニングに沿ってトレーニングの内容について確認していきました。ただ、トレーニングの内容全部を行ったわけではなく、時短のために多くのトレーニングはドキュメント部分だけを読み、そのサービスがどのようなことができるのか、使用する際にどのような注意点があるかを学べるようにすることに留めました。ラボ(ハンズオン)部分に関しては触ったことがなかったVisionやLanguageサービスについてはいくつか行って見た程度です。 トレーニングのドキュメントを読んで概要が頭に入った後はひたすら公式が準備しているプラクティス評価問題集を繰り返し取り組み、完答できるようになることを目指しました。また、問題を問いている中で少しでもわからないところがあったらプラクティス評価の答えについている関連するMS Learnのページに飛び、その内容を理解できるようにドキュメントを読み込んでいくという形で学習を進めていきました。 実際に受けてみての感想 今回MSの試験を初めて受けた+過去問がない形式の試験を初めて受けたというのもあり、勉強のやり方がわかりませんでした。実際に一回受けてみないとどのような出題形式の試験なのか掴めないと思いますので、まずは一回あまり気負わず受けてみるのがよいかなと感じています。 本試験ではMS Learnを利用できるのですが、これに大きく助けられました。検索によって答えられた部分も多かったので、是非活用してきましょう。あと、試験を受ける前にMS Learnでキーワードを調べる練習をしておくと、本番のときに慌てずに済むと感じました。また、このとき使用できるMS Learnですが、Ctrl + Fが使用できませんでした。私の環境だけだったのかもしれませんが、念の為Ctrl + Fなしでドキュメントを調べる練習をしておいたほうが良いかもしれません。 わからない問題はMS Learnで調べるという進め方をした結果、見返しなしで残り時間3分になりました。MS Learnを使用できることにより検索にたくさん時間をかけれてしまうので、答えられる問題はすく答えるようにするなど時間配分には気をつける必要があると感じました。 おわりに 今回、AI-102試験に合格し、Azure AI Engineer Associateに認定されました。初めてのAzure資格挑戦ということで最初は勉強方法が掴めなかったですが、無事合格することが出来て良かったです! Azure資格については他にも挑戦したいと考えていて、次はAZ-104合格を目指していきたいと思います。合格したらこの記事と同じように合格体験記として投稿しようと思いますので目を通していただければと思います。 ではまた~ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【AI-102】Azure AI Engineer Associate認定されました! first appeared on SIOS Tech. Lab .
前回の記事 では、サーバーレスアーキテクチャを実現するためのOpenShift Serverlessについて解説しました。今回は、OpenShift Serverless を実際に構築したいと思います。 Red Hat Developer のチュートリアル を参考にOpenShift Serverlessのサンプルアプリケーションをデプロイ、挙動の確認を行っていきます。 事前準備 下記コマンドを実行して作業端末にkn CLIをインストールします(バージョンは2025/01/22時点)。バージョンとアーキテクチャは作業端末に適切なものを選択してください。 $ curl -Lo kn-linux-arm64 https://github.com/knative/client/releases/download/knative-v1.6.0/kn-linux-arm64 $ chmod +x kn-linux-arm64 $ sudo mv kn-linux-arm64 /usr/local/bin/kn 下記コマンドを実行してインストールの完了を確認します。 $ kn version Version: v20220713-local-bfdc0a21 Build Date: 2022-07-13 09:04:48 Git Revision: bfdc0a21 Supported APIs: * Serving - serving.knative.dev/v1 (knative-serving v0.33.0) * Eventing - sources.knative.dev/v1 (knative-eventing v0.33.0) - eventing.knative.dev/v1 (knative-eventing v0.33.0) 前提条件 OpenShift 4 クラスターが構築済みであること 作業端末に oc CLI がインストール済みであること OpenShift Serverless Operatorをインストール Operatorをインストール OpenShift OperatorHub で Administrator のパースペクティブにいることを確認します。 Web コンソールで [Operators] > [OperatorHub] に移動します。 検索バーに「OpenShift Serverless」と入力して、 OpenShift Serverless をクリックして Install をクリックします。 デフォルトのまま Install をクリックします。 Knative Serving をインストール OpenShift Serverless Operator を使用して Knative Serving をインストールするには、KnativeServing オブジェクトを作成する必要があります。 Knative Serving をインストールします。 OpenShift OperatorHub で Administrator のパースペクティブにいることを確認します。 Web コンソールで [Operators] > [インストール済みのOperator] に移動します。 Web コンソールでknative-serving プロジェクトに移動します。 Knative Serving をクリックします。 Knative Serving の作成をクリックします。 すべての値をデフォルトのままにして、[Create] ボタンをクリックします。 サンプルアプリケーションデプロイ 下記コマンドを実行してプロジェクトを作成します。 $ oc new-project serverless-tutorial 下記コマンドを実行してアプリケーションをデプロイします。Knative はコマンドライン1つでアプリケーションをデプロイすることが出来ます。もちろん、マニフェストファイルでのデプロイも可能です。 $ kn service create greeter \ --image quay.io/rhdevelopers/knative-tutorial-greeter:quarkus \ --namespace serverless-tutorial Warning: Kubernetes default value is insecure, Knative may default this to secure in a future release: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation, spec.template.spec.containers[0].securityContext.capabilities, spec.template.spec.containers[0].securityContext.runAsNonRoot, spec.template.spec.containers[0].securityContext.seccompProfile Creating service 'greeter' in namespace 'serverless-tutorial': 0.058s The Route is still working to reflect the latest desired specification. 0.088s Configuration "greeter" is waiting for a Revision to become ready. 20.686s ... 20.722s Ingress has not yet been reconciled. 20.765s Waiting for load balancer to be ready 20.956s Ready to serve. Service 'greeter' created to latest revision 'greeter-00001' is available at URL: https://greeter-serverless-tutorial.apps.<ドメイン名> 挙動確認 下記コマンドを実行してデプロイしたリソースを確認します。 $ kn service list NAME      URL                                                                                  LATEST          AGE   CONDITIONS   READY   REASON greeter   https://greeter-serverless-tutorial.apps.<ドメイン名>   greeter-00001   19m   3 OK / 3     True 下記コマンドを実行してリクエストを送った際の pod の増減を確認してみます。上記コマンドで表示された URL に curl やブラウザなどでリクエストを送ります。 $ oc get pod -w NAME READY STATUS RESTARTS AGE greeter-00001-deployment-5677dbb785-lmw27 0/2 Pending 0 0s greeter-00001-deployment-5677dbb785-lmw27 0/2 Pending 0 0s greeter-00001-deployment-5677dbb785-lmw27 0/2 Pending 0 0s greeter-00001-deployment-5677dbb785-lmw27 0/2 ContainerCreating 0 0s greeter-00001-deployment-5677dbb785-lmw27 0/2 ContainerCreating 0 0s greeter-00001-deployment-5677dbb785-lmw27 1/2 Running 0 1s greeter-00001-deployment-5677dbb785-lmw27 2/2 Running 0 1s greeter-00001-deployment-5677dbb785-lmw27 2/2 Terminating 0 108s greeter-00001-deployment-5677dbb785-lmw27 1/2 Terminating 0 2m10s greeter-00001-deployment-5677dbb785-lmw27 0/2 Terminating 0 2m18s greeter-00001-deployment-5677dbb785-lmw27 0/2 Terminating 0 2m19s greeter-00001-deployment-5677dbb785-lmw27 0/2 Terminating 0 2m19s OpenShift GitOps を用いたデプロイ 事前準備 OpenShift GitOps を構築してみた を参考にして下記手順を実施します。 OpenShift GitOps をインストール OpenShift GitOps のログイン Argo CD へのデプロイ権限の付与 プライベートリポジトリの登録 マニフェスト用リポジトリに下記構成を配置します。 app ├── knative_serving.yaml └── kustomization.yaml knative_serving.yaml apiVersion: serving.knative.dev/v1 kind: Service metadata:   name: greeter   namespace: serverless-tutorial spec:   template:     spec:       containers:       - image: quay.io/rhdevelopers/knative-tutorial-greeter:quarkus         livenessProbe:           httpGet:             path: /healthz         readinessProbe:           httpGet:             path: /healthz kustomization.yaml resources: - knative_serving.yaml アプリケーションをデプロイ 下記コマンドを実行して ArgoCD アプリケーションをデプロイします。 $ oc apply -f application.yaml application.argoproj.io/serverless-dev created application.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata:   name: serverless-dev   namespace: openshift-gitops spec:   project: default   source:     repoURL: GitHubリポジトリのURL(末尾が .git で終わるURL)     path: app     targetRevision: HEAD   destination:     server: https://kubernetes.default.svc     namespace: serverless-tutorial   syncPolicy:     automated:       prune: true       selfHeal: true デプロイ確認 ArgoCD の画面から ArgoCD アプリケーションが作成されていることを確認します。 デフォルトのビューだとリソースが多すぎるため、今回はビューを変更します。アプリケーションデプロイから少し時間がたった後に確認したため、pod が立っていないことが確認できます。 挙動確認の時と同じようにリクエストを送って pod の増減を確認して完了です。 まとめ Red Hat Developer のチュートリアル を参考にOpenShift Serverlessのサンプルアプリケーションをデプロイ、挙動の確認しました。コンテナイメージさえ用意していれば簡単にサーバレスアプリケーションをデプロイすることが出来ます。ゼロスケールによりリソースの節約が可能になりますが、pod立ち上げの時間があるため、ユースケースに応じて適切に使い分ける必要があります。 参考文献   Red Hat OpenShift Serverlessとは? OpenShift GitOps を構築してみた https://developers.redhat.com/courses/getting-started-openshift-serverless?source=sso ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Serverless を構築してみた first appeared on SIOS Tech. Lab .
こんにちは。サイオステクノロジーの木村です。 この記事では、Dart の名前付き引数の特徴と使い方を記載します。 Dart における名前付き引数は、引数を明示的に指定できるため、コードの可読性や保守性が向上します。名前付き引数を使うと、引数の順番に依存せず、引数の名前を指定して渡すことができるため、特に引数が多いメソッドやコンストラクタでは大きな利点があります。 名前付き引数でない場合 まずは、名前付き引数を使わない通常の引数の例です。 void example(String name, int age, String position) { print('名前: $name, 年齢: $age, 役職: $position'); } 上記の呼び出し example('サイオス太郎', 30, 'エンジニア'); // 出力→ 名前: サイオス太郎, 年齢: 30, 役職: エンジニア 名前付き引数でない場合は、全ての引数が必須となります。また、呼び出し時、引数の順番を守らなければなりません。 名前付き引数の場合 次に、名前付き引数の例です。 void example({required String name, required int age, required String position}) { print('名前: $name, 年齢: $age, 役職: $position'); } 名前付き引数の場合、引数を {} で囲んで定義します。必須の引数には required をつけます。 上記の呼び出し example(name: 'サイオス太郎', age: 30, position: 'エンジニア'); // 出力→ 名前: サイオス太郎, 年齢: 30, 役職: エンジニア 名前付き引数を使うと、引数の順番に関係なく、引数名を指定して値を渡すことができます。つまり、以下のように呼び出しても構いません。 example(age: 30, position: 'エンジニア', name: 'サイオス太郎'); // 出力→ 名前: サイオス太郎, 年齢: 30, 役職: エンジニア 名前付き引数のデフォルト値 名前付き引数の場合、必須でない引数にはデフォルト値を指定することができます。 呼び出し時、引数の指定がない場合はデフォルト値が使われます。 void example({required String name, required int age, String position = 'なし'}) { print('名前: $name, 年齢: $age, 役職: $position'); } 上記の呼び出し example(name: 'サイオス太郎', age: 30); // 出力→ 名前: サイオス太郎, 年齢: 30, 役職: なし 以上 Dart/Flutterについては以下の記事もございますので、あわせてお読みいただけたら嬉しいです。 【Dart】 Flutter × VSCode で、環境構築 から HelloWorld まで(Mac) Flutterアプリでプッシュ通知〜Firebase Cloud Messagingで通知を受信する方法(iOS)〜 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Dart(Flutter)】メソッドの名前付き引数 first appeared on SIOS Tech. Lab .
はじめに こんにちはサイオステクノロジーの小野です。 前回 はOpenShift LightspeedというAIチャットアシスタント機能の構築方法について説明しました。今回はそのOpenShift Lightspeedを使って数々の問題を解決する様子をお届けします。なお2025年1月23日の現時点ではテクノロジープレビューのため、不具合や正式版と異なる場合があることにご了承ください。 OpenShift Lightspeed使ってみた OpenShift Lightspeed前提条件 Lightspeed環境構築済み: 前回投稿した記事 を参考にしてください 使用LLMプロバイダ:Azure OpenAI 使用LLM:GPT-4o Lightspeed機能確認 LightspeedにはOpenShiftを利用する上で便利な機能が備わっています。それを紹介します。 質問に対する応答 最初にLightspeed自身のことについて質問します。 OpenShift Lightspeedについての質問 このようにOpenShiftLightspeedの概要について回答します。また、関連ドキュメントには回答に関連する公式ドキュメントのリンクが添付されています。 連続した質問に対する応答 Lightspeedは会話履歴を記憶しており、連続した質問に対しても回答できます。 例としてIDP設定について質問します。 OpenShiftのIDP設定についての質問 IDPの種類の説明やOAuthの設定方法、LDAPの場合の設定方法などについて回答します。次にGitHubの場合の設定方法について質問します。 Githubの場合の質問 GitHubをIDPとして設定する方法について回答します。このように連続した質問に対しては会話履歴に関連づいた回答をします。 リソースの情報を添付した質問 LightspeedはOpenShiftのリソースのyamlやイベント、ログを添付して質問することができます。cluster-version-operatorというOpenShiftのバージョン管理を行っているpodを例に質問をします。 最初にpodのyamlを添付して、OpenShiftクラスターの自動更新設定について質問します。cluster-version-operatorの詳細画面に移動してチャット欄の+ボタンからYAMLを選択します。 リソースの詳細画面を開いている状態で、+ボタンからyamlやlogを添付できる OpenShiftの自動更新設定をyamlから調べてもらう yaml内から情報を読み取り、自動更新設定がオフになっていることを回答します。 次にlogを添付してエラーの有無を確認します。logやeventは添付する量を調整できるので、無駄にLLMリソースを消費せずに質問ができます。 logを添付する際にlogの量を設定する logからエラーがないか質問する 重大なエラーはなかったが、警告があることを回答します。このようにリソースを添付して送信することでOpenShiftの問題を解決できます。 Alertのトラブルシューティング リソースのyamlのみならず、Alertの情報を添付して質問することも可能です。AlertmanagerReceiversNotConfiguredというAlertの通知設定をしていないAlertを例にして質問をします。 Alertの例:Alertの通知設定がされていないという警告 Alertについての質問 Alertがなぜ発生しているのか、その対処法について回答します。このようにAlertのトラブルシューティングにも役立ちます。 日本語の質問 Lightspeedは英語で質問することを想定していますが、日本語で質問することも可能です。 先ほどのAlertの質問を日本語でします。 日本語によるAlertについての質問 Alertの説明と対処法を日本語で回答します。 簡単な質問への回答 Lightspeedに簡単な質問をした場合の回答を紹介します。 基本的な用語の質問 コンテナ関連の用語は専門用語が多く、把握するのが大変です。そこでOpenShiftの基本的な用語についての質問をします。 Deployment 最初にDeploymentとは何か質問します。 Deploymentについての質問 Deploymentの概要について回答します。またDeploymentConfigがOpenShift 4.14以降で非推奨になっている補足情報も回答します。 Pod 次にPodとは何か質問します。 Podについての質問 Podについての概要を回答します。 Operator 最後にOperatorとは何か質問します。 Operatorについての質問 Operatorについての概要を回答します。このようにOpenShiftで用いられる用語を聞くと、参考になるドキュメントへのリンクを含めて解説してくれます。 リソースのyaml作成 OpenShiftのリソースを作成するには複雑なyamlファイルを書かなければなりません。そこでリソースのyamlの例を出力します。 Secret 最初にSecretのyamlの例について質問します。 Secretのyamlの例についての質問 apiVersion: v1 kind: Secret metadata: name: example-secret namespace: my-namespace type: Opaque data: username: <base64 encoded username> password: <base64 encoded password> stringData: hostname: myapp.mydomain.com Secretリソースの例を出力します。dataフィールドに入れる値はbase64でエンコードする必要があることやstringDataを用いれば自動的にbase64にエンコードされてdataフィールドに格納されることを説明します。 Service 次にServiceのyamlの書き方について質問します。 Serviceのyamlの例についての質問 apiVersion: v1 kind: Service metadata: name: my-service namespace: my-namespace spec: selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 8080 type: ClusterIP Serviceリソースの例を出力し、各フィールドに何が書かれているのか解説します。このようにリソースのyamlの例を聞くことで、yaml内の各フィールドの意味を理解して書くことができるようになります。 よくある質問への回答 OpenShiftを利用する際によくある疑問の解消を行った例を紹介します。 Podのオートスケーリング設定 OpenShiftのpodをオートスケーリングする設定方法について質問します。 Podのオートスケーリングについての質問 Webコンソール上での方法を回答しているので、それに従います。適当なDeploymentのページを開きます。 Deploymentの例:networking-console-plugin アクションのドロップダウンリストからHorizontalPodAutscalerの追加を選択します。 アクションからHorizontalPodAutscalerの追加を選択 HorizontalPodAutoscalerの設定をすることでオートスケーリングが可能になります。 HorizontalPodAutoscalerの設定 しかし、CPU およびメモリー使用率を使用する場合、CPU およびメモリーリソースの制限を設定する必要があるそうなので、それについても追加で質問します。 CPUとメモリーのリソース制限についての質問 Deploymentにリソース制限を付ける必要があることが分かったのでリソース制限の設定をします。 アクションからリソース制限の編集を選択 リソース制限の設定 リソース制限をしてHorizontalPodAutscalerの設定をするとCPUおよびメモリー使用率によるオートスケーリングができるようになります。 リソース制限設定後のHorizontalPodAutoscalerの設定 最後にHorizontalPodAutscalerを作成するとオートスケーリングが設定されました。 作成したHorizontalPodAutscaler オートスケーリング設定後のDeployment このようにLightspeedに質問することでpodの自動スケーリング設定を行うことができます。 PodのデプロイをNamespace単位でノード指定 OpenShiftで特定のNamespace内のpodを特定のノードにデプロイする設定を質問します。 PodのデプロイをNamespace単位でノード指定する方法についての質問 Namespace全体のPodのノード指定はプロジェクトノードセレクターを設定すれば可能と回答しました。Namespaceのyamlのannotaionsに指定したいノードのラベルを設定します。 Namespaceにノードセレクターを設定 これで、このNamespace内ではannotaionsに設定したラベルを持つノードにpodがデプロイされるようになります。試しに設定したNamespace内にPodを作成します。 設定したNamespaceにPodを作成する 作成されたPodを確認するとノードセレクターに指定したラベルが設定されています。また、ノードのラベルを確認すると指定したラベルがあることが確認できます。 作成したPod。ノードセレクターに指定したラベルが、ノードにそのラベルが付与されているノードが設定されている。 ノードのラベル確認 おわりに このようにOpenShift LightspeedはOpenShift Webコンソール上で気軽に質問することで、OpenShiftの不明な点や問題点に対して、迅速な解決の手助けをしてくれます。まだテクノロジープレビューで粗い部分もありますが、正式版がリリースされた際はぜひ使ってみてください。 参考 公式ドキュメント: https://docs.redhat.com/ja/documentation/red_hat_openshift_lightspeed/1.0tp1/html/operate/index 前回の記事: OpenShift Lightspeedを構築してみた ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Lightspeedを使ってみた first appeared on SIOS Tech. Lab .
はじめに こんにちはサイオステクノロジーの小野です。今回はOpenShift Lightspeedを構築する方法を解説します。この機能はコンテナプラットフォームの複雑な機能や操作を手助けしてくれます。なお2025年1月23日の現時点ではテクノロジープレビューのため、不具合や正式版と異なる場合があることにご了承ください。 OpenShift Lightspeedとは OpenShift LightspeedはOpenShift Webコンソール上で利用できるAIアシスタントチャットボットです。OpenShiftに関する質問に対して回答してくれるため、トラブルシューティングや調査に役立ちます。 Lightspeedは以下のLLMプロバイダーと連携することで実行されます: OpenAI Microsoft Azure OpenAI IBM WatsonX RHEL AI Red Hat OpenShift AI Lightspeedの構成図は以下のようになります: 最初にユーザーがLightspeedに対して質問します。 LightspeedはLLMプロバイダーが提供しているLLMに対してAPIリクエストを送ります。 LLMがリクエストから回答を生成し、LLMプロバイダーはLightspeedにそのレスポンスを送ります。 最後にLightspeedがレスポンスから回答を表示します。 OpenShift Lightspeedの構成図   OpenShift Lightspeedの構築手順 前提条件 OpenShift Lightspeed前提条件は ドキュメント を確認してください。今回の構築は以下の条件で行いました: OpenShift:4.17 OpenShift Lightspeed:0.2.1 Azure OpenAIが構築済み Azure設定 EntraID作成 今回のLightspeedとAzure Open AIとのAPI連携はMicrosoft EntraIDによる認証を行います。 EntraIDの「アプリの登録」を開きます。新規登録を押してアプリケーションを登録します。 EntraIDのアプリの登録 EntraIDのアプリの新規登録 アプリケーションが作成されると以下のような画面に遷移するので、クライアントIDとテナントIDをメモします。 アプリケーション(クライアント)IDとディレクトリ(テナント)IDをメモ 「証明書とシークレット」を開いて新しいクライアントシークレットを作成します。作成したらシークレットの値をメモします。 シークレットの値をメモ 次に今回連携させるAzure Open AIのリソースに移動して、「アクセス制御」から追加を押下してロールの割り当ての追加をします。 Azure OpenAIのアクセス制御設定 職務ロールのCognitive Services ユーザーを選択して「次へ」を押下します。 Cognitive Services ユーザーを選択 メンバーはアクセスの割り当て先をユーザー、グループ、またはサービス プリンシパルにして、「メンバーを選択する」から先ほど作成したEntraIDのアプリケーションを選択します。選択できたら「レビューと割り当て」を押下します。 EntraIDのアプリにロールを割り当てる Cognitive Service ユーザーに追加されていればEntraIDの設定は完了です。 Cognitive Service ユーザーにEntraIDのアプリが追加されていれば設定完了 Azure OpenAI設定 Azure AI Foundryに移動して、共有リソースのデプロイを開きます。 モデルのデプロイを押下して「基本モデルをデプロイする」を選択します。 モデルのデプロイ Lightspeedに連携させるLLMのモデルを選択します。 LLMモデル選択 デプロイ名や、カスタマイズから1分あたりのトークン数の制限を設定します。制限が低すぎるとLightspeedの返答が長すぎる場合に返答しないことがあるので注意してください。 デプロイ設定 トークン数の制限設定 デプロイが完了したら、モデルの詳細画面を開き、「プレイグラウンドで開く」を押下します。 モデルの詳細画面 プレイグラウンドが開くので、コードの表示を押下すると「https://<AzureOpenAIのリソース名>.openai.azure.com/」というエンドポイントが確認できるので、これをメモします。以上でAzure Open AIの設定は完了です。 チャットプレイグラウンドの画面。デプロイしたLLMにテキストを送信できる。 サンプルコードからエンドポイントをメモする OpenShift設定 OpenShift Lightspeed オペレータインストール OperetorHubから「Lightspeed」と検索してOpenShift Lightspeed Operatorをインストールします。 OperatorHubからOpenShift Lightspeedを検索 OpenShift LightspeedのOperator情報 インストール時の設定 OpenShift Lightspeed設定 最初にAzure Open AIの認証情報を持つシークレットを作成します。OpenShiftコンソール画面の右上の「+」を押下して、以下のyamlを記入して作成を押下します。クライアントID、クライアントシークレット、テナントIDはメモしたEntraIDのそれぞれの値をbase64形式にエンコードした値を入力します。 apiVersion: v1 data: client_id: <base64にエンコードしたクライアントID> client_secret: <base64にエンコードしたクライアントシークレット> tenant_id: <base64にエンコードしたテナントID> kind: Secret metadata: name: azure-api-keys namespace: openshift-lightspeed type: Opaque Azure OpenAIの認証情報を持つシークレットを作成。base64形式にエンコードすることに注意。 次にOpenShift LightspeedのカスタムリソースであるOLSConfigを作成します。OpenShiftコンソール画面の右上の「+」を押下して、以下のyamlを記入して作成を押下します。デプロイ名は、Azure Open AIでモデルをデプロイした際に設定した名前を入力してください。モデル名はデプロイした元のモデルの名前を入力してください。モデルエンドポイントは、メモしたモデルのエンドポイントを入力してください。 apiVersion: ols.openshift.io/v1alpha1 kind: OLSConfig metadata: name: cluster spec: llm: providers: - credentialsSecretRef: name: azure-api-keys deploymentName: <デプロイ名> models: - name: <モデル名> name: myAzure type: azure_openai url: <モデルエンドポイント> ols: defaultModel: <モデル名> defaultProvider: myAzure OpenShift Lightspeedのカスタムリソース作成 作成してしばらくすると、右下のアイコンを押下したらチャットが表示されます。これでOpenShift Lightspeedが使えるようになりました。 OpenShift Lightspeedのチャット画面。右下のアイコンをクリックすると表示される。 OpenShift Lightspeed動作確認 設定が完了できたので「あなたは誰ですか?」と質問してみます。 OpenShift Lightspeedの応答 このようにAIチャットボットが質問に対して回答してくれます。Lightspeedの様々な使い方は次回のブログをご覧ください。 注意事項 注意事項として次のドキュメントを参照してください。 https://docs.redhat.com/ja/documentation/red_hat_openshift_lightspeed/1.0tp1/html/about/ols-about-data-use OpenShift Lightspeedは2025年1月23日現在テクノロジープレビューで、チャットメッセージやフィードバックなどを収集しています。その中にはOpenShiftクラスターやリソースに関する機密情報が含まれている可能性があります。そこで注意するべき点を以下に列挙します: フィルタリングと編集の制限 :テクノロジープレビューリリースにはLLMに提供する情報をフィルター処理または編集する機能が制限されています。LLMプロバイダーへの送信を希望しない情報は、OpenShift Lightspeedに入力しないでください。 データ使用契約 :OpenShift Lightspeedを使用することにより、ユーザーは、LLMプロバイダーに送信するすべてのメッセージをRed Hatがあらゆる目的で使用することに同意します。 トランスクリプトの収集 :ユーザークエリ、LLMプロバイダーに送信されたメッセージ、LLMの応答を含むすべてのトランススクリプトが一時的に記録され、2時間ごとにRed Hatに送信されます。 フィードバックの収集 :ユーザーがフィードバックを送信するとそれに関するユーザーが送信した情報とLLMプロバイダーが応答した情報が記録され、Red Hatに送信されます。 データのセキュリティとアクセス :トランスクリプトとフィードバックはセキュリティポリシーとアクセス制限に従って、Red Hat Insightシステムのバックエンドを使用して処理されます。 データ削除リクエスト :ユーザーはテクノロジープレビュー期間の終了時にRed Hatにメールを送信してデータの削除をリクエストすることができます。   おわりに 以上の設定により、OpenShift Webコンソール上でAIアシスタントチャットボットが利用できるようになりました。まだテクノロジープレビューですが、正式版が出た際には、ぜひ導入してみてOpenShiftの利用に役立ててください。 参考 公式ドキュメント: https://docs.redhat.com/ja/documentation/red_hat_openshift_lightspeed/1.0tp1 データ使用についての注意事項: https://docs.redhat.com/ja/documentation/red_hat_openshift_lightspeed/1.0tp1/html/about/ols-about-data-use ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Lightspeedを構築してみた first appeared on SIOS Tech. Lab .
今号では、Linux におけるログローテーションの仕組みについて説明します! ログローテーションとは ログローテーションとは、ログファイルが肥大化するのを防ぐために、定期的に古いログをアーカイブ (圧縮) したり、削除する仕組みです。 Linux では logrotate というツールが主に使用されています。 このプロセスが systemd のタイマー機能により実行されることで、ログ管理を行なっています。 RHEL9 の場合、主に /var/log 配下の各ログファイルがローテート対象になっており、下記の様に古いファイルは番号付きで圧縮されます。 # ls -l /var/log/ … -rw-------. 1 root root 0 Jan 9 19:43 maillog -rw-------. 1 root root 0 Nov 27 00:58 maillog-20241213 -rw-------. 1 root root 0 Dec 13 19:56 maillog-20241225 -rw-------. 1 root root 156523 Dec 27 01:59 maillog-20250101 -rw-------. 1 root root 107334 Jan 7 02:35 maillog-20250109 -rw-------. 1 root root 1396633 Jan 12 20:55 messages -rw-------. 1 root root 390128 Nov 27 11:00 messages-20241213 -rw-------. 1 root root 97309 Dec 13 19:58 messages-20241225 -rw-------. 1 root root 1143833 Dec 27 10:59 messages-20250101 -rw-------. 1 root root 879657 Jan 7 11:00 messages-20250109 … ※ファイル数が多いため、該当する箇所を一部抜粋しています。 ログローテーションの設定ファイル logrotate 全体の動作は /etc/logrotate.conf で、ログ個別の動作は /etc/logrotate.d 配下の各ファイルで設定します。 まずは logrotate.conf の内容を見てみます。 # see "man logrotate" for details # global options do not affect preceding include directives # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # packages drop log rotation information into this directory include /etc/logrotate.d # system-specific logs may be also be configured here. 各設定の意味について、それぞれ解説します。 weekly ログファイルを週次 (週1回) ローテートします。ローテートが実行されると、ログファイルは新しいものに入れ替えられます。 rotate 4 4世代分のファイルを保存します。5ファイル目以降は、古い順に削除されます。 create 古いログファイルをローテートした後に、新しいログファイルを作成します。その後は新しいログファイルに書き込まれるようなります。 dateext ローテートしたログファイルの末尾に日付を付けます。 #compress ログファイルを圧縮する場合は、この行のコメントをします。デフォルトでは圧縮しないようになっています。 include /etc/logrotate.d /etc/logrotate.d 内の設定ファイルを読み込みます。 /etc/logrotate.conf の設定は、このディレクトリ内の設定ファイルで上書きされます。 次に、/etc/logrotate.d 配下の各設定ファイルは、デフォルトでは下記の様になっています。 新たにソフトウェアをインストールすると、このディレクトリに新たなファイルが作成される場合があります。 # ls -l /etc/logrotate.d total 36 -rw-r--r--. 1 root root 130 Oct 14 2019 btmp -rw-r--r--. 1 root root 160 Aug 29 2022 chrony -rw-r--r--. 1 root root 88 Sep 9 2022 dnf -rw-r--r--. 1 root root 105 Sep 20 2023 insights-client -rw-r--r--. 1 root root 162 Jan 3 2024 kvm_stat -rw-r--r--. 1 root root 226 Jul 31 2023 rsyslog -rw-r--r--. 1 root root 237 Jan 10 2024 sssd -rw-r--r--. 1 root root 88 Sep 14 2023 subscription-manager -rw-r--r--. 1 root root 145 Oct 14 2019 wtmp では、デフォルトで用意されている /etc/logrotate.d/rsyslog の内容を見てみます。 /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler { missingok sharedscripts postrotate /usr/bin/systemctl -s HUP kill rsyslog.service >/dev/null 2>&1 || true endscript } 各設定の意味について、それぞれ解説します。 /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler 対象となるログファイルのパスを指定します。このように、複数のパスを記載することができます。 missingok ログファイルがなくてもエラーにしません。 sharedscripts ~ endscript sharedscripts ~ endscript の間に記載されたスクリプトを (ローテートされる毎に) 1度だけ実行します。 postrotate ログのローテーション後にスクリプトを実行することを示します。 /usr/bin/systemctl -s HUP kill rsyslog.service >/dev/null 2>&1 || true rsyslog を再起動するスクリプトです。 systemd のタイマー機能によるログローテーションの定期実行 上記で説明した設定ファイルのみでは、ログローテーションが自動で実行されることはありません。 RHEL9 の場合、ログローテーションは systemd が logrotate を起動することで実施されます。 なお、RHEL7 までは cron を用いて起動していました。 デフォルトでは /usr/lib/systemd/system/logrotate.timer ファイルにてタイマーの設定がされており、このうち OnCalendar=daily (日次で実行) の設定に従って、logrotate (logrotate.service) が 1日 1回起動されます。 [Unit] Description=Daily rotation of log files Documentation=man:logrotate(8) man:logrotate.conf(5) [Timer] OnCalendar=daily AccuracySec=1h Persistent=true [Install] WantedBy=timers.target logrotate が起動されると、上記で説明した設定ファイルを読み込み、その内容に応じてログの圧縮や削除などを行う仕組みとなっています。 次号では、ログローテーションの設定について、もう少し詳しく見ていきます! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!logrotate の仕組みについて1 first appeared on SIOS Tech. Lab .
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 中央省庁の一部のウェブサイトではセキュリティ対策が不十分であり、外部から指摘を受け省庁側が修正したことが分かりました。 “中央省庁の一部サイト 不正利用のおそれ” 指摘受け修正 https://www3.nhk.or.jp/news/html/20250109/k10014688801000.html?fbclid=IwZXh0bgNhZW0CMTEAAR0_BrIvYe06cGEJzbp-lid7WPzuG9_55MxmvBtEvSMsG-vnY8ZalqZmOkg_aem_H3h3j3xnde8Eln9K2gABfw 2025/1/11、Linux Foundation が「アニュアル レポート 2024 業界のイノベーションを加速」を公開しました。 Linux Foundation アニュアルレポート 2024「業界のイノベーションを加速」を公開 https://prtimes.jp/main/html/rd/p/000000334.000042042.html 2025/1/13、Linux 搭載の携帯端末「Mecha Comet」が発表されました。様々な拡張機能 (モジュール) を使う事で、自由にカスタマイズできる点が特徴です。 携帯型Linux端末「Mecha Comet」が発表–モジュールの組み合わせで可能性は無限大 https://japan.zdnet.com/article/35228208/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年1月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
ども!久しぶりに金曜日もお家で、ブログを執筆している龍ちゃんです。突然ですが、Google Calendar使っていますか?僕は入社してから、いろいろな予定をGoogle Calendarで管理するようになりました。ほぼ、TODOリスト化しています。手動で管理するのもいいんですが、システム化できそうと思っちゃったので検証したのでその報告になります。 今回は、Google Apps Script(GAS)を使ってGoogle Calendarに予定の登録・取得についてまとめました。ドキュメントは充実していましたが、例がなんとも言えない感じだったのでGoogle Calendarヘビーユーザーの皆さんに代わってソースコードを用意したので、コピペして動かしながら試してください。 事前準備 検証を進めていくにあたっての準備なので、ソースを知りたい方は読み飛ばしていただいて大丈夫です。 新しいGoogle Calendarを用意する うっかり、「メインのカレンダーの予定を消してしまった!」なんてことにならないように、検証用の新しいカレンダーを用意しておきましょう。 https://calendar.google.com/ にアクセスして、新しいカレンダーを作成しましょう。 今回は「GAS API Test」という名前のカレンダーを用意しました。次に、カレンダーの設定に入り「 カレンダーの統合>カレンダーID 」というIDを控えてください。 こちらのIDを用いてカレンダーにアクセスするので、この手順を覚えておきましょう。 共通設定:GASでGoogle Calndarにアクセス準備 まずは、GASエディタ上でGoogle Calndar APIへのサービス追加を行います。こちらを設定することでサジェスチョン機能が有効になります。 次に、カレンダーへのアクセス処理をグローバル変数として設置します。カレンダーへの参照はすべてのコードの前段として必要になります。先ほど事前準備で取得した カレンダーID を以下の xxxxx 部分に変更してください。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // カレンダーへの参照 const calendar = CalendarApp.getCalendarById(calenarID) JSのDate型で日付と時間を指定する 今回の内容で取り扱う、Date型セットを用意しました。 // 実行したタイミングの日付情報を取得する const date = new Date() Logger.log(date) // 年:月:日をそれぞれ取得する // 月も日も0からカウントされるため、実世界と合わせるためには+1する Logger.log(`${date.getFullYear()}:${date.getMonth()+1}:${date.getDate()+1}`) // 西暦で設定する date.setFullYear(2024) Logger.log(date) // 次の月に設定 date.setMonth(date.getMonth()+1) Logger.log(date) // 次の日に設定 date.setDate(date.getDate()+1) Logger.log(date) // 時間情報をセットする // 0時12分00秒 date.setHours(00, 12, 00) Logger.log(date) 取得:年・月・日 const date = new Date() Logger.log(date) // 年:月:日をそれぞれ取得する Logger.log(`${date.getFullYear()}:${date.getMonth()+1}:${date.getDate()}`) 月に関しては、 0 からカウントがスタートします。そのため、現実と合わせるためには月は +1 させることで現実と即した値になります。 情報設定(日付): setFullYear / setMonth / setDate const date = new Date() Logger.log(date) // 西暦で設定する date.setFullYear(2024) Logger.log(date) // 次の月に設定 date.setMonth(date.getMonth()+1) Logger.log(date) // 次の日に設定 date.setDate(date.getDate()+1) Logger.log(date) 月は情報は、 0 からカウントがスタートします。月情報が12月を超えて設定した場合は、年が +1 されます。日付情報が有効な日付の場合は設定され、超えた場合は月が +1 されます。 情報設定(時間情報): setHours const date = new Date() Logger.log(date) // 時間情報をセットする // .setHours(hours, min, sec) date.setHours(00, 12, 00) Logger.log(date) 時間情報設定する setHours の引数は3つあります。 パラメータ 説明 hours 時間を設定する(0~23):24以降では日付がプラスされる min 分を設定する(0~59) sec 秒を設定する(0~59) こちらの設定方法は、現実と即した形で設定することができます GASでGoogle Calendarを操作する よく使用する登録・取得の方法についてまとめていきます。コマンドの種類が豊富なので、用途別にまとめて行きます。公式リファレンスでオブジェクトの説明があるので開きながら見てもらえると良いですね。 説明 URL Google Calendarで扱えるオブジェクト https://developers.google.com/apps-script/reference/calendar/calendar?hl=ja Eventオブジェクト https://developers.google.com/apps-script/reference/calendar/calendar-event?hl=ja こちらで、カレンダーオブジェクトの取得が完了します。 単一の予定を追加する: createEvent ドキュメントとしては、 こちら になります。サンプルでは、実行した当日のカレンダーに対して、15:00~16:00の一時間で予定が追加されます。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const setEvent = () => { const startTime = new Date() startTime.setHours(15, 0, 0) const endTime = new Date() endTime.setHours(16, 0, 0) const options = { // description: "説明", // location:"自宅", // <guests:"example1@example.com>, example2@example.com", // sendInvites:false } const event = calendar.createEvent("title", startTime, endTime, options) } createEvents の引数は、4つです。それぞれ、以下を設定することができます。 名前 型 説明 title String イベントのタイトル:必須 startTime Date イベントの開始日時:必須 endTime Date イベントの終了日時:必須 options Object イベントの詳細設定:オプション options は名前の通り、設定しなくても動作します。optionsで設定できる値としては、以下のようになります。 名前 型 説明 description String イベントの説明 location String イベントの場所 guests String ゲストとして追加するメールアドレス(複数人の場合はカンマ区切り) sendInvites boolean 招待メールを送信するか(デフォルト:false) コメントアウトを外して実行すると、optionsで指定した内容のカレンダー予定が登録されます。 終日のイベントを追加する: createAllDayEvent ドキュメントとしては、 こちら になります。サンプルでは、終日(一日)・終日(二日)・終日(二日:詳細付き)の予定が3つ登録されます。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const setAllDayEvent = () => { const startTime = new Date() calendar.createAllDayEvent("test", startTime) // 終了日は含まれないため(予定を入れたい日+1)指定 const endTime = new Date() endTime.setDate(endTime.getDate() + 2) calendar.createAllDayEvent("test", startTime, endTime) const options = { description: "説明", location: "自宅", guests: "example1@example.com, example2@example.com", sendInvites: false } calendar.createAllDayEvent("test", startTime, endTime, options) } createAllDayEvent の引数は、4つです。 名前 型 説明 title String イベントのタイトル:必須 startTime Date イベントの開始日時(日付のみが参照される):必須 endTime Date イベントの終了日時(日付のみが参照され、終了日は範囲に含まれない):オプション options Object イベントの詳細設定:オプション optionsで設定することができる値は、以下になります。 名前 型 説明 description String イベントの説明 location String イベントの場所 guests String ゲストとして追加するメールアドレス(複数人の場合はカンマ区切り) sendInvites boolean 招待メールを送信するか(デフォルト:false) createAllDayEvent で気を付けたい点としては、 endTime を設定する場合です。終了日は含まれません。設定したい期間通りに設定できているかを注意深く確認する必要があります。 繰り返し単一の予定を追加する: createEventSeries それぞれ、単一・終日の登録を見てきました。それぞれのイベント形態を繰り返し登録することができる関数が createEventSeries ・ createAllDayEventSeries です。こちらのサンプルは createEventSeries です。サンプルでは、「一か月間、水曜日と木曜日の15:00~16:00に予定」が登録されます。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const setSeriesEvent = () => { const startTime = new Date() startTime.setHours(15, 0, 0) const endTime = new Date() endTime.setHours(16, 0, 0) const endScedule = new Date() endScedule.setMonth(endScedule.getMonth() + 1) const recurrence = CalendarApp.newRecurrence() .addWeeklyRule() .onlyOnWeekdays([CalendarApp.Weekday.THURSDAY, CalendarApp.Weekday.TUESDAY]) .until(endScedule) const options = { description: "説明", location:"自宅", guests:"example1@example.com, example2@example.com", sendInvites:false } calendar.createEventSeries("title", startTime, endTime, recurrence, options) } createEventSeries で登録することができる引数は5つです。 名前 型 説明 title String イベントのタイトル:必須 startTime Date イベントの開始日時(最初のイベント):必須 endTime Date イベントの終了日時(最初のイベント):必須 recurrence EventRecurrence 繰り返しのルール:必須 options Object イベントの詳細設定:オプション optionsの設定する値は、 createEvent と共通です。この関数で重要になるのは recurrence の設定項目です。指定することができるパラメーターとしては、 こちらにまとまっています 。 繰り返し終了条件を決定する方法として、繰り返し回数( .times(number) )と期間( .until(Date) )があります。これらを使用用途によって使い分けてください。 以下に汎用性が高い、繰り返しルールを記載しておきます。 特定曜日のみ繰り返すサンプル ホワイトリスト方式とブラックリスト方式のそれぞれの方式で記載します。 // 記載されている曜日を削除することで機能する:ホワイトリスト方式 // 週単位で、特定の曜日のみ繰り返す const sceduleRule = CalendarApp.newRecurrence() .addWeeklyRule() .onlyOnWeekdays([ CalendarApp.Weekday.SUNDAY, CalendarApp.Weekday.MONDAY, CalendarApp.Weekday.TUESDAY, CalendarApp.Weekday.WEDNESDAY, CalendarApp.Weekday.THURSDAY, CalendarApp.Weekday.FRIDAY, CalendarApp.Weekday.SATURDAY ]).times(10) // 除外したい曜日を記載することで機能する:ブラックリスト方式 // 毎日繰り返して、特定の曜日のみ除外する const sceduleRule = CalendarApp.newRecurrence() .addDailyRule() .addWeeklyExclusion() .onlyOnWeekdays([CalendarApp.Weekday.SUNDAY]) .times(10) 特定間隔(日ごと・隔週) 特定の間隔( .interval(number) )でルールを休眠させることができます。intervalでは前段に記載され//ているルールによって間隔を決定してくれます。 addWeeklyRule では休眠期間1週間、 addDailyRule では休眠期間1日間になります。 // interval(1)で1週間になる const sceduleRule = CalendarApp.newRecurrence().addWeeklyRule().interval(2).times(10); // interval(1)で1日間隔になる const sceduleRule = CalendarApp.newRecurrence().addDailyRule().interval(2).times(10); 第三水曜日のみ addMonthlyRule と onlyOnWeekday をこねくり回して実現できないか試してみたのですが、実装が完成しませんでした。有識者の方教えてもらえると助かります。 でも、ここまでくるとGUIか月初めにトリガーで動かすプログラムを組んだ方が良い気がしています。てか月に一回しかやらない系のイベントなら手で設定するほうが確実だよな? 特定の日付の予定を取得する: getEventsForDay ドキュメントとしては、 こちら になります。指定した日付の予定情報をすべて取得します。サンプルでは、「実行当日の予定をすべて取得し、イベント名とイベントの合計時間を取得」となります。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const getEventsForDay = () => { const startTime = new Date() const options = { // start: 0, // max: 10, // author: "", // search: "", // statusFilters: [ // CalendarApp.GuestStatus.OWNER, // CalendarApp.GuestStatus.INVITED, // CalendarApp.GuestStatus.YES, // CalendarApp.GuestStatus.MAYBE, // CalendarApp.GuestStatus.NO // ] } const events = calendar.getEventsForDay(startTime, options) // 各イベント情報をそれぞれ表示する events.forEach((event) => { console.log({ "id": event.getId(), "title": event.getTitle(), "time": (event.getEndTime() - event.getStartTime()) / 360 / 10000, "owner": event.isOwnedByMe(), "isAllDayEvent": event.isAllDayEvent(), "eventType": event.getEventType().toString(), "Mystatus": event.getMyStatus().toString() }) }) // イベントの合計時間を何時間表記で取得する const total = events.reduce((prev, event) => { const isAllDayEvent = event.isAllDayEvent() if (isAllDayEvent) { return prev } return prev + (event.getEndTime() - event.getStartTime()) / 360 / 10000 }, 0) Logger.log(total) } getEventsForDay の引数は2つになります。時間情報は参照されずに、年・月・日の情報のみ使用されます。 名前 型 説明 date Date イベント取得日時:必須 options Object イベントの詳細設定:オプション options情報としては、以下の情報を設定することができます。 名前 型 説明 start int 返答されるイベントのインデックス(何番目のイベントから取得するか) max int 返答されるイベントの最大数 author String イベント参加者のフィルタ(メールアドレス) search String フィルタリングに使用される全文検索クエリ statusFilters GuestStatus [] フィルタリングに使用されるステータスの配列(参加・未定・不参加 etc…) 特筆する点としては、 search ・ statusFilters[] になります。 search では、全文検索クエリとなっています。部分一致で検索することができます。Prefixなどを付けて予定を登録すると管理がしやすいですね。 statusFilters は、イベントに対するステータスで検索することができます。プロパティの説明は こちら にあります。カレンダー上で参加状況をちゃんと解答していれば、フィルターで情報を分析することができます。 こちらのサンプルでは、「招待されて参加したイベント・自分が発行したイベントの情報を取得して、合計時間を計算」となります。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const getEventsJoinTotalTime = () => { const startTime = new Date() const options = { statusFilters: [ CalendarApp.GuestStatus.OWNER, CalendarApp.GuestStatus.YES ] } const events = calendar.getEventsForDay(startTime, options) // イベントの合計時間を何時間表記で取得する const total = events.reduce((prev, event) => { // 終日イベントを除外する const isAllDayEvent = event.isAllDayEvent() if (isAllDayEvent) { return prev } return prev + (event.getEndTime() - event.getStartTime()) / 360 / 10000 }, 0) Logger.log(total) } 特定の期間の予定を取得する: getEvents ドキュメントとしては、 こちら になります。 getEventsForDay と使用感はほぼ一緒ですが、期間を明確に設定することができます。サンプルでは、「実行当日の8:00~18:30のイベントを取得」です。 const calenarID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" const calendar = CalendarApp.getCalendarById(calenarID) const getEvents = () => { const startTime = new Date() startTime.setHours(8, 0, 0) const endTime = new Date() endTime.setHours(18, 30, 0) const events = calendar.getEvents(startTime, endTime) events.forEach((event) => { Logger.log({ "id": event.getId(), "title": event.getTitle(), "time": (event.getEndTime() - event.getStartTime()) / 360 / 10000, "owner": event.isOwnedByMe(), "isAllDayEvent": event.isAllDayEvent(), "eventType": event.getEventType().toString(), "Mystatus": event.getMyStatus().toString() }) }) } getEvents で設定できる引数は3つです。使用時に注意が必要なのは endTime です。こちらは、イベントの開始時間が、 endTime よりも速い場合はイベントがヒットします。 名前 型 説明 startTime Date イベントの開始日時:必須 endTime Date イベントの終了日時(イベントの開始時間が含まれる場合は検索に含む):必須 options Object イベントの詳細設定:オプション options で設定することができるのは、 getEventsForDay と同じになります。 終わり 今回は、GASでGoogle Calendarを操作する方法についてまとめました。こちらで紹介したコードと他の機能を組み合わせることで、Google Calendarを含めた自動化もできると思います。 今回紹介したコードを参考に、皆さんも自分なりのGoogle Calendar活用方法を見つけてみてください。もし、わからないことがあれば、コメント欄でお気軽に質問してくださいね。(第三水曜日を指定する方法がわかったらこっそり教えてください) それでは、また次回の記事でお会いしましょう! GAS関連ブログ 2024-02-01 GASで月初めにメールを送信する:祝日・土日対応 2023-09-04 Google Apps Script(GAS)でスプレッドシートを新規シート作成 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【サンプルコード付き】GASでGoogle Calendarを操作する方法を徹底解説 first appeared on SIOS Tech. Lab .
概要 ども!久しぶりにGoogle Apps Script(GAS)でプログラムを書いている龍ちゃんです。さくっとかけてGoogleのサービスと連携できるのが利点ですね。今回は、プログラムの実行日時が土日祝日か判定する必要が出てきたので執筆です。 今回の内容です。 土日の判定をDate型を活用して判定 Google Calendarを活用して祝日を判定 実行日から一番近い平日を取得 それぞれ関数化して共有していきます。 土日の判定をDate型を活用して判定 const isWeekend = (date) => { const day = date.getDay() if (day === 0 || day === 6) { return true; } return false; } こちらは、 Date型の曜日情報を取得 して判定しています。日曜日を0として曜日情報がカウントされています。0が日曜日、6が土曜日になります。 Google Calendarを活用して祝日を判定 const holidayCalendarId = 'ja.japanese#holiday@group.v.calendar.google.com'; const calendar = CalendarApp.getCalendarById(holidayCalendarId); const isHoliday = (date) => { const otherHoliday = [ [2, 3], // 節分 [3, 3], // ひな祭り [5, 12], // 母の日 [7, 7], // 七夕 [12, 25] // クリスマス ] // monthIndex 0~11のため+1 const month = date.getMonth() + 1 // 日付はそのまま取得でOK const day = date.getDate() const isOtherHoliday = otherHoliday.some((event) => { return event[0] == month && event[1] == day }) if (isOtherHoliday) return false const events = calendar.getEventsForDay(date); return events.length > 0; } Google Calendarの「日本の祝日」から情報を取得して、活用しています。ただ、「日本の祝日」カレンダーの欠点で、「日本で休みじゃない祝日」も登録されています。そのため、人力でその判定を行っています。処理としては、以下の二点です。 祝日として登録されているが休みではない日の判定 Google Calendar経由で祝日の判定 Go o gle Calendarの操作はこちら でまとめています。 実行日から一番近い平日を取得する const getWeekdays = () => { const targetDate = new Date() while (isWeekend(targetDate) || isHoliday(targetDate)){ targetDate.setDate(targetDate.getDate() + 1) } return targetDate } こちらは、先ほど作成した isWeekend / isHoliday を使用して、実行した日が土日祝であれば一番近い平日を取得しています。 終わり ども!今回はGASで土日祝を判定するプログラムの紹介を行いました。トリガーと組み合わせて、「毎週月曜日に定期実行を設定して、月曜日が祝日だった場合は近い平日に処理を振り返る」みたいな処理も可能です。 ほなまた~ GAS関連ブログ 2024-02-01 GASで月初めにメールを送信する:祝日・土日対応 2023-09-04 Google Apps Script(GAS)でスプレッドシートを新規シート作成 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【サンプルコード付き】GASで土日祝日判定スクリプトを作成する方法 first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。 弊社ではこの度、Azure OpenAI サービスを基盤として最短一日でRAG環境を提供するAzure OpenAI Service RAGスターターパックのサービス提供を始めました。 本ブログではAzure OpenAI Service RAGスターターパックを利用し、独自データの登録からチャットUIによる検索までをご紹介します。 また、より詳細なサービス概要は 弊社ソリューションサイト SIOS NEXT TECH SOLUTIONS からもご確認いただけます。ご興味のある方は是非アクセスしてみてください。 関連ブログ Azure OpenAI Service RAGスターターパック サービス提供開始しました! Azure OpenAI Service RAGスターターパックとは? Azure OpenAI Service RAGスターターパック(以下「RAGSP」という)は社内データといった独自情報を外部知識として活用する生成AI技術であるRAG(Retrieval-Augmented Generation)を利用したアプリケーションを提供可能なパッケージとなります。 本パッケージではクラウドインフラからアプリケーションまでを最短一営業日で構築し、チャットUI+回答精度の評価改善までのオールインワン基盤をご提供します。   ドキュメントの登録 今回登録に使用するデータ 厚生労働省が出している モデル就業規則 から解説部分を取り除き、就業時間などのサンプルデータを入れたRAGテスト用就業規則を作成いたしました。今回はRAGSPのアプリケーション構築までは終わっている前提で作成したRAGテスト用就業規則をRAGSPで独自情報として登録を行い、チャットUI上から検索をかけるところまでを行っていきます。 作成したPDFはこちらになります : RAGテスト用就業規則 データを登録する では、用意したRAGテスト用就業規則をRAGSPに登録してみましょう。 1. RAGSPはAzure上で構築されていますので、データを登録するにまずはAzureポータルにログインしましょう。ログインが出来たら、画面上部の「リソース、サービス、ドキュメントの検索」に「ストレージアカウント」と入力します。   2.ストレージアカウントの一覧が表示されるので、独自データの保管先となる「環境名 + egstrsp」を選択します。 3.選択したストレージアカウントからコンテナーを選んで保存先になるコンテナー名(ここではai-test)を選択します。 4.「アップロード」をクリックし、ドラッグアンドドロップでRAGの検索対象としたいデータをアップロードをして完了です。ファイルをアップロードすると自動的にファイルを検索できる形に整形され、数分後からチャットUI上で登録したデータに関する検索ができるようになります。これでデータの登録作業は完了です! チャットUIを使用して検索してみる 1.RAGSPのURLにアクセスします。アクセスするとサインインが求められますので、ご所属の組織で利用している認証方法でサインインを行います。 2.チャットUIが表示されるので、登録したデータにかかれている内容について質問してみましょう。今回は「採用時に必要となる書類について教えて」と質問してみます。 3.少し待つと先ほど登録したデータをもとに回答が生成され、採用時に必要となる書類一覧が回答として返ってきました。また回答の最後には、回答を生成するために参照したドキュメントへのリンクも付属しています。 4.回答根拠ドキュメントへのリンクをクリックするとPDFが表示されるので、PDFの情報から正しく回答がなされているか確認してみます。しっかりデータ登録を行ったPDFから回答を作成してくれることが確認できました! まとめ 今回は弊社からリリースしたAzure Open AI Service RAGスターターパック(RAGSP)を利用し、独自データの登録からチャットUIによる検索までをご紹介を行いました。RAGSPは難しくなりがちなデータ登録作業をブラウザ上から簡単に利用することができるので、初めての方でも安心してご利用していただけるサービスとなっております。 改めての紹介になりますが、以下のページからより詳細なサービス概要をご確認いただけますので是非一度ご覧いただければと思います。お問い合わせをお待ちしております。 「Azure OpenAI Service RAGスターターパック」 サービス概要ページ https://nextech-solutions.sios.jp/genai/azure-openai-service-ragsp.html   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure OpenAI Service RAGスターターパック 利用してみた! ~データ登録・チャットUI編~ first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの遠藤です。 弊社ではこの度、Azure OpenAI サービスを基盤とした最短一日でRAG環境を提供するAzure OpenAI Service RAGスターターパックのサービス提供を始めました。 本ブログではAzure OpenAI Service RAGスターターパックの概要と特徴についてご紹介します。また、より詳細なサービス概要は 弊社ソリューションサイト SIOS NEXT TECH SOLUTIONS からもご確認いただけます。ご興味のあるかたは是非アクセスしてみてください。 Azure OpenAI Service RAGスターターパックとは? Azure OpenAI Service RAGスターターパック(以下「RAGSP」という)は社内データといった独自情報を外部知識として活用する生成AI技術であるRAG(Retrieval-Augmented Generation)を利用したアプリケーションを提供可能なパッケージとなります。 本パッケージではクラウドインフラからアプリケーションまでを最短一営業日で構築し、チャットUI+回答精度の評価改善までのオールインワン基盤をご提供します。 機能紹介 1. 回答根拠ドキュメント表示機能を搭載したチャットUI RAGSPではブラウザから操作可能なチャットUIを提供しています。また、生成された返答にに回答の根拠となったドキュメントの表示機能がついており、回答の正しさの確認を行うことができるようになっています。 2. ドキュメントをブラウザから簡単に登録 回答のもととなる独自情報の登録はAzure Portalを通じてブラウザ上から行うことができます。インデクシングなどの複雑な処理を意識することなく、運用者にとってもカンタンにRAGアプリケーションのメンテンスを行うことが可能です。 3. プロンプトフローを利用した評価・改善 Azure Machine Learning プロンプト フロー の評価フローを利用して、GUI上から関連度、類似性といた観点から定量的な評価を行うことが可能になっています。また評価の結果、改善の必要性がある判明された場合、こちらもプロンプトフロー上からローコードによる改善を行うことが可能になっています。 4. Bicepを利用したIaCを構築 Azure リソースをデプロイするドメイン固有言語 (DSL) であるBicepを利用してインフラの構築を行うため、最短1営業日での構築が可能になっています。またGitHub, GitLabに対応したCICDパイプラインを組んでいるため、後述するアプリケーションのカスタマイズの反映も簡単に行うことが出来ます。 様々なカスタマイズもご提案可能! RAGSPでは他にもオプション機能として、Azureの閉域対応や、様々な形式の入出力に対応できるようにするマルチモーダル対応などの機能がご提案可能です。 これ以外にもお客様ごとのご要望に合わせた機能のご提案も可能になっておりますので、ご気軽にご相談ください。 まとめ 今回は弊社からリリースしたAzure Open AI Service RAGスターターパック(RAGSP)についてご紹介しました。改めての紹介になりますが、以下のページからより詳細なサービス概要をご確認いただけますので是非一度ご覧いただければと思います。お問い合わせをお待ちしております。 「Azure OpenAI Service RAGスターターパック」 サービス概要ページ https://nextech-solutions.sios.jp/genai/azure-openai-service-ragsp.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure OpenAI Service RAGスターターパック サービス提供開始しました! first appeared on SIOS Tech. Lab .
こんにちは。サイオステクノロジー OSS サポート担当 山本 です。 今回は solr の仕組みの時にお話しした 辞書 を拡張するお話です。 ■おさらい:solr と辞書のお話 今回のお話を進めていく前に、軽くおさらいをしておきましょう。 solr は 予め登録しておいた一連のデータ である ドキュメント から高速な 文字列検索 を行うことに特化した、全文検索 OSS です。 この高速検索を実現するため、solr は ドキュメント を登録する時に 文字列の解析 を行い、解析の結果出てきた検索ワードとして有効なワードを元にして インデックス と呼ばれるデータベースを作成します。 検索を行う際にも 検索ワードを解析 して、出てきたワードを インデックス から検索することで、検索の際の負荷や所要時間を大幅に抑えて無駄の少ない 全文検索 ができる、というわけです。 ところで、「 文字列の解析 」と軽く言いはしましたが、これには様々なメカニズムが使われています。 特に日本語は「単語ごとに空白スペースで区切る」という言語的なルールがない故に “単語に分割する” 処理が機械的にできないため、内部の 辞書 を活用して単語に切り分けるメカニズムが使用されています。 ■解析と辞書とインデックス 解析の例を見ながら、もう少し細かくおさらいしておきます。 例えば、solr の demo 用コアで “これはあかきえんぴつです。” という文章を解析すると、以下のように分割されます。 これ / は / あかき / えんぴつ / です / 。 このように分割ができるのは、「これ」「は」「あかき」「えんぴつ」「です」という それぞれの単語が solr の内部辞書に存在している から、ということになります。 分割された後は、以前紹介した フィルタ によって基本形に戻したり検索に不適なワードを除外したりして、最終的に残ったものが インデックス に登録されます。 この文章を持つドキュメントを登録するならば、「あかい (“あかき” の基本形)」と「えんぴつ」がインデックスに追加され、ドキュメントと関連付けられます。 検索の際にはこの インデックスと一致するか をチェックしているため、例えばですが  ・「グレー」で検索して「 グレー プ」が引っかかる  ・「レンジ」で検索して「オ レンジ 」が引っかかる などのような、 一般的な文字列検索で起こってしまうような「そうなんだけど、そうじゃない…!」というタイプの検索ノイズを低減できる というのも、solr の強みの一つと言えます。 ともあれ、日本語で solr を使う場合には、 辞書に単語がちゃんと登録されているか がかなり重要であると言えます。 ちなみに、辞書を使って上手く分割できなかった部分は、文字種 (かな・カナ・漢字など) が変わる部分で区切ってそれぞれを固有名詞と想定して処理してくれます。 ■辞書を拡張する さて、では今回の本題です。 solr の採用している日本語形態素解析器 “Kuromoji” の内部辞書は非常に強力で、一般的な単語であれば殆どカバーしてくれるはずです。 しかし、それでも解析結果が常に思い描いたとおりになるわけではありません。例えば……   ・単語を分割したい 一例として、デフォルトの日本語辞書では「 ショルダーバッグ 」「 トートバッグ 」は 1単語 として扱われます。 そのため、「 バッグ 」で検索しても「ショルダーバッグ」や「トートバッグ」を含むドキュメントはヒットしません。   ・人名や社名、製品名などの固有名 一般的な単語ではない固有名は当然ながら辞書には登録されておらず、うまく解析できないケースがあります。 一例としては、「サイオステクノロジー」「OSSよろず相談室」は、demo コアのデフォルト設定では「サイ / オス / テクノロジー」「OSS / よろず / 相談 / 室」と分割され、例えば「サイ」で検索して「サイオステクノロジー」がヒットするなど意図しない形でのヒットを誘発してしまう可能性があります。 このような問題を解決できるアプローチの一つが、 辞書の拡張 です。 ■ユーザ辞書の内容確認と作成 solr では ユーザ辞書 という機能を使って、任意のフレーズが出てきた際の 単語の区切り方 を形態素解析の辞書に追加することができます。 実際に前回作成したコアにユーザ辞書を追加してみます。 (コアの作り方や前回お話ししたファイルなどについては省略します。前回記事も一読の上、読み進めてください。) ユーザ辞書もデモ用環境のコア “demo” にサンプルが入っているので、今回はこちらを参考にして、前回作成した実験用コア “test-new-core” を使って確認していきます。 まずは前回使ったデモ用環境のコンテナを起動し、”demo” のユーザ辞書のサンプル “/var/solr/data/demo/conf/lang/userdict_ja.txt” を手元の環境に持ってきます。 ## (デモ用環境起動) $ podman start test-solr ## (ユーザ辞書サンプルのコピー) $ podman cp test-solr:/var/solr/data/demo/conf/lang/userdict_ja.txt ./ 手元の環境にコピーした userdict_ja.txt を適当なテキストエディタで開き、まずは内容を確認してみます。 行頭が “#” の行はコメント行扱いとなるので、(ファイルの先頭のユーザ辞書の説明コメント部分を除くと) このファイルはこのような記述がされています。 # Custom segmentation for kanji compounds 日本経済新聞,日本 経済 新聞,ニホン ケイザイ シンブン,カスタム名詞 関西国際空港,関西 国際 空港,カンサイ コクサイ クウコウ,カスタム名詞 # Custom segmentation for compound katakana トートバッグ,トート バッグ,トート バッグ,かずカナ名詞 ショルダーバッグ,ショルダー バッグ,ショルダー バッグ,かずカナ名詞 # Custom reading for former sumo wrestler 朝青龍,朝青龍,アサショウリュウ,カスタム人名 これを見れば (あるいはファイル先頭の説明コメントを読めば) なんとなくわかるかと思いますが、ユーザ辞書は以下のような書式で 登録したいワードを列挙したテキストファイル になります。 [登録したい文字列],[登録したい文字列での単語の切り分け方],[各単語の読み方 (カナ)],[品詞] 第2要素の単語の切り分けでは、 半角スペース で単語を切り分け ます。 第3要素の読み方は、 第2要素で切り分けた単語数と同じ数 になるよう、 半角スペース区切りで各単語の読み方 を記述します。 第4要素の品詞は、主にフィルタ “ japanesePartOfSpeechStop ” で使用される要素で、このフィルタで参照しているファイルに 記述されている品詞と一致 していると、その単語は インデックスの登録対象から除外 されます。 デモ用環境では、japanesePartOfSpeechStop フィルタは “/var/solr/data/demo/conf/lang/stoptags_ja.txt” を参照しています。気になる方はこちらのファイルも確認してみてください。 以下の行を例にしてみると… 関西国際空港,関西 国際 空港,カンサイ コクサイ クウコウ,カスタム名詞  ・対象となるフレーズ (文字列) :「関西国際空港」  ・単語の切り分け方      :「関西」「国際」「空港」  ・切り分けた単語の読み方 (カナ):「カンサイ」「コクサイ」「クウコウ」  ・このフレーズの品詞     :「カスタム名詞」 となるわけですね。 さて、構造がなんとなくわかったところで、このユーザ辞書 “userdict_ja.txt” をベースにユーザ辞書を試してみましょう。 先ほど挙げた例 (「トートバッグ」「ショルダーバッグ」「サイオステクノロジー」) を使おうかと思いますが、「トートバッグ」「ショルダーバッグ」はサンプルとして既に登録されているので、「サイオステクノロジー」が1単語として扱われるように登録してみます。 以下のような行を “userdict_ja.txt” の末尾に追加しましょう。 サイオステクノロジー,サイオステクノロジー,サイオステクノロジー,カスタム名詞 ■ユーザ辞書の適用 続いて変更したユーザ辞書を、前回作成した実験用コア “test-new-core” に適用してみましょう。 まずは、作成したユーザ辞書を “test-new-core” に配置します。 “test-new-core” のスキーマファイルから参照できればどこにおいても大丈夫なはずですが、サンプルに従ってコアのディレクトリ内の “conf/lang/” 配下に配置するのが無難でしょう。 $ podman cp ./userdict_ja.txt test-solr:/var/solr/data/test-new-core/conf/lang/userdict_ja.txt 続いて、このユーザ辞書を参照するように、スキーマファイルを変更します。 “test-new-core” のスキーマファイル “managed-schema.xml” を一旦手元に持ってきて… (デモ用コンテナにはテキストエディタがないため) $ podman cp test-solr:/var/solr/data/test-new-core/conf/managed-schema.xml ./managed-schema.xml このスキーマの日本語解析の設定を行なっている部分の “ tokenizer ” 要素を以下のように変更します。 ## 変更前 &ltfieldType name="text_ja" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100"> &ltanalyzer> &lttokenizer mode="search" name="japanese"/> &ltfilter name="japaneseBaseForm"/> : : ## 変更後 &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"/> : : 変更したら “test-new-core” のスキーマファイルを置き換えれば準備 OK です。 $ podman cp ./managed-schema.xml test-solr:/var/solr/data/test-new-core/conf/managed-schema.xml 変更したスキーマの設定を読み込むため、”test-new-core” をリロードします。 リロードはコマンドと管理画面のどちらからでも可能で、 コマンドでリロードするなら以下のようなコマンドを、 $ curl -X POST http://(IP or ホスト名):8984/api/cores/test-new-core/reload 管理画面でリロードするなら “ Core Admin ” の画面から対象のコアを選択して、” Reload ” ボタンを押してください。 これで “test-new-core” にカスタムしたユーザ辞書を適用できました。 早速、管理画面で試してみましょう。 “Core Selector” タブで test-new-core を選んで、” Analysis ” を開いて、ユーザ辞書を適用した FieldType “text_ja” で「ショルダーバッグ」「サイオステクノロジー」の単語分けの状況を確認してみましょう。 上手くいっていそうです。 そういえば、前回このコアに登録したドキュメントに「サイオステクノロジー」を含むものがありましたね。 折角なのでちゃんと検索もできるかを確認してみましょう。 (コマンドだと URL エンコードで見辛いので管理画面で確認してみます。) ……引っかかっていませんね?何か間違えたのでしょうか? 試しに元々の解析で出ていたワードの一つ「サイ」で検索をかけてみましょう… こちらだと引っかかってしまいますね。(こういう引っかかり方を避けるためにユーザ辞書を変更したはずなのに…) これは一体どういうことでしょう? ■ユーザ辞書変更とインデックス ユーザ辞書変更直後に検索が上手くいかない現象には、アレが深く関係しています。 そう、アレです。 インデックス です。 何度かお話ししましたが、solr は高速な文字列検索を実現するために  ・ ドキュメント (データ) の 登録時 に、登録データを 解析した結果をインデックスに登録 する  ・検索時は検索ワードの解析結果を基に インデックスから検索 する というアプローチをとっています。 これは特に変なことをしなければ上手くいくのですが、今回起こったことを (簡略化して) 順に見ていきましょう… まず、「サイオステクノロジー」をドキュメントに登録しました。 この時点では「サイオステクノロジー」は「サイ / オス / テクノロジー」と切り分けられていたため、 インデックスには「サイ」「オス」「テクノロジー」の 3ワード がこのドキュメントと関連するワードとして登録されます。 この時点では「サイオステクノロジー」で検索すると、 解析された「サイ」「オス」「テクノロジー」の3ワードでの検索 となります。 インデックスの「サイ」「オス」「テクノロジー」は、いずれもドキュメントの「サイオステクノロジー」に紐づいているので、この検索は成功します。 さて、ここで今回の変更です。 解析結果がおかしいことに気が付いて、「サイオステクノロジー」を1ワードとして扱うように ユーザ辞書 を作りました。 しかし、 この作業をする前に登録済みのインデックスは変更されていません 。 この状態で「サイオステクノロジー」で検索すると、 解析結果の「サイオステクノロジー」をインデックスから検索 しようとします。 ところが、ドキュメント「サイオステクノロジー」に紐づいているインデックスは 登録した時点 の「サイ」「オス」「テクノロジー」の3ワードのみであり、 「サイオステクノロジー」でインデックスから検索しても一致するものがありません 。 他方、「サイ」だけで検索すればこの解析結果は「サイ」です。 これは最初に「サイオステクノロジー」をドキュメント登録した時の解析結果「サイ」「オス」「テクノロジー」の 3ワードのうちの「サイ」と合致して、結果としてドキュメント「サイオステクノロジー」がヒットしてしまいます。 この問題を解決するには、 ユーザ辞書を変更した後 にドキュメントを登録しなおし て、 インデックスを作り直す 必要があります。 また、そもそも元々登録していたドキュメント・インデックスが検索の邪魔になってしまう可能性があるので、 元々のドキュメント・インデックスは一度消したほうがよい です。 つまり、 ドキュメント登録を一からやり直し する必要があります。 ドキュメントとインデックスの削除については、今回の “test-new-core” であれば以下のようなコマンドで行うことができます。 $ curl -X POST -H 'Content-Type: application/json' --data-binary '{"delete":{"query":"*:*" }}' http://(IP or ホスト名):8984/solr/test-new-core/update 上記コマンドの実行後、コアのホームディレクトリの data/index 配下 (今回の “test-new-core” ならコンテナ内の ) にファイルがない状態なのを確認できたら、再度新しくドキュメントを登録し直せば OK です。 再度ドキュメントの登録が完了した後に改めて「サイオステクノロジー」で検索すれば、今度こそ上手くいってくれるはずです。 ■最後に 今回はユーザ辞書についてと、インデックスの補足についてお話ししてみました。 最後にお話しした インデックスの再作成 は、ユーザ辞書の登録以外にも スキーマ設定の変更 (使用するフィルタの変更など) をする場合には大体必要 になってくるので、solr を使う上では忘れてはならない要素です。 以前にお話ししたとおり、解析とインデックス作成をする都合上 solr のドキュメント登録は重めの処理となっているため、何度もインデックス作成をするのはできれば避けたいところです。 少量のテストデータで試してみたり、デモ画面の “Analysis” を使って主要なワードが思った通りに解析されているかをチェックし、できる限りドキュメントの本登録を行う前にスキーマ設定やユーザ辞書をいい感じにしておくとよいでしょう。 なおユーザ辞書に登録したフレーズは、常にユーザ辞書に登録した切り分け方が採用されるので、「デフォルト辞書との競合で意図しないことが起こる」ということは基本的にはないはずです。 安心して必要なフレーズだけ登録するようにしましょう。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Solr って何者?④:解析内容を調整する① (ユーザ辞書) first appeared on SIOS Tech. Lab .
SIOS Tech Labの龍ちゃんです。2024年は「誰でも簡単に」AIツールが作れるDifyが登場して大いに沸いていましたね。弊社では、Azureを利用したサービス開発が多くあるため、Azure OpenAI Serviceがリリースしてそちらばかり触っていました。2025年はDifyなどのノーコード・ローコードツールを駆使して、AIサービスの開発・検証を進めていきたいと考えています。 いまから入門:Difyとは 生成AIアプリ開発ツール「Dify」の特徴については、おそらく皆さんなんとなくわかっているかと思います。実際触ってみた感想としては、手軽さに驚いています。 専門的なAIエンジニアやアプリエンジニアがいなくても、GUIの操作で簡単に生成AIアプリを作ることができます。また、豊富なLLMモデルと接続することができるので、異なる会社提供のLLMを同じ環境で動作するアプリなども自作することができます。 また、OSSでソースコードが提供されているので、必要に応じてどこまでもカスタマイズを行うことができます。非エンジニアからエンジニアまで、幅広いユーザー層にとって有用なツールです。 Difyブームも落ち着いて、ドキュメントやナレッジも豊富になった2024年でした。幅広い領域で使用ユーザーがいる生成AI活用ツールとして弊社でも注目していました。これから入門して追いつきたい方に向けてナレッジをまとめていきます。 Dify開発環境 Difyの開発をお手軽に始める方法としては、「Dify Cloud」「Docker Compose」「ローカルソースコード」が提供されています。複数の観点で利点などをまとめた表が以下になります。 開発環境 手軽さ カスタマイズ性 デプロイ Dify Cloud 不要 Docker Compose Docker環境 ローカルソースコード 複数必要 その他の項目 開発環境 ストレージ 複数ユーザー SSO Dify Cloud クラウド プラン次第 構築済 Docker Compose 実行環境 可能 要構築 ローカルソースコード 実行環境に保存 可能 要構築 「 Dify Cloud 」は一番お手軽に始めることができます。サイトにアクセスしてGoogleでログインすれば、すぐに利用開始です。非エンジニアの方が試すには、一番楽な方法となります。 「 Docker Compose 」では、Docker環境が必要になります。ソースコードをGitから持ってきて、Docker Composeコマンドを実行するだけで環境を立ち上げることができます。情報も実行環境に保存されるため、ローカル実行ではローカルに情報が保存されます。 「 ローカルソースコード 」では、複数の環境(データベース,Python,Node,etc…)が必要なります。ソースコードをGitから持ってきて複数の環境での起動が必要になるため、だいぶ上級者向きの環境構築となります。それぞれの環境をコードレベルで起動することができるので、カスタマイズ性はとても高いです。 それぞれの環境の特徴としてはこんな感じ! Dify Cloude:とてもお手軽!非エンジニアの方はここから始めよう Docker Compose:クラウド上で作業したくないエンジニア、カスタマイズはあんまりしないけどローカルマシンで実行したい人向け ローカルソースコード:がっつりカスタマイズしたい人向け!起動までの道のりは長い! 今回のガイドでは、「Dify Cloud」と「Docker Compose」での環境構築について記載していきます。 Dify Cloud 事前準備として以下のものが必要となります。 有効なメールアドレス or Google アカウント or GitHubアカウント Dify.aiにアクセス してログインすれば、すぐに利用可能です。以下、最初の画面です。 1人での利用で、軽いお試しであれば無料プランで作業することができます。複数人で開発を進めたい場合は、 Planをアップグレード が利用可能です。この辺りは、使用規模と利用用途によって変わるかと思います。 Docker Compose 事前準備として以下のものが必要となります。 Git Docker 19.03~ Docker Compose 1.28~ こちらの 公式リファレンス を参考に作業を進めていきます。まずはGitを使ってソースコードをローカルに持ってきましょう。 git clone https://github.com/langgenius/dify.git 持ってきたら、dokcerフォルダに移動して、環境変数をコピーしてDocker Composeを用いて起動します。 cd dify/docker cp .env.example .env docker compose up -d これで、 http://localhost/install にアクセスすれば、初期設定画面が出てきます。あとは画面のノリに従って設定すれば利用可能になります。 つまづいたポイント Dify DevContainer起動 DifyのリポジトリにDevContainerの設定が入っていました。最初は、こちらで起動できるのかと考えました。環境内には、node環境、Python環境、Docker環境がセットされていました。そのため、ローカルソースコード開発用の設定だと考えられます。 Dify ナレッジが消える・ナレッジ作成ができない Difyでは、独自の文書を知識(ナレッジ)として登録することができます。その際につまづいたポイントとしては以下になります。 ナレッジ作成後、すぐはナレッジ利用ができるがすぐ参照することができなくなる ナレッジ作成ができない 調べていくと、DifyのDocker Composeに追加で設定をしてあげる必要が出てきました。weaviateのポート設定を追記することで解消することができました。 weaviate: image: semitechnologies/weaviate:1.19.0 ports: - "8000:8000" profiles: - "" - weaviate restart: always volumes: # Mount the Weaviate data directory to the con tainer. - ./volumes/weaviate:/var/lib/weaviate environment: # The Weaviate configurations # You can refer to the [Weaviate](<https://weaviate.io/developers/weaviate/config-refs/env-vars>) documentation for more information. PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate} QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25} AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false} DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none} CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1} AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true} AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih} AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai} AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true} AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai} 別環境で、localhost:8000番を使用していてポートの設定が勝手に割り振られたなどの可能性は無限大です。一度、コンテナを落として再アップしてください。 おわり 今回は、Difyの環境構築について解説しました。クラウド版とDocker Compose版の2つの方法を紹介しましたが、初めて触る方はクラウド版から始めることをお勧めします。次回は、実際にDifyを使って簡単なAIアプリケーションを作成する方法について解説していきたいと思います。 これからDifyを使ってゴリゴリ開発して、ブログ投稿していきます。 ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Dify入門ガイド:初期セットアップ first appeared on SIOS Tech. Lab .
はじめに 皆さんこんにちは。エンジニアの細川です。 皆さんはNestJSで開発を行っているときに Error: Nest can't resolve dependencies of the AppController のようなエラーに遭遇したことはありませんか? 基本的にこのエラーは依存性の解決がうまくできないときに発生するので、各モジュールの依存( imports や exports )を確認すれば解決できることが多いです。 しかし、コードをいくら確認しても問題ないのに、この依存性解決が出るという場面に出くわしたので共有します。同じ原因でエラーが出ている方の参考になれば幸いです。 原因 早速原因ですが、ずばりimportが以下のように型importになっていたことでした。 // 正しい状態 import { AppService } from "@modules/app/services/app.service"; // エラーが出る状態 import type { AppService } from "@modules/app/services/app.service"; この状態ではNestJSがうまく依存性を解決できず、エラーとなってしまいます。 特にBiomeを導入している方は、デフォルトでこのルールが有効になっており、formatされるタイミングで勝手に型インポートに変換されるので、注意が必要です。 Biomeの 公式ドキュメント でもルールを無効にすることを推奨されています。 エラーから原因が分かりづらいので皆さんも注意してください。 対処法(Biomeの場合) 対処法としてはこのルールをオフにすることです。 biome.json に以下の記述を追加します。 { ... "linter": { ... "rules": { // 以下を追加 "style": { "useImportType": "off" } } } } これを追加しておくことで、format時に自動で型importに変更されることもなく依存性解決エラーを解消できます。 ESLintの場合 ESLintの場合も consistent-type-imports というルールが存在するようなので、もしpluginなどに含まれていて明示的にオフにする必要がある場合は無効にしておくと良いかと思います。 詳細はESLintの 公式ドキュメント を確認してみてください。 おわりに 今回はNestJSで謎の依存性解決エラーが出る場合の対処法を紹介しました。 エラーから原因を探りづらいので、こちらの記事が参考になれば幸いです。 他にもNestJSやTypeScriptの 記事 を書いているのでぜひ読んでみてください。 今回参考にさせていただいた記事 https://biomejs.dev/ja/linter/rules/use-import-type/ https://typescript-eslint.io/rules/consistent-type-imports/ https://zenn.dev/dev_commune/articles/ba2586c6ad3efc     ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post NestJSで謎のcan`t resolve dependenciesエラーの解消方法 first appeared on SIOS Tech. Lab .
はじめに サイオステクノロジーの塚田です。Rancher入門ブログシリーズとして、 前回 はRancher上でモニタリング環境を構築する方法について解説しました。本記事では、Rancherから分散ストレージ管理サービスであるLonghornをインストールし、マルチクラスター環境下でストレージを管理する方法を解説します。 Longhornとは? Longhornとは、Rancher Lab社が開発した分散型ブロックストレージシステムです。軽量でKubernetesに特化していることが特徴です。Longhornを導入することで、複数のノードにまたがってデータを分散して管理する仕組みを容易にセットアップすることができます。 Longhornの導入手順 前提条件 Rancher Serverが構築済みであること Rancher Serverの構築方法は 過去の記事 にて紹介しております。 Rancher Serverにログインできること Rancherに管理対象となるクラスターを連携済みであること 過去の記事 にてEC2を利用して構築したKubernetesクラスターをRancherに登録する手順を紹介しております。 管理対象クラスターにrancher-monitoringをインストール済みであること rancher-monitoringのインストール方法については 前回の記事 にて紹介しております。 動作環境 今回はAmazon EC2を利用して構築したKubernetesクラスターにLonghornをインストールし、ストレージ管理のデモを行います。動作環境は以下の通りです。 ノード台数※1 Control Plane: 3 Worker Node: 2 インスタンスサイズ: t3.xlarge vCPU: 4 メモリ: 16GiB OS: Ubuntu ストレージ EBS gp3 50GB x 5 S3バケット x 1 ※1: Longhornは最低3台のノードを利用することが推奨されています。詳しくは公式ドキュメント: Minimum Recommended Hardware の項目をご参照ください。 構築イメージ 今回はRancherのダッシュボードから管理対象となるKubernetesクラスターにLonghornをインストールします。kubectlやHelmを利用して各クラスターに直接インストールすることもできますが、Rancherの統合管理機能を活用することで、Longhornのモニタリングを簡単に設定することができます。 導入後のイメージは以下の通りです。 バージョン情報 Longhorn: 1.7.2※ ※本記事執筆時点における最新バージョン Longhornのインストール Rancherにログインし、サイドバーの[Apps]→[Charts]を選択します。 チャート一覧からLonghornを選択します。 デフォルト設定のまま[Install]を押下します。 インストールが完了すると、longhorn-systemというnamespaceが作成されます。 また、Rancher UIのサイドバーにLonghornという項目が追加されます。 ここからLonghornのダッシュボードに遷移することができます。 Longhornによるストレージ管理デモ ここからはLonghornを使って、実際にストレージ管理する手順をご紹介します。 Volumeの作成と管理 Longhornをインストールすると、longhornという名前のStorage Classオブジェクトが作成されます。このStorage Classを利用することで、PersistentVolumeClaimを作成して動的にPersistentVolumeを作成することができます。 Rancherダッシュボードのサイドバーから[Storage]→[PersistentVolumeClaims]と移動します。 以下の設定でPVCを作成します。 namespace: demo-ns name: demo-pvc Storage Class: longhorn Storage Size: 10GB PVCを作成すると、PersistentVolumeが動的に作成されます。 続いて、作成したボリュームをPodにアタッチします。 Rancherダッシュボードの[Workloads]から[Deployments]に遷移し、Deploymentを新規作成します。 namespace: demo-ns Storage: PersistentVolumeClaim Deployment設定画面の[Pod]欄から[Storage]を選択し、先ほど作成したPVCを選択します。 Deployment設定画面のコンテナ設定画面の[General]に移動し、以下の設定を入力します。 Container Image: alpine:latest Stdin: Yes TTYを有効化 コンテナ設定画面の[Storage]に移動し、マウントポイントを設定します。 Mount Point: /data [Create]ボタンを押下してDeploymentを新規作成します。 Podが起動したら、Pod一覧画面から作成したPodを選択し、[Execute Shell]を押下してPodにログインします。 先ほどマウントした/dataディレクトリに移動できることが確認できました。 以下のコマンドで500MBのダミーファイルを作成してみます。 $ dd if=/dev/zero of=dummy bs=1M count=500 マウントしたディレクトリ内に500MBのファイルを作成することができました。 次に、サイドバーの[Longhorn]からLonghornのダッシュボードに遷移します。 Longhornのダッシュボードのメニューから[Volumes]を選択すると、先ほど作成したPersistentVolumeがLonghornのダッシュボード上にも表示されています。 ボリューム名を押下し、ボリューム詳細画面に遷移すると、3つのノード上でボリュームのレプリカが作成されていることがわかります。 レプリカ作成数はLonghornインストール時の設定項目[Default Storage Class Replica Count]の値を変更することで調整できます。 このように、LonghornはStorage Classの設定に基づき、ボリュームを動的にプロビジョニングするとともに、自動的にレプリカを作成して冗長性を担保しています。 データ保護: SnapshotとBackup 続いて、ストレージ内のデータを保護する機能について紹介します。 Longhornはボリュームのスナップショットとバックアップを作成することができます。スナップショットは、Longhornボリュームのある時点での状態を記録したもので、各ボリュームのレプリカ内にローカルに保存され、Kubernetesクラスター内のノード上に配置されます。バックアップは、スナップショットを元に作成されるもので、ボリュームデータの特定時点の状態を外部のセカンダリストレージ(例: S3互換オブジェクトストレージやNFS)に保存します。スナップショットはクラスター内部でのデータ管理や復元に利用され、バックアップは外部ストレージに保存して災害復旧や長期保管の用途に適しています。 実際にスナップショットやバックアップを作成してみます。 まずはLonghornのダッシュボードの[Volumes]画面に遷移し、先ほど作成したボリュームを選択します。 ボリューム詳細画面の[Snapshots and Backups]まで移動し、[Take Snapshot]ボタンを押下します。 しばらくすると、スナップショットが作成されます。 続いて、バックアップを作成してみます。 バックアップを作成するには、保管場所となる外部ストレージが必要です。 本記事では、バックアップの保存先としてS3バケットを使用します。 利用可能なストレージに関しては、公式ドキュメントの Setting up a Target の項目をご参照ください。 まずは、S3バケットを作成しておきます。 Rancherのダッシュボード[Storage]→[Secrets]へ移動し、namepsace [longhorn-system]上にAWSのクレデンシャル情報を格納するSecretを作成します。 本記事ではAddministratorAccess権限をアタッチしたIAMユーザーを使用しておりますが、必要となるIAM権限につきましては、公式ドキュメントの Set up AWS S3 Backupstore の項目をご参照ください。 Secretを作成したら、Longhornダッシュボードに遷移し、[Settings]を選択します。 Settings内のBackup欄でS3への接続情報を入力し、[Save]ボタンをクリックして保存します。 Backup Target: S3バケットのURL Backup Target Credential Secret: AWSクレデンシャル情報を格納したSecretのname これでバックアップ保存先の設定が完了しましたので、実際にバックアップを作成してみましょう。 [Volumes]よりボリューム一覧画面に遷移し、作成したボリュームを選択します。 選択したボリュームの詳細画面内[Snapshots and Backups]にて、[Create Backup]を押下し、バックアップを作成します。 [Snapshots and Backup List]にてバックアップが作成されたことを確認することができます。 また、Longhornダッシュボードの[Backup]欄の方でもバックアップを確認することができます。 スナップショット・バックアップのライフサイクル スナップショットの作成・削除、バックアップ作成はタイマー設定で自動化することができます。 今回は、以下の条件でスケジュールを設定してみます。 スナップショット 取得:日次AM02:00 保持:直近2日分 バックアップ 取得:日次AM04:00 保持:直近1日分 Longhornのダッシュボード[Volumes]画面より先ほど作成したボリュームを選択します。 [Recurring Jobs Schedule]欄の[Add]ボタンを押下し、以下のようにスケジュールを設定します。 snapshot: Retain ※2 : 3 cron: UTC17:00 ※3 (02:00 JST) every day snapshot-delete: Retain: 2 cron: UTC17:00(02:00 JST) every day backup cron: UTC19:00(04:00 JST) every day ※2: Retainはスナップショットやバックアップをいくつまで残すかを設定するパラメータです。snapshotのretain 3により直近3つまでスナップショットを保持します。snapshot-deleteのretain 2の設定により、3つ以上前のスナップショットは削除され、最終的にはスナップショットは2日分残るようになります。 ※3: LonghornのタイムゾーンはUTCで設定されています。 指定した時刻(02:00AM)になると、直近2つ分のスナップショットが作成されます。 04:00AMになると、バックアップが1つ作成されます。 翌日以降のスナップショット、バックアップは最新のデータに上書きされます。 このように、スケジューリング機能を活用することで、効率的に保存データのライフスタイル管理を実現することができます。 例えば、スナップショットは日次で保存しつつ、長期保管用のバックアップは週次で保存するなどの設定をすることで、ストレージの利用効率を向上させることができます。 Rancherモニタリング機能との連携 RancherからLonghornを導入することで、Longhornが出力するメトリクスを利用したストレージ利用状況の可視化や異常検知を簡単に設定することができます。 まずは、LonghornのメトリクスをPrometheusが受信できるよう、Longhorn用のService Monitorを作成します。 Rancherダッシュボードのサイドバーから[Monitoring]→[Serivce Monitor]画面へ遷移し、Createボタンを押下してService Monitorの新規作成画面へ移動します。 Service Monitorを作成するテンプレートは以下の通りです。今回は 公式ドキュメントに記載されているテンプレート をそのまま利用しています。 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata:   name: longhorn-prometheus-servicemonitor   namespace: longhorn-system   labels:     name: longhorn-prometheus-servicemonitor spec:   selector:     matchLabels:       app: longhorn-manager   namespaceSelector:     matchNames:     - longhorn-system   endpoints:   - port: manager Service Monitorの作成が完了したら、Longhornから出力されたメトリクスを受信できているかGrafanaで確認します。 公式ドキュメントで紹介されているダッシュボード をインポートして、Grafana上でストレージの利用状況を可視化してみます。 上記Longhorn Example v1.1.0のページからJSONをダウンロードします。 Grafanaのサイドバーから[Dashboards]を選択し、画面右上の[New]タブから[Import]を選択します。  Import Dashboard画面にて[Upload dashboard JSON file]を選択し、先ほどダウンロードしたダッシュボード設定のJSONをアップロードします。  Import dashboard画面より、「Options」-「prometheus」からPrometheusを選択します。 Importを押下し、Longhorn用のダッシュボードを作成します。 ダッシュボード一覧画面からインポートしたダッシュボードを選択します。  これで、ストレージの利用状況や死活監視が可能になりました。 Longhornから取得できるメトリクスの一覧は公式ドキュメントの Longhorn Metrics for Monitoring ページにて確認することができます。 まとめ 本記事では、Rancherを利用したLonghornの導入方法から、ストレージ管理の基本操作、そしてモニタリングの統合までを解説しました。 RancherとLonghornを連携することで、以下のようなメリットが得られます: 効率的なストレージ管理:GUIベースでの操作により、複雑な設定が簡単に。 高度なデータ保護:スナップショットやバックアップを利用した多層的な保護機能。 運用の可視化:Rancherモニタリングとの統合により、ストレージの状態やパフォーマンスをリアルタイムで監視可能。 特に、マルチクラスター環境でのストレージ管理や災害復旧の運用において、RancherとLonghornの組み合わせは大きな効果を発揮します。 本記事を参考に、ぜひRancherとLonghornを活用して効率的なストレージ管理を実現していただければ幸いです。 参考 Longhorn公式ドキュメント ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Rancher入門:RancherとLonghornを活用したストレージ運用の始め方 first appeared on SIOS Tech. Lab .
ども!年末年始の検証結果を順次ブログ化している龍ちゃんです。思いついたらすぐ検証という流れで、いろんなことを検証していたので10本ぐらいはブログのネタに困らなさそうですね。反動が今から恐ろしいです。 今回の内容は、以下の二つになります。 ローカル開発環境をDevContainerで作成する(nest.js + postgres) nest.jsからPrismaを使用してpostgresに接続する 今回のゴールとしては、nest.js内でORMとしてPrismaを使用してpostgresへ接続して動作確認となります。 環境構築 前提条件としては、DockerとDocker Composeコマンドが使えれば大丈夫です。最終的なファイルとしては、こちらのリポジトリに上がっています。まだ、絶賛開発に使用する前段階なので、何の整備もしていなくてすいません。 参考 GitHub – Ryunosuke-Tanaka-sti/2025-nest-backend GitHub ディレクトリ構成としては、以下のようになります。postgresのデータの永続化は、ボリュームマウントとしてコンテナ内へ収めておきます。 . ├── .devcontainer │   └── devcontainer.json ├── .dockerignore ├── .env # docker用環境変数 ├── Dockerfile ├── docker-compose.yml └── nest-app # nest.jsアプリ nest.jsの環境づくり node_modulesをvolumeマウント化 postgresの環境づくり nest.jsの環境づくり まずは、nest.jsの環境を作っていこうと思います。先にNodeの環境を作成して、DevContainerでいきなりアクセスしてしまいます。 三つのファイルを作成します。 Dockerfile ARG NODE_VER FROM node:${NODE_VER} as base RUN npm install -g npm@11.0.0 FROM base as dev RUN npm i -g @nestjs/cli USER node WORKDIR /home/node/app docker-compose.yml version: "3.7" services: nest: build: args: - NODE_VER=22.12.0 context: . dockerfile: Dockerfile target: dev tty: true volumes: - type: bind source: . target: /home/node/app .devcontainer/.devcontainer.json { "name": "procject-backend", "dockerComposeFile": ["../docker-compose.yml"], "service": "nest", "workspaceFolder": "/home/node/app", "customizations": { "vscode": { "extensions": [], "settings": {} } }, "remoteUser": "node", } DevContainer内に入ったら、next.jsのプロジェクトを作成します。Dockerfile内でnest CLIをインストールしているので、実行可能かを試してみます。 nest --version バージョンが帰ってきたら、成功しているのでそのままアプリを作っていきましょう。今回のアプリ名は nest-app で作成していきます。 nest new nest-app これで環境作成は完了です。 node_modulesをvolumeマウント化 node_modulesをvolumeマウントにすることで、コンテナ内に収めてしまいます。こちらの対応をしておくことで、元ファイル側のサイズを小さくすることができます。また、bindマウントしないことによりビルド速度を上昇させることができます。 こちらでやっていることは、「.dockerignoreでビルド時にnode_modulesをなかったことにして、Dockerfileでnode_modulesを作成してビルド、dokcer-compose.ymlでnode_modulesをボリュームマウントする」となります。Dockerファイルで作成している理由としては、dokcer-compose.ymlファイル経由で作成させるとroot権限で作成されて、詰まったいい思い出があります。 追加で、 .dockerignore ファイルを作成してください。 .dockerignore nest-app/node_modules Dockerfile ARG NODE_VER FROM node:${NODE_VER} as base RUN npm install -g npm@11.0.0 FROM base as dev RUN npm i -g @nestjs/cli USER node WORKDIR /home/node/app RUN mkdir nest-app COPY --chown=node:node nest-app nest-app WORKDIR /home/node/app/nest-app RUN mkdir node_modules RUN chown node:node node_modules RUN npm install docker-compose.yml version: "3.7" services: nest: build: args: - NODE_VER=22.12.0 context: . dockerfile: Dockerfile target: dev tty: true volumes: - type: bind source: . target: /home/node/app - type: volume source: node_modules target: /home/node/app/nest-app/node_modules volumes: node_modules: ファイルの適応が完了したら、**DevContainerを必ずRebuildしてください。**以上で、node_modulesのボリュームマウント化完了です。 next.jsのアプリを作成した際に発生したnpm installで持ってきたnode_modulesが元ファイルに残っていると思います。気になる方は、コンテナから抜け出して、お好きなように処理してください。 postgres環境づくり postgresの環境は、16.6とバージョンを指定して作成していきます。公式のリファレンスを置いておきます。 参考 https://hub.docker.com/_/postgres 環境変数を渡すので、まずは.envファイルを作成しておきます。本当のファイルの場合は、もっとちゃんとしたセキュリティにしてくださいね。 .env POSTGRES_USER=user POSTGRES_PASSWORD=password docker-compose.yml version: "3.7" services: nest: build: args: - NODE_VER=22.12.0 context: . dockerfile: Dockerfile target: dev tty: true volumes: - type: bind source: . target: /home/node/app - type: volume source: node_modules target: /home/node/app/nest-app/node_modules depends_on: - postgresql postgresql: env_file: ".env" container_name: postgresql image: postgres:16.6 ports: - 5432:5432 volumes: - type: volume source: postgres_data target: /var/lib/postgresql/data environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_INITDB_ARGS: "--encoding=UTF-8" TZ: "Asia/Tokyo" hostname: postgres restart: always volumes: node_modules: postgres_data: nest.jsのアプリは、postgresの環境が立ち上がった後に立ち上がるように設定しておきます。あくまで開発環境なので、厳密である必要はないのですが、DB前提のシステムを組むと想定されるので念のためですね。 ここまでコピペできたら、**DevContainerを必ずRebuildしてください。**実行中のDevContainerからpostgresの環境にアクセスして以下のコマンドを実行してください。 psql -h postgres -U user 無事アクセスすることができれば、問題なく動作していると考えられます。 Prisma接続 参考 Documentation | NestJS – A progressive Node.js framework Documentation | NestJS – A progressive Node.js framework Prismaのセットアップは公式のドキュメントが十分なので、今回作成したpostgresへアクセスするまでについて共有していきます。これから、Prsimaの勉強もしていくので、まとまったらブログ書きます。 npm install prisma --save-dev npx prisma init # prismaセットアップ .envファイルが作成される npm i --save @nestjs/config # nest.jsのコンフィグ読み込み用ライブラリ nest-app/src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ConfigModule.forRoot({isGlobal:true})], controllers: [AppController], providers: [AppService], }) export class AppModule {} Globalで環境変数を読めるようにglobalで読み込んでおきます。これで、Prismaが作成した.envファイルも読み込むことができます。 スキーマファイルに定義を記入します。 nest-app/prisma/schema.prisma // This is your Prisma schema file, // learn more about it in the docs: <https://pris.ly/d/prisma-schema> // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? // Try Prisma Accelerate: <https://pris.ly/cli/accelerate-init> generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @default(autoincrement()) @id email String @unique name String? posts Post[] } model Post { id Int @default(autoincrement()) @id title String content String? published Boolean? @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } ここまでしてやっとで .env ファイルの接続情報変更します。今回の環境では、以下に更新することで接続することができます。 DATABASE_URL="postgresql://user:password@postgres:5432/mydb?schema=public" // DATABASE_URL="postgresql://{ユーザー}:{パスワード}@{ホスト名}:5432/mydb?schema=public" 以下のコマンドで先ほどコピペした内容がDBに反映されます。 npx prisma migrate dev --name init コマンドが無事完了したら、以下のコマンドでprisma studioを立ち上げて反映できているか確認します。 npx prisma studio かっこいい画面が立ち上がり、PostとUserが作成されていれば無事にアクセスできています。 prisma studio画面 おわり 今回の閑居構築で特に詰まった点としては、postgresの環境にアクセスできるまで長かったのでpostgresの環境作成が正しいのか試すことができなかった点ですね。postgresのイメージのドキュメントをちゃんと読みに行きましたね。今回は、DevContainerのVolumeを何度も消し飛ばして検証しました。開発体験としては、Git上でローカルのデータを管理しない想定なのでバインドはしたくありませんでした。PrismaのSeedなどを作りこんでおけば問題ないかと思います。 では2025年もよろしくお願いします。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【NestJS + PostgreSQL + Prisma】DevContainerで作る快適な開発環境 first appeared on SIOS Tech. Lab .
ども!年末年始を抜けてぬるっと仕事に復帰を始めている龍ちゃんです。年末年始は、今まで溜まっていた検証+お部屋を片付けていたので、意外と充実していました。去年は、GitHub AcitonsとDevContainerでの環境構築作成をしっかりやっていた時期かなと振り返り、またブログにまとめていきます。 今回の内容は、以下の二つになります。 Azure Static Web Apps上でNext.jsの静的サイト配信を行う(GitHub Actionsを用いたデプロイ) ローカルの開発環境をDevContainerで作成する(SWA CLIを活用してローカルでプレビュー) ローカル環境でStatic Web Apps(以降:SWA)の挙動を確認することができる、SWA CLIを開発環境にインストールします。今回のゴールとしては、SWA CLI動作確認とSWAへのNext.js静的サイトを公開になります。 SWA CLIとは 参考 Azure Static Web Apps CLI について Azureさん公式のエミュレーターになります。SWAの挙動をローカルで再現してくれます。開発時に特にうれしい機能として以下の二つかなと思います。 SWA上に構築済みの認証をモックで試すことができる APIエンドポイントへのプロキシ SWA上に構築済みの認証をモックで試すことができる 参考 Azure Static Web Apps の認証と認可 SWAでは、コンフィグファイルに追記するだけで色々な認証プロバイダー(Google / X / Apple / etc…)から認証を受けることができます。SWA上で構築済みのサービスになるので、ローカルで認証を試すことができません。そこで、ダミーのモックで認証を通った状況を作ることができます。認証後の情報取得方法もローカルで動作確認できるので、非常に助かります。 APIエンドポイントへのプロキシ 参考 Azure Static Web Apps での API サポートの概要 SWAでは、Azure Function(Freeプランでも可)やWeb Apps(Standardプランのみ可)で作成したAPIを /api ルートと接続することができます。こちらも、SWA上で構築済みのサービスなのでローカルの開発では、SWAのプロキシを再現する必要があります(まぁ無理よな)。SWA CLIを使うことで、そのあたりの挙動も模倣して提供してもらえます。 開発環境構築 環境構築の内容に入っていきます。前提条件としては、DockerとDocker Composeコマンドが使えれば大丈夫です。最終的なファイルとしては、こちらのリポジトリに上がっています。 参考 GitHub – Ryunosuke-Tanaka-sti/2025-next-static-site GitHub ディレクトリ構成としては、以下のようになります。 . ├── .devcontainer │   └── devcontainer.json # DevContainer環境設定 ├── .dockerignore ├── .env            # local用環境ファイル ├── .github │   └── workflows ├── Dockerfile ├── docker-compose.yml ├── my-app # Next.jsアプリディレクトリ └── swa-cli.config.json # SWA CLIコンフィグファイル Next.jsの環境づくり node_modulesをvolumeマウント化 SWA CLIのセットアップ (SWA CLI Config) 静的サイト用対応( staticwebapp.config / Next.js config) Next.jsの環境づくり まずは、Next.jsの環境を作っていこうと思います。ここでは、Nodeの環境を作成してDevContainerでいきなりアクセスしてしまいます。三つのファイルを作成してください。 Dockerfile ARG NODE_VER FROM node:${NODE_VER} RUN npm install -g npm@11.0.0 RUN npm install -g @azure/static-web-apps-cli USER node WORKDIR /home/node/app docker-compose.yml version: "3.7" services: next: build: args: - NODE_VER=22.12.0 context: . dockerfile: Dockerfile tty: true volumes: - type: bind source: ./ target: /home/node/app .devcontainer/.devcontainer.json { "name": "procject-dev", "dockerComposeFile": ["../docker-compose.yml"], "service": "next", "workspaceFolder": "/home/node/app", "customizations": { "vscode": { "extensions": [], "settings": {} } }, "remoteUser": "node", } DevContainer内に入ったら、Next.jsのプロジェクトを作成します。今回は、create-next-appから提案されるmy-appで話を進めていきます。ここは任意に変更してください。 npx create-next-app@latest これで、Next.jsの環境が作成することができました。 node_modulesをvolumeマウント化 node_modulesをvolumeマウントにすることで、コンテナ内に収めてしまいます。こちらの対応をしておくことで、元ファイル側のサイズを小さくすることができます。また、bindマウントしないことによりビルド速度を上昇させることができます。 こちらでやっていることは、「.dockerignoreでビルド時にnode_modulesをなかったことにして、Dockerfileでnode_modulesを作成してビルド、dokcer-compose.ymlでnode_modulesをボリュームマウントする」となります。Dockerファイルで作成している理由としては、dokcer-compose.ymlファイル経由で作成させるとroot権限で作成されて涙を呑むからですね。 追加で、 .dockerignore ファイルを作成してください。 .dockerignore my-app/node_modules Dockerfile ARG NODE_VER FROM node:${NODE_VER} RUN npm install -g npm@11.0.0 RUN npm install -g @azure/static-web-apps-cli USER node WORKDIR /home/node/app RUN mkdir my-app COPY --chown=node:node my-app my-app WORKDIR /home/node/app/my-app RUN mkdir node_modules RUN chown node:node -R node_modules RUN npm install docker-compose.yml version: "3.7" services: next: build: args: - NODE_VER=22.12.0 context: . dockerfile: Dockerfile tty: true volumes: - type: bind source: ./ target: /home/node/app - type: volume source: node_modules target: /home/node/app/my-app/node_modules volumes: node_modules: ファイルの適応が完了したら、**DevContainerを必ずRebuildしてください。**以上で、node_modulesのボリュームマウント化完了です。 Next.jsのアプリを作成した際に発生したnpm installで持ってきたnode_modulesが元ファイルに残っていると思います。気になる方は、コンテナから抜け出して、元ファイルのnode_modulesを削除してください。 SWA CLIのセットアップ SWA CLI自体は、Dockerfileのnpm globalインストールですでに導入済みです。コンテナ内で以下のコマンドで確認してください。 swa --version バージョン情報が返ってくれば、インストール自体は完了しています。また、以下のコマンドで対話的にコンフィグファイルを作成することができます。 swa init フレームワーク等も自動で判断して作成してもらえるので非常に便利なコマンドです。 対話的に作成しなくても、以下のファイルをコピペしてもらえれば起動することができます。 swa-cli.config.json { "$schema": "<https://aka.ms/azure/static-web-apps-cli/schema>", "configurations": { "app": { "appLocation": "my-app", "run": "npm run dev", "appDevserverUrl": "<http://localhost:3000>" } } } 上記のファイルを作成したディレクトリで、以下のコマンド一つでエミュレーター起動までやってもらえます。 swa start 特に設定していなければ、 http://localhost:4280 で起動しているかと思います。 静的サイト用対応 最後に、Next.jsとSWAそれぞれで静的サイト用の設定を追加していきます。Next.jsのコンフィグファイルを編集して静的エクスポートを有効にします。 my-app/next-config.ts import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ output: "export", trailingSlash: true, }; export default nextConfig; こちらの設定を有効にするだけで、 npm run build で out ファイル内に静的ファイルが生成されます。 trailingSlash: true では、静的ファイルのエクスポート時に ディレクトリ/index.html という形式でファイルを読み込んでくれます。 次に、SWA側の設定ファイルです。こちらは、ローカル用と本番用の二つのファイルを用意します。ローカルでは、コンフィグファイルを指定して起動します。本番用のファイルは npm run build で静的ファイルにそのまま書き込まれるように、Next.jsの public ディレクトリに作成します。今回は、Next.jsの設定に併せて trailingSlash の設定のみ追加します。 ローカル: .env/local/staticwebapp.config.json 本番用: my-app/public/staticwebapp.config.json { "trailingSlash": "auto" } 最後に、SWA CLIのコンフィグファイルにローカルの staticwebapp.config.json の位置を教えます。 { "$schema": "<https://aka.ms/azure/static-web-apps-cli/schema>", "configurations": { "app": { "appLocation": "my-app", "run": "npm run dev", "appDevserverUrl": "<http://localhost:3000>", "swaConfigLocation": ".env/local" } } } これで swa start では、 .env/local 内のコンフィグファイルが読み込まれて実行します。 SWA deploy with GitHub Actions 事前準備としては、Azure Static Web AppsのデプロイトークンをGitHubのSecretとして保存しておく必要があります。今回は、環境 deploy内に AZURE_TOKEN として保存しているとして進めていきます。開発環境はDockerで作成しましたが、デプロイ自体はActions内でビルドしてデプロイをしています。 on: push: branches: ["main"] workflow_dispatch: env: NODE_VERSION: "22.x" permissions: contents: read jobs: build: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: "npm" cache-dependency-path: my-app/package-lock.json - name: npm install, build, and test run: | npm install npm run build working-directory: my-app - name: Upload Cache app uses: actions/cache/save@v4 with: path: my-app/out/ key: ${{ runner.os }}-app-${{ github.sha }} deploy: runs-on: ubuntu-24.04 needs: build environment: deploy steps: - uses: actions/checkout@v4 - name: Download Cache app uses: actions/cache/restore@v4 with: path: my-app/out/ key: ${{ runner.os }}-app-${{ github.sha }} - name: Build And Deploy uses: Azure/static-web-apps-deploy@1a947af9992250f3bc2e68ad0754c0b0c11566c9 with: azure_static_web_apps_api_token: ${{ secrets.AZURE_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }} action: "upload" output_location: "my-app/out/" app_location: "my-app/out/" skip_app_build: true 内容としてはシンプルで、以下の順序で実行されます。 ビルド アプリケーションのビルド 静的ファイルoutをキャッシュ デプロイ キャッシュからアプリを復元 静的ファイルをSWAに配信 Azure/static-web-apps-deploy はビルドもアクションの中で実行してくれる優れものです。ですが、今回はCI上でビルドを実行して、デプロイのためだけに使用しています。 終わり 今回の開発環境構築で特に詰まった点としては、Next.jsで静的ファイルを配信するための設定周りですね。Next.jsとSWAでそれぞれ設定が必要な点は盲点でした。 最近は、フロントエンドの開発環境構築はCI/CDパイプラインを組むところまでやるべきなのかもしれないと思ってきましたね。次回は、バックエンドの環境構築について記載を進めておきます。Azure上で公開するための開発環境構築なんて必要そうですね。三日間ぐらいDockerと戯れすぎて、yamlファイルアレルギーになりそうです。 では2025年もよろしくお願いします。これは1月中に毎回言っておきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure Static Web Appsで始めるNext.js静的サイト開発 with DevContainer first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの佐藤 陽です。 先日、MSの資格である Azure Cosmos DB Developer Specialty に認定されました! 久々にMSの試験を受けて合格したので、また合格体験記の方を書いていきたいと思います。 以前の合格体験記はこちら。 【合格体験記】Azure Solutions Architect Expert【AZ-305】 【合格体験記】Azure DevOps Engineer Expert【AZ-400】 はじめに 以前の合格体験記の際にも書いたのですが 試験の内容に関して詳細に記載すると Microsoft から怒られてしまい、資格剥奪されてしまうとのことです。 そのため非常にふんわりした内容の記事になりますが、その点ご了承ください。 Cosmos DB Developer Specialtyとは Azureが提供するNoSQL型のデータベースであるCosmosDBに特化した資格になります。 これまで受けてきた資格(Solutions Architect Expertや、Developer Associate等)は複数のリソースに関する問題が出題されていましたが 今回認定を受けたCosmos DB Developer Specialtyに関しては、CosmosDBのみが対象となっています。 さらに言えばCosmosDBの中でもCore SQLのアカウントだけが対象となっています。 そしてこの認定を受けるためには、DP-420の試験に合格する必要があります。 受験理由 なぜDP-420の受験をしたかに関してですが NoSQLを用いたアプリケーション開発経験が無く、体系的な知識を身につけたかった 最近AI関連でも多くCosmosDBなどが取り上げられるようになった の2点があります。 アプリケーション開発 これまでWebアプリの開発色々と行ってきましたが、いずれもRDBを用いたものが多かったです。 NoSQLに関して何となくの知識はありましたが、実際に手を動かして作業できるレベルではありませんでした。 しかし今後の開発において、NoSQLを使ったアプリ開発を行うことは容易に想像できました。 色々と変化が激しい世の中において、非構造化データを扱う場面が多くなることは間違いないと思ったのです。 もちろんRDBを使う場面も多くあるかと思うのですが、どちらを採用するべきかを判断するためにも NoSQLであるCosmosDBの知識をしっかり身に着けておきたいと思いました。 受験してみて実際どうだったかというと、体系的な知識を身に着けることが出来ました。 パーティション分割の考え方や、マルチリージョンの考え方など、基本的な知識を得ることが出来ました。 まだまだアプリにとって最適な設計が出来るか…と言われたら知識が不足しているとは思いますが 有識者から指摘やアドバイスなどが頂けたら、その内容を理解して自ら反映することはできるくらいにはなったかなと思います。 AI関連 CosmosDBはAIを活用したアプリケーション活用にも多く使われるようになりました。 最近ではベクトル検索や、ハイブリット検索の機能も追加され、RAGの構築などでも採用されるケースが多く見られます。 そのため、今後より活用が進んで行くだろうと思い、このあたりの知識習得をしていきたいと思いました。 こちらに関して実際どうだったかというと、AI関連の機能に関しては現段階(2025年1月)においては試験の対象外となっており、試験においても全く出題されませんでした。 一応公式ドキュメントなどは一通り読んで知識は入れましたが、資格取得を通して…といった意味ではあまり効果はありませんでした。 このあたりはまた独自でキャッチアップの方を進めていきたいと思います。 試験概要 先程も述べたように、CosmosDB特化型の試験です。 CosmosDBの構造の理解から、設計ポイント、実装時のコードレベルの問題まで幅広く出題されます。 特に パーティション分割 インデックスの構築 マルチリージョンに対する読み書き といった所は 基本的な部分であり、なおかつ最重要事項 であると思いました。 逆にここら辺の本質を理解していれば、あとはこれらの知識脳応用で乗り切れるんじゃないかなという印象です。 あとは他サービスとの連携部分で、SynapseやData Factoryとの連携部分も問われることが多かったです。 ここら辺の他サービスの知識がなかったので、自分は知識を詰め込んで乗り切りました…。 学習コンテンツ MS公式 鉄板ですが、MSの公式ドキュメントです。 結構分かりづらいことが言われているMS公式でしたが、今回のCosmosDBに関していえば割とスラスラ読めました。 あとは今回の試験がCosmosDBだけであるため、読む場所が一か所にまとまってるのもいいですね。 ただ、公式ドキュメントとMSLearnに知識が散らばっていたので、双方を照らし合わせながら読むと理解が捗るかと思います。 公式ドキュメント MS Learn Udemy Udemyにも本試験に特化した講座がありました。 Microsoft Azure Cosmos DB Exam Guide [Hands-on] こちらのUdemyの講座ですが、非常に分かりやすかったです。 ほとんど知識がない自分が一通り見たことで、CosmosDBの基本的な部分は理解できました。 ただ、一方で試験を合格するには内容が不足しています。 そのため、このUdemyの講座を一通り見て概要をつかんだ後、公式ドキュメントなどを利用して知識を補完する必要があるかと思います。 その他 試験勉強しているときに、ちょうどMS Ignite2024が開催されました。 そして、Igniteの中で以下のセッションがありました。 Cosmic efficiency: mastering performance and cost in Azure Cosmos DB | BRK194 Igniteなので非常に高いレベルの内容なのかな?と思われますが、とても基本的なところから説明してくれています。 どれくらい易しいかというとRU(Request Unit)とは何か?といった所から紹介してくれています。 CosmosDBを絶賛勉強中だった自分にはとてもタイムリーで、非常に刺さる内容でした。 あとはこちらの御成門プログラマーさんの 記事 でも紹介されていた 畠山さんのCosomosDBの セッション も非常に分かりやすかったのでお勧めです。 おわりに 今回はCosmos DB Developer Specialtyの合格体験記を書きました。 今回の受験を通してCosmos DBの基礎部分が分かったとともに、設計の難しさ・面白さが垣間見えた気がします。 これからアプリを開発していくうえで、ベストなCosmosDBの設計が出来るよう引き続きキャッチアップを続けていきたいと思います。 アウトプット 勉強していく過程でアウトプットした記事になります。 まだ途中までしか書けていないので引き続き書いていきたいと思います。 【Azure】CosmosDBにおけるRU入門ガイド【初心者向け】 https://tech-lab.sios.jp/archives/44424 【Azure】CosmosDBにおけるパーティション入門ガイド【初心者向け】 https://tech-lab.sios.jp/archives/44573 【Azure】CosmosDBにおけるインデックス入門ガイド【初心者向け】 https://tech-lab.sios.jp/archives/45014 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【合格体験記】Azure Cosmos DB Developer Specialty【DP-420】 first appeared on SIOS Tech. Lab .