| from __future__ import annotations |
|
|
| import importlib.util |
| from collections.abc import Callable |
| from dataclasses import asdict, dataclass |
| from typing import Any |
|
|
| import requests |
|
|
| VINDEX_BASE_URL = "http://127.0.0.1:8765" |
| VINDEX_METHODS = { |
| "logit_lens": "/logit_lens", |
| "slot_neighbors": "/slot_neighbors", |
| "layer_contribution": "/layer_contribution", |
| "transition_spectrum": "/transition_spectrum", |
| "calibrated_edit": "/calibrated_edit", |
| "derive_scale": "/derive_scale", |
| "star_spread": "/star_spread", |
| "protect_relations": "/protect_relations", |
| } |
|
|
|
|
| @dataclass(frozen=True) |
| class VINDEXCallPlan: |
| method: str |
| endpoint: str |
| payload: dict[str, Any] |
| execute: bool |
| safety_notes: list[str] |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return asdict(self) |
|
|
|
|
| def vindex_dependency_report( |
| base_url: str = VINDEX_BASE_URL, |
| get_func: Callable[..., requests.Response] = requests.get, |
| ) -> dict[str, Any]: |
| package_available = importlib.util.find_spec("vindex") is not None |
| server = _server_status(base_url, get_func) |
| return { |
| "package_available": package_available, |
| "server_base_url": base_url.rstrip("/"), |
| "server_reachable": server["reachable"], |
| "server_detail": server["detail"], |
| "supported_methods": sorted(VINDEX_METHODS), |
| "dependency": "Install or run VINDEX locally; no cloud endpoint is configured.", |
| } |
|
|
|
|
| def build_vindex_call_plan( |
| method: str, |
| payload: dict[str, Any], |
| base_url: str = VINDEX_BASE_URL, |
| ) -> VINDEXCallPlan: |
| if method not in VINDEX_METHODS: |
| raise ValueError(f"Unsupported VINDEX method: {method}") |
|
|
| safe_payload = _safe_payload(method, payload) |
| return VINDEXCallPlan( |
| method=method, |
| endpoint=f"{base_url.rstrip('/')}{VINDEX_METHODS[method]}", |
| payload=safe_payload, |
| execute=False, |
| safety_notes=_safety_notes(method, payload, safe_payload), |
| ) |
|
|
|
|
| def vindex_verification_report( |
| method: str = "logit_lens", |
| payload: dict[str, Any] | None = None, |
| base_url: str = VINDEX_BASE_URL, |
| get_func: Callable[..., requests.Response] = requests.get, |
| ) -> dict[str, Any]: |
| call_plan = build_vindex_call_plan(method, payload or {"model_id": "", "text": ""}, base_url) |
| return { |
| "dependency_report": vindex_dependency_report(base_url, get_func), |
| "call_plan": call_plan.to_dict(), |
| "ready_for_execution": False, |
| "reason": ( |
| "The workbench records a safe VINDEX boundary first. Execute only after the local " |
| "VINDEX package/server, model loading, and edit safety checks are verified." |
| ), |
| } |
|
|
|
|
| def _server_status( |
| base_url: str, |
| get_func: Callable[..., requests.Response], |
| ) -> dict[str, object]: |
| url = base_url.rstrip("/") |
| try: |
| response = get_func(f"{url}/health", timeout=2) |
| except requests.RequestException as exc: |
| return {"reachable": False, "detail": f"VINDEX server not reachable: {exc}"} |
| if response.ok: |
| return {"reachable": True, "detail": "VINDEX health endpoint is reachable."} |
| return { |
| "reachable": False, |
| "detail": f"VINDEX health endpoint responded with HTTP {response.status_code}.", |
| } |
|
|
|
|
| def _safe_payload(method: str, payload: dict[str, Any]) -> dict[str, Any]: |
| safe_payload = dict(payload) |
| if method == "star_spread": |
| requested = int(safe_payload.get("n_neighbors", 5)) |
| safe_payload["n_neighbors"] = min(requested, 5) |
| if method == "calibrated_edit": |
| requested_window = int(safe_payload.get("causal_window", 3)) |
| safe_payload["causal_window"] = min(requested_window, 3) |
| return safe_payload |
|
|
|
|
| def _safety_notes( |
| method: str, |
| original_payload: dict[str, Any], |
| safe_payload: dict[str, Any], |
| ) -> list[str]: |
| notes = [ |
| "Non-executing plan only; no model weights are edited by this workbench helper.", |
| "Run VINDEX locally and verify protected relations before any calibrated edit.", |
| ] |
| if method == "star_spread" and original_payload != safe_payload: |
| notes.append("n_neighbors was capped at 5 to avoid over-editing related slots.") |
| if method == "calibrated_edit" and original_payload != safe_payload: |
| notes.append("causal_window was capped at 3 layers around the phase layer.") |
| return notes |
|
|