virex-bench 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.
Files changed (140) hide show
  1. virex_bench-0.1.2/.agents/skills/simplify/SKILL.md +75 -0
  2. virex_bench-0.1.2/.editorconfig +31 -0
  3. virex_bench-0.1.2/.gitattributes +3 -0
  4. virex_bench-0.1.2/.github/workflows/check_imports.py +51 -0
  5. virex_bench-0.1.2/.github/workflows/lint-and-test.yml +68 -0
  6. virex_bench-0.1.2/.github/workflows/release.yml +71 -0
  7. virex_bench-0.1.2/.gitignore +66 -0
  8. virex_bench-0.1.2/.ignore +4 -0
  9. virex_bench-0.1.2/.python-version +1 -0
  10. virex_bench-0.1.2/AGENTS.md +169 -0
  11. virex_bench-0.1.2/CLAUDE.md +1 -0
  12. virex_bench-0.1.2/LICENSE +674 -0
  13. virex_bench-0.1.2/PKG-INFO +197 -0
  14. virex_bench-0.1.2/README.md +163 -0
  15. virex_bench-0.1.2/docs/ENVIRONMENT_VARIABLES.md +111 -0
  16. virex_bench-0.1.2/docs/assets/virex_bench_logo.png +0 -0
  17. virex_bench-0.1.2/pyproject.toml +189 -0
  18. virex_bench-0.1.2/pyrightconfig.json +35 -0
  19. virex_bench-0.1.2/scripts/eval/run_eval_gemma_4_26b_a4b_it.sh +53 -0
  20. virex_bench-0.1.2/scripts/eval/run_eval_gemma_4_31b_it.sh +53 -0
  21. virex_bench-0.1.2/scripts/eval/run_eval_nvidia_nemotron_3_nano_30b_a3b_bf16.sh +53 -0
  22. virex_bench-0.1.2/scripts/eval/run_eval_nvidia_nemotron_3_nano_4b_bf16.sh +53 -0
  23. virex_bench-0.1.2/scripts/eval/run_eval_nvidia_nemotron_3_super_120b_a12b_fp8.sh +53 -0
  24. virex_bench-0.1.2/scripts/eval/run_eval_phi_4_mini_reasoning.sh +53 -0
  25. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_5_122b_a10b_fp8.sh +53 -0
  26. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_5_27b.sh +53 -0
  27. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_5_35b_a3b.sh +53 -0
  28. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_5_9b.sh +53 -0
  29. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_6_27b.sh +53 -0
  30. virex_bench-0.1.2/scripts/eval/run_eval_qwen3_6_35b_a3b.sh +53 -0
  31. virex_bench-0.1.2/scripts/run_translate_dataset_translategemma.py +401 -0
  32. virex_bench-0.1.2/scripts/run_translate_dataset_translategemma.sh +26 -0
  33. virex_bench-0.1.2/scripts/serving/README.md +41 -0
  34. virex_bench-0.1.2/scripts/serving/run_sglang_gemma_4_e2b_it.sh +64 -0
  35. virex_bench-0.1.2/scripts/serving/run_sglang_ornith_1_0_9b.sh +43 -0
  36. virex_bench-0.1.2/scripts/serving/run_sglang_phi_4_mini_reasoning.sh +40 -0
  37. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_4b.sh +66 -0
  38. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_5_122b_a10b_fp8.sh +85 -0
  39. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_5_27b.sh +73 -0
  40. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_5_35b_a3b.sh +73 -0
  41. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_5_4b.sh +79 -0
  42. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_5_9b.sh +73 -0
  43. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_6_27b.sh +73 -0
  44. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_6_35b_a3b.sh +73 -0
  45. virex_bench-0.1.2/scripts/serving/run_sglang_qwen3_8b.sh +66 -0
  46. virex_bench-0.1.2/scripts/serving/run_vllm_gemma_4_12b_it.sh +51 -0
  47. virex_bench-0.1.2/scripts/serving/run_vllm_gemma_4_26b_a4b_it.sh +51 -0
  48. virex_bench-0.1.2/scripts/serving/run_vllm_gemma_4_31b_it.sh +51 -0
  49. virex_bench-0.1.2/scripts/serving/run_vllm_gemma_4_e2b_it.sh +49 -0
  50. virex_bench-0.1.2/scripts/serving/run_vllm_gemma_4_e4b_it.sh +49 -0
  51. virex_bench-0.1.2/scripts/serving/run_vllm_lfm2_5_8b_a1b.sh +39 -0
  52. virex_bench-0.1.2/scripts/serving/run_vllm_nvidia_nemotron_3_nano_30b_a3b_bf16.sh +39 -0
  53. virex_bench-0.1.2/scripts/serving/run_vllm_nvidia_nemotron_3_nano_4b_bf16.sh +39 -0
  54. virex_bench-0.1.2/scripts/serving/run_vllm_nvidia_nemotron_3_super_120b_a12b_fp8.sh +54 -0
  55. virex_bench-0.1.2/scripts/serving/run_vllm_ornith_1_0_9b.sh +37 -0
  56. virex_bench-0.1.2/scripts/serving/run_vllm_phi_4_mini_reasoning.sh +35 -0
  57. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_4b.sh +49 -0
  58. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_5_27b.sh +51 -0
  59. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_5_35b_a3b.sh +51 -0
  60. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_5_4b.sh +57 -0
  61. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_5_9b.sh +51 -0
  62. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_6_27b.sh +51 -0
  63. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_6_35b_a3b.sh +51 -0
  64. virex_bench-0.1.2/scripts/serving/run_vllm_qwen3_8b.sh +49 -0
  65. virex_bench-0.1.2/tests/cli/test_build_cli.py +97 -0
  66. virex_bench-0.1.2/tests/decoding/test_self_consistency.py +340 -0
  67. virex_bench-0.1.2/tests/evaluation/test_evaluate.py +535 -0
  68. virex_bench-0.1.2/tests/evaluation/test_judge.py +415 -0
  69. virex_bench-0.1.2/tests/evaluation/test_metrics.py +329 -0
  70. virex_bench-0.1.2/tests/models/__init__.py +0 -0
  71. virex_bench-0.1.2/tests/models/test_backends.py +28 -0
  72. virex_bench-0.1.2/tests/models/test_base.py +107 -0
  73. virex_bench-0.1.2/tests/strategies/cr/__init__.py +0 -0
  74. virex_bench-0.1.2/tests/strategies/cr/test_common.py +165 -0
  75. virex_bench-0.1.2/tests/strategies/cr/test_config.py +145 -0
  76. virex_bench-0.1.2/tests/strategies/cr/test_strategy.py +989 -0
  77. virex_bench-0.1.2/tests/strategies/pot/__init__.py +0 -0
  78. virex_bench-0.1.2/tests/strategies/pot/test_common.py +319 -0
  79. virex_bench-0.1.2/tests/strategies/pot/test_config.py +117 -0
  80. virex_bench-0.1.2/tests/strategies/pot/test_interpreter.py +635 -0
  81. virex_bench-0.1.2/tests/strategies/pot/test_strategy.py +634 -0
  82. virex_bench-0.1.2/tests/strategies/test_registry.py +161 -0
  83. virex_bench-0.1.2/tests/strategies/tot/test_beam_search.py +414 -0
  84. virex_bench-0.1.2/tests/strategies/tot/test_common.py +79 -0
  85. virex_bench-0.1.2/tests/strategies/tot/test_config.py +418 -0
  86. virex_bench-0.1.2/tests/strategies/tot/test_dfs_search.py +389 -0
  87. virex_bench-0.1.2/tests/strategies/tot/test_mcts_search.py +435 -0
  88. virex_bench-0.1.2/tests/strategies/tot/test_stats_plumbing.py +275 -0
  89. virex_bench-0.1.2/tests/tasks/__init__.py +0 -0
  90. virex_bench-0.1.2/tests/tasks/test_base.py +171 -0
  91. virex_bench-0.1.2/tests/test_logger.py +220 -0
  92. virex_bench-0.1.2/tests/test_modules.py +167 -0
  93. virex_bench-0.1.2/uv.lock +8149 -0
  94. virex_bench-0.1.2/virex_bench/__init__.py +38 -0
  95. virex_bench-0.1.2/virex_bench/__main__.py +4 -0
  96. virex_bench-0.1.2/virex_bench/cli/__init__.py +6 -0
  97. virex_bench-0.1.2/virex_bench/cli/build_cli.py +267 -0
  98. virex_bench-0.1.2/virex_bench/decoding/__init__.py +11 -0
  99. virex_bench-0.1.2/virex_bench/decoding/base.py +59 -0
  100. virex_bench-0.1.2/virex_bench/decoding/registry.py +26 -0
  101. virex_bench-0.1.2/virex_bench/decoding/self_consistency.py +450 -0
  102. virex_bench-0.1.2/virex_bench/envs.py +392 -0
  103. virex_bench-0.1.2/virex_bench/evaluation/__init__.py +34 -0
  104. virex_bench-0.1.2/virex_bench/evaluation/evaluate.py +503 -0
  105. virex_bench-0.1.2/virex_bench/evaluation/judge.py +482 -0
  106. virex_bench-0.1.2/virex_bench/evaluation/metrics.py +329 -0
  107. virex_bench-0.1.2/virex_bench/logger.py +132 -0
  108. virex_bench-0.1.2/virex_bench/models/__init__.py +27 -0
  109. virex_bench-0.1.2/virex_bench/models/backends.py +27 -0
  110. virex_bench-0.1.2/virex_bench/models/base.py +89 -0
  111. virex_bench-0.1.2/virex_bench/strategies/__init__.py +9 -0
  112. virex_bench-0.1.2/virex_bench/strategies/base.py +45 -0
  113. virex_bench-0.1.2/virex_bench/strategies/cot.py +30 -0
  114. virex_bench-0.1.2/virex_bench/strategies/cr/__init__.py +9 -0
  115. virex_bench-0.1.2/virex_bench/strategies/cr/common.py +255 -0
  116. virex_bench-0.1.2/virex_bench/strategies/cr/strategy.py +388 -0
  117. virex_bench-0.1.2/virex_bench/strategies/direct.py +25 -0
  118. virex_bench-0.1.2/virex_bench/strategies/modules.py +153 -0
  119. virex_bench-0.1.2/virex_bench/strategies/pot/__init__.py +9 -0
  120. virex_bench-0.1.2/virex_bench/strategies/pot/common.py +452 -0
  121. virex_bench-0.1.2/virex_bench/strategies/pot/interpreter.py +495 -0
  122. virex_bench-0.1.2/virex_bench/strategies/pot/strategy.py +211 -0
  123. virex_bench-0.1.2/virex_bench/strategies/registry.py +71 -0
  124. virex_bench-0.1.2/virex_bench/strategies/tot/__init__.py +9 -0
  125. virex_bench-0.1.2/virex_bench/strategies/tot/common.py +211 -0
  126. virex_bench-0.1.2/virex_bench/strategies/tot/search/__init__.py +41 -0
  127. virex_bench-0.1.2/virex_bench/strategies/tot/search/base.py +109 -0
  128. virex_bench-0.1.2/virex_bench/strategies/tot/search/beam.py +125 -0
  129. virex_bench-0.1.2/virex_bench/strategies/tot/search/dfs.py +191 -0
  130. virex_bench-0.1.2/virex_bench/strategies/tot/search/mcts.py +405 -0
  131. virex_bench-0.1.2/virex_bench/strategies/tot/strategy.py +234 -0
  132. virex_bench-0.1.2/virex_bench/tasks/__init__.py +13 -0
  133. virex_bench-0.1.2/virex_bench/tasks/base.py +140 -0
  134. virex_bench-0.1.2/virex_bench/tasks/registry.py +17 -0
  135. virex_bench-0.1.2/virex_bench/tasks/vietnamese_logical_reasoning.py +371 -0
  136. virex_bench-0.1.2/virex_bench/types/__init__.py +21 -0
  137. virex_bench-0.1.2/virex_bench/types/_metric.py +7 -0
  138. virex_bench-0.1.2/virex_bench/types/_result.py +97 -0
  139. virex_bench-0.1.2/virex_bench/types/_task.py +37 -0
  140. virex_bench-0.1.2/virex_bench/utils.py +15 -0
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: simplify
3
+ description: Review changed code for reuse, quality, and efficiency, then fix any issues found.
4
+ ---
5
+
6
+ # Simplify: Code Review and Cleanup
7
+
8
+ Review all changed files for reuse, quality, and efficiency. Fix any issues found.
9
+
10
+ ## Project Context
11
+
12
+ ViREx-Bench is a Vietnamese multi-step-reasoning benchmark built on **DSPy**, organized
13
+ around four axes — task / model / strategy / decoding — plus shared modules. See `AGENTS.md`
14
+ for the full layout. When reviewing and fixing, respect these boundaries:
15
+
16
+ - **Do not edit** files under `data/` (datasets managed externally) or `uv.lock` by hand.
17
+ - **Do not modify** generated/cached dirs: `.ruff_cache/`, `.cache/`, `_testing_results/`.
18
+ - **Never introduce** committed secrets or `.env` contents.
19
+
20
+ ## Phase 1: Identify Changes
21
+
22
+ Run `git diff` (or `git diff HEAD` if there are staged changes) to see what changed. If there are no git changes, review the most recently modified files that the user mentioned or that you edited earlier in this conversation.
23
+
24
+ Ignore directories and files starting with `_` (e.g. `_testing_results/`, `_test_format.py`) — these are local/testing files, not part of the main codebase.
25
+
26
+ ## Phase 2: Launch Three Review Agents in Parallel
27
+
28
+ Use the Agent tool to launch all three agents concurrently in a single message. Pass each agent the full diff so it has the complete context.
29
+
30
+ ### Agent 1: Code Reuse Review
31
+
32
+ For each change:
33
+
34
+ 1. **Search for existing utilities and helpers** (`rg`) that could replace newly written code. Common locations: `virex_bench/utils.py`, `logger.py`, per-package `common.py` (e.g. `strategies/cr/common.py`, `strategies/tot/common.py`), and files adjacent to the changed ones.
35
+ 2. **Flag any new function that duplicates existing functionality.** Suggest the existing function to use instead — e.g. reimplementing `premises_to_text`, ad-hoc logger setup instead of `init_logger`, or a new registry lookup that duplicates `get_task` / `get_strategy` / `get_decoding`.
36
+ 3. **Flag any inline logic that could use an existing utility** — hand-rolled string manipulation, manual `os.path` handling, direct `os.environ` reads that should go through `virex_bench/envs.py`, and similar patterns are common candidates.
37
+
38
+ ### Agent 2: Code Quality Review
39
+
40
+ Review the same changes for hacky patterns:
41
+
42
+ 1. **Redundant state**: state that duplicates existing state, cached values that could be derived
43
+ 2. **Parameter sprawl**: adding new parameters to a function instead of generalizing or restructuring existing ones; small helper methods that are referenced only once (inline them)
44
+ 3. **Copy-paste with slight variation**: near-duplicate code blocks that should be unified with a shared abstraction
45
+ 4. **Leaky abstractions**: exposing internal details that should be encapsulated, or breaking existing abstraction boundaries (e.g. bypassing the task/model/strategy/decoding registries, or reaching into a `dspy.Module`'s internals)
46
+ 5. **Stringly-typed code**: raw strings/dicts where a `pydantic.BaseModel`, enum, or string-union already exists; `dataclasses` where the codebase uses `pydantic.BaseModel`
47
+ 6. **Style mismatches**: truthy/falsy checks (`if x`) where `is None` / `is not None` is required for valid falsy values; `pathlib.Path` where the codebase uses `str` + `os.path`; short/abbreviated names (`ri`, `ip`, `el`) where verbose self-documenting names are the convention; `%`-style logging instead of f-strings; `print()` for diagnostics instead of the shared logger; `type[T]` misuse (passing an instance where a class is expected, e.g. `signature: type[dspy.Signature]`)
48
+ 7. **DSPy convention drift**: new strategies that aren't `dspy.Module` subclasses or don't follow the existing signature/module patterns in `strategies/`; signature docstrings or field descriptions written in a language other than **English** (task data stays native, but the instruction contract is English)
49
+ 8. **Unnecessary or over-verbose comments**: comments explaining WHAT the code does (well-named identifiers already do that), narrating the change, or referencing the task/caller — delete these; keep only non-obvious WHY (hidden constraints, subtle invariants, workarounds). For comments worth keeping, trim multi-line/rambling explanations down to a single concise line.
50
+
51
+ ### Agent 3: Efficiency Review
52
+
53
+ Review the same changes for efficiency:
54
+
55
+ 1. **Unnecessary work**: redundant computations, repeated file reads, duplicate LM/API calls, N+1 patterns
56
+ 2. **Missed concurrency**: independent operations run sequentially when they could run in parallel (e.g. per-example LM calls, independent propose/evaluate steps in ToT/CR)
57
+ 3. **Hot-path bloat**: new blocking work added to the per-example evaluation loop or per-LM-call path
58
+ 4. **Unnecessary existence checks**: pre-checking file/resource existence before operating (TOCTOU anti-pattern) — operate directly and handle the error
59
+ 5. **Memory**: unbounded data structures, missing cleanup (e.g. accumulating full LM transcripts across a large eval run)
60
+ 6. **Overly broad operations**: reading entire files/datasets when only a portion is needed, loading all items when filtering for one
61
+
62
+ ## Phase 3: Fix Issues
63
+
64
+ Wait for all three agents to complete. Aggregate their findings and fix each issue directly. If a finding is a false positive or not worth addressing, note it and move on — do not argue with the finding, just skip it.
65
+
66
+ After fixing, confirm the changed files still pass the project's checks:
67
+
68
+ ```bash
69
+ uv run --no-sync ruff check path/to/file.py
70
+ uv run --no-sync ruff format path/to/file.py
71
+ ```
72
+
73
+ Pyright runs in strict mode — do not introduce type errors, and only suppress with `# pyright: ignore` for genuine false positives, never to silence a legitimate error. If the change touches behavior, also run the relevant tests (`uv run --no-sync pytest tests/...`, which mirror the package layout).
74
+
75
+ When done, briefly summarize what was fixed (or confirm the code was already clean).
@@ -0,0 +1,31 @@
1
+ # https://editorconfig.org/
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 4
8
+
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
13
+
14
+ [*.md]
15
+ trim_trailing_whitespace = false
16
+
17
+ [*.py]
18
+ max_line_length = 100
19
+
20
+ [*.sh]
21
+ indent_size = 2
22
+
23
+ [*.{json,yaml,yml}]
24
+ indent_size = 2
25
+
26
+ [{Makefile,makefile}]
27
+ indent_style = tab
28
+ indent_size = 2
29
+
30
+ [*.txt]
31
+ insert_final_newline = false
@@ -0,0 +1,3 @@
1
+ * text=auto eol=lf
2
+ *.ipynb linguist-generated
3
+ pyrightconfig.json linguist-language=jsonc
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import argparse
4
+ import importlib.util
5
+ import pathlib
6
+ import sys
7
+
8
+
9
+ def check_imports(args: argparse.Namespace) -> None:
10
+ src_path = pathlib.Path(args.src_path)
11
+ num_files = 0
12
+ for pyfile in src_path.rglob("*.py"):
13
+ print("Trying to import", pyfile)
14
+ module_name = pyfile.with_suffix("").as_posix().replace("/", ".")
15
+ spec = importlib.util.spec_from_file_location(
16
+ name=module_name,
17
+ location=pyfile,
18
+ )
19
+ if spec is None:
20
+ print(f"Failed to load {pyfile}", file=sys.stderr)
21
+ raise SystemExit(1)
22
+
23
+ assert spec.loader is not None
24
+ module = importlib.util.module_from_spec(spec)
25
+ try:
26
+ spec.loader.exec_module(module)
27
+ num_files += 1
28
+ except Exception as err:
29
+ print(f"Error importing {module_name}: {err}", file=sys.stderr)
30
+ raise SystemExit(1) from err
31
+
32
+ print(f"All {num_files} imports checked successfully.")
33
+
34
+
35
+ def main() -> None:
36
+ parser = argparse.ArgumentParser(
37
+ description="Check imports in Python files",
38
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
39
+ )
40
+ parser.add_argument(
41
+ "--src_path",
42
+ type=str,
43
+ help="Path to the source directory",
44
+ default="src",
45
+ )
46
+ args = parser.parse_args()
47
+ check_imports(args)
48
+
49
+
50
+ if __name__ == "__main__":
51
+ main()
@@ -0,0 +1,68 @@
1
+ name: Lint and Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ pull_request:
7
+ branches: [main, dev]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ check-imports:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.12"]
16
+ steps:
17
+ - name: Clone the repository
18
+ uses: actions/checkout@v7
19
+ - name: Install the latest version of uv and set the python version
20
+ uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
21
+ with:
22
+ version: ">=0.9.21"
23
+ python-version: ${{ matrix.python-version }}
24
+ enable-cache: true
25
+ - name: Check imports
26
+ run: |
27
+ export PYTHONPATH="${{ github.workspace }}"
28
+ uv run --frozen python .github/workflows/check_imports.py --src_path virex_bench
29
+
30
+ lint-with-ruff:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - name: Clone the repository
34
+ uses: actions/checkout@v7
35
+
36
+ - name: Install the latest version of uv and set the python version
37
+ uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
38
+ with:
39
+ version: ">=0.9.21"
40
+ enable-cache: true
41
+
42
+ - name: Lint with ruff
43
+ run: |
44
+ uv run --frozen ruff check --output-format=github virex_bench tests scripts
45
+
46
+ - name: Check formatting with ruff
47
+ run: |
48
+ uv run --frozen ruff format --check --output-format=github virex_bench tests scripts
49
+
50
+ test-with-pytest:
51
+ runs-on: ubuntu-latest
52
+ strategy:
53
+ matrix:
54
+ python-version: ["3.12", "3.13", "3.14"]
55
+ steps:
56
+ - name: Clone the repository
57
+ uses: actions/checkout@v7
58
+
59
+ - name: Install the latest version of uv and set the python version
60
+ uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
61
+ with:
62
+ version: ">=0.9.21"
63
+ python-version: ${{ matrix.python-version }}
64
+ enable-cache: true
65
+
66
+ - name: Run tests with pytest
67
+ run: |
68
+ uv run --frozen pytest tests -v
@@ -0,0 +1,71 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions: {}
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Clone the repository
14
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
15
+ with:
16
+ # hatch-vcs derives the version from git tags, so full history is required.
17
+ fetch-depth: 0
18
+
19
+ - name: Install the latest version of uv
20
+ uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
21
+ with:
22
+ version: ">=0.9.21"
23
+ enable-cache: true
24
+
25
+ - name: Build sdist and wheel
26
+ run: uv build
27
+
28
+ - name: Check distribution metadata
29
+ run: uvx twine check dist/*
30
+
31
+ - name: Upload distribution artifacts
32
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+
37
+ publish-testpypi:
38
+ needs: build
39
+ if: github.event.release.prerelease == true
40
+ runs-on: ubuntu-latest
41
+ environment: testpypi
42
+ permissions:
43
+ id-token: write
44
+ steps:
45
+ - name: Download distribution artifacts
46
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+
51
+ - name: Publish to TestPyPI
52
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
53
+ with:
54
+ repository-url: https://test.pypi.org/legacy/
55
+
56
+ publish-pypi:
57
+ needs: build
58
+ if: github.event.release.prerelease == false
59
+ runs-on: ubuntu-latest
60
+ environment: pypi
61
+ permissions:
62
+ id-token: write
63
+ steps:
64
+ - name: Download distribution artifacts
65
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
66
+ with:
67
+ name: dist
68
+ path: dist/
69
+
70
+ - name: Publish to PyPI
71
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
@@ -0,0 +1,66 @@
1
+ # python stuff
2
+ __pycache__
3
+ .ipynb_checkpoints
4
+
5
+ # virtual environments
6
+ .venv
7
+ .venv.*
8
+ .venv-*
9
+
10
+ # env
11
+ .env
12
+ .env.*
13
+
14
+ # unit test / coverage reports
15
+ htmlcov/
16
+ .tox/
17
+ .nox/
18
+ .coverage
19
+ .coverage.*
20
+ .cache
21
+ .tmp/
22
+ nosetests.xml
23
+ coverage.xml
24
+ *.cover
25
+ *.py,cover
26
+ .hypothesis/
27
+ .pytest_cache/
28
+ cover/
29
+
30
+ # local stuff
31
+ _*
32
+ !__*__.py
33
+ !/virex_bench/types/_*
34
+ /checkpoints
35
+ *.local
36
+ # /.plans
37
+ /.code-review
38
+ /results
39
+ /slides
40
+ /notebooks
41
+ /tmp/
42
+ /report/
43
+ /.bashrc
44
+ /final_results/
45
+
46
+ # datasets
47
+ /data
48
+
49
+ # log files
50
+ *.log
51
+ *.logs
52
+
53
+ # cache
54
+ .pytest_cache
55
+ .ruff_cache
56
+
57
+ # shell scripts
58
+ s.sh
59
+
60
+ # other
61
+ *.bak
62
+ *.backup
63
+ /*.pdf
64
+ /*.json
65
+ !/pyrightconfig.json
66
+ /refs
@@ -0,0 +1,4 @@
1
+ # logs file
2
+ !*.log
3
+ !/logs/
4
+ !/log
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,169 @@
1
+ # AGENTS.md
2
+
3
+ ## Project
4
+
5
+ **ViREx-Bench** (Vietnamese Reasoning Exploration Benchmark) is a lightweight framework
6
+ for exploring **multi-step reasoning of LLMs for Vietnamese**.
7
+
8
+ The project has two expected outputs:
9
+
10
+ 1. **A Vietnamese logical-reasoning dataset** — each row contains a set of *premises* and a
11
+ *question* (with a gold answer), framing logical-reasoning problems in Vietnamese.
12
+ 2. **An evaluation framework** that measures how much each inference-time reasoning strategy
13
+ improves over a direct-answer baseline on that dataset.
14
+
15
+ The framework targets two orthogonal research axes (planned scope listed; see each
16
+ registry for what is currently implemented):
17
+
18
+ - **Prompting / inference-time scaling** (`strategies/`): Chain-of-Thought (CoT),
19
+ Tree-of-Thought (ToT) with pluggable search (beam, DFS, MCTS), Cumulative Reasoning
20
+ (CR), Self-Consistency, and Program-of-Thought with symbolic reasoning (Z3 solver).
21
+ *Implemented: direct baseline, CoT, CR, ToT (beam + DFS + MCTS search).*
22
+ - **Decoding** (`decoding/`): the baseline (single candidate, or multiple candidates
23
+ aggregated by majority vote), Best-of-N with a verifier, and speculative decoding to
24
+ speed up inference. *Implemented: single-pass baseline, self-consistency (N-sample
25
+ majority vote + LLM aggregation).*
26
+
27
+ **DSPy** is the main framework for implementing reasoning strategies. The CLI design is
28
+ modeled on [`mteb`](https://github.com/embeddings-benchmark/mteb) — a CLI is sufficient
29
+ (no web/leaderboard UI or serving layer).
30
+
31
+ ## Commands
32
+
33
+ Always prefix Python/tool commands with `uv run --no-sync`, omit the `--no-sync` flag only when you actually needed to avoid syncing packages everytime (which take times).
34
+
35
+ ```bash
36
+ # Lint
37
+ uv run --no-sync ruff check
38
+
39
+ # Format
40
+ uv run --no-sync ruff format
41
+
42
+ # Run the benchmark CLI (task × model × strategy × decoding)
43
+ # Models are served behind an OpenAI-compatible endpoint (no local loading).
44
+ uv run virex-bench run \
45
+ --model Qwen/Qwen3.5 \
46
+ --task vietnamese-logical-reasoning \
47
+ --strategy cot \
48
+ --backend openai \
49
+ --api-base http://localhost:8000/v1 \
50
+ --output-dir results
51
+
52
+ # `vb` is a shorter alias for `virex-bench`
53
+ uv run vb run --model Qwen/Qwen3.5 --strategy cot
54
+
55
+ # Inspect available tasks / strategies
56
+ uv run virex-bench tasks --list
57
+ uv run virex-bench strategies --list
58
+ ```
59
+
60
+ ### File-scoped fast feedback
61
+
62
+ ```bash
63
+ uv run --no-sync ruff check path/to/file.py
64
+ uv run --no-sync ruff format path/to/file.py
65
+ ```
66
+
67
+ ## Project Structure
68
+
69
+ The package is organized around four axes — **task** (dataset), **model** (backend),
70
+ **strategy** (prompting), and **decoding** (aggregation) — wired together by the
71
+ evaluation orchestrator. Layout is inspired by `mteb` (task × model registries + a thin
72
+ CLI), with two extra axes for reasoning and decoding.
73
+
74
+ ```
75
+ virex_bench/
76
+ ├── cli/ # argparse CLI: `virex-bench run | tasks | strategies`
77
+ │ └── build_cli.py # build_parser / main + subcommand handlers
78
+ ├── envs.py # centralized, lazily-read environment variables (vLLM-style)
79
+ ├── logger.py # init_logger(__name__) — shared logging setup
80
+ ├── utils.py # shared helpers (premises_to_text — numbered premise block)
81
+ ├── types/ # pydantic data models + type aliases (mirrors mteb/types)
82
+ │ ├── __init__.py # re-exports all public types
83
+ │ ├── _task.py # ReasoningExample, DatasetConfig, TaskMetadata
84
+ │ ├── _result.py # TaskResult, EvaluationReport, JudgeOutcome
85
+ │ └── _metric.py # ReasoningMetric callable alias
86
+ ├── tasks/ # reasoning datasets + registry
87
+ │ ├── base.py # ReasoningTask base class
88
+ │ ├── registry.py # get_task / list_tasks
89
+ │ └── vietnamese_logical_reasoning.py
90
+ ├── models/ # LM layer — OpenAI-compatible endpoints via dspy.LM
91
+ │ ├── __init__.py # get_model
92
+ │ ├── base.py # BaseLM(dspy.LM) wrapper
93
+ │ └── backends.py # load_backend: build a BaseLM for an OpenAI-compatible endpoint
94
+ ├── strategies/ # PROMPTING / inference-time scaling (dspy.Module subclasses)
95
+ │ ├── base.py # ReasoningStrategy base class (+ accepts_variant flag)
96
+ │ ├── registry.py # get_strategy / list_strategies + composite-name parsing (direct, cot, cr, tot[-beam|-dfs|-mcts])
97
+ │ ├── direct.py # baseline: direct answer
98
+ │ ├── cot.py # Chain-of-Thought
99
+ │ ├── modules.py # reusable dspy modules: ChainOfThought, DualTask2ChainOfThought, ThinkingCaptureLM
100
+ │ ├── cr/ # Cumulative Reasoning strategy package (Zhang et al., 2023)
101
+ │ │ ├── strategy.py # CRStrategy — propose/verify accumulation loop + solver
102
+ │ │ └── common.py # shared signatures + helpers (proposer/verifiers, CRConfig, verdict buckets)
103
+ │ └── tot/ # Tree-of-Thoughts strategy package (Yao et al., 2023)
104
+ │ ├── strategy.py # ToTStrategy — propose/evaluate/aggregate over a thought tree
105
+ │ ├── common.py # shared signatures + helpers (proposer/evaluator, scoring, dedupe)
106
+ │ └── search/ # pluggable search algorithms (beam, DFS, MCTS)
107
+ │ ├── __init__.py # search registry: build_search / list_search
108
+ │ ├── base.py # SearchConfig, SearchResult, ThoughtSearch ABC
109
+ │ ├── beam.py # BeamSearch (ToT's BFS)
110
+ │ ├── dfs.py # DFSSearch (backtracking + value pruning)
111
+ │ └── mcts.py # MCTSSearch (Monte-Carlo Tree Search)
112
+ ├── decoding/ # DECODING / answer aggregation
113
+ │ ├── base.py # DecodingStrategy base + SinglePass (single-candidate baseline)
114
+ │ ├── registry.py # get_decoding / list_decoding
115
+ │ └── self_consistency.py # SelfConsistency: N-sample majority vote + LLM aggregation
116
+ ├── evaluation/ # orchestration + scoring + LLM-as-a-judge
117
+ │ ├── evaluate.py # task × model × strategy loop + report serialization (save_report)
118
+ │ ├── metrics.py # accuracy metrics + METRIC_REGISTRY / get_metric / judge_example
119
+ │ └── judge.py # LLMJudge base, LogicalReasoningJudge, JUDGE_REGISTRY / build_judge
120
+ └── __main__.py # `python -m virex_bench` entry point -> cli.main
121
+
122
+ data/ # datasets (managed externally — do not edit by hand)
123
+ notebooks/ # dataset-prep notebooks (e.g. eval-round → HF dataset conversion)
124
+ scripts/ # dataset translation helpers + model-serving launchers (serving/)
125
+ tests/ # pytest suite — mirrors the package layout (cli / evaluation / strategies [+ cr, tot])
126
+ results/ # benchmark run outputs
127
+ ```
128
+
129
+ ## Development and Code Style
130
+
131
+ ### Development Guide
132
+
133
+ - **Python 3.12** — use modern syntax (`str | None`, `list[int]`, etc.)
134
+ - **Git**: Do not try to use `git checkout <file>` to discard or revert changes as you might cause loose uncommitted work.
135
+ - **Formatter**: Ruff (`uv run --no-sync ruff format`) — double quotes, 4-space indent, LF endings, line length 99
136
+ - **Linter**: Ruff (`uv run --no-sync ruff check`) — rules: B, C, E, F, I, W, RUF013, UP006
137
+ - **Type checker**: Pyright in strict mode. Use `# pyright: ignore` to suppress false positive or workaround some limitation in the type checker. DO NOT silence legitimate type errors.
138
+ - **Testing**: pytest (`uv run --no-sync pytest`)
139
+ - **Imports**: sorted by Ruff (isort rules), grouped: stdlib → third-party → local
140
+ - **DSPy**: Reasoning strategies are implemented as `dspy.Module` subclasses under `strategies/`. Follow the existing patterns there for signatures and modules. Write signature docstrings and field descriptions in **English** (the instruction language), even for Vietnamese tasks — the target models are multilingual, and English instructions keep the prompt contract consistent across tasks. The task data (premises/questions/answers) stays in its native language.
141
+ - **Grepping**: Prefer using `rg` (ripgrep) over `grep` for speed and better defaults.
142
+
143
+ ### Code Style
144
+
145
+ - **Pydantic**: Use `pydantic.BaseModel` for data models (examples, configs, results, reports) — not `dataclasses`. Serialize with `model_dump()` / `model_dump_json()`.
146
+ - **Logging**: Use the shared logger — `from virex_bench.logger import init_logger` then `logger = init_logger(__name__)` at module top. Prefer f-strings in logging calls over `%`-style logger formatting. Do not call `print()` for diagnostics or configure `logging` directly (CLI user-facing output via `print` is fine).
147
+ - **Env vars**: All environment variables go through `virex_bench/envs.py` — never read `os.environ` directly elsewhere. Add a typed declaration in the `TYPE_CHECKING` block and a lazy `lambda` entry in `environment_variables`, then access via `from virex_bench import envs` / `envs.VAR_NAME`. Access is lazy (read at use time, not import time), so set vars before first access.
148
+ - **CLI**: `argparse`-based subcommands (`run`, `tasks`, `strategies`), modeled on `mteb`. Both `virex-bench` and the short alias `vb` map to `cli:main`. Keep command handlers thin — delegate to `evaluation/`, `tasks/`, `models/`.
149
+ - **File path:** Use raw `str` for file paths and `os.path` for path manipulations. Avoid `pathlib.Path` to keep things simple and consistent across the codebase.
150
+ - **Variable names:** Use verbose, self-documenting names. Avoid short abbreviations (e.g., `ri`, `ip`, `ua`, `ui`, `el`, `t`) — prefer `request_metadata`, `client_ip`, `client_user_agent`, `elapsed`, etc. Single-letter names are only acceptable as loop indices or in very narrow local scopes (e.g., list comprehensions).
151
+ - **None check:** Use `if x is None` and `if x is not None` for checking if a variable is `None`. Avoid truthy/falsy checks like `if x` or `if not x` when the variable can have valid falsy values (e.g., empty string, zero, empty list).
152
+ - **`type[T]` hints:** Use `type[T]` when a function/field expects a *class* (to instantiate or inspect later), not an instance — e.g. `signature: type[dspy.Signature]` and registries like `dict[str, type[ReasoningStrategy]]`. Pass the class itself (`DirectStrategy`), not an instance (`DirectStrategy()`).
153
+ - **Comments:** Do not add decorative separator/banner comments — no `# --- text ---`, `# =====`, or full-line `# ---------` dividers between sections. If a section genuinely needs a title, use a plain `# Title` comment (no surrounding dashes/equal signs); otherwise rely on PEP 8's two blank lines between top-level definitions. Only add comments to explain non-obvious logic — never to delimit regions.
154
+ - Do not create small helper methods that are referenced only once.
155
+
156
+ ## Code review
157
+
158
+ When asked for reviewing changes, focus on:
159
+ - Potential bugs introduced by the change
160
+ - Check for behavior mismatches for refactoring changes
161
+ - Code quality and readability (style, structure, naming, etc should match the existing codebase and be clear)
162
+ - Ignore directories and files starting with `_` (e.g., `_testing_results/`, `_test_format.py`) as they are testing or local files and not part of the main codebase.
163
+
164
+ ## Boundaries
165
+
166
+ - **Never commit** `.env` files or API keys/secrets
167
+ - **Do not edit** files under `data/` directly — datasets are managed externally
168
+ - **Do not modify** generated/cached directories: `.ruff_cache/`, `.cache/`, `_testing_results/`
169
+ - **Do not touch** `uv.lock` by hand
@@ -0,0 +1 @@
1
+ AGENTS.md