Measure how accurately a compiled skill's description fires. Generates trigger-eval prompts via LLM, then asks a grader LLM whether the description should activate the skill for each prompt. Prints pass rate + miss list.
(ctx, name, save_flag, eval_set_path, count)
| 2630 | ) |
| 2631 | @click.pass_context |
| 2632 | def skill_eval(ctx, name, save_flag, eval_set_path, count): |
| 2633 | """Measure how accurately a compiled skill's description fires. |
| 2634 | |
| 2635 | Generates trigger-eval prompts via LLM, then asks a grader LLM whether |
| 2636 | the description should activate the skill for each prompt. Prints pass |
| 2637 | rate + miss list. |
| 2638 | """ |
| 2639 | from openkb.skill.evaluator import ( |
| 2640 | run_eval, |
| 2641 | save_eval_set, |
| 2642 | load_eval_set, |
| 2643 | EvalPrompt, |
| 2644 | ) |
| 2645 | |
| 2646 | from openkb.skill import skill_dir as _skill_dir |
| 2647 | |
| 2648 | kb_dir = _find_kb_dir(ctx.obj.get("kb_dir_override")) |
| 2649 | if kb_dir is None: |
| 2650 | click.echo("No knowledge base found. Run `openkb init` first.", err=True) |
| 2651 | ctx.exit(1) |
| 2652 | |
| 2653 | skill_dir = _skill_dir(kb_dir, name) |
| 2654 | if not skill_dir.is_dir(): |
| 2655 | click.echo(f"[ERROR] Skill '{name}' not found.", err=True) |
| 2656 | ctx.exit(1) |
| 2657 | |
| 2658 | try: |
| 2659 | _setup_llm_key(kb_dir) |
| 2660 | except RuntimeError as exc: |
| 2661 | click.echo(f"[ERROR] {exc}", err=True) |
| 2662 | ctx.exit(1) |
| 2663 | config = load_config(kb_dir / ".openkb" / "config.yaml") |
| 2664 | model = config.get("model", DEFAULT_CONFIG["model"]) |
| 2665 | |
| 2666 | eval_set: list[EvalPrompt] | None = None |
| 2667 | if eval_set_path: |
| 2668 | eval_set = load_eval_set(Path(eval_set_path)) |
| 2669 | click.echo(f"Loaded eval set from {eval_set_path} ({len(eval_set)} prompts).") |
| 2670 | else: |
| 2671 | click.echo(f"Generating eval set for '{name}' (count={count} per side)...") |
| 2672 | |
| 2673 | try: |
| 2674 | result = asyncio.run( |
| 2675 | run_eval( |
| 2676 | skill_dir, |
| 2677 | model=model, |
| 2678 | eval_set=eval_set, |
| 2679 | count=count, |
| 2680 | ) |
| 2681 | ) |
| 2682 | except RuntimeError as exc: |
| 2683 | click.echo(f"[ERROR] {exc}", err=True) |
| 2684 | ctx.exit(1) |
| 2685 | |
| 2686 | click.echo(f"\nEval set: {result.total} prompts") |
| 2687 | click.echo( |
| 2688 | f"Trigger accuracy: {result.passed}/{result.trigger_scored} " |
| 2689 | f"({result.pass_rate * 100:.0f}%) " |
nothing calls this directly
no test coverage detected