AIでPCを操作できるということだ
通常のClaudeのチャットからは、メニューが見当たらない。
aiに、Computer useを使ってみたいと質問したところ以下のURLを紹介してもらえた
https://docs.anthropic.com/en/docs/build-with-claude/computer-use
(英文)
まだ、beta版のようである。(この記事を書いているのは、2024/10/25)
dockerでPC内に仮想PC入れる感じになるので、
本格的に使うのであれば、
32GBぐらいのRAMと、コア数の多めのPCを別途用意したほうが良さそうに思えた。
そうしないと、スワップ処理で、もっさり動作になってしまい。ほぼ停止しているかのような錯覚を感じた。
https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo
https://docs.google.com/forms/d/e/1FAIpQLSeD3IqITWsuepB19SEv889HsBvN9WOi6HRblPrJNyA9G7q02w/viewform
https://console.anthropic.com/dashboard
Docker本体のインストール手順は割愛する。他を見てほしい。
dockerが使える状態前提。
export ANTHROPIC_API_KEY=%your_api_key% docker run \ -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \ -v $HOME/.anthropic:/home/computeruse/.anthropic \ -p 5900:5900 \ -p 8501:8501 \ -p 6080:6080 \ -p 8080:8080 \ -it ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest
Xvfb started successfully on display :1 Xvfb PID: 9 starting tint2 on display :1 ... starting mutter starting vnc PORT=5900 starting noVNC noVNC started successfully ✨ Computer Use Demo is ready! ➡️ Open http://localhost:8080 in your browser to begin
noVNCはオープンソースで開発されている、ブラウザ上で動作するHTML5製のVNCクライアントです。 このnoVNCをサーバー側にインストールして、HTTPサーバーで公開しておけば、クライアント側はブラウザでアクセスするだけでリモートデスクトップ環境を使えるようになります
ブラウザで、http://localhost:8080 を開いてみると、おそらくdockerのイメージだと思うが、dockerで立ち上げたであろうPCが立ち上がる。
dockerの中身を操作するだけならば、セキュリティは大丈夫そうだ。
ブラウザで表示した上記の画面の左側のChat欄に、どのようなことができるのか質問したら、教えてくれた。
アカウントの作成やログイン関連については、手伝えないといわれた。
OSは何ですか?と聞いたところ以下の回答だった。
Ubuntu 22.04.5 LTS
gitは、すでにインストール済みのようだ。
インストール済み:
pyenvを使用して管理されています
多数のPythonパッケージがインストールされています(numpy, pandas, streamlit, requests など)
未インストール:
テキストエディタのVIはインストールされていないようだ。
「viをインストールしてみて」
とお願いしてみた。できた。
「viのカラースキームをmonokaiにして」
とお願いしてみた。できた。日本語に対応してなかったので、まだ設定が必要そうだ
PCのメモリが16GBだと、ブラウザを立ち上げようとすると、固まってしまった。
VmmemVSLというプロセスがめちゃめちゃ占有している。
dockerがフリーズしてしまった。メモリを食いすぎ
PCにメモリはたくさん積んでおいたほうがいいだろう。
暫定対応
https://zenn.dev/quantum/articles/b29722e8795335
power shell用のコマンド
# WSLに入るコマンド。すでにWSLに入っている場合は不要 wsl # メモリをフラッシュするコマンド sudo sh -c "/usr/bin/echo 3 > /proc/sys/vm/drop_caches"
チャットが複数セッションに分かれていないので、上限に来た場合にどうするのか? 長文のチャットだと会話の継続はできなくなってくるが、dockerでたちあげた環境に紐づいてしまっていると、チャットだけクリアすることはできるのだろうか?
自主的にどんどんファイルを更新してくれたりするのは頼もしいが、複雑になってくると、やらかしてしまった場合、戻る方法はどうするのだろうか? ソースコードならば、gitがインストールされているので、都度コミットしましょうというルールでいけそうだが、設定ファイルなどを改変されると、バックアップしていないと戻せなくなってしまう。
処理が進むと重くなってくる、となると、これを使った開発は、課題を1つ解決したらまたリセットして使う仕組みならば行けそうだ。
AIとコラボ用にGitLabサーバを立てる
AI用に最低32GBのPCを用意する。
並列で作業させたい場合もあるから、もしかしたら複数台用意したほうがいいかもしれない
問題解決に近い環境をdockerのイメージを作る
関連するファイルは自分で見に行ってもらうように指示する
Issue経由などで課題を与える
課題を手伝ってもらう
gitにコミットする
githabなどに pushする
不本意ながら、AIの処理できるトークン数に限界がくるので、次の課題に向けリセットし、上記の手順を 再度行う
dockerで作業するのではなく、ホストマシンでgit cloneしたファイルを対象にすれば、いろいろと便利なのでは?と思った。
サンプルとして、以下を持ってきた。これはanthropicの公式をforkして、自分が好き勝手にできるようにしたリポジトリです。
git clone https://github.com/khayashi4337/courses.git
目標は、github上の英語の資料を、ローカルに用意して、Couputer useにdocker-compose経由で連携し、翻訳できるかどうかチャレンジしてみるのです。そのまま、git に commitやpushできたら楽なので、ローカルの情報をどこまで持たせることができるのかも確認していきます。
ローカルファイルを使えるようにするには、Dockerfile形式ではなくdocker-compose形式が一般的だ。
なので、上記のコードをローカルファイルに変換してみます。
# Git設定を確認して環境変数に設定 export GIT_USER_NAME=$(git config --global user.name) export GIT_USER_EMAIL=$(git config --global user.email) # 設定された値を確認 echo "Git User Name: $GIT_USER_NAME" echo "Git User Email: $GIT_USER_EMAIL"
version: '3' services: anthropic: image: ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest environment: - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - GIT_USER_NAME=${GIT_USER_NAME} - GIT_USER_EMAIL=${GIT_USER_EMAIL} volumes: - ${HOME}/.anthropic:/home/computeruse/.anthropic - /c/Users/kh/prj/courses:/home/computeruse/courses # サンプルとして追加したディレクトリ - /c/Users/kh/.ssh:/home/computeruse/.ssh:ro # 読み取り専用 ports: - "5900:5900" - "8501:8501" - "6080:6080" - "8080:8080" tty: true # -it フラグの代わり stdin_open: true # -it フラグの代わり
はいdocker-composeでも起動できました。.sshフォルダ丸ごと共有はお行儀がよくない気がするが、とりあえず実験用ってことにしておく。
これができるということは、今までできなかった以下のことができるようになったのです。
毎回ブラウザでlocalhost:8080を開くのが面倒になってきたので、起動スクリプトを用意しました。
#!/bin/bash docker-compose down # コンテナを起動 docker-compose up & # 20秒待機(コンテナの起動を待つ) sleep 20 # OSタイプに応じてブラウザを起動 case "$OSTYPE" in "msys"*|"cygwin"*|"win"*) # Windows if command -v start &> /dev/null; then start chrome http://localhost:8080 else cmd.exe /c start http://localhost:8080 fi ;; "darwin"*) # macOS open -a "Google Chrome" http://localhost:8080 ;; "linux-gnu"*) # Linux or WSL if grep -q Microsoft /proc/version; then # WSL環境 cmd.exe /c start http://localhost:8080 else # 通常のLinux if command -v google-chrome &> /dev/null; then google-chrome http://localhost:8080 elif command -v chrome &> /dev/null; then chrome http://localhost:8080 elif command -v chromium &> /dev/null; then chromium http://localhost:8080 else xdg-open http://localhost:8080 fi fi ;; esac
Dockerファイルに、よくやる手順を追記する。
以下をDockerfileとして保存する。手順を追加してある。
注意: 下記コード中のyou@example.comと、Your Nameは、各自のアカウントなどの設定に合わせてください。 以下のコマンドで確認できます。
echo $(git config --global user.name) echo $(git config --global user.email)
FROM ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest # 最初にrootユーザーとして実行することを明示 USER root # 日本語環境のセットアップ RUN apt-get update && \ apt-get install -y \ language-pack-ja-base \ language-pack-ja \ locales \ xclip \ vim && \ locale-gen ja_JP.UTF-8 && \ rm -rf /var/lib/apt/lists/* # デフォルトユーザー(computeruse)の.bashrcに日本語設定を追加 USER computeruse RUN echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc && \ git config --global --add safe.directory /home/computeruse/courses && \ git config --global user.email "you@example.com" && \ git config --global user.name "Your Name" echo '# Gitブランチ表示の設定' >> ~/.bashrc && \ echo 'parse_git_branch() {' >> ~/.bashrc && \ echo ' git branch 2> /dev/null | sed -e "/^[^*]/d" -e "s/* \(.*\)/ (\1)/"' >> ~/.bashrc && \ echo '}' >> ~/.bashrc && \ echo 'export PS1="\u@\h:\w\[\e[32m\]\$(parse_git_branch)\[\e[00m\]\$ "' >> ~/.bashrc
# システム全体のロケール設定 ENV LANG=ja_JP.UTF-8 \ LANGUAGE=ja_JP:ja \ LC_ALL=ja_JP.UTF-8
以下の、volumes:の設定項目は、各自が連携させたいディレクトリ名に置き換えること
version: '3' services: anthropic: build: context: . dockerfile: Dockerfile environment: - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - GIT_USER_NAME=${GIT_USER_NAME} - GIT_USER_EMAIL=${GIT_USER_EMAIL} volumes: - ${HOME}/.anthropic:/home/computeruse/.anthropic - /c/Users/kh/prj/courses:/home/computeruse/courses - /c/Users/kh/.ssh:/home/computeruse/.ssh:ro ports: - "5900:5900" - "8501:8501" - "6080:6080" - "8080:8080" tty: true stdin_open: true
Dockerfileを修正後、初回のみ
docker-compose up --build
2回目以降は
docker-compose up
最初のコミットぐらいは、手動でもいいかな。でもdockerで立ち上げた仮想PC上でコマンドを入れてみる。
git add . --all git commit -m 'first commit'
できた、自分の認証情報を与えているのでできるようになっている。
コンソールの日本語も適切に表示できている。
準備は整った。
今回は、練習として、英文のドキュメントがjupyter形式だったので、それをmarkdown形式にしてもらうというのを練習課題としてやってみようと思う。
ただし以下の縛りを付ける。
修正前にgitでブランチを切ること
作業が終わったらコミットすること
では、やってみよう。
以下のようにお願いしてみた。
以下のディレクトリ配下の /home/computeruse/courses 拡張子 .ipynb のファイルをmarkdown形式に変換しコミット、さらに日本語にしてコミットしてください。 作成するにあたって、gitのブランチを作成し、作業をお願いします。 作業が完了したら、コミットをお願いします。 まずは作業指示の認識確認のため、1つのファイルのみで作業を行ってください。
すると、claude sonnetは、こともあろうか、自分がforkしたリポジトリからブランチを切らずに、本家のほうからブランチを気って来た。。。まあ、そこで学習してたのだから、そうしたがるのはわかるが。。。。いけない。
タスクが複雑になると、ポンコツになってくるようなので、gitのコミットはさせないようにしたほうがよさそうだ。大量のタスクもやらせると、ろくでもない対応を横展開するので、NGな使い方だと思った。
Tier1という契約レベルだと、1分間に50リクエスト超えると制限に引っかかる。1つのお願いだったとしても、AIが内部で数十回リクエストを消費してしまうのだ。
いろいろやろうとすると、リクエストの頻度が高いせいか以下のエラーになる。
RateLimitError You have been rate limited. Retry after 0:01:31 (HH:MM:SS). See our API documentation for more details.
感覚的には、今のリミットの20倍ぐらい制限を緩和しないと、業務に使えないと感じた。
翻訳の依頼対象が30ファイルぐらいになることがわかって、こちらが意図しない作業を30個やってしまったあとに、「いやいやそうではない」と再度指示した段階で、「リクエストのリミットなんで、お休みします」となるわけだ。
技術的にはできるけれども、サービスデザイン起因の制限によってダメになっているというのは、実にもったいないことをしていると思った。
今までうまくいかなかったので、方針を変えよう。
とりあえず、1つのファイルを丁寧にやって、小さな成功体験を積ませるのが、近道かもしれない。
人為的な制限のため、ある程度、自分でやるようにしないといけない。
ツール作ってもらって、処理はツールでやるなどして、リクエスト回数を減らす工夫が必要だ。
本当は、ipynbファイルを直接翻訳してもらおうとしたのだが、なぜかpythonライブラリを使おうとしてしまうので、だったら、ツール作ってもらおうと思って、以下を作ってもらった
#!/usr/bin/env python3 import sys import os import nbformat from nbconvert import MarkdownExporter def convert_ipynb_to_md(input_path, output_path=None): """ Jupyter NotebookファイルをMarkdownファイルに変換する Args: input_path (str): 入力.ipynbファイルのパス output_path (str, optional): 出力.mdファイルのパス。指定がない場合は同じディレクトリに同名の.mdファイルを作成 """ try: # 出力パスが指定されていない場合、入力ファイルと同じディレクトリに.mdファイルを作成 if output_path is None: output_path = os.path.splitext(input_path)[0] + '.md' # .ipynbファイルを読み込む with open(input_path, 'r', encoding='utf-8') as f: notebook = nbformat.read(f, as_version=4) # MarkdownExporterを初期化 markdown_exporter = MarkdownExporter() # notebookをMarkdownに変換 (body, resources) = markdown_exporter.from_notebook_node(notebook) # Markdownファイルとして保存 with open(output_path, 'w', encoding='utf-8') as f: f.write(body) print(f"変換が完了しました: {output_path}") except Exception as e: print(f"エラーが発生しました: {str(e)}") sys.exit(1) def main(): # コマンドライン引数をチェック if len(sys.argv) < 2: print("使用方法: python ipynb_to_md.py input.ipynb [output.md]") sys.exit(1) input_path = sys.argv[1] output_path = sys.argv[2] if len(sys.argv) > 2 else None # 入力ファイルの存在確認 if not os.path.exists(input_path): print(f"エラー: 入力ファイル '{input_path}' が見つかりません。") sys.exit(1) # 変換を実行 convert_ipynb_to_md(input_path, output_path) if __name__ == '__main__': main()
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import glob import sys def find_ipynb_files(directory="."): """ 指定されたディレクトリ配下の.ipynbファイルを再帰的に検索して一覧表示する Args: directory (str): 検索を開始するディレクトリパス(デフォルトは現在のディレクトリ) """ try: # 絶対パスに変換 abs_directory = os.path.abspath(directory) # .ipynbファイルを再帰的に検索 pattern = os.path.join(abs_directory, "**", "*.ipynb") ipynb_files = glob.glob(pattern, recursive=True) # 結果を標準出力に出力 for file_path in ipynb_files: print(file_path) except Exception as e: print(f"エラーが発生しました: {str(e)}", file=sys.stderr) sys.exit(1) def main(): # コマンドライン引数からディレクトリを取得(指定がない場合は現在のディレクトリを使用) directory = sys.argv[1] if len(sys.argv) > 1 else "." # ディレクトリの存在確認 if not os.path.exists(directory): print(f"エラー: ディレクトリ '{directory}' が見つかりません。", file=sys.stderr) sys.exit(1) if not os.path.isdir(directory): print(f"エラー: '{directory}' はディレクトリではありません。", file=sys.stderr) sys.exit(1) # 検索を実行 find_ipynb_files(directory) if __name__ == '__main__': main()
おそらく、会話の履歴がたまってきたら、後半のリクエストって、前半のリクエスト全部をコストにしてしまっている感じがする。後半になるとリミット制限が、あっという間に来た。制限後の時間で1つのお願いをすると、すぐにリミットになったからそのような推測に至った。 いずれ、claude3.5のインターフェースのように新規チャット開始、みたいなインターフェースになるのだと思う