Skip to content

Commit 9df7af2

Browse files
Make uuid predictable in debug-mode
1 parent 466da04 commit 9df7af2

File tree

12 files changed

+40
-42
lines changed

12 files changed

+40
-42
lines changed

nemoguardrails/actions/v2_x/generation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
remove_action_intent_identifiers,
3535
)
3636
from nemoguardrails.colang.v2_x.lang.colang_ast import Flow
37-
from nemoguardrails.colang.v2_x.lang.utils import new_uuid
3837
from nemoguardrails.colang.v2_x.runtime.errors import LlmResponseError
3938
from nemoguardrails.colang.v2_x.runtime.flows import ActionEvent, InternalEvent
4039
from nemoguardrails.colang.v2_x.runtime.statemachine import (
@@ -49,6 +48,7 @@
4948
from nemoguardrails.llm.filters import colang
5049
from nemoguardrails.llm.params import llm_params
5150
from nemoguardrails.llm.types import Task
51+
from nemoguardrails.utils import new_uuid
5252

5353
log = logging.getLogger(__name__)
5454

nemoguardrails/cli/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from nemoguardrails.eval.cli.simplify_formatter import SimplifyFormatter
2929
from nemoguardrails.logging.verbose import set_verbose
3030
from nemoguardrails.server import api
31+
from nemoguardrails.utils import init_random_seed
3132

3233
app = typer.Typer()
3334
app.add_typer(evaluate.app, name="evaluate", short_help="Run an evaluation task.")
@@ -83,6 +84,9 @@ def chat(
8384
# This means that the user doesn't have to use both options at the same time.
8485
verbose = verbose or verbose_no_llm or len(debug_level) > 0
8586

87+
if len(debug_level) > 0 or os.environ.get("DEBUG_MODE"):
88+
init_random_seed(0)
89+
8690
if verbose:
8791
set_verbose(
8892
True,

nemoguardrails/cli/chat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from nemoguardrails.logging import verbose
2727
from nemoguardrails.logging.verbose import console
2828
from nemoguardrails.streaming import StreamingHandler
29-
from nemoguardrails.utils import new_event_dict, new_uid
29+
from nemoguardrails.utils import new_event_dict, new_uuid
3030

3131
os.environ["TOKENIZERS_PARALLELISM"] = "false"
3232

@@ -489,7 +489,7 @@ async def _process_input_events():
489489
new_event_dict(
490490
"UtteranceUserActionFinished",
491491
final_transcript=user_message,
492-
action_uid=new_uid(),
492+
action_uid=new_uuid(),
493493
is_success=True,
494494
)
495495
]

nemoguardrails/colang/v1_0/lang/utils.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,14 +382,6 @@ def parse_package_name(text):
382382
return package_name
383383

384384

385-
def new_uuid() -> str:
386-
"""Helper to generate new UUID v4.
387-
388-
In testing mode, it will generate a predictable set of UUIDs to help debugging.
389-
"""
390-
return str(uuid.uuid4())
391-
392-
393385
def string_hash(s):
394386
"""A simple string hash with an equivalent implementation in javascript.
395387

nemoguardrails/colang/v2_x/lang/utils.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,10 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
import uuid
1716
from dataclasses import asdict, is_dataclass
1817
from typing import Any
1918

2019

21-
def new_uuid() -> str:
22-
"""Helper to generate new UUID v4.
23-
24-
In testing mode, it will generate a predictable set of UUIDs to help debugging.
25-
"""
26-
return str(uuid.uuid4())
27-
28-
2920
def dataclass_to_dict(obj: Any) -> Any:
3021
if is_dataclass(obj):
3122
return {k: dataclass_to_dict(v) for k, v in asdict(obj).items()}

nemoguardrails/colang/v2_x/runtime/eval.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from nemoguardrails.colang.v2_x.runtime.flows import FlowState, State
2929
from nemoguardrails.colang.v2_x.runtime.utils import AttributeDict
3030
from nemoguardrails.eval.cli.simplify_formatter import SimplifyFormatter
31-
from nemoguardrails.utils import new_uid
31+
from nemoguardrails.utils import new_uuid
3232

3333
log = logging.getLogger(__name__)
3434

@@ -143,7 +143,7 @@ def eval_expression(expr: str, context: dict) -> Any:
143143
"regex": _create_regex,
144144
"search": _regex_search,
145145
"find_all": _regex_findall,
146-
"uid": new_uid,
146+
"uid": new_uuid,
147147
"pretty_str": _pretty_str,
148148
"escape": _escape_string,
149149
"is_int": _is_int,

nemoguardrails/colang/v2_x/runtime/flows.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
)
3535
from nemoguardrails.colang.v2_x.runtime.errors import ColangSyntaxError
3636
from nemoguardrails.colang.v2_x.runtime.utils import new_readable_uid
37-
from nemoguardrails.utils import new_uid
37+
from nemoguardrails.utils import new_uuid
3838

3939
log = logging.getLogger(__name__)
4040

@@ -197,7 +197,7 @@ def __init__(
197197
self, name: str, arguments: Dict[str, Any], flow_uid: Optional[str] = None
198198
) -> None:
199199
# The unique id of the action
200-
self.uid: str = new_uid()
200+
self.uid: str = new_uuid()
201201

202202
# Name of the action
203203
self.name = name

nemoguardrails/colang/v2_x/runtime/statemachine.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,10 @@
7171
State,
7272
)
7373
from nemoguardrails.colang.v2_x.runtime.utils import new_readable_uid
74-
from nemoguardrails.utils import console, new_event_dict, new_uid
74+
from nemoguardrails.utils import console, new_event_dict, new_uuid
7575

7676
log = logging.getLogger(__name__)
7777

78-
random_seed = int(time.time())
79-
8078

8179
def initialize_state(state: State) -> None:
8280
"""
@@ -126,13 +124,13 @@ def create_flow_instance(
126124
"""Create a new flow instance that can be added."""
127125
loop_uid: Optional[str] = None
128126
if flow_config.loop_type == InteractionLoopType.NEW:
129-
loop_uid = new_uid()
127+
loop_uid = new_uuid()
130128
elif flow_config.loop_type == InteractionLoopType.NAMED:
131129
assert flow_config.loop_id is not None
132130
loop_uid = flow_config.loop_id
133131
# For type InteractionLoopType.PARENT we keep it None to infer loop_id at run_time from parent
134132

135-
head_uid = new_uid()
133+
head_uid = new_uuid()
136134
flow_state = FlowState(
137135
uid=flow_instance_uid,
138136
flow_id=flow_config.id,
@@ -1068,7 +1066,7 @@ def slide(
10681066
flow_state.head_fork_uids[element.fork_uid] = head.uid
10691067
# We create the new child heads
10701068
for _idx, label in enumerate(element.labels):
1071-
parent_fork_head_uid = new_uid()
1069+
parent_fork_head_uid = new_uuid()
10721070
pos = flow_config.element_labels[label]
10731071
new_head = FlowHead(
10741072
uid=parent_fork_head_uid,
@@ -1354,7 +1352,7 @@ def _start_flow(state: State, flow_state: FlowState, event_arguments: dict) -> N
13541352
loop_id = state.flow_configs[flow_state.flow_id].loop_id
13551353
if loop_id is not None:
13561354
if loop_id == "NEW":
1357-
flow_state.loop_id = new_uid()
1355+
flow_state.loop_id = new_uuid()
13581356
else:
13591357
flow_state.loop_id = loop_id
13601358
else:
@@ -1543,7 +1541,7 @@ def _finish_flow(
15431541
# TODO: Refactor this to use event based mechanics (START_FLOW)
15441542
if flow_state.flow_id == "main":
15451543
# Find an active head
1546-
head_uid = new_uid()
1544+
head_uid = new_uuid()
15471545
new_head = FlowHead(
15481546
uid=head_uid,
15491547
flow_state_uid=flow_state.uid,

nemoguardrails/library/activefence/actions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import aiohttp
2121

2222
from nemoguardrails.actions import action
23-
from nemoguardrails.colang.v1_0.lang.utils import new_uuid
23+
from nemoguardrails.utils import new_uuid
2424

2525
log = logging.getLogger(__name__)
2626

nemoguardrails/rails/llm/llmrails.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from nemoguardrails.colang import parse_colang_file
3333
from nemoguardrails.colang.v1_0.runtime.flows import compute_context
3434
from nemoguardrails.colang.v1_0.runtime.runtime import Runtime, RuntimeV1_0
35-
from nemoguardrails.colang.v2_x.lang.utils import new_uuid
3635
from nemoguardrails.colang.v2_x.runtime.flows import Action, State
3736
from nemoguardrails.colang.v2_x.runtime.runtime import RuntimeV2_x
3837
from nemoguardrails.colang.v2_x.runtime.serialization import (
@@ -62,7 +61,7 @@
6261
)
6362
from nemoguardrails.rails.llm.utils import get_history_cache_key
6463
from nemoguardrails.streaming import StreamingHandler
65-
from nemoguardrails.utils import get_or_create_event_loop, new_event_dict
64+
from nemoguardrails.utils import get_or_create_event_loop, new_event_dict, new_uuid
6665

6766
log = logging.getLogger(__name__)
6867

nemoguardrails/streaming.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from langchain.schema.messages import AIMessageChunk
2424
from langchain.schema.output import ChatGenerationChunk, GenerationChunk, LLMResult
2525

26-
from nemoguardrails.colang.v1_0.lang.utils import new_uuid
26+
from nemoguardrails.utils import new_uuid
2727

2828
log = logging.getLogger(__name__)
2929

nemoguardrails/utils.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,37 @@
1717
import importlib.resources as pkg_resources
1818
import json
1919
import os
20+
import random
2021
import uuid
2122
from collections import namedtuple
2223
from datetime import datetime, timezone
2324
from enum import Enum
24-
from typing import Any, Dict, List, Tuple, Union
25+
from typing import Any, Dict, Tuple
2526

2627
import yaml
2728
from rich.console import Console
2829

2930
# Global console object to be used throughout the code base.
3031
console = Console()
3132

33+
secure_random = random.SystemRandom()
3234

33-
def new_uid() -> str:
34-
"""Helper to create a new UID."""
3535

36-
return str(uuid.uuid4())
36+
def init_random_seed(seed: int) -> None:
37+
"""Init random generator with seed."""
38+
global secure_random
39+
random.seed(seed)
40+
secure_random = random
41+
42+
43+
def new_uuid() -> str:
44+
"""Helper to generate new UUID v4.
45+
46+
In testing mode, it will generate a predictable set of UUIDs to help debugging if random seed was set dependent on
47+
the environment variable DEBUG_MODE.
48+
"""
49+
random_bits = secure_random.getrandbits(128)
50+
return str(uuid.UUID(int=random_bits, version=4))
3751

3852

3953
# Very basic event validation - will be replaced by validation based on pydantic models
@@ -134,7 +148,7 @@ def _update_action_properties(event_dict: Dict[str, Any]) -> None:
134148
event_dict["action_started_at"] = datetime.now(timezone.utc).isoformat()
135149
elif "Start" in event_dict["type"]:
136150
if "action_uid" not in event_dict:
137-
event_dict["action_uid"] = new_uid()
151+
event_dict["action_uid"] = new_uuid()
138152
elif "Updated" in event_dict["type"]:
139153
event_dict["action_updated_at"] = datetime.now(timezone.utc).isoformat()
140154
elif "Finished" in event_dict["type"]:
@@ -166,7 +180,7 @@ def new_event_dict(event_type: str, **payload) -> Dict[str, Any]:
166180

167181
event: Dict[str, Any] = {
168182
"type": event_type,
169-
"uid": new_uid(),
183+
"uid": new_uuid(),
170184
"event_created_at": datetime.now(timezone.utc).isoformat(),
171185
"source_uid": "NeMoGuardrails",
172186
}

0 commit comments

Comments
 (0)