mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-24 12:01:54 +00:00
fix(core): resolve mermaid node id collisions when special chars are used (#32857)
### Description * Replace the Mermaid graph node label escaping logic (`_escape_node_label`) with `_to_safe_id`, which converts a string into a unique, Mermaid-compatible node id. Ensures nodes with special characters always render correctly. **Before** * Invalid characters (e.g. `开`) replaced with `_`. Causes collisions between nodes with names that are the same length and contain all non-safe characters: ```python _escape_node_label("开") # '_' _escape_node_label("始") # '_' same as above, but different character passed in. not a unique mapping. ``` **After** ```python _to_safe_id("开") # \5f00 _to_safe_id("始") # \59cb unique! ``` ### Tests * Rename `test_graph_mermaid_escape_node_label()` to `test_graph_mermaid_to_safe_id()` and update function logic to use `_to_safe_id` * Add `test_graph_mermaid_special_chars()` ### Issue Fixes langchain-ai/langgraph#6036
This commit is contained in:
committed by
GitHub
parent
9cc85387d1
commit
15d558ff16
@@ -6,6 +6,7 @@ import asyncio
|
||||
import base64
|
||||
import random
|
||||
import re
|
||||
import string
|
||||
import time
|
||||
from dataclasses import asdict
|
||||
from pathlib import Path
|
||||
@@ -148,7 +149,7 @@ def draw_mermaid(
|
||||
+ "</em></small>"
|
||||
)
|
||||
node_label = format_dict.get(key, format_dict[default_class_label]).format(
|
||||
_escape_node_label(key), label
|
||||
_to_safe_id(key), label
|
||||
)
|
||||
return f"{indent}{node_label}\n"
|
||||
|
||||
@@ -211,8 +212,7 @@ def draw_mermaid(
|
||||
edge_label = " -.-> " if edge.conditional else " --> "
|
||||
|
||||
mermaid_graph += (
|
||||
f"\t{_escape_node_label(source)}{edge_label}"
|
||||
f"{_escape_node_label(target)};\n"
|
||||
f"\t{_to_safe_id(source)}{edge_label}{_to_safe_id(target)};\n"
|
||||
)
|
||||
|
||||
# Recursively add nested subgraphs
|
||||
@@ -256,9 +256,18 @@ def draw_mermaid(
|
||||
return mermaid_graph
|
||||
|
||||
|
||||
def _escape_node_label(node_label: str) -> str:
|
||||
"""Escapes the node label for Mermaid syntax."""
|
||||
return re.sub(r"[^a-zA-Z-_0-9]", "_", node_label)
|
||||
def _to_safe_id(label: str) -> str:
|
||||
"""Convert a string into a Mermaid-compatible node id.
|
||||
|
||||
Keep [a-zA-Z0-9_-] characters unchanged.
|
||||
Map every other character -> backslash + lowercase hex codepoint.
|
||||
|
||||
Result is guaranteed to be unique and Mermaid-compatible,
|
||||
so nodes with special characters always render correctly.
|
||||
"""
|
||||
allowed = string.ascii_letters + string.digits + "_-"
|
||||
out = [ch if ch in allowed else "\\" + format(ord(ch), "x") for ch in label]
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def _generate_mermaid_graph_styles(node_colors: NodeStyles) -> str:
|
||||
|
Reference in New Issue
Block a user