vllm-lens 1.0.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 (36) hide show
  1. vllm_lens-1.0.0/.github/workflows/checks.yaml +45 -0
  2. vllm_lens-1.0.0/.github/workflows/release.yaml +29 -0
  3. vllm_lens-1.0.0/.gitignore +30 -0
  4. vllm_lens-1.0.0/.pre-commit-config.yaml +17 -0
  5. vllm_lens-1.0.0/.python-version +1 -0
  6. vllm_lens-1.0.0/.vscode/extensions.json +16 -0
  7. vllm_lens-1.0.0/.vscode/settings.json +25 -0
  8. vllm_lens-1.0.0/PKG-INFO +93 -0
  9. vllm_lens-1.0.0/README.md +78 -0
  10. vllm_lens-1.0.0/pyproject.toml +88 -0
  11. vllm_lens-1.0.0/typestubs/transformers/__init__.pyi +3 -0
  12. vllm_lens-1.0.0/uv.lock +6024 -0
  13. vllm_lens-1.0.0/vllm_lens/__init__.py +23 -0
  14. vllm_lens-1.0.0/vllm_lens/_activations_plugin.py +405 -0
  15. vllm_lens-1.0.0/vllm_lens/_examples/activation_oracle.py +332 -0
  16. vllm_lens-1.0.0/vllm_lens/_examples/benchmark.ipynb +799 -0
  17. vllm_lens-1.0.0/vllm_lens/_examples/extract_residual_stream.ipynb +164 -0
  18. vllm_lens-1.0.0/vllm_lens/_examples/inspect-demo.ipynb +340 -0
  19. vllm_lens-1.0.0/vllm_lens/_examples/tests/test_activation_oracle.py +208 -0
  20. vllm_lens-1.0.0/vllm_lens/_examples/tests/utils/original_demo_activations.pt +0 -0
  21. vllm_lens-1.0.0/vllm_lens/_helpers/_serialize.py +112 -0
  22. vllm_lens-1.0.0/vllm_lens/_helpers/types.py +95 -0
  23. vllm_lens-1.0.0/vllm_lens/_inspect_entry.py +8 -0
  24. vllm_lens-1.0.0/vllm_lens/_worker_ext.py +463 -0
  25. vllm_lens-1.0.0/vllm_lens/inspect_provider.py +220 -0
  26. vllm_lens-1.0.0/vllm_lens/py.typed +0 -0
  27. vllm_lens-1.0.0/vllm_lens/tests/__init__.py +0 -0
  28. vllm_lens-1.0.0/vllm_lens/tests/__snapshots__/test_activations_match.ambr +4504 -0
  29. vllm_lens-1.0.0/vllm_lens/tests/conftest.py +90 -0
  30. vllm_lens-1.0.0/vllm_lens/tests/test_activations_chunked_prefill.py +91 -0
  31. vllm_lens-1.0.0/vllm_lens/tests/test_activations_cross_api.py +382 -0
  32. vllm_lens-1.0.0/vllm_lens/tests/test_activations_match.py +105 -0
  33. vllm_lens-1.0.0/vllm_lens/tests/test_activations_offline.py +97 -0
  34. vllm_lens-1.0.0/vllm_lens/tests/test_activations_pp.py +199 -0
  35. vllm_lens-1.0.0/vllm_lens/tests/test_serialize.py +98 -0
  36. vllm_lens-1.0.0/vllm_lens/tests/test_steering.py +256 -0
@@ -0,0 +1,45 @@
1
+ name: Checks
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths-ignore:
8
+ - '.devcontainer/**'
9
+ - '.github/**'
10
+ - '.vscode/**'
11
+ - '.gitignore'
12
+ - 'README.md'
13
+ pull_request:
14
+ branches:
15
+ - main
16
+ paths-ignore:
17
+ - '.devcontainer/**'
18
+ - '.github/**'
19
+ - '.vscode/**'
20
+ - '.gitignore'
21
+ - 'README.md'
22
+ workflow_call:
23
+ inputs:
24
+ dummy:
25
+ type: string
26
+ required: false
27
+
28
+ jobs:
29
+ checks:
30
+ name: Checks
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - name: Install uv
35
+ uses: astral-sh/setup-uv@v4
36
+ - name: Set up Python
37
+ run: uv python install
38
+ - name: Install dependencies
39
+ run: uv sync
40
+ - name: Ruff lint
41
+ run: uv run ruff check
42
+ - name: Ruff format
43
+ run: uv run ruff format --check
44
+ - name: Pyright
45
+ run: uv run pyright
@@ -0,0 +1,29 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ checks:
9
+ name: Run checks
10
+ uses: ./.github/workflows/checks.yaml
11
+
12
+ release:
13
+ name: Release to PyPI
14
+ needs: checks
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ id-token: write
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v4
22
+ - name: Set up Python
23
+ run: uv python install
24
+ - name: Set version from tag
25
+ run: sed -i "s/version=\".*\"/version=\"${GITHUB_REF_NAME#v}\"/" pyproject.toml
26
+ - name: Build
27
+ run: uv build
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,30 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Environment variables
13
+ .env
14
+
15
+ # Logs
16
+ logs/
17
+ scratch/
18
+
19
+ # Core dump
20
+ **/core
21
+
22
+ # Scratch files
23
+ **/scratch.ipynb
24
+
25
+ # Container images (built from containers/*.def)
26
+ *.sif
27
+
28
+ # Other
29
+ benchmarks.json
30
+ .claude/settings.json
@@ -0,0 +1,17 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--no-fix]
7
+ - id: ruff-format
8
+ args: [--check]
9
+
10
+ - repo: local
11
+ hooks:
12
+ - id: pyright
13
+ name: pyright
14
+ entry: uv run --no-sync pyright
15
+ language: system
16
+ types: [python]
17
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,16 @@
1
+ {
2
+ "recommendations": [
3
+ "anthropic.claude-code",
4
+ "charliermarsh.ruff",
5
+ "davidanson.vscode-markdownlint",
6
+ "donjayamanne.githistory",
7
+ "elagil.pre-commit-helper",
8
+ "littlefoxteam.vscode-python-test-adapter",
9
+ "ms-python.python",
10
+ "ms-python.vscode-pylance",
11
+ "ms-toolsai.jupyter",
12
+ "tamasfe.even-better-toml",
13
+ "ukaisi.inspect-ai",
14
+ "johnpapa.vscode-peacock",
15
+ ]
16
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "python.envFile": "${workspaceFolder}/.env",
3
+ "editor.codeActionsOnSave": {
4
+ "source.organizeImports": "explicit"
5
+ },
6
+ "editor.formatOnSave": true,
7
+ "evenBetterToml.formatter.allowedBlankLines": 1,
8
+ "evenBetterToml.formatter.arrayAutoCollapse": true,
9
+ "evenBetterToml.formatter.arrayAutoExpand": true,
10
+ "evenBetterToml.formatter.arrayTrailingComma": true,
11
+ "evenBetterToml.formatter.columnWidth": 88,
12
+ "evenBetterToml.formatter.compactArrays": true,
13
+ "evenBetterToml.formatter.compactEntries": true,
14
+ "evenBetterToml.formatter.compactInlineTables": true,
15
+ "evenBetterToml.formatter.indentEntries": true,
16
+ "evenBetterToml.formatter.indentString": " ",
17
+ "evenBetterToml.formatter.indentTables": true,
18
+ "evenBetterToml.formatter.inlineTableExpand": true,
19
+ "evenBetterToml.formatter.reorderArrays": true,
20
+ "evenBetterToml.formatter.reorderKeys": true,
21
+ "evenBetterToml.formatter.trailingNewline": true,
22
+ "evenBetterToml.schema.enabled": true,
23
+ "evenBetterToml.schema.links": true,
24
+ "evenBetterToml.syntax.semanticTokens": false,
25
+ }
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: vllm-lens
3
+ Version: 1.0.0
4
+ Summary: vLLM plugin for interacting with activations during inference
5
+ License-Expression: MIT
6
+ Classifier: Development Status :: 3 - Alpha
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
9
+ Requires-Python: >=3.12
10
+ Requires-Dist: datasets>=4.0.0
11
+ Requires-Dist: pydantic>=2.0
12
+ Requires-Dist: vllm>=0.16.0
13
+ Requires-Dist: zstandard>=0.23.0
14
+ Description-Content-Type: text/markdown
15
+
16
+ # vLLM-lens
17
+
18
+ Extract residual-stream activations and apply steering vectors (including activation oracles) to any vLLM model during inference. Typically hundreds of times faster than HF Transformers, with the ability to generate text, extract activations, and run activation oracles in the same dynamic batch.
19
+
20
+ Auto-registers as both a [vLLM general plugin](https://docs.vllm.ai/en/latest/design/plugin_system.html) and an [Inspect](https://inspect.aisi.org.uk/) model provider on install. Interact with model internals per-call via `SamplingParams.extra_args` (vLLM) or `GenerateConfig.extra_body` (Inspect).
21
+
22
+ Supports async, sync, and serve modes with `mp` and `ray` distributed backends for multi-node tensor parallelism. In offline modes, activations are returned directly on `output.activations`. In serve mode (`vllm serve`), they are serialised in the HTTP response and decoded with `decode_activations()`.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ uv add vllm-lens
28
+ ```
29
+
30
+ ## Examples
31
+
32
+ These examples use the Inspect integration. See the [`examples/`](examples/) folder for offline and online vLLM usage.
33
+
34
+ ### Inspect AI provider
35
+
36
+ An [Inspect AI](https://inspect.ai-safety-institute.org.uk/) model provider registered as `vllm-lens`. Extends the built-in vLLM provider to serialize `torch.Tensor` steering vectors for HTTP transport and decode base64-encoded activations from responses into `ModelOutput.metadata["activations"]`. Also supports LoRA adaptors.
37
+
38
+ Usage is the same as the [default vLLM provider](https://inspect.aisi.org.uk/providers.html#vllm) but with the `vllm-lens` prefix (e.g. `vllm-lens/meta-llama/Llama-3.1-1B`).
39
+
40
+ #### Extracting activations
41
+
42
+ ```python
43
+ capture_config = GenerateConfig(
44
+ temperature=0.0,
45
+ max_tokens=1,
46
+ extra_body={
47
+ "extra_args": {"output_residual_stream": extraction_activation_layers},
48
+ "chat_template_kwargs": {"enable_thinking": False},
49
+ },
50
+ )
51
+ output = await model.generate(state.messages, config=capture_config)
52
+ residual_stream = output.metadata["activations"]["residual_stream"]
53
+ ```
54
+
55
+ #### Steering with an Activation Oracle
56
+
57
+ ```python
58
+ from vllm_lens import SteeringVector
59
+
60
+ messages = [ChatMessageUser(content=oracle_content)]
61
+ oracle_config = GenerateConfig(
62
+ temperature=0.0,
63
+ max_tokens=50,
64
+ extra_body={
65
+ "extra_args": {
66
+ "apply_steering_vectors": [
67
+ SteeringVector(
68
+ activations=act_vector,
69
+ layer_indices=[injection_layer],
70
+ scale=steering_coefficient,
71
+ norm_match=True,
72
+ position_indices=[special_pos],
73
+ )
74
+ ],
75
+ },
76
+ "lora_request": {
77
+ "lora_name": "oracle",
78
+ "lora_int_id": 1,
79
+ "lora_path": lora_path,
80
+ },
81
+ "chat_template_kwargs": {"enable_thinking": False},
82
+ },
83
+ )
84
+ response = await model.generate(messages, config=oracle_config)
85
+ ```
86
+
87
+ ## Theory
88
+
89
+ Ships a vLLM worker extension that adds hooks to the model in the underlying workers (credit to Sid Black for pioneering this), plus a plugin to track which activations belong to which prompts across vLLM's dynamic batching with paged attention (similar to the nnsight approach).
90
+
91
+ ## Credits
92
+
93
+ Developed by Alan Cooney, with credit going to Sid Black for the orignal vLLM worker extension idea.
@@ -0,0 +1,78 @@
1
+ # vLLM-lens
2
+
3
+ Extract residual-stream activations and apply steering vectors (including activation oracles) to any vLLM model during inference. Typically hundreds of times faster than HF Transformers, with the ability to generate text, extract activations, and run activation oracles in the same dynamic batch.
4
+
5
+ Auto-registers as both a [vLLM general plugin](https://docs.vllm.ai/en/latest/design/plugin_system.html) and an [Inspect](https://inspect.aisi.org.uk/) model provider on install. Interact with model internals per-call via `SamplingParams.extra_args` (vLLM) or `GenerateConfig.extra_body` (Inspect).
6
+
7
+ Supports async, sync, and serve modes with `mp` and `ray` distributed backends for multi-node tensor parallelism. In offline modes, activations are returned directly on `output.activations`. In serve mode (`vllm serve`), they are serialised in the HTTP response and decoded with `decode_activations()`.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ uv add vllm-lens
13
+ ```
14
+
15
+ ## Examples
16
+
17
+ These examples use the Inspect integration. See the [`examples/`](examples/) folder for offline and online vLLM usage.
18
+
19
+ ### Inspect AI provider
20
+
21
+ An [Inspect AI](https://inspect.ai-safety-institute.org.uk/) model provider registered as `vllm-lens`. Extends the built-in vLLM provider to serialize `torch.Tensor` steering vectors for HTTP transport and decode base64-encoded activations from responses into `ModelOutput.metadata["activations"]`. Also supports LoRA adaptors.
22
+
23
+ Usage is the same as the [default vLLM provider](https://inspect.aisi.org.uk/providers.html#vllm) but with the `vllm-lens` prefix (e.g. `vllm-lens/meta-llama/Llama-3.1-1B`).
24
+
25
+ #### Extracting activations
26
+
27
+ ```python
28
+ capture_config = GenerateConfig(
29
+ temperature=0.0,
30
+ max_tokens=1,
31
+ extra_body={
32
+ "extra_args": {"output_residual_stream": extraction_activation_layers},
33
+ "chat_template_kwargs": {"enable_thinking": False},
34
+ },
35
+ )
36
+ output = await model.generate(state.messages, config=capture_config)
37
+ residual_stream = output.metadata["activations"]["residual_stream"]
38
+ ```
39
+
40
+ #### Steering with an Activation Oracle
41
+
42
+ ```python
43
+ from vllm_lens import SteeringVector
44
+
45
+ messages = [ChatMessageUser(content=oracle_content)]
46
+ oracle_config = GenerateConfig(
47
+ temperature=0.0,
48
+ max_tokens=50,
49
+ extra_body={
50
+ "extra_args": {
51
+ "apply_steering_vectors": [
52
+ SteeringVector(
53
+ activations=act_vector,
54
+ layer_indices=[injection_layer],
55
+ scale=steering_coefficient,
56
+ norm_match=True,
57
+ position_indices=[special_pos],
58
+ )
59
+ ],
60
+ },
61
+ "lora_request": {
62
+ "lora_name": "oracle",
63
+ "lora_int_id": 1,
64
+ "lora_path": lora_path,
65
+ },
66
+ "chat_template_kwargs": {"enable_thinking": False},
67
+ },
68
+ )
69
+ response = await model.generate(messages, config=oracle_config)
70
+ ```
71
+
72
+ ## Theory
73
+
74
+ Ships a vLLM worker extension that adds hooks to the model in the underlying workers (credit to Sid Black for pioneering this), plus a plugin to track which activations belong to which prompts across vLLM's dynamic batching with paged attention (similar to the nnsight approach).
75
+
76
+ ## Credits
77
+
78
+ Developed by Alan Cooney, with credit going to Sid Black for the orignal vLLM worker extension idea.
@@ -0,0 +1,88 @@
1
+ [project]
2
+ classifiers=[
3
+ "Development Status :: 3 - Alpha",
4
+ "Intended Audience :: Science/Research",
5
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
6
+ ]
7
+ dependencies=[
8
+ "datasets>=4.0.0",
9
+ "pydantic>=2.0",
10
+ "vllm>=0.16.0",
11
+ "zstandard>=0.23.0",
12
+ ]
13
+ description="vLLM plugin for interacting with activations during inference"
14
+ license="MIT"
15
+ name="vllm-lens"
16
+ readme="README.md"
17
+ requires-python=">=3.12"
18
+ version="1.0.0" # Updated by CICD
19
+
20
+ [build-system]
21
+ build-backend="hatchling.build"
22
+ requires=["hatchling"]
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages=["vllm_lens"]
26
+
27
+ [tool.uv]
28
+ override-dependencies=["aiobotocore>=3.0.0", "transformers>=5.3.0"]
29
+ [tool.uv.sources]
30
+ torch=[
31
+ {index="pytorch-cu126", marker="sys_platform == 'linux' or sys_platform == 'win32'"},
32
+ ]
33
+ torchvision=[
34
+ {index="pytorch-cu126", marker="sys_platform == 'linux' or sys_platform == 'win32'"},
35
+ ]
36
+
37
+ [[tool.uv.index]]
38
+ explicit=true
39
+ name="pytorch-cu126"
40
+ url="https://download.pytorch.org/whl/cu126"
41
+
42
+ [dependency-groups]
43
+ dev=[
44
+ "datasets>=4.6.0",
45
+ "inspect-ai>=0.3.183",
46
+ "ipykernel>=7.2.0",
47
+ "ipywidgets>=8.1.8",
48
+ "jaxtyping>=0.3.9",
49
+ "jinja2>=3.1.6",
50
+ "peft>=0.18.1",
51
+ "pre-commit>=4.5.1",
52
+ "pyright>=1.1.408",
53
+ "pytest-asyncio>=1.3.0",
54
+ "pytest>=9.0.2",
55
+ "python-dotenv>=1.2.1",
56
+ "ray[serve]>=2.54.0",
57
+ "ruff>=0.15.3",
58
+ "syrupy>=5.1.0",
59
+ "torch>=2.9.1",
60
+ "tqdm>=4.67.3",
61
+ "transformers>=5.3.0",
62
+ "typer>=0.24.1",
63
+ ]
64
+
65
+ [tool.pytest.ini_options]
66
+ asyncio_default_test_loop_scope="module"
67
+ asyncio_mode="auto"
68
+ filterwarnings=[
69
+ "ignore::DeprecationWarning:importlib._bootstrap",
70
+ "ignore:This process.*is multi-threaded.*use of fork:DeprecationWarning",
71
+ ]
72
+
73
+ [tool.pyright]
74
+ include=["vllm_lens"]
75
+ reportMissingImports=false
76
+ reportMissingModuleSource=false
77
+ reportMissingTypeStubs=false
78
+ stubPath="typestubs"
79
+ useLibraryCodeForTypes=false
80
+
81
+ [tool.ruff.lint]
82
+ ignore=["E402", "F722", "F821"]
83
+
84
+ [project.entry-points."vllm.general_plugins"]
85
+ activations="vllm_lens._activations_plugin:register"
86
+
87
+ [project.entry-points.inspect_ai]
88
+ vllm_lens="vllm_lens._inspect_entry"
@@ -0,0 +1,3 @@
1
+ from typing import Any
2
+
3
+ def __getattr__(name: str) -> Any: ...