import os import json import subprocess from threading import Thread import logging from logging.handlers import RotatingFileHandler import torch import spaces import gradio as gr from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TextIteratorStreamer subprocess.run('pip install flash-attn --no-build-isolation', env={'FLASH_ATTENTION_SKIP_CUDA_BUILD': "TRUE"}, shell=True) log_file = '/tmp/app_debug.log' logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) file_handler = RotatingFileHandler(log_file, maxBytes=10*1024*1024, backupCount=5) file_handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.debug("Application started") MODEL_ID = "Qwen/Qwen2.5-Coder-7B-Instruct" CHAT_TEMPLATE = "ChatML" MODEL_NAME = MODEL_ID.split("/")[-1] CONTEXT_LENGTH = 16000 COLOR = "blue" EMOJI = "🤖" DESCRIPTION = f"This is the {MODEL_NAME} model designed for coding assistance and general AI tasks." @spaces.GPU() def predict(message, history, system_prompt, temperature, max_new_tokens, top_k, repetition_penalty, top_p): logger.debug(f"Received prediction request: message='{message}', system_prompt='{system_prompt}'") if CHAT_TEMPLATE == "Auto": stop_tokens = [tokenizer.eos_token_id] instruction = system_prompt + "\n\n" for user, assistant in history: instruction += f"User: {user}\nAssistant: {assistant}\n" instruction += f"User: {message}\nAssistant:" elif CHAT_TEMPLATE == "ChatML": stop_tokens = ["<|endoftext|>", "<|im_end|>"] instruction = '<|im_start|>system\n' + system_prompt + '\n<|im_end|>\n' for user, assistant in history: instruction += f'<|im_start|>user\n{user}\n<|im_end|>\n<|im_start|>assistant\n{assistant}\n<|im_end|>\n' instruction += f'<|im_start|>user\n{message}\n<|im_end|>\n<|im_start|>assistant\n' elif CHAT_TEMPLATE == "Mistral Instruct": stop_tokens = ["", "[INST]", "[INST] ", "", "[/INST]", "[/INST] "] instruction = f'[INST] {system_prompt}\n' for user, assistant in history: instruction += f'{user} [/INST] {assistant}[INST]' instruction += f' {message} [/INST]' else: raise Exception("Incorrect chat template, select 'Auto', 'ChatML' or 'Mistral Instruct'") print(instruction) streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) enc = tokenizer(instruction, return_tensors="pt", padding=True, truncation=True) input_ids, attention_mask = enc.input_ids, enc.attention_mask if input_ids.shape[1] > CONTEXT_LENGTH: input_ids = input_ids[:, -CONTEXT_LENGTH:] attention_mask = attention_mask[:, -CONTEXT_LENGTH:] generate_kwargs = dict( input_ids=input_ids.to(device), attention_mask=attention_mask.to(device), streamer=streamer, do_sample=True, temperature=temperature, max_new_tokens=max_new_tokens, top_k=top_k, repetition_penalty=repetition_penalty, top_p=top_p ) t = Thread(target=model.generate, kwargs=generate_kwargs) t.start() outputs = [] try: for new_token in streamer: outputs.append(new_token) if new_token in stop_tokens: break yield "".join(outputs) logger.debug(f"Prediction completed successfully for message: '{message}'") except Exception as e: logger.exception(f"Error during prediction for message '{message}': {str(e)}") yield "An error occurred during processing." device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') quantization_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16 ) tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) model = AutoModelForCausalLM.from_pretrained( MODEL_ID, device_map="auto", quantization_config=quantization_config, attn_implementation="flash_attention_2", ) logger.debug("Model and tokenizer loaded successfully") gr.ChatInterface( predict, title=EMOJI + " " + MODEL_NAME, description=DESCRIPTION, examples=[ ["Can you solve the equation 2x + 3 = 11 for x in Python?"], ["Write a Java program that checks if a number is even or odd."], ["How can I reverse a string in JavaScript?"], ["Create a C++ function to find the factorial of a number."], ["Write a Python list comprehension to generate a list of squares of numbers from 1 to 10."], ["How do I implement a binary search algorithm in C?"], ["Write a Ruby script to read a file and count the number of lines in it."], ["Create a Swift class to represent a bank account with deposit and withdrawal methods."], ["How do I find the maximum element in an array using Kotlin?"], ["Write a Rust program to generate the Fibonacci sequence up to the 10th number."] ], additional_inputs_accordion=gr.Accordion(label="⚙️ Parameters", open=False), additional_inputs=[ gr.Textbox("You are a code assistant.", label="System prompt"), gr.Slider(0, 1, 0.3, label="Temperature"), gr.Slider(128, 4096, 1024, label="Max new tokens"), gr.Slider(1, 80, 40, label="Top K sampling"), gr.Slider(0, 2, 1.1, label="Repetition penalty"), gr.Slider(0, 1, 0.95, label="Top P sampling"), ], theme=gr.themes.Soft(primary_hue=COLOR), ).queue().launch() logger.debug("Chat interface initialized and launched")