58 lines
3.0 KiB
Python
58 lines
3.0 KiB
Python
"""Export causal, continuous MaAI scores for EOT Studio (no label gating)."""
|
|||
|
|
import csv
|
||
|
|
import hashlib
|
||
|
|
import json
|
||
|
|
|
||
|
|
from smoke_run import HERE, ROOT, EXPECTED, WEIGHTS, CPC, np, sf, soxr, torch
|
||
|
|
from evaluate_can_reply import model
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
torch.set_num_threads(4)
|
||
|
|
torch.set_num_interop_threads(1)
|
||
|
|
for p in (WEIGHTS, CPC):
|
||
|
|
assert hashlib.sha256(p.read_bytes()).hexdigest() == EXPECTED[p.name]
|
||
|
|
with (HERE/'results/work-data-can-reply/predictions.csv').open(encoding='utf-8-sig') as f:
|
||
|
|
checkpoints = list(csv.DictReader(f))
|
||
|
|
calls = []
|
||
|
|
for call in sorted({r['call_id'] for r in checkpoints}):
|
||
|
|
path = ROOT/'data/韩泰机器人抢话/音频'/f'{call}.mp3'
|
||
|
|
pcm, sr = sf.read(path, dtype='float32', always_2d=True)
|
||
|
|
assert pcm.shape[1] == 2
|
||
|
|
maai = model()
|
||
|
|
maai.CALC_PROCESS_TIME_INTERVAL = 10**9
|
||
|
|
resampler = soxr.ResampleStream(sr,16000,2,dtype='float32',quality='HQ')
|
||
|
|
pending = np.empty((0,2),dtype=np.float32)
|
||
|
|
points = []
|
||
|
|
# Streaming resampling never reads the next input block. Timestamp each
|
||
|
|
# result when its audio is actually available, including filter delay.
|
||
|
|
for start in range(0,len(pcm),sr//10):
|
||
|
|
end = min(len(pcm),start+sr//10)
|
||
|
|
block = resampler.resample_chunk(pcm[start:end],last=end==len(pcm))
|
||
|
|
pending = np.concatenate([pending,block])
|
||
|
|
score = None
|
||
|
|
while len(pending)>=1600:
|
||
|
|
frame,pending = pending[:1600],pending[1600:]
|
||
|
|
maai.process(np.ascontiguousarray(frame[:,0]),np.ascontiguousarray(frame[:,1]))
|
||
|
|
result = maai.result_dict_queue.get_nowait()
|
||
|
|
score = 1-float(result['p_now'][0])
|
||
|
|
assert np.isfinite(score) and 0<=score<=1
|
||
|
|
if score is not None:
|
||
|
|
points.append([round(end*1000/sr,3),round(score,7)])
|
||
|
|
calls.append(dict(call_id=call,audio_path=f'韩泰机器人抢话/音频/{call}.mp3',
|
||
|
|
audio_sha256=hashlib.sha256(path.read_bytes()).hexdigest(),
|
||
|
|
duration_ms=round(len(pcm)*1000/sr,3),points=points,
|
||
|
|
checkpoints=sorted([[int(r['decision_ms']),round(1-float(r['p_now_user']),7)]
|
||
|
|
for r in checkpoints if r['call_id']==call])))
|
||
|
|
del maai
|
||
|
|
print(f'{call[:8]}: {len(points)} timeline scores',flush=True)
|
||
|
|
output = dict(schema_version=1,model='maai',name='MaAI',sample_interval_ms=100,
|
||
|
|
score='1 - p_now[user]',
|
||
|
|
method='Continuous stereo replay, 16kHz, 10Hz, CPC + ch_kyoto noise-robust VAP, 20s KV cache. Causal streaming resampler; timestamps denote input availability. Checkpoints retain the earlier independent <=20s point evaluation.',
|
||
|
|
model_sha256=EXPECTED,script_sha256=hashlib.sha256((HERE/'export_timeline.py').read_bytes()).hexdigest(),calls=calls)
|
||
|
|
(HERE/'results/score-timeline.json').write_text(json.dumps(output,ensure_ascii=False,separators=(',',':'))+'\n')
|
||
|
|
|
||
|
|
|
||
|
|
if __name__=='__main__':
|
||
|
|
main()
|