Browse Source

Deploy Qwen3-Coder-Next uncensored fine-tuner

Sameric 4 months ago
parent
commit
93538163f5
5 changed files with 22 additions and 25 deletions
  1. 12 13
      Dockerfile
  2. 2 2
      app.py
  3. 1 1
      config.yaml
  4. 4 6
      scripts/merge_and_push.py
  5. 3 3
      train.py

+ 12 - 13
Dockerfile

@@ -4,9 +4,6 @@ ENV DEBIAN_FRONTEND=noninteractive
 ENV PYTHONUNBUFFERED=1
 ENV GRADIO_SERVER_NAME=0.0.0.0
 ENV GRADIO_SERVER_PORT=7860
-ENV HF_HOME=/tmp/hf_cache
-ENV TRANSFORMERS_CACHE=/tmp/hf_cache
-ENV TORCH_HOME=/tmp/torch_cache
 
 # System dependencies
 RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -33,6 +30,9 @@ RUN pip install --no-cache-dir torch torchvision torchaudio --index-url https://
 # Install flash-attention for faster training
 RUN pip install --no-cache-dir flash-attn --no-build-isolation 2>/dev/null || echo "Flash attention build failed, continuing without it"
 
+# Create non-root user FIRST
+RUN useradd -m -u 1000 user
+
 # Create app directory
 WORKDIR /app
 
@@ -43,20 +43,19 @@ RUN pip install --no-cache-dir -r requirements.txt
 # Copy app files
 COPY . .
 
-# Create non-root user for HF Spaces
-RUN useradd -m -u 1000 user
-
-# Create cache directories and make them owned by the non-root user
-RUN mkdir -p /tmp/hf_cache /tmp/torch_cache /tmp/qwen3-uncensored-lora /tmp/merged_model \
-    && chown -R user:user /tmp/hf_cache /tmp/torch_cache /tmp/qwen3-uncensored-lora /tmp/merged_model \
-    && chmod -R 777 /tmp/hf_cache /tmp/torch_cache /tmp/qwen3-uncensored-lora /tmp/merged_model \
-    && chown -R user:user /app
-
-USER user
+# Create ALL directories under user home (NOT /tmp)
+RUN mkdir -p /home/user/hf_cache /home/user/torch_cache /home/user/output /home/user/merged \
+    && chown -R user:user /home/user /app
 
+# Set cache env vars to user home
 ENV HOME=/home/user
+ENV HF_HOME=/home/user/hf_cache
+ENV TRANSFORMERS_CACHE=/home/user/hf_cache
+ENV TORCH_HOME=/home/user/torch_cache
 ENV PATH="/home/user/.local/bin:$PATH"
 
+USER user
+
 EXPOSE 7860
 
 CMD ["python", "app.py"]

+ 2 - 2
app.py

@@ -12,8 +12,8 @@ from pathlib import Path
 import gradio as gr
 import yaml
 
-STATUS_FILE = "/tmp/training_status.json"
-LOG_FILE = "/tmp/training.log"
+STATUS_FILE = "/home/user/training_status.json"
+LOG_FILE = "/home/user/training.log"
 
 # Track background training thread
 training_thread = None

+ 1 - 1
config.yaml

@@ -67,7 +67,7 @@ datasets:
 
 # Training Arguments
 training:
-  output_dir: "/tmp/qwen3-uncensored-lora"
+  output_dir: "/home/user/output"
   num_train_epochs: 2
   per_device_train_batch_size: 1
   gradient_accumulation_steps: 16

+ 4 - 6
scripts/merge_and_push.py

@@ -20,7 +20,7 @@ logging.basicConfig(
 )
 logger = logging.getLogger(__name__)
 
-STATUS_FILE = "/tmp/training_status.json"
+STATUS_FILE = "/home/user/training_status.json"
 
 
 def write_status(status: str, detail: str = "", progress: float = 0.0):
@@ -29,7 +29,7 @@ def write_status(status: str, detail: str = "", progress: float = 0.0):
 
 
 def merge_and_push(
-    adapter_path: str = "/tmp/qwen3-uncensored-lora/final_adapter",
+    adapter_path: str = "/home/user/output/final_adapter",
     hub_model_id: str = "",
     push_to_hub: bool = True,
 ):
@@ -82,7 +82,7 @@ def merge_and_push(
     # -----------------------------------------------------------------------
     # 3. Save merged model
     # -----------------------------------------------------------------------
-    output_path = "/tmp/merged_model"
+    output_path = "/home/user/merged"
     write_status("merging", "Saving merged model...", 0.6)
     logger.info(f"Saving merged model to: {output_path}")
 
@@ -163,9 +163,7 @@ if __name__ == "__main__":
     import argparse
 
     parser = argparse.ArgumentParser()
-    parser.add_argument(
-        "--adapter-path", default="/tmp/qwen3-uncensored-lora/final_adapter"
-    )
+    parser.add_argument("--adapter-path", default="/home/user/output/final_adapter")
     parser.add_argument(
         "--hub-model-id",
         required=True,

+ 3 - 3
train.py

@@ -29,7 +29,7 @@ logging.basicConfig(
     format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
     handlers=[
         logging.StreamHandler(sys.stdout),
-        logging.FileHandler("/tmp/training.log", mode="a"),
+        logging.FileHandler("/home/user/training.log", mode="a"),
     ],
 )
 logger = logging.getLogger(__name__)
@@ -37,7 +37,7 @@ logger = logging.getLogger(__name__)
 # ---------------------------------------------------------------------------
 # Status file for Gradio UI to poll
 # ---------------------------------------------------------------------------
-STATUS_FILE = "/tmp/training_status.json"
+STATUS_FILE = "/home/user/training_status.json"
 
 
 def write_status(
@@ -563,7 +563,7 @@ def abliterate(
                 param.data -= param.data @ proj
 
     # Save and push
-    output_path = "/tmp/merged_model"
+    output_path = "/home/user/merged"
     write_status("saving", "Saving abliterated model...")
     model.save_pretrained(output_path, safe_serialization=True)
     tokenizer.save_pretrained(output_path)