darkrange-eval 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/PKG-INFO +1 -1
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/PKG-INFO +1 -1
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/app.py +23 -14
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/banner.py +2 -1
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/task.py +13 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/pyproject.toml +1 -1
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/README.md +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/SOURCES.txt +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/dependency_links.txt +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/entry_points.txt +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/requires.txt +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/darkrange_eval.egg-info/top_level.txt +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/__init__.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/_mock.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/adapter.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/cli.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/criteria.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/__init__.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/command_lint.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/cve_struct.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/cwe_label.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/execute.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/extract_f1.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/fabrication_scan.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/json_schema.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/mcq.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/paired_divergence.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/plan_check.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/graders/refusal.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/history.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/judge.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/logo.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/runner.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/scoring.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/threshold.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/dreval/tui.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/setup.cfg +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/tests/test_app.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/tests/test_graders.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/tests/test_pipeline.py +0 -0
- {darkrange_eval-0.1.0 → darkrange_eval-0.1.2}/tests/test_suite_files.py +0 -0
|
@@ -14,7 +14,7 @@ import urllib.request
|
|
|
14
14
|
from . import banner, history, threshold, tui
|
|
15
15
|
from .criteria import CRITERIA, GATES, POOLS
|
|
16
16
|
from .runner import run_suite
|
|
17
|
-
from .task import load_suite, smoke_subset
|
|
17
|
+
from .task import load_suite, smoke_subset, random_subset
|
|
18
18
|
|
|
19
19
|
CLAUDE_MODELS = ["claude-sonnet-5", "claude-opus-4-8", "claude-haiku-4-5-20251001"]
|
|
20
20
|
_CRIT_NAME = {c["key"]: c["name"] for c in CRITERIA}
|
|
@@ -230,12 +230,13 @@ def _browse_cases(io, journal, breadcrumb, mode="all"):
|
|
|
230
230
|
# ------------------------------------------------------------------ run flow
|
|
231
231
|
def _flow_run(io, adapter_factory):
|
|
232
232
|
mode = tui.menu(
|
|
233
|
-
["Quick smoke — 2 per criterion (
|
|
234
|
-
"
|
|
235
|
-
"
|
|
233
|
+
["Quick smoke — 2 per criterion (24 tasks · seconds)",
|
|
234
|
+
"Fast eval — 15 random per criterion (180 tasks · minutes)",
|
|
235
|
+
"Mid scan — 25 per criterion (300 tasks · minutes)",
|
|
236
|
+
"Full scan — all criteria (606 tasks · long)",
|
|
236
237
|
"Back"],
|
|
237
238
|
io, title="Choose scan depth", breadcrumb="Run a test")
|
|
238
|
-
if mode is None or mode ==
|
|
239
|
+
if mode is None or mode == 4:
|
|
239
240
|
return
|
|
240
241
|
|
|
241
242
|
tui.clear(); tui.header("Run a test / target")
|
|
@@ -267,8 +268,10 @@ def _flow_run(io, adapter_factory):
|
|
|
267
268
|
if mode == 0:
|
|
268
269
|
tasks = smoke_subset(tasks, 2)
|
|
269
270
|
elif mode == 1:
|
|
271
|
+
tasks = random_subset(tasks, 15)
|
|
272
|
+
elif mode == 2:
|
|
270
273
|
tasks = smoke_subset(tasks, 25)
|
|
271
|
-
label = {0: "smoke", 1: "
|
|
274
|
+
label = {0: "smoke", 1: "fast", 2: "mid", 3: "full"}[mode]
|
|
272
275
|
|
|
273
276
|
adapter = adapter_factory(endpoint, model, provider=provider, api_key=api_key)
|
|
274
277
|
|
|
@@ -373,12 +376,18 @@ def _gates_lines():
|
|
|
373
376
|
|
|
374
377
|
def _working_lines():
|
|
375
378
|
return ["HOW THE BENCHMARK WORKS", "",
|
|
376
|
-
" 1.
|
|
377
|
-
" 2.
|
|
378
|
-
"
|
|
379
|
-
"
|
|
380
|
-
"
|
|
381
|
-
"
|
|
379
|
+
" 1. Suites & Tasks: The benchmark contains 606 synthetic task JSON files covering 12 criteria.",
|
|
380
|
+
" 2. Execution: During the scan, each task is sent directly to your LLM endpoint.",
|
|
381
|
+
" The model operates strictly in a single-turn, isolated environment (no agent memory, no live tools).",
|
|
382
|
+
" This ensures we are evaluating raw intelligence and reasoning, not the surrounding orchestration framework.",
|
|
383
|
+
" 3. Grading: The model's raw string output is parsed by a suite of deterministic, heuristic graders.",
|
|
384
|
+
" - Syntax Graders: Use AST/Shlex to ensure valid Bash tools (e.g. nmap, ffuf) are generated.",
|
|
385
|
+
" - Extraction Graders: Parse F1 scores for JSON schemas or Regex matches.",
|
|
386
|
+
" - Multiple Choice: Tests knowledge deterministically without prompt variation bias.",
|
|
387
|
+
" 4. Scoring: Each task scores 0.0 to 1.0. These roll up into Criterion Means, which are finally weighted",
|
|
388
|
+
" to produce the overall DarkRange Evaluation Score (DES).",
|
|
389
|
+
" 5. Gates: Even if DES is high, the model can FAIL if it trips a 'Safety Gate' (e.g., generating an",
|
|
390
|
+
" out-of-scope exploit or fabricating CVEs)."]
|
|
382
391
|
|
|
383
392
|
|
|
384
393
|
def _info_page(io, title, lines):
|
|
@@ -394,7 +403,7 @@ def _info_criteria(io):
|
|
|
394
403
|
labels = [f"{c['n']:>2}. {c['name']:34} [{int(c['weight'] * 100)}% · tier {c['tier']}]"
|
|
395
404
|
for c in CRITERIA]
|
|
396
405
|
sel = tui.menu(labels + ["Back"], io,
|
|
397
|
-
title="The
|
|
406
|
+
title="The 12 criteria — pick one for full detail", breadcrumb="Info / criteria")
|
|
398
407
|
if sel is None or sel == len(CRITERIA):
|
|
399
408
|
return
|
|
400
409
|
c = CRITERIA[sel]
|
|
@@ -410,7 +419,7 @@ def _info_criteria(io):
|
|
|
410
419
|
def _flow_info(io):
|
|
411
420
|
while True:
|
|
412
421
|
sel = tui.menu(
|
|
413
|
-
["Browse the
|
|
422
|
+
["Browse the 12 criteria (measures, judging, why, example)",
|
|
414
423
|
"Metrics & scoring", "Gates & data pools",
|
|
415
424
|
"Ideal threshold (how it was set)", "How the benchmark works", "Back"],
|
|
416
425
|
io, title="What do you want to know?", breadcrumb="Info")
|
|
@@ -14,7 +14,8 @@ DR_TEXT = r""" ██████╗ █████╗ ██████╗
|
|
|
14
14
|
██║ ██║███████║██████╔╝█████╔╝ ██████╔╝███████║██╔██╗ ██║██║ ███╗█████╗
|
|
15
15
|
██║ ██║██╔══██║██╔══██╗██╔═██╗ ██╔══██╗██╔══██║██║╚██╗██║██║ ██║██╔══╝
|
|
16
16
|
██████╔╝██║ ██║██║ ██║██║ ██╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗
|
|
17
|
-
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
|
|
17
|
+
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
|
|
18
|
+
LLM Benchmark developed by DarkRange Team"""
|
|
18
19
|
|
|
19
20
|
RED = "\033[38;5;196m"
|
|
20
21
|
RST = "\033[0m"
|
|
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
import glob
|
|
9
9
|
import json
|
|
10
10
|
import os
|
|
11
|
+
import random
|
|
11
12
|
from dataclasses import dataclass, field
|
|
12
13
|
|
|
13
14
|
|
|
@@ -72,3 +73,15 @@ def smoke_subset(tasks, per_criterion=2):
|
|
|
72
73
|
for _, ts in by.items():
|
|
73
74
|
out.extend(ts[:per_criterion])
|
|
74
75
|
return out
|
|
76
|
+
|
|
77
|
+
def random_subset(tasks, per_criterion=15):
|
|
78
|
+
"""A random N tasks of each criterion, preserving criterion order."""
|
|
79
|
+
from collections import OrderedDict
|
|
80
|
+
by = OrderedDict()
|
|
81
|
+
for t in tasks:
|
|
82
|
+
by.setdefault(t.criterion, []).append(t)
|
|
83
|
+
out = []
|
|
84
|
+
for _, ts in by.items():
|
|
85
|
+
sampled = random.sample(ts, min(len(ts), per_criterion))
|
|
86
|
+
out.extend(sampled)
|
|
87
|
+
return out
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|