gary-boon Claude Opus 4.5 commited on
Commit
3d9d9ee
·
1 Parent(s): 3e80769

Remove mistral_common to fix dependency conflict

Browse files

- Remove mistral_common from requirements (conflicts with numpy/pydantic)
- Simplify prompt_formatter to use manual Mistral format
- Format: [INST] {system}\n\n{user} [/INST] (no <s>, tokenizer adds BOS)
- Keep recommended_temperature=0.15 for Devstral

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

Files changed (2) hide show
  1. backend/prompt_formatter.py +13 -62
  2. requirements.txt +0 -1
backend/prompt_formatter.py CHANGED
@@ -5,54 +5,12 @@ Handles formatting prompts appropriately for different model types:
5
  - Instruction models: System prompt + user message with chat template
6
  """
7
 
8
- from typing import Dict, Optional, Any, List
9
  import logging
10
 
11
  logger = logging.getLogger(__name__)
12
 
13
 
14
- def _try_mistral_common_format(messages: List[Dict[str, str]], model_name: str) -> Optional[str]:
15
- """
16
- Try to use mistral_common for proper Mistral/Devstral chat formatting.
17
- Returns None if mistral_common is not available or fails.
18
- """
19
- try:
20
- from mistral_common.protocol.instruct.messages import (
21
- SystemMessage, UserMessage
22
- )
23
- from mistral_common.protocol.instruct.request import ChatCompletionRequest
24
- from mistral_common.tokens.tokenizers.mistral import MistralTokenizer
25
-
26
- # Load the tokenizer from HF hub
27
- tokenizer = MistralTokenizer.from_hf_hub(model_name)
28
-
29
- # Build messages
30
- mistral_messages = []
31
- for msg in messages:
32
- if msg["role"] == "system":
33
- mistral_messages.append(SystemMessage(content=msg["content"]))
34
- elif msg["role"] == "user":
35
- mistral_messages.append(UserMessage(content=msg["content"]))
36
-
37
- # Encode to get token IDs
38
- request = ChatCompletionRequest(messages=mistral_messages)
39
- tokenized = tokenizer.encode_chat_completion(request)
40
-
41
- # Decode back to text for use with HF tokenizer
42
- # This gives us the properly formatted prompt string
43
- decoded = tokenizer.decode(tokenized.tokens)
44
-
45
- logger.info(f"Used mistral_common format for {model_name}")
46
- return decoded
47
-
48
- except ImportError:
49
- logger.warning("mistral_common not available, using fallback format")
50
- return None
51
- except Exception as e:
52
- logger.warning(f"mistral_common formatting failed: {e}, using fallback")
53
- return None
54
-
55
-
56
  class PromptFormatter:
57
  """
58
  Unified prompt formatting for different model types.
@@ -62,9 +20,9 @@ class PromptFormatter:
62
  - Model treats it as text to continue
63
 
64
  Instruction models (Devstral, instruct variants):
65
- - Use mistral_common for Mistral/Devstral models
66
- - Fallback to tokenizer's chat_template if available
67
- - Final fallback to manual Mistral format
68
  """
69
 
70
  def format(
@@ -110,9 +68,8 @@ class PromptFormatter:
110
  Format prompt for instruction-tuned models.
111
 
112
  Priority:
113
- 1. mistral_common for Mistral/Devstral models
114
- 2. Tokenizer's native chat_template
115
- 3. Manual Mistral format fallback
116
  """
117
  # Get system prompt (override > model default > generic fallback)
118
  system_prompt = system_prompt_override or model_config.get("system_prompt")
@@ -125,15 +82,7 @@ class PromptFormatter:
125
  {"role": "user", "content": prompt}
126
  ]
127
 
128
- # For Mistral/Devstral models, try mistral_common first
129
- architecture = model_config.get("architecture", "")
130
- hf_path = model_config.get("hf_path", "")
131
- if architecture == "mistral" or "mistral" in hf_path.lower():
132
- formatted = _try_mistral_common_format(messages, hf_path)
133
- if formatted:
134
- return formatted
135
-
136
- # Try tokenizer's native chat template
137
  if hasattr(tokenizer, 'chat_template') and tokenizer.chat_template is not None:
138
  try:
139
  formatted = tokenizer.apply_chat_template(
@@ -146,16 +95,18 @@ class PromptFormatter:
146
  except Exception as e:
147
  logger.warning(f"chat_template failed: {e}, using manual format")
148
 
149
- # Fallback: Manual Mistral/Llama format
150
- # Note: Don't include <s> as the tokenizer adds it during tokenization
151
  return self._manual_mistral_format(prompt, system_prompt)
152
 
153
  def _manual_mistral_format(self, prompt: str, system_prompt: str) -> str:
154
  """
155
- Manual Mistral instruction format as fallback.
156
 
157
  Format: [INST] {system}\n\n{user} [/INST]
158
- Note: <s> is NOT included as the tokenizer adds BOS automatically.
 
 
159
  """
160
  logger.info("Using manual Mistral instruction format")
161
  return f"[INST] {system_prompt}\n\n{prompt} [/INST]"
 
5
  - Instruction models: System prompt + user message with chat template
6
  """
7
 
8
+ from typing import Dict, Optional, Any
9
  import logging
10
 
11
  logger = logging.getLogger(__name__)
12
 
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  class PromptFormatter:
15
  """
16
  Unified prompt formatting for different model types.
 
20
  - Model treats it as text to continue
21
 
22
  Instruction models (Devstral, instruct variants):
23
+ - Wrap with system prompt + user message
24
+ - Use tokenizer's chat_template if available
25
+ - Fallback to manual Mistral format
26
  """
27
 
28
  def format(
 
68
  Format prompt for instruction-tuned models.
69
 
70
  Priority:
71
+ 1. Tokenizer's native chat_template (if available)
72
+ 2. Manual Mistral format fallback
 
73
  """
74
  # Get system prompt (override > model default > generic fallback)
75
  system_prompt = system_prompt_override or model_config.get("system_prompt")
 
82
  {"role": "user", "content": prompt}
83
  ]
84
 
85
+ # Try tokenizer's native chat template first
 
 
 
 
 
 
 
 
86
  if hasattr(tokenizer, 'chat_template') and tokenizer.chat_template is not None:
87
  try:
88
  formatted = tokenizer.apply_chat_template(
 
95
  except Exception as e:
96
  logger.warning(f"chat_template failed: {e}, using manual format")
97
 
98
+ # Fallback: Manual Mistral/Llama instruction format
99
+ # Note: We DON'T include <s> - the tokenizer adds BOS automatically
100
  return self._manual_mistral_format(prompt, system_prompt)
101
 
102
  def _manual_mistral_format(self, prompt: str, system_prompt: str) -> str:
103
  """
104
+ Manual Mistral instruction format.
105
 
106
  Format: [INST] {system}\n\n{user} [/INST]
107
+
108
+ Note: BOS token (<s>) is NOT included - the tokenizer adds it
109
+ automatically during tokenization with add_special_tokens=True (default).
110
  """
111
  logger.info("Using manual Mistral instruction format")
112
  return f"[INST] {system_prompt}\n\n{prompt} [/INST]"
requirements.txt CHANGED
@@ -10,7 +10,6 @@ pydantic==2.5.0
10
  torch>=2.3.0
11
  transformers>=4.44.0
12
  accelerate>=0.30.0
13
- mistral_common>=1.5.0 # Required for Devstral chat template formatting
14
 
15
  # Utilities
16
  numpy==1.24.3
 
10
  torch>=2.3.0
11
  transformers>=4.44.0
12
  accelerate>=0.30.0
 
13
 
14
  # Utilities
15
  numpy==1.24.3