Closed8

コマンドラインでLLMが使える「llm」を試す

kun432kun432

前からあるのは知っていたけど、全然試してなかった。名前がそのまますぎる。

https://github.com/simonw/llm

LLM

大規模言語モデル(LLM)とのやり取りを可能にするCLIユーティリティとPythonライブラリです。リモートAPIと、ローカルにインストールして実行できるモデルの両方に対応しています。

コマンドラインからプロンプトを実行したり、結果をSQLiteに保存したり、埋め込みを生成するなどの機能があります。

リモートモデルとローカルモデルへのアクセスを提供するLLMプラグインディレクトリをご参照ください。

詳細なドキュメント: llm.datasette.io

このプロジェクトの背景:

上にも書いてあるけど、プラグインの仕組みを採用してて、ここが結構豊富。

https://llm.datasette.io/en/stable/plugins/directory.html

ちなみに作者の方はDjangoの作者の方らしい。

https://en.wikipedia.org/wiki/Simon_Willison

kun432kun432

公式ドキュメントはこちら。

https://llm.datasette.io/en/stable/

Quick Startに従ってやってみる。今回はDocker上でお試し。

$ docker run --rm -it python:3.12-slim /bin/bash

以降はDockerコンテナ内で。

パッケージインストール

$ pip install llm

コマンドがインストールされた。

$ which llm
/usr/local/bin/llm
$ llm --version
llm, version 0.16
$ llm --help
Usage: llm [OPTIONS] COMMAND [ARGS]...

  Access large language models from the command-line

  Documentation: https://llm.datasette.io/

  To get started, obtain an OpenAI key and set it like this:

      $ llm keys set openai
      Enter key: ...

  Then execute a prompt like this:

      llm 'Five outrageous names for a pet pelican'

Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

Commands:
  prompt*       Execute a prompt
  aliases       Manage model aliases
  chat          Hold an ongoing chat with a model.
  collections   View and manage collections of embeddings
  embed         Embed text and store or return the result
  embed-models  Manage available embedding models
  embed-multi   Store embeddings for multiple strings at once
  install       Install packages from PyPI into the same environment as LLM
  keys          Manage stored API keys for different models
  logs          Tools for exploring logged prompts and responses
  models        Manage available models
  openai        Commands for working directly with the OpenAI API
  plugins       List installed plugins
  similar       Return top N similar IDs from a collection
  templates     Manage stored prompt templates
  uninstall     Uninstall Python packages from the LLM environment

デフォルトはOpenAIっぽいので、OpenAI APIキーをセット

$ llm keys set openai
Enter key:                     # APIキーを入力

ではLLMにクエリを送ってみる。

$ llm "競馬の楽しみ方を5つリストアップして"

結果はストリーミングで出力される。

競馬の楽しみ方を5つリストアップします。

1. **予想や分析を楽しむ**: 馬の成績や騎手、コースの特性などを研究し、自分なりの予想を立てることで、レースに対する理解が深まります。このプロセス自体が大きな楽しみとなります。

2. **レース観戦**: 実際のレースを観ることには、多くの興奮があります。スタンドやテレビでの観戦と、現地での観戦では異なる楽しみ方があります。レースの迫力や馬の動きに魅了されるでしょう。

3. **友人や家族との交流**: 競馬は友人や家族と一緒に楽しむことができる娯楽です。予想を語り合ったり、一緒に応援したりすることで、コミュニケーションの場にもなります。

4. **馬券購入の戦略**: 馬券を買うことで、よりレースに集中することができます。購入方法や賭け方に戦略を立て、自分のスタイルを見つける楽しみがあります。

5. **歴史や文化の探求**: 競馬には長い歴史と独特の文化があります。有名な競走馬や伝説的な騎手の話、競馬場の由来や伝統行事について学ぶことで、競馬の奥深さを感じることができます。

これらの楽しみ方を通じて競馬をより深く楽しむことができるでしょう。

標準入力の内容を渡すことができる。-sは多分システムプロンプトだと思う。

$ df -h | llm -s "ディスクの使用状況を教えて"
現在のディスクの使用状況は以下の通りです:

- **overlay**
  - サイズ: 96G
  - 使用領域: 90G
  - 空き領域: 1.1G
  - 使用率: 99%
  - マウントポイント: /

- **tmpfs**
  - サイズ: 64M
  - 使用領域: 0
  - 空き領域: 64M
  - 使用率: 0%
  - マウントポイント: /dev

- **shm**
  - サイズ: 64M
  - 使用領域: 0
  - 空き領域: 64M
  - 使用率: 0%
  - マウントポイント: /dev/shm

- **/dev/vda1**
  - サイズ: 96G
  - 使用領域: 90G
  - 空き領域: 1.1G
  - 使用率: 99%
  - マウントポイント: /etc/hosts

- **tmpfs**
  - サイズ: 3.9G
  - 使用領域: 0
  - 空き領域: 3.9G
  - 使用率: 0%
  - マウントポイント: /sys/firmware

全体として、特にoverlayや/dev/vda1の使用率が99%と非常に高いため、空き領域がほとんどありません。このままでは新たなデータを保存することが難しくなりますので、不要なファイルを削除するか、別のストレージを用意することを検討した方が良いでしょう。

ということはこういう書き方もできる。

$ df -h > df.txt
$ llm -s "ディスク使用状況を教えて" < df.txt

またはシェルで変数展開させたり。

$ llm -s "ディスク使用状況を教えて: $(df -h)"
あなたのディスクの使用状況は以下の通りです:

- **Filesystem**: overlay
  - **サイズ**: 96G
  - **使用済み**: 90G
  - **空き容量**: 1020M
  - **使用率**: 99%
  - **マウントポイント**: /
(snip)

llm chatで対話モードに入れる。

$ llm chat
Chatting with gpt-4o-mini
Type 'exit' or 'quit' to exit
Type '!multi' to enter multiple lines, then '!end' to finish
>
> 競馬の楽しみ方を教えて
競馬の楽しみ方はいくつかありますので、以下にいくつかのポイントを挙げてみます。

### 1. 馬や騎手の研究
- **馬の能力を知る**: 過去のレース成績や血統、調子、コース適性などを調べることで、より深く競走馬を理解できます。
- **騎手の実績**: 騎手の得意なコースや最近の成績を把握することで、レースの展開を予測しやすくなります。

### 2. レースの観戦
- **実際に競馬場に行く**: ライブでレースを見ることで、緊張感や興奮をリアルに体感できます。また、競馬場内の雰囲気やグルメも楽しめます。
- **テレビやネット中継**: 自宅でリラックスしながらレースを観戦するのも一つの楽しみ方です。家族や友人と一緒に見るのも楽しいでしょう。

### 3. 賭け方を工夫する
- **単勝・複勝だけでなく、馬連や馬単**: 賭け方を変えることで、レースへの楽しみが増えます。特に馬連や馬単は高配当が期待できることも。
- **予想を共有する**: 友人や家族と予想を交流することで、競馬の楽しみが増します。誰かが当たると盛り上がりますね。

### 4. 競馬の歴史や文化を学ぶ
- **歴史を知る**: 競馬には深い歴史があります。競馬の名馬や名騎手の物語を知ることで、さらに感情移入できます。
- **地域の競馬イベント**: 地元の競馬や関連イベントに参加することで、地域の文化やコミュニティとも繋がることができます。

### 5. SNSやコミュニティに参加する
- **情報交換**: SNSや掲示板での情報交換を通じて、異なる視点の予想や見解を知ることができます。
- **ファンとの交流**: 同じ趣味を持つ人たちと交流することで、競馬の楽しさが広がります。

これらの楽しみ方を通じて、競馬をより深く楽しむことができるでしょう。ぜひ、自分に合ったスタイルを見つけてみてください!
> quit

モデルを変えるには-mで。

$ llm -m gpt-4o-mini "おはよう!"
おはようございます!今日は何か特別なことがありますか?
kun432kun432

プラグインを使ってみる。

https://llm.datasette.io/en/stable/plugins/directory.html

プラグインはプロプライエタリなモデルプロバイダを追加するもの、ローカルモデルを追加するもの、その他の機能を追加するものなどがあるが、今回は以下の2つを試してみる。

https://github.com/simonw/llm-claude-3

Anthropic Claude3へのLLMアクセス

https://github.com/simonw/llm-jq

LLMの助けを借りてjqプログラムを書いて実行する このプロジェクトの背景については、llm-jqを使ってjqプログラムを生成して実行するプロンプトを実行するを参照してください。

まず、llm-claude-3から。パッケージインストール。

$ llm install llm-claude-3

AnthropicのAPIキーをセット

$ llm keys set claude
Enter key:                     # APIキーを入力

Claude−3−Haikuを使う

$ llm -m claude-3-haiku "競馬の楽しみ方を5つリストアップして"
競馬の楽しみ方を5つリストアップすると以下のようになります:

1. 馬と騎手のパフォーマンスを楽しむ
   - 競走馬の力強い走りや、騎手の巧みな乗り味を堪能する。

2. レース予想に挑戦する
   - 各馬の能力や調整状態を分析して、優勝馬や着順を予想する楽しみ。

3. 賭けに興じる
   - 金銭的なリスクを伴う賭けに勝負を挑むスリルを味わう。

4. 競馬場の雰囲気を楽しむ
   - 迫力ある観戦体験や、競馬場ならではの熱気を感じる。

5. 競馬情報に精通する
   - 馬やジョッキー、調教師などの情報をつぶさに収集し、知識を深める。

これらの楽しみ方を組み合わせることで、競馬ファンならではの充実した体験ができるでしょう。

次にllm-jq。こちらもパッケージを追加。

$ llm install llm-jq

llmレポジトリのアクティビティ一覧を取得して、アクティビティごとの内訳を集計してもらう。Dockerイメージにcurl/jqがないので追加もしている。

$ apt update && apt install -y curl
$ curl -s   https://api.github.com/repos/simonw/llm/activity | llm jq '活動の種類の内訳を集計して、多いものから並べて'
[
  {
    "type": "push",
    "count": 14
  },
  {
    "type": "pr_merge",
    "count": 6
  },
  {
    "type": "branch_creation",
    "count": 4
  },
  {
    "type": "branch_deletion",
    "count": 4
  },
  {
    "type": "force_push",
    "count": 2
  }
]
map(.activity_type) | group_by(.) | map({type: .[0], count: length}) | sort_by(-.count)
kun432kun432

ドキュメントは豊富なのでいろいろ調べてみると良いと思う。とりあえずざっと見て回って気になったところだけピックアップ。

ストリーミング無効化

デフォルトだとストリーミング有効になっているが、これを無効化する場合は--no-stream

$ llm --no-stream "明日の天気は?"
申し訳ありませんが、私はリアルタイムの情報を提供することができません。最新の天気情報は、天気予報のウェブサイトやアプリでご確認ください。どの地域の天気を知りたいか教えていただければ、一般的な気象パターンについてお話しすることはできますよ。

モデルのパラメータ

-oでパラメータを付与できる。例えばtemperatureを1.5、max_tokensを10にする。

$ llm -o temperature 1.5 -o max_tokens 100 "競馬の楽しみ方を教えて。"
競馬の楽しみ方はいくつかありますので、以下にいくつかのアイデアを紹介します。

### 1. 馬の知識を深める
- 想像連れた馬やジョッキーについて学ぶことで、競馬をより深く理解できます。血統、成績、過去のレースなどを調べ、好きな馬を見つけて応援する楽しみもあります。

###

途中で切れているのがわかる。

会話のセッションを継続する

llm chatで対話モードならば、会話のコンテキストは継続する。

$ llm chat
> おはよう、私の趣味は競馬です。覚えてね。
おはようございます!競馬が趣味なんですね。馬やレースについての話題や情報があれば、お気軽に教えてください。楽しんでお話ししましょう!
> 明日の天気は?
申し訳ありませんが、リアルタイムの天気情報を提供することはできません。お住まいの地域の天気予報を確認するには、天気予報のウェブサイトやアプリをご利用ください。他にお手伝いできることがあれば教えてください!
> 私の趣味ってなんだっけ?
あなたの趣味は競馬ですね!何か具体的に話したいことや質問があれば、ぜひ教えてください。
> quit

llmコマンド単体だと毎回新しい会話セッションになるが、-Cを使うと、前回実行時の会話コンテキストから継続することができる。

まず普通の例。

$ llm "私の趣味は競馬です。覚えてね。"
もちろんです!あなたの趣味は競馬ですね。何か特に好きな馬やレースについてお話ししたいことがあれば教えてください。

$ llm "私の趣味はなんでしょう?。"
あなたの趣味については具体的な情報がないため、お答えすることができません。しかし、もし趣味について教えていただければ、さらにお話を広げたり、おすすめの趣味を提案したりすることができますよ!あなたの興味のあることや好きな活動について教えてもらえますか?

会話のコンテキストが継続されていないことがわかる。

-cを試してみる。まず普通に会話。

$ llm "私の趣味は競馬です。覚えてね。"
もちろん、あなたの趣味が競馬であることを覚えました!競馬について何か特別なことやお好きな馬、レースなどがあれば教えてください。

2回目は-cを付与する。

$ llm -c "私の趣味はなんでしょう?。"
あなたの趣味は競馬です。何か他に知りたいことや話したいことがあれば、ぜひ教えてください!

前回の続きから会話が継続していることがわかる。

-cは前回の会話の続きになるが、それ以前の会話に戻ることもできる。まずllm logsで過去の会話履歴を確認する。

$ llm logs
# 2024-10-28T10:04:05    conversation: 01jb99adnxcz86w2fts8pjscy9

Model: **gpt-4o-mini**

## Prompt:

私の趣味はなんでしょう?。

## Response:

あなたの趣味については具体的な情報がないため、お答えすることができません。しかし、もし趣味について教えていただければ、さらにお話を広げたり、おすすめの趣味を提案したりすることができますよ!あなたの興味のあることや好きな活動について教えてもらえますか?

# 2024-10-28T10:05:12    conversation: 01jb99cef80jbwbb0674j3zm67

Model: **gpt-4o-mini**

## Prompt:

私の趣味は競馬です。覚えてね。

## Response:

もちろん、あなたの趣味が競馬であることを覚えました!競馬について何か特別なことやお好きな馬、レースなどがあれば教えてください。

# 2024-10-28T10:05:41    conversation: 01jb99cef80jbwbb0674j3zm67

Model: **gpt-4o-mini**

## Prompt:

私の趣味はなんでしょう?。

## Response:

あなたの趣味は競馬です。何か他に知りたいことや話したいことがあれば、ぜひ教えてください!

conversationの右にあるのが会話IDとなる。これを--cidで指定することで、特定の過去の会話を継続することができる。

$ llm --cid 01jb99cef80jbwbb0674j3zm67 "私の趣味は何だっけ?"
あなたの趣味は競馬です。何か具体的な質問や話題があればお聞かせください!

よく使うシステムプロンプトはテンプレート化することもできる。

$  llm -s "日本語に翻訳して" --save translate_ja

登録されたテンプレートのリスト

$ llm templates
translate_ja : system: 日本語に翻訳して

呼び出す場合

$ echo "A CLI utility and Python library for interacting with Large Language Models, both via remote APIs and models that can be installed and run on your own machine." | llm -t translate_ja
リモートAPIおよび自分のマシンにインストールして実行できるモデルを介して、大規模言語モデルと対話するためのCLIユーティリティおよびPythonライブラリです。

モデルの一覧

$ llm models
OpenAI Chat: gpt-3.5-turbo (aliases: 3.5, chatgpt)
OpenAI Chat: gpt-3.5-turbo-16k (aliases: chatgpt-16k, 3.5-16k)
OpenAI Chat: gpt-4 (aliases: 4, gpt4)
OpenAI Chat: gpt-4-32k (aliases: 4-32k)
OpenAI Chat: gpt-4-1106-preview
OpenAI Chat: gpt-4-0125-preview
OpenAI Chat: gpt-4-turbo-2024-04-09
OpenAI Chat: gpt-4-turbo (aliases: gpt-4-turbo-preview, 4-turbo, 4t)
OpenAI Chat: gpt-4o (aliases: 4o)
OpenAI Chat: gpt-4o-mini (aliases: 4o-mini)
OpenAI Chat: o1-preview
OpenAI Chat: o1-mini
OpenAI Completion: gpt-3.5-turbo-instruct (aliases: 3.5-instruct, chatgpt-instruct)
Anthropic Messages: claude-3-opus-20240229
Anthropic Messages: claude-3-opus-latest (aliases: claude-3-opus)
Anthropic Messages: claude-3-sonnet-20240229 (aliases: claude-3-sonnet)
Anthropic Messages: claude-3-haiku-20240307 (aliases: claude-3-haiku)
Anthropic Messages: claude-3-5-sonnet-20240620
Anthropic Messages: claude-3-5-sonnet-20241022
Anthropic Messages: claude-3-5-sonnet-latest (aliases: claude-3.5-sonnet, claude-3.5-sonnet-latest)
kun432kun432

まとめ

gptmeと同じような感じなんだけど、gptmeとの違いは、あちらはツールを持ったエージェント、こちらは単にLLMリクエストを送るコマンドというところかな。

ただ、gptmeで惜しいなと思っていたのは、必ず出力に"Assitatnt"って出ることだった。これを抑止できればLLMの生成結果を別のコマンドにパイプでそのまま渡せるのになーと思っていたのだけど(一度ファイルに出力させる必要があった)、llmならこの問題は起きない。

プラグインで機能追加できるってのも良いし、こちらのほうがスクリプトなんかには組み込みやすそうに思える。

kun432kun432

MacならHomebrewでインストールできる。

$ brew info llm
==> llm: stable 0.17 (bottled)
Access large language models from the command-line
https://llm.datasette.io/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/l/llm.rb
License: Apache-2.0
このスクラップは26日前にクローズされました