Open8

LinuxとPythonとGitHubとDockerを学びながらLangChainの公式チュートリアルをやろうと思い立ち勉強し始めたブランク7年元オンプレWindowsCエンジニアの勉強メモ

segavvysegavvy

はじめに

最近のAIをキャッチアップするため再び開発ができるようになりたい!と思い立ち、3ヶ月程度で最近の環境を学んでAIを使ったちょっとしたコードを書けるようになる!という目標を立てました。

これまでの経験

2017年までソフトウェアエンジニアをやっていました。

主に、Windows Serverで動作する全文検索エンジンの開発(Cとオレオレフレームワーク)や、そのサービスと通信するWindows COMのクライアントコンポーネント(C++とATL)の開発をしていました。ソース管理は伝説のVisual SourceSafeです。コンテナなんてものはなく、VirtualPCやVMwareやHyper-VでOSごと仮想化してました。他にもVBやVBAやVBScript、C#などの開発を経験し、仕事で最後に作ったのはWindowsのGUIアプリ(C#とWPF)です。

2018年以降は職種が変わり、仕事でコードを書く機会がなくなりました。趣味でもDeepLearningの入門書を読んでみたLangChainの入門書を読んでみたりしてPythonのコードを軽く書く程度で、本格的な開発はしていません。

学ぶ段取り

何を学べば良いのかChatGPTのo3-miniと壁打ちしたところ、Linux、Python、GitHub、Dockerを学ぶべきというお告げをもらい、題材はLangChainの公式チュートリアルに決めました。

ただ、Linuxは軽く触った程度でコマンド5個くらいしか知らないですし、Pythonは前述のように入門レベルです。GitHubも単にソース公開のサービスとしてしか使ったことがなく、Dockerはまともに触ったことすらありません。浦島太郎状態もいいところです。

手元にあるMac miniとParallels Desktopを使う前提でo3-miniと相談したところ、次のようなプランができあがりました。

  1. 開発用OSとしてUbuntuの仮想マシン(VM)を用意
  2. それをMacのVS CodeからSSHで接続して利用
  3. Ubuntuで開発環境を構築
  4. LangChainのチュートリアルに挑戦しながらGitHubでバージョン管理
  5. Dockerはここまでできたら挑戦しましょう

Dockerははみ出ちゃいましたね😅

というわけで

平日は本業が忙しいので週末メインです。3ヶ月でどこまで行けるのか不安ですが、3日坊主にならないようにメモを公開していくことにしました。何か間違ったことをやっていたり変な方向に進んでいたら、アドバイスをいただけますとうれしいです!

segavvysegavvy

Parallels DesktopでUbuntuのVM作成

使っているのはParallels Desktop 20 for Mac Pro Edtionです。バージョンは20.2.2 (55879)でした。
Ubuntuのインストールはすごく簡単で、Parallelsの「ファイル」メニューの「新規...」を選んで、無料システムのUbuntu Linuxを選ぶだけです。何もつまずくことなくVMができあがりました。Parallels Desktopがちょっと便利すぎる。これじゃLinuxの勉強にならなそう……

MacにVS Codeをインストール

これはすでに入れていたのでそのまま使います。

Visual Studio Code extension for Parallels Desktopのインストール

Parallelsの起動時にVS Codeの機能拡張Visual Studio Code extension for Parallels Desktopを紹介してくるので入れてみたら、VS Codeの画面内でVMの起動や終了、スナップショットの作成などができるようになりました。これは便利かも。なお、Parallels Desktop ProかBusiness Edtionが必要とのことなのでご注意ください。

ちなみにここでターミナルのアイコン(マウスオーバーで「Get inside VM」と出てくるボタン)をクリックすると、なんとrootでログインできました。すごいな、これ。まだMacとのネットワークすらつながってないはずなので、Parallelsがバイパスしてくれているみたいです。

Macのデフォルトシェルをzshへ切り替え

あと、zshがお勧めですよ、のメッセージが出てますね。ターミナル使う機会があまりなかったので放置してましたが、Apple公式曰くzshいいよ!とのことなので、Macのターミナルを起動して切り替えます。

chsh -s /bin/zsh

これでMacのターミナルでは切り替わったのですが、あれ?VS Codeが連動しない。ChatGPTに聞いたらVS Codeの統合ターミナルのデフォルトシェルも切り替えないとダメとのことで、VS CodeのコマンドパレットでTerminal: Select Default Profile と入力してzshを選択することで切り替えました。

UbuntuにSSHサーバーをインストール

ChatGPT曰くパッケージ管理のツールにはaptapt-getがあって、日常的なパッケージ管理はaptがいいよとのことなので、aptでセットアップします。なお、作業前にVMのスナップショットを作ったので、失敗しても簡単にやり直せます。VMだとこれがホント便利ですね。

なお、先ほどのVS Code機能拡張の「Get inside VM」ボタンで入ったrootで作業してもいいのですが、これだとUbuntuの画面に触れる機会がなくなってしまいそうなので、あえてVM側の画面からやってみます。

sudo apt update

これでaptのパッケージリストが最新になりました。
続いてopenssh-serverのインストールです。

sudo apt install openssh-server

問題なさそうなので起動します。

sudo systemctl start ssh

そして状態の確認です。

sudo systemctl status ssh

お、activeとなっているので良さそう!
あと、これだとUbuntuの起動と連動しないみたいなので、自動起動にしておきます。

sudo systemctl enable ssh

MacとUbuntu VMを同じネットワークに変更

MacのIPアドレスはDHCPで取得している192.168.210.92なのですが、VMのUbuntuは違うネットワークになっているので合わせます。

ParallelsのVMの初期設定では「共有ネットワーク」になっていてParallelsのNAT機能でIPが振られてしまうので「ブリッジネットワーク」に切り替えます。

これでMacと同じネットワークになりました。

ega@M2-Mac-mini ~ % ping 192.168.210.107
PING 192.168.210.107 (192.168.210.107): 56 data bytes
64 bytes from 192.168.210.107: icmp_seq=0 ttl=64 time=0.552 ms
64 bytes from 192.168.210.107: icmp_seq=1 ttl=64 time=0.491 ms
64 bytes from 192.168.210.107: icmp_seq=2 ttl=64 time=0.696 ms
64 bytes from 192.168.210.107: icmp_seq=3 ttl=64 time=0.779 ms
64 bytes from 192.168.210.107: icmp_seq=4 ttl=64 time=0.560 ms
^C
--- 192.168.210.107 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.491/0.616/0.779/0.106 ms

つながった!

MacのVS Codeに「Remote - SSH拡張機能」をインストール

MacのVS CodeからUbuntu VMを使うためにRemote - SSH拡張機能をインストールします。

接続先の設定を~/.ssh/configに書かないといけないのですが、歯車アイコンを押すと新規ファイルを作ってくれます。便利!

我が家のPCはマンション共用のルーターのDHCPでIPアドレスが振られており(マンション各戸は同じネットワークを共用するのですがVLANで区切られているそう)、IPアドレスがきまぐれで変わります。そのため、本当はホスト名で指定したりIPを固定化しておきたいのですが、残念ながらDHCPの設定は変えられないので、変更に気づいたら都度直すことにします。

Host Ubuntu
    HostName 192.168.210.107
    User parallels

これでVS Codeから接続すると、フィンガープリントの確認とパスワードの入力を経て、無事接続できました!

これ、ファイル操作だけでなくプロセス動かしたりデバッグしたりできる訳ですよね。MacのVS CodeであたかもローカルのようにUbuntuが使えるとは。しばらく開発から遠ざかっていた間に、世の中がすごく進化していました😁

あと、ここまで数時間でつまずかずにこれたのはChatGPTのおかげです。昔だったらあっという間に1日溶けてたかも。AIの進化で勉強時間が短縮できるようになったのはホントありがたいです。

segavvysegavvy

UbuntuでPythonの開発環境の構築

ここからはPythonの開発環境の構築なのですが、バージョン管理やパッケージ管理の仕組みが乱立してて、どれを使えばいいのかさっぱりわかりません。軽くググっただけでも、venv、pip、pyenv、Pipenv、poetry、asdf、……いやいや、ちょっと多すぎ。

そんな中で、この整理に最適な記事を発見しました!なんと知り合いの@oshima_123さんの記事!これはありがたい!

https://zenn.dev/os1ma/articles/935f6e653f1052

こちらの動画でも解説されています!

https://www.youtube.com/watch?v=yjjYg6zCCwc

また、最近だとこの問題を解決すべく、uvというのがあることもXで教えていただきました。

https://x.com/tetsu_1008/status/1908761898461651348

どれを使うか悩みましたが、いきなり統合された便利なものを使うと中身がブラックボックスになってしまい仕組みが理解ができなくなりそうなので、まずはシンプルな機能しかないpyenv、venv、pipを触ってみて、その後でasdf+Poetryやuvなどの統合されたものに進もうと思います。

ということで、Pythonのバージョン管理にpyenv、仮想環境の管理にvenv、パッケージ管理にpipを使う形で環境構築に挑みます。

segavvysegavvy

pyenvのインストール

公式の手順に従ってインストールしてみます。2025/04/06時点の手順です。
https://github.com/pyenv/pyenv?tab=readme-ov-file#linuxunix

A. Getting Pyenv

まず、推奨になっているインストーラーの実行です。

curl -fsSL https://pyenv.run | bash

bash用のスクリプトがダウンロードされて実行される形です。なるほど、デフォルトのシェルがなんであれ、この形ならbashのスクリプトだけ用意すれば済む訳ですね。

B. Set up your shell environment for Pyenv

続いてシェルの環境設定ですが、ここはシェルごとに異なります。そもそも、Ubuntuで動いてるシェルが何なのかすら知らない状態なので、その確認から。$SHELL変数を確認すればいいそうです。

$ echo $SHELL
/bin/bash

bashなことがわかったので、bashの手順で設定します。

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc

シェルの文法がさっぱりわからなかったので軽く調べました。

  • exportは環境変数を設定するもので、PYENV_ROOTに$HOME/.pyenvを設定
  • [[ -d $PYENV_ROOT/bin ]]は条件分岐で、-dは指定パスがディレクトリかどうかチェック、もしそうなら&&以降のexportでPATHの先頭に$PYENV_ROOT/binを挿入
  • evalはシェルのコードを実行するもので、pyenv init - bashが出力するシェルコードを実行
  • echoは標準出力の表示で、それを>>でリダイレクトすることで~/.bashrcに追記

また、~/.profileも存在したので同様に追記します。これは、bash以外のシェルでも共通で設定したいものを書く場所だそうです。

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
echo 'eval "$(pyenv init - bash)"' >> ~/.profile

~/.bash_profile~/.bash_loginは存在しなかったので、特に何もしないでよいのかな。
それにしても、シェルの文法やファイルの使われ方は、慣れるまでにちょっと時間がかかりそうです。Windowsとも違うしシェルも何種類もあるし、なんで人類は似たようなものをたくさん作ってしまうのか……

C. Restart your shell

手順にしたがってシェルを再起動します。

exec "$SHELL"

D. Install Python build dependencies

Pythonのビルドに必要な環境の構築です。手順に従ってaptでインストールします。

sudo apt update; sudo apt install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl git \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

また、以下のような説明がありました。

The Python's documentation reports a different set of dependencies in the documentation and in the script used in the GitHub Actions

If you are going build PyPy from source or install other Python flavors that require CLang, also install llvm.

(Google翻訳)
Pythonのドキュメントでは、ドキュメントとGitHub Actionsで使用されるスクリプトで異なる依存関係のセットが報告されています。

PyPy をソースからビルドする場合、または CLang を必要とする他の Python フレーバーをインストールする場合は、 もインストールしてくださいllvm。

なるほど、いわゆる普通のC言語で作られたCPython以外に、PythonにはPyPyやその他のバリエーション(フレーバー)があるんですね。で、それらを入れる場合はビルドが必要なので追加でllvmが必要になると。現時点では普通のCPython以外を使うかわからないので、とりあえず入れないでおきましょう。

pyenvを使ってみる

これで使えるはず。

まず、使えるPythonのバージョンの一覧を表示。

pyenv install --list

すごくたくさん出てきました。2025/04/06時点で最新の3.13.2を入れてみます。

pyenv install 3.13.2

無事インストールできたので、バージョン一覧を表示してみます。

$ pyenv versions
* system (set by /home/parallels/.pyenv/version)
  3.13.2

これで元々のUbuntuに入っていたものと3.13.2の2種類が入った状態になりました。今のバージョンを調べてみます。

$ python3 --version
Python 3.12.3

今は3.12.3でした。これがUbuntsに入っていたものですね。これをグローバルで3.13.2に切り替えてみます。

$ pyenv global 3.13.2
$ pyenv versions
  system
* 3.13.2 (set by /home/parallels/.pyenv/version)
$ python3 --version
Python 3.13.2

切り替わりました!
pyenvのインストール完了です!

segavvysegavvy

pythonpython3の違い

venvに進む前にふと思ったのが、pythonpython3の違い。これはPython 2とPython 3の過渡期の名残り?のようで、最近はどちらもでPython 3が動くみたいです。

$ python --version
Python 3.13.2
$ python3 --version
Python 3.13.2

確かにバージョンは同じですね。Pythonの実行ファイルは同じなのでしょうか?

$ which python
/home/parallels/.pyenv/shims/python
$ which python3
/home/parallels/.pyenv/shims/python3

これはpyenvが環境切り替えのために用意しているスクリプトでした。中身はどちらもこんな感じです。

#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

program="${0##*/}"

export PYENV_ROOT="/home/parallels/.pyenv"
exec "/home/parallels/.pyenv/libexec/pyenv" exec "$program" "$@"

環境変数を追加してpyenv exec python〜に読み替えているみたいですね。これだと、最終的にどの実行ファイルが動いているのかわかりません。

ChatGPTに聞いたら、Pythonのプログラム内からsys.executableで実行ファイルのパスがわかるとのこと。こっちで調べてみましょう。

$ python
Python 3.13.2 (main, Apr  6 2025, 21:30:52) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.executable)
/home/parallels/.pyenv/versions/3.13.2/bin/python
$ python3
Python 3.13.2 (main, Apr  6 2025, 21:30:52) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.executable)
/home/parallels/.pyenv/versions/3.13.2/bin/python3

あれ?やっぱり実行ファイルが違う。lsで確認してみます。

$ cd /home/parallels/.pyenv/versions/3.13.2/bin/
$ ls -al python*
lrwxrwxrwx 1 parallels parallels    10 Apr  6 21:31 python -> python3.13
lrwxrwxrwx 1 parallels parallels    10 Apr  6 21:31 python3 -> python3.13
-rwxr-xr-x 1 parallels parallels 72224 Apr  6 21:30 python3.13
-rwxr-xr-x 1 parallels parallels  3377 Apr  6 21:31 python3.13-config
-rwxr-xr-x 1 parallels parallels 70581 Apr  6 21:31 python3.13-gdb.py
lrwxrwxrwx 1 parallels parallels    17 Apr  6 21:31 python3-config -> python3.13-config
lrwxrwxrwx 1 parallels parallels    17 Apr  6 21:31 python-config -> python3.13-config

お、->はシンボリックリンクだそうなので、Windowsのショートカットみたいなものですね。どちらも同じ実行ファイルpython3.13を指していることが確認できました。これならどちらを使っても大丈夫そうですが、古い環境でも大丈夫なように以降もpython3で進めます。

venvのインストール

venvをインストールしようと思ったのですが、python標準なのでインストール不要でした。公式の以下の説明を見て進めます。

https://packaging.python.org/ja/latest/guides/installing-using-pip-and-virtual-environments/

今回は~/projects/langchain-tutorialディレクトリを作って、ここで作業する環境を作りました。

$ pwd
/home/parallels/projects/langchain-tutorial
$ python3 -m venv .venv

これでvenvの環境構築完了です。

$ source .venv/bin/activate

これでアクティベートできました。

$ which python
/home/parallels/projects/langchain-tutorial/.venv/bin/python
$ python3 --version
Python 3.13.2

きちんと.venv以下のpythonが動いていますね。ここでpyenvとの関係が気になったので、ちょっと確認してみます。

$ ls -l /home/parallels/projects/langchain-tutorial/.venv/bin/python
lrwxrwxrwx 1 parallels parallels 49 Apr  7 00:28 /home/parallels/projects/langchain-tutorial/.venv/bin/python -> /home/parallels/.pyenv/versions/3.13.2/bin/python

お、きちんとpyenvの環境下のpythonを指していますね。ただ、シンボリックリンクになっているので、おそらくpyenvでPythonのバージョンを切り替えても動的には追従しないんじゃないかと思います。ちょっと試してみましょう。

$ pyenv versions
  system
* 3.13.2 (set by /home/parallels/.pyenv/version)
$ pyenv global system
$ pyenv versions
* system (set by /home/parallels/.pyenv/version)
  3.13.2
$ python3 --version
Python 3.13.2

ですよね。systemは3.12.3なのですが切り替わりません。
venvの環境を作る時は、先にpyenvを使ってPythonのバージョンを切り替えておく必要がありそうです。

venvの環境を終了してみましょう。

$ deactivate 
$ python3 --version
Python 3.12.3

これで、pyenvの指定した環境に戻りました。
混乱しそうなので、pyenvでも最新の3.13.2に戻して先に進みます。

$ pyenv global 3.13.2

venvの仕組み

venvの仕組みについては、前回紹介した記事や動画のスライドがわかりやすかったです。

https://speakerdeck.com/os1ma/pythonno-jia-xiang-huan-jing-wowan-quan-nili-jie-siyou

いくつか備忘のためにメモを。

  • venvもpyenv同様、仮想環境と言っても使うディレクトリを切り替えているだけ
  • activateコマンドで環境変数PATHの先頭に独立したディレクトリを追加してくれる
  • activateコマンドの実体はシェルスクリプトで、環境変数を変更するためにsource.)コマンドで実行しないといけない(後述)
  • インストールするPythonのモジュールは独立したディレクトリに配置されていく
  • deactivateで戻してくれる

ちょっとややこしかったのは、LinuxがWindowsのコマンドプロンプトとは違う点です。
Windowsではコマンドプロンプトでバッチファイルを実行しても同じプロセスで動き、別プロセスにするにはstartコマンドが必要です。これに対してLinuxでは、普通にシェルスクリプトを動かすと別プロセスになり、同じプロセスで動かすにはsource.)コマンドが必要ということですね。そのため、activateではsourceコマンドが必要になります。
あと、同じく環境変数を戻すdeactivatesourceコマンドなしでなぜ動くのかというと、これはactivateのシェルスクリプト実行時にシェル関数として組み込まれるので、シェル関数として同じプロセスで実行されるからですね、なるほど。

それにしても、source.と略しちゃうのはやりすぎでは?と思ったら、なんと.が先で、後からsourceができたそうです。UNIX系のシェルは奥が深いな。

pipのインストール

pipもPython標準なのでインストール不要ですが、最新版にするために、以下の公式の手順を実行します。

https://packaging.python.org/ja/latest/guides/installing-using-pip-and-virtual-environments/#prepare-pip

まず、venvのアクティベート。

$ . .venv/bin/activate

そしてpipの最新化です。

$ python3 -m pip install --upgrade pip
Requirement already satisfied: pip in ./.venv/lib/python3.13/site-packages (24.3.1)
Collecting pip
  Downloading pip-25.0.1-py3-none-any.whl.metadata (3.7 kB)
Downloading pip-25.0.1-py3-none-any.whl (1.8 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 19.8 MB/s eta 0:00:00
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 24.3.1
    Uninstalling pip-24.3.1:
      Successfully uninstalled pip-24.3.1
Successfully installed pip-25.0.1
$ python3 -m pip --version
pip 25.0.1 from /home/parallels/projects/langchain-tutorial/.venv/lib/python3.13/site-packages/pip (python 3.13)

これで2025/04/13時点の最新である25.0.1がインストールされました。

LangChainのインストール

続いて、LangChainのインストールです。ここでLangChainの公式ページを見ていて気になったことが。

https://python.langchain.com/docs/introduction/

たとえばOpenAIのモデルを使う場合、セットアップのコマンドは公式だと以下の感じで直接pipコマンドを叩いています。

pip install -qU "langchain[openai]"

でも、Pythonの以下の公式ガイドでは、python3 -mを実行する形になっています。

https://packaging.python.org/ja/latest/guides/installing-using-pip-and-virtual-environments/#install-packages-using-pip

python3 -m pip install requests

そもそも-mは何するオプションなのかを調べてみたら、指定したモジュールの__main__を実行するものでした。Pythonをまだちゃんとわかっていませんが、pip自体もPythonで作られたモジュールということですね。

そうなるとよくわからないのが、pipでなぜ直接実行できるのかなのですが、これも調べたら、単にPythonで書かれたスクリプトになっていて、pipのmain()を実行する形になっていました。

#!/home/parallels/projects/langchain-tutorial/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

つまり、どっちも同じということみたいです。

ちょっと脱線してしまいますが、スクリプトファイルの先頭行で#!付けてpythonの実行ファイルを指定したら、Pythonのコードをシェルスクリプトのように実行できるんですね。てっきりシェルの指定しかできないのかと思っていました。Windowsだと同じことするには拡張子の紐付けが絡んで面倒なことになるので、Linuxはいろいろと新鮮です。

どちらでも良さそうなことがわかったので、シンプルにpipでインストールしてみます。私はすでにOpenAIのAPI-KEYがあるので、chat modelで「OpenAI」を選択して案内されるpipコマンドを実行してみました。

pip install -qU "langchain[openai]"

インストールが終わったので、公式ガイドの通りに実行してみます。Pythonのインタラクティブモードで試してみました。

$ python3
Python 3.13.2 (main, Apr  6 2025, 21:30:52) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import getpass
... import os
... 
... if not os.environ.get("OPENAI_API_KEY"):
...   os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")
... 
... from langchain.chat_models import init_chat_model
... 
... model = init_chat_model("gpt-4o-mini", model_provider="openai")
... 
Enter API key for OpenAI: 
>>> model.invoke("Hello, world!")
AIMessage(content='Hello! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 11, 'total_tokens': 21, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_44added55e', 'id': 'chatcmpl-BLkBXygmOENUNjSnWtL6YJdMCcA8N', 'finish_reason': 'stop', 'logprobs': None}, id='run-1421b243-2ba9-4d6c-9a4c-360730bf9786-0', usage_metadata={'input_tokens': 11, 'output_tokens': 10, 'total_tokens': 21, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})
>>> 

おぉ、「Hello! How can I assist you today?」が返ってきた!
LangChainのインストール完了です!

segavvysegavvy

Pythonの開発環境の構築

先週、LangChainのインストールまでしてしまいましたが、VS CodeでのPtyhonの開発環境を整えるのが先でした。

今日はVS Codeの本家サイトにあるチュートリアル「Getting Started with Python in VS Code」(VS Code で Python を使い始める)をGoogle翻訳で訳しつつ、VS CodeでPythonのhello world!に挑戦してみます。

https://code.visualstudio.com/docs/python/python-tutorial

Prerequisites(前提条件)

ややこしかったのが、VS Code拡張機能の「Python」をMac側に入れるのかUbuntu側に入れるのかです。今回はUbuntuを使うので、MacのVS Codeを使っていてもインストールはUbuntu側だそうです。Mac上のVS Codeは本当にUIの上っ面だけを実行している形ですね。

Install a Python interpreter(Pythonインタープリターをインストールする)

これは先週pyenvを使って完了しています。

Start VS Code in a workspace folder(ワークスペースフォルダでVS Codeを起動する)

先週は~/projects/langchain-tutorialを作ってLangChainをインストールしたのですが、今回はそれとは別に~/projects/helloディレクトリを作成することにしました。ここをVS Codeの「ファイル」ー「フォルダーを開く...」メニューで開きます。

Create a virtual environment(仮想環境を作る)

なんと、コマンドパレットで「Python: Create Environment」するとvenvの環境が作れるそうです。

ここで「Venv」を選択して、

あれ?pyenvで入れた「3.13.2」の環境がでてこない😢

でも「Python: Select Interpreter」でインタープリターを選択する時はpyenv環境も出てきます。不思議。

どうやらこのissueが同じことを言っている風なのですが、すでに1年前に修正されている模様です(Google翻訳だとイマイチ正確に読み取れず違うかも😅)。

https://github.com/microsoft/vscode-python/issues/20881

ちょっと調べた感じだとshim(先週、pipがなぜ直接実行できるのかを調べたらスクリプトになっていましたが、そのようなスクリプトの総称みたいです)のPATHが通ってないみたいな解説が出てくるのですが、先週pyenvをインストールした際に~/.bashrc~/.profileに追記したeval "$(pyenv init - bash)"でshimのPATHもきちんと通るようです。そもそも「Python: Select Interpreter」で出てくる段階でVS Codeは認識してますもんね。原因がよくわかりません。

とりあえず「Python: Create Environment」でインタープリターを選ぶ際に、pyenvで入れた3.13.2の場所/home/parallels/.pyenv/versions/3.13.2/bin/pythonを選んで進んでみると、「.venv」ディレクトリができました!

どうやらpython3 -m venv .venvをやってくれたみたいです。コマンドを覚えるのが苦手な私にとって、これは便利!

Create a Python source code file(Pythonソースコードファイルを作成する)

おぉ、インテリセンスもきちんと働きます。これもUbuntu側で動いてMacのVS Codeは表示しているだけなのか、なかなかすごいです。

Run Python code(Pythonコードを実行する)

動いた!

ということは、venvのアクティベートsource .venv/bin/activateも自動でやってくれていますね。便利!

Configure and run the debugger(デバッガーを設定して実行する)

デバッガーも問題なく動きました。リモートデバッグもリモートであることをまったく意識させません。すごいな。ホント、浦島太郎状態です。

Install and use packages(パッケージをインストールして使用する)

新規でターミナルを開くと、自動的にvenvのアクティベートが実行されています。ターミナル名にマウスを持っていくと説明が出てきました。

$VIRTUAL_ENVも確かに切り替わっています。

アクティベートの意識が不要なのは便利ですね。無事、venv環境にnumpyもインストールでき動きました!

以降、VS Codeでこのhelloディレクトリを開けば、このプロジェクト用のvenvがアクティベートされ、ターミナルを開いてpip installすればvenvの環境内にインストールされます。venvのコマンドは忘れても大丈夫かも。VS Code様さまです!

segavvysegavvy

VS Code以外で作ったvenv環境をVS Codeで開くとどうなる?

コマンドパレットで「Python: Create Environment」するとvenv環境を作れることがわかりましたが、先週python3 -m venv .venvで作ってしまったLangChainのインストール環境がどうなるのか確認しました。

VS Codeでこの~/projects/langchain-tutorialを開いて、コマンドパレットで「Python: Create Environment」を選び「Venv」を選択すると「既存のものを使用」が!

これを選ぶとちゃんと使えました。新規のターミナルにもきちんと反映されていてLangChainがインストール済みになっています。

いいね!

segavvysegavvy

GitHubの概要把握

GitHubをきちんと勉強したことがなかったので、本家サイトのGet Startedの「体験してみる」を一通り読んでみました。

https://docs.github.com/ja/get-started/start-your-journey

なんとなく聞いたことがある程度だったブランチ、コミット、プッシュ、プルリクエスト、マージ、クローン、フォークなどの言葉が理解でき、すっきりしました。

クローンとフォークが少し迷いましたが、クローンはローカルにコピーする作業で、フォークは元を枝分かれさせてサーバ側でコピーする機能ですね。

VS CodeでのGitHubの使い方

続いて、VS CodeによるGitHubの使い方を、Google翻訳に頼りながら本家サイトの「Using Git source control in VS Code」で勉強してみます。YouTubeの動画も日本語の字幕が出せるのでなんとかなるかな。

https://code.visualstudio.com/docs/sourcecontrol/overview

Working in a Git repository(Gitリポジトリでの作業)

さっそく、LangChainの最初のチュートリアルBuild a simple LLM application with chat models and prompt templates(チャットモデルとプロンプトテンプレートを使用してシンプルな LLM アプリケーションを構築する)を題材にGitHubを使ってみようと思ったのですが、LangChainのこのチュートリアルはJupyter Notebookが前提になっていました。右上に「Open in Colab」のボタンまで用意されています。確かにGoogle Colabなら環境に依存する問題がないのでチュートリアルには最適です。

https://python.langchain.com/docs/tutorials/llm_chain/

でも、Google Colabを使ってしまうとGitHubやVS Codeの勉強にならないので、このチュートリアルの内容を使いつつも自分でGitのリポジトリを作ってみようと思います。

Cloning a repository(リポジトリのクローン作成)

今回はクローンせずに自分で作るので、「Open Folder」で前回インストール時に作ったvenvのフォルダー~/projects/langchain-tutorialを開きます。それにしても、開くだけでvenvのアクティベートを自動でやってくれるのは便利ですね。せっかく学んだvenvのことを忘れるのも時間の問題です😅

Initialize a repository(リポジトリを初期化する)

「Initialize Repository」ボタンでリポジトリを初期化し、「simple_llm_application.py」を作って、チュートリアルの最初のブロックを貼り付けます。

simple_llm_application.py
import getpass
import os

try:
    # load environment variables from .env file (requires `python-dotenv`)
    from dotenv import load_dotenv

    load_dotenv()
except ImportError:
    pass

os.environ["LANGSMITH_TRACING"] = "true"
if "LANGSMITH_API_KEY" not in os.environ:
    os.environ["LANGSMITH_API_KEY"] = getpass.getpass(
        prompt="Enter your LangSmith API key (optional): "
    )
if "LANGSMITH_PROJECT" not in os.environ:
    os.environ["LANGSMITH_PROJECT"] = getpass.getpass(
        prompt='Enter your LangSmith Project Name (default = "default"): '
    )
    if not os.environ.get("LANGSMITH_PROJECT"):
        os.environ["LANGSMITH_PROJECT"] = "default"
if "OPENAI_API_KEY" not in os.environ:
    os.environ["OPENAI_API_KEY"] = getpass.getpass(
        prompt="Enter your OpenAI API key (required if using OpenAI): "
    )

環境変数を読み込むコードしかないですが、GitHubの練習なのでまずはこれでいいでしょう。

あれ?dotenvが見つからないと言ってますね。python-dotenvが必要みたいなのですが、Pythonと一緒には入らないのかな。VS Codeのターミナルでpip showして確認してみます。

$ pip show python-dotenv
WARNING: Package(s) not found: python-dotenv

やっぱりないので、pip install python-dotenvでインストールしました。そうしたら、インストール直後にソースから警告が消えました。リアルタイムで反映されるのすごい。

APIキーなどは、プロジェクトルートの.envファイルに書いておけばいい感じでしょうか。とりあえず必要になりそうなものを書き込んでおきます。LangSmithのAPIキーもOpenAIのAPIキーも以前の勉強で作成したものです。

.env
LANGSMITH_TRACING="true"
LANGSMITH_API_KEY="hogehoge"
OPENAI_API_KEY="fugofugo"
LANGSMITH_PROJECT="langchain_tutorial"

あと、python-dotenvの「Getting Started」にある以下の注意に従い、.gitignoreファイルを作って記入しておきます。

You will probably want to add .env to your .gitignore, especially if it contains secrets like a password.
(特にパスワードなどの秘密情報が含まれている場合は、.gitignoreに.envを追加することが必要になる可能性があります。)

.gitignore
.env

そういえば、.venvディレクトリは何もしていないのに初めからGitの管理対象外になっています、不思議。ちょっと調べたら、公式サイト曰く、version 3.13から.venvディレクトリの直下に.gitignoreが作成されるようになったとのことで、ファイルの覗いたら*が書いてありました。いたせりつくせりです。

Commit(コミット)

Gitはコマンド覚えるのが大変かと思ったら、VS Code使うと操作がGUIでできてしまいます。コマンド覚えないで済むのはありがたい!
なお、YouTubeの動画では「出力」タブに実行したgitのコマンドが表示されると解説されていたのですが、なぜか表示されません。が、よく見たら切り替えのメニューがありました。

動画ではスタッシュなどの操作説明もありますが、いつ使うのかピンときていません。この辺は使うようになった時に戻ってこようと思います。

初めてコミットしようとしたらGitの設定が足りない!と怒られました。「詳細を表示」ボタンで表示される本家のページを見ながらセットアップします。

https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup

$ git config --global user.name "segavvy"
$ git config --global user.email segavvy@yahoo.co.jp

これでコミットもできました!

あと、解説の中でGenerate a commit message with AI(AIでコミットメッセージを生成する)というのがあったので試してみます。

画面にあるcopilotアイコンをクリックするとMicrosoftアカウントの設定を求められるので、指示に従って設定するとGitHub Copilotのフリープランが使えるようになります。

なんと、もうGPT-4.1(Preview)が選べます。さっそく、この貼り付けたコードをチェックしてもらいました。

これはいいですね!
コミットメッセージの生成も試してみましょう。チュートリアルの続きのコードを追加してコミットしてみます。

simple_llm_application.pyに追記
# ----------------------------------------------------
from langchain.chat_models import init_chat_model

model = init_chat_model("gpt-4o-mini", model_provider="openai")

from langchain_core.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage("Translate the following from English into Italian"),
    HumanMessage("hi!"),
]

model.invoke(messages)

ここでコミットメッセージの入力欄の右にあるアイコンをクリックすると、Copilotがコミットメッセージを生成してくれます!

いやはや、すごい時代になってきました。

Git blame information(Gitの責任情報)

Google翻訳の「責任情報」が何のことだかわからなかったのですが、最終のコミット情報を表示してくれる機能ですね。デフォルトではステータスバーに表示されていました。

コマンドパレットから「Git: Toggle Git Blame Editor Decoration」で切り替えるとエディタ上にもでてきます。便利!

ただ、ちょっとエディタ上のはちょっとウザいかな。OFFに戻して進みます。

Review uncommitted code changes with AI(コミットされていないコードの変更を AI で確認)

コミット前にCopilotがレビューしてくれる機能があるそうなので、ソースコードの終わりの部分をチュートリアルの続きのコードに変えて、ストリーミング呼び出しにしてみます。

simple_llm_application.pyの末尾を更新
for token in model.stream(messages):
    print(token.content, end="|")

ここでCopilotにレビューさせてみました。

ストリーミングのループの最後に改行入れたらどう?とのご指摘です。確かにそうなので、
その下にある「Apply」ボタンを押してソースに反映し、Copilotにコミットメッセージを書かせてコミットしました。Copilot、なかなかいいじゃないですか!

なお、レビューのコメントが英語なのが残念ですが、これは本家サイトの説明曰く、カスタム指示の設定で直せそうです。

https://code.visualstudio.com/docs/copilot/copilot-customization

このページのUse settings(設定を使用する)に従って、Code reviewのgithub.copilot.chat.reviewSelection.instructionsを設定してみます。[Code]メニューの「基本設定」ー「設定」で設定を探せばOKですね。

すでにコミットしてしまったので、コマンドパレットから「Git: Undo Last Commit」して、最後のprint()もない状態に戻して再度レビューさせてみます。

あれ?ダメですね。VS Codeを起動しなおしたり、Ubuntu側に反映できていないのかと思いコマンドパレットから「Developer: Reload Window」もやってみたのですが英語になってしまいます。今設定しているのは「選択範囲のレビュー」なのですが、もしかしたら今使っている「コミット前のレビュー」とは異なる機能なのかも!コミット前のレビューに対するカスタム指示はUse settings(設定を使用する)にないので、今はまだ設定できないのかもしれませんね。

今日は最後に、このコードをGitHubのサーバーに公開してみました。左下のアイコンを選んで、

サインインを許可して、

画面の指示に従っていけばOKです。プライベートなリポジトリが無事できあがりました!

それにしても、VS CodeだとGitのコマンドをまったく打たないですね。コマンド覚えなくて本当にいいのか不安になるレベルです。

あと、今日初めてGitHub Copilotを触りましたが、なかなかいい感じです。ただ、右下のCopilotアイコンで使用量を見たら、ちょっと使っただけなのにチャットメッセージはもう6%の消費。Freeプランだとあっという間になくなりそう。