Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,7 @@ make test-package PACKAGE=nmp_common
uv run pytest -v packages/nmp_common/tests/

# Test a specific service
make test-service SERVICE=evaluator
uv run pytest -v services/evaluator/tests/
make test-service SERVICE=guardrails

# Test a specific file
uv run pytest -v path/to/test_file.py
Expand Down Expand Up @@ -746,4 +745,3 @@ If you're updating existing tests:
- [ ] Chaos engineering tests
- [ ] Load and stress tests
- [ ] Contract testing between services

2 changes: 1 addition & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def pytest_collection_modifyitems(config, items):
item.add_marker(pytest.mark.e2e)
marker_names.add("e2e")

# Auto-mark integration tests (e.g., /services/evaluator/tests/integration/)
# Auto-mark integration tests (e.g., /services/core/jobs/tests/integration/)
elif "/integration/" in fspath_str:
if "integration" not in marker_names:
item.add_marker(pytest.mark.integration)
Expand Down
2 changes: 1 addition & 1 deletion docs/evaluator/tutorials/run-llm-judge-evaluation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ This tutorial uses `nvidia/nemotron-3-nano-30b-a3b` from NVIDIA Build.
```python
from nemo_evaluator_sdk import RunConfig, LLMJudgeMetric
from nemo_evaluator_sdk.values import (
FilesetRef,
InferenceParams,
JSONScoreParser,
Model,
RangeScore,
)
from nmp.evaluator.app.values import FilesetRef

JUDGE_MODEL_URL = "https://integrate.api.nvidia.com/v1/chat/completions"
JUDGE_MODEL_NAME = "nvidia/nemotron-3-nano-30b-a3b"
Expand Down
3 changes: 0 additions & 3 deletions packages/nmp_common/src/nmp/common/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ When multiple MCP servers exist across the platform:
```
services/core/mcp/ # Core infrastructure tools
services/guardrails/mcp/ # Guardrails-specific tools
services/evaluator/mcp/ # Evaluation-specific tools
services/customizer/mcp/ # Customization-specific tools
```

Expand Down Expand Up @@ -157,11 +156,9 @@ When aggregating multiple service MCP servers:
```python
# services/core/mcp/src/nmp/core/mcp/server.py
from nmp.guardrails.mcp.server import guardrails
from nmp.evaluator.mcp.server import evaluator

platform = FastMCP("NeMo Platform")
platform.mount(guardrails) # All tools use same patterns
platform.mount(evaluator) # Consistent for agents
```

**Benefits**:
Expand Down
4 changes: 2 additions & 2 deletions packages/nmp_testing/src/nmp/testing/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,11 @@ def create_test_client(

Example (with access_log for request verification):
with create_test_client(
EvaluatorService, auth_enabled=True, access_log=True, client_type=ClientContext
FilesService, auth_enabled=True, access_log=True, client_type=ClientContext
) as ctx:
ctx.access_log.clear() # Clear requests from setup
ctx.test_client.get(
"/apis/evaluation/v2/workspaces/default/metrics",
"/apis/files/v2/workspaces/default/filesets",
headers={"X-NMP-Principal-Id": "test@example.com"},
)
# Verify internal entity requests used the same principal
Expand Down
5 changes: 2 additions & 3 deletions plugins/nemo-guardrails/benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ the `bench` extra on `nemo-guardrails-plugin`. The `make benchmark-guardrails`
target installs them automatically via `uv run --extra bench`; they are not
part of the plugin's runtime install.

The upstream `aiperf` CLI itself pins `aiofiles<24.2`, which conflicts with
NMP's evaluator-service. To avoid downgrading the shared workspace venv, the
harness creates an isolated venv at
The upstream `aiperf` CLI itself pins older transitive dependencies. To avoid
downgrading the shared workspace venv, the harness creates an isolated venv at
`plugins/nemo-guardrails/benchmarks/artifacts/venvs/aiperf/` on first run and
reuses it on subsequent runs. CI gets a fresh one each invocation; locally
this caches across runs for fast iteration.
Expand Down
7 changes: 3 additions & 4 deletions plugins/nemo-guardrails/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ dependencies = [
bench = [
"httpx>=0.27",
"pyyaml>=6.0",
# NOTE: aiperf itself is *not* listed here. Its 0.x line pins
# aiofiles<24.2 which conflicts with evaluator-service's
# aiofiles>=25.1. To avoid downgrading the shared workspace venv, the
# harness installs aiperf into a dedicated venv at run time; see
# NOTE: aiperf itself is *not* listed here. Its 0.x line pins older
# transitive dependencies. To avoid downgrading the shared workspace venv,
# the harness installs aiperf into a dedicated venv at run time; see
# `nemo_guardrails_plugin.benchmarks.bootstrap`.
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

"""Bootstrap an isolated venv for the upstream AIPerf load generator.

``aiperf`` pins ``aiofiles<24.2`` which conflicts with NMP's evaluator-service
requirement of ``aiofiles>=25.1``, so we install it into a dedicated venv
instead of the shared workspace one. The venv is reused across local runs;
``aiperf`` pins older transitive dependencies, so we install it into a dedicated
venv instead of the shared workspace one. The venv is reused across local runs;
CI gets a fresh one each invocation.
"""

Expand Down
2 changes: 0 additions & 2 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ exclude = [
"node_modules",
"site-packages",
"venv",
"services/evaluator/src/external/evaltool",
"services/auditor/fixes/cve-2025-8194",
"services/guardrails/fixes/cve-2025-8194",
"services/evaluator/fixes/cve-2025-8194",
"services/safe-synthesizer/fixes/cve-2025-8194",
"services/safe-synthesizer-api/fixes/cve-2025-8194",
"architecture/examples",
Expand Down
6 changes: 3 additions & 3 deletions script/copyright_fixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@
def _matches_path_filter(relpath: str, patterns: list[str]) -> bool:
"""Return True if *relpath* matches any of the given path patterns.

Patterns are matched as prefixes first (e.g. ``services/evaluator``
matches ``services/evaluator/src/foo.py``). If a pattern contains
Patterns are matched as prefixes first (e.g. ``services/guardrails``
matches ``services/guardrails/src/foo.py``). If a pattern contains
glob characters it falls back to fnmatch on the full relative path.
"""
for pat in patterns:
Expand Down Expand Up @@ -524,7 +524,7 @@ def update_license_headers(
don't end up with a monster commit::

# Only process two directories
./script/copyright_fixer.py . --include services/evaluator --include packages/models
./script/copyright_fixer.py . --include services/guardrails --include packages/models

# Process everything except generated SDK code
./script/copyright_fixer.py . --exclude packages/nemo_platform
Expand Down
23 changes: 0 additions & 23 deletions script/generate_openapi_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,29 +495,6 @@ def apply_schema_fixes(spec_files: List[str], apply_reorder: bool = True) -> Non
print_verbose(f"Applying streaming fixes to {spec_file}")
spec = fix_openai_streaming_endpoints(spec)

# Rename namespaced schemas BEFORE tweak_spec strips namespace prefixes.
# This prevents collisions when multiple services define classes with the
# same name (e.g. both evaluator and guardrail define "Model").
# Keys are the full namespaced schema name as generated by FastAPI/Pydantic;
# values are the desired OpenAPI schema name after renaming.
namespaced_schema_renames: dict[str, str] = {
# SDK Model schema (Model is imported from nemo_evaluator_sdk.values.models)
"nmp__evaluator__app__values__models__Model": "Evaluator.Model",
"nemo_evaluator_sdk__values__models__Model": "Evaluator.Model",
}
if "platform" in spec_file:
if "components" in spec and "schemas" in spec["components"]:
schemas = spec["components"]["schemas"]
for namespaced_key, new_name in namespaced_schema_renames.items():
if namespaced_key in schemas:
schemas[new_name] = schemas.pop(namespaced_key)
rename_schema_references(spec, namespaced_key, new_name)
else:
print_verbose(
f"Warning: expected schema '{namespaced_key}' not found in {spec_file}, "
f"skipping rename to '{new_name}'"
)

# Apply the standard fix-schema logic
spec = tweak_spec(spec)
spec = hoist_nested_defs(spec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ test_normalize_endpoint if {
mock_endpoints := {
"/apis/models/v2/workspaces/{workspace}/models": {"get": {}},
"/apis/models/v2/workspaces/{workspace}/models/{name}": {"get": {}},
"/apis/files/v2/workspaces/{workspace}/filesets": {"get": {}},
"/apis/files/v2/workspaces/{workspace}/filesets/{name}": {"get": {}},
"/apis/entities/v2/workspaces": {"get": {}},
"/apis/entities/v2/workspaces/{workspace}/members": {"get": {}}
Expand All @@ -52,4 +53,7 @@ test_normalize_endpoint if {
common.normalize_endpoint("/apis/entities/v2/workspaces") == "/apis/entities/v2/workspaces"
with data.authz.endpoints as mock_endpoints

# Test filesets collection pattern
common.normalize_endpoint("/apis/files/v2/workspaces/test-ns/filesets") == "/apis/files/v2/workspaces/{workspace}/filesets"
with data.authz.endpoints as mock_endpoints
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,27 +221,27 @@ def test_build_command_uses_current_interpreter_for_python_module_commands() ->
executor = SubprocessExecutionProvider(
provider="subprocess",
profile="default",
command=["python", "-m", "nmp.evaluator.tasks.evaluate_metric"],
command=["python", "-m", "nemo_evaluator.tasks.evaluate"],
)

assert SubprocessJobBackend._build_command(executor, None) == [
sys.executable,
"-m",
"nmp.evaluator.tasks.evaluate_metric",
"nemo_evaluator.tasks.evaluate",
]


def test_build_command_uses_current_interpreter_for_python3_commands() -> None:
executor = SubprocessExecutionProvider(
provider="subprocess",
profile="default",
command=["python3", "-m", "nmp.evaluator.tasks.evaluate_metric"],
command=["python3", "-m", "nemo_evaluator.tasks.evaluate"],
)

assert SubprocessJobBackend._build_command(executor, None) == [
sys.executable,
"-m",
"nmp.evaluator.tasks.evaluate_metric",
"nemo_evaluator.tasks.evaluate",
]


Expand All @@ -253,13 +253,13 @@ def test_build_command_prefers_virtual_env_python(tmp_path) -> None:
executor = SubprocessExecutionProvider(
provider="subprocess",
profile="default",
command=["python", "-m", "nmp.evaluator.tasks.evaluate_metric"],
command=["python", "-m", "nemo_evaluator.tasks.evaluate"],
)

assert SubprocessJobBackend._build_command(executor, str(tmp_path / "venv")) == [
str(venv_python),
"-m",
"nmp.evaluator.tasks.evaluate_metric",
"nemo_evaluator.tasks.evaluate",
]


Expand Down
1 change: 0 additions & 1 deletion services/core/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ This service follows NeMo Platform v2 patterns:
Future expansion will support mounting service-specific MCP servers from:

- `nmp.guardrails.mcp`
- `nmp.evaluator.mcp`
- `nmp.customizer.mcp`
- etc.

Expand Down
5 changes: 0 additions & 5 deletions services/evaluator/.dockerignore

This file was deleted.

8 changes: 0 additions & 8 deletions services/evaluator/README.md

This file was deleted.

42 changes: 0 additions & 42 deletions services/evaluator/docker-compose-db-migration.yaml

This file was deleted.

54 changes: 0 additions & 54 deletions services/evaluator/example-config.yaml

This file was deleted.

Loading
Loading