3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

はじめに

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

作ったもの

Tech Trend Words

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

主な機能

トレンドワードの表示

image.png

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

サマリーコメントの表示

image.png

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

履歴の表示

過去のデータも日別に表示できます。
※2016年12月12日まで遡ることができますが、2024年07月14日以前のデータはQiitaのみとなり、ストック数が10以上の記事を投稿日基準で抽出しています。
image.png

PWA対応

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

IMG_0474.jpeg

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

技術面

トレンド記事のデータの取得

AWS Lambda+EventBridgeを利用しています。(毎日0時に発火)
取得したデータはSupabaseに格納しています。

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

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}}を↑で取得したタイトルのリストに差し替え)
※過去分の取得にも同様のプロンプトで行い、数千件を取得しましたが1回も出力形式のフォーマットエラーはなかったです。進化のスピード恐るべし。

プロンプト
KEYWORDS_PROMPT = """
次のトレンド記事のタイトルリストから重要なキーワードとサブワードを抽出し、頻度に基づいて3つのテーマに分類してください。キーワードとサブワードは各テーマで5つ選んでください。
作業の過程やコメントは出力せず、結果だけ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":  ["キーワード サブワード", "キーワード サブワード", "キーワード サブワード"],
}

"""
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を超えるもの)

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に配置
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"
        }
    ]
}
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 launchfly deployするだけでFlaskのアプリと認識してくれるのでそのままいい感じにデプロイできます。便利。

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

おわりに

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

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?