Fix LFM 2 tool parser. (#27614)

This commit is contained in:
Yi (Vincent) Zhong
2026-07-30 10:15:08 +00:00
committed by GitHub
parent fd86795107
commit 1f04eaab6a
@@ -37,6 +37,16 @@ from sglang.srt.function_call.utils import safe_ast_parse
logger = logging.getLogger(__name__)
_PYTHONIC_NAME_LITERALS = {
"True": True,
"False": False,
"None": None,
"true": True,
"false": False,
"null": None,
}
class Lfm2Detector(BaseFormatDetector):
"""
Detector for LFM2 (Liquid Foundation Model 2) function call format.
@@ -87,15 +97,12 @@ class Lfm2Detector(BaseFormatDetector):
elif isinstance(val, ast.Tuple):
return tuple(self._get_parameter_value(v) for v in val.elts)
elif isinstance(val, ast.Name):
# Handle True, False, None as names in older Python
if val.id == "True":
return True
elif val.id == "False":
return False
elif val.id == "None":
return None
else:
raise ValueError(f"Unsupported name reference: {val.id}")
# Python True/False/None are ast.Constant on modern Python, but
# accept their legacy node shape plus LFM2's JSON-literal spellings.
try:
return _PYTHONIC_NAME_LITERALS[val.id]
except KeyError:
raise ValueError(f"Unsupported name reference: {val.id}") from None
elif isinstance(val, ast.UnaryOp) and isinstance(val.op, ast.USub):
# Handle negative numbers like -5
inner = self._get_parameter_value(val.operand)
@@ -107,6 +114,19 @@ class Lfm2Detector(BaseFormatDetector):
f"Tool call arguments must be literals, got: {type(val).__name__}"
)
def _get_function_name(self, func: ast.AST) -> Optional[str]:
"""Extract a flat or dotted function name from a Pythonic call node."""
parts: List[str] = []
while isinstance(func, ast.Attribute):
parts.append(func.attr)
func = func.value
if not isinstance(func, ast.Name):
return None
parts.append(func.id)
return ".".join(reversed(parts))
def _parse_pythonic_call(
self, call: ast.Call, call_index: int, tool_indices: Dict[str, int]
) -> Optional[ToolCallItem]:
@@ -121,14 +141,13 @@ class Lfm2Detector(BaseFormatDetector):
Returns:
ToolCallItem if successful, None if the call should be skipped
"""
if not isinstance(call.func, ast.Name):
function_name = self._get_function_name(call.func)
if function_name is None:
logger.warning(
f"Tool call function must be a simple name, got: {type(call.func).__name__}"
f"Tool call function must be a name or dotted name, got: {type(call.func).__name__}"
)
return None
function_name = call.func.id
# Validate that the function exists in the tools
if function_name not in tool_indices:
logger.warning(