Uncategorized 21/01/2026 10 דק׳ קריאה

מדריך מקצה לקצה: הקמת AI משלך (LoRA/QLoRA + UI + Production)

pablo guides · 0 תגובות

מה אנחנו בונים כאן?

אנחנו מקימים מודל קטן (1B–3B) ומבצעים עליו אימון עדין (LoRA/QLoRA) כדי להתאים אותו לשוק ספציפי: סגנון תשובה, פורמט, כללים, מדיניות “לא להמציא”, ושאלת הבהרה כשחסר מידע.

1) דרישות מערכת (מומלץ)

GPU: NVIDIA 8GB VRAM לפחות (12–24GB עדיף)

מערכת: Ubuntu 22.04/24.04 עם SSH

דומיין: אופציונלי (ל־Nginx+SSL)

2) הכנת שרת Ubuntu (התקנות בסיס)


sudo apt update && sudo apt -y upgrade
sudo apt -y install python3 python3-venv python3-pip git git-lfs build-essential curl
git lfs install

mkdir -p ~/ai_market && cd ~/ai_market
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip wheel setuptools

3) התקנות AI (LoRA/QLoRA)
אם יש NVIDIA GPU (מומלץ)

PyTorch (דוגמה CUDA 12.1):


pip install –index-url https://download.pytorch.org/whl/cu121
torch torchvision torchaudio

כלים לאימון + UI:


pip install -U transformers datasets accelerate peft trl bitsandbytes sentencepiece safetensors gradio fastapi uvicorn

בדיקת GPU:


python -c "import torch; print('CUDA?', torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'NO GPU')"

אם אין GPU (CPU בלבד)


pip install -U torch transformers datasets accelerate peft trl sentencepiece safetensors gradio fastapi uvicorn

4) הורדה/שכפול מודל בסיס

אופציה A (אוטומטי): from_pretrained() יוריד לקאש.

אם אתה רוצה קאש מסודר:


export HF_HOME=~/hf
export TRANSFORMERS_CACHE=~/hf/transformers

אופציה B (Clone מלא):


mkdir -p ~/models && cd ~/models
git clone https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v1.0

5) בחירת מודל קל להתחלה

מומלץ להתחיל עם:

TinyLlama/TinyLlama-1.1B-Chat-v1.0 (קל מאוד, MVP מהיר)

microsoft/phi-2 (איכות טובה יחסית לגודל קטן)

6) הכנת דאטה לאימון (JSONL)

צור תיקייה וקובץ:


cd ~/ai_market
mkdir -p data
nano data/train.jsonl

דוגמה לתוכן (שורה = דוגמה):


{"instruction":"ענה בעברית בצורה מקצועית וקצרה, ואם חסר מידע שאל שאלה משלימה אחת.","input":"מה ההבדל בין טאבו לחברה משכנת?","output":"טאבו הוא רישום זכויות סופי בלשכת רישום המקרקעין. חברה משכנת מנהלת רישום פנימי/זמני בפרויקטים שטרם נרשמו בטאבו. האם מדובר בדירה חדשה מקבלן או יד-שנייה?"}
{"instruction":"תן תשובה בנקודות, בלי חפירה.","input":"לקוח רוצה לבטל עסקה אחרי 20 יום. מה לבדוק?","output":"1) תנאי ביטול בחוזה. 2) מועדי הודעת ביטול לפי חוק/הסכם. 3) דמי ביטול/החזרים. 4) תיעוד כתוב של כל התקשורת."}

7) אימון LoRA/QLoRA

צור קובץ אימון:


cd ~/ai_market
nano train_lora.py

הדבק את הסקריפט המלא:

=========================================================
אימון LoRA / QLoRA למודל קל (SFT)
Author: pablo guides
=========================================================

import os
import torch
from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig
from trl import SFTTrainer
from transformers import TrainingArguments

MODEL_NAME = os.environ.get("BASE_MODEL", "TinyLlama/TinyLlama-1.1B-Chat-v1.0")
TRAIN_FILE = os.environ.get("TRAIN_FILE", "data/train.jsonl")
OUT_DIR = os.environ.get("OUT_DIR", "out_lora")

def format_example(example):
instr = (example.get("instruction") or "").strip()
inp = (example.get("input") or "").strip()
out = (example.get("output") or "").strip()

text = f"""### הוראה:

{instr}

קלט:

{inp}

תשובה:

{out}"""
return {"text": text}

def main():
use_cuda = torch.cuda.is_available()

tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token

load_kwargs = {"device_map": "auto"} if use_cuda else {"device_map": None}

if use_cuda:
# QLoRA 4bit אם bitsandbytes זמין
try:
import bitsandbytes # noqa: F401
load_kwargs.update({"load_in_4bit": True, "torch_dtype": torch.float16})
print("QLoRA 4bit מופעל (GPU).")
except Exception:
load_kwargs.update({"torch_dtype": torch.float16})
print("bitsandbytes לא זמין — עובר ל-LoRA רגיל (GPU).")
else:
print("CPU בלבד — זה יהיה איטי מאוד, מומלץ GPU.")

model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, **load_kwargs)
model.config.use_cache = False

ds = load_dataset("json", data_files={"train": TRAIN_FILE})
train_ds = ds["train"].map(format_example, remove_columns=ds["train"].column_names)

lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
)

args = TrainingArguments(
output_dir=OUT_DIR,
per_device_train_batch_size=2 if use_cuda else 1,
gradient_accumulation_steps=8,
learning_rate=2e-4,
num_train_epochs=2,
logging_steps=10,
save_steps=200,
save_total_limit=2,
fp16=use_cuda,
optim="paged_adamw_8bit" if use_cuda else "adamw_torch",
report_to="none",
warmup_ratio=0.03,
lr_scheduler_type="cosine",
)

trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=train_ds,
peft_config=lora_config,
dataset_text_field="text",
max_seq_length=1024,
packing=False,
args=args,
)

trainer.train()

trainer.model.save_pretrained(OUT_DIR)
tokenizer.save_pretrained(OUT_DIR)
print(f"\n✅ סיימנו. נשמר ב: {OUT_DIR}")

if name == "main":
main()

הרצת האימון:


cd ~/ai_market
source .venv/bin/activate
python train_lora.py

החלפת מודל (דוגמה):


BASE_MODEL="microsoft/phi-2" OUT_DIR="out_phi2_lora" python train_lora.py

8) בדיקת Inference (אחרי אימון)

צור קובץ בדיקה:

הדבק:

=========================================================
בדיקת מודל בסיס + LoRA
Author: pablo guides
=========================================================

import os
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel

BASE_MODEL = os.environ.get("BASE_MODEL", "TinyLlama/TinyLlama-1.1B-Chat-v1.0")
LORA_DIR = os.environ.get("LORA_DIR", "out_lora")

prompt = """### הוראה:
ענה בעברית, קצר ומדויק. אם חסר מידע שאל שאלה משלימה אחת.

קלט:

מה ההבדל בין טאבו לחברה משכנת?

תשובה:

"""

tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, use_fast=True)
model = AutoModelForCausalLM.from_pretrained(
BASE_MODEL,
device_map="auto" if torch.cuda.is_available() else None,
torch_dtype=torch.float16 if torch.cuda.is_available() else None
)

model = PeftModel.from_pretrained(model, LORA_DIR)
model.eval()

inputs = tokenizer(prompt, return_tensors="pt")
if torch.cuda.is_available():
inputs = {k: v.to(model.device) for k, v in inputs.items()}

with torch.no_grad():
out = model.generate(
**inputs,
max_new_tokens=200,
do_sample=True,
temperature=0.7,
top_p=0.9,
repetition_penalty=1.12
)

print(tokenizer.decode(out[0], skip_special_tokens=True))

הרצה:

9) UI לצ’אט (Gradio)

צור קובץ UI:

הדבק:

=========================================================
UI צ'אט למודל + LoRA (Gradio)
Author: pablo guides
=========================================================

import os
import torch
import gradio as gr
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel

BASE_MODEL = os.environ.get("BASE_MODEL", "TinyLlama/TinyLlama-1.1B-Chat-v1.0")
LORA_DIR = os.environ.get("LORA_DIR", "out_lora")

SYSTEM_STYLE = """אתה עוזר מקצועי לשוק ספציפי.
ענה בעברית, קצר ומדויק.
אם חסר מידע — שאל שאלה משלימה אחת לפני תשובה מלאה.
אם אינך בטוח — אמור שאינך בטוח ואל תמציא.
"""

def build_prompt(user_msg: str, history):
parts = [f"### מערכת:\n{SYSTEM_STYLE}\n"]
for u, a in history:
parts.append(f"### משתמש:\n{u}\n\n### עוזר:\n{a}\n")
parts.append(f"### משתמש:\n{user_msg}\n\n### עוזר:\n")
return "\n".join(parts)

def load_model():
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, use_fast=True)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token

model = AutoModelForCausalLM.from_pretrained(
BASE_MODEL,
device_map="auto" if torch.cuda.is_available() else None,
torch_dtype=torch.float16 if torch.cuda.is_available() else None
)

model = PeftModel.from_pretrained(model, LORA_DIR)
model.eval()
return tokenizer, model

tokenizer, model = load_model()

@torch.no_grad()
def chat(user_msg, history):
prompt = build_prompt(user_msg, history)

inputs = tokenizer(prompt, return_tensors="pt")
if torch.cuda.is_available():
inputs = {k: v.to(model.device) for k, v in inputs.items()}

out = model.generate(
**inputs,
max_new_tokens=300,
do_sample=True,
temperature=0.7,
top_p=0.9,
repetition_penalty=1.12,
eos_token_id=tokenizer.eos_token_id,
pad_token_id=tokenizer.eos_token_id
)

text = tokenizer.decode(out[0], skip_special_tokens=True)
marker = "### עוזר:\n"
idx = text.rfind(marker)
answer = text[idx + len(marker):].strip() if idx != -1 else text.strip()
return answer

demo = gr.ChatInterface(
fn=chat,
title="צ'אט AI (מודל קל + LoRA)",
description="ממשק בדיקה מהיר למודל המאומן שלך",
theme="soft"
)

if name == "main":
demo.launch(server_name="0.0.0.0", server_port=7860)

הרצה:

גישה בדפדפן:

http://SERVER_IP:7860

10) פתיחת פורטים ב־Ubuntu (UFW)


sudo ufw allow OpenSSH
sudo ufw allow 7860/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

11) הרצה קבועה: systemd service

צור שירות:


sudo nano /etc/systemd/system/ai-chat.service

הדבק (שים לב להחליף ubuntu למשתמש שלך ולוודא נתיבים):


[Unit]
Description=AI Chat (Gradio) Service
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/ai_market
Environment=BASE_MODEL=TinyLlama/TinyLlama-1.1B-Chat-v1.0
Environment=LORA_DIR=out_lora
ExecStart=/home/ubuntu/ai_market/.venv/bin/python /home/ubuntu/ai_market/app_ui.py
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

הפעלה ובדיקה:


sudo systemctl daemon-reload
sudo systemctl enable ai-chat.service
sudo systemctl start ai-chat.service
sudo systemctl status ai-chat.service

לוגים:


journalctl -u ai-chat.service -f

12) Production: Nginx Reverse Proxy + SSL

התקנות:


sudo apt -y install nginx certbot python3-certbot-nginx

יצירת קובץ קונפיג (דוגמה: ai.example.com):


sudo nano /etc/nginx/sites-available/ai-chat

הדבק:


server {
listen 80;
server_name ai.example.com;

location / {
proxy_pass http://127.0.0.1:7860;
proxy_http_version 1.1;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

}

הפעלה:


sudo ln -s /etc/nginx/sites-available/ai-chat /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

SSL:


sudo certbot –nginx -d ai.example.com

13) אבטחה בסיסית: Basic Auth

יצירת משתמש/סיסמה:


sudo apt -y install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd pablo

הוסף בתוך location / { … }:


auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;

Reload:


sudo nginx -t && sudo systemctl reload nginx

14) איך משפרים איכות מהר

אסוף 100 שאלות אמיתיות

כתוב תשובה אידיאלית לכל שאלה

הוסף 200–2000 דוגמאות איכותיות לדאטה

אימון עוד סבב אחד

בדוק וחזור

15) תקלות נפוצות

CUDA OOM: להקטין batch, להגדיל gradient_accumulation_steps, להשתמש QLoRA 4bit

פורמט לא עקבי: להוסיף עוד דוגמאות שמדגימות פורמט

הזיות: להוסיף דוגמאות “אין מספיק מידע” + שאלת הבהרה

מבנה תיקיות מומלץ


~/ai_market/
.venv/
data/train.jsonl
train_lora.py
run_infer.py
app_ui.py
out_lora/