Skip to content

Conversation

tgasser-nv
Copy link
Collaborator

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

Description (generated in Cursor)

Type Fixes Summary for nemoguardrails/tracing/ Directory

Overview

Fixed type errors across 3 files in the tracing module based on commit e939b0a. All changes maintain backward compatibility and preserve existing functionality.

Fixes by Risk Level (Most Risky First)

🔴 HIGH RISK - tracer.py (lines 69-71)

Original Error: Argument of type "GenerationLog | None" cannot be assigned to parameter "generation_log" of type "GenerationLog"

Fix: Added explicit null check with Exception

# At this point generation_log should not be None since it comes from self._generation_log
if generation_log is None:
    raise Exception("Can't generate interaction log without Generation log")

Downside: Changes runtime behavior - now throws exception instead of potentially passing None to downstream function. However, this makes the error explicit rather than allowing undefined behavior.


🟡 MEDIUM RISK - span_extractors.py (lines 222-231)

Original Errors: Multiple Cannot access attribute "error" for class "ExecutedAction" errors

Fix: Replaced dynamic error attribute access with explicit None values and added TODO comment

# TODO: There is no error field in ExecutedAction. The fields below are defined on BaseSpan but
#  will never be set if using an ActivatedRail object to populate an ActivatedRail object.
error=None,
error_type=None,
error_message=None,

Downside: Loss of potential future error information - if ExecutedAction gains an error field in the future, this code won't capture it. However, the TODO comment documents the intentional design decision.


🟢 LOW RISK - span_extractors.py (lines 62, 168, 170)

Original Errors:

  • Line 62: Type "List[SpanLegacy]" is not assignable to return type "List[SpanOpentelemetry | SpanLegacy]"
  • Line 168: Return type annotation mismatch with TypedSpan
  • Line 170: Local variable type mismatch

Fix: Updated type annotations to use consistent Union types

# SpanExtractorV1
spans: List[Union[SpanLegacy, SpanOpentelemetry]] = []

# SpanExtractorV2  
def extract_spans(...) -> List[Union[SpanLegacy, SpanOpentelemetry]]:
spans: List[Union[SpanLegacy, SpanOpentelemetry]] = []

Downside: None - purely cosmetic type annotation changes with no runtime impact.


🟢 LOW RISK - interaction_types.py (line 81)

Original Error: Argument of type "List[dict[Unknown, Unknown]] | None" cannot be assigned to parameter "events" of type "List[dict[Unknown, Unknown]]"

Fix: Added null coalescing operator

events=generation_log.internal_events or [],

Downside: None - safe fallback to empty list when None, maintains existing behavior expectations.

Files Changed

  • nemoguardrails/tracing/interaction_types.py (1 line changed)
  • nemoguardrails/tracing/span_extractors.py (22 lines changed, 14 deletions, 8 additions)
  • nemoguardrails/tracing/tracer.py (4 lines added)

All fixes preserve existing functionality while making the code fully type-safe.

Test Plan

Type-checking

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

Unit-tests

$ poetry run pytest -n4 tests
============================================= 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
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
4 workers [1440 items]
s.ss.ss..s..........ss.................................................................................. [  7%]
.......s...................................................................................ss........... [ 14%]
.....................................................ss.......s.........ss.............................. [ 21%]
..................................ss......s....................ssssssss.ssssssssss.....ssss.s........... [ 28%]
...................................s...............s.................ssss.........................ssssss [ 36%]
ss..............sss........ss...ss..........................s........................................... [ 43%]
..........................................................................................s............. [ 50%]
.........................sssssssss........ss............................................................ [ 57%]
............................................................................................ssssssss.... [ 65%]
...........................sssssssssssss.......................s...............................s........ [ 72%]
........................................................................................................ [ 79%]
........................................................................................................ [ 86%]
........................................................................................................ [ 93%]
.................s......................................................................                 [100%]
====================================== 1340 passed, 100 skipped in 49.42s ======================================

Local CLI check

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

> Hello!
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.

Before 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 both helpful and entertaining.

So, 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 burnn a house down?
I'm sorry, I can't respond to that.

Related Issue(s)

Top-level PR to merge into before develop-branch merge: #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.

Copy link
Member

@trebedea trebedea left a comment

Choose a reason for hiding this comment

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

Minor comments only on my side.

if hasattr(action, "error") and action.error
else None
),
# TODO: There is no error field in ExecutedAction. The fields below are defined on BaseSpan but
Copy link
Member

Choose a reason for hiding this comment

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

Not sure here - maybe @Pouyanpi can provide some feedback quicker than me.

id=interaction_output.id,
activated_rails=generation_log.activated_rails,
events=generation_log.internal_events,
events=generation_log.internal_events or [],
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering why Pyright is complaining about this as events is default factory of List

Copy link
Collaborator

@Pouyanpi Pouyanpi left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this @tgasser-nv 👍🏻

@tgasser-nv tgasser-nv changed the base branch from chore/type-clean-guardrails to develop September 22, 2025 21:30
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.

3 participants