ランダムニュース記事 AI アプリ – day3

30 days AI challenge

本記事は 2026/02/01 ~ 2026/03/01 の間毎日 AI アプリケーション開発(AI を搭載したアプリ開発 or AI を使用した開発)をテーマに 30 days AI challenge を行う 3 日目のブログポストです。

皆さんは “エコーチェンバー” や “フィルターバブル” という言葉をご存じでしょうか。インターネットで情報収集を行う現代人は、ネットで目にする情報に偏りが出てしまうような状況に至りがちです。SNS では自分と同じような意見ばかりになり、クッキーや閲覧履歴などをもとにアルゴリズムがその人の好きそうな記事や広告を表示し、結果その人は同じような情報を目にするようになる。といった現象が該当します。

そんな状況を少しでも解消しようという理由で作成した本日のアプリが “ランダムニュース表示 AI アプリ” です。名前は適当です。

前置きが長くなりましたが、本題に入ります。

今日の AI アプリ

今日作成した AI アプリは、ニュース記事をランダムに取得しその冒頭を表示するアプリです。

海外の API を使用しており海外記事の取得になるため、AI を使って日本語に翻訳する機能も搭載してみました。

※何度か記事取得ボタンを連打したら IT 関連記事ができてしまい、エコーチェンバー、、フィルターバブル、、と思いましたがまあよいでしょう、、笑

技術概要

ニュース記事は News API というサイトの API を使用しています。News API では C# や.NET でのチュートリアル(サンプルコード)が用意されているようです。

API で HTTP リクエストを送り結果を取得することもできますし、クライアントライブラリをインポートして使用することもできるようです。

GitHub Copilot に “News API から情報を取得したい” とリクエストしたところ以下のように HTTP Request にて実装してくれました。一部コード箇所のみ記載しています。

public NewsService(IConfiguration configuration, HttpClient httpClient)

    private readonly HttpClient _httpClient;

    public async Task<(string title, string description, string url, string image, string publishedAt, string error)> GetRandomNewsAsync()
    {
        try
        {
            var response = await _httpClient.GetAsync(
                $"https://newsapi.org/v2/top-headlines?country=us&apiKey={_apiKey}");
            
            var jsonString = await response.Content.ReadAsStringAsync();

            using var json = JsonDocument.Parse(jsonString);
            var root = json.RootElement;
            
            var article = articlesWithImages[_random.Next(articlesWithImages.Count)];
            
     ~その他ロジックもろもろ~

        }
        catch (Exception ex)
        {
      ~例外処理~
        }
    }

C# ライブラリでの書き換えも考えましたが、GitHub のソースを見たところ最後のコミットが 9 年前になっておりあまり保守されていないようなので、HTTP request のほうが無難のようです。

AI (Gemini)による翻訳ボタンを押すと、↓こんな感じで表示した内容を日本語に翻訳してくれます。

Gemini に翻訳リクエストを投げているコード箇所は以下の通りです(こちらも一部抜粋)。

Gemini に関しては SDK が公開されているので、using Google.GenAI; と名前空間を参照しメソッドを呼び出しています。あとは、プロンプトを投げて結果を受け取るだけなので実装としては非常にシンプルです。

isTranslating の boolean 変数は、翻訳された状態の時にもう一度ボタンを押すと原文に戻す、という処理を実装したのでその機能に使用されます。

    private async Task TranslateToJapanese()
    {
        isTranslating = true;
        
        var prompt = $"以下の英語のニュース記事を日本語に翻訳してください。タイトルと説明をそれぞれ翻訳し、以下の形式で返してください。\n\nタイトル: {article.title}\n説明: {article.description}\n\n回答形式:\nタイトル: [翻訳されたタイトル]\n説明: [翻訳された説明]";
        
        try
        {
            var response = await GeminiService.GetChatResponseAsync(prompt, new List<Google.GenAI.Types.Content>());
            
            var lines = response.Split('\n');
            foreach (var line in lines)
            {
                if (line.StartsWith("タイトル:"))
                    titleJa = line.Substring(5).Trim();
                else if (line.StartsWith("説明:"))
                    descriptionJa = line.Substring(3).Trim();
            }
            
            if (string.IsNullOrEmpty(titleJa)) titleJa = article.title;
            if (string.IsNullOrEmpty(descriptionJa)) descriptionJa = article.description;
            
            isTranslated = true;
        }
    }

ちなみに “記事を読む” ボタンをクリックするとその記事の取得元サイトに飛びます(これはプロンプトで指示していないが GitHub Copilot が親切心で実装してくれました、参照元を表示するという意味でも必要だったと思います。ナイス Copilot)。

おわりに

今日のアプリは割とシンプルな実装だったのでコードの可読性も高く “何か知らんけど動いている” から “よ、よめるぞ” という段階になったと思います。

AI にすべてのコードを生成してもらいとりあえず動くからよし、というのもよいですが、やはりコードを読んで何をしているか理解しつつ自分で追記していくのが面白いですね。

翻訳だけに Gemini token を消費するのも惜しい気がしますが、AI 要素なので今回は良しとします。

今日は若干コード箇所にも触れられたので、引き続きできる限り実装内容にも触れていけたら良いなと思います。

明日もよろしくお願いします!(いろんなアイデアがわいてくる)

コメント

タイトルとURLをコピーしました