0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

非エンジニアのAI業務自動化(ディベートとJev)/Jevの使いどころを探した

0
Posted at

1本目で、Jevは論者の選び方では、Claudeと約60%しか合わないと書きました。

では、Jevは何に使えるのか?

私はOrcaで、複数のAIに設計書を書かせ、別のAIにレビューさせています。

ディベートの前と後、そしてこの設計書の流れの中で、いくつか使い道を試しました。この記事では、試したもの、やめたもの、残したものを、数字つきで書きます。

前の記事は、こちらです。

呼び出し部品を標準ライブラリだけで書いた

調べた時点で、第三者が作ったJevのコマンドラインツールがありました。ただ、2,382行あり、中身を確かめるのが重いので使いませんでした。標準ライブラリだけで、呼び出し部品を書きました。使ったモデルは、jev-1.13.0です。

jev_client.py
def ask(state, questions, model=MODEL, timeout=30, caller="", retries=2):
    """One request: `state` (str/dict/list) + a map of typed questions -> parsed response dict."""
    body = json.dumps({"state": state, "model": model, "questions": questions}).encode()
    for attempt in range(retries + 1):
        req = urllib.request.Request(API_URL, data=body, method="POST")
        req.add_header("Authorization", f"Bearer {api_key()}")
        req.add_header("Content-Type", "application/json")
        t0 = time.time()
        try:
            with urllib.request.urlopen(req, timeout=timeout) as resp:
                data = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:
            if e.code in (429, 500, 502, 503, 504) and attempt < retries:
                time.sleep(float(e.headers.get("Retry-After", 2 ** attempt)))
                continue
            raise RuntimeError(f"Jev HTTP {e.code}: {e.read()[:300]!r}")
    _log_usage(data.get("usage", {}), time.time() - t0, caller or os.environ.get("JEV_CALLER", ""))
    return data

決めたことは、3つです。

  • 送るのは、3つのキー(状況・モデル・問い)だけ。30秒で打ち切る
  • 再試行は、混雑や5xxのエラーのときだけ、2回まで。Retry-Afterがあれば、その秒数だけ待つ
  • キーは、環境変数か、同期フォルダの外のファイルから読む。値は表示しない

呼ぶたびに、「いつ・誰が・何トークン・何ミリ秒」だけを1行記録します。送った中身は残しません。

日本語で試した

Jevの資料は、英語が主で、日本語は精度が下がるので、自分のデータで試すよう書かれていました。そこで、日本語20件(39の判断)をJevに判断させ、Claudeの判断と比べました。結果は、39判断のうち38が一致です。リクエストは21回でした。

分類・合否・振り分けは、問いが日本語でも英語でも全件一致しました。確信度は0.74〜1.00です。全件一致は、この3種類の話です。38/39は、日本語20件の全体の話で、別の試験です。

苦手なことは、資料に書かれていたとおりでした。文章を書く、計算する、日付を抜き出す、数を数える、画像を見る。否定や含意は、明示しないと読み取れません。

承認の自動化はやめた

最初に試したのは、危険なコマンドの承認の自動化です。Jevの紹介記事にあった「確率が2つとも0.9以上なら自動で許可する」という使い方を、そのまま試しました。

危険なコマンドの確率は0.02〜0.15で、向きは正しく出ました。ただ、安全な読み取り(grepやsed)でも「作業に必要か」が0.88〜0.89で、8件中0件しか通りません。git pull --rebaseの「元に戻せるか」は0.43でした。

そこで、紛らわしい24件で試し直しました。危険なもの(隠れた削除、作業の破棄、秘密の送信など)は、どのしきい値でも1件も通しません。しかし、通すべき読み取り・テストは、次のとおりです。

しきい値 通った件数(通すべき10件のうち)
0.9 0件
0.8 2件
0.7 3件

lsやgit statusでも、「作業に必要か」は0.55〜0.68でした。さらに、APIキーをcatで読む操作を、「元に戻せる」(0.82〜0.93)と判定しました。境界にならないので、承認の自動化はやめました。 代わりに、決まったコマンドの許可一覧で通すことにしました。

会話の圧縮もやめた

会話の記録が長くなったとき、捨ててよい部分をJevに振り分けさせる使い方も試しました。実際の会話の記録2本で、「捨てる」に振り分けられたのは、文字数の11%と30%だけでした。Jevは要約を書けないためです。私の指示は全件残ったので、安全ではありますが、効果が小さいのでやめました。

レビュー前の事前チェックに残した

最後に残したのが、レビュー前の事前チェックです。設計書に必須の項目が書かれているかを、レビューの前に確かめます。欠けていれば、レビューの2人を呼ばずに、設計へ戻します。

J9.png

チェックリストは、2種類の項目でできています。1つは「〜が書かれているか?」という問いで、Jevに聞きます。問いの実物は、次のとおりです。

checklist.json
{"items": [
 {"id": "current_problems", "question": "今のコードの問題点が、コードを読んで確かめた形で書かれているか?"},
 {"id": "retry", "question": "同時更新の衝突(409)のときの再試行の方針が書かれているか?"},
 {"id": "validation", "question": "入力チェックと、不正な入力のときに返すエラー(400 など)が書かれているか?"},
 {"id": "tests", "question": "テスト計画(どのケースをどう確かめるか)が書かれているか?"},
 {"id": "scope", "question": "今回の範囲に入れないことが明記されているか?"}
]}

もう1つは、図の数など、数える項目です。Jevは数えられないので、コードで数えます。

コードのnoulは、「書かれているか」を確率で返す問いの型です。

precheck.py
for it in items:
    if "count" in it:
        n = len(re.findall(it["count"], extract(doc, it["section"]) if it.get("section") else doc))
        results.append({"id": it["id"], "p": 1.0 if n >= it.get("min", 1) else 0.0, "count": n})
    else:
        groups.setdefault(it.get("section"), []).append(it)

for section, its in groups.items():
    state = extract(doc, section) if section else doc
    if not state.strip():  # 見出しがない:項目は未記入なので、聞かずに0
        results += [{"id": it["id"], "p": 0.0, "note": "section not found"} for it in its]
        continue
    qs = {it["id"]: {"type": "noul", "instructions": it["question"]} for it in its}
    best = {}
    for part in chunks(state):  # 長いと断られるので分けて送る。書かれていれば、どこか1つの部分に出る
        r = ask(part, qs, caller="precheck")
        for k, v in r["answers"].items():
            best[k] = max(best.get(k, 0.0), v["noul"])
  • 数える項目は、基準の数以上なら1.0、満たさなければ0.0
  • 同じ節の問いは、1リクエストにまとめる。見出しが見つからなければ、聞かずに0
  • 3万字を超える文書は、## の見出しで分けて送り、一番高い確率を採る。書かれていれば、どこか1つの部分には出るはずだからです。約3万トークンは通り、約5万トークンは断られました
  • しきい値は0.5。1つでも下回れば差し戻す。終了コード0(通過)、1(差し戻し)、2(エラー)で、親のエージェントが次の動きを分ける

結果は、判定(pass・return)、項目ごとの確率、リクエストの回数、入力トークン、かかった秒数を、JSONで返します。設計書1本の確認は、1〜6回のリクエストで、0.4〜2.3秒でした。

過去の設計書7本に当てた

7本とも、通過しました。

一番低い確率は、0.89〜0.95です。Jevに送った量は、設計書7本で16,405〜38,026トークンです。
うち3本は1回で送った量(16,405〜32,303)、別の3本は節ごとに6回に分けた合計(26,718〜29,819)です。
残る1本は38,026トークンで、1回では上限に当たったので、2回に分けて送りました。

レビューで不合格になった5本の理由は、コードと合わない説明、壊れるケースの見落とし、引用に実在の会社名など、すべて中身の誤りでした。事前チェックでは見つけられず、省けたレビューは0回です。

わざと崩した版でも試しました。

崩し方 結果
節を見出しごと消す 差し戻し(コードが見つけた)
見出しを残し、本文を「(未記入)」にする 0.05で差し戻し(Jevが見つけた)
図9個のうち8個を消す 0.95で通過
図を全部消す 0.96で通過(本文に図の説明が残るため)

図の数はJevでは見抜けないので、数える項目にしました。数える項目にすると、全部消した版は差し戻されました。

実際の作業でも、12回(設計4・下書き8)すべて通過し、差し戻しは0回でした。計約20万トークン、8.5秒です。1回は0.3秒前後で、レビュー1回の5〜40分と比べれば、ほぼ時間はかかりません。ただ、保険にはなりますが、レビューの回数と時間は減りませんでした。

分かったこと

役目は、次のように分けるとうまくいきました。

  • 数えるのは、コード
  • 書かれているかを見るのは、Jev
  • 正しいかを見るのは、レビューの2人

Jevは、「選ぶだけ」「あるかないか」の判定の部品です。仕事の正しさは見ません。ディベートでは票を数える役、設計書では事前チェックの役に残し、承認の自動化と会話の圧縮はやめました。図は、今の役割分担です。

J4.png

1本目の票の数え上げも、同じ考え方です。Jevに任せたのは選ぶ部分だけで、論を書くのも、まとめを書くのも、Claudeです。

決めるのは人です。Jevを何に使うかも、私が決めています。

続き

海外Yパパさんの動画で具体的に使っている仕組みを参考に、私が必要とする使いかでどう使うかを書いてみます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?