gpt-oss-20bの検証

gpt-oss-20bの検証

gpt-oss-20bの検証

OpenAIがローカルLLMのgpt-ossを公開しました!
今回「gpt-oss-20b」と「gpt-oss-120b/b>」の2つのモデルが公開されており、gpt-oss-20bはなんと16GBのVRAMで動作するモデルになります!!

今回はこの「gpt-oss-20b」の効果検証を実施したため、その際のインプットとアウトプットを紹介しようと思います。
なお、この内容はYouTubeで公開した動画内で実行したものになるので、よければ動画も参考にしてください。
https://youtu.be/UioXhzRkxdM


一般的なタスク

まずは、一般的なタスクです。

ニュース記事を連携して、要約をしてもらいます。

  1. プロンプト
  2. 次の文章を要約してください。
    
    ###ニュース記事
    マクドナルドと「ポケットモンスター」のコラボレーションとして、8月9日から『ポケモンカードゲーム』の限定カード全5種類が配布されている。
    
    マクドナルドとメルカリは共同で転売などの対策を行うとしていたが、連休初日となる9日、マクドナルドには多くの人が殺到し、混乱が発生。
    
    マクドナルド公式アプリには、限定カードの早期配布終了や混雑に対する謝罪文が掲載されるまでになっている。
    
    『ポケカ』コラボ開始前に、マックとメルカリは共同で対策を実施
    今回の「ポケットモンスター」とのコラボレーションは、8月8日から実施。通常期間はピカチュウをはじめとするポケモンのおもちゃがおまけとなっており、『ポケモンカードゲーム』の配布は9日(土)~11日(月)の限定の施策として行われている。
    
    今回のおまけの需要が高いことは認識されており、マクドナルドとメルカリは共同で対策を行うと発表。
    
    マクドナルド側は1人5つまでという購入制限を設けたほか、サイト上で「転売または再販売その他営利を目的としたご購入はご遠慮ください。また、食べきれない量のご注文もご遠慮いただけますようお願いします」と注意喚起。
    
    メルカリ側も注意喚起を行ったほか、悪質な出品の削除を行うと宣言していた。
    
    キャンペーン初日に大きな混乱が発生、各地のマックに人が押し寄せる
    事前の対策をもってキャンペーンがスタートした8月9日。SNS上では、各地のマクドナルドに人が殺到している声が上がった。
    
    その中では、店舗によってはアプリからのモバイルオーダーを行った注文者が受け取り口に殺到しているとの投稿や、カードだけを抜いて商品を捨てている注文者がいるとの投稿も多くされている。
    
    そういった声は連休初日のSNSで大きく注目を集めることとなり、15時ごろにはXのトレンド1位に「ハッピーセット」、5位に「転売ヤー」、8位に「マクドナルド」がそれぞれランクイン。
    
    公式アプリにも「限定のポケモンカードは、多くの店舗で予定より早く配布を終了しております」「楽しみにしてくださったお客様、また混雑によりご迷惑をおかけしたことを、心よりお詫び申し上げます」とのメッセージが掲載されている。
    
    5月には『ちいかわ』ハッピーセットでも混乱が発生
    「ハッピーセット」をめぐっては、5月に行われた『ちいかわ』とのコラボレーションでも混乱が発生していた。
    
    購入制限などの対策を行うも、一部店舗では発売当日に早朝から人が押し寄せ、商品は予定していた期間よりも早く販売を終了。
    
    おまけのグッズがメルカリなどのフリマサイトへ大量に出品されていたこともあり、購入者の多くが転売目的だったのではないかと批判が集中。早期の販売終了に対してマクドナルドが謝罪文を公開するまでになっていた。
    
    ※記事初出時、一部表記に誤りがございました。お詫びして訂正いたします。

  3. アウトプット(抜粋)
  4. 要約
    
    コラボ内容
    
    マクドナルドと「ポケットモンスター」が協業し、8 月 9日から3〜11日にかけて限定の『ポケモンカードゲーム』カード(全5種類)を配布。
    通常はピカチュウなどのおもちゃが付くハッピーセットに加え、期間限定でカード付き。
    
    対策
    
    マクドナルド:1人5枚まで購入制限、転売・再販売禁止の注意喚起。
    メルカリ:悪質な出品を削除する旨を発表し、同様に転売禁止を呼び掛け。
    
    混乱
    
    キャンペーン初日(8 月 9日)に各地のマックへ殺到。
    アプリでモバイルオーダーした人が受取口に集まり、カードだけ抜いて商品を捨てるケースも報告。
    SNS・Xでは「ハッピーセット」「転売ヤー」「マクドナルド」などトレンド入り。
    
    謝罪
    
    マクドナルド公式アプリに「限定カードは早期終了」とのメッセージと、混雑による迷惑への謝罪が掲載。
    
    過去例
    
    5 月の『ちいかわ』ハッピーセットでも同様に混乱・転売批判が起き、早期販売終了を経て謝罪文が公開された。
    
    要するに、ポケモンカード付きハッピーセットキャンペーンで転売対策を取ったものの、人殺到と混乱が発生し、公式アプリで謝罪・早期終了の連絡が行われた。

要約は問題なく処理できています。

続いては同じ会話のまま、要点抽出をさせます。

  1. プロンプト
  2. 先ほどのニュースから要点を3つ抽出してください。

  3. アウトプット(抜粋)
  4. 1. 限定カード配布と転売対策
    
    マクドナルドは8 月 9〜11日に『ポケモンカードゲーム』の5種類を配布し、1人5枚まで購入制限と「転売・再販売禁止」を明示。メルカリも悪質出品削除を宣言。
    
    2. キャンペーン初日の混乱
    
    連休初日に各地で殺到が発生し、モバイルオーダー受取口に押し寄せる顧客やカードだけ抜いて商品を捨てる行為など、SNS・Xで話題になった。
    
    3. 公式謝罪と早期終了の通知
    
    マクドナルド公式アプリに「限定カードは多くの店舗で予定より早く配布を終了」とし、混雑による迷惑への謝罪メッセージが掲載。

会話の流れでも問題なく、対象のニュース記事を判断し、要点抽出をすることができていました。


では、続いてはプログラミング能力を確認します。

C#で基礎コードを記述させます。

  1. プロンプト
  2. C#でHelloWorldを出力するプログラムを作成してください。

  3. アウトプット
  4. 以下は、コンソールアプリケーションとして動かすと「Hello, World!」という文字列を標準出力に表示する最もシンプルなC#プログラムです。
    
    (.NET 6以降の トップレベルステートメント を使った書き方です)
    
    // Program.cs
    
    Console.WriteLine("Hello, World!");
    実行手順(.NET 6+)
    プロジェクト作成
    
    dotnet new console -n HelloWorldApp
    cd HelloWorldApp
    Program.cs を上記コードで置き換えるか、エディタで書き直す。
    
    ビルド&実行
    
    dotnet run
    するとコンソールに
    
    Hello, World!
    と表示されます。
    
    もし .NET Core / .NET Framework の古いバージョンを使っている場合は、以下のように Main メソッドを書きます。
    using System;
    
    namespace HelloWorldApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello, World!");
            }
        }
    }
    まとめ
    トップレベルステートメント(.NET 6+)は Main を明示的に書く必要がなく、コードをより簡潔にします。
    従来の構文でも動作しますので、環境に合わせて選んでください。
    Happy coding!

続いては、奇数偶数の判定プログラムで、少し要求を加えます。

  1. プロンプト
  2. C#で次のプログラムを作成してください。
    ・ユーザーに任意の入力をさせます。
    ・入力値が数値でない場合は、再度入力を求めます。
    ・入力値が数値の場合は、その値が奇数か偶数かを判断し、出力をします。
    ・dotnet6.0以降で実行できるようにしてください。

  3. アウトプット(抜粋)
  4. // Program.cs
    
    using System;
    
    Console.WriteLine("任意の整数を入力してください(例: 42):");
    
    while (true)
    {
        // ユーザーから文字列を取得
        string? input = Console.ReadLine();
    
        // null もしくは空文字なら再度要求
        if (string.IsNullOrWhiteSpace(input))
        {
            Console.WriteLine("入力がありません。もう一度整数を入力してください:");
            continue;
        }
    
        // 整数へ変換できるか確認
        bool success = int.TryParse(input, out int number);
    
        if (!success)
        {
            Console.WriteLine($"'{input}' は整数ではありません。再度入力してください:");
            continue;            // 再びループの先頭に戻る
        }
    
        // 整数が取得できたら奇偶判定
        string parity = (number % 2 == 0) ? "偶数" : "奇数";
        Console.WriteLine($"入力された整数 {number} は {parity} です。");
    
        break;   // 正常に終了したのでループを抜ける
    }

最後に、プログラミングの問題です。

  1. プロンプト
  2. 概要
    あなたはオンライン書店のデータアナリストです。手元には「書籍リスト」「著者リスト」「売上履歴リスト」の3種類のデータがあります。これらのデータを活用して、マネージャーから依頼された以下の3つの分析タスクを達成するC#コンソールアプリケーションを作成してください。
    
    課題
    以下の3つの要件を満たす処理を実装してください。
    
    2024年の売上トップ3書籍: 2024年中に最も売上金額が高かった書籍のトップ3を、売上金額の降順で表示してください。表示項目は「順位」「書籍タイトル」「著者名」「総売上金額」とします。
    
    著者別総売上ランキング: 各著者とその著者が書いた書籍の総売上金額を計算し、売上金額の降順でリストアップしてください。表示項目は「著者名」「総売上金額」とします。
    
    高評価のミステリー小説リスト: ジャンルが「ミステリー」で、かつレビュー評価が4.5以上の書籍をリストアップしてください。表示項目は「書籍タイトル」「著者名」「評価」とします。
    
    テストデータとプログラムの雛形
    ###program.cs
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    // ===== データモデル =====
    public class Author
    {
        public int Id { get; set; }
        public string Name { get; set; } = "";
    }
    
    public class Book
    {
        public int Id { get; set; }
        public string Title { get; set; } = "";
        public int AuthorId { get; set; }
        public string Genre { get; set; } = "";
        public decimal Price { get; set; }
        public double Rating { get; set; }
    }
    
    public class Sale
    {
        public int BookId { get; set; }
        public DateTime SaleDate { get; set; }
        public int Quantity { get; set; }
    }
    
    // ===== メインプログラム =====
    public class Program
    {
        public static void Main(string[] args)
        {
            // テストデータの準備
            var authors = SetupAuthors();
            var books = SetupBooks();
            var sales = SetupSales();
    
            // --- 課題1 ---
            Console.WriteLine("## 課題1: 2024年の売上トップ3書籍");
            SolveRequirement1(authors, books, sales);
            Console.WriteLine("\n------------------------------------\n");
    
    
            // --- 課題2 ---
            Console.WriteLine("## 課題2: 著者別総売上ランキング");
            SolveRequirement2(authors, books, sales);
            Console.WriteLine("\n------------------------------------\n");
    
            // --- 課題3 ---
            Console.WriteLine("## 課題3: 高評価のミステリー小説リスト");
            SolveRequirement3(authors, books);
            Console.WriteLine("\n------------------------------------\n");
        }
    
        private static void SolveRequirement1(List authors, List books, List sales)
        {
    
        }
    
        private static void SolveRequirement2(List authors, List books, List sales)
        {
    
        }
    
        private static void SolveRequirement3(List authors, List books)
        {
    
        }
    
    
        // ===== テストデータ生成メソッド (この部分は編集不要です) =====
        private static List SetupAuthors() => new List
        {
            new Author { Id = 1, Name = "夏目 漱石" },
            new Author { Id = 2, Name = "太宰 治" },
            new Author { Id = 3, Name = "芥川 龍之介" },
            new Author { Id = 4, Name = "東野 圭吾" }
        };
    
        private static List SetupBooks() => new List
        {
            new Book { Id = 1, Title = "こころ", AuthorId = 1, Genre = "小説", Price = 550, Rating = 4.2 },
            new Book { Id = 2, Title = "吾輩は猫である", AuthorId = 1, Genre = "小説", Price = 600, Rating = 4.0 },
            new Book { Id = 3, Title = "人間失格", AuthorId = 2, Genre = "小説", Price = 450, Rating = 4.8 },
            new Book { Id = 4, Title = "羅生門", AuthorId = 3, Genre = "小説", Price = 400, Rating = 4.4 },
            new Book { Id = 5, Title = "容疑者Xの献身", AuthorId = 4, Genre = "ミステリー", Price = 800, Rating = 4.7 },
            new Book { Id = 6, Title = "白夜行", AuthorId = 4, Genre = "ミステリー", Price = 950, Rating = 4.6 },
            new Book { Id = 7, Title = "マスカレード・ホテル", AuthorId = 4, Genre = "ミステリー", Price = 750, Rating = 4.3 }
        };
    
        private static List SetupSales() => new List
        {
            // --- 2024年の売上 ---
            new Sale { BookId = 5, SaleDate = new DateTime(2024, 1, 15), Quantity = 120 },
            new Sale { BookId = 3, SaleDate = new DateTime(2024, 2, 10), Quantity = 150 },
            new Sale { BookId = 6, SaleDate = new DateTime(2024, 3, 20), Quantity = 80 },
            new Sale { BookId = 1, SaleDate = new DateTime(2024, 4, 5), Quantity = 90 },
            new Sale { BookId = 5, SaleDate = new DateTime(2024, 5, 25), Quantity = 60 }, // 容疑者Xの献身 (追加売上)
            new Sale { BookId = 7, SaleDate = new DateTime(2024, 6, 18), Quantity = 110 },
            new Sale { BookId = 2, SaleDate = new DateTime(2024, 7, 30), Quantity = 70 },
            new Sale { BookId = 3, SaleDate = new DateTime(2024, 8, 11), Quantity = 50 }, // 人間失格 (追加売上)
    
            // --- 2023年の売上 (比較用) ---
            new Sale { BookId = 1, SaleDate = new DateTime(2023, 12, 1), Quantity = 100 },
            new Sale { BookId = 4, SaleDate = new DateTime(2023, 11, 15), Quantity = 200 }
        };
    }

  3. アウトプット(抜粋)
  4. // ───────────────────────────────────────────────────────────────
    // program.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    // ===== データモデル =====
    public class Author
    {
        public int Id { get; set; }
        public string Name { get; set; } = "";
    }
    
    public class Book
    {
        public int Id { get; set; }
        public string Title { get; set; } = "";
        public int AuthorId { get; set; }
        public string Genre { get; set; } = "";
        public decimal Price { get; set; }
        public double Rating { get; set; }
    }
    
    public class Sale
    {
        public int BookId { get; set; }
        public DateTime SaleDate { get; set; }
        public int Quantity { get; set; }
    }
    
    // ===== メインプログラム =====
    public class Program
    {
        public static void Main(string[] args)
        {
            // テストデータの準備
            var authors = SetupAuthors();
            var books   = SetupBooks();
            var sales   = SetupSales();
    
            // --- 課題1 ---
            Console.WriteLine("## 課題1: 2024年の売上トップ3書籍");
            SolveRequirement1(authors, books, sales);
            Console.WriteLine("\n------------------------------------\n");
    
            // --- 課題2 ---
            Console.WriteLine("## 課題2: 著者別総売上ランキング");
            SolveRequirement2(authors, books, sales);
            Console.WriteLine("\n------------------------------------\n");
    
            // --- 課題3 ---
            Console.WriteLine("## 課題3: 高評価のミステリー小説リスト");
            SolveRequirement3(authors, books);
            Console.WriteLine("\n------------------------------------\n");
        }
    
        /* ------------------------------------------------------------ */
        /* 1. 2024年売上トップ3書籍                                      */
        private static void SolveRequirement1(List authors,
                                               List   books,
                                               List   sales)
        {
            // ① 2024 年の販売データだけを取得
            var sales2024 = sales.Where(s => s.SaleDate.Year == 2024);
    
            // ② BookId ごとに売上金額(数量 × 価格)を合計
            var bookSales =
                from s in sales2024
                join b in books on s.BookId equals b.Id
                group new { s, b } by b.Id into g
                select new
                {
                    BookId   = g.Key,
                    TotalRevenue = g.Sum(x => x.s.Quantity * x.b.Price)
                };
    
            // ③ 価格と著者情報を結合し、順位付け
            var top3 =
                from bs in bookSales
                join b   in books on bs.BookId equals b.Id
                join a   in authors on b.AuthorId equals a.Id
                orderby bs.TotalRevenue descending
                select new
                {
                    Title  = b.Title,
                    AuthorName = a.Name,
                    Revenue = bs.TotalRevenue
                };
    
            // ④ 出力
            int rank = 1;
            Console.WriteLine("{0,4} | {1,-30} | {2,-15} | {3,12}", "順位", "書籍タイトル", "著者名", "総売上金額");
            foreach (var item in top3.Take(3))
            {
                Console.WriteLine("{0,4} | {1,-30} | {2,-15} | {3,12:N0}",
                                  rank++, item.Title, item.AuthorName, item.Revenue);
            }
        }
    
        /* ------------------------------------------------------------ */
        /* 2. 著者別総売上ランキング                                      */
        private static void SolveRequirement2(List authors,
                                               List   books,
                                               List   sales)
        {
            // 全期間の販売データを Book と結合
            var revenueByAuthor =
                from s in sales
                join b in books on s.BookId equals b.Id
                group new { s, b } by b.AuthorId into g
                select new
                {
                    AuthorId = g.Key,
                    TotalRevenue = g.Sum(x => x.s.Quantity * x.b.Price)
                };
    
            // 著者情報と結合し、降順に並べ替え
            var ranking =
                from r in revenueByAuthor
                join a in authors on r.AuthorId equals a.Id
                orderby r.TotalRevenue descending
                select new { AuthorName = a.Name, Revenue = r.TotalRevenue };
    
            // 出力
            Console.WriteLine("{0,-20} | {1,12}", "著者名", "総売上金額");
            foreach (var item in ranking)
            {
                Console.WriteLine("{0,-20} | {1,12:N0}",
                                  item.AuthorName, item.Revenue);
            }
        }
    
        /* ------------------------------------------------------------ */
        /* 3. 高評価ミステリー小説リスト                                 */
        private static void SolveRequirement3(List authors,
                                               List   books)
        {
            // ミステリーで評価が4.5以上の本を取得
            var query =
                from b in books
                where b.Genre == "ミステリー" && b.Rating >= 4.5
                join a in authors on b.AuthorId equals a.Id
                select new { Title = b.Title, AuthorName = a.Name, Rating = b.Rating };
    
            // 出力
            Console.WriteLine("{0,-30} | {1,-15} | {2,6}", "書籍タイトル", "著者名", "評価");
            foreach (var item in query)
            {
                Console.WriteLine("{0,-30} | {1,-15} | {2,6:N1}",
                                  item.Title, item.AuthorName, item.Rating);
            }
        }
    
        /* ------------------------------------------------------------ */
        /* テストデータ生成メソッド (編集不要) -------------------------- */
        private static List SetupAuthors() => new List
        {
            new Author { Id = 1, Name = "夏目 漱石" },
            new Author { Id = 2, Name = "太宰 治" },
            new Author { Id = 3, Name = "芥川 龍之介" },
            new Author { Id = 4, Name = "東野 圭吾" }
        };
    
        private static List SetupBooks() => new List
        {
            new Book { Id = 1, Title = "こころ",          AuthorId = 1, Genre = "小説", Price = 550, Rating = 4.2 },
            new Book { Id = 2, Title = "吾輩は猫である",   AuthorId = 1, Genre = "小説", Price = 600, Rating = 4.0 },
            new Book { Id = 3, Title = "人間失格",       AuthorId = 2, Genre = "小説", Price = 450, Rating = 4.8 },
            new Book { Id = 4, Title = "羅生門",         AuthorId = 3, Genre = "小説", Price = 400, Rating = 4.4 },
            new Book { Id = 5, Title = "容疑者Xの献身",   AuthorId = 4, Genre = "ミステリー", Price = 800, Rating = 4.7 },
            new Book { Id = 6, Title = "白夜行",         AuthorId = 4, Genre = "ミステリー", Price = 950, Rating = 4.6 },
            new Book { Id = 7, Title = "マスカレード・ホテル", AuthorId = 4, Genre = "ミステリー", Price = 750, Rating = 4.3 }
        };
    
        private static List SetupSales() => new List
        {
            // --- 2024年の売上 ---
            new Sale { BookId = 5, SaleDate = new DateTime(2024, 1, 15), Quantity = 120 },
            new Sale { BookId = 3, SaleDate = new DateTime(2024, 2, 10), Quantity = 150 },
            new Sale { BookId = 6, SaleDate = new DateTime(2024, 3, 20), Quantity = 80 },
            new Sale { BookId = 1, SaleDate = new DateTime(2024, 4, 5),  Quantity = 90  },
            new Sale { BookId = 5, SaleDate = new DateTime(2024, 5, 25), Quantity = 60  }, // 容疑者Xの献身 (追加売上)
            new Sale { BookId = 7, SaleDate = new DateTime(2024, 6, 18), Quantity = 110 },
            new Sale { BookId = 2, SaleDate = new DateTime(2024, 7, 30), Quantity = 70  },
            new Sale { BookId = 3, SaleDate = new DateTime(2024, 8, 11), Quantity = 50  }, // 人間失格 (追加売上)
    
            // --- 2023年の売上 (比較用) ---
            new Sale { BookId = 1, SaleDate = new DateTime(2023, 12, 1), Quantity = 100 },
            new Sale { BookId = 4, SaleDate = new DateTime(2023, 11, 15), Quantity = 200 }
        };
    }

課題内容や既存コードをしっかりと理解して処理をすることができています。


さいごに

今回は、「gpt-oss-20b」の検証を行いました。
20Bというそれなりのパラメータ数をもつモデルですが、これが16GBのVRAMで動作するのは素晴らしいと思います。
それでいて、精度もしっかりしているので、普段遣いでも問題無いレベルのものと思います。
もちろんクラウドの生成AIの方が優秀ではあるものの、コスト面やセキュリティ面を考えた際に、このモデルをローカルで動作させるのはアリだと思います!

今回はこの辺で、ではまた!

コメント

このブログの人気の投稿

Power Automateでファイル名から拡張子を取得

PowerAppsで座席表を作成する

Power AutomateでTeamsのキーワードをトリガーにする