🤗pyにKISSして🤗
あか(aka7774)によるAI関連のpython成果物に対する提言です!
KISSの原則 (*´з`)
問題意識
- AIエンジニアのコードに再利用性が無さすぎて、ユーザー全員がWebAPIやWebUIを再実装している(俯瞰して見ると車輪の再発明工場になってて、まさにstupid!)
- たまに気合入れて大げさなWebAPIサーバを実装している例があるけど、そういうのは頑張っても動作しないので存在価値が無い(お前のことだぞ、Llava!)
- gradioで凝ったWebUIを無理やりつくると負の遺産になってしまう(私のgithubにはautomatic1111用のExtensionが死屍累々としている)
- という現状を負担感なく改善していきたいよね
あるべき姿
- コマンドラインでもWebAPIでもWebUIでもimportでも同じ処理が動く状態がベスト
- この中で一個だけ作るとしたらWebAPIにして欲しい。最悪 /docs でWebブラウザからでもcurlでも実行できるから。
- コマンドラインオプションが何十個もあるよりは用途別にコマンドが分かれてたほうがコード読む側としてはマシ
- gradioのコードは最小限にして、UIの記述とfnの中身はファイルを分けて、fnの中身だけをimportする
実装テンプレート
app.py
import fn
import gradio as gr
fn.load_model()
with gr.Blocks() as demo:
# UI here
if __name__ == '__main__':
demo.launch()
- gradioを実装する
- 実行とモデルのロードを切り分けて、実行時間を短縮する
- FastAPIでマウントするために、import app出来るよう、勝手にlaunch()しないようにする
- 複数のタブを使うような複雑なUIにする時は、タブごとにファイルを分けると見通しが良くなる
main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import fn
import gradio as gr
from app import demo
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
gr.mount_gradio_app(app, demo, path="/gradio")
fn.load_model()
@app.post("/sample")
async def api_sample(args: dict):
return {}
- FastAPIを実装する。たとえば venv/bin/python -m uvicorn main:app で起動する
- CORSは一旦開けといてもらえると助かる(必要に応じて閉じる)
- /gradio で app にアクセスできるようにして、サーバの起動は1個で済むようにする
- app.py 同様、モデルは事前ロードする(VRAMを別々に食わなくて済む)
- APIの体裁は、Form Upload→binaryのパターンと、base64のjsonで読み書きするパターンの両方あればすごく親切・・・
fn.py
def load_model():
pass
def run():
pass
- load_model() を作っておく。モデルのロードが無い場合も、何もしない関数を残しておくといいかも。
- 具体的な処理はこのファイル内に書いて、app.pyやmain.pyには書かない。
- ファイル名は好きにしていいと思う。私はgradioの呼び方に従った。
venv.sh
#!/usr/bin/bash
python3 -m venv venv
curl -kL https://bootstrap.pypa.io/get-pip.py | venv/bin/python
venv/bin/python -m pip install gradio
venv/bin/python -m pip install -r requirements.txt
- ここまでの手順で作った物は Huggingface Spaces で動かせるので、Online Demoにすると良い。
- CPUとGPUの切り分けが必要な時、それだけのためにtorchをimportしないように気を付ける。
- bash venv.sh とすると、Space が自動で行うセットアップ処理と同じことをしたいという狙い。
- (condaしか導入手順が無いリポジトリは勘弁して欲しい・・・)
requirements.txt
fastapi
uvicorn
- gradioはvenv.shで導入する(バージョンを固定する時もそっちに書く)
README.md
sdk: gradio
sdk_version: 4.20.0
app_file: app.py
- Huggingface Spaces のテンプレートに従う。(gradioのバージョンはここで指定する)
ホーム