乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

プログラミング

今回はDuckDBを用いた
簡単SQLデータ分析についてです

解説動画はこちら



DuckDB

データ分析したいけどSQLならわかるんだけど
Python良く分からないなー

そんな時はDuckDB使えばいいじゃない!!

ということで
DuckDBのご紹介です。

Python上でSQLでデータ取得できるライブラリで
DataFrameをそのままSQLテーブルとして扱えます。

pandasの複雑なメソッドを覚えなくても
SQL操作で任意のデータが抽出できるものです。
pandasも加えると更に深掘りも出来てお得です。


早速使い方を見ていきましょう。


インストール

Google Colabでは
インストール済みなので不要です。

ローカルなどでインストールしていない人は
下記コマンドを実行しておいてください。
pip install duckdb


ライブラリの呼び出し

これだけです。
import duckdb


操作の基本
# 実行結果を表示
duckdb.sql("SQL文").show()

# 実行結果を変数に格納
データフレーム変数 = duckdb.sql("SQL文").df()

データフレームを作ってSQL文を投げてみます
import pandas as pd

df = pd.DataFrame({
    "a":[1,2,3],
    "b":[10,20,30]
})

sql = "SELECT * FROM df WHERE a > 1"

result_df = duckdb.sql(sql).df()
result_df

ab
0220
1330

DuckDBではデータフレームや
ファイルに直接SQL文のクエリを実行し
データ抽出が行えます。


SQL分をファイルから読み込みする
sql = open("ファイルパス").read()
df = duckdb.sql(sql).df()


ファイルを直接クエリする

sql = open("ファイルパス").read()
df = duckdb.sql(sql).df()
Google Colabなどでもファイルを置いておけば参照できます。



サンプルデータで簡易分析

sklearnサンプルデータを用いて
DuckDBでSQL分析してみましょう。

今回用いるデータは
「California Housing Dataset」

カリフォルニアの
地域ごとの住宅価格などのデータです。
下記コードで読み込みできます。
import duckdb
import pandas as pd
from sklearn.datasets import fetch_california_housing

# データロード
data = fetch_california_housing(as_frame=True)

df = data.frame

# DuckDBに接続
con = duckdb.connect()

# DataFrameを登録
con.register("housing", df)

データの準備が整ったら
DuckDBでSQLを実行してみましょう。

1.平均住宅価格
sql = """
SELECT
    AVG(MedHouseVal) as avg_price
FROM housing
"""

print(con.sql(sql).df())

2.住宅価格ランキング
sql = """
SELECT
    MedHouseVal
FROM housing
GROUP BY MedHouseVal
ORDER BY MedHouseVal DESC
LIMIT 10
"""

print(con.sql(sql).df())

3.地域ごとの住宅価格
sql = """
SELECT
    ROUND(Latitude,1) as lat,
    ROUND(Longitude,1) as lon,
    AVG(MedHouseVal) as avg_price,
    COUNT(*) as houses
FROM housing
GROUP BY lat, lon
ORDER BY avg_price DESC, houses DESC
LIMIT 15
"""

print(con.sql(sql).df())

4.収入と住宅価格
sql = """
SELECT
    CASE
        WHEN MedInc < 2 THEN 'low'
        WHEN MedInc < 5 THEN 'middle'
        ELSE 'high'
    END as income_level,
    AVG(MedHouseVal) as avg_price,
    COUNT(*) as cnt
FROM housing
GROUP BY income_level
ORDER BY avg_price DESC
"""

print(con.sql(sql).df())

5.家の広さと価格
sql = """
SELECT
    ROUND(AveRooms,0) as rooms,
    AVG(MedHouseVal) as price,
    COUNT(*) as n
FROM housing
GROUP BY rooms
HAVING n > 50
ORDER BY rooms
"""

print(con.sql(sql).df())


応用編

海沿い住宅は高いのかどうか

カリフォルニアは 西側が海なので
経度(Longitude) で判定


sql = """
SELECT
    CASE
        WHEN Longitude < -121 THEN 'coastal'
        ELSE 'inland'
    END AS location_type,
    AVG(MedHouseVal) AS avg_house_price,
    COUNT(*) AS houses
FROM housing
GROUP BY location_type
"""

result = con.sql(sql).df()

print("海沿い住宅(coastal) vs 内陸住宅(inland)")
print(result)

結果はコードを試すか
動画の方をご覧ください





まとめ


DuckDBを用いるとSQLを使ったデータ分析が
簡単に行えます。

Pythonのコードに慣れていなくても
直接ファイルにSQLを実行して分析結果を得られます。

複雑な集計もSQLを書ければ出来ちゃうので
データアナリストでなくても簡単に分析できちゃいます。

手元にデータが有るけどデータベース作れない
SQLは分かるけどpython分からない人向け
超お手軽ライブラリなので、おすすめです

ぜひ試してみてください
それでは。





 

今回は
FastAPI × htmx で作るプロトタイプを爆速実装する方法
についてです。


解説動画はこちら




 FastAPI × htmx

昨今のPython界隈は streamlit というライブラリのおかげで
フロントエンドもまとめて作ることができる様になりました。

そのおかげで、似たような見た目ばかりになる
streamlit臭のするデザインのモックばかり
という哀しい現象が起きてきています。

なので、こんな状況を打破すべく
 - デザイン部分は自由に作り込める
 - フロントエンド(React/Vue)の学習コストが高すぎて、モック作りが進まない
 - FastAPI(堅牢なバックエンド) + htmx(HTML だけで Ajax)というシンプル構成

という FastAPI + htmx の組み合わせの方法をお伝えします。


FastAPI とは何か

爆速で動く、現代的な『注文受け付け窓口』
Python言語で作られたWEBフレームワークです。

プログラムの実行速度が非常に速く
開発者がコードを書くスピードも速くなるように設計されており

仕様書(APIドキュメント)を自動で作成
型(データ)のチェックなども行ってくれます。


htmx とは何か

HTMLを『魔法の言葉』に変える道具
通常、Webページの一部を書き換えるには
JavaScriptをたくさん書く必要があります。

htmxだと「HTMLを数文字書き足すだけ」で実現でき
JavaScriptの部分をHTMLの属性だけで指示できるます。

学習コストが劇的に低い(HTMLが分かるなら)
ので初学者でも取り組みが楽です。


なので
この組み合わせが事業モックに最適です。

フロントとバックエンド、2つの学習コストが低い
シンプルでサクサク動くし、修正が簡単

モックとして作った後も
そのまま本番サービス転用も可能です。



環境構築と基本設定

Python側のインストール
pip install fastapi uvicorn jinja2 python-multipart


FASTAPIの実行方法
main.py のあるディレクトリで
uvicorn main:app --reload

WEBブラウザー側で http://127.0.0.1:8000/
にアクセスするとFASTAPIの画面が見れます。



デモプロジェクトの概要


デモプロジェクトのディレクトリ構成

├── main.py
└── templates/
    ├── index.html        (ベースレイアウト)
    ├── customer_list.html (顧客一覧)
    ├── customer_detail.html (顧客詳細)
    ├── stock_list.html    (在庫一覧)
    ├── stock_detail.html  (在庫詳細)
    └── chat.html          (AIチャット)


こんな内容のものを作ることができます。
スクリーンショット 2026-02-21 17.28.21
スクリーンショット 2026-02-21 17.28.28
スクリーンショット 2026-02-21 17.28.34




main.py のコード

FAST API のコードはこんな感じになっています。
from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from datetime import datetime

app = FastAPI()
templates = Jinja2Templates(directory="templates")

# --- ダミーデータ ---
CUSTOMERS = {
    "C001": {"id": "C001", "name": "山田 太郎", "birth": "1985/05/20", "gender": "男性", "address": "東京都渋谷区...", "rank": "S", "items": [{"name": "ルンバ", "qty": 1, "price": 50000}]},
    "C002": {"id": "C002", "name": "佐藤 花子", "birth": "1992/11/02", "gender": "女性", "address": "大阪府大阪市...", "rank": "A", "items": [{"name": "化粧水", "qty": 2, "price": 4000}]},
    # ...他3件(実装上は同様に定義)
}

STOCKS = {
    "S001": {"id": "S001", "name": "ロキソニンS", "category": "解熱鎮痛剤", "count": 150, "desc": "第1類医薬品。速効性に優れています。"},
    "S002": {"id": "S002", "name": "アレグラFX", "category": "鼻炎薬", "count": 45, "desc": "眠くなりにくいアレルギー専用鼻炎薬。"},
}

def calc_age(birth_str):
    birth_date = datetime.strptime(birth_str, "%Y/%m/%d")
    today = datetime.today()
    return today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))

# --- Routes ---
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

# 1. 顧客管理
@app.get("/customers", response_class=HTMLResponse)
async def list_customers(request: Request):
    data = []
    for c in CUSTOMERS.values():
        data.append({**c, "age": calc_age(c['birth']), "birth_month": c['birth'][:7]})
    return templates.TemplateResponse("customer_list.html", {"request": request, "customers": data})

@app.get("/customers/{cid}", response_class=HTMLResponse)
async def detail_customer(request: Request, cid: str):
    c = CUSTOMERS.get(cid)
    return templates.TemplateResponse("customer_detail.html", {"request": request, "customer": c, "age": calc_age(c['birth'])})

# 2. 在庫チェック
@app.get("/stocks", response_class=HTMLResponse)
async def list_stocks(request: Request):
    return templates.TemplateResponse("stock_list.html", {"request": request, "stocks": STOCKS.values()})

@app.get("/stocks/{sid}", response_class=HTMLResponse)
async def detail_stock(request: Request, sid: str):
    return templates.TemplateResponse("stock_detail.html", {"request": request, "stock": STOCKS.get(sid)})

# 3. AIチャット
@app.get("/chat", response_class=HTMLResponse)
async def chat_page(request: Request):
    return templates.TemplateResponse("chat.html", {"request": request})

@app.post("/chat/send", response_class=HTMLResponse)
async def chat_send(request: Request, message: str = Form(...)):
    # 簡易的なAIレスポンスのシミュレーション
    ai_response = f"「{message}」について承知いたしました。AIとしての回答をここに表示します。"
    return f"""ここは省略しています"""

index.htmlなどは
AIエージェントを使って作ってみてください





まとめ


FAST API + htmx を用いると爆速でモック開発ができる
こちらは必要最低限の知識を学ぶだけで済む
デザイン部分は自由に作り込めるので好きなCSSを勉強しよう

足りない部分はAIエージェント使ってください
こちらは作りたいものを指示するだけ
本番作りもAIエージェントで爆速開発できます

PS
最近はこれでプロトタイプ開発していたりします。
AIエージェントも使いこなせると
爆速で開発できる様にできますよ

それでは。

 

今回はバイブコーディングを
うまく行かせるためのコツについてです。

解説動画はこちら




バイブコーディングのコツ


昨今ではもう当たり前になってきている
バイブコーディング

これをうまく活かせるための
コツについてお伝えします。


ポイントは3つだけ

1.マークダウン形式で指示する

2.ロールを与える

3.できるだけ具体的に指示する

これだけ守れたら十分です

それ以外の説明や細かい所は
動画の方を見ていただければと思います。



ゲーム作成プロンプト

この内容に、追加で仕様を加えるなどで
改変することができると思います。
# 依頼:HTML Canvasを使用した「掘削アクションパズル」の作成

以下の仕様に基づき、シングルファイルのHTML(HTML/CSS/JS一体型)でゲームを作成してください。

## 1. ゲーム概要
- タイトル:簡易版ドリラー
- プレイヤーは下方向に向かってブロックを掘り進み、スコアと深さを競う。
- 「酸素(AIR)」の概念があり、時間経過で減少する。

## 2. コアメカニクス
- **移動と掘削**: 
    - 矢印キーで移動。
    - 隣接する(上下左右)ブロックを、移動キー(左、下、右)で破壊。
    - 1ブロック下に進むごとに深さを +1する
    - 破壊できたらその方向に進む
- **ブロックの挙動**:
    - ブロックの種類は4種類
    - 青色の土ブロック : 1アクションで破壊可能、破壊するのに酸素ゲージを1消費する
    - 茶色の土ブロック : 2アクションで破壊可能、破壊するのに酸素ゲージを2消費する
    - 灰色の岩ブロック : 3アクションで破壊可能、破壊するのに酸素ゲージを5消費する
    - 銀色のメタルブロック : 破壊不能、移動アクション毎に酸素ゲージを2消費する
- **リソース管理**:
    - 酸素ゲージは最大100。毎秒1ずつ減少。
    - 特定のブロック(エアーカプセル)を取得すると酸素が15回復。
    - 特定のブロックの破壊でも酸素ゲージを消費する
    - 酸素ブロックはおよそ、30メートルに1つの割合で出現する
- **ゲーム管理**:
    - 画面読み込みと同時にゲーム開始
    - 酸素ゲージ0でゲームオーバー
    - スペースキー押下で再ゲームスタート

## 3. 画面構成
- 画面の上部と下部の2部構成
- 画面上部はスコアなどの表示ゾーン
- Canvasサイズ400x100
- 画面上部に左から「DEPTH(深さ)スコア」「AIR(残り酸素)ゲージ」を表示。
- DEPTHスコアの表示は画面左上に固定し、数値4桁で0埋めする
- AIRゲージは画面上部の中央に長めに固定
- AIRゲージ全体は白枠組みで、残り酸素を黄色で表現し右から左に向かって減るようにする
- AIRゲージの右側に残り酸素を数値で表示(MAX100で3桁0埋めする)
- 画面下部はブロックゾーン
- Canvasサイズ: 400x600(縦長)
- ブロックサイズ: 40x40のグリッド
- 掘り進めるごとに、うまく調整してスクロールするようにする
- 深さ10m毎にブロックキャンバスの左外側にその深さを数値で表示させる

## 4. ビジュアル・操作性
- ブロックの色は4色(青、茶、灰、銀)、それぞれ、四角で表現し、枠は白くする
- エアーカプセルは桃色の簡易的な丸型図形とする
- キャラクターは黒色の簡易的な下向きの三角形でOK。
- 操作:
    - Left/Right:移動
    - Down:下のブロックを掘る

## 5. 実装のステップ
1. Canvasのセットアップとゲームループ(requestAnimationFrame)の作成。
2. ブロック配置データの生成(配列管理)。
3. プレイヤーの移動と掘削処理。
4. ブロックの消滅ロジックの実装。
5. 酸素減少とゲームオーバー判定の実装。

まずは、これらを網羅した動くコードを出力してください。


これをLLMに直接放り投げれば
HTMLでJSを用いたゲームを作ってもらえると思います。

是非コピペしてみてください

それでは。




 

プログラミング未経験の方のための
プログラミング学習講座を作成しました

その名も
「1時間で学べるPythonプログラミング」


講義動画はこちら




この講座は初学者の方が
短時間でPython言語を学ぶことのできる
プログラミング学習用の講座です

プログラミングが分からないない方は
Python言語を通じて
プログラミングの基礎を学習できます

講座は動画に加えてGoogle Colabを用いて
手元でコードを動かすことのできます
コードがどう動くのかを確認をしながら
進めていってください

資料はここ:
Google Colabの資料


00:00 1.はじめに
02:13 2.導入方法
02:55 3.GoogleColaboratoryの操作方法
06:19 4.Pythonの計算の基礎
27:27 5.Pythonの制御文
42:14 6.Pythonのクラス
49:11 7.Pythonのその他構文
64:30 8.まとめ

なおPythonチートシートを作成しています。

コーディングに迷った際に役に立ち

WEB検索する時間を無くして

作業時間を効率化できます。

note
Pythonチートシート


 

今回は最近公開された
Xのフィードアルゴリズムについてです

解説動画はこちら





Xのフィード・アルゴリズムの仕組みについて

Xのアルゴリズムコードはこちらになります。

xai



システムの4つの主要コンポーネント



Xのフィードアルゴリズムは
大きく4つのコンポーネントで構成されています。

4components



1. Home Mixer:
全体の司令塔(オーケストレーション層)です。

候補の抽出からランク付け、フィルタリングまでの全工程を管理します。
パイプラインは以下のステージで構成されています:

    1.Query Hydration - ユーザーのエンゲージメント履歴とメタデータを取得
    2.Candidate Sources - ThunderとPhoenixから候補を取得
    3.Hydration - 候補に追加データを付与
    4.Pre-Scoring Filters - 不適格な投稿を除外
    重複、古い投稿、自分の投稿、ブロック/ミュートしたアカウント、ミュートキーワードなど
    5.Scoring - 複数のスコアラーを順次適用
      Phoenix Scorer (ML予測)
      Weighted Scorer (予測の重み付け結合)
      Author Diversity Scorer (多様性のための減衰)
      OON Scorer (Out-of-Network調整)
    6.Selection - スコアでソートし、上位K件を選択
    7.Post-Selection Filters - 最終検証 (削除済み/スパム/暴力的コンテンツなど)
    8.Side Effects - キャッシュとログ記録


2. Thunder:
フォロー中ユーザーの投稿をリアルタイムで追跡するメモリ内ストアです。

ミリ秒単位の高速な読み込みを可能にします。

主要機能:
    1.Kafkaからのリアルタイム取り込み - 投稿の作成/削除イベントを消費
    2.ユーザー別ストア管理 - オリジナル投稿、リプライ/リツイート、動画投稿を分類
    3.サブミリ秒ルックアップ - 外部データベースにアクセスせずに高速検索
    4.自動トリミング - 保持期間を超えた古い投稿を自動削除

パフォーマンス最適化:
    1.タイムアウト機能 (デフォルト設定可能)
    2.ユーザーあたりの投稿数制限
    3.メモリ効率化のための自動容量調整


3. Phoenix:
機械学習(ML)を担当する心臓部です。

検索: フォロー外から好みに合う投稿を見つけ出します。
ランキング: ユーザーがその投稿に反応(いいねやリプライなど)する確率を予測します。

・アルゴリズムの詳細

2つのステップ

1. Retrieval(Retrieval段階):
数億のツイートから、2タワーモデル(Two-Tower Model)を用いて
「関連がありそうな数千件」をミリ秒単位で抽出します。

2. Ranking(ランキング段階):
抽出された数千件に対し、トランスフォーマーモデルを用いて
いいねやリポストなどの「具体的なエンゲージメント確率」を
詳細に予測・採点します。


Retrieval: Two-Tower Model (2タワーモデル)
   1. User Tower(ユーザー側): 
   ユーザーの属性(User Hashes)と、過去のエンゲージメント履歴(History)を
   トランスフォーマーで処理し、ユーザーの「現在の興味」を
   1つの数値ベクトル(User Representation)に凝縮します。

   2. Candidate Tower(ツイート側): 
   ツイート内容や投稿者情報を同様にベクトル化(Candidate Representation)します。

近さの計算(ドット積)
   「近さ」の採点は、ユーザーベクトルと
   ツイートベクトルの**ドット積(内積)**で行われます。

   ベクトル同士の向きが近い(興味が一致する)ほどスコアが高くなります。
   全てのツイートが事前にベクトル化されているため
   数億件の中から瞬時に上位K件を取得可能です。


Multi-Action Prediction (複数アクション予測)
   P(favorite)      - いいね
   P(reply)         - リプライ
   P(repost)        - リツイート
   P(quote)         - 引用ツイート
   P(click)         - クリック
   P(profile_click) - プロフィールクリック
   P(video_view)    - 動画視聴
   P(share)         - シェア
   P(dwell)         - 滞在時間
   P(follow_author) - フォロー
   P(not_interested) - 興味なし (負の重み)
   P(block_author)  - ブロック (負の重み)
   P(mute_author)   - ミュート (負の重み)
   P(report)        - 報告 (負の重み)


最終スコア計算:

   Final Score = Σ (weight_i × P(action_i))

ポジティブなアクションは正の重み、ネガティブなアクションは負の重みを持ちます。


4.Candidate Pipeline:
推薦システムを構築するための再利用可能なフレームワークです。
   Source データソースから候補を取得
   Hydrator 候補に追加特徴を付与
   Filter 表示すべきでない候補を除外
   Scorer ランキング用のスコアを計算
   Selector 上位候補をソート・選択
   SideEffect 非同期サイドエフェクト実行 (キャッシュ、ログ)
   QueryHydrator クエリコンテキストを準備




おすすめが表示されるまでの流れ


フィードが生成されるまでには、以下のステップを踏みます。
flow


1. データの準備 (Hydration): ユーザーの過去のエンゲージメント履歴や
フォローリストを読み込みます。

2. 候補の抽出: 「Thunder(フォロー内)」と「Phoenix(フォロー外)」の
両方から候補となる投稿を集めます。
   
3. フィルタリング(前処理): 重複した投稿、古すぎる投稿
自分がブロックしている相手の投稿、既に見た投稿などを除外します。

4. スコアリング(ランク付け):
 Grokベースのモデルが「いいね」「リプライ」「リポスト」
 「クリック」などの発生確率を個別に予測します。
 それらを重み付けして最終スコアを算出します。
 特定の著者ばかりに偏らないよう「著者多様性スコア」で調整をかけます。

5. 最終選定: スコアの高い順に並べ替え、最終的な表示候補を選び出します。

6. フィルタリング(後処理): 削除済み、スパム、暴力的なコンテンツなどが
混じっていないか最終チェックを行います。


おすすめに表示されやすくなるポイント

ポジティブエンゲージメント
以下のアクションが予測されるとスコアが上昇:

いいね、リツイート、リプライ
動画視聴 (一定時間以上の動画)
フォロー
クリック、シェア、滞在時間

In-Network(フォロー中)
フォローしているアカウントの投稿は優遇されます。

新鮮な投稿 古すぎない
タイムリーな投稿が優先されます。

動画コンテンツ 一定時間以上の動画は
特別な重み付けを受けます。



おすすめに除外されやすくなるポイント

ネガティブシグナル 以下が予測されると
スコアが低下:

興味なし、ブロック、ミュート、報告

ブロック・ミュートしたアカウント
完全に除外されます。

ミュートキーワード
設定したキーワードを含む投稿は除外。

自分自身の投稿
自分の投稿は「For You」から除外。

既に見た投稿
過去に表示された投稿は除外(Bloom Filter使用)。

古すぎる投稿
一定期間以上経過した投稿は除外。

削除済み・スパム・暴力的コンテンツ
最終段階で除外されます。



スコアリングの仕組み

最終スコア = Σ (重み × 各アクションの予測確率)

= P(いいね) × いいね重み
+ P(リツイート) × リツイート重み
+ P(リプライ) × リプライ重み
+ ...
+ P(ブロック) × ブロック重み (負の値)
+ P(ミュート) × ミュート重み (負の値)
処理順序:

1. Phoenix Transformer → ML予測
2. Weighted Scorer → 重み付け結合
3. Author Diversity Scorer → 多様性調整
4. OON Scorer → In/Out-of-Network調整
5. Selection → 上位K件選択



ポジティブシグナルの重み

以下のアクションが予測されると、投稿のスコアが上昇します:

アクション 説明 重要度
いいね (Favorite) ユーザーがいいねする確率 ⭐⭐⭐
リツイート (Retweet) リツイートする確率 ⭐⭐⭐
リプライ (Reply) リプライする確率 ⭐⭐⭐
引用ツイート (Quote) 引用ツイートする確率 ⭐⭐
クリック (Click) 投稿をクリックする確率 ⭐⭐
プロフィールクリック 投稿者のプロフィールをクリック ⭐⭐
動画視聴 (Video View) 動画を視聴する確率 ⭐⭐⭐
画像展開 (Photo Expand) 画像を展開する確率 ⭐⭐
シェア (Share) 外部にシェアする確率 ⭐⭐
滞在時間 (Dwell) 投稿に滞在する時間 ⭐⭐
フォロー (Follow Author) 投稿者をフォローする確率 ⭐⭐⭐


実践的アドバイス

表示されやすくするには:
✅ エンゲージメントを促す投稿(いいね、RT、リプライされやすい)
✅ 動画・画像付きコンテンツ
✅ タイムリーな情報
✅ フォロワーとの関係構築

除外されないために:
❌ スパム的な投稿を避ける
❌ 暴力的・不適切なコンテンツを避ける
❌ ミュートキーワードに引っかからない
❌ 重複投稿を避ける



まとめ

今回のXのアルゴリズム更新のポイントは
「人間による調整を徹底的に排除し
AI(Grokベースのモデル)に判断を委ねたこと」にあります。

システムは「フォロー内」と「フォロー外」の投稿を統合し
膨大なユーザー履歴から
「あなたが次にどのボタン(いいね、リプライ等)を押すか」
を精密に予測して並べ替えます。

また、多様性を確保しつつ、不適切なコンテンツや重複を
二段階のフィルタリングで排除する
非常に高度かつクリーンな構成になっています。


アルゴリズムの詳細コードを見たい方は
ぜひgithubの方を見てみてください

それでは。

このページのトップヘ