Microsoft Store で配布されているアプリがネイティブアプリかストアアプリ(UWP)かを見分ける方法

ストア形式といえば、忘れ去れてている感がある Microsoft Store ですが、現状ではサン土木すで制限された UWP アプリの他にネイティブ Windows アプリを登録できます。

UWP アプリは、「UWP」は「ユニバーサル Windows プラットフォーム」の略で、iPhone の App Store や Android の Google Play で配布されているアプリのように、安全にダウンロード&インストールしたのち、安全にプログラムが実行される(ユーザーがアプリの権限を不許可にしたりして制限ができるなど)アプリのことです。Windows 8 からの Microsoft 肝いり企画だったわけですが、Mobile Windows の廃止により、その価値は激減しています。

実行ファイルを配布するときに、どれを選ぶのかがややこしいのですが、

  • ストアでUWPアプリ
    一番制限がきついパターンだが、一番安全に配布できる
  • ストアでWindows アプリ
    一応セキュリティ審査/署名があるが、実行はネイティブなので、UWP アプリより少し制限が緩い
  • インストーラーを作って配布
    従来の一般的な配布。ただし、ストアよりも目に惹かれないので、できればストア配布を推奨…とされる
  • EXEファイルを直接配布
    社内での配布の場合はこれで十分なことが多い。 

久しく制限のきつい開発環境≒大手IT会社のハコヅメ環境をやっていないので、今の実情はわからないのですが、社内でツールの制限をかけるときに「何処からダウンロードするのか?」「どのツールを使うのか?」が求めらえるところでしょう。

例えば Line Desktop は Windows アプリ

Microsoft Store で「Line」を検索すると「LINE Desktop」がでてきます。このアプリは従来ならば UWP アプリで作るところですが、このアプリはネイティブの Windows アプリです。

判別が難しいのが難点なのですが、追加情報のところの「このアプリでは次のことができます」の中で「すべてのシステムリソースを使用する」となっていると、ネイティブな Windows アプリです。

一見すると、このアプリが Windows の秘密機能をあれこれやってキーロガーとか個人情報とかを抜きとるように見えますが(実際、できるんだけど)、実はそうではありません。ネイティブの Windows アプリなので「特に制限されてない」だけです。制限はされていませんが、一般的な Windows アプリと同様に、Administor 権限とか System 権限が必要なものは、それが使えるユーザー(管理ユーザー)でしか動きません。

一方で電卓アプリは UWP アプリ

一方で電卓アプリは、UWP アプリとして登録されています。

同じように機能の制限を見ると、「インターネット接続にアクセスする」ことだけが許可されています。

この文言は非常に解り辛いのですが、

  • 「すべてのシステムリソースを使用する」の表示があれば、Windows アプリ
  • それ以外の制限が書いてあれば、UWP アプリ

という違いがあります。前述した通り、UWP アプリとして作られている電卓アプリのほうが安全です。

プロセスを比較する

タスクマネージャで両者のプロセスを見ていきましょう。

LINE Desktop の場合は、各種のプロエスが動いています。

プロセスのプロパティを見ると、「C:\Users\masuda\AppData\Local\LINE\bin\current」のような場所で動いています。

エクスプローラーでフォルダーを見ると、Qt フレームワークを使って書かれていることがわかります。他にも DLL があって、一般的な Windows アプリと同じです。

同じように「電卓」をみてみましょう。

プロパティを見てみると、「C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_11.2405.2.0_x64__8wekyb3d8bbwe」のように、C:\Program Files\WindowsApps フォルダーの配下にアプリケーションが配置されています。

この WindowsApps フォルダーがサンドボックスの役割をしています。このフォルダーは閲覧が制限されていて Powershell などを管理者モードにしないと見ることができません。

ls コマンドなどで、インストールされているアプリの正式名を知ることができます。このそれぞれのフォルダーに UWP アプリの実体が含まれています。

ためしに Temas のフォルダーを見ていきましょう。

この中で使われている DLL や JS コードなどを見ることで、ああ JavaScript で作られているな、とか判断したりするわけです。

カテゴリー: 開発 | Microsoft Store で配布されているアプリがネイティブアプリかストアアプリ(UWP)かを見分ける方法 はコメントを受け付けていません

Semantic Kernel を Windows フォームアプリで使う

「Azure OpenAI Service 入門」のサンプルコードを Semantic Kernel に書き換えるシリーズの第3弾は、Windows フォームを使ってみる、の巻です。

こんな感じで、必要項目を埋めるといい感じのブログ記事を書いてくれるツールを作ります。いわゆるブログ記事の量産ツールではあるのですが、自社製品である架空の「製品ABC」の紹介をブログ記事の中に織り込みます。書籍では第5章にあります。

第8章で、いろいろなツール(スマホ、ブラウザ、JSなど)から使える解説をするのですが、最初に WinForms を持ってきたのは諸々の技術を使うよりも初心者には手っ取り早いからです。私的には WPF で書いたほうが手っ取り早いのですが、まあ、一定の読者層を見込んでというところです。

SemanticKernel パッケージを使う

	<ItemGroup>
		<PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
	</ItemGroup>

画面をデザインする

デザイナで作って、コントロールに適当に名前を付けておきます。

実装するのは「生成ボタン」だけです。

生成ボタンをクリックしたときの処理

/// <summary>
/// 生成ボタンをクリックしたときの処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button1_Click(object sender, EventArgs e)
{

    string blogTheme = textBox1.Text;   // テーマ
    string blogTerms = textBox2.Text;   // 専門用語
    DateTime blogDate = dateTimePicker1.Value; // 作成日
    string authorName = textBox3.Text;  // 作成者
    string attention = textBox4.Text;   // 注意事項
    string additionalInfo = textBox5.Text; // 追加情報

    string prompt = $"""
        テーマ:{blogTheme}
        専門用語:{blogTerms}
        作成日:{blogDate.ToString("yyyy年MM月dd日")}
        作成者:{authorName}
        注意事項:{attention}

        このテーマと専門用語を用いて、詳細かつ情報豊富なブログ記事を作成してください。

        追加情報:
        #追加情報のはじまり
        {additionalInfo}
        #追加情報のおわり

        出力フォーマット:
        #出力フォーマットはじまり

        ■タイトル
        [タイトルをここに記入]

        ■ブログ記事
        [記事の詳細な内容をここに記入]

        作成日:[作成日をここに記入] 
        作成者:[作成者をここに記入]
        ※注意事項 
        [注意事項をここに記入]

        #出力フォーマットおわり

        ブログ記事:
        """;

    var builder = Kernel.CreateBuilder();
    builder.AddAzureOpenAIChatCompletion("test-x", endpoint, apiKey);
    var kernel = builder.Build();

    var result = await kernel.InvokePromptAsync(prompt);
    string generatedText = result.GetValue<string>() ?? "";
    string blogPost = generatedText.Trim().Replace("\n","\r\n");
    textBox6.Text = blogPost;
}

それぞれのテキストボックスから値を取ってきて、プロンプトを作成します。semantic kernel にはプロンプトテンプレートという機能があるのですが、C#の場合はそのまま変数の埋め込みができるので、先にプロンプト自体を作ってしまったほうがわかりやすいでしょう。

プロンプト自体は、半年前に少し工夫したものですが、ポイントとしては

  • 箇条書きにする
  • 見出しに「■」や「#」のマークを付ける
  • AI に入れて欲しいときは「[作成日をここに記入]」のように括弧で括ると適用しやすい

ことです。

書籍にも書きましたが、下手にプロンプトエンジニアリングの本を読むよりも、最近では「○○を出力するためのプロンプトを作ってください」と AI 自身に頼んだほうが、AI が解釈しやすいプロンプトを吐き出してくれます。

区切りとなるコロン「:」も、全角と半角が混在しても大丈夫です。何度か試してみて、補助的な指示を工夫してみてください。

このプログラムを実行すると、次のようなブログ記事が得られます。

カテゴリー: 開発 | Semantic Kernel を Windows フォームアプリで使う はコメントを受け付けていません

カドカワシステムへのサーバー攻撃について(想像を含む)

参考先

ニコニコインフォ https://blog.nicovideo.jp/niconews/225099.html

当社サービスへのサイバー攻撃に関するFAQ | 株式会社ドワンゴ https://dwango.co.jp/news/5088891233107968/

現在のニコニコ動画には課金もしていないし、あまり見ることもなくなって久しいのですが、ニコニコ動画が始まった当初(ハルヒや、文字ぴったんや、初音ミクや、アイマスの「とかちつくちて」のあたりとか)の頃は結構見ていたので、それのお礼も兼ねて考察しておきます。

というか、半田病院のランサムウェアの件とかIT屋としてはなんとか対処したい案件ではあります。遭遇したくはないが、遭遇してしまったときに被害を最小におさえときたい。

現在、ツイッター(新X)で憶測が走り回っていて、いろなものがリツーイト(新ポスト)されてくるのですが、合っているような合ってないような、合ってないようなものが多いので、ちょっとイライラします。イライラを個人にぶつけるのはアレなので(新型コロナ以来、この手の代理戦争はしない、と決めています)、掃き出し口として自分のブログに残しておきます。この手の方法は、心理学的にも行動経済学的にも「システム1を垂れ流しにしない」こととして有効なので、何か別のものに書きつけておくのは良い方法です。意外と、それだけで気持ちがおさまるので。

犯人像を考える

犯人像を考えるのは捜査のプロファイル手法としての常套手段です。というのが「羊たちの沈黙」という小説にあってですね、当時は流行ったのです。実際にFBIで取り入られている手法なのですが(今はよくわかりません)、犯人像を決めてその動機や知識から実際の犯行の手段を想像し、現実の犯行とあわせてみるという考え方です。こうすると、犯人がかなり絞り込めます。

同じようにサーバー攻撃を考えるときに、犯人が何を求めているのか?を考えます。

一般的にサーバー攻撃は、愉快犯、敵対攻撃、ランサムウェアによる身代金、機密情報の奪取(顧客情報など)に分けられます。愉快犯や敵対攻撃の場合、サーバー攻撃は非常に簡単です。システムダウンが目的なので、DDoS攻撃のような単純なものが使われます。相手のホームページに犯行声明を上げたりするパターンもあります。当初、ニコニコ動画が動かなくなっていたときには、DDoS攻撃かと言われいたものですが、犯行声明などがないので「ランサムウェア」ではないか、と思っていました。

ところが、周知の通りランサムウェアの場合は、相手のファイルを暗号化させて身代金を取って復号化する、という手段が必要になります。目的は「身代金=ビットコインなど」なのですから、相手のシステムをダウンさせてはいけません。まして、今回のように復旧に至ってしまっては、サイバー攻撃をした意味がないのです。

角川社内の顧客情報やクレジットカードの情報を抜き出すということも考えられるのですが、その場合でもシステム全体をアウトにする必要はありません。むしろ損です。

社内の機密情報を抜き取りたい(顧客情報を売る、クレジットカード情報をとる、インサイダー取引情報を抜き出す)場合には、できるだけ角川のシステムを生かしておかないといけません。さらに、継続的に情報を抜き出すためには、もっと目につかない形でこっそりとやるのが常套手段です。

情報抜き取りのほうは、これからの調査で、実は5年前ぐらいからやられていた、というパターンも考えられます。で、だいたい抜き取ってしまったので、犯人が遊びで角川のシステムをダウンさせた、とも考えられます。これは、もう少し経ったら解る情報でしょう。

現在のところは、そういう情報がないので、「犯人は、ランサムウェアで身代金をとろうとした」と考えるのが妥当です。

そうなると、システム全体がアウトになった原因はどこにあるのか?ということになります。犯人としてはシステム全体をダウンさせることは望んでいません。むしろ、一部だけを暗号化したかったわけです。そうしないと身代金をとれないですからね。

となると、システム全体に被害が広まってしまったのではカドカワシステムの自責ではないか?と思われるのです。

ネットワーク図を考える

私はカドカワ相手に仕事をしたことがないので、このような想像でネットワーク図を書けるのですが、仕事で関わっている人は書けないですよね。なので、あくまで想像です。先の「ニコニコインフォ」から想像したものです。

「グループ企業が提供するデータセンター内サーバー間の~」の部分が気になりました。どうも提供している会社は一社(Kadokawa connected)で、その会社が一括してさまざまなカドカワのシステムを担っているような雰囲気です。これは、グループ会社全体での作業の効率化にはなるし、情報のやりとりが素早くできるという大きな利点があるのですが、今回のようにサーバーのひとつがやられると隣接するサーバーもやられてしまう、このとき隣接するサーバーが多いと被害も大きくなってしまいます。おそらく、全社のサーバーがひとつに集まっていた(ひとつのネットワークを共有していた)のが被害が大きくなった要因と考えられます。

侵入経路は内部犯行、外部からのアクセス、社員PCのアクセス等が考えられるのですが、戸田病院の例などを考えるとVPN経由で侵入されるパターンと思われます。実際にこの手のサーバー攻撃でランサムウェアが使われる場合はVPN経由が多いのが常です(どこかで円グラフがあるのですが、40%ぐらいはそれです)。

VPNは別の物理ネットワークを仮想的にひとつのネットワークとしてつなげられるという便利さはあるのですが、ある意味でいったんVPNの仮想ネットワークに侵入されてしまうと同じネットワーク内ということなってしまうので、社内ネットワークが乗っ取られやすい状態になってしまいます。

特に、今回の場合は社内の社員PCよりもサーバーにランサムウェアを仕込まれていることから、社外からアクセスする社員SE(あるいはPC)経由でVPNを奪取されたと考えられます。

あと、VPN経由などでサーバーを起動できるのは結構普通にできるので、別に不思議なものではありません。ポートを叩く方式とソフトウェアを使う方式があります。どちらかの犯人側がスクリプトで動かせばよい(社内の別のサーバーで定期的に)ので、その方式かなと思われます。

犯人側からは想定外がおきた

繰り返しになりますが、私見では「犯人側から想定外だった」と考えています。ある意味で、ニコニコ動画をダウンさせる(最初の6/8に発覚したのがニコニコ動画なので、ニコニコ動画のサーバー狙いじゃないかな)つもりだったのが、カドカワの社内業務システムに広がってしまったという現象でしょう。あるいは、その逆かもしれません。

ターゲットとしては、ニコニコ動画のような結構技術的に復旧可能そうな陣営に手を出すよりも、社内業務のサーバーを暗号化してしまって、ちょっとした身代金で済むと思わせたほうが犯人としては儲かりますからね。

被害拡大を防ぐには

カドカワ本体としてもN高などの緊急性の高いもの(一般層からのパッシングが高いもの)は早めに復旧したいところです。幸いにもN高のシステムは復旧が早く(バックアップあるいは再構築手順がうまくなされていた?)現状では支障がなさそうです。

ただし、できることならば、社内業務がやられてしまっても、N高やニコニコ動画には影響がないようにネットワークを組んでおくのがベストと思われます。

一般的には古い対策ではありますが、物理的にネットワークを分ける手段が考えれます。もともと、カドカワの各社グループは別のネットワークだったわけですから、相互をあまり使わない形でネットワークを組むことも考えられます。が、確かカドカワのシステムをAWSに乗せ換えるなどの処置が進めていたため( AWSコスト最適化ガイドブック https://www.hanmoto.com/bd/isbn/9784046053558)このあたりが、社内の仮想化の部分とAWSの仮想化の部分で密接になってしまったのかもしれません。社内の仮想システムの攻撃(おそらくランサムウェアによる社内仮想化ファイルの暗号化)は、犯人にとっては想定外と思われます。メンテナンスシステムの利便性を考えて、ネットワークを共通化する(あるいは管理者IDの共通化?)したことによる弊害ではないかと考えられます。

官庁絡みではありますが、この手のバックアップを守る手段としては、

  • 物理的にHDDを抜いてしまってバックアップを守る
  • 定期的に磁気テープに出力する
  • 相互に関係ない部署(特に財務系、社内業務、B2Cシステム)ではネットワークを切り離す

という手段が取られます。

SE(システムエンジニア)的にもプログラマ的にも今回のサイバー攻撃は、ちゃんと考察したおいてほうがいいかな、と思って記録に残しておきます。もちろん、ニコニコ動画の復旧を応援しながらでもあり、ここまでは私の想像でしかないのですが。

補足ですが、以下のようにプライベートクラウド(社内の仮想システム)の場合はアウトで、パブリッククラウド(おそらくAWSのこと)の運用には影響がなかったということなので、「AWSのほうが安全だった」という結果になっていますね。たまに、ツイッターで逆の意見が多い(プライベートクラウドのほうが安全)という話がでているので、注意してください。

追記 2024/06/23

NewsPicks のスクープが載った模様。ほぼ、これが正解でしょう。既に身代金を払っていて、更に追加を要求されて広がっている、という最悪な状態。これでは KADOKAWA 側を擁護できない…

追記 2024/07/04

追加で身代金を払ったのか定かではないが、流出サイトからは削除された模様。

このツイートの参考先も真偽は明らかではないが、記録のため。

カテゴリー: 開発 | カドカワシステムへのサーバー攻撃について(想像を含む) はコメントを受け付けていません

Semantic Kernel のチャットでスケジュール管理ができるツールを作る

「Azure OpenAI Service 入門」を Semantic Kernel で書き換えるシリーズの第4弾です。

書籍の第8章では、いろいろな実行環境で OpenAI を使ってみようということで、デスクトップやスマホアプリ、ブラウザアプリ、シングルページアプリケーションなど作成しています。色々コードが散ってしまうのが読者…というか筆者が大変だったので「スケジュール管理ツール」1本に絞っています。

一般的なスケジュール管理では、項目を追加・削除するボタンで操作をしますが、このスケジュール管理ツールでは自然言語を使って項目を操作します。「4/1 は休日にして」とか、「4/10 の項目を消して」という具合ですね。あらかじめ、スケジュールのデータを AI 側に保持させておいて、それに対して指示を出すので、正確に変更されるとは限らない!のが最大の欠点でありますが、まあ、チャットツールを作るときの良い練習にはなると思います。

書籍のほうでは、常に成功しているように見えますが、執筆時には成功するように指示文を作るところに苦労しています。

画面はシンプル

画面はシンプルで「送信」と「保存」ボタンしかありません。指示をテキストボックスにいれて「送信」するだけです。

MVVMパターンを使う

MVVMパターンのために CommunityToolkit.Mvvm パッケージをいれておきます。

  <ItemGroup>
	  <PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
	  <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
  </ItemGroup>

ViewModel クラス

コンストラクタはこんな感じ。

    public class PromptViewModel : ObservableObject
    {
        private const string _model = "test-x";
        private string _apikey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? "";
        private const string _url = "https://sample-moonmile-openai.openai.azure.com/";

        private Kernel _kernel;
        private IChatCompletionService _service;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public PromptViewModel()
        {
            var builder = Kernel.CreateBuilder();
            builder.AddAzureOpenAIChatCompletion(
                _model,
                _url,
                _apikey);
            _kernel = builder.Build();
            _service = _kernel.GetRequiredService<IChatCompletionService>();

            this.SendCommand = new RelayCommand(this.Send);
            this.SaveCommand = new RelayCommand(this.Save);
        }

最初にあらかじめスケジュールを送信しておくのがミソです。本来ならば、ここの予定表はファイルから読み込めばいいのですが、端折っています。

        /// <summary>
        /// 最初のプロンプトを送信する
        /// </summary>
        public async void SendInit()
        {
            _history.AddSystemMessage(
                """
                箇条書きで予定表を作ってください。

                予定表のフォーマット:
                - [日付] [内容]

                現在の予定は以下の通りです。
                [予定表はここから]
                - 4/1 入社式
                - 4/2 新人歓迎会
                - 4/3 プログラム研修1
                - 4/4 プログラム研修2
                [予定表はここまで]

                予定表を表示してください。

                """);

            var response = await _service.GetChatMessageContentAsync(
                                           _history,
                                           kernel: _kernel);
            // 応答を取得
            string combinedResponse = response.Items.OfType<TextContent>().FirstOrDefault()?.Text ?? "";
            this.Output = combinedResponse;
            // AIの応答を履歴に追加
            _history.AddAssistantMessage(combinedResponse);
        }

送信ボタンを押した時は、ヒストリも含めて送信します。

        /// <summary>
        /// プロンプトを送信する
        /// </summary>
        public async void Send()
        {
            _history.AddUserMessage(Input);
            var response = await _service.GetChatMessageContentAsync(
                                           _history,
                                           kernel: _kernel);
            // 応答を取得
            string combinedResponse = response.Items.OfType<TextContent>().FirstOrDefault()?.Text ?? "";
            this.Output = combinedResponse;
            // AIの応答を履歴に追加
            _history.AddAssistantMessage(this.Output);
        }

ファイルに保存されるのは、最後の応答だけで構いません。最後の応答に最新のスケジュールが含まれるからです。

        /// <summary>
        /// 最後の回答をストレージに保存
        /// </summary>
        public void Save()
        {
            // ここでは簡便のためメッセージとして表示させる
            var msg = _history.Last()?.Content;
            // 保存ダイアログを開く
            var dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "schedule"; 
            dlg.DefaultExt = ".txt"; 
            dlg.Filter = "Text documents (.txt)|*.txt"; 
            if ( dlg.ShowDialog() == true )
            {
                var filename = dlg.FileName;
                System.IO.File.WriteAllText(filename, msg);
                MessageBox.Show("保存しました。", "AIスケジューラー");
            }
        }

実行してみる

こんな感じに誕生日を追加することができます。執筆時は GPT-3.5で動きが悪かったのですが、GPT-4oに切り替えると結構スムースに指示が反映されます。

カテゴリー: 開発 | Semantic Kernel のチャットでスケジュール管理ができるツールを作る はコメントを受け付けていません

Azure OpenAI Service 本のサンプルを Semantic Kernel で書き直す(チャット編)

Completion(入力候補)の API を使って1回だけ質問する場合はAIの答えを表示するだけで終了するのですが、チャットのようにAIとの会話を進める場合には、チャットの内容を保存しなければなりません。何故、保存しないとダメか?ってのは書籍に書いたので、ここでは、ChatHistory を使えば、AIとの会話を保存できます、とだけ言っておきます。いや、やっていることは、List に追加しているだけなんですが。

Microsoft.SemanticKernel パッケージを追加する

  <ItemGroup>
    <PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
  </ItemGroup>

kernel を作る

using Azure.AI.OpenAI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
    "test-x",
    "https://sample-moonmile-openai.openai.azure.com/",
    Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? "");
var kernel = builder.Build();

ChatHistory を作る

Console.WriteLine("チャットの例");
// チャットの履歴をためておく
var history = new ChatHistory();
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

GetRequiredService メソッドを使って ChatCompletionService のインスタンスを持ってこないといけないのが微妙なところですが、まあこれで動きます。

You(自分)のメッセージ入力はコンソールで、GetChatMessageContentAsync を使い API を呼び出します。会話履歴は hisotry にため込んでいるので、これも一緒に渡します。

while ( true ) {
    Console.Write("You: ");
    var prompt = Console.In.ReadLine();
    if ( string.IsNullOrEmpty(prompt) )
    {
        break;
    }
    // ユーザーの入力を履歴に追加
    history.AddUserMessage(prompt);
    var response = await chatCompletionService.GetChatMessageContentAsync(
                                   history,
                                   kernel: kernel);
    // 応答を取得
    string combinedResponse = response.Items.OfType<TextContent>().FirstOrDefault()?.Text ?? "";
    Console.WriteLine("AI: " + combinedResponse);
    // AIの応答を履歴に追加
    history.AddAssistantMessage(combinedResponse);
}

AI の応答がちょっとややこしいのですが、レスポンスの先頭の要素だけ持ってきて(パラメータによって、複数の回答を得ることができるので)、これを画面に表示します。

AIの回答も履歴に追加して、次の入力を待ちます。

実行してみる

中央林間から東京駅までの道のりを尋ねたものです。

最初にシステムメッセージを履歴に加えておけば、口調や応答の長さなどの調節ができます。

AI の回答を見ながら、結局タクシーで行くという結論を出すわけですが、この試行錯誤は入力候補のような1回だけのプロンプトでは到達できません。このようにチャットを使い複数回 AI とやりとりすることが重要になります。

カテゴリー: 開発 | Azure OpenAI Service 本のサンプルを Semantic Kernel で書き直す(チャット編) はコメントを受け付けていません

Azure OpenAI Service 本のサンプルを Semantic Kernel で書き直す

発売時期的に Azure OpenAI Service の API を直接使っている「Azure OpenAI Service入門」ではありますが、同じことは Semantic Kernelを使って書き換えることが可能です。

もともと、Semantic Kernel は Python の LangChain の .NET版(主にC#ではありますが)なところがあって、生成AIのモデルを問わない形になっています。出版時には、OpenAI社の GPTシリーズが主流であったためのこれに揃えて Azure OpenAI Serviceを活用しているのですが、現在では Google の Gemini など他の生成AIのモデルもあり、同じプログラムでもモデルを切り替えられるのは便利…とは思うんですがどうなんでしょう?

ひとまず、APIとしてはどのAIモデルもAPIをJSON形式で呼び出すようになっているので、そのフォーマットを切り替えるだけで概ねいけそうです。違いとしては、Calling Functionのように他システムと組み合わせたいときのプレ処理・ポスト処理に係る部分でしょう。属にいうRAG(検索拡張生成)と呼ばれる部分です。「RAG」というとちょっと難しい感じもしますが、要するの画像処理のプレ処理やポスト処理にあたります。画像処理を行うときに、プレ処理として2値化やグレー処理、エンボス処理などを行いますが、それと似たような形でテキスト解釈をGPTのAPIに任せて関数をコールバックさせることができます。私の場合、GPTシリーズでしかやったことがないのですが、Gemini などの他の生成AIでも同じことができるでしょう(未確認)。

まずは簡単なところから

簡単なところで、第7章のコードを書き直してみましょう。

Microsoft.SemanticKernel パッケージを追加する

Semantic Kernel はパッケージ「Microsoft.SemanticKernel」を使うので、*.csproj を以下に書き換えます。

  <ItemGroup>
    <PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
  </ItemGroup>

現在のところ最新版は ver.1.14.1 になります。

実は、Microsoft.SemanticKernelパッケージは、Azure.AI.OpenAI パッケージに依存しています。なので書籍で書いたAzure.AI.OpenAIパッケージのもそのままで動くし、Semantic Kernel で書き直したものも動きます。ちなみに、Azure.AI.OpenAI パッケージは beta 版のまま ver.2 に移行しているので、ver.1 はリリース版はない…と見るんでしょうね。やっぱり(苦笑)

従来の Completion(入力候補)を呼び出す

おそらく従来型のCompletion(プロンプトから1回だけ呼び出すもの)の方法を先に示します。

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
    "test-x",
    "https://sample-moonmile-openai.openai.azure.com/",
    Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? "");
var kernel = builder.Build();

最初の Kernel 部分(従来の OpenAIClientに当たるところ)を Builder パターンで作成します。

  1. CreateBuilder でビルダーを作成
  2. AddAzureOpenAIChatCompletion でチャット/入力候補用の設定を追加
  3. Build メソッドで Kernel を作成

という手順です。ここでの「test-x」は、Azure OpenAI Studio で作成したデプロイ名です。

var kernel_args = new KernelArguments(
    new OpenAIPromptExecutionSettings()
    {
        Temperature = (float)0.5,
        MaxTokens = 800,
        TopP = (float)0.95,
        FrequencyPenalty = 0,
        PresencePenalty = 0,
    });

温度や最大トークンなどは、OpenAIPromptExecutionSettings で作成します。先に作成した Kernel に渡すために、KernelArguments でくるんでおきます。このあたり、KernelArguments 内で色々と切り替える(プロンプトテンプレートとか)のですが、ひとまず OpenAI のチャットか入力候補を試したいときはこれで十分です。

Console.WriteLine("通常のプロンプト") ;
var result = await kernel.InvokePromptAsync(
    """
    Azure OpenAIについて詳しく説明してください。
    """,
    kernel_args
    );

Console.WriteLine(result.GetValue<string>());

InvokePromptAsync でプロンプトを呼び出します。

各種パラメータがデフォルト値のままでいい場合は、kernel_args は追加しなくて構いません。応答は、GetValue で string 型にキャストしています。

結果

stream で出しているわけではないので応答が長いのですが、こんな感じで AI から応答が返ってきます。

文章が途中で途切れてしまっているのは、トークン数を800に制限したためで、チャット型式にして「続き」のように要求するか、最大トークン数をもう少し大きめにしておきます。

このあたりの詳しいところは書籍の第7章に書いてあります。

サンプルコードはこちら。ブランチを SemanticKernel にして取得してください。

https://github.com/moonmile/openai-samples/tree/SemanticKernel

カテゴリー: 開発 | Azure OpenAI Service 本のサンプルを Semantic Kernel で書き直す はコメントを受け付けていません

テーブル定義(DDL)から Laravel の web api を ChatGPT で作成する

さらに、ChatGPT でコーディングをするシリーズの続き。

いわゆるスキャフォールディングの手法を使います。CakePHP や Ruby on Rails には、テーブルからコマンドを使って MVC パターンの各クラス&メソッドを生成することができるのですが、何故か Laravel にはありません。いくつか、それっぽいものがあるのですが、実際にやりたいところとして、

  • SQL の create table 文を渡す
  • 適当にリレーションを解釈して欲しい。
  • 出力は Controller/Model を出力して欲しい。
  • Laravel の場合は api.php も必要
  • web api で利用するので、View の blade は必要ない

という要件があるので、通常のスキャフォールディングツールでは過剰なところがあります。特に View の部分はいらないのと、できれば Vue3 の出力までして欲しい、という感じです。

仕方がないので、何かの機会があったら PHP のツールを作ろうと思っていたところなのですが(Laravel が PHP なので…これは仕方がない)、ChatGPT がでてきました。

SQL を渡して、出力を要求する

プロンプト以下のように、SQLをベタ打ち、できるだけ指示を短くしています。

以下の SQL から、指定した店舗内にある商品一覧を表示する。
これを、Laravel の web api で作成して。

--
-- 店舗テーブル
-- 
create table Stores ( 
	id int not null,		-- 店舗id
	name varchar(100),		-- 店舗名
	address varchar(255),	-- 店舗住所
	created_at datetime,	-- 作成日時
	updated_at datetime,	-- 更新日時
	is_delete bool		-- 削除フラグ
);

--
-- 店舗から商品への連携テーブル
--
create table store_product_link (
    store_id int not null,	    -- 店舗ID
    product_id int not null,	-- 商品ID
    stock int,				    -- 在庫数
    created_at datetime,	    -- 作成日時
    updated_at datetime,	    -- 更新日時
	is_delete bool		        -- 削除フラグ
);

以前、GPT-3.5の頃にはうまくいかなかったのですが、GPT-4o ではかなり綺麗に出力されます。

コツとしては、Laravel で出力を要求するところと、SQL のコメントにある「店舗」や「商品」などをプロンプト内に明確に追加することです。ただし、ここの新人教育で使っている店舗や商品の SQL 自体が、GPT-4o で出力したものなので、GPT 自体に読みやすい(内部的に保持している者に近い)形式になっているだけかもしれません。実運用で使われている業界用語を場合はうまくいかない可能性もあります。

そのような場合は、完全に自動生成されるのを期待するのではなく、多少の手作業の時間を残しておいたほうがよいでしょう。そうだとしても、結構面倒な Model 同士の連結なども出してくれるので、最初のテンプレートとしてかなり重宝します。

カテゴリー: 開発 | テーブル定義(DDL)から Laravel の web api を ChatGPT で作成する はコメントを受け付けていません

ER図作成とコードファースト(migrate)に GitHub Copilot を活用する

設計書に ChatGPT を使うシリーズの続き。

以下の手法は、ChatGPT 上でも可能ですが、Visual Studio Code 上で Github Copilot を使ったほうが便利です。現在、自分は ChatGPT と Github Copilot に二重に課金をしている状態なのですが(執筆の関係上というのもあるけど)、通常の開発者ならば Github Copilot だけで十分かもしれません。

テーブル定義(create table)から ER 図を作成する

いわゆる DDL(create table の定義)から、ER 図を作成できる。テーブル作成自体は SQL Server Managerment Studio とか MySQL Workbeanch とかを使っても構わない。この手のツールでは、create table をダンプする機能があるので、それを使ってSQL文を書けばよい。あるいは、手書きでもかまわない。

実際に 10 個程度のテーブルが書いてある。この最後の行当たりで、次のプロンプトを書く。

「これらのテーブルから ER 図を書いて」

これを ChatGPT でやると「ER図のツールがあれば、云々」と文句を言が「mermaid形式で書いて」と頼むと、素直に以下のように erDiagram で書いてくれる。mermaid 形式は、markdown 形式を使って図を書くフォーマットである。

この前後に、「“`mermaid」を入れると、プレビューで ER 図を表示できる。

これを手作業で直しても良いし、そのまま仕様書に貼り付けても良い。

Laravel の migrete を作る

同時に、Laravel の migrate も作ってしまう。

php artisan make:migration create_products_table

このように database/migrations の下にファイルができるようにする。

migrate ファイルに該当する create table の SQL を貼り付けて選択状態にする。

プロンプトで「createに直して」で十分である。手作業で直すよりも圧倒的に早いし、created_at と updated_at を timestamps() に変換してくれる。softDeletes() のほうはたまに失敗するので、手作業で直すとか、何度か生成させればよい。

注意:softDeletes() にすると、deleted_at か is_delete になるので、厳密にしたい場合は指定したほうがいいかも

ChatGPT だと、関連するコードを貼り付けたり言語をしていしないといけないが( ChatGPT のデフォルト言語が Python なので、Python コードが最初に出力されてしまう)、VSCode 上の GitHub Copilot だと、拡張子や前後のコードから判断してくれるらしく、かなりスムーズにコードが生成されることがわかる。

参考先

https://github.com/moonmile/h2w-traning-2024/tree/master/src/laravel/webapi の ER.md あたりを参考にしてください。

カテゴリー: 開発 | ER図作成とコードファースト(migrate)に GitHub Copilot を活用する はコメントを受け付けていません

映画「オッペンハイマー」の感想

原子力学科卒としては、観ておかないといけないなぁと思いつつ、そのままになったていたのだが、時間が取れたので映画館に行った。

結論から言えば、ツイートした通り、同時公開されたときに何故か日本だけ外された(あるいは外した)ことが悔やまれる内容である。宣伝の仕方が不味かったのもそうだけど、宣伝的に原爆実験をしたシーンが表に出てきてしまい、それに反感を覚える日本人(あるいは広島在住者?)が多かったのかもしれない。バービーとのコラボ?っぽいツイートで騒動になったのもそれだろうが、結果的に同時公開しなかったことが悔やまれる。

映画としてはマンハッタン計画の中心人物として持てはやされるオッペンハイマーが、当時の「機密安全保持疑惑」に嵌められたというスタイルを取っており、それが史実かどうかはよくわからない。アメリカ内ので彼の評判も私はよく知らないので、なんとも言えないが、日本側から見ると、

  • アメリカが原爆を開発した。
  • ポツダム宣言以後に、広島と長崎に原爆を落とした
  • アメリカでは原爆は戦争を終了させる人助けとして認知されている

という見方になるが、映画を見るとアメリカから見れば

  • ドイツやソ連に先立って、アメリカは原爆を開発する必要があった
  • ドイツが敗北した後でも、日本の侵攻を防ぐために攻撃する必要があった
  • 政治的な問題として、ポツダム宣言以前に原爆実験を成功させる必要があった
  • 政治的な問題として、威力を示すために、広島と長崎に原爆を落とす必要があった

となっている。映画「オッペンハイマー」では、オッペンハイマー自身の苦悩としてあらわしているものの、実際のところ、

  • ポツダム宣言の前に、原爆実験を成功させる

ことを「成功」と呼び、そこにいた科学者も含めて成功者としてオッペンハイマーを称え狂喜するシーンがある。それにオッペンハイマー自身が応じるわけだが、ここでは

  • 回りの狂喜する声が聞こえない。
  • オッペンハイマーは、自分自身の声をぼんやりと聞いている

という演出がなされる。

直前の原爆実験の秒読みや実験直前の嵐のシーンなどは、なんらかの科学実験を連想させ、その成功を映像とともに観客も喜び出しそうになる(実際、アメリカが歓喜があがったようだ)のだが、その直後の先ほどのシーンを考えれば、それがほんとうに「喜ぶべきものだったのか?」と自問させるところである。

日本人から見れば、大量殺戮兵器としての「原爆」の完成を喜ぶなんて!と思うところだが、当時のアメリカ人からすれば(それはオッペンハイマー自身もそうだっただろう)、原爆による悲惨さ(とくに火傷や後遺症など)は知るべくもない。誰も実際に広島に投下するまでは解らなかった時系列があり、その事実の前では原爆も完成を喜ぶのも無理はない、という感じがする。映画を見ている私達は、原爆の事実を知っているのので、あのシーンに疑問を投げかけることができるが、知らなければそれは「狂喜」しただろう。いや、誰もが喜んだと思われる(殺傷力も過小に見積もられていたし)。

そこで一緒に映画の中で成功を喜ぶ科学者と同じく声を上げたアメリカの観客が、その後で、オッペンハイマーが、黒焦げの子供の消し炭を踏み潰したシーンを、どう見ただろうか?ということである。その落差が非常にうまく演出として効果をあげている。

「トランスサイエンス」という言葉がまさにこの映画にあてはまると思う。いや、アルビン・ワインバーグ – Wikipedia 自身もマンハッタン計画に加わっているので、まさにそれなのだろう。物理学者の世界では、どうしてもこの原爆を作ってしまったという「マンハッタン計画」を歴史上避けられない。おそらく、それはコンピュータを主とするソフトウェア開発者もあてはまる。私の場合は、二重にあてはまるのだが。

追記

いくつかツイッターで検索すると、原作があるそうなので、後で読むことにする。

Amazon.co.jp: オッペンハイマー 上 異才 (ハヤカワ文庫NF) eBook : カイ バード, マーティン J シャーウィン, 河邉 俊彦, 山崎 詩郎: 本

感想として「オッペンハイマーを英雄として描いている」部分が気に入らない方が多いようだが(実際に演じた役者にとっても、「原爆の父」あるいは「原爆」がアメリカの大切な資産として扱っている人が多いらしい)、実際のところ当時のアメリカにとってオッペンハイマーは英雄であったろうし、おそらく今でも英雄的な扱いと思われる。

映画の中でトルーマン大統領が言っているが「恨まれるのは科学者ではなくて、政治家だ」と言っている通り、裁かれるのは当時の政治家であり、おそらく大統領の言葉は、当時のチャーチル首相を模した言葉だろう。敵国(この場合は日本、チャーチルにとってはドイツ)にとって憎まれるのは、当然のことでありむしろ勲章に近いものがある。

が、科学者としての物理化学者としてのオッペンハイマーは、そのような政治屋ではない。という描き方がされている。だから、当時のアメリカ国民から「英雄」とされつつも、原爆を作ってしまったという自責の念があり、それは最後のアインシュタインの言葉の通り、最終的に評価されるということは科学者自身のためではなく、周りが納得いくための儀式でしかない。つまりは、原爆を落とし、その後の被爆者という現実を作ってしまったことに対しても、時間が経過すればそれらの現実味が薄れて、最終的には「原爆の父」であり「泥沼の戦争を原爆でケリをつけた」という認識しか大衆には残っていないのである。

果たして、日本人がそれを受け入れられるかどうかは分からない。少なくとも30年前にこの映画があったらならば、まだ相当数生き残っていた被爆者からの声明がでたであろう。しかし、今に至っては被爆者も減り、当の広島や長崎からも「オッペンハイマー」という映画に対してなんらかの声明が出た(でなかったと思うが?)ようすはない。

そこは、同時上映にならなかたことで逃してしまった残念な点であると思う。

もうひとつ、余談ではあるが、当時の反共という流れ、戦時中はアメリカはソ連との同盟国であり、それと同時に冷戦時代になり「反共」という形で、一気に掌返しが起こる。オッペンハイマー自身が、共産主義に共鳴し、党員ではないが「共産党的な考え方」に共感を覚えるのは無理もない。当時の財閥対労働者、戦時中の資本家上位の風潮に対して、大学教員(教授も含めて)≒労働者というスタイルにならざるをえない。ここは、現在の共産主義とは違うところだ。

このあたりの雰囲気は、いまの大学も変わっていないだろうし、人道主義が優先なのは(同区立法人化したとはいえ)変わってないと思うのだが、さて。国立の授業料の件などでどうなるだろうか?大学紛争時代に戻ってしまうのか、興味あるところである。

カテゴリー: 開発 | 映画「オッペンハイマー」の感想 はコメントを受け付けていません

「BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?」の感想メモ

ベント・フリウビヤ、 ダン・ガードナー著「BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?」 の感想メモです。

サブタイトルに「どデカいことを成し遂げたヤツらはなにをしたのか?」とあるが、巨大プロジェクトの自慢話が書いてあるわけではない。どちらかというと、巨大プロジェクトが如何に失敗しているのか、というのを分析した話である。サブタイトルの付け方に失敗して対象する読者層が間違っているような気もするのが、いわゆる、行動経済学を応用したプロジェクトマネジメントの話になる。

まだ第1章とちょっとを読んだばかりだけども、面白そうなのは確かなので記録を残しておこう。ツイッターだと、消えてしまいそうなので。

参考文献と論文

巻末には参考文献と著者らが書いた論文集が載っている。なので、通常のビジネス本とは違い、なんらかの根拠がある(あるいは偽根拠があるw)ことが示されているので、それらの文献にあたれば数々の発言の再現を確認できるだろう。

Full article: The Empirical Reality of IT Project Cost Overruns: Discovering A Power-Law Distribution https://www.tandfonline.com/doi/full/10.1080/07421222.2022.2096544

ファットテールの図などが載っているメインとなる論文だろう。

フィッティングする数式もある。が、果たしてこれが過剰なフィッティングでしかないのかは分からない。参考にしたプロジェクトは1万件を超えるのでサンプリングとしては十分である。そのデータも公開されているらしい。

第1章は序章

第1章は、いくつかの具体的なプロジェクトの例に過ぎない。「ゆっくり考えて、素早くはじめる」という(たぶん)「ファスト&スロー」の中に書かれている内容の追随になっていると思う。

これは第1章を読んだばかりだけど

  • 失敗学
  • 「アジャイルな見積もりと計画づくり」
  • 「失敗の本質」

あたりが思い浮かぶ。

実は、10年前だったか CCPM を知って、ITプロジェクトに応用しようとして、そのテールの分布を計算していた時期がある。ほぼ同時期(自分より2,3年前になるが)コーン氏が同様のことをやっていて、テールの部分を数式化してマネジメントソフトウェアとして販売していたという実績がある。しかし、現在の彼のサイトを見ると解るが、このソフトウェアはない。実は開発会社はつぶれていて(あまり売れなかったのだろう)、今では小さな?コンサル会社になっている。この手法だが、マネジメントソフトウェアにしてもあまり意味がない。属人性が強すぎるので、テールの分散が広くPM個人に依存してしまうからだ。私個人の経験でも、大きく失敗しないPMは、常に大きく失敗しない個人的な手法を持っている。これは20年著っとの個人的な経験で幾人か知っている。逆に、大きく失敗するPMは常に失敗する。

失敗するPMがあまり顕在化されないのは、一度失敗してしまった(大きく赤字になってしまった)PMはこの業界から一瞬で消え去ってしまうか、あるいはこの著作のように「大きなプロジェクトを任された」という実績にて、次のプロジェクトに参画するためだ。失敗学的な「失敗」を定義されないまま、別の会社のプロジェクトに組み込まれることが多い(いわゆる根性があるとか最後までやりぬくとか体力があるとか、あるいは権力に従うとか)ので、プロジェクトを失敗させやすいPMは常にプロジェクトを失敗させる可能性を含んでいる。

この部分、「BIG THINGS」に書かれているかはわからないのだが、文化的な進化論のひとつである。第2章以降を読み進めるとわかるかなと。

第2章以降は行動経済学に沿う

第2章以降は、行動経済学の各ナッジについて解説することになる。行動経済学が眉唾だと思う人にはちょっと向かないかもしれない。ちょっと言い過ぎ(都合のよい事象を出し過ぎ)な感もあるが、リチャード・セイラー著「実践行動経済学」を読んでいれば大丈夫だろう。

各種の決め台詞っぽい名づけ(「コミットメントの錯誤」とか「戦略的虚偽表明」とか)に引き付けられる向きもあろうが、ここは眉唾してスルーしておくのがベターだ。具体例は、各論文にでてくるだろうから。

「要求仕様の探求学」では、要件定義工程での品質の作り込み(品質の上げ方)の手法が書かれている本である。結構古いのとウォーターフォール開発の頃の著作なので、昨今のアジャイル開発では向かないが、最近の反アジャイル思想の中で、開発途中では品質は上がらない、というような話がでてきたときには「要求仕様の探求学」を出してみるとよい。G.M.ワインバーグの著作である。まずは、「品質とは何か?」をきちんと定義してから、議論してみるのがよい。

2000年頃のITプロジェクトは確実に他業界よりも遅れていたのだが、本書をみていくとプロジェクト進行に関してはITプロジェクトは追いついている印象を受ける。むしろ、2002年から始まるアジャイル開発のノウハウが本書の各章にでてくる。

現時点(2024年時点)で、ITプロジェクトでは成功と失敗(みずほ銀行、COCOAの失敗、ガバメントクラウドの失敗…途中?)の差は大きく、大規模プロジェクトや官庁プロジェクトの失敗が目をひく。で、当たり間のことだが、失敗プロジェクトを見習いたいわけではなく、成功プロジェクトの秘訣を(あるいはプロジェクトを失敗させない要素を)ピックアップしておきたい。

  • 第2章の「早く決めたい衝動」については、アジャイル開発により、まず手を付けてプロトタイプを顧客に見せるという手法がITプロジェクトでは可能になっている。ゆえに、全体を決めなくても、最初の一歩を踏み出すほうがITプロジェクトでは良い。ただし、その後は最初のプロトタイプに縛られない工夫が必要である。官庁系のプロジェクトで大きく失敗するのは、ここの「熟考のし過ぎ」あるいは「官僚の作る5か年計画に縛られる」に原因がある。
  • 第3章の目標をはっきりとさせるは、PMBOKにおけるプロジェクト計画書やプロジェクト憲章にあたる。CCPMでは、目的から各タスク(WBSでもよい)を導き出して無駄なタスクを作り出さない手法がある。本書では「フローチャートを「逆」から埋める」という書き方がされていて、「バックキャスティング」という用語を使う。
  • 第4章は、いわゆる設計で使う「ポンチ絵」のことであり、システム構成図であったりシステム概要であったりする。試作品を作り「イテレーション開発」を行うことを勧めている。
  • 第5章と第6章お場合は、経験から学ぶことと、過去のプロジェクトから計画見積もりをすることを示している。ITプロジェクトでは、PDCAやファンクションポイント法などの見積もり法がある。ファンクションポイント法は今はほとんど使われていないが、過去の似たプロジェクトを参考にしながら目の前のプロジェクトを試算するのはIT業界では普通に行われている。おそらく建築業界よりもプロジェクトの単位が短くなった(WEBプロジェクトでは2,3か月というのがざらである)ので、進化のサイクルが早くなったと考えられる。
  • 第6章で、マイルストーンではなくインチストーンの提案をされているが、アジャイル開発あるいは最近のITプロジェクトでは「チケット駆動」という形でインチサイズの「チケット」が使われる。スクラム開発のバックログがそれにあたる。
  • 第7章は、アジャイル開発の手順そのものである。
  • 第8章のチーム作りに関しては、「ピープルウェア」がある。本書でも「リーン開発」が言及されている。また、IT業界で流行っている「心理的安全性」≒テスト駆動などの手法がある。
  • 第9章は、IT業界が得意とするモジュール化やコンポーネント化の話になる。マイクロサービスやAzure FunctionsやAWS Lambda のサーバーレス技術もそれにあたるだろう。WEB API もこれにあたる。「反復開発」なんて当たり前のようにやっている。

という訳で、残りは「終章」しかないのだけど、BIG THINGSの本に書いてある内容は「行動経済学」がベースになっているわけだが、その現実的な手法としては「アジャイル開発」のさまざまな手法あるいはここ2000年以降のITプロジェクトが培ってきたノウハウや経験に等しいことが伺える。

まあ、それでもみずほ銀行のシステム統合や遅々として進まないガバメントクラウドやデ庁のしぐさもあるわけで、ITプロジェクトだからといって成功するわけではない。ゆえに、失敗プロジェクトに身を投じないだけの思慮をプロジェクトリーダーやマネージャは必要とされていると私は考える。

ちょっと興味深いので、ダニエル・カーネマン著「ファスト&スロー」を読んでから、また追記しよう。

カテゴリー: 開発 | 「BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?」の感想メモ はコメントを受け付けていません