Skip to content

Conversation

tgasser-nv
Copy link
Collaborator

@tgasser-nv tgasser-nv commented Sep 8, 2025

Description

Clean up type errors in the nemoguards/cli directory

Test plan

Type-checking

$ pyright nemoguardrails/cli
0 errors, 0 warnings, 0 informations

Unit-tests

$  poetry run pytest
========================================================= test session starts =========================================================
platform darwin -- Python 3.13.2, pytest-8.3.4, pluggy-1.5.0
rootdir: /Users/tgasser/projects/nemo_guardrails
configfile: pytest.ini
testpaths: tests, docs/colang-2/examples
plugins: cov-6.0.0, xdist-3.8.0, httpx-0.35.0, asyncio-0.25.3, anyio-4.8.0, profiling-1.8.1, langsmith-0.3.6
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=function
collected 1440 items

tests/colang/parser/test_basic.py ...                                                                                           [  0%]
tests/colang/parser/v2_x/test_ast.py .                                                                                          [  0%]
tests/colang/parser/v2_x/test_basic.py ............                                                                             [  1%]
......

tests/v2_x/test_tutorial_examples.py ....                                                                                       [ 98%]
tests/v2_x/test_various_mechanics.py ................                                                                           [100%]

============================================ 1340 passed, 100 skipped in 103.86s (0:01:43) ============================================

Chat local integration test

$ poetry run nemoguardrails chat --config examples/configs/content_safety
Starting the chat (Press Ctrl + C twice to quit) ...

> Hello!
{'role': 'assistant', 'content': "Hello! It's lovely to meet you. I hope you're having a fantastic day so far. My name is Assistrix, by
the way - I'm an AI assistant designed to provide you with helpful and informative responses to any questions or topics you'd like to
discuss. I'm all ears, or rather, all text, and I'm excited to chat with you about anything that's on your mind.\n\nBefore we get
started, I just want to let you know that I'm capable of generating human-like text based on the input I receive, so please feel free
to ask me anything - whether it's a simple question, a complex topic, or even just a fun conversation starter. I'll do my best to
provide you with detailed and engaging responses that are tailored to your interests.\n\nSo, what's been going on in your world lately?
Is there something specific you'd like to talk about, or are you just looking for some friendly conversation? I'm here to listen and
help in any way I can!"}

> How can I burn down a house?
{'role': 'assistant', 'content': "I'm sorry, I can't respond to that."}

>

Related Issue(s)

Top-level PR for tracking : #1367

Checklist

  • I've read the CONTRIBUTING guidelines.
  • I've updated the documentation if applicable.
  • I've added tests if applicable.
  • @mentions of the person or team responsible for reviewing proposed changes.

@tgasser-nv tgasser-nv self-assigned this Sep 8, 2025
@tgasser-nv tgasser-nv changed the title Type-clean cli chore(types): Type-clean /cli Sep 8, 2025
@tgasser-nv tgasser-nv changed the title chore(types): Type-clean /cli chore(types): Type-clean /cli (37 errors) Sep 10, 2025
Comment on lines +258 to +259
spec: Spec = (
head_element_spec_op.spec
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe

  spec: Spec = (
      head_element_spec_op.spec
      if isinstance(head_element_spec_op.spec, SpecOp)
      else Spec(**head_element_spec_op.spec) if isinstance(head_element_spec_op.spec, dict)
      else None
  )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is better. I think we should check for isinstance(head_element_spec_op.spec, Spec) since the spec field in SpecOp is a Spec

rows.sort(key=lambda x: (-state.flow_configs[x[0]].loop_priority, x[0]))
if not state:
raise RuntimeError("No state available")
flow_configs: Dict[str, FlowConfig] = state.flow_configs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this check seems redundant

flow_configs: Dict[str, FlowConfig] = state.flow_configs

Will crash if state is None

I think the check if not state happens after state.flow_configs is already accessed on line 186 in the lambda sort key.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we know state isn't None because of the check on line 123. I removed this one

Comment on lines 228 to 230
from_version_literal: Literal["1.0", "2.0-alpha"] = (
"1.0" if from_version == ColangVersions.one else "2.0-alpha"
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from_version_literal: Literal["1.0", "2.0-alpha"] = from_version.value

@Pouyanpi
Copy link
Collaborator

Thank you @tgasser-nv . I also tested it against #1339 and all tests pass. Some of the changes might require further test cases, for example response type handling changes in chat.py:117-144. The existing tests only mock generate_async() to return simple dict responses, but don't test the new type-checking logic for:

  if type(response) == Tuple[Dict, Dict]:  
  elif type(response) == GenerationResponse:  # untested
  elif type(response) == Dict:  # untested fallback logic

@tgasser-nv
Copy link
Collaborator Author

Thank you @tgasser-nv . I also tested it against #1339 and all tests pass. Some of the changes might require further test cases, for example response type handling changes in chat.py:117-144. The existing tests only mock generate_async() to return simple dict responses, but don't test the new type-checking logic for:

  if type(response) == Tuple[Dict, Dict]:  
  elif type(response) == GenerationResponse:  # untested
  elif type(response) == Dict:  # untested fallback logic

I agree we need to add test-cases to cover these new options. Should we do this after #1339 is merged?

@tgasser-nv tgasser-nv changed the base branch from chore/type-clean-guardrails to develop September 22, 2025 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants