internlm/internlm3-8b-instruct
7
1"""This script refers to the dialogue example of streamlit, the interactive2generation code of chatglm2 and transformers.3 4We mainly modified part of the code logic to adapt to the5generation of our model.6Please refer to these links below for more information:7 1. streamlit chat example:8 https://docs.streamlit.io/knowledge-base/tutorials/build-conversational-apps9 2. chatglm2:10 https://github.com/THUDM/ChatGLM2-6B11 3. transformers:12 https://github.com/huggingface/transformers13Please run with the command `streamlit run path/to/web_demo.py14 --server.address=0.0.0.0 --server.port 7860`.15Using `python path/to/web_demo.py` may cause unknown problems.16"""17 18# isort: skip_file19import copy20import re21import warnings22from dataclasses import asdict, dataclass23from typing import Callable, List, Optional24 25import streamlit as st26import torch27from torch import nn28 29from transformers.generation.utils import LogitsProcessorList30from transformers.utils import logging31 32from transformers import AutoTokenizer, AutoModelForCausalLM # isort: skip33 34logger = logging.get_logger(__name__)35st.set_page_config(layout='wide')36 37 38@dataclass39class GenerationConfig:40 # this config is used for chat to provide more diversity41 max_length: int = 3276842 top_p: float = 0.843 temperature: float = 0.844 do_sample: bool = True45 repetition_penalty: float = 1.00546 47 48@torch.inference_mode()49def generate_interactive(50 model,51 tokenizer,52 prompt,53 generation_config: Optional[GenerationConfig] = None,54 logits_processor: Optional[LogitsProcessorList] = None,55 prefix_allowed_tokens_fn: Optional[Callable[[int, torch.Tensor], List[int]]] = None,56 additional_eos_token_id: Optional[int] = None,57 **kwargs,58):59 inputs = tokenizer([prompt], padding=True, return_tensors='pt')60 input_length = len(inputs['input_ids'][0])61 for k, v in inputs.items():62 inputs[k] = v.to(model.device)63 input_ids = inputs['input_ids']64 _, input_ids_seq_length = input_ids.shape[0], input_ids.shape[-1]65 if generation_config is None:66 generation_config = model.generation_config67 generation_config = copy.deepcopy(generation_config)68 generation_config._eos_token_tensor = generation_config.eos_token_id69 model_kwargs = generation_config.update(**kwargs)70 if generation_config.temperature == 0.0:71 generation_config.do_sample = False72 eos_token_id = generation_config.eos_token_id73 if isinstance(eos_token_id, int):74 eos_token_id = [eos_token_id]75 if additional_eos_token_id is not None:76 eos_token_id.append(additional_eos_token_id)77 has_default_max_length = kwargs.get('max_length') is None and generation_config.max_length is not None78 if has_default_max_length and generation_config.max_new_tokens is None:79 warnings.warn(80 f"Using 'max_length''s default \81 ({repr(generation_config.max_length)}) \82 to control the generation length. "83 'This behaviour is deprecated and will be removed from the \84 config in v5 of Transformers -- we'85 ' recommend using `max_new_tokens` to control the maximum \86 length of the generation.',87 UserWarning,88 )89 elif generation_config.max_new_tokens is not None:90 generation_config.max_length = generation_config.max_new_tokens + input_ids_seq_length91 if not has_default_max_length:92 logger.warn( # pylint: disable=W490293 f"Both 'max_new_tokens' (={generation_config.max_new_tokens}) "94 f"and 'max_length'(={generation_config.max_length}) seem to "95 "have been set. 'max_new_tokens' will take precedence. "96 'Please refer to the documentation for more information. '97 '(https://huggingface.co/docs/transformers/main/'98 'en/main_classes/text_generation)',99 UserWarning,100 )101 102 if input_ids_seq_length >= generation_config.max_length:103 input_ids_string = 'input_ids'104 logger.warning(105 f'Input length of {input_ids_string} is {input_ids_seq_length}, '106 f"but 'max_length' is set to {generation_config.max_length}. "107 'This can lead to unexpected behavior. You should consider'108 " increasing 'max_new_tokens'."109 )110 111 # 2. Set generation parameters if not already defined112 logits_processor = logits_processor if logits_processor is not None else LogitsProcessorList()113 logits_processor = model._get_logits_processor(114 generation_config=generation_config,115 input_ids_seq_length=input_ids_seq_length,116 encoder_input_ids=input_ids,117 prefix_allowed_tokens_fn=prefix_allowed_tokens_fn,118 logits_processor=logits_processor,119 )120 unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)121 while True:122 model_inputs = model.prepare_inputs_for_generation(input_ids, **model_kwargs)123 # forward pass to get next token124 outputs = model(125 **model_inputs,126 return_dict=True,127 output_attentions=False,128 output_hidden_states=False,129 )130 131 next_token_logits = outputs.logits[:, -1, :]132 133 # pre-process distribution134 next_token_scores = logits_processor(input_ids, next_token_logits)135 136 # sample137 probs = nn.functional.softmax(next_token_scores, dim=-1)138 if generation_config.do_sample:139 next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)140 else:141 next_tokens = torch.argmax(probs, dim=-1)142 143 # update generated ids, model inputs, and length for next step144 input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)145 unfinished_sequences = unfinished_sequences.mul((min(next_tokens != i for i in eos_token_id)).long())146 147 output_token_ids = input_ids[0].cpu().tolist()148 output_token_ids = output_token_ids[input_length:]149 for each_eos_token_id in eos_token_id:150 if output_token_ids[-1] == each_eos_token_id:151 output_token_ids = output_token_ids[:-1]152 response = tokenizer.decode(output_token_ids)153 154 yield response155 # stop when each sentence is finished156 # or if we exceed the maximum length157 if unfinished_sequences.max() == 0:158 break159 160 161def on_btn_click():162 del st.session_state.messages163 del st.session_state.deepthink_messages164 165 166def postprocess(text, add_prefix=True, deepthink=False):167 text = re.sub(r'\\\(|\\\)', r'$', text)168 text = re.sub(r'\\\[|\\\]', r'$$', text)169 if add_prefix:170 text = (':red[[Deep Thinking]]\n\n' if deepthink else ':blue[[Normal Response]]\n\n') + text171 return text172 173 174@st.cache_resource175def load_model():176 model_path = 'internlm/internlm3-8b-instruct'177 model = AutoModelForCausalLM.from_pretrained(178 model_path, trust_remote_code=True, device_map='auto', torch_dtype=torch.bfloat16179 )180 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)181 return model, tokenizer182 183 184def prepare_generation_config():185 with st.sidebar:186 max_length = st.slider('Max Length', min_value=8, max_value=32768, value=32768)187 top_p = st.slider('Top P', 0.0, 1.0, 0.8, step=0.01)188 temperature = st.slider('Temperature', 0.0, 1.0, 0.7, step=0.01)189 radio = st.radio('Inference Mode', ['Normal Response', 'Deep Thinking'], key='mode')190 st.button('Clear Chat History', on_click=on_btn_click)191 192 st.session_state['inference_mode'] = radio193 generation_config = GenerationConfig(max_length=max_length, top_p=top_p, temperature=temperature)194 195 return generation_config196 197 198user_prompt = '<|im_start|>user\n{user}<|im_end|>\n'199robot_prompt = '<|im_start|>assistant\n{robot}<|im_end|>\n'200cur_query_prompt = '<|im_start|>user\n{user}<|im_end|>\n\201 <|im_start|>assistant\n'202 203 204def combine_history(prompt, deepthink=False, start=0, stop=None):205 if stop is None:206 stop = len(st.session_state.messages)207 elif stop < 0:208 stop = len(st.session_state.messages) + stop209 messages = []210 for idx in range(start, stop):211 message, deepthink_message = st.session_state.messages[idx], st.session_state.deepthink_messages[idx]212 if deepthink:213 if deepthink_message['content'] is not None:214 messages.append(deepthink_message)215 else:216 messages.append(message)217 else:218 if message['content'] is not None:219 messages.append(message)220 else:221 messages.append(deepthink_message)222 meta_instruction = (223 'You are InternLM (书生·浦语), a helpful, honest, '224 'and harmless AI assistant developed by Shanghai '225 'AI Laboratory (上海人工智能实验室).'226 )227 if deepthink:228 meta_instruction += """You are an expert mathematician with extensive experience in mathematical competitions. You approach problems through systematic thinking and rigorous reasoning. When solving problems, follow these thought processes:229## Deep Understanding230Take time to fully comprehend the problem before attempting a solution. Consider:231- What is the real question being asked?232- What are the given conditions and what do they tell us?233- Are there any special restrictions or assumptions?234- Which information is crucial and which is supplementary?235## Multi-angle Analysis236Before solving, conduct thorough analysis:237- What mathematical concepts and properties are involved?238- Can you recall similar classic problems or solution methods?239- Would diagrams or tables help visualize the problem?240- Are there special cases that need separate consideration?241## Systematic Thinking242Plan your solution path:243- Propose multiple possible approaches244- Analyze the feasibility and merits of each method245- Choose the most appropriate method and explain why246- Break complex problems into smaller, manageable steps247## Rigorous Proof248During the solution process:249- Provide solid justification for each step250- Include detailed proofs for key conclusions251- Pay attention to logical connections252- Be vigilant about potential oversights253## Repeated Verification254After completing your solution:255- Verify your results satisfy all conditions256- Check for overlooked special cases257- Consider if the solution can be optimized or simplified258- Review your reasoning process259Remember:2601. Take time to think thoroughly rather than rushing to an answer2612. Rigorously prove each key conclusion2623. Keep an open mind and try different approaches2634. Summarize valuable problem-solving methods2645. Maintain healthy skepticism and verify multiple times265Your response should reflect deep mathematical understanding and precise logical thinking, making your solution path and reasoning clear to others.266When you're ready, present your complete solution with:267- Clear problem understanding268- Detailed solution process269- Key insights270- Thorough verification271Focus on clear, logical progression of ideas and thorough explanation of your mathematical reasoning. Provide answers in the same language as the user asking the question, repeat the final answer using a '\\boxed{}' without any units, you have [[8192]] tokens to complete the answer.272""" # noqa: E501273 total_prompt = f'<s><|im_start|>system\n{meta_instruction}<|im_end|>\n'274 for message in messages:275 cur_content = message['content']276 if message['role'] == 'user':277 cur_prompt = user_prompt.format(user=cur_content)278 elif message['role'] == 'robot':279 cur_prompt = robot_prompt.format(robot=cur_content)280 else:281 raise RuntimeError282 total_prompt += cur_prompt283 total_prompt = total_prompt + cur_query_prompt.format(user=prompt)284 return total_prompt285 286 287def main():288 # torch.cuda.empty_cache()289 print('load model begin.')290 model, tokenizer = load_model()291 print('load model end.')292 293 user_avator = 'assets/user.png'294 robot_avator = 'assets/robot.png'295 296 st.title('InternLM3-8B-Instruct')297 298 generation_config = prepare_generation_config()299 300 def render_message(msg, msg_idx, deepthink):301 if msg['content'] is None:302 real_prompt = combine_history(303 st.session_state.messages[msg_idx - 1]['content'], deepthink=deepthink, stop=msg_idx - 1304 )305 placeholder = st.empty()306 for cur_response in generate_interactive(307 model=model,308 tokenizer=tokenizer,309 prompt=real_prompt,310 additional_eos_token_id=92542,311 **asdict(generation_config),312 ):313 placeholder.markdown(postprocess(cur_response, deepthink=deepthink) + '▌')314 placeholder.markdown(postprocess(cur_response, deepthink=deepthink))315 msg['content'] = cur_response316 torch.cuda.empty_cache()317 else:318 st.markdown(postprocess(msg['content'], deepthink=deepthink))319 320 # Initialize chat history321 if 'messages' not in st.session_state:322 st.session_state.messages = []323 if 'deepthink_messages' not in st.session_state:324 st.session_state.deepthink_messages = []325 326 # Display chat messages from history on app rerun327 for idx, (message, deepthink_message) in enumerate(328 zip(st.session_state.messages, st.session_state.deepthink_messages)329 ):330 with st.chat_message(message['role'], avatar=message.get('avatar')):331 if message['role'] == 'user':332 st.markdown(postprocess(message['content'], add_prefix=False))333 else:334 if st.toggle('compare', key=f'compare_{idx}'):335 cols = st.columns(2)336 if st.session_state['inference_mode'] == 'Deep Thinking':337 with cols[1]:338 render_message(deepthink_message, idx, True)339 with cols[0]:340 render_message(message, idx, False)341 else:342 with cols[0]:343 render_message(message, idx, False)344 with cols[1]:345 render_message(deepthink_message, idx, True)346 else:347 if st.session_state['inference_mode'] == 'Deep Thinking':348 if deepthink_message['content'] is not None:349 st.markdown(postprocess(deepthink_message['content'], deepthink=True))350 else:351 st.markdown(postprocess(message['content']))352 else:353 if message['content'] is not None:354 st.markdown(postprocess(message['content']))355 else:356 st.markdown(postprocess(deepthink_message['content'], deepthink=True))357 358 # Accept user input359 if prompt := st.chat_input('What is up?'):360 # Display user message in chat message container361 with st.chat_message('user', avatar=user_avator):362 st.markdown(postprocess(prompt, add_prefix=False))363 real_prompt = combine_history(prompt, deepthink=st.session_state['inference_mode'] == 'Deep Thinking')364 # Add user message to chat history365 st.session_state.messages.append({'role': 'user', 'content': prompt, 'avatar': user_avator})366 st.session_state.deepthink_messages.append({'role': 'user', 'content': prompt, 'avatar': user_avator})367 368 with st.chat_message('robot', avatar=robot_avator):369 st.toggle('compare', key=f'compare_{len(st.session_state.messages)}')370 message_placeholder = st.empty()371 for cur_response in generate_interactive(372 model=model,373 tokenizer=tokenizer,374 prompt=real_prompt,375 additional_eos_token_id=92542,376 **asdict(generation_config),377 ):378 # Display robot response in chat message container379 message_placeholder.markdown(380 postprocess(cur_response, deepthink=st.session_state['inference_mode'] == 'Deep Thinking') + '▌'381 )382 message_placeholder.markdown(383 postprocess(cur_response, deepthink=st.session_state['inference_mode'] == 'Deep Thinking')384 )385 # Add robot response to chat history386 response, deepthink_response = (387 (None, cur_response) if st.session_state['inference_mode'] == 'Deep Thinking' else (cur_response, None)388 )389 st.session_state.messages.append(390 {391 'role': 'robot',392 'content': response, # pylint: disable=undefined-loop-variable393 'avatar': robot_avator,394 }395 )396 st.session_state.deepthink_messages.append(397 {398 'role': 'robot',399 'content': deepthink_response,400 'avatar': robot_avator,401 }402 )403 torch.cuda.empty_cache()404 405 406main()407 