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エージェントの完了報告をPythonで検収する

0
Posted at

「OpenAI、初のハードウェア『Codex Micro』を230ドルで発売」

7月15日のこのニュースを見て、複数の作業を並行で見張る道具が前に出てきたなと思いました。これが意味するのは、AIに仕事を一件ずつ頼む時間が終わり、同時に走る仕事の「完了」をどう扱うかが現場の詰まりどころになる、ということです。

僕は、完了報告に「できました」とだけ書かせる運用には反対です。成果物の場所も検証結果もない一行は、件数が増えるほど確認作業を後ろへ送るだけです。今日、下のスクリプトをサンプルJSONとCSVで動かしたところ、ファイルの有無だけでなく、JSONの必須キーとCSVの列・行数まで分けて落とせました。ここ地味に効きます。

完了の判断を、報告文から成果物の検収へ移します。

先に「何があれば終わりか」をJSONにする

たとえば営業資料の要約なら、要約ファイルがあるだけでは足りません。次のアクションが入っているか、担当者の一覧がCSVなら列名が揃っているかまで決めます。AIへの依頼文とは別に、検収用の tasks.json を置きます。

[
  {
    "id": "sales-01",
    "status": "done",
    "artifact": "deliverables/summary.json",
    "format": "json",
    "required_keys": ["summary", "next_actions"]
  },
  {
    "id": "sales-02",
    "status": "done",
    "artifact": "deliverables/list.csv",
    "format": "csv",
    "required_columns": ["company", "owner"],
    "min_rows": 1
  }
]

artifactdeliverables/ 配下に限定しているのも大事です。報告側が勝手に別の場所のファイルを指しても、検収対象にはしません。

Pythonで成果物を検収する

次を verify_deliverables.py として保存し、python3 verify_deliverables.py tasks.json で実行します。外部ライブラリは使いません。AIが書いた任意のコマンドは実行せず、ファイルの形だけを確認します。

import csv
import json
import sys
from pathlib import Path

REQUIRED = ("id", "status", "artifact", "format")

def under_deliverables(value, root):
    path = Path(value).resolve()
    try:
        path.relative_to(root)
    except ValueError:
        raise ValueError("artifact は deliverables/ 配下に置く")
    return path

def verify(task, root):
    errors = [f"{key} がない" for key in REQUIRED if not task.get(key)]
    if errors:
        return errors
    if task["status"] != "done":
        return ["status が done ではない"]
    try:
        artifact = under_deliverables(task["artifact"], root)
    except ValueError as err:
        return [str(err)]
    if not artifact.is_file():
        return [f"成果物がない: {task['artifact']}"]
    if artifact.stat().st_size < task.get("min_bytes", 20):
        return [f"成果物が小さすぎる: {artifact.stat().st_size} bytes"]

    if task["format"] == "json":
        try:
            data = json.loads(artifact.read_text(encoding="utf-8"))
        except json.JSONDecodeError as err:
            return [f"JSONとして読めない: {err.msg}"]
        missing = [key for key in task.get("required_keys", []) if key not in data]
        return [f"JSONの必須キーがない: {', '.join(missing)}"] if missing else []

    if task["format"] == "csv":
        with artifact.open(encoding="utf-8", newline="") as f:
            reader = csv.DictReader(f)
            rows = list(reader)
        columns = set(reader.fieldnames or [])
        missing = set(task.get("required_columns", [])) - columns
        if missing:
            return [f"CSVの必須列がない: {', '.join(sorted(missing))}"]
        if len(rows) < task.get("min_rows", 1):
            return [f"CSVの行数が足りない: {len(rows)}"]
        return []

    return [f"未対応の format: {task['format']}"]

def main():
    tasks = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
    root = Path("deliverables").resolve()
    failed = False
    for task in tasks:
        reasons = verify(task, root)
        label = task.get("id", "idなし")
        if reasons:
            failed = True
            print(f"{label}: NG {' / '.join(reasons)}")
        else:
            print(f"{label}: OK")
    return 1 if failed else 0

if __name__ == "__main__":
    raise SystemExit(main())

手元のサンプルでは、sales-01: OKsales-02: OK。必須キーをわざと外した sales-03 は、NG JSONの必須キーがない: approved_by で止まりました。報告の文面を読むより、どこを直せばよいかが早く分かります。

完了率より、差し戻し理由を残す

この仕組みの狙いは、完了率をきれいに見せることではありません。成果物なし、形式不正、必要項目不足を別々に残すと、依頼の書き方が悪いのか、出力形式が曖昧なのかを次回に直せます。全部を人が読む運用より、確認する場所がずっと小さくなります。

最初はJSONとCSVだけで十分です。資料ならページ数、メール下書きなら宛先リストなど、業務に合わせて検収条件を一つ足します。AIを並行で使うほど、速さより先に「終わった」の定義を固める。僕はここから始めるのがいちばん実務的だと思っています。

参考: OpenAI、初のハードウェア「Codex Micro」を230ドルで発売

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?