mirror of
https://github.com/NVIDIA-NeMo/DataDesigner
synced 2026-05-24 09:48:29 +00:00
* adjust plan * feat: remove litellm dependency and bridge path (PR-7) - Delete litellm_bridge.py adapter, litellm_overrides.py, and their tests - Remove LiteLLM fallback branch and DATA_DESIGNER_MODEL_BACKEND env var from clients/factory.py; unknown provider_type now raises ValueError - Remove apply_litellm_patches() call from models/factory.py - Remove LiteLLM exception match arms and DownstreamLLMExceptionMessageParser from models/errors.py; port context window detail extraction to _extract_context_window_detail for native ProviderError path - Remove litellm from lazy_heavy_imports.py and pyproject.toml runtime deps - Remove flatten_extra_body parameter from TransportKwargs.from_request - Clean up LiteLLM references in docstrings, comments, and AGENTS.md - Add full ProviderErrorKind test coverage to test_model_errors.py - Update benchmark script to patch OpenAICompatibleClient instead of CustomRouter Made-with: Cursor * fix: forward tools to _fake_response in benchmark patch The old CustomRouter patch forwarded **kwargs (including tools) to _fake_response, but the new OpenAICompatibleClient patch only passed model and messages — silently disabling tool-call simulation in benchmark scenarios that exercise allow_tools. Made-with: Cursor * fix: address PR-7 review feedback - Return ChatCompletionResponse from benchmark fakes instead of FakeResponse to match the native client contract (facade expects .message, not .choices[0].message) - Add ids= to parametrize block in test_model_errors.py for readability - Remove unnecessary try/except from _extract_context_window_detail; the `if marker in` guard is sufficient - Make context window marker match case-insensitive - Replace stale httpx.AsyncClient callout in async_concurrency.py docstring with generic "async-stateful resources" Made-with: Cursor
109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from data_designer.config.models import (
|
|
ChatCompletionInferenceParams,
|
|
EmbeddingInferenceParams,
|
|
ImageInferenceParams,
|
|
ModelConfig,
|
|
)
|
|
from data_designer.engine.model_provider import ModelProvider, ModelProviderRegistry
|
|
from data_designer.engine.models.clients.base import ModelClient
|
|
from data_designer.engine.models.factory import create_model_registry
|
|
from data_designer.engine.models.registry import ModelRegistry
|
|
from data_designer.engine.secret_resolver import SecretsFileResolver
|
|
from data_designer.engine.testing import StubMCPFacade, StubMCPRegistry
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_secrets_resolver() -> SecretsFileResolver:
|
|
module_path = Path(__file__).parent
|
|
return SecretsFileResolver(module_path / "stub_secrets.json")
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_model_provider_registry() -> ModelProviderRegistry:
|
|
return ModelProviderRegistry(
|
|
providers=[
|
|
ModelProvider(
|
|
name="stub-model-provider",
|
|
endpoint="https://api.example.com/v1",
|
|
provider_type="openai",
|
|
api_key="STUB_API_KEY",
|
|
)
|
|
]
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_model_configs() -> list[ModelConfig]:
|
|
return [
|
|
ModelConfig(
|
|
alias="stub-text",
|
|
model="stub-model-text",
|
|
provider="stub-model-provider",
|
|
inference_parameters=ChatCompletionInferenceParams(
|
|
temperature=0.80, top_p=0.95, max_tokens=100, max_parallel_requests=10, timeout=100
|
|
),
|
|
),
|
|
ModelConfig(
|
|
alias="stub-reasoning",
|
|
model="stub-model-reasoning",
|
|
provider="stub-model-provider",
|
|
inference_parameters=ChatCompletionInferenceParams(
|
|
temperature=0.80, top_p=0.95, max_tokens=100, max_parallel_requests=10, timeout=100
|
|
),
|
|
),
|
|
ModelConfig(
|
|
alias="stub-embedding",
|
|
model="stub-model-embedding",
|
|
provider="stub-model-provider",
|
|
inference_parameters=EmbeddingInferenceParams(
|
|
dimensions=100,
|
|
),
|
|
),
|
|
ModelConfig(
|
|
alias="stub-image",
|
|
model="stub-model-image",
|
|
provider="stub-model-provider",
|
|
inference_parameters=ImageInferenceParams(),
|
|
),
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_model_registry(
|
|
stub_model_configs: list[ModelConfig],
|
|
stub_secrets_resolver: SecretsFileResolver,
|
|
stub_model_provider_registry: ModelProviderRegistry,
|
|
) -> ModelRegistry:
|
|
return create_model_registry(
|
|
model_configs=stub_model_configs,
|
|
secret_resolver=stub_secrets_resolver,
|
|
model_provider_registry=stub_model_provider_registry,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_model_client() -> MagicMock:
|
|
"""Mock ModelClient for testing ModelFacade without a real HTTP adapter."""
|
|
return MagicMock(spec=ModelClient)
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_mcp_facade_for_model() -> StubMCPFacade:
|
|
"""Default stub MCP facade with max_tool_call_turns=3."""
|
|
return StubMCPFacade()
|
|
|
|
|
|
@pytest.fixture
|
|
def stub_mcp_registry_for_model(stub_mcp_facade_for_model: StubMCPFacade) -> StubMCPRegistry:
|
|
"""Default stub MCP registry."""
|
|
return StubMCPRegistry(stub_mcp_facade_for_model)
|