| 212 | |
| 213 | |
| 214 | def load_chat_template( |
| 215 | chat_template: Union[Path, str], |
| 216 | model_path: Path = None, |
| 217 | is_literal: bool = False, |
| 218 | ) -> Optional[str]: |
| 219 | if chat_template is None: |
| 220 | if model_path: |
| 221 | chat_template_file = os.path.join(model_path, "chat_template.jinja") |
| 222 | if os.path.exists(chat_template_file): |
| 223 | with open(chat_template_file) as f: |
| 224 | return f.read() |
| 225 | return None |
| 226 | if is_literal: |
| 227 | if isinstance(chat_template, Path): |
| 228 | raise TypeError("chat_template is expected to be read directly " "from its value") |
| 229 | |
| 230 | return chat_template |
| 231 | |
| 232 | try: |
| 233 | with open(chat_template) as f: |
| 234 | return f.read() |
| 235 | except OSError as e: |
| 236 | if isinstance(chat_template, Path): |
| 237 | raise |
| 238 | JINJA_CHARS = "{}\n" |
| 239 | if not any(c in chat_template for c in JINJA_CHARS): |
| 240 | msg = ( |
| 241 | f"The supplied chat template ({chat_template}) " |
| 242 | f"looks like a file path, but it failed to be " |
| 243 | f"opened. Reason: {e}" |
| 244 | ) |
| 245 | raise ValueError(msg) from e |
| 246 | |
| 247 | # If opening a file fails, set chat template to be args to |
| 248 | # ensure we decode so our escape are interpreted correctly |
| 249 | return load_chat_template(chat_template, is_literal=True) |
| 250 | |
| 251 | |
| 252 | def random_tool_call_id() -> str: |