Spaces:
Runtime error
Runtime error
Download gemini_batch.py from stevafernandes/bee-ai: direct link, hf CLI and curl.
- Browser
- Download file 4.3 kB
-
https://huggingface.co/spaces/stevafernandes/bee-ai/resolve/main/gemini_batch.py
- Command line
-
hf download hf://spaces/stevafernandes/bee-ai/gemini_batch.py
-
curl -L -o gemini_batch.py https://huggingface.co/spaces/stevafernandes/bee-ai/resolve/main/gemini_batch.py
4.3 kB
| """ | |
| gemini_batch.py - run Gemini's structured listening (gemini_audio.describe_clip) over every | |
| recording in the workbook and cache the results. | |
| GEMINI_API_KEY_FILE=... python gemini_batch.py --audio-dir <dir> [--workers 4] [--retest 40] | |
| Outputs (artifacts/features/): | |
| gemini_raw/<file>.json one cached JSON per recording (resumable) | |
| gemini_semantic.csv flat numeric features per file (gemini_audio.semantic_features) | |
| gemini_retest.csv optional: a second, independent call for N files to measure | |
| test-retest agreement of the structured fields | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import sys | |
| import time | |
| from concurrent.futures import ThreadPoolExecutor, as_completed | |
| import pandas as pd | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| sys.path.insert(0, HERE) | |
| import acoustic as ac # noqa: E402 | |
| import data as bd # noqa: E402 | |
| import gemini_audio as ga # noqa: E402 | |
| def _one(path, client): | |
| y, sr = ac.load_audio(path, ac.SR) | |
| return ga.describe_clip(y, sr, client=client) | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--audio-dir", required=True) | |
| ap.add_argument("--workbook", default=os.path.join(HERE, "AI_Data_Training.xlsx")) | |
| ap.add_argument("--out", default=os.path.join(HERE, "artifacts", "features")) | |
| ap.add_argument("--workers", type=int, default=4) | |
| ap.add_argument("--retest", type=int, default=0) | |
| ap.add_argument("--limit", type=int, default=None) | |
| a = ap.parse_args() | |
| if not ga.available(): | |
| print("no Gemini API key configured (GEMINI_API_KEY / GEMINI_API_KEY_FILE); nothing to do") | |
| return | |
| raw_dir = os.path.join(a.out, "gemini_raw") | |
| os.makedirs(raw_dir, exist_ok=True) | |
| df = bd.load_workbook(a.workbook, audio_dir=a.audio_dir) | |
| files = list(df.loc[df["has_audio"], "sound_file"]) | |
| on_disk = {f.lower(): f for f in os.listdir(a.audio_dir)} | |
| files = [on_disk[f.lower()] for f in files] | |
| if a.limit: | |
| files = files[: a.limit] | |
| client = ga.get_client() | |
| todo = [f for f in files if not os.path.exists(os.path.join(raw_dir, f + ".json"))] | |
| print(f"{len(files)} files, {len(todo)} to describe, workers={a.workers}", flush=True) | |
| t0 = time.time() | |
| n_err = 0 | |
| with ThreadPoolExecutor(max_workers=a.workers) as ex: | |
| futs = {ex.submit(_one, os.path.join(a.audio_dir, f), client): f for f in todo} | |
| for k, fut in enumerate(as_completed(futs), 1): | |
| f = futs[fut] | |
| try: | |
| d = fut.result() | |
| json.dump(d, open(os.path.join(raw_dir, f + ".json"), "w")) | |
| except Exception as e: # noqa | |
| n_err += 1 | |
| print(f" error {f}: {type(e).__name__}: {str(e)[:120]}", flush=True) | |
| if k % 50 == 0 or k == len(todo): | |
| print(f" {k}/{len(todo)} {time.time()-t0:.0f}s errors={n_err}", flush=True) | |
| rows = [] | |
| for f in files: | |
| p = os.path.join(raw_dir, f + ".json") | |
| d = json.load(open(p)) if os.path.exists(p) else None | |
| row = dict(file=f, **ga.semantic_features(d)) | |
| if d is not None: | |
| row["gem_model"] = d.get("model") | |
| row["gem_dominant_sounds"] = "; ".join(d.get("dominant_sounds") or []) | |
| row["gem_notes"] = d.get("notes") | |
| rows.append(row) | |
| pd.DataFrame(rows).to_csv(os.path.join(a.out, "gemini_semantic.csv"), index=False) | |
| print("wrote gemini_semantic.csv", flush=True) | |
| if a.retest: | |
| import random | |
| rnd = random.Random(0) | |
| sub = rnd.sample(files, min(a.retest, len(files))) | |
| rows = [] | |
| with ThreadPoolExecutor(max_workers=a.workers) as ex: | |
| futs = {ex.submit(_one, os.path.join(a.audio_dir, f), client): f for f in sub} | |
| for fut in as_completed(futs): | |
| f = futs[fut] | |
| try: | |
| d = fut.result() | |
| rows.append(dict(file=f, **ga.semantic_features(d))) | |
| except Exception as e: # noqa | |
| print(f" retest error {f}: {e}", flush=True) | |
| pd.DataFrame(rows).to_csv(os.path.join(a.out, "gemini_retest.csv"), index=False) | |
| print("wrote gemini_retest.csv", flush=True) | |
| if __name__ == "__main__": | |
| main() | |