
こんにちは、CCCMKホールディングスAIエンジニアの三浦です。
AI Agentを使って開発をしていると、自分が詳しく知らない言語やフレームワークを使って大量のコードを書き出してしまうことが多く、自分で開発しているはずなのにどこか地に足がついていないような感覚に陥ることがよくあります。
自分にとって未知の技術を使われてしまうと開発した成果物に対する説明が十分に出来なくなってしまうため、これは避けたい事象です。
AI Agentをうまく制御出来ない時、大抵自分自身の基準がぶれていたり定まっていない時がほとんどです。AI Agentがよく分からないフレームワークや言語を使ってしまうのも、開発においてこの言語やフレームワークを使うべきである、という明確な指針がないことが原因だと考え、最近これらを明確にしたいと調査を進めていました。
検討中のツール
私たちのこれまでの開発案件や今後の方針を考えてみると、次のような開発が多くなると考えています。
- Pythonをメインの言語として使用する
- 既存システムにAI/ML系の機能をAPIで提供する
- API開発がメインだけどコンセプトを伝えるためにUIの開発も必要になることがある
- アプリのデプロイ先はAzure App Serviceがメイン
これらを踏まえてベースとなる開発ツールやフレームワークを最新の動向を参考にまとめてみると以下のようになりました。
| スコープ | ツール |
|---|---|
| ローカル環境 | uv |
| 本番環境 | docker |
| リンター・フォーマッター | ruff |
| テスト | pytest |
| フロント | htmx + jinja2 |
| API | fastapi |
| コード管理 | Azure DevOps |
| CI/CD | Azure Pipelines |
| AI開発 | Github Copilot |
とくにPythonの環境構築・管理でよく使われているのがuvというツールです。uvを導入することでpipやvenv, pyenvといったツールを使う異なるuv一本で対応することが可能です。さらにパッケージのインストールが超高速で、pipの10~100倍速いそうです。
今回はこのuvでどんなことが出来るのかを調べてみたことをまとめていきたいと思います。
uvを導入してみよう
Linuxでuvをインストールするには以下のコマンドを実行します。
curl -LsSf https://astral.sh/uv/install.sh | sh
uvのinitコマンドを使うとPythonのプロジェクトを初期化して作成することが出来ます。
uv init test-project
以下のメッセージが表示されます。
Initialized project `test-project` at `/home/xxxx/test-project`
プロジェクト名のフォルダが、以下の構成で作成されます。プロジェクトの基礎となるファイルが自動生成されています。
test-project/ ├── .git/ ├── .gitignore ├── .python-version ├── README.md ├── main.py └── pyproject.toml
pyproject.tomlはプロジェクトの構成が記されたファイルで初期状態では次のような内容になっています。
[project] name = "test-project" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = []
Pythonのバージョンを管理する
uvはpyenvのようにPythonのバージョンを管理する機能を持っています。
インストール済みもしくはインストール可能なPythonのバージョン一覧を確認。
uv python list
次のように一覧表示されました。
cpython-3.15.0a3-linux-x86_64-gnu <download available> cpython-3.15.0a3+freethreaded-linux-x86_64-gnu <download available> cpython-3.14.2-linux-x86_64-gnu <download available> cpython-3.14.2+freethreaded-linux-x86_64-gnu <download available> cpython-3.13.11-linux-x86_64-gnu <download available> cpython-3.13.11+freethreaded-linux-x86_64-gnu <download available> cpython-3.12.12-linux-x86_64-gnu <download available> cpython-3.12.3-linux-x86_64-gnu /usr/bin/python3.12 ...
特定のバージョンをインストールしたい場合は
uv python install 3.11.14
のようにしてインストールが出来ます。
プロジェクトで使用するPythonのバージョンを固定する場合pyproject.tomlのrequires-pythonと矛盾したものは指定できないため、値を編集します。
requires-python = ">=3.12" ↓ requires-python = ">=3.11"
その後、次のコマンドで使用するPythonのバージョンを変更できます。
uv python pin python3.11.14
このコマンドが成功すると、プロジェクトフォルダ内の.python-versionファイルの内容書き変わり、uv python pinで指定したPythonのバージョン番号が書き込まれます。
パッケージのインストール
プロジェクトに新しいパッケージを追加する場合はuv addを使用します。
uv add fastapi
実行するとまず仮想環境が.venvに作成されます。その後依存関係の解消と依存パッケージのインストールが行われるのですが・・・とんでもなく高速です。
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12 Creating virtual environment at: .venv Resolved 11 packages in 675ms Installed 10 packages in 203ms + annotated-doc==0.0.4 + annotated-types==0.7.0 + anyio==4.12.1 + fastapi==0.128.0 ...
pyproject.tomlのdependenciesには自動的にaddしたパッケージが追記されています。
dependencies = [ "fastapi>=0.128.0", ]
全ての依存パッケージは、uv.lockというファイルに書き込まれます。
また、本番環境では必要ないけれど開発時に必要になるパッケージも出てくることがあります。その場合は以下のように--devオプションを付けて実行します。
uv add --dev pytest
pyproject.tomlに以下の内容が追記されます。
[dependency-groups]
dev = [
"pytest>=9.0.2",
]
別の環境でプロジェクトの環境を再現する場合、uv syncコマンドを使って依存パッケージのインストールをすることが出来ます。pip install -r requirements.txtのイメージですね。
uv sync
先ほど述べたように、開発時にだけ使うパッケージが含まれている場合、本番環境ではそれらを除いたパッケージをインストールしたい場合は次にように実行することが出来ます。
uv sync --no-dev
さらにuv syncには--frozenと--lockedというオプションを指定することが出来ます。どちらもpyproject.tomlとuv.lockに差分が生じている場合の動作に影響するもので、いずれのオプションも指定していないとuv.lockが更新されインストール、--frozenの場合はuv.lockの内容を正としてインストール(uv.lockは更新されない)、--lockedの場合はエラーで失敗する、という動作になります。
スクリプトの実行
プロジェクトの中でPythonのスクリプトを実行する場合は
uv run main.py
のように実行するとpyproject.tomlの内容に従ってスクリプトが実行されます。プロジェクト外でスクリプトを実行したい場合で依存ライブラリを使いたい場合は以下のように実行することが出来ます。
uv run --with 'fastapi' sample.py
この場合、一時的に仮想環境が作られ依存パッケージがインストールされる動きになり、既存の環境を汚すことなくスクリプトの実行が可能になります。
まとめ
最近uvでプロジェクト管理されている事例をよく見ることがあってどんなものなんだろう、と気になっていたのですが、使ってみると確かにすごく便利だな、と感じました。特にパッケージのインストールがものすごく高速で衝撃的でした。
uvを中心にruffやテストを実施するpytestを組み込んでいって開発環境を充実させていきたいと思います。