Commit eecf7d43 authored by Your Name's avatar Your Name

Add ToolCallParser fallback for XML-style tool call parsing

- Added _parse_xml_style_tool_calls() method to parse XML format like:
  <tool><name>search</name><arguments>{...}</arguments></tool>
- Modified extract_tool_calls() to use XML parsing as fallback
- ToolCallParser now serves as fallback for all specific model parsers
  via ModelParserAdapter (QwenParser, DeepSeekParser, LlamaParser,
  MistralParser, ClaudeParser, CommandRParser, GemmaParser, GrokParser,
  PhiParser, ApexBig50Parser)
parent 10bb6085
...@@ -860,6 +860,37 @@ class ToolCallParser: ...@@ -860,6 +860,37 @@ class ToolCallParser:
self.tokenizer = tokenizer self.tokenizer = tokenizer
self.model_name = model_name self.model_name = model_name
def _parse_xml_style_tool_calls(self, text: str) -> List[Dict]:
"""Parse XML-style tool calls like <tool><name>...</name><arguments>...</arguments></tool>."""
tool_calls = []
# Pattern for <tool><name>...</name><arguments>...</arguments></tool>
pattern = r'<tool>\s*<name>(.*?)</name>\s*<arguments>(.*?)</arguments>\s*</tool>'
matches = re.findall(pattern, text, re.DOTALL | re.IGNORECASE)
for name, args_str in matches:
name = name.strip()
if not name:
continue
# Try to parse arguments as JSON
try:
args = json.loads(args_str.strip()) if args_str.strip() else {}
except json.JSONDecodeError:
# If not valid JSON, treat as empty object
args = {}
tool_calls.append({
"id": f"call_{uuid.uuid4().hex[:16]}",
"type": "function",
"function": {
"name": name,
"arguments": json.dumps(args)
}
})
return tool_calls
def set_model_name(self, model_name: str): def set_model_name(self, model_name: str):
"""Set the model name for model-specific parsing.""" """Set the model name for model-specific parsing."""
self.model_name = model_name self.model_name = model_name
...@@ -936,6 +967,12 @@ class ToolCallParser: ...@@ -936,6 +967,12 @@ class ToolCallParser:
except json.JSONDecodeError: except json.JSONDecodeError:
pass pass
# If no tool calls found yet, try XML-style parsing as fallback
if not tool_calls:
xml_tool_calls = self._parse_xml_style_tool_calls(text)
if xml_tool_calls:
tool_calls.extend(xml_tool_calls)
return tool_calls if tool_calls else None return tool_calls if tool_calls else None
def strip_tool_calls_from_content(self, text: str) -> str: def strip_tool_calls_from_content(self, text: str) -> str:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment