Extract function_call blocks from model output. Handles 3 formats: 1. ```function_call\\n{...}\\n``` (standard) 2. function_call\\n{...} (without backticks) 3. Raw JSON with "name" + "args" keys Returns (clean_text, [{"name": ..., "args": ...}])
(text: str)
| 248 | |
| 249 | |
| 250 | def parse_google_function_calls(text: str) -> tuple: |
| 251 | """Extract function_call blocks from model output. |
| 252 | |
| 253 | Handles 3 formats: |
| 254 | 1. ```function_call\\n{...}\\n``` (standard) |
| 255 | 2. function_call\\n{...} (without backticks) |
| 256 | 3. Raw JSON with "name" + "args" keys |
| 257 | |
| 258 | Returns (clean_text, [{"name": ..., "args": ...}]) |
| 259 | """ |
| 260 | function_calls = [] |
| 261 | pattern1 = r'```function_call\s*\n(.*?)\n```' |
| 262 | pattern2 = r'(?:^|\n)function_call\s*\n(\{[^`]*?\})' |
| 263 | clean = text |
| 264 | for pattern in [pattern1, pattern2]: |
| 265 | for match in re.findall(pattern, clean, re.DOTALL): |
| 266 | try: |
| 267 | data = json.loads(match.strip()) |
| 268 | if "name" in data: |
| 269 | function_calls.append({ |
| 270 | "name": data["name"], |
| 271 | "args": data.get("args", data.get("arguments", {})), |
| 272 | }) |
| 273 | except (json.JSONDecodeError, KeyError): |
| 274 | pass |
| 275 | clean = re.sub(pattern, '', clean, flags=re.DOTALL).strip() |
| 276 | if not function_calls and clean.strip().startswith("{"): |
| 277 | try: |
| 278 | data = json.loads(clean.strip()) |
| 279 | if "name" in data and ("args" in data or "arguments" in data): |
| 280 | function_calls.append({ |
| 281 | "name": data["name"], |
| 282 | "args": data.get("args", data.get("arguments", {})), |
| 283 | }) |
| 284 | clean = "" |
| 285 | except (json.JSONDecodeError, KeyError): |
| 286 | pass |
| 287 | return clean, function_calls |
no outgoing calls
no test coverage detected