Tool-call parsing: Qwen3 native <tool_call> XML fallback in _parse (parser-agnostic, zero overhead when server converts properly)
This commit is contained in:
parent
7114564301
commit
3d16e9647a
@ -108,9 +108,25 @@ def _key_for(api_base: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _parse_text_tool_calls(text: str) -> list:
|
def _parse_text_tool_calls(text: str) -> list:
|
||||||
"""Extract [{"name":..,"arguments":{..}}] JSON from a text-protocol reply."""
|
"""Extract tool calls from a text reply. Handles both shapes:
|
||||||
|
- JSON array: [{"name":..,"arguments":{..}}]
|
||||||
|
- Qwen3 native XML: <tool_call>{"name":..,"arguments":{..}}</tool_call>
|
||||||
|
(for vLLM builds whose qwen3_xml parser doesn't convert to tool_calls)
|
||||||
|
"""
|
||||||
import re as _re
|
import re as _re
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for m in _re.finditer(r'<tool_call>\s*(\{.*?\})\s*</tool_call>', text, _re.S):
|
||||||
|
try:
|
||||||
|
obj = json.loads(m.group(1))
|
||||||
|
if isinstance(obj, dict) and obj.get('name'):
|
||||||
|
out.append({'id': '', 'type': 'function',
|
||||||
|
'function': {'name': obj['name'],
|
||||||
|
'arguments': json.dumps(obj.get('arguments', {}))}})
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
continue
|
||||||
|
if out:
|
||||||
|
return out
|
||||||
candidates = _re.findall(r'\[[\s\S]*?\]', text) or []
|
candidates = _re.findall(r'\[[\s\S]*?\]', text) or []
|
||||||
for cand in candidates:
|
for cand in candidates:
|
||||||
try:
|
try:
|
||||||
@ -196,7 +212,7 @@ class OpenAICompatible(ModelAdapter):
|
|||||||
msg = choice.get('message') or {}
|
msg = choice.get('message') or {}
|
||||||
calls = []
|
calls = []
|
||||||
raw_calls = list(msg.get('tool_calls') or [])
|
raw_calls = list(msg.get('tool_calls') or [])
|
||||||
if not raw_calls and self.extra.get('tools_mode') == 'text':
|
if not raw_calls:
|
||||||
raw_calls = _parse_text_tool_calls(msg.get('content') or '')
|
raw_calls = _parse_text_tool_calls(msg.get('content') or '')
|
||||||
for c in raw_calls:
|
for c in raw_calls:
|
||||||
fn = c.get('function') or {}
|
fn = c.get('function') or {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user