株式会社Insight Edgeのブログ - TECH PLAY

TECH PLAY

株式会社Insight Edge

株式会社Insight Edge の技術ブログ

全206件

こんにちは!Insight Edgeの塩見です。 2023年7月11日(火)~13日(木)の3日間、東京ビッグサイトにて「AI World 2023」が初開催されました。本展示会では、ChatGPTを活用したソリューションが数多く展示されていたため、その内容をご紹介したいと思います。 AI Worldとは? ChatGPTとは? 各社のChatGPTソリューション紹介 株式会社AVILEN 「研修、アイディアソン、ソリューション開発」 株式会社ギブリー 「法人GAI・行政GAI」 パーソルプロセス&テクノロジー株式会社 「TIMO Meeting」 Allganize Japan株式会社「Alli」 まとめ AI Worldとは? AI Worldは、ビジネス変革と業務効率化をテーマとした大型展示会です。この展示会では、DX(デジタルトランスフォーメーション)、業務効率化、チャットボット、機械学習、画像・音声認識、自然言語処理、対話AIを始めとする最新のAIソリューションが一堂に展示されます。商談を求める企業にとっては、課題解決のための貴重なヒントを手に入れることができ、またAI技術の最先端を一目で確認することができる場となっています。  AI World 2023 さらに、この展示会はリアルな場所での展示の他、オンラインでのセミナー視聴や製品資料のダウンロードも可能です。これにより、遠方からの参加者や、展示会場に来ることができない方でも情報収集が容易になっています。 場所としては、東京ビッグサイト(西1・2ホール)を使用して開催され、展示製品数は同時開催された他展示会と合わせると、日本最大級とされる約870製品が出展されました。また、デジタル庁や総務省、東京都などの公的機関からの後援を受けており、その規模と重要性を物語っています。実際、来場者数は計22,295名であり、業界関係者やビジネスパーソンからの高い関心が伺えます。 ChatGPTとは? ChatGPTは、OpenAIによって開発された大規模な言語モデルを活用したAIチャットサービスです。ユーザーとの対話形式で情報提供や問い合わせ応答が可能であり、その高度な自然言語処理能力により、様々なビジネスやサービスに応用されています。ChatGPTは2022年末に公開され、その後、急速に利用者数が増加しました。 2023年2月、本展示会と類似内容の展示会であるDX EXPOが開催され、その場でも多くのAIソリューションが展示されていましたが、ChatGPTの公開から間もない為、ChatGPTに関連したソリューションを展示していた企業は1社程度しかありませんでした。 一方、本展示会では、10を超えるChatGPTソリューションが展示されており、多くの企業がChatGPT公開後に関連サービスの開発を進めていたことがわかります。実際、これらのソリューションは展示会見学者の注目を多く集めており、企業だけでなくユーザの期待値も高いことが想定できます。 各社のChatGPTソリューション紹介 ここからは、AI Worldにて展示されていたChatGPTソリューションを一部ご紹介します。各ソリューションの詳細が記載されたWebページへのURLリンクも併せて載せていますので、こちらもご参照ください。 株式会社AVILEN 「研修、アイディアソン、ソリューション開発」 株式会社AVILENでは、ChatGPTをビジネス活用する上で、各社の課題やフェーズに応じたソリューションを一気通貫で支援するサービスを提供していました。 具体的には、以下の支援サービスがあります。 ChatGPTビジネス研修 ChatGPTアイディアソン ChatGPTソリューション開発(Chat Mee, Chat Mee Pro) ビジネス研修では、「そもそもChatGPTで何ができるのかわからない」というユーザ向けに、ChatGPTの基礎知識をE-ラーニングで学習してもらいながら、ChatGPTを実際に体験するワークを実施します。 アイディアソンでは、「ChatGPTを自社でどのように活用できるかアイディアが欠けている」と感じるユーザ向けに、企画立案から実行まで、コンペ形式でAVILENがサポートします。 ソリューション開発では、「ChatGPT導入・開発に必要なノウハウやリソースが不足している」と感じるユーザ向けに、ChatGPTに精通したデータサイエンティストが課題の明確化から開発、保守まで一気通貫で支援します。 現在、ChatGPTの利用は日本国内でも増加していますが、まだChatGPTを利用したことがないユーザが大多数であることを考えると、ChatGPTの基礎教育・業務課題やユースケースの整理・ソリューション開発といった一連の流れをサポートするこのサービスは、非常に有益だと感じました。 株式会社AVILEN ChatGPT活用支援サービスの詳細はこちら 株式会社ギブリー 「法人GAI・行政GAI」 株式会社ギブリーでは、法人・行政でChatGPTを安全に使用できるGAIサービスを展開しています。ChatGPTを法人・行政内で使用する場合、機密情報が漏洩する可能性がありますが、これらのGAIサービスでは、情報が外部に漏洩するリスクをなくしつつ、ChatGPTを法人・行政内で使用することが可能です。 その他、NGワードの登録、ユーザの利用状況をモニタリングできるダッシュボード機能、実務における様々な利用シーンを想定したプロンプトレシピ機能等、ChatGPTを実務で活用する上での利便性の高い機能を多く揃えています。 セキュアな環境でChatGPTを活用する為のサービスは、直近続々とリリースされている印象がありますが、プロンプトレシピやダッシュボード機能など、ユーザに選んでもらう上では、プラスアルファの機能が重要になってくるのかなと思います。 株式会社ギブリー 法人GAIの詳細はこちら 株式会社ギブリー 行政GAIの詳細はこちら パーソルプロセス&テクノロジー株式会社 「TIMO Meeting」 TIMO Meetingは、会議プロセスのデジタル化を通じて、生産性向上を実現する国内初のミーティングマネジメントツールです。本ツールにもChatGPTが活用されており、「AIアシスタント」と「AIアドバイザリー」の2つの機能があります。 AIアシスタントでは、会議予定に添付された資料を読み込み、資料を元にして、会議の目的・背景・論点などを端的にまとめてくれます。これにより、会議参加者は事前にこの会議がどのようなものかを理解することができ、会議の効率性や効果の改善に繋がります。 AIアドバイザリーでは、会議予定の添付資料に関する質問をチャット形式で投げかけることで、資料内容を要約してもらう等、AIからの様々なアドバイスを受けることができます。 TIMO Meetingでは、自社独自ソリューションにChatGPTを組み込み、他社と差別化を計りつつソリューション価値を向上することが出来ている良い事例かと思います。 パーソルプロセス&テクノロジー株式会社 TIMO Meetingの詳細はこちら Allganize Japan株式会社「Alli」 Allganize Japan株式会社は、AIチャットボットのAlliを展示していました。就業規則などの社内資料を元に、ユーザの質問に対して、ChatGPTの自然な応答を元に回答をしてくれるようです。 Allganize Japan株式会社は、2023年2月に開催されたDX EXPOでも自社ソリューションの展示を行っていましたが、DX EXPOの中で唯一、ChatGPTを活用したソリューションの展示を実施していました。この時の展示スペースはとても小さかったのですが、今回は非常に大きなスペースでAlliの紹介をしていました。 スタッフの方にお話を伺ったところ、前回の展示会以降、ChatGPTに関する問い合わせが大きく増え、今回ブースをさらに拡大することになったようです。ChatGPTのサービスリリースは昨年末でしたので、わずか1~2ヶ月で展示会にソリューションを出展したことになります。この迅速な対応は非常に印象的であり、今回のAI Worldでも、多くのユーザから注目を集めていました。 Allganize Japan株式会社 Alliの詳細はこちら まとめ 近年、ChatGPTの活用範囲は日本国内でも拡大しており、多くの企業が各社独自のビジネスモデルにChatGPTを取り入れて、自社サービスの成長を促進しようとしています。 今回の展示会では、セキュアな環境でChatGPTを使用できるソリューションが数多く展示されていました。実際、このようなソリューションへのニーズは増加しているように感じます。 一方で、2023年8月にはOpenAIから法人向けのChatGPT Enterpriseが発表され、更なる付加価値を持つChatGPTソリューションの提供が開始されました。このような状況下、ChatGPTの単なる機能提供を行うソリューションでは、今後の差別化は難しいと感じられます。 パーソルプロセス&テクノロジー株式会社のTimo Meegingのように、自社独自ツールの価値を向上させるためにChatGPTを活用する、または株式会社AVILENのように、ChatGPTのユースケース整理やコンサルティングサービスを提供する、といった取り組みが重要であると感じました。これは、今回の展示会を通じて得た私の個人的な感想です。 今後もChatGPTの進化と、それを取り入れる企業の斬新なアイディアに注目していきたいと思います。
はじめに  データサイエンティストの五十嵐です。今回は「帰納バイアスと理論研究」というタイトルでお送りします。  機械学習のモデルは、与えられたデータからパターンを学習し、未知のデータに対する予測を行います。この機械学習モデルにおいて、帰納バイアスが存在する場合があり、多くのモデルではそれらの帰納バイアスを上手く利用することにより様々な成果を上げてきています。しかし、近年のLLM (Large Language Model)では、帰納バイアスの弱い手法により大きな成果を上げており、大量のデータセットを利用可能な場合、帰納バイアスが弱くても高い性能を発揮することができることが明らかになってきました。しかし、これらは実験的に得られた知見、すなわち経験則である場合が多く、その理論研究は十分には進展していないのが現状です。そこで、本記事では帰納バイアスについて簡単に紹介した後、今年の6月にarxivに掲載された帰納バイアスの理論研究について踏み込んだ論文、 “Scaling MLPs: A Tale of Inductive Bias“ について紹介しようと思います。  本記事により、帰納バイアスに関する今後の理論研究についての動向を探る一助になれれば嬉しいです。 帰納バイアス(Inductive Bias)とは  帰納バイアスとは、学習モデルや学習アルゴリズムが学習する際の前提や仮定、構造上生じるバイアスのことを指します。これは、モデルがデータから一般的なルールを導き出す際のバイアスや傾向を形成します。  例えば、決定木はデータ階層的に分割するというバイアスをもち、ロジスティック回帰では特徴空間において線形の決定境界を保つため、データが線形に分離可能であるという前提をおいています。また、入力特徴が互いに独立であるという仮定も持っています。CNN(Convolutional Neural Network)は局所結合により構成されており、局所特徴を層ごとに集約するという帰納バイアスがあります。  このように、様々な手法・モデルは多くの帰納バイアスを持ちます。(尚、上記で紹介した学習モデルについて、紹介した以外にも帰納バイアスは存在します。) 帰納バイアスの影響  帰納バイアスは、モデルの一般化能力に大きな影響を与えます。  帰納バイアスにより、得られるメリットには下記のようなものがあります。 計算効率の向上.  帰納バイアスにより、学習すべき仮説空間が制限されるために計算効率が向上します。無限の仮説空間から最適なモデルを見つけ出すのは難しいですが、制約されることにより難易度が低下します。 一般化能力の向上.  適切な帰納バイアスを持つことで、未知のデータに対するモデルの予測性能、すなわち、一般化能力が向上する可能性があります。帰納バイアスが実際のデータ生成プロセスに近い場合、新しいデータに対する予測精度が向上します。 知識の事前組み込み.  特定の分野やタスクに関する専門的な知識を帰納バイアスとしてモデルに組み込むことで、学習の効率や精度を向上させることができます。 解釈可能性の向上.  一部の帰納バイアスが、モデルの解釈性を向上させる効果があります。例えば、線形モデルや決定木などのシンプルなモデルは、その構造上の帰納バイアスによって、結果の解釈が容易になります。 学習に必要なデータ数の削減.  これについて詳細は後述しますが、適切な帰納バイアスを用いることで学習に必要なデータ数が帰納バイアスが弱い場合よりも少なくて済むことが知られています  このように、学習モデルや学習アルゴリズムは帰納バイアスを上手く利用しているのです。 帰納バイアスについて  近年、LLM (Large Langage Model)が話題ですが、これらのLLMはTransformerが用いられています。このTransformerは先述したような仮定を置いていないので、帰納バイアスが弱いです。帰納バイアスが弱いということは、帰納バイアスの恩恵を受けられないということなので、データが大量に存在しない場合は帰納バイアスが強いモデルに比べて高い精度が出しにくい可能性が考えられます。実際、ViT (Vision Transformer)で有名な論文 "An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale (2021)" では、データ量が大規模でない場合は帰納バイアスの強い従来のCNNベースのモデルの方が強く、データ量が大規模な場合は帰納バイアスが弱いViTの方が強い、ということが示されています。  また、Transformerの性能はモデルサイズ(パラメータ数)、データサイズ、計算能力の3変数に依存する冪乗則に従うこと( "Scaling Laws for Neural Language Models (2020)" )も知られており、データ量が大きくなる程、性能が向上することが示唆されています。  これらのことから、学習データが大規模な場合、帰納バイアスが弱い学習モデルを用いた方が良いことが示唆されます。しかし、このことを理論的に解明しようとしている研究はまだあまり多くありません。 本記事で紹介する論文  前置きが長くなりました。本記事で紹介する論文は “Scaling MLPs: A Tale of Inductive Bias“ です。 この論文の概要を下記に記します。 概要  2023年6月23日にarXivに掲載されました。著者はスイス連邦工科大学所属です。  この論文は、これまで経験的に示されてきた、帰納バイアスが小さい場合データセットや計算の能力、モデルサイズが大きい方が性能がよくなるという事象を理論的に解明する足掛かりを作るため、深層学習の最も基本的な構成要素であるMLP (Multi Layer Perceptron)を用いて実験を行っています。  MLPを用いることで数学的に単純にできるため、MLPは深層学習の理論分野では主に使われています。これは、より複雑な構造で観察される現象をシンプルな構造で説明するという発想で、理論分野ではよく用いられています。MLPは帰納バイアスが非常に弱いという点からも理想的です。 実験設定  本論文では、帰納バイアスを理解することが容易であることからvisionタスクで実施しています。 利用したデータセットは下記です。 CIFAR10 CIFAR100 STL10 TinyImageNet ImageNet1k ImageNet21k など事前学習でおなじみのデータセットです。  また、activation function、skip connection、regularization、data augmentation、inverted bottleneckなど、通常用いられる工夫は都度利用しています。 実験結果  上表からデータ数やモデルサイズが大きい方が精度が高くなっていることがわかります。モデルについては、B-L / Wi-mという形式で表現されています。。Bはボトルネック(今回はinverted bottleneck)、Lはネットワークの深さ(ブロック数)、Wi-mはネットワークの幅(各ブロックのノード数)です。  上表はモデルとパラメータ数です。これらのモデルを用いて、CIFAR10とImageNet1kに関して、計算能力毎の性能を評価したグラフが下図です。  上図は、先述したモデルごとのLinear Evaluation Errorを示したグラフです。左図はCIFAR10、右図はImageNet1kについてのTest errorを表しており、横軸は計算能力です。この結果から、MLPに関しても性能はそのスケールや計算能力により劇的に改善することが分かります。 結論  MLPの性能はそのスケールとともに劇的に改善することがわかりました。これは、帰納バイアスがなくてもスケールによりカバーできることを示しています。つまり、大量のデータと十分な計算能力があれば帰納バイアスが重要ではないことを示唆されています。  また、MLPは実際に使われているようなモデルによって示されている経験的な進歩を反映しているとも考えられます。つまり、MLPが深層学習における理論の理解においては重要であることを示しています。 まとめ  本記事では帰納バイアスについての説明と理論研究論文の紹介を行いましたので、全体をまとめます。 データが大規模な場合、帰納バイアスが弱い学習モデルの方が良いことが実験的に示されてきてはいたが、理論研究はあまり進んでいない “Scaling MLPs: A Tale of Inductive Bias“ では、深層学習の基本的な構成要素であるMLPを用いて、visonタスクで同様の傾向が示されるのか研究を行った MLPの性能はそのスケールとともに劇的に改善することが示され、大量のデータと十分な計算能力があれば帰納バイアスは重要でないことを示唆された MLPは実際に使われているようなモデルによって示されている経験的な進歩を反映しているとも考えられる。つまり、MLPが深層学習における理論の理解には重要であることが示唆されている 最後に  最後まで読んでくださりありがとうございました。  色々前置きを書きましたが、人工知能研究の最終達成目標の一つであろう汎用人工知能(AGI)の達成には、間違いなく帰納バイアスが非常に弱いモデルや手法が必要不可欠かと思います。そのためには、理論研究が必須なので、この分野の研究動向は今後も探っていこうと思います。Transformerがより発展していくのか、全く別の手法が開発されるの個人的には非常に楽しみな分野です。
こんにちは。ビジネスイノベーションスペシャリストの森です。 最近コードを書くときは、Github CopilotとGPT-4を使っていますが、実装スピードが10倍(体感)になりました。 微妙な部分を書き換えながら使うので、初心者がコーディングできるようになるのは難しいと思いますが、 コーディングの単純作業部分を全部任せられるのは非常に便利です。 こんなこともあり、Tech業界は最近生成AI一色です。Insight Edgeでも、数多くのChatGPT(LLM)活用プロジェクトに取り組んでいます。 この記事では、本格的なLLMのビジネス現場活用に向け、日々取り組んでいるテーマと、その技術的な課題を紹介します。 また、本記事のタイトル含め、LLMと記載すべきところをChatGPTという単語を使っている箇所があります。 OpenAI社のChatGPTというサービス名称ではなく、概念(一般名詞)としてChatGPTという言葉の使い方をしていることを予め補足します。 目次 はじめに LLMを業務に活用する場合の課題 外部データの取り込み 出力形式の指定 (Function Calling) パイプラインの管理 終わりに はじめに 2023年3月のGPT-4リリース以降、ChatGPTをはじめとした大規模言語モデル(以降LLM)が注目されています。 Insight Edgeとしても、住友商事グループの生成AI活用に向けたグループ横断のワーキンググループである SC-AI HUB に参画し、生成AIのビジネス活用に取り組んでいます。 企業や組織におけるLLMの活用では、いわゆる「セキュアなChatGPT」の取り組みが有名です。多くの企業や自治体が、Microsoft社のAzure OpenAI Serviceで提供されているエンタープライズ用途のChatGPTを用いたセキュアなChatGPTの導入を進めています。 一方、セキュアなChatGPT以外の大規模な本格導入例は、ほとんど出てきていません。 一時期話題となったAutoGPTなどエージェント機能を組み合わせるアイデアや、ChatGPT Pluginで色々なサービスを利用する機能もリリースされていますが、 現状、アーリーアダプターがX(旧:Twitter)で使い方を紹介するくらいで、大規模に実用されるまでは至っていません。 企業活動において最も期待されているユースケースとして、企業内のデータを組み合わせてLLMを使う用途があります。 RAG(Retrieval Augmented Generation) や REALM(Retrieval Augmented Language Model) などの論文で提案された手法を使って実現することが有名ですが、本記事では説明を割愛します。 Microsoft Azureでも、このユースケースを実現するために Add Your Data や、 Cognitive Search のベクトルサーチ対応など、新しい機能を積極的にリリースしています。 しかしながら、企業内の情報検索のユースケースとして、ビジネス現場で活用されている例は、ほとんど出てきていません。 Insight EdgeもこのユースケースのPoCに数多く取り組んでいますが、ビジネス現場での実運用に向けては様々な課題に直面しています。 例えば、元データのPDFがスキャン画像だったり、テキスト化が難しいフローチャートや表に重要な情報が含まれていたりと、アルゴリズム以前に元データの整備が必要なケースがあります。 また、Stuffと呼ばれる最もシンプルな情報検索のパイプラインでは対応できない質問が業務上想定されるユースケースだったりもします。 後述しますが、与えた文書に対する要約と質問の両方を自然に回答することですら、割と難しかったりします。 現在リリースされているほとんどのサービスは、最もシンプルな情報検索のユースケースしか実装されていない状況です。 少し凝ったことをやろうとすると、Langchainやsemantic kernelを使って、スクラッチで実装する必要があります。 LLMを業務に活用する場合の課題 外部データの取り込み ChatGPT PluginsのPopular Pluginsを見てみると、上位3件はPDFの取り込みプラグインです。 エンタープライズ用途同様に、ChatGPTに独自の情報を加えるユースケースは、一般的にも最も注目されているようです。 実際にPDFを取り込むプラグインを使って、課題を説明します。 Insight EdgeでPoCを実施する中で困っていることの1つが、ユーザーは文書に対する質問(情報検索)と要約を意図せずに利用することです。 OpenAIなど、LLMをクラウド型で提供するサービスでは、一度のリクエストで取り込めるトークン数(文字数)の制限があります。そのため、情報検索と要約は同じ処理では実現できません。 情報検索は、文書中の該当部分だけを抽出してChatGPTにプロンプトとして入力します。 要約は、全文を参照する必要がありますが、全文を一定文字数ごとに区切って、順番に入力して処理をしていきます。要約を実現する処理パイプラインとしては、Map Reduce型と、Refine型に大別されます(後述)。 つまり、ユーザーからのリクエストが情報検索か要約かによって、システム側で処理を切り替える必要がでてきます。 ChatGPTの人気プラグインが、この問題にどうやって対処しているのか確認してみましょう。 一番人気のプラグインである「AI PDF」を使って、全体で20ページほどの論文の要約を指示してみます。 ChatGPT Pluginでは、以下のように、APIにどのようなリクエストが飛んだかを確認できます。 実際のリクエストを確認してみると、要約の指示をしたのにも関わらず、APIリクエストには文書の冒頭2ページ分しか入力されていませんでした。 幸い論文だと、冒頭にAbstractがあるため何となく良さそうな結果が返ってきますが、他のデータだとうまくいかなそうです。 実行結果の抜粋が以下になります。 やはり、明らかに冒頭2ページしか参照していません。つまり、このプラグインでは要約の処理は実装されておらず、要約の指示であっても質問回答用の処理しか実行されないことがわかりました。 人気のプラグインであっても、この程度のようです。まだまだこのユースケースの実用にはハードルがあることがわかります。 特に、冒頭2ページしか読み込んでいないのに、全文を処理しましたと出力する仕様となっているのは、ちょっといただけません。 補足ですが、Azureでは、Azure OpenAI Studio Add Your Dataというサービスでこのユースケースをサポートしています。 しかし、現状Azure OpenAI StudioのUI経由でしか利用できないため、システムに組み込みたい場合や、企業内ユーザーへの公開用途には使えません。 また、 Bing Chat Enterprise では、 ユーザーがPDFデータをアップロードする機能が搭載されています。 上述したOpenAIのPlugin同様、まだ実用に課題はあるものの、ビジネス用途で利用できるサービスの一つです。 このBing Chat Enterpriseは、セキュアなChatGPT用途にも使用することができます。 冒頭記載した通り、多くの企業でセキュアなChatGPTの導入が進んでいます。 元々、ベンダーへの委託を含め自社で開発する選択肢しかありませんでしたが、今ではBing Chat Enterpriseのような外部サービスをそのまま利用する選択肢もあります。 住友商事では、セキュアなChatGPTをはじめ、シンプルなユースケースには外部のサービスを利用し、 業務に特化した複雑なユースケースをInsight Edgeを中心に開発する取組み方をしています。 出力形式の指定 (Function Calling) ChatGPTを含むLLMからの回答を使って、別の処理を実施したい場合、プロンプトで回答形式を指定することが一般的です。 しかし、jsonなど決まったフォーマットで出力させようとしても、思ったように出力できないことが多いです。 体感ですが、GPT3.5を使った場合、上手く出力できる確率は良くて5割程度、GPT4だと8~9割です。 パラメータ数の少ないLLMでは、Finetuneしない場合、決まったフォーマットでの出力は絶望的です。 また、決まったフォーマットでの回答ニーズは、通常のチャット用途においても高まっています。 Chain-of-Thought Prompting や、 メタ認知プロンプティング のように、LLMに段階的に推論をさせることで回答の精度を上げる手法が考案されています。 これらの手法は、以下の画像のように、LLMに対して思考の過程をプロンプトで定義します。 このように、段階的な思考の指示することで、回答の精度を向上・担保します。 この手法を使う場合、段階的な推論の全てのログをユーザーに表示してしまうと、回答量が多くなりUXを損ねる場合があります。 多くの場合において、ユーザーに提示するのは段階的な推論の最終段階の結果のみで十分です。 つまり、システムへの組み込み用途だけでなく、LLMからの回答精度を上げる場合にも、出力形式の指定が必要となります。 ChatGPTでは、出力を決まった形式に指定するための機能として、Function Callingというサービスを提供しています。 これだけでも他のLLMではなくChatGPTを使う理由となるくらい、今後重要となる可能性があるサービスだと思います。 パイプラインの管理 セキュアなChatGPT用途では、単にAPIにユーザーからの質問を投げて、APIからの回答をそのままユーザーに提示するだけの処理で実現できます。 しかしながら、社内情報を使った回答の用途を含め、業務的に実用レベルのユースケースを実現しようとすると、 単にAPIに質問を投げて回答を取得するだけの処理では実現できません。 以下に一般的なパイプラインを紹介します。 外部情報を組み合わせたユースケースで最もシンプルなパイプラインは、 Stuff Documents パイプラインです。 仕組みは簡単で、プロンプトと参考情報をセットにしてAPIにリクエストを投げるパイプラインです。 上述の通り、外部情報を取り込める既存サービスのほとんどは、このStuffが実装されています。 一方、これまでのプロジェクトの経験上、Stuffを実装しただけではユーザーに提供できるクォリティの回答が得られません。 セキュアなChatGPT以降の事例が出てこない理由の1つはここにあると思っていて、 いろいろな企業がこのStuffを試し始めているものの、なかなか上手くいってないのではないかと思います。 文書の要約では、別のパイプラインが必要です。 Stuffは、文書の必要な部分を渡す処理ですが、要約では、全文を取り込む必要があります。 しかし、文字数の多い文書の場合は、一度のAPIリクエストで全文を取り込むことができないため、パイプラインで工夫する必要があります。 Map Reduceは、一定量ごとに区切った文書(chunk)をそれぞれ1回要約して、最後に全ての要約結果を集約して2回目の要約を実施する処理です。 1回目の要約部分は並列処理できるので、速度重視の場合はこのパイプラインを選びます。 Azure OpenAI Serviceなど、クラウド提供型のLLMの場合、Rate Limitが厳しいため、 Rate Limitの問題をケアして実行する必要があります。 要約では、Refineというパイプラインも選択肢として考えられます。 Refineは、一定量ごとに区切った文書(chunk)を順番に読み込んでいき、都度要約を繰り返す方式です。 処理が直列なので、Map Reduceと比較すると時間がかかります。 上述しましたが、このように、情報検索と要約は同じパイプラインで実現できません。 利用者の立場からすると、意図せずに情報検索と要約の両方を質問することに加え、要約の後に質問を続けたいという利用ニーズもあります。 この他にも、回答精度を上げようとしたり、利用者の業務ニーズに応じて複雑なパイプラインが必要となります(prompt chaining)。 プロジェクトでは、パイプラインが複雑になるにつれて、開発したエンジニアしか処理内容を把握していない状況になりがちです。 継続的な運用を考えると、パイプラインの設計や管理を実施する必要が出てきます。 Microsoft Azureでは、prompt flowというパイプライン管理ツールを提供しています。 一見ローコードツールのような外見ですが、肝心の処理自体はpythonで記述する必要があり、 Airflowやkedroのように、パイプライン管理の用途を想定して作られていると思います。 まだプレビュー版で、prompt flowも実用的なレベルではありませんが、LLMops領域のサービスは重要となってきそうです。 終わりに 本記事では、本格的なLLMのビジネス現場活用に向け、日々取り組んでいるテーマと、その技術的な課題を紹介しました。 現状では、スクラッチでトライアンドエラーしながら開発できるエンジニアがいないと、LLMを活用してやりたいことを実現するのは難しいです。 LLMを本格的にユーザー企業が活用して成果を出すには、まだまだ技術的なハードルが高いように感じています。 例えばディープラーニングも、色々なツールが徐々に整備され、今では誰でもちょっとした学習ならできるようになりましたが、 LLMの活用もディープラーニングの黎明期と同じような雰囲気を感じます。 現在、アカデミア含め、ものすごいスピードで目下の技術課題が解決されています。 最新技術のキャッチアップを欠かさずに、着実にできることを増やしていきたいと思っています。
MathJax = {tex: {inlineMath: [['$', '$']]}}; Insight Edgeのデータサイエンティストのki_ieです。 今日の記事ではJupyter notebookをはてなブログで公開できるマークダウンに変換する方法を紹介します。 はじめに 数式とコード、さらにコードの実行結果を含む技術的な記事を書くには、Jupyter notebookが便利です。 しかしJupyter notebookは、そのままでははてなブログに公開できる形ではありません。 下書きだけJupyter notebookで行って最後は手作業でmarkdownに移行して仕上げる という方法もありますが、ソースが2つできてしまい記事の修正時が大変です。 notebookファイルだけをソースとして、ブログ記事は変換スクリプト一発生成できる方が望ましいですよね! 本記事では、この変換を実現するスクリプトを紹介します。 変換スクリプト 想定環境 実験は以下の環境で行いました。 Pythonのバージョンあまり依存しないと想定しています。 jupyterのバージョンによっては、正しく動作しない可能性があります。 Python: 3.11 jupyter: nbformat: 5.8.0 notebook: 6.5.4 スクリプト スクリプトは以下の通りです。 # FILENAME: nb_hatena_converter.py """ Usage: python nb_hatena_converter.py YOUR_NOTEBOOK.ipynb OUTPUT.md """ import nbformat, nbconvert import sys import re bs = " \\ " nl = " \n " NO_CONV_TAG = "<!-- NO_NB_HATENA_CONVERSION -->" special_chars = r"\*_`#+-.!{}[]()^" # backslash は文字列末尾には置かない ("がエスケープされるため) math_range_re = re.compile( r"(\${1,2}[^\$]+\${1,2})" ) special_chars_re = re.compile( "" .join([ '[' ] + [bs + ch for ch in special_chars] + [ ']' ]) ) mathjax_html_tag = r''' <script> MathJax = {tex: {inlineMath: [['$', '$']]}}; </script> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script> ''' # 参考URL: https://o-treetree.hatenablog.com/entry/mathjaxexample def convert_str (s: str , cell, cell_no) -> str : # 数式部分またはそれ以外の部分の文字列 s を入力とし、必要な変換を施します。 full_match = math_range_re.fullmatch(s) res = s # 特に変換がなかった場合、もとの入力を返します。 # セルが NO_CONV_TAG で始まる場合、そのセルは変換しません。 if cell.source.find(NO_CONV_TAG) == 0 : pass # s が数式部分でない場合、変換しません。 elif not full_match: pass # s が数式部分の場合、特殊文字をエスケープします。 elif full_match: res = special_chars_re.sub(repl= lambda match_obj: bs + match_obj.group( 0 ), string=s) if res != s: print (f '{s} --> {res} @ {cell_no=} beginning with {cell.source[:15].replace(nl, bs + "n")}' ) else : raise NotImplementedError () assert isinstance (res, str ) return res def main (path_to_input, path_to_output): # 1. ノートブックを読み込みます。 notebook = nbformat.reads( open (path_to_input).read(), as_version= 4 ) md_exporter = nbconvert.MarkdownExporter() # 2. ノートブックのセルを, convert_str を使って書き換えます。 # (メモリ上での操作なので、ファイルに変更は加わりません) print ( 'Substitutions: ' ) for cell_no, cell in enumerate (notebook.cells): # markdown セルのみ変換処理の対象です。 if cell.cell_type == 'markdown' : # 2.1. cell の内容を、数式部分とそうでない部分に分割します。 # 例: source = "abc $d$ ef $$g$$" # --> # substrs = ["abc ", "$d$", " ef ", "$$g$$"] substrs = math_range_re.split(cell.source) # 2.2. 各部分に対して、 convert_str で必要なエスケープ変換を施します。 new_source = '' .join([convert_str(s, cell, cell_no) for s in substrs]) cell.source = new_source else : pass # 3. nbconvert.MarkdownExporter を使って、markdown に変換します。 # この変換処理は MarkdownExporter のデフォルトの処理を利用します。 converted_md, md_info = md_exporter.from_notebook_node(notebook) # 4. MathJax を利用できるように、ファイルの最初に HTML タグを追加します result_md = ' \n ' .join([mathjax_html_tag, converted_md]) # 5. 出力します with open (path_to_output, 'w' ) as f: f.write(result_md) if __name__ == '__main__' : main(sys.argv[ 1 ], sys.argv[ 2 ]) 使い方 1. jupyter notebookの準備 notebookに特別な工夫は不要です。数式を含むnotebookを用意しましょう。数式は、インラインでも、別行立て数式でも大丈夫です。 ここでは、以下の数式がどのように変換されるか確認しましょう $n = p \cdot q$ $$f(x)=\frac{{\sum_{i \in I} |x_i|}^2}{\sum_{i \in I} x_i^2}$$ 2. 変換 以下の方法でプログラムを起動し、変換結果のmarkdownファイルを得ます。 python nb_hatena_converter.py YOUR_NOTEBOOK.ipynb OUTPUT.md 3. 変換結果の確認 先程の数式は以下のように変換されます: $n = p \cdot q$ $$f(x)=\frac{{\sum_{i \in I} |x_i|}^2}{\sum_{i \in I} x_i^2}$$ (この記事自体も nb_hatena_converter.py で生成されたものです。上記の数式がはてなブログで正しく表示されているなら、それはこのスクリプトが正しく動作した結果です!) 4. 仕様 仕様概要は次の通りです。詳細は、プログラムとコメントを確認してください。 変換対象 markdownセルだけが変換対象です。codeやrawセルは変換されません。 markdownセルで数式部分と判定された部分に対して、変換処理が施されます。 セル単位のスキップ <!-- NO_NB_HATENA_CONVERSION --> で始まるmarkdownセルは変換を受けません。 このタグが含まれていても、セルの最初でなければ変換の対象となります。 数式部分の判別 $ または $$ で囲まれた部分を数式部分だと認識しています(詳細: math_range_re )。大雑把な判別なので、必要に応じて適宜改造してください。 変換処理の概要 はてな上での表示とjupyter notebook上での表示のずれは特殊記号の処理の優先順位が異なるため発生します。 このスクリプトは数式部分内に存在するmarkdown上の特殊記号をエスケープすることで、特殊記号が数式部分の開始/終了記号( $ , $$ )よりも優先されて処理されることを防いでいます。 おわりに このスクリプトで数式のあるブログ執筆のハードルが少しでも下がったら幸いです👍
こんにちは!小林と申します。この間、九州縦断旅をしたのですがどこに行っても温泉があって毎日のように温泉に入れて幸せでした。 つい先日、社内のAWS・GCPのインフラコストの削減施策を担当いたしました。この経験を通じて、コストがどこで発生し、どのようにそれを削減できるかについて深く理解する機会を得ました。 そこで、これらの知見を共有し皆さんが同様の課題を抱えてしまった際の参考になることを目指して、今回ブログで紹介させていただきます。 目次 インフラコスト削減施策の目的 調査 AWS のコスト GCP のコスト 実施項目 インスタンス自動起動停止ツール インスタンスごとの利用料金を監視・通知 AWS の場合 GCP の場合 EBS 棚卸し まとめ 結果 振り返り reference インフラコスト削減施策の目的 当社では、開発チームがAWSやGCPについて自由に検証できるよう、検証用アカウントを提供しています。しかし、このような自由度の高い環境では、不要なリソースが放置され、それが過剰なコストとなってしまうという問題がありました。 特に、高価なインスタンスが利用されていないのにも関わらず、起動し続けられていることがしばしばありました。 これらの問題に対応するため、以下の2つの施策を当初の目標として設定し、コスト削減に取り組みました 利用金額が一定の閾値を超えた場合に、その情報を通知する仕組みを導入し、過剰なリソースの使用を抑制する。 週末や使用が予想されない時間帯に、リソースを自動的に停止する機能を追加し、無駄なコストを削減する。 以上の施策により、リソースの最適化とコスト削減を達成することを目指しました。 調査 実際の取り組みへの着手前に、現状のコストが何に発生しているのかを詳細に調査し、インスタンス以外にもコスト削減の余地がないか探ります。AWSとGCPの両方で調査を実施しました。 AWS のコスト CostExplorerを利用して施策前のコスト分布を確認しました。たとえば、2023年3月時点の当社のコスト内訳を見ると、EC2インスタンス関連のコスト(EC2インスタンス、EC2その他)が月額コストの50%を占めていることが分かります。したがって、まずはEC2インスタンスに対して今回の施策を適用するのが有効であると推察できます。さらに、「EC2その他」という項目も非常に高額であることが明らかになりました。この項目には、EIP(AWS Eastic IPアドレス)やEBS(Amazon EBS)が含まれます。 EIPやEBSはインスタンスが停止している場合でも課金が発生し続ける特性を持っています。それゆえ、使用されていないEIPやEBSが存在する可能性も考慮に入れるべきです。この結果を踏まえ、AWSについては、インスタンスだけでなくEIP・EBSについても棚卸し等の施策が必要となりそうです。 図1 GCP のコスト 続いて、GCPのコスト状況についても確認します。 GCPについても全体のコストのうち半分ほどがCompute Engine(図2のグラフ青色部分)によって占められています。 AWSと同様にインスタンスに対する削減施策を実施する必要がありそうです。 図2 実施項目 調査結果から、当初の目的であったインスタンスのコスト削減施策が有効であると考えられました。さらに、AWSではEBSの棚卸しも行うことを決定しました。したがって、今回の取り組みは以下の3点となります。 インスタンス自動起動停止の仕組み作り 土日にインスタンスを自動で起動・停止できるようにし、インスタンスの管理を容易にする。 インスタンスごとの利用料金を監視・通知 インスタンスごとの利用料金を算出する仕組みを整え、規定値を超えた場合に通知するシステムを導入する。 EBS(ボリューム)の棚卸しを実施 あまり使用されていないインスタンスにアタッチされているEBSボリュームを確認し、必要ないものは削除する。 次に、それぞれの取り組みについて詳細を説明します。 インスタンス自動起動停止ツール まず、インスタンスを自動的に起動・停止する手段について考えてみましょう。 AWSのインスタンス自動起動停止には一般的に、Amazon EventBridge + Lambda、EventBridge Scheduler、またはInstance Schedulerのようなアーキテクチャが用いられます。 GCPではデフォルトでインスタンススケジューラを設定できます。 しかし、これらのアーキテクチャでは、新たにインスタンスを作成するごとにスケジュールを設定する必要があり、これが開発者の負担となってしまいます。理想的には、ユーザがインスタンスを作成した際に、自動的に設定された自動起動・停止される仕組みが欲しいです。 そこで今回は、スプレッドシートとGASを用いてインスタンスの自動起動・自動停止するツールを開発し、それを利用することにしました。スプレッドシートを利用する利点としては、ユーザが使い慣れていることと、一覧性があり、管理しやすいという点が挙げられます。 また、今回作成するツールには自動起動・停止するだけでなく、より管理しやすくするため、以下のような機能を追加しました。 インスタンスの利用者名を記載する 誰が責任を持ってインスタンスを利用しているのかを明確にする インスタンスの起動時刻を記載する 起動状態で長期間放置されていないかをチェックする インスタンスタイプを表示する 長期間稼働しているインスタンスが高額なものでないかを確認する ツールの使い方・仕様は、以下の通りです。 定期的に一覧を自動更新する 常に最新のインスタンス状況が確認できるようにする ユーザが手動でインスタンスリストを更新できるようにする 追加したばかりのインスタンスについて、手動で更新し、すぐに設定できるようにする 自動起動・自動停止欄にチェックをつけることでそれぞれ定時に自動で実施される インスタンス作成時のデフォルトでは自動停止のみチェックされる インスタンスの停止忘れによる無駄な課金を防ぐ 以下は作成したツールのイメージです。 図3 最後に、ツールの作成手順を簡単に説明します。 インスタンスを管理するためのIAM/サービスアカウントを作成する ただし、アカウントは誰でも利用できる状態になるので、必要最低限の権限のみを付与します。 スプレッドシートとGASを作成する スプレッドシートは図を参照ください。今回、 GASの作成には、以前当社のブログでも紹介されたClaspを利用しました。(参考: リンク ) トリガーを設定する 今回GASを起動するトリガーとしては、自動起動(定時にインスタンスを起動する)・自動停止(定時にインスタンスを停止する)・更新(インスタンス一覧を更新する)を用意しました。 インスタンスごとの利用料金を監視・通知 インスタンスごとの利用料金を監視・通知するためにどのような技術を利用したかをAWS・GCPそれぞれ紹介します。 AWS の場合 AWSにおいて、インスタンスごとの利用料金を把握するためには、コスト配分タグの利用が効果的です。設定したタグを利用して、以下のような内訳を確認可能です。ただし、コスト配分タグを利用する際は以下の点に注意してください。 利用できるのはOrganizationsの管理アカウントのみ タグの有効化には1日程度かかる場合がある 月の途中でタグを付与した場合、その月の残り期間はタグ未付与とみなされる。 次に、コストの通知について説明します。今回は、AWS LambdaとSlackを組み合わせて通知機能を実現しました。具体的な開発方法については、以下の参考記事などをご覧ください。 https://dev.classmethod.jp/articles/notify-slack-aws-billing/ なお、今回設定した通知の閾値は当社での利用額に対して、少し大きめの額で設定しました。あくまで異常な課金の発生を発見するために設定した値となります。 GCP の場合 GCPはAWSと異なり、コスト分配タグのような機能がないため、Compute Engineに設定できるラベルを用いることにしました。ラベル付は、インスタンス自動起動停止ツールのGAS内で自動に行いました。 ラベル付された結果は、課金のレポートから確認ができます。 ラベル付には こちら のAPIを利用しました。 EBS 棚卸し EBS(Elastic Block Store)ボリュームとは、EC2インスタンスに接続され、データを永続的に保存するためのブロックレベルのストレージデバイスです。EC2インスタンスから物理的に分離されているため、インスタンスを停止または終了してもデータは保持されます。EBSボリュームは確保した容量に対して料金が発生します。そのため、長期間使用されていないインスタンスに接続されているEBSボリュームでも、料金は継続的に発生します。 このような背景から、以下の条件を満たすEBSボリュームについては棚卸しを実施しました。 利用されてから1年以上経過していること 容量が100GiB以上であること 具体的な棚卸しの手順は次の通りです。 対象となるEBSボリュームがアタッチされているインスタンスの利用者に連絡をする EBSボリュームのスナップショットをとる EBSボリュームをデタッチする もしくは インスタンスを削除する EBSボリュームを削除する なお、スナップショットを作成しないとデータは完全に復元できなくなります。したがって、データの保持が必要な場合はスナップショットの作成を忘れないようにしてください。 まとめ 結果 EC2インスタンスの利用料金については、月ごとの使用状況により大きく変動するため、7月度は高額になってしまいましたが、5月と6月では施策導入前よりも大幅に低く抑えることができました。 また、特にEC2その他のコストについて、EBSの棚卸しとともにEIP(Elastic IP)についても棚卸しを実施した結果、当初の半額程度まで削減できました。 GCPについては、Compute Engineの使用料が一定水準を保っており、大幅なコスト増は抑えられていると言えます。 特に注目すべきは、EC2のその他のコストです。これは長期間放置されているとかなり高額になるため、今まで特に組織的に棚卸しをしていなかった分削減効果が大きくなりました。 振り返り この施策を通じて、ツール自体の効果以上に、それぞれのリソースがどれほどのコストを生じているかを理解し、自分自身でコストに対する意識を持つことができました。 さらに、今回の試作を通して運用面での課題も明らかになりました。 定期的な棚卸しの必要性 年単位で放置されているようなリソースが存在し、その所在が分からないものもあります。そのため、棚卸しの手順を繰り返し行えるように準備する必要があります。 アカウントの管理方法の課題 検証用アカウントを共用する方式では、誰がどのリソースを使用すればよいのか判断が難しいです。これに対する対策として、タグ付けのルール化などが考えられますが、検証用アカウントに多くのルールを設けるとメンバーへの負担が大きくなります。ユーザー個人ごとに検証用アカウントを発行する手段もありますが、管理が複雑化するなどの課題もあります。 また、自身でコスト削減を試みるだけでなく、Trusted Advisorのようなツールを利用する手段も検討できます。 この施策を通じて得られた新たな学びは多いです。今後は、より効率的なコスト管理を実現するために、システムを整備していきたいと思います。 reference 社内開発用 EC2 インスタンス料金を節約したい cron で時間指定して ec2 インスタンスを自動起動・停止する AWS のコストをサクッと削減 ~ EBS 編 ~ AWS コスト配分タグを使ってみよう AWS コスト配分タグの運用に入門してみた AWS のコスト配分タグを正しく理解する Lambda x Amazon SNS で、AWS の請求額を毎日メールで通知する AWS Trusted Advisor で無駄なコストを見つける
目次 はじめに ブランチ戦略 Git Flow GitLab Flow GitHub Flow 開発チームのブランチ戦略 GitHub Flowの採用理由 運用の基本ルール 実際にGitHub Flow運用してみて 良かったこと 悪かったこと まとめ はじめに Insight EdgeのLead Engineerの三澤です。 Insight Edgeでは開発プロジェクトに応じてその時々でチームを編成し、プロジェクトの内容に合わせてチーム単位で技術やアーキテクチャや開発ルールの選定・決定をしています。 今回は直近の開発で運用してきた開発ルール(ブランチ戦略)の1つGitHub Flowについて、実際の運用方法や良かった点・悪かった点をご紹介したいと思います。 本記事ではGitとブランチを既知のものとして進めることにご了承ください。 ブランチ戦略 GitHub Flowの話へいきなり入る前に、まずはなぜブランチ戦略を考える必要があるのかを考えてみます。 皆さんもGitを用いて複数人で開発を進めることがあるかと思いますが、その際には各自がブランチを作成し開発を進めるのが一般的です。しかしこの時、もしブランチ戦略を決めずに各開発者が勝手にブランチを作成してしまうとどうなるでしょうか?各ブランチの意味が不明瞭になるだけでなく、ルールを決めずに開発を進めますので各ブランチのコードをマージするのも一苦労になります。さらに、ブランチが乱立することになりますので、どのブランチが正しく動くソースコードなのかが分からなくなるといった問題を引き起こす可能性があります。ブランチ戦略は、そのような問題に対してルールを定めそれに則って開発を進めることによって解決を図るものです。 ここでは3つの代表的なブランチ戦略を簡単にご紹介します。 Git Flow Git Flow は、Vincent Driessenが2010年に提案したブランチモデルです。masterを安定ブランチとして、そこから分岐したdevelopブランチを開発用のブランチとして開発を進めます。開発者はdevelopブランチから機能毎にfeatureブランチを作成して開発を進め、developブランチへマージを繰り返すというのが基本動作です。その後、developブランチで一定の機能開発やバグフィックスが完了するとreleaseブランチを作成します。このreleaseブランチではリリースの準備としてコードの整理やテストなどが行われます。ここで問題がないことを確認できたらいよいよreleaseブランチの内容をmasterブランチへマージされ本番環境へリリースされます。このようにブランチを用途によって適宜使い分けながらタスクやリリースの管理や安定性の確保しますので、各ブランチの役割が明確になるというメリットがあります。一方で、パッと見てわかる通りブランチの種類が多く管理が複雑になるというデメリットがあります。 GitLab Flow GitLab Flow は、GitLabが提唱するブランチ戦略です。Productionブランチモデル、Environmentブランチモデル、Releaseブランチモデルといったいくつかのパターンがあるのですが、ここではEnvironmentブランチモデルを紹介します。GitLab Flowでの機能開発はGit Flowと異なりdevelopではなくmasterブランチから分岐したfeatureブランチで行います。featureブランチでの開発が完了すると、その内容をmasterへマージし検証環境でテストするという作業を繰り返します。その後、ある程度開発が進んだタイミングでリリース準備を行います。リリース準備はmasterブランチから分岐したpre-productionブランチで行い、問題がなければ本番環境へリリースされます。このリリースしたコードはproductionブランチにマージされ、終了するという流れです。Git Flowほどの厳密なリリース管理が不要になるというメリットがありますが、それでもやはりまだ複雑というデメリットがあります。 GitHub Flow GitHub Flow は、GitHubが提唱するGitLab Flowよりもさらにシンプルなブランチ戦略です。開発はmainブランチから派生したfeatureブランチで行います。featureブランチで開発が完了するとmainブランチにマージされ、このマージされた内容が本番環境へリリースされます。このmainブランチには常にデプロイ可能な安定したソースコードが格納されていることを前提としているのが特徴です。ブランチが2本しか存在しないのでとても理解しやすく、mainブランチにマージしたことを基本としてリリースされるので、開発した内容を短いサイクルでリリースにつなげられることがメリットになります。一方でmainブランチの内容が常にリリースとなることから、検証環境へのリリースやリリースバージョン管理が出来ないというデメリットがあります。なお、我々のチームではGitHub Flowをベースに一部改変することでそのデメリットを克服しています。その内容については後ほど紹介します。 開発チームのブランチ戦略 GitHub Flowの採用理由 タイトルにも書いている通り、我々のチームではGitHub Flowを採用しています。一方で、私の開発経験としてはこれまでGit Flowのブランチ戦略を採用することが多かったです。そのためGit Flowで進めるという選択肢もありました。では、なぜ我々のチームがGitHub Flowを採用したかというと、Insight Edgeでは小回りの効く比較的小規模なチームで素早く開発をすることが多かったから、が理由になります。Git Flowのような厳密な管理をするブランチ戦略は、先の説明の通りリリースまでの工程や確認が多くなります。そのため、こまめに機能をリリースしながらシステムをアップデートしていくというアジャイル的な我々の開発スタイルにミートしませんでした。GitHub Flowのようにシンプルでこまめにリリースを重ねていける開発スタイルが小規模チームは適していると考えました。 一方で先にも触れた通り、GitHub Flowはmainブランチの内容が常にリリースとなることから、検証環境へのリリースやリリースバージョン管理が出来ないというデメリットがあります。そのために我々はGitHub Flowに一部改変を加えています。ここでもしかすると、リリース管理を行うGitLab Flowでも良いのではないかという疑問が湧いてくるかもしれません。しかし、こちらについては管理するブランチ数はなるべく減らしたいこと、リリース管理自体はproductionブランチがなくてもタグで代用できることから採用を見送りました。 運用の基本ルール Insight EdgeではGitHubをプラットフォームとして採用していますので、以降は基本的にGitHubでの用語を用いて我々の開発ルールを説明します。 開発環境 リリースする環境としては、以下の3つを準備しています。 dev 開発者がいつでも任意のタイミングでリリースして良い開発環境。 stg mainブランチへのマージ後に必ずリリースされる本番適用前の検証環境。 prod stgでの検証後にリリースされる本番用環境。 ブランチ 作成するブランチは下記の2本になります。 mainブランチ 安定ブランチです。常にリリース可能なソースコードを管理します。 feature/xxxxブランチ mainブランチから切ります。開発する機能に応じて作成します。xxxxには開発する機能の内容が書かれます。 Pull Request featureブランチで開発が完了するとmainブランチにマージするためPull Requestを開発者が発行します。レビューはリポジトリ管理者と、開発メンバの2人で実施します。2人のレビューによるレビューで問題がなければマージされますが、このマージはfeatureブランチの作成者が行うのではなくリポジトリの管理者が責任を持って行います。 手順 以下が簡単な開発の流れになります。 mainブランチからfeatureブランチを作成 featureブランチで開発完了後、mainブランチへPull Request featureブランチの内容をレビュー。問題なければmainブランチにリポジトリ管理者がマージ mainブランチにマージ後、stg環境へリリース stg環境にてマージされた内容の動作を確認 stg環境で問題なければリポジトリ管理者がリリースバージョンを示すtagを付与 (前回の本番環境へのリリース内容と今回のリリース内容の差分を示すリリースノートを作成) tagの付与されたコミットをprd環境へリリース 通常のGitHub Flowは、手順1-4の流れを繰り返しますが、我々は6以降の手順を追加して運用しています。tagを活用することによって追加のブランチを作成する必要が無くなりますし、prd環境へのリリースバージョンが明確になるという嬉しさがあります。 手順7についてはプロジェクトによっては作成しないこともあるためカッコ付きとしています。我々の開発では、GitHub Actionsで前回のtagと差分を取得しリリースノートを自動作成するようにしています。tagと一緒にリリースノートも作成することで前回との差分が一目瞭然となるため非常に便利です。 また、stg環境へのリリースもGitHub Actionsでmainブランチへのマージをトリガーとしてリリースされるようにしています。prd環境へのリリースについてもGitHub Actionsでリリース出来るようにしていますが、こちらについては最後に人手の承認を挟んでからリリースするようにしています。 上記の手順でそれぞれどの環境にどの内容がリリースされているのかを示したのが下記の図になります。mainにマージされたものは全てstgにリリースされますが、prdへはtagのついたものだけがリリースされます。 その他、開発時のポイント GitHub Flowだからというわけではありませんが、次のような点にも気をつけて開発を進めています。 レビュアーのレビュー負荷を下げるために Pull Requestのサイズはなるべく小さくしています。目安は1-2時間でレビュー出来る分量です。 lintに加えてSonarCloudによるソースコードの静的解析をPull Request時に適用しています。静的解析が通らないとマージできないようにしており、一定の品質が保たれるようにしています。 実際にGitHub Flowを運用してみて GitHub Flowの採用により現在のところ大きな課題はなく運用ができていると感じています。もちろん今後開発の規模が大きくなった時等には新たな課題が出てくることが予想されますが、小規模チームで高速にプロダクトをリリースしていくのに良くフィットした開発ルールと言えます。 最後に運用してみて良かったこと、悪かったことを紹介して終わろうと思います。 良かったこと シンプルな運用フローであるため学習コストが低い 小さい単位でのPull Requestとコードレビューにより、品質管理とフィードバックのサイクルがスムーズになった 悪かったこと こまめにPull Requestを発行するのでレビュー頻度が高くなりがち。特にレビューはリポジトリ管理者に集中し負荷が高い状態が続いてしまった 対策:Pull Requestの発行時に、変更内容の詳細やレビューしてほしい観点を細かく記載することで認知負荷を下げる。チーム編成時のコーディングルールの事前すり合わせを徹底する ブランチが2本しかないのでmainブランチへのマージ時にコンフリクトが発生することがあった 対策:こまめにPull Requestとは言うものの、その単位が大きいことがしばしばあったため、変更を小さな単位で頻繁にレビュー・マージすることを徹底することで、マージ時の競合の範囲を減らしていく まとめ 小規模開発チームが取るべきブランチ戦略としてGitHub Flowに着目し、我々のチームがどのように運用してきたかをご紹介しました。GitHub Flowは素早くプロダクトがリリースできることからPoCなど、価値検証を高速に回していくことが求められる開発現場に特にフィットすることが確認できました。 Insight Edgeでは一緒に変革しながら価値検証ループを高速に回していけるメンバを募集中です!技術選定はもちろん、このような開発ルールについても柔軟に変革できる環境となっていますので、興味がある方はカジュアルにお話させて頂ければと思います。お気軽に 公式サイト の採用ページからお申し込みください!
こんにちは。Insight Edgeでデータサイエンティストをしている伊達です。 皆さんの会社では、どのような交流施策を導入されていますか? 新型コロナが5類感染症に移行され、弊社メンバーの出社頻度は徐々に増えてきたものの、現状はハイブリッドワークが基本となっています。 ハイブリッドワークだと、各自が好きな出社頻度を決められる反面、全員が常にオフィスにいるわけではないため、組織内での交流や情報交換の場をうまく作らないと、メンバー同士の会話はプロジェクトの定例やミーティングのみになってしまいます。 今回は、私がこれまでに在籍した分析組織で試した交流施策を紹介します。 大学院の研究室 ゼミ ランチ会(論文紹介) 雑談 前職:金融機関子会社のデータ分析系部署 もくもく会(兼雑談会) 最近の論文/ニュース/講演をチェックする会 現在:総合商社のDX内製化組織 勉強会 分析チームLT会 論文読み会 まとめ 大学院の研究室 ゼミ 大学院で所属していたのはコンピュータビジョン系の研究室で、画像認識、3次元復元、SLAMなどの研究をしている学生が多かったです。 研究室であればどこもやっていると思いますが、私が所属した研究室でも毎週1時間ほど、学生が自分の研究内容を紹介するゼミを開催していました。 特色は、学生の約半数が留学生だったため、発表・議論が英語だったことです。 自分の研究内容を英語で他人に発表し、議論する訓練を日々できたことは、国際学会等に参加するための準備として大いに役立ちました。 一方で、まだ研究を始めたばかりで英語の苦手意識がある学部生は割と辛そうでした。 ランチ会(論文紹介) 週に一度、有志の学生で集まり、先生が提供してくれたお弁当を食べながら、それぞれ最近見つけて気になっている論文を紹介する会です。 当時(2017〜2019年頃)は、画像認識系の深層学習手法の研究が急速に進んでおり、毎週面白そうな論文が出ていてネタに尽きなかった、という思い出があります。 こういう論文読み会/紹介を開く場合は、参加メンバーの興味がある程度近い必要があるかなと思います。 自分たちの場合は全員コンピュータビジョン分野の研究をしていたので、「こういう論文もあるぞ」と話が派生していったり、参加メンバーから手法の価値や実験結果の妥当性についてツッコミが入ることもあり、盛り上がりました。 雑談 当時は学生だったので勤務時間という概念がなく、(集中してなさそうな人の)デスクに行って雑談したり、研究室の共有スペースにあるソファでコーヒーを飲みながら、だらだら雑談していました(これを交流施策と読んで良いのか分かりませんが)。 やはり研究生活ではしんどい日もあるので、誰かと他愛のない話をしたいこともありますよね…? こういう場では、かっちりした研究の話はあまりせず、ぼんやりとした課題意識、人生、就活、趣味といったことをみんなと話せて、割と大事な時間でした。 こういう「ムダ」に見える時間も実は大事だと思っていますが、仕事中に長々と雑談していると怒られそうなので、社会人になるとなかなか難しいところですね。 前職:金融機関子会社のデータ分析系部署 もくもく会(兼雑談会) 同じ部の若手3〜4人程度で、毎日夕方に30分程度web会議でマイクオン&ビデオオフにしたまま、作業しながら雑談をする会を開いていました。 普段のプロジェクトの定例やミーティングだと上司や顧客がいるため、そういった場であまり話せないような柔らかい質問、ぼんやりとした課題意識、その他相談ができる場でした。 目的としては大学院の時の雑談と似ていて、「わざわざ会議を開くほどではないけど、できれば聞いておきたいことや確認しておきたいこと」を話したり、仕事とはあまり関係ない話もできたりすることで、個人的には良い場だったと思っています。 一応もくもく会という体で作業をしている(ように見える)ので、会社の勤務時間中でも、こういう場は開催しやすいかもしれません。 最近の論文/ニュース/講演をチェックする会 週に1回、各自気になった論文・記事・ニュースを共有したり、最近の学会等の講演の動画をみんなで視聴して議論したりする会です。 AIやクラウドは日々新たな手法やツールが発表され、一人での情報収集には限界があるため、こういった場で、自分が見落としていたが社内の他の人が見つけた良い論文や記事などを発見でき、良かったです。 紹介内容については、がっつりスライドを作るというより、論文や記事を画面共有しながら雑談する感じなので、あまり準備に時間がかからなくて良かったです。 一応毎週アウトプットの場があるので、日々目にする情報を意識的にスクリーニングし、紹介するに値するかどうか考える習慣がつきます。 現在:総合商社のDX内製化組織 勉強会 弊社では業務時間の10%を自己研鑽に充てることが認められており、その一環として、特定のトピックに興味を持ったメンバー同士で集まって、定期的に勉強会を開催しています。 トピックは開発系、分析系、デザイン系など色々で、トピックによっては異なるチームからの参加があり、チームの垣根を超えた交流や知見共有の機会にもなっています。 自分が最近参加したのは、デザイン経営勉強会、時系列分析勉強会、Kaggle勉強会、MLOps勉強会でした。 分析チームLT会 これまで分析チーム内のデータサイエンティストの知見共有の場があまりなかったため、社内のメンバーが立ち上げてくれました。 LT会なので時間は30分で、毎週1人、最近の分析案件や興味を持って調べたことなどを共有しています。 組織の中で学びを共有し、最新の技術にみんなでキャッチアップしていくために、こういう場は重要だと思っています。 論文読み会 これは上記の分析チームLT会で、私が大学院の時の論文読み会について紹介したところ、他のメンバーが立ち上げてくれた会です。 毎週ランチの時間に30分程度、発表担当者が調べた論文について発表し、みんなで議論します。 トピックによっては論文だけではなく、実務における分析に役立ちそうなものであれば、Kaggleコンペの解法やブログ記事を紹介することもあります。 まとめ 今回は、私がこれまでに在籍した分析組織で試した交流施策を紹介しました。 私が紹介した交流施策を目的別に整理すると、下記のようになるかなと思います。 最新技術をざっくり知りたい → 論文紹介、ニュースや講演のチェック 特定のトピックや技術を深く知りたい → ゼミ、勉強会 社内交流 → 雑談、もくもく会(兼雑談会) 交流施策は「これをどの組織も導入した方が良い」という絶対的なものはなく、各組織のありたい姿や課題によって適切にデザインし、導入していくべきだと考えています。 今回の記事が皆さんの組織における交流施策の検討・導入のきっかけになれば幸いです。
こんにちは、Insight EdgeでData ScientistのKNです。Insight Edgeでは多種多様なDX案件を手掛けており、その多くでは機械学習や統計解析を用いた分析コードを作成することが求められます。 分析チームの開発言語は基本的にPythonが使われています。PoCの段階ではJupyter Notebookを用いてEDAや可視化、モデル構築がよく行われます。そして、PoCを終え期待した効果が確かめられた場合はPoCで作成したコードをそのまま採用せずに、長期運用を前提としたproduction-readyなコードに書き換える必要があります。 本記事では、主にデータ分析で使われるPythonコードを対象として、adhocな分析コードを実運用を見据えたコードに書き換える際役に立つと考えている取り組みについて紹介します。 また、本記事の内容はリファクタリングに関連はしていますが、設計方針やプログラミングスタイルについては取り上げません。それらは良いコードを書く上では重要ですが、すでに優れた書籍が数多く存在し、習得するのも時間がかかります。今回はPythonに特化して、即効性が高く、始めやすいtipsについての紹介になります。 目次 なぜ分析コードを修正する必要があるのか 型情報の付与、フォーマッターとリンターの活用 バリデータの活用 テストの活用 まとめ なぜ分析コードを修正する必要があるのか 結論から述べると、「コードの信頼性を向上させ、運用コストを下げるため」です。ここでの運用コストとは様々な意味合いが含まれます。 例えば、コードの可読性が低いと、コードの理解に時間がかかり、バグを誘発する原因にになります。また、ロジックの正しさの保証が不十分だと、変更の際に追加の確認作業が発生します。 さらに、データ分析では大量のデータ処理をする特徴があります。もし不正なデータが入力された場合、プログラムの挙動が問題になることがあります。実行過程でエラーが発生するならまだいいのですが、エラーが出ないまま間違った処理をしてしまい、分析の結論に影響を与えた結果、間違った意思決定を促す可能性があります。これらの問題点から、次の観点に沿ってコードを改善することが重要だと考えます。 図1:コードの改善軸と実現するための手段 「コードの可読性」、「データの保証」、「ロジックの保証」という3つの改善軸があり、それぞれに対して、「型情報の付与、フォーマッターとリンターの活用」、「バリデータの活用」、「テストの活用」で対応できると考えます。 もちろん、それぞれの関係は互いに独立ではありません。型情報を与え、型チェックを行うことでロジックやデータに対する保証は向上します。テスト前提のコードを書くことで、適度にコンポーネント化されたプログラムは可読性が高くなります。そういった相乗効果はありますが、寄与度の高さを踏まえると図のような関係になるかと思います。 以下、それぞれの項目について詳しく紹介します。 型情報の付与、フォーマッターとリンターの活用 型情報の付与 Pythonは型が無い動型言語です。それ故に、気軽に始められ、少ない記述量で動作可能なものを作成できます。データ分析現場では大変便利なツールとして、重宝されています。一方で、正しく動作可能かどうかは実際に動かして見るまで分からない面があるので、コードの可読性が低くなりがちです(ダックタイピングと呼ばれる所以です)。 Pythonは3.6以降、「型ヒント」と言って型情報を追記できる機能が追加されました。型ヒントを追加することで、コードの可読性を向上させ、コードの理解にかかる時間を減少させることができます。また、型ヒントを追加することで、IDEの補完機能を活用でき、開発効率も向上します。 # 型ヒント例 # 型ヒント追加前 def convert (texts): ... # 型ヒント追加後 # 関数シグネチャの情報だけでコードの挙動が理解できるようになる。 def convert (texts: List[ str ]) -> Documents: ... また、既存のコードに型情報を追加する際に、もし型情報を書きづらい箇所があった場合、そこにはリファクタリングする余地のある可能性が高いです。 # 型ヒントがうまく書けない例 data = { 1 : 'c' , 'a' : 2 , '1' : [ 'd' , 'e' ]} # Anyは任意の型を許す # これは極端な例だが、辞書型でKeyやValueが異質な型の場合、可読性が著しく落ちる def process (data: Dict[Any, Any]) -> Dict[Any, Any]: ... process(data) ただし、型ヒントは型情報を追加するだけで、実際には型チェックを行いません。型チェックを行うためには、mypyという解析ツール(リンター)を用いる必要があります。mypyは、型ヒントを追加したコードを解析し、型チェックを行うツールです。mypyを用いることで、型ヒントの追加漏れや、型ヒントと異なる型の値を代入している箇所を検出できます。 mypyは大変便利なツールですが、mypyを使うことで静的言語のような型保証が得られるかと言えば、それは疑わしいかと思います。mypyはあくまで型ヒントが互いに矛盾なく使われていることを保証するのみで、実行時に型ヒントとは異なる値が変数に代入されたとしても問題にはならないからです。 また、mypyを厳密に適用すると(オプションで --strict と設定)、かなり冗長に型情報を追加する必要があり、反対に可読性が低下する可能性もあります。シンプルに書きつつPythonを使用するメリットが減少してます。 さらに、自分のコードに厳密に型ヒントを強制したとしても、インポートしているサードバーティ製のライブラリに型ヒントが追加されていない場合がよくあります。代表的なライブラリでは、型情報ファイルをダウンロードできたり、型情報ファイルを自動生成できるものもありますが、手間の割に効果が限定的です。 どの程度の厳密性を適用するかは組織の方針やプロジェクトの性質から判断する必要があると感じます。また、既存のコードに対しいかにmypyを適用していくかは 本家のドキュメント に記述がありますので参考にしてみてください。 フォーマッターとリンターの活用 フォーマッターとは、コードスタイルを整えてくれるツールです。代表的なPythonのフォーマッターは、Blackというツールです。Blackは、PEP8に準拠したコードを自動生成してくれます。PEP8は、Pythonのコーディング規約です。Blackを使うことで、コードのスタイルを統一できます。それによって、コードの可読性を向上させ、コードのフォーマットでの意見の違い等余計なことに悩む必要も無くなります。また、isortと呼ばれるモジュールのインポート順をフォーマットしてくれるツールもあります。 リンターはソースコードを(実行前に)静的解析して、エラー等をチェックしてくれるツールです。先ほど紹介したmypyも型チェックのリンターでした。それ意外の代表的なリンターとしてFlake8があります。Flake8はコードのエラーチェックを行うpyflake、PEP8スタイルに準拠しているかチェックをするpycodestyle, コードの複雑度をチェックするmccabeをバンドルしたものになります。注意点としては、あくまでチェックツールなので自動的に修正してくれるわけではありません。そのため、コードスタイルの補正を先にBlackとisortで行ってから、Flake8でチェックするのが良いかと思います。 基本的にこれらのツールの適用に発生するコストは低いため、極力活用することが望ましいです。 バリデータの活用 PoCの作業中では、データにどのような値が含まれているか観察しながら分析をするので、データの正しさに対する注意、関心が怠りやすくなるかと思います。しかし、実際の本番導入以降でどのようなデータが投入されるかは未知数です。たとえ、データの内容について事前に確約していたとしても、必ずしも守られるとは限りません。 バリデータを活用することで、投入されるデータの正しさについて完全とはいかなくても、十分な保証を得ることができます。特に、実行過程のなるべく早い段階で適用することが望ましいです。早い段階でデータの不当性を見つけることで、副作用を伴う処理(DBへの書き込み等)を防ぐことができます。また、事前にデータの正当性を保証することにより、冗長なデータをチェックする処理を省き、ロジックコードは本質的な処理がメインになリます。その結果、可読性も向上し、データチェックのエラーハンドリングも減少します。 まず紹介するツールは、 pydantic になります。pydanticは型情報やメタ情報を使って、実行時にデータのバリデーションを行ってくれるツールです。実行時のデータチェックを伴うデータクラスと見なすとイメージつきやすいかと思います。 # pydantic例 from pydantic import BaseModel, PositiveInt, ValidationError class User (BaseModel): id : int name: str = 'John Doe' signup_ts: datetime | None tastes: dict [ str , PositiveInt] # この場合、idがintでない、signup_tsが無いという理由でエラーとなる external_data = { 'id' : 'not an int' , 'tastes' : {}} try : User(**external_data) except ValidationError as e: ... 次に、 pandera の紹介になります。panderaは、pandasのデータフレームに対して、スキーマを定義してバリデーションを行うことができます。データ分析の際には、表形式のデータを扱うことが多いので便利です。 # pandera例 schema = DataFrameSchema( { "性別" : Column( str , checks=Check( lambda s: s.isin([ "男性" , "女性" ]))), "年齢" : Column( float , nullable= True , checks=Check.gt( 0 )), "身長" : Column( float , nullable= True , checks=Check.gt( 0 )), } ) df = base_list_schema.validate(df) テストの活用 テストコードを書くことのメリットは色々なところで語り尽くされているので、異論はないかと思います。 ただし、通常のシステム開発と異なり、データ分析や機械学習領域では、テスト駆動開発や実装とテストをほぼ同時に進めるやり方は主流でないと(個人的には)感じています。 データ分析や機械学習のPoCの段階では、ほとんどの場合、より良いKPI(予測精度)の達成が目的となります。その実現手段は何でも良いため、様々な特徴量加工やモデル構築を試し、最も良いアプローチのみを採用し、それ以外のほとんどは無駄になることが多いです。試行錯誤中のコードに対してテストを書いて確認はできますが、結局は無駄になるコードへのテストは中々行われづらいの実情かと思います。 しかしながら、運用が決まった後は、テストコードを必ず書いたほうが良いです。なぜなら、データ加工やモデル構築の処理が確定したので、その処理の正しさを保証する必要があるからです。これは、特にリファクタリングや機能追加を行う際に重要です。本来の機能が壊れていないかことを容易に確認しながら、作業できるため信頼度が高くなります。また、他の人がコードを読む際にも、テストコードがあることでコードの意図を理解しやすくなります。これらの効果はコードの規模が大きくなるほど顕著になります。 一方で、テストはロジックの正しさをある程度保障するものですが、完全ではありません。あくまで限られたテストケースのみにおいて正しさを保障するに過ぎません。また、テストを書くこともコストかかりますし、量が増えてくるとコードの変更ごとのテスト実行の時間も無視できなくなります。さらに、プログラムの仕様を大幅に更する場合(データ分析ではよくありますが)、既存テストも書き直す必要が発生するので、変更への負荷が重くなります。 テストを全く書かないというのはありえないですが、テストをどの程度充実させるかどうかはPJの規模や性質によって変わってくると思います。私は後段の理由もあり、テストの充実度は通常のシステム開発よりも低くなっても良いと思います。データ分析、機械学習領域のテスト方針については私自身十分に結論が出ていないので、今後も検討していきたいと思います。 機械学習の場合の注意点 機械学習の場合の厄介な問題として、データ自体が流動的なため、たとえコードの処理に問題がなくても、精度悪化する場合があります。これは結果としてアプリケーションの本来の機能が達成できていないという点で問題です。 精度劣化の問題に対処するには、継続的にPJのKPIやモデルの精度を監視する体制が必要です。この作業をスポットで行う場合は手動でも問題ないかもしれませんが、日々の業務サイクルに組み込もうとすると、MLOpsの構築が必要なってきます。 テストコードでは精度の保証はできないので、ある程度のテストコードでロジックの正しさを保証しつつ、精度監視をを行うことで機械学習アプリケーションの品質を担保できます。 テストフレームワークについて 代表的なPythonのテストフレームワークは pytest です。標準ライブラリのunittestもありますが、それよりもシンプルで柔軟にテストコードを書くことができます。pytestの使い方については公式ドキュメントを参照してみてください。 最近では、ChatGPTに聞いてもそれなりの回答をしてくるので活用しない手はないです。ただし、業務コードで聞く場合は社内ポリシーに従ってください。 図2: 素数判定のテストコードをchatgptに聞いた結果 まとめ データ分析、機械学習コードの品質を上げるために、「コードの可読性」、「データの保証」、「ロジックの保証」という3つの改善軸があることを紹介しました。 コードの可読性を容易に実現する手段として、「型情報の付与、フォーマッターとリンターの活用」を紹介しました。フォーマッターやリンターは手間が掛からず実行できるので積極的に使うべきです。mypyは厳密に適用すると大変で却って可読性が落ちるので、PJの規模や性質に応じて適用範囲を決めると良いです。 データの保証をするためのツールとして、pydanticとpanderaを紹介しました。両者ともより細かい制約を設定できます。外部データの読み込み時に適用することで、初期段階で不正を検知できますし、コードもよりシンプルになります。 プログラムのロジックを保証するために、テストを書くことが重要であることを述べました。テストを書くことで、早い段階でプログラムのエラーが検知でき、コードの変更に伴うリグレッションも防ぎ、コードの品質を担保することに繋がります。テストの充実度はPJの規模や性質に応じて決めるべきですが、テストだけではデータ分析や機械学習の品質の保証はできないので、そのためにはMLOps等のアプローチを検討することも必要です。 参考文献 ロバストPython ―クリーンで保守しやすいコードを書く
こんにちは!Insight Edge で Developer をしている Kobori です。 本記事では、Amazon Cognito と Nest.js を使用した認証認可について、調査で得た使い方とノウハウを紹介します! 初めて使用される人でも、本記事を見てユーザープールの設定からユーザー認証まで一通りの機能が使えるようになればと思いを込めて書きました。 ぜひ、最後までご覧いただけたらと思います。 この記事でわかること Cognito のユーザープールの作り方 Nest.js の Guard でのユーザー認証方法 Cognito とは? AWS のユーザー認証、ユーザーの管理ができるサービスです。 ユーザー認証に関わる下記のような充実した機能があります。 実装面においても、AWS ライブラリが用意されているので、フロントエンド、バックエンド問わず、工数を削減してセキュリティの高い機能を実装できます。 Cognito のユーザープールとは? Cognito ユーザープールは、Cognito のサービスの一部でありユーザー管理、属性管理、認証するサービスです。 ユーザー情報(ID、パスワード、メールアドレスなど)やグループ情報の保持、トークン管理、アクセス制限などの設定ができます。 開発者は、ユーザー認証に係る機能を代替えして使用することで、よりアプリ開発に注力することが可能となります。 詳しくは、 Amazon Cognito プール 参照 Cognito の主な提供機能 サインアップ サインイン パスワードリセット パスワード変更 ユーザー属性の管理 JWT トークン(アクセストークン、リフレッシュトークン、リフレッシュトークン)発行 ユーザー固有の UUID 発行 多要素認証 リスクの検出 Cognito の利用料金 月間 50,000 アクティブユーザまで無料で使用できます。 ※ リスクの検出の機能である「高度なセキュリティ」については、追加の料金が発生します。 詳しくは、 Amazon Cognito 料金 参照 Cognito ユーザープールの作成 Cognito でユーザー管理をするには、ユーザープールの作成が必要です。 ステップ別の主な設定内容 ステップ 1:サインイン時に使用するメールアドレス、電話番号の有無の設定 ステップ 2:パスワード要件や多要素認証の有無、アカウント復旧方法の設定 ステップ 3:サインアップ時の確認方法やユーザーに付与する属性情報の設定 ステップ 4:Cognito から送信する E メールの設定 ステップ 5:ユーザープール名、認証方式、トークンの有効期限の設定 作成時の各種設定 ステップ 1:サインインエクスペリエンスを設定 ステップ 2:セキュリティ要件を設定 Authenticator アプリケーション、SMS メッセージでの確認も可能 ステップ 3:サインアップエクスペリエンスを設定 デフォルトのまま次へ ステップ 4:メッセージ配信を設定 一時的な設定として、Cognito での動作確認を優先するのであれば「Cognito で E メールを送信」を選択 SES で E メール送信を行う場合は、AWS SES の設定が必要です ステップ 5:アプリケーションを統合 ユーザープール名の入力 「Cognito のホストされた UI を使用」にチェックと「ドメイン」の指定 アプリケーションクライアント名の入力 ユーザープールにユーザー作成 「E メールで招待を送信」を選択すると仮パスワードが送信される ※ 招待を送信しない場合、仮パスワードの設定をする コマンド で認証確認 サインイン 下記コマンド実行でユーザー名とパスワードを使ってサインインできる クライアント ID クライアントアプリケーションの ID を指定 この ID は、Cognito のコンソール画面のアプリケーションの統合のタブで確認できる ユーザー名 サインインするユーザーのユーザー名を指定します。 パスワード サインインするユーザーのパスワードを指定します。 aws cognito-idp initiate-auth --client-id ”クライアントID” --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME=”ユーザー名”,PASSWORD=”パスワード” 初期パスワード変更 初回サインイン時に返された「Session」を使って初期パスワードを変更する aws cognito-idp respond-to-auth-challenge --client-id "クライアントID" --challenge-name NEW_PASSWORD_REQUIRED --challenge-responses NEW_PASSWORD="新しいパスワード",USERNAME="ユーザー名" --session "初回サインイン時に返されたsession" ログアウト 下記コマンド実行でログアウトできる aws cognito-idp global-sign-out --access-token "アクセストークン" Nest.js で認証と認可 トークンを使ったアプリ側での認可 Cognito では、コマンドや API でサインインした際に 3 つのトークンが発行され返されます。 サインインでユーザー認証し、レスポンス(ユーザー情報)に含まれるアクセストークンを使用し、ユーザーの有無やトークンの有効期限を判定してアプリ側での認可をします。 リフレッシュトークンを使うと有効期限の切れたアクセストークンを再発行できるので、有効期限が切れた場合に再ログインさせるか、自動で再発行するかアプリ側で使い分けができます。 取得できるトークンの種類 アクセストークン アクセス制限や、ユーザーの認可に使用するトークン グループ情報も含まれている 有効期限は、5分~1日 ID トークン ユーザーの属性情報(例:ユーザー名、メールアドレス)が含まれるトークン 有効期限は、5分~1日 リフレッシュトークン(更新トークン) 再認証なしでアクセストークンと ID トークンの再発行を取得するためのトークン 有効期限は、60分~10年 事前準備 下記をインストール npm install @aws-sdk/client-cognito-identity-provider 下記を import import { AdminInitiateAuthResponse } from 'aws-sdk/clients/cognitoidentityserviceprovider'; サインイン JavaScript でのサインイン処理例 const cognito = new CognitoIdentityServiceProvider(); const data = await cognito .initiateAuth({ AuthFlow: 'USER_PASSWORD_AUTH', ClientId: "クライアントID", AuthParameters: { USERNAME: "ログインユーザー名", PASSWORD: "ログインパスワード", }, }) .promise(); data.AuthenticationResult.AccessToken; ログアウト JavaScript でのログアウト処理例 const cognito = new CognitoIdentityServiceProvider(); await cognito .globalSignOut({ AccessToken: "アクセストークン", }) .promise(); Guard を使ったユーザー検証 Nest.js の Guard でユーザー検証する アクセストークンを使ったユーザー取得をすることで、ユーザーの有無とアクセストークンの有効期限が検証できる ※ユーザーが取得できない場合やアクセストークンの有効期限切れの場合は、例外が発生します const cognito = new CognitoIdentityServiceProvider(); this.user = await cognito .getUser({ AccessToken: "アクセストークン", }) .promise(); Nest.js の Guard でユーザーのグループ検証する グループ情報は、アクセストークンに含まれるのでデコードすることでユーザーに設定したグループ情報が取得できる 下記のように取得後に対象のグループが含まれているか判定をすることで、グループの検証ができる jsonwebtoken のインストール npm install jsonwebtoken アクセストークンをデコードしてグループ情報取得 import jwt from 'jsonwebtoken'; ・・・ const decodedToken = jwt.decode("アクセストークン"); return decodedToken ? decodedToken["cognito:groups"] : []; Cognito を使ってみた感想 難しそうと思っていた認証部分ですが、Cognito の導入により必要な機能を補うことができるので、開発者は、心置きなくアプリ開発に専念できると思いました。 また、ユーザー認証に必要な基本的な機能が揃っており、無料から使える点やライブラリや UI が用意されているため 手軽かつスピーディーな開発に繋がるでしょう。
はじめに  こんにちは。Insight Edge, Data Scientistのnakanoです。  これまで機械学習モデルを使用する際は、データの前処理、特徴量エンジニアリング、モデルの選択、 ハイパーパラメータの調整といった複雑な手順を専門知識を持つデータサイエンティストが手作業で行う必要がありました。 しかし最近は、クラウドベンダーが提供しているAutoMLサービスの認知度も上がり、 サービスに料金を支払うことでモデル構築プロセスを自動化することが身近になりつつあります。 そのため、技術者として機械学習モデルを構築する業務はだいぶ楽になってきた一方で、 サービスへの課金額を考慮しなければならなくなりました。  私自身、Vertex Forecast(Google Cloudが提供する時系列予測向けのAutoMLサービス)を使う際にどれだけ課金すれば良いのか迷った経験があります。 そこで今回は、その経験を元にVertex Forecastの課金額の決定方法やノウハウを説明します。 はじめに Vertex Forecastとは Vertex Forecastの料金体系 ケース:1000店舗の1週間後までの客数予測モデル トレーニング時間の課題 トレーニング時間の決定方法 トレーニング時間の目安 コンテキストウィンドウの目安 私見 経験 所感 結論 Vertex Forecastとは  Vertex Forecastとは、Google Cloudが提供している時系列データ向けのAutoMLサービスです。 2021年5月にプレビュー版が公開され、2022年6月にGA版が公開されました。 AWSのAmazon Forecastが2019年8月にGA版が公開されていることを考えると、比較的新しいサービスといえます。 Amazon Forecastに比べて設定できるパラメータが少ないこともあり、非技術者でも使いやすく作られたサービスと感じます。 Vertex Forecastの料金体系  まずVertex Forecastの料金体系を紹介します。 Vertex Forecastでは、学習と予測の2つのプロセスがあり学習は時間単位、 予測はデータポイント数(予測する値の数)に応じて課金されます。 学習(Training) トレーニング時間1時間分あたり、$21.25 予測(Prediction) 予測値1000個あたり、$0.20 (0-1M points) 予測値1000個あたり、$0.10 (1M-50M points) 予測値1000個あたり、$0.02 (>50M points) 引用:Vertex AI pricing,Vertex AI Forecast ケース:1000店舗の1週間後までの客数予測モデル  具体的なケースで費用を計算してみます。 たとえば1000店舗を運営しているレストランチェーン店のデータサイエンティストとして勤務していたとし、 店舗から仕込みや発注の都合で直近1週間の客数予測を毎週1回把握したいと要望があったとします。 またデータサイエンティストの事前の分析結果から、 客数予測モデルは毎月1回 (ここでは仮に)10時間分のコストをかけて再トレーニング させる必要があるとします。  この場合の費用は以下のとおり、$218.1/月と見積もれます。 学習(Training)費用 $21.25/時間 * 10時間 * 1回/月 = $212.5/月 予測(Prediction)費用 $0.2/1000 * 1000店舗 * 7日/週 * 4週/月 = $5.6/月 トレーニング時間の課題  上記のレストランチェーン店のケースでは、 トレーニング時間を仮に10時間分と設定しましたが、実際はどのように決めればよいのでしょうか? 使用するモデルが既に決定している場合は、学習用データと検証用データの損失関数を参照することでトレーニングが十分であるかどうかを確認できます。 しかし、Vertex Forecastでは損失関数を確認できません。 他のVertex Forecastユーザーもこの点について言及されていたので、学習の進捗がわからない点はユーザーならば認識している課題のようです。 ( ML: Vertex AI Forecast AutoML ではじめる需要予測 )  そのため、トレーニング時間決定にノウハウが必要となります。 トレーニング時間の決定方法 トレーニング時間の目安  まずトレーニング時間の参考値として、公式ドキュメントの表を紹介します。 この表では、行数、特徴量数、予測ホライズン(予測期間の長さ)によってトレーニング時間の目安が記載されています。 留意点として、この表の値はあくまで目安であり、コンテキストウィンドウ(入力期間の長さ)や特徴量の内容によっても必要なトレーニング時間は変わってきます。  コンテキストウィンドウ(入力期間の長さ)は、ユーザーが学習時に設定する値です。 大きいほど、モデルの精度が向上しますが、トレーニング時間も増加します。 ではコンテキストウィンドウは、どのように設定すればよいのでしょうか? 行数 特徴量の数 予測ホライズン(予測期間の長さ) トレーニング時間 1,200 万 10 6 3~6 時間 2,000 万 50 13 6~12 時間 1,600 万 30 365 24~48 時間 引用:Train a forecast model 予測ホライズン、コンテキストウィンドウとは 予測ホライズンとは、モデルがどれくらい先まで予測するかを設定する値です。日ごとの時系列データで1週間先まで予測する場合は7となります。 コンテキストウィンドウとは、モデルがどれくらいの期間を遡ってデータを参照して予測するかを設定する値です。予測に直近4週間の値を入力する場合は、28となります。 コンテキストウィンドウの目安  次に、コンテキストウィンドウの決定方法についてまとめます。 公式ドキュメントに記載された手順をフローチャートにまとめました。 ざっくりとしたプロセスですが、精度に満足するまでコンテキストウィンドウを増やしていくというものです。 このとき、コンテキストウィンドウの増加とともにトレーニング時間も比例的に増やす必要があります。 コンテキストウィンドウの目安 私見  ここまで公式ドキュメントで紹介されているトレーニング時間とコンテキストウィンドウの決定方法について説明しました。 私自身の経験と所感、結論をまとめます。 経験  以前、以下のケースで時系列データ予測をVertex Forecastで検証しました。 特徴量:4個(タイムスタンプ列(日付):1個、カテゴリ変数列2個、ターゲット変数列1個) タイムスタンプ列とターゲット変数列以外の特徴量が2件しか無いのは、トレーニング時間を抑えるため最低限の特徴量だけを特に前処理せずに入れたためです。 コンテキストウィンドウ:50 予測ホライズン:10 行数:約100万行(時系列識別子1000件、データポイント1000件)  このケースでは、12時間のトレーニング時間まで精度が向上しました。 公式ドキュメントのトレーニング時間の目安と比べて、これはやや長めの時間を必要としました。 標準的なトレーニング時間よりも多くの時間を必要とした要因としては、 特徴量のうち2個は数10のカテゴリ数を持つカテゴリ変数だったことや、 今回のデータが特定の日や曜日でイベントを持つデータだったため日付列から作成できる特徴が多かったことなどが、 考えられます。 所感  AutoMLサービスというと、手元のデータをアップロードするだけで簡単にモデルが構築できるというイメージがありました。 実際に使ってみたところ、私のケースでは簡単に精度の高いモデルが作成できました。 一方で、使えそうなデータをやみくもにトレーニングさせるのは、コスト面で現実的ではありません。 精度に寄与しない特徴量を削除するなど、工夫は必要となります。  欲張って特徴量を増やしすぎず、また学習を一度で完結させようとするのではなく適切な課金を確保することが、AutoMLをうまく利用する上でのポイントだと感じました。 結論  最後に推奨方法と私見をあわせて、結論をまとめます。 課金額に余裕があるとき。 公式ドキュメントのベストプラクティスに沿って、コンテキストウィンドウと予測ホライズンは同じ値にして、トレーニング時間6時間から始め適切なコンテキストウィンドウを探す。 適切なコンテキストウィンドウが見つかったら、時間を増減させて、トレーニング時間を調整する。 課金額に余裕がないとき(ちょっと触ってみたいとき) 特徴量を減らす。(計算量を減らすため) コンテキストウィンドウと予測ホライズンは同じ値にする。(計算量を減らすため) トレーニング時間1時間と2時間でトレーニングさせる。( 重要 :節約のため最小単位の1時間分($21.25)だけ試してみたいところですが、2時間分も動かしておいて、精度の伸びしろを確認しておくことは重要だと考えています。)
こんにちは。InsightEdgeのDataScientistのSugaです。以前からテレワークをしていますが、最近は自宅の仕事場環境を改善すべくスタンディングデスクやモニターアームを導入してすごく快適になりました。 今回は昨年に経済産業省が主催しているデジタル推進人材育成プログラムである、「マナビDX Quest」に参加したときの記事を書いたので、お時間がある方は読んでもらえれば幸いです。 目次 プログラムへの参加 マナビDX Questとは? 前身はAI Quest 初心者でも参加OK プログラム参加へのきっかけ お知らせが届く 参加動機 応募するときのポイント スキルアセスメント 時間の確保と参加する周辺環境整備 志望動機の推敲 プログラムキックオフ プログラム概要 キックオフセッション 受講手続き オンボーディング コミニュケーション 第1タームPBL(Project Based Learning) 店舗を運営する企業の収益改善 教材の内容 参加者との交流 交流セッション開催 Slackチャンネル 学び合う文化 第2タームPBL(Project Based Learning) 製造業の工数予測 プレゼン課題 地域企業協働プログラムへの参加 チーム組成と準備期間 チーム募集 開始前準備 企業とのマッチング 地域企業協働プログラムの取り組み ワークショップ開催 提案書作成 現地視察 報告書 まとめ 所感 関係人口の大切さ 今年も開催 プログラムへの参加 マナビDX Questとは? マナビDX Quest は 経済産業省が主催するデジタル推進人材育成プログラム です。ぱっと見ると、 「マイナビ?!」 と読めるのですが、毎日コミュニケーションズとは無関係のようです。 「学び」をカタカナにしたようですね。 DXもデジタルトランスフォーメーション(Digital Transformation)の略だと思っていたら、デラックスのDXみたいですね。てっきりデジタルトランスフォーメーションだと思っていました(笑) 前身はAI Quest 前身のプログラムはAI Questという名前で2019年から開始していますが、2022年からはマナビDX Questとして、AI(人工知能)の分野だけでなく、デジタル技術全般に関わるものとしてより範囲を広げて開始されました。詳細については本家のWebページを参照してもらればと思います。 初心者でも参加OK 以下に詳細の抜粋を紹介します。 このプログラムは特別なデジタルスキルを必要とせず、基本的なリテラシーと学ぶ意欲があれば誰でも参加できます。受講生は実際のDXプロジェクトを体験しながら、デジタル技術とビジネス要素(課題の発見、ゴール設定、コミュニケーション力など)を学びます。さらに、データの活用やビジネス変革といったスキルを習得し、データサイエンスプロフェッショナルやビジネスアーキテクトなどの役割を目指すことが出来るというものです。 世の中にはたくさん教育プログラムがありますが、調べてみると面白いものがたくさんあるんですね。 プログラム参加へのきっかけ 以前にプログラミングや機械学習の講師をやっている時期があり、そのときの生徒さんの一人に、カリキュラムを早々と終わらせてしまって、自分で技術書やBlogを読んで自主的に勉強している方がいました。 あるときに、AI Questというプログラムを見つけたので これに参加してみたいという相談 がありました。勉強になりそうだったので、参加してみたら良いのではという話をしました。 自分「どんな内容のプログラムなんですか?」 生徒「画像での不良品検知をやっているんですが、受講者同士でコンペをやって精度を競うんです」 生徒「その他に、実際の案件みたいにやるのでとてもリアルですよ」 生徒「参加者も初心者の人から、ガチな人までいて幅広いですよ」 自分「なかなか面白い試みですね、普通の研修とは少し違う感じですね」 自分「でも、こういう研修って参加費が高くて、なかなか一般の人は受講できないよね」 生徒「書類選考はありますが、通過したら無料で受講できますよ」 自分「え!?、無料なんだ、それは良いですね」 その時は面白い取り組みをしている程度という感じだったのですが、プログラム内容もしっかりしていて、次にあるときには参加しても良いかなと思っていました。 お知らせが届く その後、すっかりそのことは忘れていました。2022年7月になってから、 データサイエンティスト協会 のメーリングリストやコンペティションサイトである SIGNATE からの案内があり、新たにマナビDX Questとしてプログラム参加を募集するということでした。プログラムの内容を確認すると、6ヶ月に渡る長丁場だったので少し不安な部分もありましたが、名前が変わって内容も刷新されるということで 面白そうだったので参加する ことにしました。 参加動機 参加動機をまとめると、 どんな教育プログラムをするのかが気になる 参加者同士の交流が出来て、学習者にどんなニーズがあるのかが気になる 普段はデータ分析や予測モデル実装をする部分が多いのでコンサルティングもたまにはやりたい 新入社員教育など教育のコンテンツを作っていくときの参考にする ということがありました。 応募するときのポイント スキルアセスメント 応募するときにはスキルアセスメントがあるのですが、事前の心構えが必要になります。 いきなりテストが開始されるのでびっくりしないことが重要です 。もし、Jupiter Notebookを使いたい人は事前に用意しておくと良いと思います。データ集計の課題もありますが、データ量はそれほど多くないのでExcelでも対応できると思います。制限時間があるのでなるべく素早く解答する必要があります。 時間の確保と参加する周辺環境整備 それから、基本的には働きながら参加することになるので、 事前に職場へ報告して同意を得ておくとスムーズ です。ただ、仕事終わりや休日などのプライベートの時間で参加ができるので人によっては必要ないかもしれないです。 志望動機の推敲 それから、全員参加出来るわけではなく、選抜があるのですが、スキルアセスメントの結果よりも 志望動機のほうが重要視される と感じました。ですので、志望動機の内容はよく推敲して投稿するほうが良いと思いました。ただ、選考基準は公開されていないのであくまでそういう印象があるということです。 まとめると以下のようになります。 スキルアセスメントへの心構えとデータ分析課題への準備 時間の確保と参加する周辺環境整備 志望動機の推敲 プログラムキックオフ プログラム概要 詳細なプログラムについては本家のサイトを参照してもらうとして、主に以下のようなプログラムがあります。 * ケーススタディ教育プログラム * 地域企業協働プログラム ケーススタディ教育プログラムは「課題解決のためのAI実装プロジェクト」を擬似的に体験するものです。教材を自分で選択して取り組むことになりますが、教材によって課題整理/問題解決/コンサルティング/ロードマップ策定に重きが置かれているテーマもあれば、実際のAIモデル開発に重きが置かれているものもあります。 サイトにも掲載がありますが、 需要予測・在庫最適化 不良箇所検出 店舗を運営する企業の収益改善 業務最適化 などのテーマがありました。 ケーススタディ教育プログラムはPBL(ProjectBasedLearning)と呼ばれていて、 8月から10月に実施される第1ターム 12月末から2月まで実施される第2ターム に分かれています。 地域企業協働プログラムは受講生がチームを作り、実際の地域の中小企業の課題解決に取り組むものです。約2ヶ月間をかけて具体的な課題に対して解決策を提案して報告していく内容になっています。 キックオフセッション 受講手続き 応募後に受講が決定するとメールで受講案内が送られてきて、手続きをするこになります。PBLでは教材配布やモデル開発をするための インフラとしてSIGNATE を利用することになるのでその登録などを行います。受講期間中は オンラインの教材が使用可能 なのでこれから学び始める人にとってはとても良い環境だと思いました。 オンボーディング 受講者向けのガイダンスがオンラインで開催されるので、オンボーディングも丁寧に行われていると感じました。受講者は1800人の規模なので、説明会をするにしても工夫が必要で主催者側はスタートするまでの準備が大変そうという印象でした。また、 参加できない人向けにZoomの録画も提供されている のでそのあたりも親切でした。 コミニュケーション コンセプトとして受講者同士の学び合いを推奨しているので、その仕組をどのように設計するかも重要なポイントだと思いました。Slackチャンネルが用意されていたり、 コミニュケーションツールを活用したりと受講者同士が学び合う仕組みを準備 していました。開会式後、プログラムがスタートするのでそれまでに準備を進めていきます。 第1タームPBL(Project Based Learning) 店舗を運営する企業の収益改善 参加した Project Based Learning (PBL) では、店舗を運営する企業の収益改善のテーマを選択しました。このテーマは 過去案件として実際にあった現場研修プログラム をもとにして作られたものらしく、実際のビジネスシーンに近いリアルな内容でした。 教材は段階的に進行し、毎週新しい教材が公開されていきます。 まずはヒアリング内容から課題を抽出するところからスタートしました。その後、 実際のデータが提供され、そのデータ分析から課題をさらに深掘りし、デジタルを活用した解決策を探求していきます 。このプロセスは実際のDXプロジェクトでよくあるシナリオを再現しており、現実の問題解決をしていく過程を忠実に模擬していると思いました。 途中の提出物はPPTでの提案資料となり、 他の参加者と相互に評価をする課題 があります。点数の高かった人が成績優秀者に選ばれるという、競争要素も含んだ内容になっていました。この評価プロセスは自分自身の成果を他者と比較し、自分のアウトプットに対してどの程度の価値があるのかを知る良い機会となりました。 プロジェクトの自由度は非常に高く、店舗を運営する企業の収益改善の目的に沿っていれば、どんな課題設定にしてもよいです。ですので、 自分なりに課題をどう解決するかの仮説を考えて、解決策のアイディアを考える 良い時間になりました。 例えば、 * 需要予測 * 在庫最適化 * ダイナミックプライシング * デジタルマーケティング など、さまざまなアプローチを考えました。問題解決という観点ではデジタル技術を使わない方法(業務効率化や業務プロセス改善)もあり、 自由な発想によって多くの方法を出せる ということも感じました。一方で、初めての経験する方や初心者の人は、示されていたガイドラインに従う形で進めることも出来ます。 教材の内容 全体として、PBLは自分の考えを具現化し、それを他者と共有し評価するという、 実践的なビジネススキルを身につけるためのとても有効なプログラム だと感じました。また、店舗を運営する企業の収益改善という具体的なテーマを通して、データ分析から解決策提案までの一連のフローを経験でき、そのプロセスを通じて多くの学びを得ることができる教材だと思いました。 このとき、同じ課題をやっている受講者のSlackチャンネル中で活発に議論がなされていました。 各自が理解したことや提案したいアイディアを共有するための定期的な勉強会が主体的に開催されていて そこでの議論もとても有用なものでした。アイディアを共有してフィードバックを受けることで、より良い解決策になっていく受講者もいて、積極的に参加していく姿勢は素晴らしいと感じました。 参加者との交流 交流セッション開催 プログラム開始後は交流セッションが頻繁に開催されていました。そこでは、 Zoomのブレイクアウトセッションを通じて他の参加者と直接会話を交わす機会 が多く設けられていました。他の参加者の背景や参加理由を聞くだけもとても面白かったです。何か話すきっかけが出来たときはSlackでお礼コメントをするととても丁寧で良いと思いました。 ただ、通常の仕事も一緒だと思いますが、 顔が見えない分とても丁寧なコミニュケーションの必要性 を感じました。事務局からも 「丁寧なコミニュケーションをしてください」 と案内があり、やはり一定の配慮は意識した方が良いと思いました。 また、事務局主催の交流セッションの他にも、有志による交流セッションも多く開催されており、自発的な活動が行われていました。Zoomの有料アカウントを持っている人は良いのですが、持っていない人もいるので コミニュケーションツールが提供されて、常時交流できる環境 が整備されていました。 Slackチャンネル Slackチャンネルが設けられており、かなり多くのチャンネルが作られていました。これらのチャンネルでは、 特定のテーマや分野に関する議論の場として機能し、参加者間の交流の場 になっていました。そもそも、1800人規模のSlackはかなり規模が大きいので一定の運用ルールを作っていかないと収拾がつかなくなるので、運用面でも工夫が必要だと感じました。 プログラムの後半の地域企業協働プログラムではチームを組む必要があり、そのための準備として プログラムの早い段階では参加者同士で交流をしている人 が多かったです。チーム組成の話はこの後でしたいと思います。 学び合う文化 特に良いと思ったのは、 包括的なサポート体制と学び合う文化 です。過去に参加した経験のある人がメンターとして有志でサポートするしくみを作っていて、初心者の方々へのサポートが非常に充実していました。本来であれば、講師を採用して有償でサポートする体制を整えますが、 受講者同士が学び合うことでコストダウン にもなります。 さらに、わからないところは経験者によってすぐにアドバイスを提供するという風土が醸成されます。加えて、 サポートに対するコミュニティ貢献賞や成績優秀賞など表彰 も用意されていて様々な形でモチベーションを与えていることも良い点だと感じました。 第2タームPBL(Project Based Learning) 製造業の工数予測 第2タームに開催されるPBLは任意参加なので、プログラム途中でアンケートが実施されて、希望者が受講することになります。また、地域企業協働プログラムと同時期に行われるので、 企業協働プログラムに集中したい人は受講していない 人もいました。 自分はせっかくの機会なので受講することにして、 製造業の工数予測 のテーマを選択しました。基本的な流れは第1タームで経験しているので、全体のプロセスは同じなのですが、提案資料を作るだけでなく、実際に予測モデルを開発するという点が第1タームと異なるポイントでした。SIGNATEを使用してプライベートなコンペティションが開催されて 参加者で予測精度を競っていく ことになります。精度の良かった上位者には発表の機会が与えて、他の受講者にやった工夫を共有することになります。基本的にはテーブルデータの回帰問題を扱うので、特徴量エンジニアリングをどれだけ出来たかの勝負になっていました。データは実際に地域企業協働プログラムに参加した企業のものをベースに作られていると思っていて、かなり リアルな教材の作り になっていました。 プレゼン課題 教材の最後には意思決定者向けのプレゼンを作る課題もあり、受講者が作った資料もとても参考になりました。成績優秀者で非常にきれいなデータ分析のグラフを作っている方がいて、ぱっと見るとBIツールを使ったようにしか見えないのですが、発表後に聞いてみるとExcelで作っていることがわかり、とてもびっくりしました。 多様な背景を持つ受講者がたくさんいるので、まだまだ 知らない視点 がたくさんあると感じられました。その他、モデリング時のデータに対する見方もたくさんあり、 相互で学び合うことでのメリット があると思いました。 地域企業協働プログラムへの参加 チーム組成と準備期間 チーム募集 地域企業協働プログラムは2022年12月中旬にはじまりました。その前にチーム組成をする必要があり、チーム組成のイベントもたくさんありました。チーム人数は固定で決まっているので、多くなったり少なくなったりすることは出来なかったです。slackでの募集もあり、自分の場合はslackのチーム募集のチャンネルを使ってチームを作りました。募集後に顔合わせの打ち合わせをやって、自己紹介をしたり、どんなことができるかの共有をしてチームを組めるかを決めて行きました。 違うメンバーで顔合わせの打ち合わせは何回かやって、最終的に気が合いそうな人で組むことにしました。プログラムに参加している時点でやる気がある人なのでそこは問題ないのですが、条件をつけて探している人もいました。学生で参加している人もいましたが、社会人で参加している人も多く、時間の都合が合いやすい人でチームを作っている人もいました。 開始前準備 プロジェクトがうまくいくかどうかは良いチームを作れたかどうかにかかっている ので、チーム組成はとても重要だと思いました。営業職、コンサルティングをやっている人からエンジニア、データ分析を仕事にしている人や初学者、学生まで幅広い参加者がいます。チームとしては全体のバランスが大切で、出来ればいろんな多様性をもった人で組む方がうまくいくと思いました。同業者でも良いとは思うのですが、解決策の幅が狭くなってしまう傾向があるように感じました。 また、チームを組んだら、チームの目標と価値観をしっかり決めておくことや顔合わせをしっかりとやってお互いのことを知っておくなど準備をしたほうが良いです。仕事や学業など忙しい中で参加している人が多いので、忙しい時間帯を知ったりして、しっかりコミニュケーションできる関係を事前に作っておくことが大切です。自分が参加したチームも事前に顔合わせをしたり、 自分達のチームのロゴを作ったり 自己紹介資料を準備したりと事前準備をしっかりやりました。 企業とのマッチング チームとしてやりたいジャンルをあらかじめ登録して、プログラム参加企業とのマッチングが行われます。注意点として、必ずしもすべてのチームとのマッチングがされるわけではないので、希望に添えないこともあるということは事前に知っておく必要があります。 マッチングされなかったチームは分析コンペティションに参加する など、自主的に課題に取り組んでいるところもありました。 自分達のチームは四国にある企業とマッチングしました。課題のテーマとしては、 地域活性化とデジタルマーケティング でした。あらかじめ地域企業やりたいテーマを資料でもらって、そこから初回ミーティングをZoomで実施してどんなことがやりたいかをヒアリングしていくことになりました。プロジェクトを進める上でのポイントとして、企業側との技術的なキャップや期待値のギャップはとてもあるので、そのキャップを意識しながら話を進めていくことになります。技術をつかえばどんなことでも出来ると思われているととても大変なので、そのあたりを解消することも大切です。また、企業側のやりたいことが不明確である場合も多く、どんなことがやりたいかを明確にしていくことからスタートして行きました。 企業側はDX推進をやりはじめたばかりなので、 ロードマップ策定をやって今後の方向性を決めることが出来れば ある程度はうまくいったと言えます。企業側とのコミニュケーションをはじめるにあたってはなるべく信頼関係を作れるようにすることを意識しました。各チームメンバーと企業側の担当者の方の自己紹介をお互いにやって、スムーズにやりとり出来るよう心がけました。 地域企業協働プログラムの取り組み ワークショップ開催 企業側との打ち合わせは毎週土曜日に設定して打ち合わせを重ねて行きました。チームで話し合って、 アイディアを広げるワークショップを自主的にやろう ということになり、プロジェクトに参加する全員でアイディア出しをしました。特に、ワークショップはチームから提案してやることにしました。その結果として、企業側と打ち解けることも出来てやって良かったです。ワークショップをやることは、実際の解決につながるかどうかは不明確なところもありますが、シンプルにアイディアをワイワイと話すのは楽しいので仲良くなる目的として成功したと思いました。 その後はより具体的に地域活性化のアイディアを考えていくために、リサーチをしたり、ヒアリングをして行きました。 地域のことは知らないことも多く、観光や産業や歴史など幅広く調査をしました 。また、ドメイン知識は企業側に聞くと早いことがあり、分からないことは素直に聞くことでたくさんの発見がありました。 提案書作成 チーム内の打ち合わせも平日夜に集まって提案内容を作って行きました。Google Slidesを共有してみんなで編集しながらオンラインで会話しながらやっていました。 チームメンバーは地方に住んでいる人もいたので、基本はオンラインでやりとり しながら進めていました。 企業側は年度初めから新しいサービスを提供することになっていて、その サービス提供に合わせて施策が出来るようなスケジュール を組んで検討して行きました。 現地視察 ある程度、提案内容が固まった段階でやはり 実際に現場を見に行かなとわからない ということもあり、2022年12月にチームメンバーと一緒に四国へ行くことにしました。現地に行ってみると気づくことも多くとても良い経験になりました。さらに、地元の市役所の地域振興担当にもヒアリングを行って、地域の課題もヒアリングしました。最終的にはプログラムの最終発表のためにメンバー全員で四国に行って発表もしました。まとめた内容は企業側からの評判も良かったです。 写真は四国に行ったときの風景です。 報告書 最終的な報告書が経済産業省から公開されているので、 プログラムの詳細についてはそちらを参照 してもらえればと思います。かなりの分量があり各地で受講者が奮闘していた軌跡を知ることが出来ます。 令和4年度 地域デジタル人材育成・確保推進事業 2022年度「マナビDX Quest」現場研修プログラム事例集 まとめ 所感 応募当初はプログラム参加に少し迷いもありましたが、最終的にはプログラムに参加してよかったと思っています。平日夜や土日を使うので少し忙しくはなりますが、その分得ることも多かったです。地域企業協働プログラムに参加したチームメンバーはその後も情報交換をしたりしていて、 プログラム参加したことで新しい交流も生まれた と思いました。また、きっかけがなければは四国に行くタイミングもなかったので、新しく地域とつながるきっかけにもなりました。 関係人口の大切さ 市役所の地域振興担当が言っていたことがとても印象的で、 地域活性は関係人口(実際に住んでいる人ではなく、仕事や観光などで地域を訪れる人)が大切 ということでした。プログラムに取り組んだ自分達のチームはまさに関係人口となって地域を訪れたのでそのことを実感しました。地域企業協働プログラムに参加した企業は報告書を見ると、88社もあったので、プログラムに参加したそれぞれのチームごとの経験があったと思います。 今年も開催 今年度(2023年度)も「マナビDX Quest」は開催することが決まっていて7月中旬頃まで募集しているので 興味をもった方はチャレンジしてみる と普段とは違った体験が出来ると思います。 ※ ここに書かれているのは、あくまでも2022年度のプログラムに参加したときの個人の感想なので、人によっては違う経験をしたり、プログラム内容について 多少の差異や勘違いがあることはご了承ください 。また、教材内容や地域企業協働プログラムについては公開されている情報にもとづいて記事を作成しています。
こんにちは!Insight Edgeの小林まさみつです。 以前からChatGPTが様々なところで話題に上がっていて、とても盛り上がっていますね。 弊社でもChatGPTを活用してどのように価値を生み出すことができるかを日々考えており、業務の10%の時間を使って行なっている勉強会の1つのテーマとなっています。 その勉強会の中で「私の代わりにChatGPTがSlackのメッセージを送信する」アプリを作成しましたのでご紹介いたします。 ※本プログラムでは、実行される処理の内容がChatGPTの回答に依存するため、意図しない処理を実行する可能性があります。ご利用の際は自己責任でお願いいたします 目次 1. 概要 2. 構成 2.1. 構成要素 2.2. 処理の流れ 3. 環境 4. 実装 5. 実行結果 5.1. コンソールとSlack 5.2. 実際に処理されたシェルスクリプト 6. まとめ・今後の展望 1. 概要 現在、ChatGPTを活用した文章生成アプリケーションが様々に存在しますが、その大部分は人との対話やチャット用途に焦点を当てています。 一方で、ChatGPTの能力を活かし、生成されたプログラムを実際に動作させるアプリは前述の用途に対するアプリに比べてあまり探求されていない印象です。 そこで今回は、ChatGPTの潜在能力を最大限引き出す新たな試みに取り組みました。具体的には、ChatGTPに送信された文章の回答だけでなく、その回答をSlackに投稿するプログラムも生成させるようにし、文章の送信からそのプログラムの実行までを一括で行うアプリを開発しました。 アプリの動作イメージ 本アプリでは以下のような動作をイメージして作成していきます。 コンソールに、SlackのチャネルIDと投稿したい内容を生成する文章を入力する 投稿したいチャネルIDを入力してください:D03TDUPPQMP 投稿したい内容を入力してください:食事に誘って Slackにメッセージが投稿される 2. 構成 アプリの構成は以下の通りです。 2.1. 構成要素 登場する要素は以下の通りです。 コンソール:今回はコンソール上でアプリを動作させます。 GPTアプリ:コンソールから受け取った文章を元に、OpenAI APIへリクエストを送信し、ChatGPTにより生成されたプログラムを実行します。 OpenAI API: OpenAI社 が提供しているAPIです。今回は LangChain を用いてAPIを呼び出します。 Dockerコンテナ:自身の環境を汚さずに実行したいため、Dockerを用います。 Slack API: Slack のAPIです。メッセージを送信するために用います。 2.2. 処理の流れ 処理の流れとしては以下の通りです。 コンソールでSlackへ投稿したいメッセージの内容をGPTアプリへ入力する。 OpenAI APIへ以下の2つのリクエストを送信する。 コンソールに入力された内容を元に、投稿するメッセージを生成する。 Slackにメッセージを投稿するプログラムを生成する。 OpenAI APIから先ほどの2つの回答を受け取る。 受け取った内容を元に、Dockerコンテナを起動する。 DockerからSlack APIへメッセージ投稿のリクエストを送信する。 Dockerコンテナを削除し、自身の環境を元に戻す。 3. 環境 本システムの環境は以下の通りです。 前述の通り、OpenAI APIを利用するために、LangChainを用います。 MacOS 13.3.1 Python 3.11.1 pip 22.3.1 openai 0.27.7 langchain 0.0.184 Docker 20.10.20 各種APIキーは以下から作成できます。 OpenAI API: https://platform.openai.com/account/api-keys Slack API: https://api.slack.com/tutorials/tracks/getting-a-token ※Slack APIは User Token を作成し、 chat:write をスコープに加えます。 4. 実装 OpenAIは、APIリクエストの内容を保存しない(学習に用いない)としていますが、念の為SlackのAPIキーは送信しません。そのため、環境変数に格納しておき、その環境変数を用いてプログラムを作成するようにしています。 また、プログラムをシェルスクリプトとして生成してもらうことで、Pythonのsubprocessモジュールで直接実行するようにしました。 import subprocess from langchain.chat_models import ChatOpenAI from langchain.schema import ( HumanMessage, SystemMessage ) from langchain import LLMChain from langchain.prompts.chat import ( ChatPromptTemplate, HumanMessagePromptTemplate ) import os import re os.environ[ "OPENAI_API_KEY" ] = "**********" os.environ[ "SLACK_API_KEY" ] = "xoxp-**********" # Slackに投稿するテキスト生成用のLLMChain def create_slack_message (question): chat = ChatOpenAI(temperature= 0 ) human_message_prompt = HumanMessagePromptTemplate.from_template( """相手に対して次の内容を送信してください。 例 Q:今日の挨拶をして おはよう!元気? では、以下の内容でお願いします。 {text}""" ) question_prompt = ChatPromptTemplate.from_messages([human_message_prompt]) question_chain = LLMChain(llm=chat, prompt=question_prompt) answer = question_chain.run(text=question) return answer # Dockerfileを生成し、実行するコード生成用のLLMChain def create_docker_code (): chat = ChatOpenAI(temperature= 0 ) messages = [ SystemMessage(content= "あなたはシェルスクリプト、Docker、Slack APIにとても詳しく親切な人です" ), HumanMessage( content= """ 以下の内容を実行するシェルスクリプトを作成してください。 1. Slack APIを用いて他者にチャットを送るために必要な記述をしたDockerfileをカレントディレクトリに作成してください。 2. また、そのDockerfileを利用してコンテナを起動してください。 3. 2で作成したコンテナを削除してください。 以下の条件を満たしてください。 ・SlackAPIキー:$SLACK_API_KEY(環境変数に設定済み) ・送信先のチャネルID:$CHANNEL_ID(環境変数に設定済み) ・メッセージの内容:$SLACK_MESSAGE(環境変数に設定済み) ・SlackAPIキーはリクエストヘッダに、チャネルIDはリクエストボディに含めてください 回答は、以下の例のように記述してください。 特に、コメントや説明が無くスクリプトのみ記載されていることに気をつけてください。 また、改行コードはエスケープしてください。 ```sh cat << EOF > Dockerfile \\ nFROM alpine:latest \\ nRUN apk add --no-cache curl \\ nCMD curl -X GET -d '{"text":"$QUESTION","channel":"$CHANNEL_ID"}' "https://google.com" \\ nEOF docker build -t google-app . docker run -d -p 80:80 google-app docker rm -f google-app docker rmi google-app ``` """ ), ] return chat(messages).content if __name__ == "__main__" : # Slackに投稿するチャネルIDを環境変数に設定 os.environ[ "CHANNEL_ID" ] = input ( "投稿したいチャネルIDを入力してください:" ) # Slackに投稿するテキストを生成し、環境変数に格納 message_request = input ( "投稿したい内容を入力してください:" ) slack_message = create_slack_message(message_request).replace( " \n " , " \\ n" ) os.environ[ "SLACK_MESSAGE" ] = slack_message # Slackに投稿するためのスクリプトを生成し、その中のコードのみを抽出する ans = create_docker_code() code_block = re.findall( r'```[^\n]*\n(.*)```' , ans, re.DOTALL)[ 0 ] codes = code_block.split( " \n\n " ) # subprocessを用いてコードを1行ずつ実行する for shtxt in codes: subprocess.run(shtxt, shell= True ) ※本アプリはプログラムの生成がOpenAI APIに依存するため、エンジンが更新されたタイミングなどで動かなくなる可能性があります。受け取る回答のフォーマットに左右されないように改善していく必要があります。 5. 実行結果 実行結果は以下の通りです。 Dockerが起動し、実際にSlackへメッセージが投稿されていることを確認できました。 5.1. コンソールとSlack % python gpt.py 投稿したいチャネルIDを入力してください:D03TDUPPQMP 投稿したい内容を入力してください:食事に誘って [+] Building 3.2s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 434B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 3.1s => [1/2] FROM docker.io/library/alpine:latest@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 0.0s => CACHED [2/2] RUN apk add --no-cache curl 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:71d44499df5f6bea3c9bf89a84b59e0a3ceba1042f0dce52b63f4667749cacee 0.0s => => naming to docker.io/library/slack-app 0.0s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them 15e9ef691c891cffe18016ba92c106288cc7e0abc7f61b670cbfa4fd71275c23 15e9ef691c89 Untagged: slack-app:latest Deleted: sha256:71d44499df5f6bea3c9bf89a84b59e0a3ceba1042f0dce52b63f4667749cacee 5.2. 実際に処理されたシェルスクリプト Slackへメッセージを投稿するためのスクリプトです。 catコマンドでDockerfileを生成し、それを元に起動・削除しています。 cat << EOF > Dockerfile FROM alpine:latest RUN apk add --no-cache curl CMD curl -X POST -H "Authorization: Bearer $SLACK_API_KEY " -H "Content-type: application/json" -d \' {"channel":" $CHANNEL_ID ","text":" $SLACK_MESSAGE "} \' "https://slack.com/api/chat.postMessage" EOF docker build -t slack-app . docker run -d slack-app docker rm -f $( docker ps -aqf " ancestor=slack-app " ) docker rmi slack-app 6. まとめ・今後の展望 今回はChatGPTにSlackのメッセージを送信してもらうアプリを紹介しました。本アプリの作成を通してChatGPTの可能性をより実感できました。今後の展望としては、SlackのChannel IDを指定するのではなく、人名やチャネル名などを元に送信先を決定できるようしたいと考えています。そうすることでより使いやすくなりそうです。具体的には、Alexaアプリにすることでより簡単にメッセージを送信できるようになります。他にも、相手のメッセージに対して自動で返信してくれるようにするのも面白そうです。 本アプリではSlackのメッセージ送信を対象としましたが、他にも様々なコードを実行させることができるので色々試してみたいと思います。
init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: "AMS", useLabelIds: true } }, tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'left', CommonHTML: { linebreaks: { automatic: true } } }); MathJax.Hub.Queue(["Typeset", MathJax.Hub]); } } init_mathjax(); 目次 初めに 提案されたモデルの概要 モデルの問題設定 モデルの意義 提案されたモデル 変数変換後の提案されたモデル 着目している性質 劣モジュラ性 $L^\natural$凸性 証明に必要なLemma 1, Theorem 1 Lemma 1 Theorem 1 最適解が唯一つであることの証明 所感 参考文献 初めに  弊社の分析チームではライトニングトークを社内勉強会の1つとして取り入れており、本稿で解説する論文はその時に私が紹介したものです。勉強会では証明の話はせず、論文の概要をお話しました。 そこで今回は論文で提案されたモデルの最適解が唯一つであることの証明を簡単に解説します。  論文の証明では、まず最適解の候補を2つに絞り、モデルの性質に基づいて1つであることを導いています。着目している性質は$L^\natural$凸性と呼ばれる、極小値と最小値が一致する性質で、劣モジュラ性と関連します。提案されたモデルは$L^\natural$凸性を持つかは明らかでなく、変数を変換したモデルが持っております。本論文では変数変換したモデルの持つ劣モジュラ性により解の更なる絞り込みを行い、変数変換前の提案されたモデルに議論を移すことで証明しています。  以上の内容の解説にあたり、本稿の構成は以下としています。まず提案されたモデルの概要として問題設定やモデル説明をします。次に、本記事で着目している性質($L^\natural$凸性、劣モジュラ性)の定義を述べ、証明に必要なLemma 1やTheorem 1を簡単に説明します。そして最後に、最適解が唯一つであることの証明を見ていきたい思います。 提案されたモデルの概要 モデルの問題設定  問題設定は、著者らが実務で取り組んだ修理部品の在庫管理に由来しています。修理部品は装置の故障が起きなければ使われることはないため在庫は捌きにくいです。そのため長期間保管することになり、保管にかかる費用がかさんでしまいます。しかし、費用を抑えるために在庫量を減らすと、在庫切れを起こす可能性が高まります。万一在庫切れが生じた場合、修理部品を手配できるまでの期間、装置が止まってしまいます。それにより多大な損失が発生することから、在庫切れは避けなければなりません。そこで著者らは必要最小限の在庫量を保管できるよう、装置にセンサを取り付けて解析し、故障予測を行っています。故障予測では、修理部品の必要数と必要になる日にちを予測していますが、予測を外してしまう時もあります。日にちの予測を外すとは、故障する日にちを早め/遅めに予測してしまうことを指しており、保管費用などに影響を及ぼします。また必要数について、少なく予測した場合は在庫切れの可能性が高まり、多く予測した場合は保管費用の増大につながります。特に後者の場合、筆者らは過剰に抱えた在庫を追加料金を支払って発注元に返品し、在庫費用を抑える工夫をしています。本問題は、このような状況における修理部品の管理費用を最小にする発注計画を考えることです。但し、発注には一定のリードタイムはありますが、返品は即日対応であり、修理部品は装置の近くに建設した倉庫に保管しているため修理部品を届ける時間はかかりません。  よって以上をまとめると、本問題は需要予測を用いた在庫管理問題となります。具体的には、需要量や需要のタイミングといった需要予測の情報を援用し、発注量や返却量のタイミングと量を調整して管理費用を最小化する問題に取り組むものです。管理費用とは発注費用、返却費用、在庫の保管費用、そして在庫切れに伴う損失を含みます。また、問題を単純化するために修理物品と倉庫は1種類と仮定しています。    モデルの意義  モデルは、 前節で述べた設定の問題 を解くとともに、不確かであっても需要予測の情報を用いた方が在庫管理にかかる費用が抑えられることを確認するために用いられています。  論文によると、従来のモデルは需要情報が完全に正しいとしていることが多く、需要のタイミングや予測誤差が考慮されることはあまりなかったそうです。また、在庫を大量に抱えてしまった場合、従来は在庫を捌けるのを待つのみで、発注元への返却は考慮されていませんでした。需要のタイミングや予測誤差、発注元への返却を考慮している点が本モデルの新規性となります。  このような在庫最適化はある時刻の発注・返却が次以降の発注・返却に影響を及ぼすため、実行可能解の数が爆発的に増え、解析が難しくなります。最適解を唯一つ持つモデルであること(や本稿でほとんど言及しませんが、効率の良いアルゴリズムを構築できるモデルであること)は解析を簡単にし、運用や費用低減の評価を容易にします。 提案されたモデル 提案されているモデルは以下のようになります(モデルの表記は原文ママ)。 $$ \begin{align} &\begin{split} f_t(\mathbf{a}, \mathbf{z}) = \min_{(z_L, y) \in \mathcal{A}_x} {J_t({\mathbf{a}, \mathbf{z}, z_L, y}) }, \end{split} \\ &\begin{split} J_t({\mathbf{a}, \mathbf{z}, z_L, y}) &= cz_L + c_ry + L(a_{\tau_u}, \dots, a_{\tau_l}, x+z_0-y) \\ &+ E[ f_{t+1}(\mathbf{\bar{a} - \mathbf{\bar{R}}, \it{W}}, (x + z_0 - y - \sum_{\tau = \tau_l}^{\tau_u}R_{\tau} - D^{u} )^{+}, z_1, \ldots, z_L)], \end{split} \\ &\begin{split} \mathrm{where} \end{split} \\ &\begin{split} L(a_{\tau_u}, \dots, a_{\tau_l}, x+z_0-y) &= hE[(x + z_0-y-\sum_{\tau = \tau_l}^{\tau_u}R_{\tau} - D^{u} )^{+}] \\ &+ c_eE[(\sum_{\tau = \tau_l}^{\tau_u}R_{\tau} + D^{u}-x - z_0+y)^{+}]. \end{split} \\ \end{align} $$  $f_t$は時刻$t$から終端時刻までにかかる管理費用の最小値で、この値をとるような発注量と返却量の組み合わせである$(z_L, y) \in \mathbb{Z}_{+} \times \mathbb{Z}_{+}$を求めたいということになります。$z$の添字に使われている$L$はリードタイムを表しており、$z_L$は発注したものが時刻$t+L$に納品されることを示しています。発注や返却は時刻$t$のみで行うわけではないため、実際に求めたい値は各時刻における発注量と返却量になります。 時刻$t$以降の管理費用は、需要量と時刻$t$以前に発注していた物品の納品量に依存するため、それらを表す$\mathbf{a}, \mathbf{z}$の関数になります。$\mathbf{a}={a_{\tau_u}, \dots, a_{\tau_0}}$であり、時刻$t+\tau$における需要量を$a_{\tau}$としています。$\tau$は需要のリードタイムようなものであり、今回の問題設定において$\tau \in [\tau_l, \tau_u]$を満たす$\tau$について、$t+\tau$に需要は発生するとしています。それ以外のタイミングに需要は発生するかもしれませんが、その場合は予測に失敗したことを意味します。また$\mathbf{z}={x, z_{0}, \dots, z_{L-1}}$であり、$x$は時刻$t$における手持ち在庫量としています。  次にモデルの構成要素である$J_t$に着目します。$J_t$はその定義から、時刻$t$にかかる管理費用(最初3項)と、時刻$t+1$から終端時刻までの管理費用$\bar{f}_{t+1}$(最終項)に分けることができます。最初3項は順番に、発注にかかる費用($c$は発注単価)、返却にかかる費用($c_r$は返却単価)、そして在庫に関する費用になります。在庫に関する費用は$L$としてまとめられており、倉庫の保管費用($h$は保管単価)と在庫切れに関する損失($c_e$は損失単価)から成っています。  本稿では上記モデルの最適解が唯一つであることを見ていきます。 変数変換後の提案されたモデル  $v_l = x + \sum_{t=0}^l z_t$、$l = -1, \dots, L$とし、新たに変数$\mathbf{v} = (v_{-1}, v_0, \dots, v_l)$を導入します(変数の表記は原文ママ)。但し、$v_{-1} = x$となります。新しく導入した変数により例えば$z_L = v_L -v_{L-1}$のように記述できるため、 $\mathbf{z}$を$\mathbf{v}$で記述できるようになります。これにより$f_t(\mathbf{a}, \mathbf{z})$から$\bar{f_t}(\mathbf{a}, \mathbf{v})$が、$J_t({\mathbf{a}, \mathbf{z}, z_L, y})$から$\bar{J_t}({\mathbf{a}, \mathbf{v}, v_L, y})$が得られます。 着目している性質 劣モジュラ性  実効定義域が空でない関数$g:\mathbb{Z}^n \rightarrow \mathbb{Z} \cup {\infty}$ が以下を満たす時、$g$は劣モジュラであるといいます。 $$ \begin{align} g(p)+g(q)\ge g(p \vee q)+g(p \land q), \quad p, q \in \mathbb{Z}^n. \end{align} $$ 但し、$\vee, \land$はベクトルの要素ごとに最大値、最小値を出力する演算です。 $L^\natural$凸性  上で定義した関数$g$が以下に示す並進劣モジュラ性を満たす時、関数$g$は$L^\natural$凸であるといいます。 $$ \begin{align} g(p)+g(q)\ge g((p-\alpha \mathbb{1}) \vee q)+g(p \land q+\alpha \mathbb{1}), \quad p, q \in \mathbb{Z}^n, \alpha \in \mathbb{Z}_+. \end{align} $$ 但し、$\mathbb{1}$は全ての要素が$1$のベクトルです。  この性質は離散中点凸性と同値であり、また$g$が整凸性と劣モジュラ性の両方を持つことにも等しくなります。本論文では$L^\natural$凸の持つ劣モジュラ性を用いて、Lemma 1を含め種々のLemmaの証明がなされています。 証明に必要なLemma 1, Theorem 1 Lemma 1 For each $(\mathbf{a}, \mathbf{z}) \in \mathcal{U} \times \mathcal{Z}$ and $t = 1, \dots, T$, the optimal decisions are characterized by $z_L^{*}(a, z) \times y^{*}(a, z) = 0$. このLemmaは最適解の満たす性質を言及したもので、管理費用を最小にする発注量と返却量の積は0になると述べています。この主張をもう少し説明すると、発注量と返却量の両方が正であるときは、返却している分だけ余分に発注していることになり、その分を減らせると言っています。 Theorem 1 a) $\bar{J_t}({\mathbf{a}, \mathbf{v}, v_L, y})$ is $L^\natural-convex$ in $(\mathbf{v}, v_L, y) \in Q$ for each $\mathbf{a} \in \mathcal{U}$ and $t = 1,\dots,T$. b) $\bar{f_t}(\mathbf{a}, \mathbf{v})$ is $L^\natural-convex$ in $\mathbf{v} \in \mathcal{V}$ for each $\mathbf{a} \in \mathcal{U}$ and $t = 1,\dots,T$.  本稿で言及する主張のみ掲載しています。この主張は、提案されたモデルについては不明ですが、変数変換後のモデルは$L^\natural$凸性、つまり劣モジュラ性を持つと言っています。変数変換後のモデルを議論の対象にすると、任意の実行可能解の組に対して、劣モジュラ性が満たす不等式を適用できるため、最適解についての議論ができそうだと分かります。  Theorem 1の証明は$\bar{f}_{t}(\mathbf{a}, \mathbf{v})$の持つ再帰構造に着目した帰納法に基づいています。具体的には、$\bar{f}_{t+1}(\mathbf{a}, \mathbf{v})$が$L^\natural$凸性を持つと仮定し、$\bar{f}_{t}(\mathbf{a}, \mathbf{v})$の内部で再起的に記述される$\bar{f}_{t+1}$が$L^\natural$凸性を持つことと、それに対する期待値や最小化の操作が$L^\natural$凸性を保存することより$\bar{f}_{t}(\mathbf{a}, \mathbf{v})$も$L^\natural$凸性を持つことを導いています。  変数変換は、再帰的に記述されるモデル$\bar{f}_{t+1}$が$L^\natural$凸性を持つことを保証するために行なった操作になります。本稿では言及しませんが、 前に定義した関数$g(p)$ が$L^\natural$凸性を持つならば、$p-\alpha \mathbb{1} \ge \mathbf{0}$となる$\alpha$に対して$g(p-\alpha \mathbb{1})$は$L^\natural$凸性を持ちます(Lemma 2)。変数変換をしなければ、再起的に記述される$f_{t+1}$はイメージ$\mathbf{z}-y\mathbf{e}_1$についての関数となることから$L^\natural$凸性を持つとは限りませんが、$\bar{f}_{t+1}$はイメージ$\mathbf{v}-y\mathbb{1}$についての関数となることから保証されます。 最適解が唯一つであることの証明  Lemma 1より、$J_t$の最適解は「発注量=0」である$(0, y^{*})$または「返却量=0」である$(z_L^{*}(\mathbf{a}, \mathbf{z}), 0)$の2通りになります。両方が同時に満たされる場合は明らかに解が唯一つとなるため、そうならない場合を考えます。最適解が唯一つであることを証明するためには、両方が同時に最適解になり得ないことを証明すればよく、背理法を用います。  同時に最適解になり得ないことを導くために、Theorem 1より得られる変数変換後のモデル$\bar{J_t}$の劣モジュラ性に着目します。劣モジュラ性の式は、実行可能解の組とその組の最小・最大から得られる変数の合計4つを取り扱うことになります。ここで実行可能解の組を上手く選び、「発注量=0」の最適解$(v_{L-1}, y^{*})$と「返却量=0」の最適解$(v_{L-1} + z_L^{*}(\mathbf{a}, \mathbf{z}), 0)$の2つが得られるようにします。そのような実行可能解を劣モジュラ性が満たす式に代入し、以下の式を作ります。 $$ \begin{align} &\begin{split} \bar{J_t}({\mathbf{a}, \mathbf{v}, v_{L-1}, y^{*}}) - \bar{J_t}({\mathbf{a}, \mathbf{v}, v_{L-1}, 0}) \ge \\ \bar{J_t}({\mathbf{a}, \mathbf{v}, v_{L-1} + z_L^{*}(\mathbf{a}, \mathbf{z}), y^{*}}) - \bar{J_t}({\mathbf{a}, \mathbf{v}, v_{L-1} + z_L^{*}(\mathbf{a}, \mathbf{z}), 0}) \end{split} \end{align} $$  ここで代入している変数が最適解であることから、左辺は非正であり、右辺は非負となることから不等式は成立しなくなります。「発注量=0」と「返却量=0」のときは両辺が一致しますが、本節の冒頭で述べたようにその場合を除外しています。よってTheorem 1に反することから、$\bar{J_t}$の最適解は唯一つになります。  $\bar{J_t}$と$J_t$の実行可能解は1対1に対応していることから、$J_t$の最適解も唯一つであることが示されます。 所感  本稿では、不確かな需要情報をもとに在庫管理を行う提案モデルの最適解が一意に定まることの証明を簡単に解説しました。この証明では、変数変換後のモデルが持つ劣モジュラ性と背理法を用いており、比較的シンプルなものになっています。  提案されたモデルの式は、ある時刻の在庫に関する費用の算出にあたって未来の需要を考慮しています。個人的には、これにより在庫の保管費用を過小評価していると思われるため、改良の余地はあるように見えます。また、本モデルの有用性は発注費用や需要の頻度など問題の細かな設定に応じて変わるため、リグレットを使ってモデルを定式化すると面白いと感じています。解の導出は難しくなりますが、バウンドを求められれば、数値実験と合わせることで有用性の見通しが立ちやすくなるように思います。 参考文献 [1]. Topan, Engin, et al. "Using imperfect advance demand information in lost-sales inventory systems with the option of returning inventory." IISE Transactions 50.3 (2018): 246-264. [2]. Fujishige, Satoru, and Kazuo Murota. On the relationship between L-convex functions and submodular integrally convex functions. Kyoto University. Research Institute for Mathematical Sciences [RIMS], 1997. [3]. Kazuo Murota, Discrete Convex Analysis. Hausdorff Institute of Mathematics, Summer School, 2015.
こんにちは!Lead Engineerの筒井です。生成AIが話題ですね。弊社においても生成AI活用の取り組みを進めています。Insight Edgeでは生成AIの活用も含め、住友商事グループ各社の課題解決に取り組む仲間を募集しています!ご興味がある方はぜひ、お気軽に 公式サイトの採用ページ からご連絡ください! さて、ChatGPTを企業で活用する場合、主にAzure OpenAI Appsを通じて利用することになるということもあり、各案件のシステム構築に最近はAzureを活用し始めています。この記事では、Azure Container Apps上にAPIサーバーを構築し、APIキーでアクセス制限をかける方法を紹介します。 概要 今回は前提として、以下のようなケースを想定しています。 Azure上でコンテナをサクッと動かしたい コンテナは2種類あり、相互に通信する。うち1つはAPIサーバーであり、外部からWebアクセスする フロントエンド側を色々試したい事情があり、HTTPヘッダにAPIキーを入れるくらいで簡単にアクセス制御したい 認証機能をアプリ側で実装するのではなく、Azure側に委譲したい Container Appsには組み込みの認証機能があり、とても簡単に各種IdPと連携した認証機能を設定することができます。ただ、APIキーによる認証機能は含まれないため、前段にAzure API Managementを設置することで対応することにしました。また、Azure App Serviceを利用すると、同様の仕組みをもっと簡単に実現することができます。しかし、今回はWebサービスでないコンテナもあるため、Container Appsを採用しました。 というわけで、システム構成はシンプルですが、下図のようになりました。 構築方法 仮想ネットワークを作成する 上図の通り、各通信は仮想ネットワーク経由で行われます。そのため、仮想ネットワークとサブネットを作成し、サブネットにネットワークセキュリティグループを割り当てておきます。ネットワークセキュリティグループには、以下のリンク先を参考に必要なルールを追加します。インターネットから仮想ネットワーク宛のHTTPS通信を許可するルールを追加すれば最低限動作はします。 Container Apps上にコンテナーアプリを立ち上げる Container Apps上にコンテナーアプリを立ち上げます。 まずは、Container Apps環境を作成します。今回はAPI Managementから仮想ネットワーク経由でコンテナーアプリにアクセスさせるため、「自分の仮想ネットワークを使用する」を「はい」とし、仮想IPは「内部」を選びます。 コンテナーアプリ側では、イングレスを下図のように設定します。Container AppsなのでHTTP/TCPやターゲットポートを任意に指定できますね。実際には2種類のコンテナーアプリを作成しましたが、ここではAPIサーバーのみ紹介します。もう一方もやり方は同じです。 API Managementリソースを作成する 事前にAPI Managementに割り当てるパブリックIPアドレスを作成しておき、それからAPI Managementのリソースを作成します。下図のように設定することで、仮想ネットワークに内にリソースを作成し、割り当てたパブリックIPアドレスによりインターネットからアクセスできるようになります。 プライベートDNSゾーン リンク 仮想ネットワーク内でAPI Managementやコンテナーアプリがお互いに名前で通信できるようにするために、プライベートDNSゾーンを作成し、仮想ネットワークに割り当てます。 作成するプライベートDNSゾーンの「名前」には、コンテナーアプリの「アプリケーションURL」のドメイン部分を指定します。 作成が終わったら、先ほど作成した仮想ネットワークを選択して割り当てます。 さらに、レコードセットとして、コンテナーアプリの名前とIPアドレスを対応づけるAレコードを、コンテナーアプリごとに追加します。この時、IPアドレスはどのコンテナーアプリもすべてContainer Apps環境の静的IPアドレスを指定します。 API Managementにコンテナーアプリを割り当てる API Managementの「API」メニューから「Container App」を選択し、コンテナーアプリを割り当てます。さらに、「Subscription required」にチェックすることで、「サブスクリプション」メニューにあるキーをAPIキーとして利用できるようになります。 動作確認 以上で構築が完了しましたので、動作確認をしてみます。 まず、コンテナーアプリに割り当てられているURLは、名前解決もできずインターネットからアクセスすることができません。 次に、APIキーなしでAPI Mangementに割り当てられているURLにアクセスすると、以下のようにエラーが返ってきます。 最後に、APIキーを付与して同じURLにアクセスすると、正常にレスポンスが返ってきます。 まとめ 実際の利用時には、APIキーよりもContainer Appsに組み込みの認証機能を利用することが多いと思いますが、この記事ではAzureの機能を使いつつ、APIキーでアクセス制限をかける方法を紹介しました。なお、App Serviceでは同じことが簡単にできると記載しましたが、その場合はApp Service上にアプリを立ち上げた後、API Managementをそのアプリに紐づけると、ここで紹介したネットワークやDNSなどの設定を全て自動で終わらせてくれるという感じです。この記事が今回紹介したような構成を検討している方の参考になれば幸いです。
梅雨の時期でジメジメしてきましたね。なかなか外にでかけづらいので休日はティアキンに精を出したいと思っているエンジニアリングマネージャの猪子です。 ある程度経験を積んだエンジニアであれば、過去何回か案件や通常業務で利用する技術の選定をしたことがあるかと思います。 本記事ではInsight Edgeにおける技術・アーキテクチャの採用指針や実際に採用した技術について紹介したいと思います。 採用技術・アーキテクチャを決める軸 企業でメインとして利用する技術や案件で採用するアーキテクチャを決める為の基準は非常に重要で、判断を間違うと著しく開発効率が下がったり、更に悪い状況だとサービス継続が危ぶまれる場合もあります。 これまで、幾つかの技術を採用してきましたが、私が新規に技術を採用する際の観点は以下にまとめられるかと思います。 観点 内容 ビジネス目標との整合性 選定する技術は企業のビジネス戦略と一致しているか。例えば、高度なデータ分析を必要とする企業であれば、より高度な機能を持つデータレイク、データストアなどのツール / サービス選定が必要です。 非機能要求 機能だけでなく、アプリケーションのパフォーマンス要件、セキュリティ要件、信頼性要件等、非機能面での技術的な要求に対応できるかという点です 費用対効果 採用する技術のコストは、その技術が提供するビジネス価値に対して適切かどうか。直接的な調達コストだけでなく、メンテナンスやトレーニングのコストも考慮が必要です。 開発者との親和性 開発者との親和性も大切な要素です。親和性においてはスキル・経験があり、効率的に技術を利用できるか、という側面の他に、採用の観点を含め開発者がその技術利用したいというモチベーションがあるかという側面もあります 技術の成熟度とコミュニティのサポート 新しい技術を採用する際に技術がまだ成熟していない場合、成熟しているがEOLが近い場合、業界で利用している開発者が少ない場合は注意が必要です(特に言語・FW等)。又、コミュニティサポートや豊富な情報リソースがあるかも要確認です。 全てを完全に満たすものというのは難しいので(基本存在しない)、その時々の状況に応じた観点の優先度を決めつつ評価・評価していく事が必要です。 過去に自分が見た失敗事例でいうと、選定したプログラム言語としては"ビジネス目標との整合性"、"非機能要求"、"開発者との親和性"については合致していたものの、"技術の成熟度"という側面で使いこなせる人材が業界に少数なため、運用保守出来る人材を採用できずサービス継続のために泣く泣くプログラム言語を移行したというものがあります。。。 Insight Edgeの採用技術・アーキテクチャの方向性 Insight Edgeは元々少数のメンバでアプリ開発・データ分析両方の案件をスピード感を持って推進するという"ビジネス目標との整合性"、"開発者との親和性"や"技術的な成熟度"からPythonを選択していました。 フロントエンドについても同様の観点からReact / TypeScriptを採用しています。 ちなみにGitHubが発表している 2022年で最もGitHub上で利用されている言語 の1-4位は上からJavaScript、Python、Java、TypeScriptとなっています。(4つ中3つをInsight Edge内で利用) 元々PythonはML系のライブラリ・機能の優位性からデータサイエンティストを中心にそのシェアを伸ばしてきていると思いますが、近年、ML系技術がさらにコモディティ化しており、今後もWebエンジニアがML系技術を積極利用することは変わらないと思うのでPythonのシェアは高いまま維持し続けるだろうと予想しています。 これらある程度全社共通的な技術を利用しつつ、Insight Edgeでは今後の案件でさらなる開発効率化が見込めそうなものについては積極的に技術を取り入れるようにしています。(目安として、1つの案件で1つは技術的なチャレンジを取り入れるようにしています) このあたりのチャレンジングな技術要素は案件の主担当者のエンジニアに委ねています。 我々の主な目標はPoCの開発であり、PoCではスピードを出しつつ、検証に必要十分な品質を確保するのが重要な要素になります。如何にこれを満たすための最適な技術・アーキテクチャを選定するかが案件をリードするエンジニアの腕の見せどころであり、常日頃からエンジニアも業務の中で新規技術のキャッチアップを行う事が出来るような全社的な取り組みをしています。 採用技術・アーキテクチャ例 これまでInsight Edgeで採用した具体的な採用技術を幾つか紹介します。 業務共通 通常業務で利用しているツール・サービスについてはInsight Edge設立当初に既存メンバが慣れているもの、という観点で決めたものが多いです。 概ね一般的なものが多いですが、WrikeについてはWBS・ガントチャートのUIが心地よくて個人的に気に入って使ってます。 用途 ツール・サービス名 メッセージング Slack ドキュメント管理 Confluence プロジェクト管理 Wrike レポジトリ GitHub クラウドPlatform AWS / Google Cloud / Azure 業務でよく使うものについては、"費用対効果"も重要ですが、開発者がモチベーション高く気持ちよく仕事が出来るか("開発者との親和性")を重視しています! 開発編 Webアプリ Webアプリを素早く構築技術は多種多様であり、Insight Edgeでもスピード感を持ってPoC開発をするために各種技術を使い分けています。又、必要に応じ、仕様の複雑さ、技術的な制約を鑑みてノーコード・ローコードを活用し、出来るだけ"作らない"開発を目指しています。 その他、各種サービスモジュールも多分に活用しています 用途 ツール・サービス名 ノーコード・ローコード Bubble / Power Apps / AppSheet / GAS / GitHub Copilot etc 認証 Cognito(AWS) / IAP(GCP) CICD GitHub Actions ローカル開発環境 Docker Desktop その他 各種クラウドPlatformのサービス等 IoT IoT機器については要件によって各種センサ / 通信プロトコル / 電池等を使い分けるので案件毎で千差万別です。 通信プロトコル(主にLPWA)については、各種ありますが導入のし易さ(基地局設置不要)、通信コスト等の観点から "LoRaWAN", "Sigfox"を採用することが多いです。 データ分析編 モデル + 簡易IF データ分析系の案件では何らかのモデルを構築し、ユーザが利用するための簡易的なIF(画面 / API)を提供することが多いです。 元々はスクラッチで作ることもあったのですが、最近では Streamlit , Mercury 等を使い、JupyterLab等で記載されたプログラムをWebアプリ化することが多いです BI / DWH BIツールはコスト・機能・デスクトップアプリとしてのレスポンス性能で Looker Studio, Tableauを使い分け、MS Suiteとの統合が必要な場合、Power BIも利用しています。 DWHはBigQueryを基本にしつつ、最近はSnowflakeも採用をし始めています。パフォーマンスや、コスト効率、AWSしか使えないが、BigQueryの利用体験をしたい時に採用する想定です. その他 その他継続的にChatGPT、XR等最新の技術トレンドもキャッチアップし、業務・案件の中に取り入れています。 尚、Insight Edgeでは業務時間の10%を活用し、これらの技術トレンドのキャッチアップ等自己研鑽に取り組む"勉強会"の制度を設けています。 勉強会は業務に直結しないテーマもOKで、エンジニアだけではなく営業やコンサルタントの人も参加し、自由な発想や創発が生まれる場としています。 終わりに 如何だったでしょうか?Insight Edgeは、カイゼンのマインドを持ち日頃から最適な技術を調査・選定するのが好きなメンバが集まっている会社です。 技術を活用した効率化が好き!新規技術にも取り組んでいきたい!という方はカジュアルにお話させて頂ければと思いますので、お気軽に こちら からお申し込みください!
Insight EdgeのLead Engineerの日下です。 弊社ではちょっとしたWebアプリを作るときに、AWSを用いたサーバーレスアーキテクチャで フロントエンド CloudFront + S3 + SPA(React等) バックエンド API Gateway + Lambda という構成をしばしば使います。 今回は、この構成においてありがちなキャッシュによるバージョン不整合の対策について紹介します。 SPAにおけるキャッシュ問題 上記の構成は安価かつスケーラブルにSPAを運用できることが魅力ですが、 フロントエンドの静的ファイルに対してブラウザのキャッシュやCloudFrontのエッジキャッシュが働いてしまい、 アプリの更新がうまく反映されなかったり、フロントエンドとバックエンドのバージョン不整合の原因になることがあります。 jsやcssファイルにはハッシュ値が付与されるものの、呼び出し元であるindex.htmlにキャッシュが効いてしまうとjsやcssも古いファイルが参照されるため、 それによってキャッシュされたものが呼び出されたり、リンク切れが発生したりしてしまいます。 デプロイのたびに CloudFrontのキャッシュを削除(Invalidation)してもブラウザのキャッシュには対策できない ため ユーザー側でフルリロードしなければ最新化されずバージョン不整合などの原因になります。 アプリの処理としてバージョン整合性チェックを実装する方法もありますが、今回はお手軽な方法として、 index.htmlファイルにCache-Controlを設定してキャッシュを無効化する方法を紹介します。 S3のオブジェクトメタデータにキャッシュ動作を設定する CloudFront + S3 で配信するファイルは、S3のオブジェクトメタデータにCache-Control等を設定することでHTTPヘッダに反映できます。 マネジメントコンソールで確認・設定する場合、index.htmlのファイルの詳細画面にて プロパティ タブの メタデータ の項目に設定します。 S3のオブジェクトメタデータ設定 デプロイ時にAPIで設定 自動デプロイに組み込むためにAWS CLIでもやってみます。 CLIにはオブジェクトメタデータのみを編集するコマンドが無いため、以下のように aws s3api copy-object を使用してメタデータを編集します。 その際、Content-Typeなど他のメタデータも明示的に指定しないと失われてしまうため、 --content-type オプション等で指定しています。 # 既存のオブジェクトにメタデータを設定 aws s3api copy-object --bucket your-web-contents-bucket --key index.html --copy-source your-web-contents-bucket/index.html --metadata-directive REPLACE --cache-control "no-cache, no-store" --content-type "text/html" このコマンドは既存オブジェクトのメタデータを編集できますが、 aws s3 sync 等でファイルをアップロードした後にメタデータ編集を実行する手順だと、そのタイムラグの間にキャッシュ設定未反映のファイルがユーザに配信されてしまう可能性があります。 アップロードと同時にキャッシュ設定を反映させるには、先にindex.html以外を aws s3 sync で更新し、 最後にindex.htmlを aws s3 cp コマンドでメタデータ設定とともにアップロードすると良いでしょう。 # index.html以外をアップロード aws s3 sync ./build s3://your-web-contents-bucket --exclude index.html --delete # index.htmlをメタデータ設定とともにアップロード aws s3 cp ./build/index.html s3://your-web-contents-bucket/index.html --metadata-directive REPLACE --cache-control "no-cache, no-store" --content-type "text/html" CloudFront経由で配信されたindex.htmlのヘッダをブラウザの開発者ツールで確認してみます。 ちゃんと設定されていますね。 レスポンスヘッダ
こんにちは。Insight Edge開発チームのntです。前回の投稿 1 では、事業案件や技術的な話について紹介しましたが、今回はInsight Edgeの社風に焦点を当てます。 Insight Edgeのバリューの1つに「みんなでやる」という考え方があります。そのバリューを実現するために、チームワークを高めるための活動のひとつとして、弊社分析チームの善之さん( yoshiyuki555 )らと共に企画して開催したシャッフルランチ会です。 以下、その開催レポートです。 はじめに 仕事上のチームビルディングや新しい人間関係を築くために、飲み会や最近ではランチ会などの社内イベント企画が多いかと思います。ランチ会とは、社員同士でグループを組み、会社がランチ代を補助してランチに行くことができる制度です。 Insight Edgeは2019年に創業して以来、社員が順調に増えています。しかし、創業間もなくコロナ禍に見舞われ、安全第一の観点からテレワーク環境が増えました。成果につながるためには、フィジカルなコミュニケーションの機会を確保する必要があります。そのため、出社によるコミュニケーションの活性化が重要と考え、火曜日と金曜日を出社推奨日とし、その他の日でも出社が可能としています。一方で、同じ事業案件を担当している人や、何らかの用事がある人以外とは、会話が自然に発生することが少ないという課題がありました。 旧ランチ会企画とその課題 以前、コミュニケーション活性化や異なる組織ラインの交流促進のためにランチ会を導入しました。補助利用には条件があり、異なる組織ラインで4名~6名程度のグループを組む必要がありました。開催の流れは、Slackで「今日会社来ている人でランチ行きませんか?」と声をかけ、メンバーでランチに行く形式でした。1カ月間の運用後、次のような課題が浮上しました。 ランチ会を誘う人の心理的負荷が高い ランチ会を利用するメンバーに偏りが生じ、期待するほど活性化の効果が得られなかった この問題を解決するため、新しいランチ会企画を立ち上げました。以下では、企画の流れやアンケート結果について詳しく説明します。 ランチ会企画の流れ ランチ会企画の準備期間は1カ月で、実際にランチ会を3カ月間運用しました。最後にアンケートを実施し、振り返り評価しました。 自身の問題意識 私がこの問題に取り組む理由は、出社時に声かけや雑談をするものの、コミュニケーション範囲に限界を感じていたからです。接点数(=雑談した人数)をシステマチックに拡大するアイディアで効果が得られると考えました。マネージャーと週次の1 on 1でアイデアを提案し、別の組織ラインからのメンバーも参加し、運営チームを立ち上げました。 運営チーム結成・課題認識・打ち手検討(1週目) 運営チームは、開発チーム1名(私)、分析チーム1名(善之さん)、マネージャー1名の合計3名で結成されました。企画効果を定量的に振り返ることができ、形骸化しないよう配慮しました。以下の問題解決のため課題や要件を定義しました。 目的:コミュニケーション活性化 前提:コミュニケーション活性化は、社員同士の接点が増加している状態を意味する。ランチ会に参加することで、社員同士の新たな接点が生まれる。 手段:ランチ会企画の運営により、社員全員が偏りなくランチ会に参加し雑談できる環境を整え、接点数を効率的に最大化する。 企画の要件: 参加対象:社員全員 参加回数:各社員が3回参加(月に1回、3ヶ月間) 取りまとめ:各社員が1回ずつ取りまとめを担当し、負荷を分散させる。 グループ人数:1グループあたり4~5人 組み合わせ方法:最適化アルゴリズムを実装する。 開催期間・組み合わせ案:3ヶ月分の開催時期と組み合わせ案は事前に指定する。 課題認識が一致した後、次週から企画準備タスクに取り組み始めました。 ランチグループ及び参加者の組み合わせ方法(2~3週目) 最適化アルゴリズムを使って、社員同士のランチ会の組み合わせ案を作成しました。 まず、社員の組み合わせ表(接点の有無のマトリックス)を作成。各チームリーダーに協力を得て、接点があるペアには1、ない場合には0と記入。センシティブな情報なため社内公開は見送りました。 次に、最適化アルゴリズムを以下の要件に従って実装: 現状の接点組み合わせを入力 同じグループにマネージャーは1人まで 開催することでグループ内の社員同士の接点を増やす 上記を3回反復して全体の接点数を最大化 実装は善之さんが担当。出力結果をもとにGoogleスプレッドシートでランチグループ管理表を作成し、全員へ展開。調整や記録が容易になります。 社内決裁や、参加者にランチ会について周知するために用いる企画資料の作成も行いました。これで準備が整いました。 企画の承認(3週目) 社内決裁は運営マネージャーが取りまとめ、迅速に承認および経費予算の決裁を得ました。 シャッフルランチ会の運用(4週目~(3ヶ月間)) 運用フェーズでは以下を実施しました。 運営側: 企画案内・周知 月に1回各グループの推進を依頼 参加者側: 合計3回参加(取りまとめ役を最大1回担当) ランチ時間内に雑談や情報交換 他のチームが行ったお店を候補選定に利用 以上で、シャッフルランチ会が3ヶ月間進みました。 振り返りと評価 シャッフルランチ会の効果を調査するため、アンケートを実施しました。 アンケート設計 アンケートで得たい情報は以下です: 効果についての定量的評価 ランチ会の改善ポイント 他のアイディアがあるか Google Formsで1週間の記名式アンケートを行いました。 結果と今後の改善点 回答率は74%。結果サマリは以下の通りです。 質問 結果サマリ ランチ会で新たな接点が作れたか? 全員が新たな接点を作ることができた ランチ会で不安や抵抗感が減ったか? 全員不安や抵抗感が低減、最も多かった回答は「かなり減った」 新たに話せるようになった人数 目標と比べて若干少なかったものの、平均して複数名との接点が作れていた 気軽に話せる人数 全員一定数いるものの、まだ増加余地あり ランチ会の頻度、継続する場合の頻度 月1回がちょうど良い。継続するなら1ヶ月に1回前後が適切 改善点(自由記述) 実施負荷軽減、チーム編成 他の企画アイディア(自由記述) 交流機会増加、社員のプロフィール拡充 具体的な数値や考察はここでは省略しますが、ランチ会が新たな接点作りやコミュニケーションの不安減少に効果がありました。 まとめ ランチ会開催による検証結果は以下のとおりです。 アンケート調査によれば、チームビルディングや社内コミュニケーションが向上しました。 コミュニケーション改善を継続するために、ランチ会を引き続き実施することが望ましいです。 ランチ会を継続する際は月1回程度が理想的であり、実施負荷の軽減やチーム編成の改善も検討が必要です。 Insight Edgeの社内コミュニケーション向上取り組みが、同様の課題を持つ組織にとって参考になれば幸いです。 また、Insight Edgeは社員が自ら意見を述べ、成果向上のために柔軟に組織を変革できる環境です。この柔軟さを活かし、会社を共に盛り上げてくれるメンバを募集しています。 興味がある方はカジュアルにお話させて頂ければと思いますので、お気軽に 公式サイト の採用ページからお申し込みください! Google Sheets + Google Apps Script でローカル開発・本番デプロイ ↩
こんにちは! Lead Data Scientistの梶原(悠)です。 Insight Edgeには商社内の資源系ビジネス部門から市況・需要予測系の相談が多くよせられます。 しかし、この種の案件は予測モデリングの本質的な難易度とユーザーからの期待値のずれが大きく、なかなか有効な活用に繋がりにくい印象があります。 こうした現況の改善に向けて技術的な論点は色々あるのですが、今回は、市況が急変するなどしてデータの分布が大きく変わるケースの対処をテーマに、簡易なツール調査を行います。 目次 ドリフトとは ドリフトの検出ツール 検出デモ まとめ データドリフトとは データドリフトは、時間の経過によって特徴量の分布が変化してしまう現象です。 例えば、金属価格を予測する機械学習モデルを訓練し、継続的に運用するサービスを考えます。 このモデルの説明変数の分布は、イノベーションや地政学的なショックにより変化する可能性があります。 学習時点では現れなかったようなサンプルが頻出すると、予測の信頼性が悪化する可能性があります。 関連する概念として、コンセプトドリフトやラベルドリフトなどが挙げられます。 概念 継続的運用やオンライン学習の文脈 バッチ学習の文脈 説明変数と目的変数の関係の変化 コンセプトドリフト(Concept drift) コンセプトシフト(Concept shift) 目的変数の分布の変化 ラベルドリフト(Label drift) ラベルシフト(Label shift) 説明変数の分布の変化 データドリフト(Data drift) データセットシフト(Dataset shift) / 共変量シフト(Covariate shift) データドリフトの影響を緩和するために、定期的なデータの監視とモデルの再学習が有効です。 運用環境のデータと訓練データとの間で分布の差異を監視することで、ドリフトの早期検出が可能になります。 ドリフトの検出ツール オープンソースのドリフト検出ツールは多数存在します。 使える手法の豊富さや可視化機能の充実度合いなどによる差別化が見られます。 ツール名 ライセンス プログラミング言語 フレームワーク ドキュメンテーション Seldon Alibi-detect Apache 2.0 Python TensorFlow, PyTorch https://docs.seldon.io/projects/alibi-detect/en/latest/ Evidently Drift Detection Apache 2.0 Python scikit-learn https://docs.evidentlyai.com/ TorchDrift MIT Python PyTorch https://torchdrift.org/ Deequ Apache 2.0 Scala, Java Apache Spark https://github.com/awslabs/deequ 検出デモ Seldon Alibi-detectによるシンプルなドリフト検知デモを行います。 確率分布間の距離の指標であるMMD(Maximum Mean Discrepancy)を使ってドリフトを検知するalibi_detect.cd.MMDDriftOnlineクラスを使用します。 ある企業では翌日の金属価格の予測モデルを日次で運用しているとします。 さらにこのユーザーは、説明変数にガス・石油の燃料価格を用いているとします。 これらの変数のドリフトを捉えたいとします。 まず、セントルイス銀行のWebサイトからガスと石油のサンプルデータを取得してみます。 import pandas as pd import pandas_datareader.data as web import datetime tickers = { "PNGASJPUSDM" : "Gas" , "DCOILBRENTEU" : "Oil" } data_df = ( web.DataReader( tickers.keys(), "fred" , start=datetime.datetime( 2016 , 1 , 1 ), end=datetime.datetime( 2023 , 2 , 1 ) ) .interpolate() .dropna() .rename(columns=tickers) ) 可視化してみると、2020年前半の石油価格の落ち込みや2021年からのガスと石油の価格高騰が目立ちます。2020年の落ち込みはコロナショック、2021年からの高騰はウクライナ危機によるものと想像されます。 現在は2019年の1月だとします。過去のデータを参照期間として、ドリフトの検出器を作成します。 検出器の内部では、並べかえ検定によりドリフト検出の閾値が作成されます。 今回のケースでは、並べかえ検定による閾値は小さすぎて実用的でありません。 実際に使う場合は、参照期間のデータの時系列クロスバリデーションなどにより、自分で閾値を作り込む対処が考えられます。 from alibi_detect.cd import MMDDriftOnline # データを参照期間とテスト期間に分割する. now = pd.to_datetime( "2019/1/1" ) ref_df = data_df[data_df.index <= now] test_df = data_df[now < data_df.index] X_ref = ref_df.values.copy() X_test = test_df.values.copy() # ドリフト検出器を作成する. detector = MMDDriftOnline( X_ref, ert= 500 , window_size= 30 , backend= "pytorch" , verbose= True ) 未来のデータをテスト期間とし、検出器を走らせてMMDを算出します。 素朴な参考値として、参照期間で走らせたMMDも算出してみます。 # 参照期間とテスト期間のMMDを算出する. test_df[ "squared_mmd" ] = [detector.score(x) for x in X_test] ref_df[ "squared_mmd" ] = [detector.score(x) for x in X_ref] テスト期間のMMDは、2020年の4月や2021年の10月に参照期間におけるMMDの最大値を超えています。 これは、コロナショックやウクライナ危機による燃料価格の急変を検出していると想像されます。 まとめ この記事では、データドリフトの検出ツールのライトな調査を実施し、燃料価格のデータでMMDによるドリフト検出のデモを行いました。 かなり尻切れとんぼな内容になってしまいましたが、何らかの参考になりましたら幸いです。 学習時と運用時の間でデータの分布が変わってしまう問題周辺は、継続的に調査していきたいと思っています。
  はじめまして! Insight Edge で UI/UX デザイナーとして働いている佐藤と申します。 IT の業界におられる方はご承知の通り、UI デザインツールは様々存在し日々進化をしてきました。 Adobe XD、Sketch、Figma と様々、実務の中で導入し使用してきた中で、コンポーネント作成やプロトタイプ作成、リサイズやレスポンシブデザイン、そしてエンジニアへインスペクト連携する際などの効率性などの視点などから、現時点で最も優れているツールは、Figma が頭ひとつ抜きん出ている印象に感じております。 そこで、この記事では、Autolayout によるデザイン作成などを中心に、使い方や作り方の基礎をお話出来ればと思います。 AutoLayout は業務の効率化に繋がる AutoLayout を使いこなす上での基本的な機能 拡大縮小時に便利なフレーム設定 起点を設定する方法や設定の場所 要素の配置バリエーション バリアント作成をしてさらなる効率化 バリアント機能を使ってボタンの状態変化を簡単に作れる プロトタイプ作成時にも重宝 ChatGPT にも訊いてみた まとめ 参考記事 AutoLayout は業務の効率化に繋がる デザインがある程度決まった後に、或いはプロトタイプを作成する段階で、様々なデバイスでデザインの確認や検証を行うケースがあると思います。共通部品となる要素をコンポーネント化し、かつ中身を AutoLayout によって作成しておくと、部品のリサイズやプロトタイプ作成時において、デザイン業務の効率化や高速化を実現できます。 今回、記事用にサンプルの画面デザインを用意しました。 下記の画像の場合カード部分が共通コンポーネントです。 AutoLayout を使いこなす上での基本的な機能 拡大縮小時に便利なフレーム設定 Figma の インターフェースの項目に「フレーム」というものがあります。 ここで何を基準にして中身を構成するか設定できます。 上のアニメーションで見せたような、横に伸ばして要素を伸び縮みさせる方法はここのメニューを駆使して調整していきます。 上記にある GIF 画像のように、文字量に応じて縦の長さを可変させる場合は「コンテンツをハグ」を、なおかつ横に伸ばす時に本文部分をカード横サイズに合わせて追従させる場合は「コンテナに合わせて拡大」を選択します。固定幅はその名の通りです。これらを応用して組み合わせて、コンポーネントを作成しておけば、いくつも同じ要素が並ぶようなインターフェースを作る際に一気に展開や修正することができます。 起点を設定する方法や設定の場所 先程、見ていた「フレーム」メニューの真下に「オートレイアウト」のメニューがありますね。 ここも作成する上で大変重要で、よく触るメニューです。 「フレーム」&「オートレイアウト」で基本的にはおおよそのレイアウトは完成しますし、要素を揃えたりマージンを共通の数値にしたり、起点を設定したり、とても役立ちます。 余談ですが、私はこの Figma のインターフェース(9つのマトのようなもの)を初めて見た時に、何か操作できるものに直感的には正直見えなくて、気づいた時「え?これ触れるの?」って戸惑った記憶があります。気付くまで、苦戦した記憶があります…。 整列系のメニューが上部にもあるので、感覚で覚えようとしたら遠回りしました。 なので、初心者の方は是非ここを見落とさないようにすると大変良いと思います。 リリース初期から触ってる方や、詳しい方にとっては「そんなの普通に分かるわ!」と言われそうですけど、この仕組みに気付くまで、灯台下暗し状態でした。 気づいた時、これ楽々だな〜と感じたのを思い出します。 ここを理解しておけば、情報設計の構築 → デザイン案用にタタキ台や感覚で作った状態の絵 → 清書を進めながら要素の整列をし精緻化していく → プロダクトの対応デバイスに応じてデザインのリサイズやイメージの作成をする → エンジニアにインスペクト連携する、といった一連の UI デザイン作成の流れを素早く行うことが可能になります。正確な数値で作りたい時や起点をどこにするかの設定にも、一瞬で応えてくれるので便利です。 要素の配置バリエーション 詳細設定の使い方次第で様々な表現が可能になります。ほんの一例ですが画像で紹介しておきます。 バリアント作成をしてさらなる効率化 バリアント機能を使ってボタンの状態変化を簡単に作れる UIデザインを作成していく上で、上記に触れたレイアウトの他に、ボタンの状態の変化やプロトタイプを作ってイメージを確認する時などに役立つのが「バリアント」機能です。 こちらを準備しておくと下記の画像のように、同種のコンポーネントを一つのグループにして、レイヤー名を自動でプロパティ値に設定してくれるので、ボタンの状態変化を表現したりプロトタイプの作成時に便利です。 プロトタイプ作成時にも重宝 プロトタイプやモックを作る時にも非常に便利です。 プロトタイプパネルへ移動した後、対象のコンポーネントを選択して、インタラクションを追加し、挙動に応じてプロパティを変更するだけで、プロトタイプの作成時に、状態変化用に別ページを増やさなくても作ることができます。 ChatGPT にも訊いてみた 昨今もっぱら世の中を賑わせている ChatGPT。 せっかくなので GPT 先生にも、以下のように質問してみました。 解説上手すぎて完全に負けました…(途中で「使っ」で切れてるけど…) 今回は、可視化して説明することに重点を置いたので、自分の言葉で書き始めてまとめており、抜粋して使うこともしなかったのですが、今後は利活用していこうっと…(泣)と感じております。 まとめ 難易度としては、さほど高くない内容ですが、初級の方に向けて参考になればと思っています。 冒頭でも述べましたが、ここ数年のプロトタイピングツール戦国時代の中で、主に私は、並行してAdobe XD や Sketch そして Figma を導入し、実務の現場の中で覚えて参りました。 20年以上デザインの現場にいる者として、Adobe Illustrator や Photoshop のレガシー的なツールに慣れ親しんだ人間としては、ソフトの使い方の観点という意味で最初は難航したものの、実際に手を動かしてマスターするとそれぞれの利点に納得するものです。 そして、その中で「使える」ものはどんどん吸収していくべきだと考えています。 AutoLayout についてもその中の小さな手法に過ぎませんが、日々新しい事を覚えて、面白く感じる、便利に感じる、痒い所に手が届いている、なんて感じる日々を積み重ねる事が、何かを良い方向に変えていく原動力になっていくものと信じています。 大袈裟ですが、それが業務効率化や作成速度の向上に繋がるのであれば、他の新たなキャッチアップに時間を割くことも可能になりますし、時代の流れとして今後は使えるものを上手に使う、Figma の AutoLayout や先に述べた ChatGPT についてもそうですが、そういった「道具」をより上手く使って、効率的に仕事をこなしていくことが求められていくようになっていく気がしています。 本日現在だと、Figma に対応した GPT AI プラグインも出現してきています。便利なモノは積極的に利活用して、良き相棒が自分の側にいるような気分で楽しんで参考にしながら、進化するデザインツールや AI と向き合っていきたいと感じている今日この頃です。 参考記事 Figma auto layout playground (Community) https://www.figma.com/community/file/784448220678228461/Figma-Auto-Layout-playground/Figma-auto-layout-playground Figma tutorial (What’s new in Auto layout) https://www.youtube.com/watch?v=floQKLsWAy4 www.youtube.com  
こんにちは、開発エンジニアの熊田です。入社してから早くも2か月が経ちました。 今回は、AWSに触れる機会の少なかった私が、ある案件のアプリ基盤のリプレイス作業を担当した経験を振り返りながら、運用保守を外部委託するまでの話を書いていきます。 目次 AWSアカウントの分離 背景 - これまで社内共通AWSアカウントで運用していた 新規AWSアカウントを作成 アプリ基盤のリプレイス 課題 - ストレージ不足とデプロイ作業の属人化 対応 - Fargateの導入とドキュメント整備 運用保守の外部委託 ユーザ管理と最小権限 役割の明確化 振り返り ECSではなくLambdaの方がベストだった IaCと自動デプロイ利用による改善余地あり 終わりに AWSアカウントの分離 まず、リプレイス作業するにあたり、既存環境とは別に新環境用のAWSアカウントを用意しました。 AWS Organizationsを利用していましたので、アカウントは「組織の一部であるAWSアカウント」として作成しました。 背景 - これまで社内共通AWSアカウントで運用していた AWSアカウントを分離する背景には、Insight Edge設立初期の案件という特有の事情がありました。 技術検証用AWSアカウントが用意されており、開発メンバは各々そこでAWSサービスを利用して開発作業を行ってきました。 いまでも技術検証目的で利用するアカウントですが、AWS Organizationsを導入する以前ですと、技術検証用AWSアカウントのまま本番利用するものがありました。 今回のリプレイス対象がまさに上記に該当します。これまでは社内メンバが管理していたので特に支障はありませんでしたが、社員の保守工数を下げる目的で外部委託することにしました。 共通アカウント上にあることで問題となるのは、委託先に開示してはいけないシステムとしたいシステムの区別ができないことです。 これに対処するには、別途AWSアカウントを作成する必要がありました。 新規AWSアカウントを作成 そもそもAWS Organizationsは、用途ごとにAWSアカウントを分けるマルチアカウント運用をする際には必須といえるサービスです。 公式サイトによると、AWSアカウントを一元管理するサービスで、1つの管理アカウントと複数のメンバーアカウントで構成されます。 アカウントを組織単位 (OU) にグループ化し、各OUに異なるアクセス ポリシーをアタッチできます。 さらに、メンバーアカウントの一括請求にも対応しています。 「組織の一部であるAWSアカウント」としてアカウント作成する手順は 公式サイト に載っており、簡単に実施できます。 アプリ基盤のリプレイス さてさて、アカウントの準備ができました。 次に必要だったのは、旧環境の構成であるDocker on EC2から、Fargate&ECSへのリプレイスです。 EC2上でコンテナを動かす際に2つ課題が生じていましたので、それらに対応するためリプレイスを実施しました。 課題 - ストレージ不足とデプロイ作業の属人化 まずはストレージ不足による定期的なメンテナンス作業が必要であることがあげられます。サーバレスでない環境ではよく起こる問題です。 Linuxディストリビューションでのバックアップがストレージを逼迫させることがあり、サービスが停止することもありました。 もうひとつの課題は、デプロイ作業の属人化です。 最初にEC2上でコンテナを起動し、そのコンテナ上でソースファイルや学習モデルを更新していくため、初期のDockerイメージと乖離してしまっていました。 また、Dockerfileなども用意されていなかったため、現在使用しているDockerイメージが何をもとに作成されたのか、すぐには把握しきれなくなってしまいました。 最初に構築した人が作業する分にはこれまでの作業を把握しており大きな問題にはなりませんが、他の人が対応する場合はなかなか作業が進められない状況に陥っていました。 対応 - Fargateの導入とドキュメント整備 これら課題に対応するべく、Fargateを使うことにしました。 サーバレスであればストレージ不足に悩む必要もありませんし、諸々のメンテナンス作業からも解放されます。 また、もともとDockerコンテナを利用していたため、オーソドックスなFargate&ECS構成へリプレイスすることにしました。 構成図としては以下のような形になっています。 Application Load Balancer(ALB)の前にNetwork Load Balancer(NLB)を配置しています。 ALBのIPは動的に変わることを考慮して、この構成にしています。NLBにより静的IPを利用できるので、NLBのターゲットグループにALBを設定しています。 今回のアプリは、NLBのIPアドレスを利用してスプレッドシート(GAS)からAPIリクエストするため、上記のようにIPアドレスが変わらないよう対策しています。 構築する際は、こちらのブログを参考にさせていただきました。 Network Load BalancerのターゲットグループにApplication Load Balancerを設定する もうひとつの課題であるデプロイ作業の属人化を解消するために、ドキュメント整備にも力を入れています。 外部委託先の方が困らないようにするためにも、初見の人でもデプロイできる手順書を作成しました。 具体的には、ローカル端末でのイメージ作成、ECRにPush、ECSサービスの更新を実施する手順です。 今回のアプリは本番運用開始から数年経っており、頻繁にデプロイされるアプリでもなかったので、今回はコスト的な観点から自動デプロイは用意しませんでした。 余談ではありますが、ECS Execを利用できるように設定しています。 これにより、ローカル端末からFargateのコンテナへ直接アクセスできるようになります。 SSH接続が不要であり、エラー発生時のトラブルシューティングにも活用できる利点がありますので用意しました。 運用保守の外部委託 新環境の構築が終わりましたので、ようやく運用保守を外部委託する話に移ります。 なお、外部委託するにあたって、NDA(秘密保持契約)は必須ですので、委託先への情報開示は締結後に行います。 マネージャに対応してもらっていましたので、詳細については触れませんが用語の説明を記載しておきます。 NDA(秘密保持契約)とは 相手方に開示する自社の秘密情報について、契約締結時に予定している用途以外で使うことや、他人に開示することを禁止したい場合に締結する契約 (引用元:https://keiyaku-watch.jp/media/keiyakuruikei/himitsuhojikeiyaku/nda/) ユーザ管理と最小権限 システム面の話に戻ります。委託先のメンバが運用保守を行うためには、IAMユーザ、GitHubへのアクセス権限が必要になります。 IAMユーザについては、新しく作成したアカウントでIAMユーザを作成しました。 委託メンバは複数名いたので、グループを作成しポリシーをアタッチしました。 そして、グループにIAMユーザを追加します。 これにより、各メンバのアクセス権限をグループとして一括で管理できるようになります。 なお、グループにアタッチしたポリシーは最小権限に設定しています。 よく目にする用語だと思いますが、「最小特権の原則」に則っています。 セキュリティ強化を目的に推奨されてる原則で、障害や不正による被害を最小限に抑えられる効果があります。 GitHubについては、Organizationを利用しているので、outside collaboratorとして招待しました。 数あるリポジトリのうち一部しか参照してほしくないので、リポジトリごとに招待しています。 実際の作業は、GitHub管理者の方に実施いただきました。 役割の明確化 委託するにあたって、役割を明確にしました。当たり前な話ではありますが、仕事を進める上で役割・責任を明確にすることは重要です。 委託先には何を担っていただきたいか、一方、委託元であるInsight Edgeとしても何を担ったままなのか明確に定義しました。 そのうえで作業フローのイメージを共有することで、双方の仕事が進めやすくなるかと思います。 振り返り 今回の作業ではやらなかったことや、今後やってみたいことがありましたので、それらについてまとめていきます。 ECSではなくLambdaの方がベストだった? コンテナを実行する構成としてオーソドックスなFargate&ECS構成を採用しましたが、リクエストの量、リクエストの時間帯が限定的なことから、Lambda実行にした方が、コストメリットがあったように思われます。 ただし、新環境自体は高スペックではないので、コストの差は微々たるものでした。 それよりもlambdaはコールドスタート問題があり、処理時間が想定より長くなる可能性があったため、今回はUXを優先してLambda利用を見送りました。 今回は検証できませんでしたが、SnapStart等でLambdaのコールドスタートを短縮出来る可能性があるので今後検証してみたいです。 IaCと自動デプロイ利用による改善余地あり AWSサービスの構築はIaCを利用してコード化&自動構築する方法もありましたが、今回はスピード優先としてコンソール画面から環境構築しています。 また、GitHubワークフローなどを用意して、自動デプロイする手もありましたが、今回の案件は開発及びデプロイ頻度が極まれでした。 そのため前述でも触れたとおり、手順書、DockerFileがあれば十分対応できることもあり、コスト観点からGitHubワークフローの用意は行っていません。 今後、追加開発などが始まり、環境構築、デプロイ頻度が増える場合には、それぞれの自動化を検討したいと思います。 終わりに リプレイス作業と外部委託についての話は以上になります。読んでいただきありがとうございました。 Insight Edgeに入社して2か月経ちましたが、非常に充実した日々を過ごしています。弊社には、技術力の高い人たちが集まり、プロジェクトも挑戦的なものばかりです。 最初は私の慣れもかねてスタンダードな作業に取り組んでいました。そして、現在は新規サービスを開発する挑戦的なプロジェクトに関わっています。 前職では会計システム開発にずっと関わっており安定性重視の仕事をしてきましたが、いまは新しいことへ取り組む機会にあふれており非常にやりがいがあります。 いま参画しているプロジェクトでもたくさんの学びがありますので、次回はそのことについての記事を書いてみたいなと思います。