THINKING MEGANE

ターミナルフレンドリーなAIコマンド、afaを作った

Go言語で、AIモデルに対する推論をコマンドラインで実行するafaというツールを作りました。入出力としてテキストストリームを前提としており、パイプやリダイレクトを用いて他のコマンドと連携しやすいのが特徴です。

$ echo $ERROR_MESSAGE | afa new -p "What is happening?" /path/to/file1 /path/to/file2

与えるプロンプトやコンテキスト情報によってAIモデルが柔軟に振る舞いを変えてくれるので、これまでの個別ツールでは対応が難しかった用途における自動化にも有用でしょう。 また、テキストストリームを扱えるリッチなTUIのコマンドafa-tuiも別途提供しているので、ターミナル上でのチャットも快適です。

デモ

リッチTUIによるチャット

快適なインタラクティブチャットのため、Markdownを装飾して描画しつつ、lessコマンド相当の操作感のページャーと、プロンプトの入力欄を持つViewerと連携できます。

Chat

Zsh Line Editor(ZLE)を用いたターミナル上でのコマンド提案

ZLEと連携すれば、コマンドライン上でのプロンプトをそのまま提案されたコマンドに置き換えて実行できます。

Command Suggestions

Vim上でのコード提案

Vimと連携すれば、選択範囲のコードを提案されたものに置換できます。使い慣れたエディタであればdiff表示や差分の部分反映もお手のものですね。

Code Suggestions

機能一覧

  • ターミナルフレンドリーなAIコマンドとして機能します。
  • リッチなターミナルユーザーインターフェース(TUI)を持つチャットクライアントとして機能します。
  • システムとユーザーのための文脈に応じたプロンプトをテンプレートを使用してサポートします。
  • プロンプト、標準入力、およびファイルパスを文脈として受け付けます。
  • セッションを管理し、resume サブコマンドを介して迅速に再開できるようにします。
  • 安全にエスケープされたJSONオプションで構造化された出力をサポートし、他のコマンドとの統合を容易にします。
  • コアアプリケーションはサードパーティライブラリに依存せずに独立して動作します。
  • AIモデルとしてOpenAIをサポートします(他のAIモデルのサポートは将来計画されています)。

なお、この文章は、英語で書かれたafaのREADMEのFeatures項目をコピーして、pbpaste | afa new -script -p "翻訳して" | pbcopyで貼り付けました。便利ですね。

基本的な使い方

Viewerを使用しないシンプルなチャットを起動する。

$ afa new

Viewerを使用してチャットを起動する。

$ afa new -V

コンテキスト情報を加えてチャットを起動する。コンテキスト情報には「標準入力」「プロンプトメッセージ(-pオプションによるもの)」、そして「ファイルパス」を与えることができる。 ただし、仕様上、標準入力を与えるとキーボードからの入力を継続できないため、インタラクティブなチャットはできない。この場合は、プロセス置換(<())をファイルパスとして与えることを検討されたい。

$ echo $ERROR_MESSAGE | afa new -p "What is happening?" /path/to/file1 /path/to/file2
# Please be cautious; when standard input is provided, interactive mode is disabled.
# Consider using process substitution.
#=> afa new -p "What is happening?" /path/to/file1 /path/to/file2 <( echo $ERROR_MESSAGE )

直近のセッションを再開する。

$ afa resume

指定したセッションを再開する。なお、afa listコマンドでセッション一覧を表示できる。

# The command `afa list` displays past sessions.
$ afa source -l SESSION_NAME

ユーザープロンプトを指定する。ユーザープロンプトは、Go言語のテンプレート形式であり、テンプレート内ではプリセットの値としてコンテキスト情報に対応する、MessageMessageStdin、そして NameContentをメンバとするFile構造体のリストであるFilesを以下のように呼べる。これにより動的なプロンプトの生成が可能となる。

# `Message`, `MessageStdin`, and `Files` that include `File` with `Name` and `Content` members can be used in the template file.
$ echo "Please explain the following.\n{{ (index .Files 0).Content }}" > CONFIG_PATH/templates/user/explain.tmpl
afa -u explain /path/to/file

スクリプトモードを指定して起動する。コマンドライン実行に適したモードのオプション設定を一括で行う-scriptオプションを指定することで、他のコマンドとの連携が容易になる。具体的には-I=false -H=false -S=false -V=false -L=falseが設定される。

pbpaste | afa new -script -p "Transrate this" | pbcopy

OpenAIの独自機能として提供されるStructured Output用のスキーマを指定できる。これは指定したJSON構造体に沿うような出力を強制する機能である。例えば、余分な説明が不要なコマンド提案などに適している。 クオート文字のエスケープを担う-Qオプションと合わせて使うことでjqによる整形が容易になるので活用されたい。

$ cat <<< EOS > CONFIG_PATH/schemas/command_suggestion.json
{
  "type": "object",
  "properties": {
    "suggested_command": {
      "type": "string"
    }
  },
  "additionalProperties": false,
  "required": [
    "suggested_command"
  ]
}
EOS

$ P="List Go files from the directory named 'internal' and print the first line of each file."
$ afa new -script -Q -j command_suggestion -p $P | jq '. | fromjson' | jq -r '.suggested_command'
#=> find internal -name '*.go' -exec head -n 1 {} \;

実践例

実践例を列挙します。 もし使いたい例があれば、GitHubのリポジトリのREADMEにプロンプトや設定例と共に載せているので参考にしてみてください。

  • Zsh Line Editor(ZLE)を用いたターミナル上でのコマンド提案
    • デモで紹介したものです
  • Vim上でのコード提案
    • これもデモで紹介したものです
  • ターミナルに表示されたエラーメッセージの分析
    • tmuxcapture-paneを使って直近の実行結果を分析できます。複数行にわたるエラーメッセージのコピペの手間が省けて便利ですね
  • GitHubのプルリクエストの自動生成
    • git diffgit logの情報を元にタイトルと要約を生成してプルリクエストを開きます。ZLEを想定しているので背景情報も踏まえて考えてもらえるようになっています。また、既存のテンプレートの上に要約を差し込む形にしているので、どのリポジトリでも使いやすいかなと思います。
  • pecoを用いたセッションの絞り込みと読み込み
    • インタラクティブな絞り込みで素早く過去のセッションにアクセスできます。

AFA

AFAはAI for Allの略で、あらゆるコマンドラインツールに対して連携可能($\forall x \in X , \exists \mathrm{AI}(x)$、つまりコマンドラインツールの集合Xの全ての要素xに対し、その結果を入力とするAI(x)な組み合わせが存在する)なAIコマンドになるといいなと思って付けた名前です。

現時点でもまだViewerの入力欄が不調になることがあったりWindowsでの動作確認ができていないなど課題はありますが、通常使う分には十分な品質になったと思うので公開しました。よく使うオプションセットをconfigに設定し、いくつかのユーザープロンプトを登録しておいてalias af='afa new'とするだけで、個人的には、調べ物やチャットを含め、ブラウザの利用頻度がかなり減ったことを実感しています。

Homebrewによるインストールbrew install monochromegane/tap/afa monochromegane/tap/afa-tuiも提供していますので、よければ使ってみてください。

将来的には、サーバー上での異常検知のような定式化の難易度が高いタスクでの適用も検討しています(サードパーティー製ライブラリへの非依存とViewerツールとの分離は、そのためでもあります)。AFAであれば、他のコマンドラインツールとの親和性を活かして、通知やロギングは従来の仕組みも活用できると考えています。適用例など共有してもらえたら嬉しいです。

このエントリーをはてなブックマークに追加