miutti's picture
Source: kernel, desktop app, tools (snapshot of the GitHub repo)
df41178 verified
Raw History Blame Contribute Delete
6.52 kB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
bench.py -- 性能を測る
「賢くなった気がする」では直すところを間違える。
・ちゃんと答えられた割合
・かかった時間(はじめて / 2回目)
・ノートが当たった割合
を、まとめて出す。
"""
import os, sys, io, time, json, contextlib
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import kernel
# 入力 → 期待する答えの一部(含まれていれば正解とみなす)
CASES = [
("デスクトップの写真を数えて", "5 個"),
("机の上の画像はいくつ?", "5 個"),
("デスクトップの動画は何個?", "1 個"),
("デスクトップのPDFを数えて", "1 個"),
("デスクトップには何がある?", "旅行1.jpg"),
("ダウンロードのPDFを数えて", "3 個"),
("デスクトップの去年の写真を数えて", "4 個"),
("デスクトップの書類を数えて", "2 個"),
("デスクトップの一覧を見せて", "会議.pdf"),
("ダウンロードには何がある?", "請求書.pdf"),
("デスクトップのテキストを数えて", "1 個"),
("机の上の去年の画像はいくつ", "4 個"),
("デスクトップの音楽を数えて", "0 個"),
("ダウンロードの画像を数えて", "1 個"),
# --- ここから、実際のやりとりで出てきた言い方 ---
("机の上の去年のスナップ、片付けといて", "個を"),
("デスクトップに散らかってる写真を集めて", "個を"),
("さっき撮ったやつを見せて", "jpg"),
("デスクトップの一番大きいファイルは?", "mp4"),
("ダウンロードで一番古いのは何?", "古い.pdf"),
("デスクトップに同じファイルある?", "組"),
("デスクトップぜんぶで何メガ?", "MB"),
("デスクトップの画像は何個?", "5 個"),
("先月のダウンロードを数えて", "個"),
("デスクトップのjpgだけ見せて", "旅行1.jpg"),
("デスクトップの画像以外を数えて", "3 個"),
# --- ここから、文法(述語と助詞)で読むもの ---
("ダウンロードから書類をデスクトップに移して", "3 個を"),
("デスクトップの写真を寄せといてくれる?", "個を"),
("デスクトップのテキストをしまっとく", "個を"),
("デスクトップの画像を並べてもらえる?", "旅行1.jpg"),
("デスクトップの画像を数えといて", "5 個"),
("机の上の去年の写真をまとめてほしい", "個を"),
("デスクトップの動画を数えてください", "1 個"),
("デスクトップのPDFを見せてよ", "会議.pdf"),
]
import chat
def once(text):
"""1回動かして (答え, ミリ秒, 記録) を返す
聞かれているのか命令なのかは、本番と同じ振り分けで決める。
ここを全部「聞かれている」にしていたので、
「片付けといて」まで一覧が返って、不正解に数えていた
"""
# 動かす命令は練習用フォルダを書き換えるので、毎回まっさらに戻す。
# 戻していなかったため、前の命令が動かした結果を次が見てしまい、
# 2回目以降の正解率が下がっていた(ノートのせいに見えていた)
with contextlib.redirect_stdout(io.StringIO()):
kernel.make_demo()
slots = kernel.draw_cards(text)
kind = chat.classify(text, slots)
ro = (kind != "命令")
buf = io.StringIO()
t0 = time.time()
with contextlib.redirect_stdout(buf):
try:
ans = kernel.handle(text, readonly=ro, quiet=True)
except Exception as e:
ans = f"失敗: {e}"
ms = (time.time() - t0) * 1000
return (ans or ""), ms, buf.getvalue()
def note_uses():
"""ノートが当たった回数。
前はノートの「回数」の合計を前後で引き算していた。
だが手順を組み立て直すたびに 回数 が 1 に戻る作りだったので、
合計が下がることがあり、当たった回数がマイナスになっていた
(実測で -23/33 が出た)。
いまは kernel がその場で数えているので、それを読む。
"""
try:
return kernel.note_hit_total()
except AttributeError:
return 0
def run(label, reset_note):
if reset_note:
for f in ("notebook.json", "policy.json"):
p = os.path.join(HERE, f)
if os.path.exists(p):
os.remove(p)
before = note_uses()
ok = 0
total = 0.0
rows = []
for text, want in CASES:
ans, ms, _log = once(text)
good = want in (ans or "")
ok += good; total += ms
rows.append((text, want, ans, ms, good, False))
hit = note_uses() - before
n = len(CASES)
print(f"\n■ {label}")
print(f" 正解 : {ok}/{n} ({ok/n*100:.0f}%)")
print(f" ノート当たり: {hit}/{n} ({hit/n*100:.0f}%)")
print(f" 合計時間 : {total:.0f} ミリ秒 (1件あたり {total/n:.1f})")
for text, want, ans, ms, good, _h in rows:
if not good:
print(f" ✗ {text}")
print(f" ほしい「{want}」/ 出た「{str(ans)[:60]}」")
return ok, n, total, hit
if __name__ == "__main__":
# KERNEL_THINK=1 で「じっくり(何人かで考える)」を測る
if os.environ.get("KERNEL_THINK") == "1":
kernel.THINK_HARD = True
print("※ じっくりモード(何人かで考えて多数決)で測ります")
a = run("1回目(ノート空っぽ)", reset_note=True)
b = run("2回目(ノートが溜まった状態)", reset_note=False)
c = run("3回目", reset_note=False)
print("\n■ まとめ")
print(f" 正解 : {a[0]}/{a[1]} → {b[0]}/{b[1]} → {c[0]}/{c[1]}")
print(f" 合計時間: {a[2]:.0f} → {b[2]:.0f} → {c[2]:.0f} ミリ秒")
print(f" ノート : {a[3]} → {b[3]} → {c[3]} 件が当たった")