מדריך מקצה לקצה: הקמת AI משלך (LoRA/QLoRA + UI + Production)
מה אנחנו בונים כאן?
אנחנו מקימים מודל קטן (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 (אחרי אימון)
צור קובץ בדיקה:
nano run_infer.py
הדבק:
=========================================================
בדיקת מודל בסיס + 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))
הרצה:
python run_infer.py
9) UI לצ’אט (Gradio)
צור קובץ UI:
nano app_ui.py
הדבק:
=========================================================
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)
הרצה:
python app_ui.py
גישה בדפדפן:
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/
