{"record":{"id":"3c5ed3e077e43d54","repo":"zylon-ai/private-gpt","slug":"tokenizer-is-required-and-must-support-apply-chat","errorCode":null,"errorMessage":"Tokenizer is required and must support apply_chat_template: {tokenizer}","messagePattern":"Tokenizer is required and must support apply_chat_template: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/llm/prompt_styles/chat_template_prompt_style.py","lineNumber":39,"sourceCode":"\nlogger = logging.getLogger(__name__)\n\nChatTemplateContentFormat = Literal[\"string\", \"openai\"]\n\n_FALLBACK_USER_MESSAGE = {\"role\": \"user\", \"content\": \"\"}\n\n\nclass ChatTemplatePromptStyle(PromptStyleBase):\n    def __init__(\n        self,\n        tokenizer: TokenizerBase | None = None,\n        content_format: ChatTemplateContentFormat = \"string\",\n        *args: Any,\n        **kwargs: Any,\n    ) -> None:\n        super().__init__(*args, **kwargs)\n        if tokenizer is None or not hasattr(tokenizer, \"apply_chat_template\"):\n            raise ValueError(\n                f\"Tokenizer is required and must support apply_chat_template: {tokenizer}\"\n            )\n        self._tokenizer = tokenizer\n        self._content_format = content_format\n\n    def _messages_to_prompt(\n        self,\n        messages: Sequence[ChatMessage],\n        tools: Sequence[BaseTool] | None = None,\n        reasoning_effort: ReasoningEffort | None = None,\n        tokenize: bool = False,\n        **kwargs: Any,\n    ) -> PromptData:\n        reasoning_effort = reasoning_effort or ReasoningEffort.NONE\n        continue_final_message = (\n            bool(messages) and messages[-1].role == MessageRole.ASSISTANT\n        )\n        conversation = self._to_hf_messages(messages)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/llm/prompt_styles/chat_template_prompt_style.py#L21-L57","documentation":"ChatTemplatePromptStyle (the builtin 'chat' prompt style) builds prompts by calling tokenizer.apply_chat_template, so its constructor requires a tokenizer object that exposes that method. The constructor raises ValueError when tokenizer is None or when the supplied tokenizer lacks apply_chat_template (e.g. estimator or tiktoken tokenizers). This fails fast at wiring time instead of producing malformed prompts later.","triggerScenarios":"Calling ChatTemplatePromptStyle(tokenizer=None) or PromptStyleRegistry.get_prompt_style('chat', tokenizer=<obj without apply_chat_template>). Typically happens when llm.tokenizer_mode is 'estimator'/'tiktoken' but prompt_style is 'chat', or when the DI wiring never passes the tokenizer into the prompt style.","commonSituations":"Config mismatch: prompt_style='chat' combined with a tokenizer mode that does not yield an HF-style tokenizer; forgetting to pass the tokenizer when constructing the style manually in tests or custom components; switching a deployment from a local model to an estimator-based setup without changing prompt_style.","solutions":["Pass a tokenizer that implements apply_chat_template (e.g. HuggingFaceTokenizer.from_pretrained(...)) into ChatTemplatePromptStyle / get_prompt_style('chat', tokenizer=...).","Align config: if tokenizer_mode is 'estimator' or 'tiktoken', either switch tokenizer_mode to 'huggingface'/'chat' or choose a different prompt_style.","If wiring manually, construct the tokenizer first and pass it: style = PromptStyleRegistry.get_prompt_style('chat', tokenizer=tok)."],"exampleFix":"// before\nstyle = PromptStyleRegistry.get_prompt_style('chat', tokenizer=None)\n\n// after\nfrom private_gpt.components.llm.tokenizers.registry import TokenizerRegistry\ntok = TokenizerRegistry.get_tokenizer('huggingface', model_id='mistralai/Mistral-7B-Instruct-v0.3')\nstyle = PromptStyleRegistry.get_prompt_style('chat', tokenizer=tok)","handlingStrategy":"validation","validationCode":"from private_gpt.components.llm.prompt_styles.chat_template_prompt_style import ChatTemplatePromptStyle\n\ndef can_build_chat_style(tokenizer) -> bool:\n    return tokenizer is not None and hasattr(tokenizer, 'apply_chat_template')\n\nif not can_build_chat_style(tok):\n    raise ConfigurationError('prompt_style=chat requires an apply_chat_template-capable tokenizer')","typeGuard":"def is_chat_template_tokenizer(t: object) -> bool:\n    return t is not None and callable(getattr(t, 'apply_chat_template', None))","tryCatchPattern":null,"preventionTips":["Keep prompt_style='chat' paired only with tokenizer modes that produce HF-style tokenizers ('huggingface'/'chat').","Validate tokenizer capability at startup wiring, not per request.","Write a smoke test that constructs the prompt style with your production tokenizer config."],"tags":["configuration","tokenizer","prompt-style","validation"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}