File size: 6,523 Bytes
df41178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/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]} 件が当たった")