interp-engine 1.13.2__tar.gz → 1.14.0__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 (224) hide show
  1. {interp_engine-1.13.2 → interp_engine-1.14.0}/PKG-INFO +1 -1
  2. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/INTERNALS.md +6 -0
  3. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_backend.py +38 -1
  4. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_plugin.py +2 -0
  5. interp_engine-1.14.0/interp_engine/vllm_seq_fit.py +85 -0
  6. {interp_engine-1.13.2 → interp_engine-1.14.0}/pyproject.toml +1 -1
  7. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_set.py +2 -1
  8. interp_engine-1.14.0/tests/test_vllm_seq_fit.py +191 -0
  9. {interp_engine-1.13.2 → interp_engine-1.14.0}/.gitignore +0 -0
  10. {interp_engine-1.13.2 → interp_engine-1.14.0}/LICENSE +0 -0
  11. {interp_engine-1.13.2 → interp_engine-1.14.0}/README.md +0 -0
  12. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/README.md +0 -0
  13. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/__init__.py +0 -0
  14. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/bench_spec.py +0 -0
  15. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/cells.py +0 -0
  16. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/probe.py +0 -0
  17. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/probe_lens_stream.py +0 -0
  18. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/publish.py +0 -0
  19. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/report_bench.py +0 -0
  20. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/deepseek-v4-flash-0731__eager.json +0 -0
  21. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/deepseek-v4-flash-0731__vllm-cudagraph.json +0 -0
  22. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/deepseek-v4-flash-0731__vllm-static.json +0 -0
  23. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/deepseek-v4-flash-0731__vllm.json +0 -0
  24. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/gemma-2-2b__eager.json +0 -0
  25. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/gemma-2-2b__vllm-cudagraph.json +0 -0
  26. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/gemma-2-2b__vllm-static.json +0 -0
  27. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/gemma-2-2b__vllm.json +0 -0
  28. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/llama-3.1-8b__eager.json +0 -0
  29. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/llama-3.1-8b__vllm-cudagraph.json +0 -0
  30. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/llama-3.1-8b__vllm-static.json +0 -0
  31. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/llama-3.1-8b__vllm.json +0 -0
  32. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3-4b__eager.json +0 -0
  33. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3-4b__vllm-cudagraph.json +0 -0
  34. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3-4b__vllm-static.json +0 -0
  35. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3-4b__vllm.json +0 -0
  36. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3.8-27b__eager.json +0 -0
  37. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3.8-27b__vllm-cudagraph.json +0 -0
  38. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3.8-27b__vllm-static.json +0 -0
  39. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results/qwen3.8-27b__vllm.json +0 -0
  40. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/results-latest.md +0 -0
  41. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/run_all.sh +0 -0
  42. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/run_bench.py +0 -0
  43. {interp_engine-1.13.2 → interp_engine-1.14.0}/benchmarks/workloads.py +0 -0
  44. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/AGENT_INTEGRATION.md +0 -0
  45. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/ARCHITECTURE_QUIRKS.md +0 -0
  46. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/COMPATIBILITY.md +0 -0
  47. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/ENGINE_HOOK_MAPPINGS.md +0 -0
  48. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/GRADIENTS.md +0 -0
  49. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/PERFORMANCE.md +0 -0
  50. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/PORTING.md +0 -0
  51. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/README.md +0 -0
  52. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/SUPPORTED_POINTS.md +0 -0
  53. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/USAGE.md +0 -0
  54. {interp_engine-1.13.2 → interp_engine-1.14.0}/docs/VALIDATING_A_NEW_MODEL.md +0 -0
  55. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/__init__.py +0 -0
  56. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/_conformance.py +0 -0
  57. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/_loop.py +0 -0
  58. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/address.py +0 -0
  59. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/api.py +0 -0
  60. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/arch.py +0 -0
  61. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/attn_config.py +0 -0
  62. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/attn_scores.py +0 -0
  63. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/autograd_support.py +0 -0
  64. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/capture.py +0 -0
  65. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/chat_compose.py +0 -0
  66. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/chat_conventions.py +0 -0
  67. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/chat_formatters.py +0 -0
  68. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/cuda_preflight.py +0 -0
  69. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/describe.py +0 -0
  70. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/directions.py +0 -0
  71. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/dispatch.py +0 -0
  72. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/facts.py +0 -0
  73. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/hooks.py +0 -0
  74. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/lens.py +0 -0
  75. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/lens_stream.py +0 -0
  76. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/lens_topk.py +0 -0
  77. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/load.py +0 -0
  78. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/mappers.py +0 -0
  79. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/memory.py +0 -0
  80. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/model.py +0 -0
  81. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/moe_routing.py +0 -0
  82. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/notebook_stdout.py +0 -0
  83. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/oracle.py +0 -0
  84. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/points.py +0 -0
  85. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/protocol.py +0 -0
  86. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/residual_basis.py +0 -0
  87. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/sampling.py +0 -0
  88. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/select.py +0 -0
  89. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/__init__.py +0 -0
  90. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/__main__.py +0 -0
  91. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/app.py +0 -0
  92. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/config.py +0 -0
  93. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/lens.py +0 -0
  94. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/runner.py +0 -0
  95. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/server/schemas.py +0 -0
  96. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/steer.py +0 -0
  97. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/steer_specs.py +0 -0
  98. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/sync.py +0 -0
  99. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/tokenize.py +0 -0
  100. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/__init__.py +0 -0
  101. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/_demux.py +0 -0
  102. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/_hooks.py +0 -0
  103. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/_payload.py +0 -0
  104. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/_tp.py +0 -0
  105. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/_tree.py +0 -0
  106. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/attn.py +0 -0
  107. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/capture.py +0 -0
  108. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/graphs.py +0 -0
  109. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/lens/__init__.py +0 -0
  110. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/lens/intervene.py +0 -0
  111. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/lens/readout.py +0 -0
  112. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/lens/unembed.py +0 -0
  113. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/mhc.py +0 -0
  114. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/native.py +0 -0
  115. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/project.py +0 -0
  116. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/requests.py +0 -0
  117. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/static.py +0 -0
  118. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/static_program.py +0 -0
  119. {interp_engine-1.13.2 → interp_engine-1.14.0}/interp_engine/vllm_capture/steering.py +0 -0
  120. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/conftest.py +0 -0
  121. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/harness.py +0 -0
  122. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/model_expectations.yaml +0 -0
  123. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/synthetic_families.py +0 -0
  124. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_address.py +0 -0
  125. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_api_fixtures.py +0 -0
  126. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_api_generated.py +0 -0
  127. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_attn_config_tripwire.py +0 -0
  128. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_attn_probs_indexing.py +0 -0
  129. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_attn_scores.py +0 -0
  130. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_attn_z_gqa.py +0 -0
  131. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_autograd_support.py +0 -0
  132. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_bench_workloads.py +0 -0
  133. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_capability_refusals.py +0 -0
  134. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_capture_addressing.py +0 -0
  135. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_chat_compose.py +0 -0
  136. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_chat_formatters.py +0 -0
  137. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_chat_templates.py +0 -0
  138. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_core.py +0 -0
  139. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_cuda_preflight.py +0 -0
  140. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_describe.py +0 -0
  141. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_directions.py +0 -0
  142. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_doc_code_fences.py +0 -0
  143. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_eager_autograd.py +0 -0
  144. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_facts.py +0 -0
  145. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_family_points.py +0 -0
  146. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_gated_attn_out.py +0 -0
  147. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_gpu_sizer.py +0 -0
  148. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_head_contributions.py +0 -0
  149. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_hook_call_conventions.py +0 -0
  150. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_injected_system_spans.py +0 -0
  151. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_layer_kinds.py +0 -0
  152. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_lens_stream.py +0 -0
  153. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_lens_stream_pairing.py +0 -0
  154. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_load.py +0 -0
  155. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_logit_transform.py +0 -0
  156. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_mappers.py +0 -0
  157. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_memory.py +0 -0
  158. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_mlp_internals.py +0 -0
  159. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_model_expectations.py +0 -0
  160. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_moe.py +0 -0
  161. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_multigpu.py +0 -0
  162. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_multimodal_arch.py +0 -0
  163. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_new_models_gpu.py +0 -0
  164. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_no_chat_template.py +0 -0
  165. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_normalized_hook.py +0 -0
  166. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_notebook_stdout.py +0 -0
  167. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_oracle.py +0 -0
  168. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_packaging.py +0 -0
  169. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_padded_positions.py +0 -0
  170. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_parity_gpt2.py +0 -0
  171. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_per_layer_attn_dims.py +0 -0
  172. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_point_capability.py +0 -0
  173. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_points_registry.py +0 -0
  174. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_protocol.py +0 -0
  175. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_published_benchmarks.py +0 -0
  176. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_qk_norm.py +0 -0
  177. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_qkv_layout.py +0 -0
  178. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_reasoning_spans.py +0 -0
  179. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_release.py +0 -0
  180. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_resid_mid.py +0 -0
  181. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_residual_basis.py +0 -0
  182. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sample_from_embeds.py +0 -0
  183. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sampling.py +0 -0
  184. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sandwich_norms.py +0 -0
  185. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_select.py +0 -0
  186. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_server.py +0 -0
  187. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sliding_window_attn.py +0 -0
  188. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_small_models_gpu.py +0 -0
  189. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_decode_writes_gpu.py +0 -0
  190. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_dsv4_gpu.py +0 -0
  191. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_parity_gpu.py +0 -0
  192. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_program.py +0 -0
  193. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_program_gpu.py +0 -0
  194. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_static_warmup.py +0 -0
  195. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_context.py +0 -0
  196. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_math_parity.py +0 -0
  197. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_ops_per_site_gpu.py +0 -0
  198. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_reaches_generate.py +0 -0
  199. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_scope.py +0 -0
  200. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_specs.py +0 -0
  201. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_steer_stream_stack.py +0 -0
  202. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sync_loop.py +0 -0
  203. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_sync_parity.py +0 -0
  204. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_unified_free_functions.py +0 -0
  205. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_unresolved_families.py +0 -0
  206. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_userless_prefix_spans.py +0 -0
  207. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_batch_axis.py +0 -0
  208. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_capture_gpu.py +0 -0
  209. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_capture_scales.py +0 -0
  210. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_engine_loop.py +0 -0
  211. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_graph_path.py +0 -0
  212. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_graphs_on_gpu.py +0 -0
  213. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_hook_availability.py +0 -0
  214. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_hyper_connections.py +0 -0
  215. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_kv_isolation.py +0 -0
  216. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_new_points.py +0 -0
  217. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_only_families.py +0 -0
  218. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_padded_gpu.py +0 -0
  219. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_plugin.py +0 -0
  220. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_transformers_backend_gpu.py +0 -0
  221. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vllm_wire_grammar.py +0 -0
  222. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_vocabulary_boundary.py +0 -0
  223. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_worker_lens_capture_readout.py +0 -0
  224. {interp_engine-1.13.2 → interp_engine-1.14.0}/tests/test_worker_lens_readout.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: interp-engine
3
- Version: 1.13.2
3
+ Version: 1.14.0
4
4
  Summary: A fast, standardized, and easy to use interpretability engine.
5
5
  Project-URL: Homepage, https://github.com/decoderesearch/interp-engine
6
6
  Project-URL: Repository, https://github.com/decoderesearch/interp-engine
@@ -83,6 +83,12 @@ files and why they are where they are.
83
83
  child dies before it loads anything, and the caller is told to see a root cause that is in another
84
84
  process. Called from `_ensure_engine`; a no-op in a script, a server, or a kernel that captured
85
85
  the real descriptors itself.
86
+ - `vllm_seq_fit.py` — fits `max_num_seqs` to the Mamba state cache on a hybrid trunk. With full
87
+ decode CUDA graphs, vLLM needs one Mamba block per sequence, and it knows the block count only
88
+ inside its EngineCore child, after it measures memory. The worker plugin wraps vLLM's check to
89
+ write that count to a temporary file; `VLLMModel._start_engine` reads it after the failed start
90
+ and starts once more with `max_num_seqs` set to it. A caller's explicit `max_num_seqs` gets no
91
+ retry. `tests/test_vllm_seq_fit.py` covers both halves on CPU.
86
92
 
87
93
  ## Correctness
88
94
 
@@ -18,9 +18,11 @@ macOS/CPU.
18
18
  from __future__ import annotations
19
19
 
20
20
  import asyncio
21
+ import contextlib
21
22
  import importlib.util
22
23
  import logging
23
24
  import os
25
+ import tempfile
24
26
  import warnings
25
27
  from collections.abc import AsyncIterator, Awaitable, Callable, Iterable, Mapping, Sequence
26
28
  from typing import Any, TypeVar
@@ -82,6 +84,7 @@ from interp_engine.vllm_capture.static import (
82
84
  static_unsupported_reason,
83
85
  )
84
86
  from interp_engine.vllm_plugin import WORKER_EXTENSION_CLS
87
+ from interp_engine.vllm_seq_fit import SEQ_FIT_ENV, read_block_limit
85
88
 
86
89
  logger = logging.getLogger(__name__)
87
90
 
@@ -1128,6 +1131,7 @@ class VLLMModel:
1128
1131
  extra_vllm_kwargs=extra_vllm_kwargs,
1129
1132
  max_lora_rank=max_lora_rank,
1130
1133
  )
1134
+ self._max_num_seqs_pinned = "max_num_seqs" in (extra_vllm_kwargs or {})
1131
1135
  facts = read_residual_facts(hf_model_id, trust_remote_code)
1132
1136
  self._attn_dims = read_attn_dims(hf_model_id, trust_remote_code)
1133
1137
  reads, writes, graph = resolve_static_points(
@@ -1389,10 +1393,43 @@ class VLLMModel:
1389
1393
  # The line below forks a child that suppresses stdout by descriptor, which a
1390
1394
  # notebook kernel's stdout does not have. See `notebook_stdout`.
1391
1395
  ensure_stdout_descriptor()
1392
- self.engine = AsyncLLM.from_engine_args(AsyncEngineArgs(**self._engine_kwargs))
1396
+ self.engine = self._start_engine(AsyncLLM, AsyncEngineArgs)
1393
1397
  self._engine_loop = asyncio.get_running_loop()
1394
1398
  return self.engine
1395
1399
 
1400
+ def _start_engine(self, async_llm: Any, engine_args: Any) -> Any:
1401
+ """Build the engine. On a hybrid trunk, start again once if ``max_num_seqs`` does not fit.
1402
+
1403
+ See :mod:`interp_engine.vllm_seq_fit`. The retry happens only when a worker recorded the
1404
+ Mamba block count and the caller did not set ``max_num_seqs``.
1405
+ """
1406
+ if getattr(self, "_max_num_seqs_pinned", False):
1407
+ return async_llm.from_engine_args(engine_args(**self._engine_kwargs))
1408
+ fd, path = tempfile.mkstemp(prefix="interp-engine-seq-fit-")
1409
+ os.close(fd)
1410
+ os.environ[SEQ_FIT_ENV] = path
1411
+ try:
1412
+ try:
1413
+ return async_llm.from_engine_args(engine_args(**self._engine_kwargs))
1414
+ except Exception:
1415
+ blocks = read_block_limit(path)
1416
+ if blocks is None:
1417
+ raise
1418
+ logger.warning(
1419
+ "%s: max_num_seqs %s exceeds the %s Mamba cache blocks left after memory profiling; "
1420
+ "starting the engine again with max_num_seqs=%s. Set max_num_seqs to skip the retry.",
1421
+ self.hf_model_id,
1422
+ self._engine_kwargs.get("max_num_seqs", "(vLLM default)"),
1423
+ blocks,
1424
+ blocks,
1425
+ )
1426
+ self._engine_kwargs["max_num_seqs"] = blocks
1427
+ return async_llm.from_engine_args(engine_args(**self._engine_kwargs))
1428
+ finally:
1429
+ os.environ.pop(SEQ_FIT_ENV, None)
1430
+ with contextlib.suppress(OSError):
1431
+ os.unlink(path)
1432
+
1396
1433
  async def warmup(self) -> None:
1397
1434
  """Build the engine now instead of on the first request, and run one throwaway decode.
1398
1435
 
@@ -80,11 +80,13 @@ from interp_engine.vllm_capture import (
80
80
  worker_unregister_steering,
81
81
  )
82
82
  from interp_engine.vllm_capture.static import patch_worker_for_static
83
+ from interp_engine.vllm_seq_fit import patch_mamba_seq_check
83
84
 
84
85
  # Worker process imports this module for worker_extension_cls. Patching load_model here
85
86
  # (not as an extension method named load_model) is what lets static wraps run before
86
87
  # CUDA-graph capture. vLLM refuses an extension attribute that collides with Worker.
87
88
  patch_worker_for_static()
89
+ patch_mamba_seq_check()
88
90
 
89
91
  # Pass as ``worker_extension_cls=`` when constructing your engine. vLLM resolves this
90
92
  # qualified name inside each worker process, so it must stay importable under this path.
@@ -0,0 +1,85 @@
1
+ """Fit ``max_num_seqs`` to the Mamba state cache, so a hybrid trunk starts without a hand-set value.
2
+
3
+ With full decode CUDA graphs, vLLM needs one Mamba cache block per sequence, up to
4
+ ``max_num_seqs`` (128 by default). It knows the block count only after it measures memory,
5
+ inside the engine-core child, and refuses to start when there are fewer blocks than sequences.
6
+ Static attention buffers take memory from that cache, so a config that starts without them can
7
+ fail with them. The parent sees only "Engine core initialization failed".
8
+
9
+ The worker half wraps vLLM's check: when it refuses, the worker writes the block count to the
10
+ file named by :data:`SEQ_FIT_ENV`, then raises as before. The parent half reads that file after
11
+ the failed start and starts again with ``max_num_seqs`` set to the count. A caller who sets
12
+ ``max_num_seqs`` gets no retry: an explicit value wins, and fails the same way it did before.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import inspect
18
+ import os
19
+ from typing import Any
20
+
21
+ # Path of the file the worker writes the Mamba block count to. The parent sets it before it
22
+ # starts the engine, and the engine-core and worker processes inherit it.
23
+ SEQ_FIT_ENV = "INTERP_ENGINE_SEQ_FIT_FILE"
24
+
25
+
26
+ def mamba_block_limit(kv_cache_config: Any, max_num_reqs: int | None) -> int | None:
27
+ """Return the Mamba block count when it is below ``max_num_reqs``, else ``None``."""
28
+ if kv_cache_config is None or max_num_reqs is None:
29
+ return None
30
+ if not getattr(kv_cache_config, "has_mamba_layers", False):
31
+ return None
32
+ blocks = int(getattr(kv_cache_config, "num_blocks", 0))
33
+ if blocks <= 0 or max_num_reqs <= blocks:
34
+ return None
35
+ return blocks
36
+
37
+
38
+ def record_block_limit(blocks: int) -> None:
39
+ """Write ``blocks`` to the file named by :data:`SEQ_FIT_ENV`. Do nothing when it is unset."""
40
+ path = os.environ.get(SEQ_FIT_ENV)
41
+ if not path:
42
+ return
43
+ with open(path, "w", encoding="utf-8") as f:
44
+ f.write(str(blocks))
45
+
46
+
47
+ def read_block_limit(path: str) -> int | None:
48
+ """Return the block count a worker wrote to ``path``, or ``None`` when none did."""
49
+ try:
50
+ with open(path, encoding="utf-8") as f:
51
+ text = f.read().strip()
52
+ except OSError:
53
+ return None
54
+ return int(text) if text.isdigit() and int(text) > 0 else None
55
+
56
+
57
+ def patch_mamba_seq_check() -> None:
58
+ """Wrap ``CompilationConfig.resolve_cudagraph_mode_and_sizes`` to record the block count.
59
+
60
+ The wrap changes no result. It only writes the count before vLLM's own error propagates.
61
+ """
62
+ try:
63
+ from vllm.config.compilation import CompilationConfig # pyright: ignore[reportMissingImports]
64
+ except Exception: # noqa: BLE001
65
+ return
66
+ orig = CompilationConfig.resolve_cudagraph_mode_and_sizes
67
+ if getattr(orig, "_ie_seq_fit", False):
68
+ return
69
+ signature = inspect.signature(orig)
70
+
71
+ def resolve_cudagraph_mode_and_sizes(self: Any, *args: Any, **kwargs: Any) -> Any:
72
+ try:
73
+ return orig(self, *args, **kwargs)
74
+ except ValueError:
75
+ try:
76
+ bound = dict(signature.bind(self, *args, **kwargs).arguments)
77
+ except TypeError:
78
+ bound = {}
79
+ blocks = mamba_block_limit(bound.get("kv_cache_config"), bound.get("max_num_reqs"))
80
+ if blocks is not None:
81
+ record_block_limit(blocks)
82
+ raise
83
+
84
+ resolve_cudagraph_mode_and_sizes._ie_seq_fit = True # pyright: ignore[reportFunctionMemberAccess]
85
+ CompilationConfig.resolve_cudagraph_mode_and_sizes = resolve_cudagraph_mode_and_sizes
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "interp-engine"
3
- version = "1.13.2"
3
+ version = "1.14.0"
4
4
  description = "A fast, standardized, and easy to use interpretability engine."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -776,8 +776,9 @@ def test_ensure_engine_sets_breakable_beside_static_env():
776
776
  assert "apply_breakable_env" in src
777
777
  static_at = src.index("STATIC_ENV")
778
778
  breakable_at = src.index("apply_breakable_env")
779
- engine_at = src.index("from_engine_args")
779
+ engine_at = src.index("_start_engine")
780
780
  assert static_at < breakable_at < engine_at
781
+ assert "from_engine_args" in inspect.getsource(VLLMModel._start_engine)
781
782
 
782
783
 
783
784
  def test_a_read_buffer_is_not_used_as_a_boolean_when_sizing_the_write():
@@ -0,0 +1,191 @@
1
+ """A hybrid trunk whose Mamba cache holds fewer blocks than ``max_num_seqs`` starts on the retry.
2
+
3
+ vLLM measures the block count inside its engine-core child and refuses to start when there are
4
+ fewer blocks than sequences. The worker records the count, and the parent starts again with
5
+ ``max_num_seqs`` set to it. Stand-ins replace vLLM: what is under test is the handoff between the
6
+ two halves, which needs no GPU.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ import sys
13
+ import types
14
+ from collections.abc import Iterator
15
+ from typing import Any
16
+
17
+ import pytest
18
+
19
+ from interp_engine import vllm_seq_fit
20
+ from interp_engine.vllm_backend import VLLMModel
21
+ from interp_engine.vllm_seq_fit import (
22
+ SEQ_FIT_ENV,
23
+ mamba_block_limit,
24
+ patch_mamba_seq_check,
25
+ read_block_limit,
26
+ record_block_limit,
27
+ )
28
+
29
+
30
+ class _KVConfig:
31
+ def __init__(self, num_blocks: int, has_mamba_layers: bool = True) -> None:
32
+ self.num_blocks = num_blocks
33
+ self.has_mamba_layers = has_mamba_layers
34
+
35
+
36
+ def test_block_limit_only_when_mamba_blocks_are_short() -> None:
37
+ assert mamba_block_limit(_KVConfig(88), 128) == 88
38
+ assert mamba_block_limit(_KVConfig(128), 128) is None, "enough blocks"
39
+ assert mamba_block_limit(_KVConfig(88, has_mamba_layers=False), 128) is None, "no Mamba layers"
40
+ assert mamba_block_limit(None, 128) is None
41
+ assert mamba_block_limit(_KVConfig(88), None) is None
42
+
43
+
44
+ def test_record_and_read_round_trip(tmp_path: Any, monkeypatch: pytest.MonkeyPatch) -> None:
45
+ path = str(tmp_path / "fit")
46
+ monkeypatch.setenv(SEQ_FIT_ENV, path)
47
+ record_block_limit(88)
48
+ assert read_block_limit(path) == 88
49
+
50
+
51
+ def test_read_ignores_a_missing_or_empty_file(tmp_path: Any) -> None:
52
+ empty = tmp_path / "empty"
53
+ empty.write_text("")
54
+ assert read_block_limit(str(empty)) is None
55
+ assert read_block_limit(str(tmp_path / "absent")) is None
56
+
57
+
58
+ def test_record_without_the_env_writes_nothing(tmp_path: Any, monkeypatch: pytest.MonkeyPatch) -> None:
59
+ monkeypatch.delenv(SEQ_FIT_ENV, raising=False)
60
+ monkeypatch.chdir(tmp_path)
61
+ record_block_limit(88)
62
+ assert list(tmp_path.iterdir()) == []
63
+
64
+
65
+ @pytest.fixture
66
+ def fake_compilation(monkeypatch: pytest.MonkeyPatch) -> Iterator[type]:
67
+ """Install a stand-in ``vllm.config.compilation`` whose check matches vLLM's signature."""
68
+
69
+ class CompilationConfig:
70
+ def resolve_cudagraph_mode_and_sizes(
71
+ self,
72
+ min_cg_support: Any,
73
+ min_cg_attn_backend: str | None,
74
+ uniform_decode_query_len: int = 1,
75
+ use_v2_model_runner: bool = False,
76
+ tensor_parallel_size: int = 1,
77
+ kv_cache_config: Any = None,
78
+ max_num_reqs: int | None = None,
79
+ is_profiling: bool = False,
80
+ ) -> str:
81
+ blocks = mamba_block_limit(kv_cache_config, max_num_reqs)
82
+ if blocks is not None:
83
+ raise ValueError(f"max_num_seqs ({max_num_reqs}) exceeds available Mamba cache blocks ({blocks}).")
84
+ if min_cg_support == "bad":
85
+ raise ValueError("unrelated")
86
+ return "FULL"
87
+
88
+ module = types.ModuleType("vllm.config.compilation")
89
+ module.CompilationConfig = CompilationConfig # pyright: ignore[reportAttributeAccessIssue]
90
+ for name in ("vllm", "vllm.config"):
91
+ monkeypatch.setitem(sys.modules, name, sys.modules.get(name) or types.ModuleType(name))
92
+ monkeypatch.setitem(sys.modules, "vllm.config.compilation", module)
93
+ yield CompilationConfig
94
+
95
+
96
+ def test_patched_check_records_the_block_count_and_still_raises(
97
+ fake_compilation: type, tmp_path: Any, monkeypatch: pytest.MonkeyPatch
98
+ ) -> None:
99
+ path = str(tmp_path / "fit")
100
+ monkeypatch.setenv(SEQ_FIT_ENV, path)
101
+ patch_mamba_seq_check()
102
+ patch_mamba_seq_check()
103
+
104
+ config = fake_compilation()
105
+ with pytest.raises(ValueError, match="exceeds available Mamba cache blocks"):
106
+ config.resolve_cudagraph_mode_and_sizes("ok", None, 1, kv_cache_config=_KVConfig(88), max_num_reqs=128)
107
+ assert read_block_limit(path) == 88
108
+
109
+
110
+ def test_patched_check_changes_nothing_else(
111
+ fake_compilation: type, tmp_path: Any, monkeypatch: pytest.MonkeyPatch
112
+ ) -> None:
113
+ path = str(tmp_path / "fit")
114
+ monkeypatch.setenv(SEQ_FIT_ENV, path)
115
+ patch_mamba_seq_check()
116
+
117
+ config = fake_compilation()
118
+ assert (
119
+ config.resolve_cudagraph_mode_and_sizes("ok", None, kv_cache_config=_KVConfig(128), max_num_reqs=128) == "FULL"
120
+ )
121
+ with pytest.raises(ValueError, match="unrelated"):
122
+ config.resolve_cudagraph_mode_and_sizes("bad", None)
123
+ assert not os.path.exists(path), "no block count for an unrelated error"
124
+
125
+
126
+ class _FakeAsyncLLM:
127
+ """Fails like vLLM while ``max_num_seqs`` exceeds ``blocks``, recording the count as the worker does."""
128
+
129
+ def __init__(self, blocks: int | None) -> None:
130
+ self.blocks = blocks
131
+ self.calls: list[dict[str, Any]] = []
132
+
133
+ def from_engine_args(self, args: dict[str, Any]) -> str:
134
+ self.calls.append(dict(args))
135
+ if self.blocks is not None and args.get("max_num_seqs", 128) > self.blocks:
136
+ record_block_limit(self.blocks)
137
+ raise RuntimeError("Engine core initialization failed. See root cause above.")
138
+ return "engine"
139
+
140
+
141
+ def _model(extra: dict[str, Any] | None = None) -> VLLMModel:
142
+ model = object.__new__(VLLMModel)
143
+ model.hf_model_id = "stand-in/hybrid"
144
+ model._engine_kwargs = {"model": "stand-in/hybrid", **(extra or {})}
145
+ model._max_num_seqs_pinned = "max_num_seqs" in (extra or {})
146
+ return model
147
+
148
+
149
+ def test_start_engine_retries_with_the_recorded_block_count() -> None:
150
+ llm = _FakeAsyncLLM(blocks=88)
151
+ model = _model()
152
+
153
+ assert model._start_engine(llm, dict) == "engine"
154
+ assert [c.get("max_num_seqs") for c in llm.calls] == [None, 88]
155
+ assert model._engine_kwargs["max_num_seqs"] == 88
156
+ assert SEQ_FIT_ENV not in os.environ
157
+
158
+
159
+ def test_start_engine_starts_once_when_it_fits() -> None:
160
+ llm = _FakeAsyncLLM(blocks=None)
161
+
162
+ assert _model()._start_engine(llm, dict) == "engine"
163
+ assert len(llm.calls) == 1
164
+
165
+
166
+ def test_start_engine_reraises_a_failure_with_no_block_count() -> None:
167
+ class Broken(_FakeAsyncLLM):
168
+ def from_engine_args(self, args: dict[str, Any]) -> str:
169
+ self.calls.append(dict(args))
170
+ raise RuntimeError("out of memory")
171
+
172
+ llm = Broken(blocks=None)
173
+ with pytest.raises(RuntimeError, match="out of memory"):
174
+ _model()._start_engine(llm, dict)
175
+ assert len(llm.calls) == 1
176
+
177
+
178
+ def test_an_explicit_max_num_seqs_wins_and_is_not_retried() -> None:
179
+ llm = _FakeAsyncLLM(blocks=88)
180
+ model = _model({"max_num_seqs": 128})
181
+
182
+ with pytest.raises(RuntimeError, match="initialization failed"):
183
+ model._start_engine(llm, dict)
184
+ assert len(llm.calls) == 1
185
+ assert model._engine_kwargs["max_num_seqs"] == 128
186
+
187
+
188
+ def test_the_worker_plugin_installs_the_patch() -> None:
189
+ import interp_engine.vllm_plugin as plugin
190
+
191
+ assert plugin.patch_mamba_seq_check is vllm_seq_fit.patch_mamba_seq_check
File without changes
File without changes