ITの最新トレンドをAIがまとめてくれるWebアプリを作ってみた

## はじめに

みなさん日々の情報収集はどのように行われていますでしょうか。
私はQiitaを始め、Zennやはてなブックマークなどを巡回してトレンド記事を見るのが日課になっています。
しばらく続けていると、最近ずっと話題になってるなーとか、急に出てきたこれは何だ、というような気づきがあります。
そういったことをAIにやらせてみたら面白いんじゃないかと思い、トレンドになっている記事のタイトルからキーワードを抽出して整理し、コメントを添えるWebアプリを作ってみました。

## 作ったもの
Tech Trend Words

https://tech-trend-words.jp/

※毎日ツイートもしますので是非フォローをお願いします！
http://x.com/wordstech59132


## 主な機能

### トレンドワードの表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/54b11d32-c1d4-164f-7600-cf70144f3457.png)



Qiita,Zenn,はてなブックマークでトレンドになっている記事タイトルからワードを抽出しています。(powered by ChatGPT API)
気になったワードはタップしてすぐ検索できます。

### サマリーコメントの表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/9a67aa6b-6e30-2150-5d50-ce64fe98faf9.png)




トレンドワードの一覧から傾向などを読み取り、コメントを表示します。
ベテランたぬきエンジニアのテクトレはんが担当します。(powered by ChatGPT API)


### 履歴の表示
過去のデータも日別に表示できます。
※2016年12月12日まで遡ることができますが、2024年07月14日以前のデータはQiitaのみとなり、ストック数が10以上の記事を投稿日基準で抽出しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/a61c9398-5a38-a7c1-caf1-34b90d7b825c.png)






### PWA対応
毎日サクッとチェックできるように、スマホなどのホーム画面に追加できます。

![IMG_0474.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/2b75647a-8dfc-c222-3252-c8f3bae06437.jpeg)


※ホーム画面への追加方法

https://support.bccks.jp/faq/pwa_2020/


## 技術面
### トレンド記事のデータの取得
AWS Lambda＋EventBridgeを利用しています。(毎日0時に発火)
取得したデータはSupabaseに格納しています。

```feedparser```を利用してQiia,Zenn,はてなのRSSから情報を取得します。

```python:feedparse
import feedparser

def fetch_feed(feed_url):
    feed = feedparser.parse(feed_url)
    titles = [{"title": entry.title, "link": entry.link} for entry in feed.entries]
    return titles

def fetch_popular_article_titles():
    urls = [
        "https://qiita.com/popular-items/feed",
        "https://zenn-api.vercel.app/api/trendTech",
        "http://b.hatena.ne.jp/hotentry/it.rss",
    ]

    response = []
    for url in urls:
        response += fetch_feed(url)

    return response

```

OpenAI APIに投げるプロンプトは↓のような感じにしています。（```{{trend_title_list}}```を↑で取得したタイトルのリストに差し替え）
※過去分の取得にも同様のプロンプトで行い、数千件を取得しましたが１回も出力形式のフォーマットエラーはなかったです。進化のスピード恐るべし。

```python:プロンプト
KEYWORDS_PROMPT = """
次のトレンド記事のタイトルリストから重要なキーワードとサブワードを抽出し、頻度に基づいて３つのテーマに分類してください。キーワードとサブワードは各テーマで５つ選んでください。
作業の過程やコメントは出力せず、結果だけJson形式で出力してください。
summaryは直接的にキーワードを並べるのではなく、トレンドになっている理由などを考察するようにし、関西弁で出力してください。

## トレンド記事のタイトルリスト
{{trend_title_list}}


## テーマ
1. technology and tools
2. projects and teams
3. learning and growth

## 出力形式
{
    "summary":"summary text",
    "technology_and_tools": ["キーワード サブワード", "キーワード サブワード", "キーワード サブワード"],
    "projects_and_teams":  ["キーワード サブワード", "キーワード サブワード", "キーワード サブワード"],
    "learning_and_growth":  ["キーワード サブワード", "キーワード サブワード", "キーワード サブワード"],
}

"""
```

```python:OpenAI APIにリクエスト
def fetch_openai_response(prompt):
    client = OpenAI(api_key=OPENAI_API_KEY)
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        response_format={"type": "json_object"},
    )
    return response.choices[0].message.content
```

### 過去データの取得
QiitaのAPIより取得しました。(データ取得2024-07-14開始以前かつ、ストック数10を超えるもの)
```python
import requests

# QiitaのAPIエンドポイント
api_url = "https://qiita.com/api/v2/items"

# APIリクエストのパラメータ
params = {
    "page": {1~100},
    "per_page": {1~100},
    "query": "stocks:>10 and created:<=2024-07-14",
}

# APIリクエストを送信
response = requests.get(api_url, params=params)

# レスポンスをJSON形式で取得
data = response.json()

# DB格納処理など
~~~
```

### PWA化のためのファイル
- ```static```に配置
```json:manifest.json
{
    "name": "Tech Trend Words",
    "short_name": "TechTrend",
    "start_url": "/",
    "display": "standalone",
    "background_color": "#343132",
    "theme_color": "#343132",
    "icons": [
        {
            "src": "/static/images/icon-192x192.webp",
            "sizes": "192x192",
            "type": "image/webp"
        },
        {
            "src": "/static/images/icon-512x512.webp",
            "sizes": "512x512",
            "type": "image/webp"
        }
    ]
}
```

```javascript:serviceworker.js
const CACHE_NAME = 'tech-trend-cache-v1';
const urlsToCache = [
    '/',
    '/static/css/styles.css',
    '/static/js/scripts.js',
    '/static/images/title.webp',
    '/static/images/tekutorehan.webp',
];

self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(urlsToCache);
            })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                if (response) {
                    return response;
                }
                return fetch(event.request);
            })
    );
});
```
- ```static/images```に配置
    - ```icon-192x192.webp```
    - ```icon-512x512.webp```

### その他
Webアプリ自体はFlaskで作成し、Fly.ioでホスティングしています。
```fly launch```⇒```fly deploy```するだけでFlaskのアプリと認識してくれるのでそのままいい感じにデプロイできます。便利。

タイトルトップやテクトレはんの画像、PWA用のアイコンなどは全てChatGPT(Dall-E3)に作ってもらいました。文字が正確に出力されるようになったのは大きいですね。


## おわりに
今後、取得したデータをつかってトレンドの推移なども表示できるようにしていきたいなと思っています。
こんなデータが見たい、こんな機能が欲しい。などありましたらコメント、DM、メール等でご連絡ください！