feat(api): canonical top-level imports for LLM types and registry functions#1882
Conversation
…ctions Make `from nemoguardrails import ...` the canonical user-facing path for the integrator-facing surface of v0.22: - LLM types from `nemoguardrails.types` (ChatMessage, FinishReason, LLMFramework, LLMModel, LLMResponse, LLMResponseChunk, Role, ToolCall, ToolCallFunction, UsageInfo) are re-exported from both `nemoguardrails` (top-level) and `nemoguardrails.llm`. - Framework registry functions from `nemoguardrails.llm.frameworks` (register_framework, set_default_framework, get_default_framework) are also re-exported from `nemoguardrails.llm`. They were already exported from `nemoguardrails` top-level. Custom LLM Framework, Custom LLM Model, and testing-your-config doc examples switch their import lines to the top-level form so the "integrator constructs value types and protocol classes" path uses one import statement. `nemoguardrails/types.py` gains a module-level docstring documenting it as the stable public LLM interop surface, plus an explicit `__all__` listing the public names. Parametrized exports tests verify each name is exposed on every supported import path and resolves to the same canonical object.
Greptile SummaryThis PR establishes
|
| Filename | Overview |
|---|---|
| nemoguardrails/init.py | Adds re-exports of all public LLM types from nemoguardrails.types and register_provider from nemoguardrails.llm.providers; updates all accordingly. No circular-import risk since types.py has no nemoguardrails-internal imports. |
| nemoguardrails/llm/init.py | Transforms a previously empty init into a re-export hub for types and registry functions. Import chain is safe: frameworks/init.py and providers/init.py only import from sibling submodules, not from the top-level nemoguardrails package. |
| nemoguardrails/types.py | Adds module docstring promising stability across minor versions and an explicit all. The listed names match the actual class/type definitions in the file. |
| tests/test_types_exports.py | New parametrized test suite verifying presence in all, attribute access, and object identity across all three import paths for both type names and registry functions. |
| docs/configure-rails/custom-initialization/custom-llm-framework.md | Updates code examples to use the new top-level import path; changes are cosmetic and consistent with the new public API. |
| docs/configure-rails/custom-initialization/custom-llm-model.md | Consolidates previously separate imports of types and register_provider into a single from nemoguardrails import block, consistent with the new API surface. |
| docs/user-guides/testing-your-config.md | Updates LLMResponse import to use the new top-level path. Correct and consistent. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["from nemoguardrails import …\n(top-level __init__.py)"] --> B["nemoguardrails.types\nChatMessage, FinishReason,\nLLMFramework, LLMModel,\nLLMResponse, LLMResponseChunk,\nRole, ToolCall,\nToolCallFunction, UsageInfo"]
A --> C["nemoguardrails.llm.frameworks\nregister_framework,\nset_default_framework,\nget_default_framework"]
A --> D["nemoguardrails.llm.providers\nregister_provider"]
E["from nemoguardrails.llm import …\n(llm __init__.py)"] --> B
E --> C
E --> D
B --> F["nemoguardrails.llm.frameworks.registry\n(canonical implementation)"]
C --> F
D --> G["nemoguardrails.llm.frameworks\n(delegates to active framework)"]
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
tests/test_types_exports.py:74-89
The suite has `test_direct_from_imports_top_level` and `test_direct_from_imports_llm_subpackage` that exercise direct star-import style for all type names, but there is no equivalent direct-import smoke test for the four registry functions. A `SyntaxError`-style import failure (e.g. a typo in a future refactor) would only be caught by the parametrized attribute/identity tests, not by a `from nemoguardrails import register_provider, …` style check. Adding a parallel block for the registry names keeps the coverage symmetrical.
```suggestion
def test_direct_from_imports_llm_subpackage():
from nemoguardrails.llm import ( # noqa: F401
ChatMessage,
FinishReason,
LLMFramework,
LLMModel,
LLMResponse,
LLMResponseChunk,
Role,
ToolCall,
ToolCallFunction,
UsageInfo,
)
def test_direct_from_imports_registry_top_level():
from nemoguardrails import ( # noqa: F401
get_default_framework,
register_framework,
register_provider,
set_default_framework,
)
def test_direct_from_imports_registry_llm_subpackage():
from nemoguardrails.llm import ( # noqa: F401
get_default_framework,
register_framework,
register_provider,
set_default_framework,
)
# Registry functions and the submodule that owns each one.
```
Reviews (2): Last reviewed commit: "feat(api): also re-export register_provi..." | Re-trigger Greptile
Documentation preview |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThis PR expands the public API surface of the nemoguardrails package, exposing LLM-related types and framework registry functions at both the top level and the nemoguardrails.llm subpackage. The changes include updating type module exports, re-exporting from package entry points, adding comprehensive validation tests, and updating documentation examples to use the new import paths. ChangesLLM Type API Expansion
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
tgasser-nv
left a comment
There was a problem hiding this comment.
Looks good, just need to add register_provider to the init() so we can import from nemoguards rather than nemoguards.llm.providers
Apply reviewer suggestion to extend the canonical-import-path work: register_provider was the one integrator-facing function that still required reaching into nemoguardrails.llm.providers, while its framework-level peers (register_framework, set_default_framework, get_default_framework) were already at top-level. Now an integrator writing a custom LLMModel reaches every symbol they need from `from nemoguardrails import ...`: the value types, the protocol, and the registration function. Collapses the two-line import in custom-llm-model.md to one. The existing nemoguardrails.llm.providers module remains the authoritative implementation site; the variants (register_chat_provider, register_llm_provider, get_provider_names, get_chat_provider_names, get_llm_provider_names) are not re-exported - register_provider is the canonical one, the others are either aliases or deprecated. Tests: extend REGISTRY_FUNCTIONS to a (name, canonical_module) tuple list so each function's same-object check resolves to its real owning module. 45 tests pass.
Description
Make
from nemoguardrails import ...the canonical user-facing path for the integrator-facing surface of v0.22:LLM types from
nemoguardrails.types(ChatMessage, FinishReason, LLMFramework, LLMModel, LLMResponse, LLMResponseChunk, Role, ToolCall, ToolCallFunction, UsageInfo) are re-exported from bothnemoguardrails(top-level) andnemoguardrails.llm.Framework registry functions from
nemoguardrails.llm.frameworks(register_framework, set_default_framework, get_default_framework) are also re-exported fromnemoguardrails.llm. They were already exported fromnemoguardrailstop-level.Custom LLM Framework, Custom LLM Model, and testing-your-config doc examples switch their import lines to the top-level form so the "integrator constructs value types and protocol classes" path uses one import statement.
nemoguardrails/types.pygains a module-level docstring documenting it as the stable public LLM interop surface, plus an explicit__all__listing the public names.Parametrized exports tests verify each name is exposed on every supported import path and resolves to the same canonical object.
Related Issue(s)
Checklist
Summary by CodeRabbit
Release Notes
New Features
Documentation