6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

安価なAIモデルで議事録作成:OpenAI gpt-4.1-nano vs Gemini 2種を比較してみた🐱

Posted at

要約

安価なAIモデル群を、特に議事録作成という観点から比較しました。無難に行くなら OpenAI gpt-4.1-nano、長い会議の場合は Gemini 2.5-flash-lite が良さそうです。

はじめに

定例会議の議事録作成、面倒に感じていませんか?
LLMを使えばある程度自動化できますが、「どのモデルが一番いいの?」と悩むことも多いかと思います。また、コストも気になりますよね。
この記事では、私が議事録作成のために比較的安く利用できる同じ価格帯のモデルを簡易的に比較した結果をまとめました。

対象読者

  • 議事録作成をLLMで自動化・効率化したい方
  • 議事録作成をできるだけ安く済ませたい方
  • GeminiやOpenAIのAPI活用に興味がある方

今回比較したモデル

  • Gemini 2.5-flash-lite
  • Gemini 2.0-flash
  • OpenAI gpt-4.1-nano

今回比較したモデル群は、いずれも 入力$0.10/Mトークン, 出力$0.40/Mトークン の価格帯に属しており、コスト感を揃えた上での性能比較となっています。

ただし、実際には同じプロンプトかつ同じ価格帯でも、消費するトークン数はモデルごとに異なるため、若干の差が生まれます。

モデル基本情報比較

定量的な比較

入力の最大トークン数はほぼ同等です。

比較点 Gemini 2.5-flash-lite Gemini 2.0-flash OpenAI gpt-4.1-nano
最大トークン数(入力 / 出力) 1,048,576 / 65,536 1,048,576 / 8,192 1,047,576 / 32,768
ナレッジカットオフ 2025年1月 2024年8月 2024年6月

参考リンク:

ナレッジカットオフとは、各モデルが学習したデータの最終時点を指します。例えば「2025年1月」と記載されている場合、そのモデルは2025年1月までの情報しか持っていません。

検証の詳細

検証アプローチ

今回の検証は、プロンプトを固定し、できるだけプロバイダごとの差分を吸収して行います。
具体的には、以下のインターフェースを各モデルで実装しました。

from abc import ABC, abstractmethod
from dataclasses import dataclass


@dataclass
class Summary:
    content: str
    input_token_count: int
    output_token_count: int


class Summarizer(ABC):
    """議事録を作成するための抽象基底クラス"""

    @abstractmethod
    def generate_meeting_notes(self, transcription: str) -> Summary:
        """文字起こしから議事録を生成する"""
        pass

検証は次の2ステップで実施しました。

  1. AIが生成したサンプル文字起こしデータを使い、各モデルで議事録を作成して評価
  2. 実際の会議の文字起こしデータを使い、各モデルで議事録を作成して評価

この2つのケースで、モデルごとの違いや特徴を比較しました。

検証に使用したスクリプト

結果だけ知りたい方は、検証結果のセクションまで飛ばしてください。

OpenAI

from openai import OpenAI


class OpenAISummarizer(Summarizer):
    """OpenAI API を利用して議事録を生成するクラス"""

    def __init__(
        self,
        api_key: str,
        summarize_prompt_provider: SummarizePromptProvider,
        model: str = "gpt-4.1-nano",
    ):
        self.client = OpenAI(api_key=api_key)
        self.model = model
        self.summarize_prompt_provider = summarize_prompt_provider

    def generate_meeting_notes(self, transcription: str) -> Summary:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {
                    "role": "system",
                    "content": self.summarize_prompt_provider.get_system_prompt(),
                },
                {
                    "role": "user",
                    "content": self.summarize_prompt_provider.get_prompt(transcription),
                },
            ],
        )
        content = response.choices[0].message.content
        if content is None:
            raise RuntimeError("コンテンツが返されませんでした")

        usage = response.usage

        input_token_count = usage.prompt_tokens if usage is not None else None
        output_token_count = usage.completion_tokens if usage is not None else None

        return Summary(
            content=content,
            input_token_count=input_token_count or 0,
            output_token_count=output_token_count or 0,
        )

Gemini

from google.genai import Client
from google.genai.types import GenerateContentConfig


class GeminiSummarizer(Summarizer):
    """Google Gemini API を利用して議事録を生成するクラス"""

    def __init__(
        self,
        api_key: str,
        summarize_prompt_provider: SummarizePromptProvider,
        model: str = "gemini-2.0-flash",
    ):
        self.client = Client(api_key=api_key)
        self.summarize_prompt_provider = summarize_prompt_provider
        self.model = model

    def generate_meeting_notes(self, transcription: str) -> Summary:
        response = self.client.models.generate_content(
            model=self.model,
            contents=self.summarize_prompt_provider.get_prompt(transcription),
            config=GenerateContentConfig(
                system_instruction=self.summarize_prompt_provider.get_system_prompt()
            ),
        )
        content = response.text
        if content is None:
            raise RuntimeError("コンテンツが返されませんでした")

        usage = response.usage_metadata

        input_token_count = usage.prompt_token_count if usage is not None else None
        output_token_count = usage.candidates_token_count if usage is not None else None

        return Summary(
            content=content,
            input_token_count=input_token_count or 0,
            output_token_count=output_token_count or 0,
        )

OpenAIとGeminiで微妙にAPIのシグネチャが異なりますが、どちらもシステムプロンプトとユーザープロンプトを分けて指定できます。一般に、システムプロンプトはモデルの振る舞いを定義するために使用され、ユーザープロンプトは実際の入力データを提供します。

プロンプト

from abc import ABC, abstractmethod


class SummarizePromptProvider(ABC):
    """AI に対してプロンプトを提供するための抽象基底クラス"""

    @abstractmethod
    def get_prompt(self, transcription: str) -> str:
        """音声のテキスト化結果を受け取り、AI に対してプロンプトを生成する"""
        pass

    @abstractmethod
    def get_system_prompt(self) -> str:
        """AI に対してシステムプロンプトを提供する"""
        pass


class ContextualSummarizePromptProvider(SummarizePromptProvider):
    """追加のコンテキストを持つプロンプトを提供する抽象基底クラス"""

    def __init__(self, additional_context: str | None = None) -> None:
        super().__init__()
        self.additional_context = additional_context

    def get_prompt(self, transcription: str) -> str:
        return f"{self.additional_context or ''}\n文字起こし: {transcription}"


class ObsidianSummarizePromptProvider(ContextualSummarizePromptProvider):
    """Obsidian 用の議事録フォーマットのプロンプトを提供する具象クラス"""

    def get_system_prompt(self) -> str:
        return "あなたは優秀な議事録作成者です。ユーザーから指定されたフォーマットと文字起こしなどの情報から、マークダウンで議事録を作成してください。マークダウン以外の内容は出力しないこと。"

    def get_prompt(self, transcription: str) -> str:
        prompt = f"""【フォーマット】
#minute <!-- タグとして機能するため、このまま記載する -->

**日時**:
**参加者**: <!-- 参加者は省略せず記載する -->

## TL;DR
<!-- 簡潔に箇条書きで記載する -->

## 進捗
<!-- 簡潔に箇条書きで記載する -->

## 議題
### 1. xxx
<!-- 話し合った内容を見返しやすいようにまとめる。表を用いても良い -->
### 2. yyy
### ...

## 決まったこと
## 決まらなかったこと

【会議】
{super().get_prompt(transcription)}
"""

        return prompt

検証データ

AIが生成した文字起こしデータとコンテキストファイル(以下、モックデータ)を使用しました。

文字起こしデータ

それでは次期バージョン1.4の開発進捗会議を始めます。まずは現状の進捗報告からお願いします。iOS側の状況はどうでしょうか?
現在は新機能のダークモード対応が実装完了して、レビュー待ちの状態です。クラッシュの報告が1件ありましたが、原因は確認済みで修正済みです。今週中にベータ版をTestFlightで配布予定です。
Androidもほぼ同じタイミングです。ダークモードは実装済み、テスト中です。若干レイアウト崩れがある画面があったので、今日中に修正します。
その点ですが、Androidの設定画面のフォントサイズが意図より大きくなっていたので、デザインガイドを更新してSlackで共有済みです。確認お願いします。
確認して適用します。
リリースに向けたスケジュールを確認します。現在の進捗から逆算すると、テスト完了が来週末、App StoreとGoogle Playの申請がその翌週というスケジュールで進めたいと思います。QA側の体制は大丈夫ですか?
テストケースは一通り準備済みです。今週中に手動テスト、来週に自動テストの実行予定です。リグレッションテストも含めてチェックします。
それでは次回の会議は8月1日の同じ時間に設定します。各自、それまでに各タスクの完了をお願いします。以上で本日の会議を終了します。

コンテキストファイル

【会議名】
次期アプリバージョン開発進捗会議

【日時】
2025年7月25日(金)10:00〜11:00

【参加者】
- プロジェクトマネージャー
- iOSエンジニア
- Androidエンジニア
- UI/UXデザイナー
- QA(品質管理)担当者

検証結果

定性的な比較

比較点 Gemini 2.5-flash-lite Gemini 2.0-flash OpenAI gpt-4.1-nano
レスポンス速度 とても速い 速い 遅い
要約の質 良い 良い 良い
マークダウンの整形 やや不安定 やや不安定 安定している
指示の理解度 普通 普通 高い

実際の出力結果例

実際の会議の議事録は掲載できないため、AIが生成した文字起こしデータをもとに、各モデルで生成された議事録を示します。実際の会議の議事録でも同様の傾向が見られました。

Gemini 2.0-flash

#minute

**日時**: 2025年7月25日(金)10:00〜11:00
**参加者**: プロジェクトマネージャー、iOSエンジニア、Androidエンジニア、UI/UXデザイナー、QA(品質管理)担当者

## TL;DR
*   次期バージョン1.4の開発進捗確認
*   iOS/Androidともにダークモード対応は実装完了、テスト段階
*   リリーススケジュールはテスト完了が来週末、申請がその翌週を予定

## 進捗
*   iOS: ダークモード実装完了、レビュー待ち。クラッシュ報告1件は修正済み。今週中にベータ版をTestFlightで配布予定。
*   Android: ダークモード実装済み、テスト中。レイアウト崩れを今日中に修正予定。
*   UI/UX: Android設定画面のフォントサイズに関するデザインガイドを更新し、Slackで共有。
*   QA: テストケース準備済み。今週中に手動テスト、来週に自動テスト実行予定。リグレッションテストも実施。

## 議題
### 1. iOS進捗報告
*   ダークモード対応が実装完了し、レビュー待ちの状態。
*   クラッシュの報告が1件あり、原因確認・修正済み。
*   今週中にベータ版をTestFlightで配布予定。

### 2. Android進捗報告
*   ダークモードは実装済み、テスト中。
*   レイアウト崩れがある画面があり、今日中に修正予定。

### 3. デザインガイド更新について
*   Androidの設定画面のフォントサイズが意図より大きくなっていたため、デザインガイドを更新し、Slackで共有。

### 4. リリーススケジュール確認
*   テスト完了が来週末、App StoreとGoogle Playの申請がその翌週というスケジュールで進めることを確認。

### 5. QA体制確認
*   テストケースは一通り準備済み。
*   今週中に手動テスト、来週に自動テストの実行予定。
*   リグレッションテストも含めてチェック。

## 決まったこと
*   次回の会議は8月1日の同じ時間に設定。
*   各担当者は次回会議までに各タスクを完了させる。

## 決まらなかったこと
*   特になし

検証結果(Gemini 2.0-flash):

何度か試しましたが、列挙の際に無駄なスペースが入ることが多かったです。また、あまり重要なことではありませんが、箇条書きの記号が - ではなく * が使われることが多かったです(-が使用されることもある)。

全体的にマークダウンが安定しない印象を受けました。

データ種別 elapsed_time(秒) input_token_count output_token_count
モックデータ 3.47 515 502
実際のデータ 6.83 11,260 860

Gemini 2.5-flash-lite

#minute
**日時**: 2025年7月25日(金)10:00〜11:00
**参加者**: プロジェクトマネージャー, iOSエンジニア, Androidエンジニア, UI/UXデザイナー, QA(品質管理)担当者

## TL;DR
*   次期アプリバージョン1.4の開発進捗会議を実施。
*   iOS、Androidともにダークモード対応は実装完了、テスト・レビュー待ち。
*   Androidの設定画面のフォントサイズの問題はデザインガイド更新で対応。
*   リリーススケジュールはテスト完了が来週末、申請が翌週を予定。
*   QAはテストケース準備済み、手動テスト・自動テストを順次実施。
*   次回会議は8月1日。

## 進捗
*   **iOS**: ダークモード対応実装完了、レビュー待ち。クラッシュ1件原因特定・修正済み。今週中にベータ版TestFlight配布予定。
*   **Android**: ダークモード対応実装完了、テスト中。レイアウト崩れのある画面を本日中に修正予定。
*   **UI/UX**: Android設定画面のフォントサイズに関するデザインガイドを更新し、Slackで共有済み。
*   **QA**: テストケース一通り準備済み。今週中に手動テスト、来週に自動テスト実行予定。リグレッションテストも実施。

## 議題
### 1. 各プラットフォームの進捗報告
*   **iOS**: 新機能のダークモード対応は実装完了し、レビュー待ち。クラッシュ報告1件あったが、原因特定・修正済み。今週中にベータ版をTestFlightで配布予定。
*   **Android**: ダークモード対応は実装完了し、テスト中。若干のレイアウト崩れがある画面を本日中に修正予定。
*   **UI/UX**: Android設定画面のフォントサイズが意図より大きくなっている件について、デザインガイドを更新しSlackで共有。エンジニアが確認・適用する。

### 2. リリーススケジュールとQA体制
*   現在の進捗から、テスト完了を来週末、App StoreとGoogle Playへの申請をその翌週とするスケジュールを提案。
*   QA側はテストケース準備済みであり、今週中に手動テスト、来週に自動テスト(リグレッションテスト含む)を実行する体制が整っている。

## 決まったこと
*   次期アプリバージョン1.4のリリーススケジュールは、テスト完了を来週末、申請をその翌週とする。
*   次回の進捗会議は8月1日(金)10:00に設定する。

## 決まらなかったこと
*   特になし。

検証結果(Gemini 2.5-flash-lite):

何度か試しましたが、2.0-flashと同様の印象を受けました。要約のようなタスクでは、顕著な差は感じませんでした。

ただし、速度は一番速く、出力の最大トークン数も一番長いため、出力が長くなる場合や、レスポンス速度が重要な場合には、こちらのモデルを選ぶと良いでしょう。

データ種別 elapsed_time(秒) input_token_count output_token_count
モックデータ 2.08 530 588
実際のデータ 6.70 12,217 1,465

OpenAI gpt-4.1-nano

#minute

**日時**:
2025年7月25日(金)10:00〜11:00

**参加者**:
- プロジェクトマネージャー
- iOSエンジニア
- Androidエンジニア
- UI/UXデザイナー
- QA(品質管理)担当者

## TL;DR
- 次期バージョン1.4の開発進捗を確認。
- iOSとAndroidともにダークモード対応は完了し、テスト中。
- Androidの設定画面のフォントサイズ調整をデザインガイドを更新し共有済み。
- スケジュールは来週末にテスト完了、翌週にアプリ申請を予定。
- QAはテストケース準備済み、今週手動テスト、来週自動テスト実施。

## 進捗
- iOS:ダークモード実装完了、レビュー待ち。クラッシュ修正済み。
- Android:ダークモード実装済み、レイアウト修正中。設定画面のフォントサイズ調整済み。
- スケジュール:テストは来週末完了、各プラットフォームへの申請は翌週。
- QA:テストケース準備完了、今週手動テスト、来週自動テスト予定。

## 議題
### 1. 各プラットフォームの最新進捗状況
| プラットフォーム | 進捗状況                               | 備考                   |
| ---------------- | -------------------------------------- | ---------------------- |
| iOS              | ダークモード対応完了、レビュー待ち     | クラッシュ修正済み     |
| Android          | ダークモード実装済み、レイアウト修正中 | フォントサイズ調整済み |

### 2. スケジュール調整
- テスト完了予定:来週末
- アプリ申請予定:翌週
- QA体制:問題なし、手動・自動テスト実施予定

### 3. デザインガイドの更新と共有
- Android設定画面のフォントサイズについてデザインガイドを更新し、Slackで共有済み。

### 4. 次回会議の日程
- 2025年8月1日 10:00〜11:00

## 決まったこと
- Android設定画面のフォントサイズ調整を反映し、Slackで共有済み。
- 来週末にテスト完了、翌週にアプリ申請。
- 今週中にQAの手動テスト、来週に自動テストを実施。
- 次回会議を8月1日に設定。

## 決まらなかったこと
特になし。

検証結果(OpenAI gpt-4.1-nano):

OpenAIのモデルは、マークダウンの整形が非常に安定しており、列挙の際に無駄なスペースが入ることはありませんでした。また、レスポンス速度は他のモデルに比べて遅いですが、プロンプトを考慮してくれることが多いと感じました。今回示している議事録の例でも、一部表形式でまとめてくれています。

また、OpenAIはクレジット制であり、このクレジットは有効期限があります。期限が近いクレジットがあるのであれば、OpenAIのモデルを使うのも良いでしょう。

データ種別 elapsed_time(秒) input_token_count output_token_count
モックデータ 9.30 693 625
実際のデータ 18.39 17,488 1,031

結論

GeminiとOpenAIのモデルを比較した結果、最も違いが出たのはマークダウンの綺麗さでした。現状(2025年7月時点)では、Geminiは綺麗なマークダウンの出力が苦手で、特に無駄なスペースが目立ちました。この価格帯で安定したマークダウンを出力したい場合には、OpenAIの方が適していると感じました。

ただし、OpenAIのモデルは消費トークン数がやや多く、レスポンス速度も遅い傾向があります。長時間の文字起こしの場合は、Geminiの方が良いかもしれません。

Gemini同士の比較では、ややトークン数に差がある程度で、明確な差は感じられませんでした。

まとめ

gpt-4.1-nano

無難な選択肢。クレジットがあるならこちらを選ぶと良い。

  • ✅ マークダウンの出力が安定している
  • ✅ 指示に対する理解度が高い
  • ❌ レスポンス速度が遅い
  • ❌ 消費トークン数がGeminiと比べてやや多い

gemini-2.5-flash-lite

レスポンス速度が速く、最新のモデル。出力の最大トークン数もgpt-4.1-nanoの約2倍

  • ✅ ナレッジカットオフが最新
  • ✅ レスポンス速度が最も速い
  • ✅ 出力の最大トークン数が最も長い
  • ❌ マークダウンが安定しない

gemini-2.0-flash

gpt-4.1-nanoと比較して、レスポンス速度が速い

  • ✅ レスポンス速度が速い
  • ❌ マークダウンが安定しない

参考

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?