2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者OK】Cursor×Streamlitで作る!AI感情分析アプリを爆速実装する完全ガイド

Last updated at Posted at 2025-12-21

CursorとStreamlitで作るAI感情分析アプリ - 初心者向け完全ガイド

はじめに

この記事では、CursorとStreamlitを使って、OpenAI APIを活用したテキスト分析・要約ツールを作成する方法を紹介します。
テキストだけのやり取りだと相手の感情が見えなくて誤解してしまったりなどありますよね。そういう時に、AIの力を借りて相手の感情分析ができると助かるな、と思い、それができるアプリを作ってみました。
プログラミング初心者の方でもこの記事の手順通りに進めば、短時間で簡易なAIアプリが作れます。
※コードもあらかじめこちらで作ってあるので、コピペだけでいけます。ですが、環境によってはうまくいかない場合もあるので、万が一うまくいかなかった場合はコメントなどで連絡ください。

この記事で作るもの

完成するアプリの機能

  • テキスト要約: 長文を簡潔/標準/詳細の3段階で要約
  • 感情分析: ポジティブ/ネガティブ/中立を判定し、信頼度も表示
  • キーワード抽出: 重要なキーワードを5-10個自動抽出
  • 多言語翻訳: 英語、日本語、中国語など7言語に対応
  • 結果ダウンロード: 分析結果をMarkdown形式で保存可能

使用技術

  • Cursor: AIを活用したコードエディタ
  • Streamlit: Pythonでウェブアプリを簡単に作成できるフレームワーク
  • OpenAI API: GPT-4o-miniを使用

必要な環境

ソフトウェア

料金

  • OpenAI API: 初回10ドル程度のチャージが必要
    • gpt-4o-miniを使用すれば、1回の分析で約0.3円
    • 10ドルで約3000回以上の分析が可能

ステップ1: Cursorでプロジェクトを作成

1-1. プロジェクトフォルダの作成

  1. デスクトップで右クリック
  2. 新規作成 → フォルダー
  3. フォルダ名を text-analysis-app に設定

1-2. Cursorでフォルダを開く

  1. Cursorを起動
  2. メニューから File → Open Folder を選択
  3. 作成した text-analysis-app フォルダを選択
  4. 開くボタンをクリック

Cursorの左側のサイドバーに、プロジェクトフォルダが表示されます。
image.png

ステップ2: Pythonのインストール

Pythonとは

Pythonは、プログラミング言語の1つです。今回作るアプリはPythonで動きます。

2-1. Pythonがインストールされているか確認

まず、自分のパソコンにPythonが既にインストールされているか確認しましょう。

  1. Cursorで画面上部のメニューから Terminal → New Terminal をクリック
  2. 画面下部にターミナル(黒い画面)が表示されます
  3. 以下のコマンドを入力してEnterキーを押します。
python --version

もし command not found や 認識されていません と表示されたら

python3 --version

も試してください。

結果の確認

  • Python 3.8.x や Python 3.11.x のような表示が出た場合: インストール済みです。次のステップに進んでOKです。
  • エラーが出た場合: Pythonをインストールします。

ステップ3: 必要なファイルを作成

このアプリを動かすには以下4つのファイルが必要です。

  • text_analysis_app.py(メインアプリケーションファイル)
  • requirements.txt(Pythonで作成したアプリが使う「必要なライブラリ(パッケージ)のリスト」を書いたファイル)
  • .gitignore(APIキーなどの機密情報を誤ってGitHubにアップロードしないためのファイル)
  • README.md(ツールの説明)

このステップでは、以上4つのファイルを作成します。
Cursorの左サイドバーで1つずつファイルを作っていきます。

3-1. text_analysis_app.pyファイルの作成

  1. Cursorの左サイドバー(text-analysis-appフォルダが表示されている部分)で右クリック
  2. New File を選択
  3. ファイル名を text_analysis_app.py と入力してEnter

画面中央にファイルが開きます。以下のコードを全てコピーして貼り付けてください:

import streamlit as st
from openai import OpenAI
import json

# ページ設定
st.set_page_config(
    page_title="テキスト分析・要約ツール",
    page_icon="📝",
    layout="wide"
)

# カスタムCSS
st.markdown("""
<style>
    .main-header {
        font-size: 2.5rem;
        font-weight: 700;
        color: #1f1f1f;
        margin-bottom: 0.5rem;
    }
    .sub-header {
        font-size: 1.2rem;
        color: #666;
        margin-bottom: 2rem;
    }
    .analysis-box {
        background-color: #f8f9fa;
        border-radius: 10px;
        padding: 1.5rem;
        margin: 1rem 0;
        border-left: 4px solid #4CAF50;
    }
    .keyword-tag {
        display: inline-block;
        background-color: #e3f2fd;
        color: #1976d2;
        padding: 0.3rem 0.8rem;
        border-radius: 15px;
        margin: 0.2rem;
        font-size: 0.9rem;
    }
    .sentiment-positive {
        color: #4CAF50;
        font-weight: bold;
    }
    .sentiment-negative {
        color: #f44336;
        font-weight: bold;
    }
    .sentiment-neutral {
        color: #FF9800;
        font-weight: bold;
    }
</style>
""", unsafe_allow_html=True)

# タイトル
st.markdown('<div class="main-header">テキスト分析・要約ツール</div>', unsafe_allow_html=True)
st.markdown('<div class="sub-header">文書を分析して、要約・感情分析・キーワード抽出・翻訳を実行</div>', unsafe_allow_html=True)

# サイドバー設定
with st.sidebar:
    st.header("設定")
    
    # API キー入力
    api_key = st.text_input(
        "OpenAI API Key",
        type="password",
        help="OpenAI APIキーを入力してください"
    )
    
    st.divider()
    
    # 分析オプション
    st.subheader("分析オプション")
    analyze_summary = st.checkbox("要約", value=True)
    analyze_sentiment = st.checkbox("感情分析", value=True)
    analyze_keywords = st.checkbox("キーワード抽出", value=True)
    analyze_translation = st.checkbox("翻訳", value=False)
    
    if analyze_translation:
        target_language = st.selectbox(
            "翻訳先言語",
            ["英語", "日本語", "中国語", "韓国語", "スペイン語", "フランス語", "ドイツ語"]
        )
    
    st.divider()
    
    # 要約の長さ設定
    if analyze_summary:
        summary_length = st.select_slider(
            "要約の長さ",
            options=["簡潔", "標準", "詳細"],
            value="標準"
        )
    
    st.divider()
    
    # モデル選択
    model_choice = st.selectbox(
        "AIモデル",
        ["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo"],
        help="gpt-4o-miniが最も安価でおすすめです"
    )

# メインエリア
col1, col2 = st.columns([1, 1])

with col1:
    st.subheader("入力テキスト")
    
    # ファイルアップロード
    uploaded_file = st.file_uploader(
        "ファイルをアップロード(.txt, .md)",
        type=["txt", "md"]
    )
    
    # テキストエリア
    if uploaded_file is not None:
        text_content = uploaded_file.read().decode("utf-8")
        input_text = st.text_area(
            "テキスト内容",
            value=text_content,
            height=400,
            key="input_text"
        )
    else:
        input_text = st.text_area(
            "テキストを入力してください",
            height=400,
            placeholder="分析したいテキストをここに入力するか、ファイルをアップロードしてください...",
            key="input_text_manual"
        )
    
    # 文字数表示
    if input_text:
        st.caption(f"文字数: {len(input_text)} 文字")

def analyze_text_with_openai(text: str, api_key: str) -> dict:
    """OpenAI APIを使用してテキストを分析"""
    
    if not api_key:
        st.error("APIキーを入力してください")
        return {}
    
    client = OpenAI(api_key=api_key)
    results = {}
    
    # 要約
    if analyze_summary:
        with st.spinner("要約を生成中..."):
            length_instruction = {
                "簡潔": "2-3文で簡潔に",
                "標準": "5-7文程度で",
                "詳細": "詳細に10文以上で"
            }
            
            summary_prompt = f"""以下のテキストを{length_instruction[summary_length]}要約してください。
            
テキスト:
{text}

要約:"""
            
            try:
                response = client.chat.completions.create(
                    model=model_choice,
                    messages=[{"role": "user", "content": summary_prompt}],
                    max_tokens=1000
                )
                results["summary"] = response.choices[0].message.content
            except Exception as e:
                st.error(f"要約エラー: {str(e)}")
    
    # 感情分析
    if analyze_sentiment:
        with st.spinner("感情分析中..."):
            sentiment_prompt = f"""以下のテキストの感情を分析してください。
            
以下のJSON形式で回答してください:
{{
    "sentiment": "ポジティブ/ネガティブ/中立のいずれか",
    "confidence": "信頼度(0-100の数値)",
    "explanation": "判断理由の簡単な説明"
}}

テキスト:
{text}"""
            
            try:
                response = client.chat.completions.create(
                    model=model_choice,
                    messages=[{"role": "user", "content": sentiment_prompt}],
                    max_tokens=500
                )
                
                sentiment_text = response.choices[0].message.content
                # JSONを抽出
                if "```json" in sentiment_text:
                    sentiment_text = sentiment_text.split("```json")[1].split("```")[0]
                elif "```" in sentiment_text:
                    sentiment_text = sentiment_text.split("```")[1].split("```")[0]
                
                results["sentiment"] = json.loads(sentiment_text.strip())
            except Exception as e:
                st.error(f"感情分析エラー: {str(e)}")
    
    # キーワード抽出
    if analyze_keywords:
        with st.spinner("キーワード抽出中..."):
            keywords_prompt = f"""以下のテキストから重要なキーワードを5-10個抽出してください。
            
JSON形式で回答してください:
{{
    "keywords": ["キーワード1", "キーワード2", ...]
}}

テキスト:
{text}"""
            
            try:
                response = client.chat.completions.create(
                    model=model_choice,
                    messages=[{"role": "user", "content": keywords_prompt}],
                    max_tokens=500
                )
                
                keywords_text = response.choices[0].message.content
                if "```json" in keywords_text:
                    keywords_text = keywords_text.split("```json")[1].split("```")[0]
                elif "```" in keywords_text:
                    keywords_text = keywords_text.split("```")[1].split("```")[0]
                
                results["keywords"] = json.loads(keywords_text.strip())
            except Exception as e:
                st.error(f"キーワード抽出エラー: {str(e)}")
    
    # 翻訳
    if analyze_translation:
        with st.spinner(f"{target_language}に翻訳中..."):
            translation_prompt = f"""以下のテキストを{target_language}に翻訳してください。
            
テキスト:
{text}

翻訳:"""
            
            try:
                response = client.chat.completions.create(
                    model=model_choice,
                    messages=[{"role": "user", "content": translation_prompt}],
                    max_tokens=2000
                )
                results["translation"] = response.choices[0].message.content
            except Exception as e:
                st.error(f"翻訳エラー: {str(e)}")
    
    return results

# 分析実行ボタン
with col2:
    st.subheader("分析結果")
    
    if st.button("分析を実行", type="primary", use_container_width=True):
        if not input_text:
            st.warning("テキストを入力してください")
        elif not api_key:
            st.warning("APIキーを入力してください")
        else:
            results = analyze_text_with_openai(input_text, api_key)
            
            # 結果を表示
            if "summary" in results:
                st.markdown("### 要約")
                st.markdown(f'<div class="analysis-box">{results["summary"]}</div>', unsafe_allow_html=True)
            
            if "sentiment" in results:
                st.markdown("### 感情分析")
                sentiment_data = results["sentiment"]
                sentiment = sentiment_data.get("sentiment", "不明")
                confidence = sentiment_data.get("confidence", 0)
                explanation = sentiment_data.get("explanation", "")
                
                sentiment_class = "sentiment-neutral"
                if "ポジティブ" in sentiment:
                    sentiment_class = "sentiment-positive"
                elif "ネガティブ" in sentiment:
                    sentiment_class = "sentiment-negative"
                
                st.markdown(f"""
                <div class="analysis-box">
                    <p><strong>感情:</strong> <span class="{sentiment_class}">{sentiment}</span></p>
                    <p><strong>信頼度:</strong> {confidence}%</p>
                    <p><strong>理由:</strong> {explanation}</p>
                </div>
                """, unsafe_allow_html=True)
            
            if "keywords" in results:
                st.markdown("### キーワード")
                keywords = results["keywords"].get("keywords", [])
                keywords_html = "".join([f'<span class="keyword-tag">{kw}</span>' for kw in keywords])
                st.markdown(f'<div class="analysis-box">{keywords_html}</div>', unsafe_allow_html=True)
            
            if "translation" in results:
                st.markdown(f"### 翻訳 ({target_language})")
                st.markdown(f'<div class="analysis-box">{results["translation"]}</div>', unsafe_allow_html=True)
            
            # 結果をダウンロード
            if results:
                st.divider()
                result_text = "# テキスト分析結果\n\n"
                
                if "summary" in results:
                    result_text += f"## 要約\n{results['summary']}\n\n"
                
                if "sentiment" in results:
                    result_text += f"## 感情分析\n"
                    result_text += f"- 感情: {results['sentiment']['sentiment']}\n"
                    result_text += f"- 信頼度: {results['sentiment']['confidence']}%\n"
                    result_text += f"- 理由: {results['sentiment']['explanation']}\n\n"
                
                if "keywords" in results:
                    result_text += f"## キーワード\n"
                    result_text += ", ".join(results['keywords']['keywords']) + "\n\n"
                
                if "translation" in results:
                    result_text += f"## 翻訳 ({target_language})\n{results['translation']}\n\n"
                
                st.download_button(
                    label="結果をダウンロード",
                    data=result_text,
                    file_name="analysis_results.md",
                    mime="text/markdown",
                    use_container_width=True
                )
    else:
        st.info("左側にテキストを入力し、分析を実行ボタンをクリックしてください")

# フッター
st.divider()
st.markdown(f"""
<div style='text-align: center; color: #666; font-size: 0.9rem;'>
    <p>このアプリはOpenAI API ({model_choice})を使用しています</p>
    <p>対応ファイル形式: .txt, .md</p>
    <p>推奨モデル: gpt-4o-mini(安価で高性能)</p>
</div>
""", unsafe_allow_html=True)

コードを貼り付けたら、Ctrl + S(Windows)または Cmd + S(Mac)を押して保存してください。

3-2. requirements.txtの作成

次のファイルを作成します。

  1. 左サイドバーで再度右クリック
  2. New File を選択
  3. ファイル名を requirements.txt と入力してEnter

以下の内容をコピーして貼り付けてください:

streamlit>=1.28.0
openai>=1.0.0

保存します(Ctrl + S または Cmd + S)。

3-3. .gitignoreの作成

  1. 左サイドバーで右クリック
  2. New File を選択
  3. ファイル名を .gitignore と入力してEnter(最初のドットを忘れずに)

以下の内容をコピーして貼り付けてください:

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
venv/
env/
ENV/
.venv

# Streamlit
.streamlit/

# API Keys and Secrets
.env
*.env
secrets.toml
.secrets/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Logs
*.log

保存します(Ctrl + S または Cmd + S)。

3-4. README.mdの作成

  1. 左サイドバーで右クリック
  2. New File を選択
  3. ファイル名を README.md と入力してEnter

以下の内容をコピーして貼り付けてください:

# テキスト分析・要約ツール

OpenAI APIを使用したテキスト分析アプリケーションです。

## 機能

- テキスト要約: 長文を簡潔/標準/詳細の3段階で要約
- 感情分析: ポジティブ/ネガティブ/中立を判定
- キーワード抽出: 重要なキーワードを自動抽出
- 多言語翻訳: 7言語に対応

## 使い方

1. ブラウザでアプリが開きます
2. サイドバーにOpenAI APIキーを入力
3. テキストを入力して分析を実行

## 料金

- OpenAI API使用料が発生します
- gpt-4o-miniを使用すれば1回約0.3円程度

## 作成者

このアプリはCursorとStreamlitを使って作成しました。

保存します(Ctrl + S または Cmd + S)。

3-5. ファイルが全て揃ったか確認

Cursorの左サイドバーに以下の4つのファイルが表示されているはずです。
image.png

もしくは、フォルダからでも確認できます。
image.png

この状態になっていればOKです。次のステップに進みましょう。

ステップ4: OpenAI APIキーの取得

4-1. OpenAIアカウントの作成

  1. https://platform.openai.com/ にアクセス
  2. Sign upをクリックしてアカウントを作成
  3. メールアドレスで登録

4-2. APIキーの作成

APIキーとは何か

APIキーは、OpenAIのAIサービスを使うための認証コード(パスワードのようなもの)です。

このアプリでは、テキストの要約や感情分析をOpenAIのAI(GPT)に依頼します。その際、あなたが正規のユーザーであることを証明するために、このAPIキーが必要になります。

なぜAPIキーが必要なのか

  • OpenAIのAIサービスは非常に高性能で、サーバーの維持にコストがかかります
  • 誰でも無制限に使えると、サーバーに負荷がかかりすぎてしまいます
  • そのため、APIキーで利用者を識別し、使った分だけ料金を請求する仕組みになっています

料金について

OpenAI APIは従量課金制です。使った分だけお金がかかります。

今回使用するgpt-4o-miniモデルの場合

  • 1回の分析(要約+感情分析+キーワード抽出): 約0.3円〜0.8円
  • 最低チャージ額: 10ドル(約1,500円)
  • 10ドルで実行できる回数: 約2,000回〜5,000回

つまり、10ドルをチャージすれば、かなり長い期間使い続けることができます。
また、使わなければ料金は発生しません。チャージした金額から、使った分だけ引かれていく仕組みです。

注意: チャージした10ドルは、購入から1年で期限切れになります。

APIキーの作成手順

それでは、実際にAPIキーを作成していきましょう。
※もし以前すでにAPIキーを作ってあり保存してあれば作成不要です。

  1. ログイン後、左メニューからAPI keysを選択

image.png

  1. Create new secret keyをクリック
  2. 名前を入力(例: text-analysis-app)
  3. Create secret keyをクリック
  4. 表示されたキーをコピーして安全な場所に保存

注意: このキーは1回しか表示されないので、必ずコピーして保存してください。

4-3. クレジットのチャージ

  1. 左メニューからSettingsを選択
  2. Billingをクリック
  3. Add payment detailsをクリック
  4. クレジットカード情報を入力
  5. Continueをクリック
  6. 金額を選択(推奨: 10ドル)
  7. 自動リチャージのチェックを外す(使いすぎ防止)
  8. Confirm paymentをクリック

自動リチャージのチェックを外すことは忘れないでください。
ただ、もし今後もずっと使い続けたい場合はチェックをつけておいてもOKです。
その場合は止めない限りずっと課金されます。

ステップ5: アプリの起動

5-1. ターミナルを開く

Cursorで以下の操作を行います:

  • Windowsの場合: Ctrl + @
  • Macの場合: Control + @

または、上部メニューのTerminal → New Terminalをクリック

5-2. 必要なパッケージをインストール

ターミナルで以下のコマンドを実行します。
(requirements.txtをインストールする)

pip install -r requirements.txt

もしくは

pip3 install -r requirements.txt

Successfully installedと表示されればインストール成功です。

5-3. アプリを起動

以下のコマンドを実行:

streamlit run text_analysis_app.py

もしくは

python -m streamlit run text_analysis_app.py

ブラウザが自動的に開き、アプリが表示されます。

image.png

もし自動で開かない場合は、ターミナルに表示される http://localhost:8501 をブラウザで開いてください。

ステップ6: アプリを使ってみる

6-1. APIキーの設定

  1. 左サイドバーのOpenAI API Key欄に、取得したAPIキーを貼り付け

image.png

  1. モデルはgpt-4o-miniを選択(最も安価)

6-2. テキストを分析

  1. 分析オプションにチェックを入れる(要約、感情分析、キーワード抽出など)
  2. 左側のテキストエリアに分析したい文章を入力
  3. 分析を実行ボタンをクリック
  4. 右側に結果が表示されます

6-3. サンプルテキスト

試しに以下のテキストで分析してみます。

あぁ、今日は疲れた・・・
でも色々と買い物できたし、部屋のお掃除もできてすっきりした!
明日から仕事・・・うんざりするけど、もうすぐ年末休みに入るから頑張る!

image.png

分析結果

分析オプションの「感情分析」だけチェックを入れて「分析を実行」ボタンを押すと結果はこうなりました。

image.png

いいですね!

ちなみに、「要約」「キーワード抽出」「翻訳」にもチェックを入れるとこうなります。
image.png

トラブルシューティング

エラー: ModuleNotFoundError

パッケージのインストールがうまくいっていません。

pip install -r requirements.txt

を再実行してください。

エラー: You exceeded your current quota

OpenAI APIにクレジットがチャージされていません。課金手順を再確認してください。

ブラウザが自動で開かない

ターミナルに表示される http://localhost:8501 を手動でブラウザにコピーして開いてください。

アプリを停止したい

ターミナルで Ctrl + C を押してください。

まとめ

この記事では、CursorとStreamlitを使って、OpenAI APIを活用したテキスト分析アプリを作成しました。

次のステップ

このアプリを基に、さらに機能を追加するとしたら以下が考えられるかなと思います。

  • 文章の難易度判定
  • PDFファイルのアップロード対応
  • 複数ファイルの一括処理
  • グラフによる可視化
  • 他のAI機能を追加してみる
  • デプロイしてウェブ上で公開する
  • データベースと連携させる
  • 認証機能を追加する

CursorのAI機能を活用すれば、アイデアを素早く形にできます。ぜひ自分なりのカスタマイズを加えて、オリジナルのアプリを作ってみてください。
CursorのAI機能(Cmd/Ctrl + L でチャット、Cmd/Ctrl + K で編集)を使えば、
これらの機能も簡単に追加できます。

ぜひ自分なりのカスタマイズを加えて、オリジナルのアプリを作ってみてください。

参考リンク

質問やフィードバックがあれば、コメント欄でお気軽にお知らせください。

この記事が役に立ったら、いいねをお願いします。

2
0
1

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?