Use an LLM to generate ``count`` should-trigger + ``count`` should-not eval prompts grounded in what the skill actually claims to cover. The generator now sees the SKILL.md body and reference previews, not just the description. That keeps the should-trigger questions realistic (ques
(
skill_dir: Path,
*,
model: str,
count: int = EVAL_DEFAULT_COUNT,
)
| 193 | |
| 194 | |
| 195 | async def generate_eval_set( |
| 196 | skill_dir: Path, |
| 197 | *, |
| 198 | model: str, |
| 199 | count: int = EVAL_DEFAULT_COUNT, |
| 200 | ) -> list[EvalPrompt]: |
| 201 | """Use an LLM to generate ``count`` should-trigger + ``count`` should-not |
| 202 | eval prompts grounded in what the skill actually claims to cover. |
| 203 | |
| 204 | The generator now sees the SKILL.md body and reference previews, not |
| 205 | just the description. That keeps the should-trigger questions |
| 206 | realistic (questions the skill is genuinely set up to answer) and the |
| 207 | should-not questions plausibly-adjacent (so trigger accuracy actually |
| 208 | catches over-broad descriptions, not just disjoint ones). |
| 209 | """ |
| 210 | desc = _read_description(skill_dir) |
| 211 | content = _skill_content_block(skill_dir) |
| 212 | |
| 213 | instructions = ( |
| 214 | "You are designing an evaluation set for a knowledge-base skill. " |
| 215 | "The skill's activation description is:\n\n" |
| 216 | f" {desc}\n\n" |
| 217 | "The skill's body (SKILL.md without frontmatter) and references " |
| 218 | "are below. Use them to ground the questions in what the skill " |
| 219 | "actually claims to cover.\n\n" |
| 220 | f"{content}\n\n" |
| 221 | f"Produce exactly {count} 'should-trigger' user questions " |
| 222 | "(questions a user might ask where this skill genuinely helps — " |
| 223 | "ones the body and references contain material for) and exactly " |
| 224 | f"{count} 'should-not' user questions (plausibly-adjacent " |
| 225 | "questions where this skill is NOT the right tool — they should " |
| 226 | "be close enough that a sloppy description would mis-trigger, " |
| 227 | "but the body clearly does not cover them).\n\n" |
| 228 | "Output ONLY a JSON object with this exact shape:\n" |
| 229 | f' {{"should_trigger": [...{count} strings...], ' |
| 230 | f'"should_not": [...{count} strings...]}}\n\n' |
| 231 | "No prose. No markdown. Just the JSON object." |
| 232 | ) |
| 233 | |
| 234 | agent = Agent( |
| 235 | name="eval-set-generator", |
| 236 | instructions=instructions, |
| 237 | model=f"litellm/{model}", |
| 238 | model_settings=ModelSettings( |
| 239 | extra_headers=get_extra_headers() or None, |
| 240 | extra_args=get_timeout_extra_args(), |
| 241 | ), |
| 242 | ) |
| 243 | try: |
| 244 | result = await Runner.run(agent, "Generate the eval set now.", max_turns=3) |
| 245 | except MaxTurnsExceeded as exc: |
| 246 | raise RuntimeError( |
| 247 | "Eval set generation hit the max-turn cap. The model may be " |
| 248 | "looping; try a different model or a smaller --count." |
| 249 | ) from exc |
| 250 | raw = (result.final_output or "").strip() |
| 251 | |
| 252 | # Strip optional code fence |