【永久0円】人間LLMのすすめ
はじめに
こんなお悩みはありませんか?
LLMは気づいたら値上がり。最新モデルは限定公開。ローカルLLMを建てようにもグラボが足りない。
...実は、電気を使わず使い放題の計算資源があることをご存知ですか?
―そう、貴方です。
作ったもの
というわけで作りました。名付けて humanllm です。
まずはサーバーを起動します。
$ npm run dev
起動するとUI画面とOpenAI API互換サーバーが立ち上がります。
LLMモデルになって、届いたプロンプトに返答しましょう。
Codexを使ってみる
さっそくエージェントで使ってみましょう。ここではOpenAI APIが導入しやすいCodexを使っていきます。
まずはモデルの設定を準備します。
model ="human"
model_provider ="humanllm"
[model_providers.humanllm]
name ="Human LLM"
# humanllmのAPIサーバー
base_url ="http://localhost:3000/v1"
# ダミー値
bearer_token_env_var ="HUMANLLM_API_KEY"
[projects."/home/syuparn/tmp/hoge"]
trust_level ="trusted"
[tui.model_availability_nux]
"gpt-5.5" =4
モデルを指定して起動します。
$ codex --profile humanllm
プロンプトを送信
Codexでプロンプトを送信します。
Pythonでhello worldを実装してください。
UIにプロンプトが届きました。本文の何十倍も長いシステムプロンプトがいっしょに付いています。
内容は以下の通りです。
コマンドやスキルを使う際の注意点や、ユーザーから許可をもらう必要がある点について書かれています。
その後には、本題のプロンプトがあります。
返信
というわけで返答しましょう。
すぐには思いつかないのでまずは進捗を。UIの Send Progress で考えている途中経過を返しましょう。
ちょっとまってね
Codexが受け取りました。
思いついたので本題のソースコードを返します。今度は Send で最終的な返答を送ります。
print("Hello, world!")
Codexが受け取りました。任務完了です。
コマンドを実行
今度は、ファイルの保存を依頼するプロンプトが飛んできました。
hello.pyに保存してください
コマンドを実行する必要があるので、 Run Command で実行したいコマンドを返します。
echo 'print("Hello, world!")' > hello.py
Codex側で受け取ったコマンドが実行されたようです。
成功したかどうか確認します。
ls
Codexで実行されます。
結果がhumanllmへ送られます。ファイルはちゃんとできているようです。
[function_call_output]
Exit code: 0
Wall time: 0 seconds
Output:
hello.py
結果を返答します。
Codex側へ返ってきました。
お疲れさまでした。
実装
最後に humanllm の実装について軽く紹介します。
1
構成
- OpenAI APIサーバー:
localhost:3000 - UI:
localhost:5173
UI画面はAPIサーバーとWebSocketで通信しており、APIサーバーを介してCodex等エージェントとやり取りしています。
ハマったところ
webSocketが返信できない
Reactのデバッグ用の StrictMode によって、WebSocketの構築、破棄が2回連続で起きてしまい疎通が切れてしまいました。そのため、<StrictMode> タグを外しています。
途中経過の送信
途中経過が送信できず、最終結果を送信したタイミングですべてまとめて送信されてしまいました。
OpenAI APIのstreaming APIでは、途中経過と最終的な返答を別のタイプで区別してあげる必要がありました。
- 途中経過:
response.output_text.delta - 最終的な返答:
response.completed
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_39eb1b00-9137-4a74-accd-5d85fcf21073","output_index":0,"content_index":0,"delta":"reply"}
ところが、Codexでは上記に対応しても一括で送られてしまう問題が解消しません。
Codexでは途中経過のメッセージを \n 区切りで認識しているため、さらに返答の末尾に \n を付けてあげる必要がありました。
最終的な実装は以下の通りです。
const handleDelta = useCallback(() => {
if (!selectedId || !responseText.trim()) return
send({ type: 'delta', requestId: selectedId, content: responseText.trim() + '\n' })
setResponseText('')
}, [selectedId, responseText, send])
コマンド実行
コマンド実行にはまた別のタイプが必要です。Codexではタイプ function_call を使用します。
実行したいコマンドを、arguments に "{\"command\": \"{コマンド}\"}" という形式で指定します。
おわりに
以上、humanllmの紹介でした。
あなたもLLMになって無料でエージェントをぶん回しましょう👁 :grin:
関連記事
-
ちなみにClaude Codeを普段使いしているのにCodexで検証したのは、 クローズドソースのプロンプトを覗いていいのか微妙だったからです。 ↩
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme
