לבנות מחדש אתרים עם SEO/אבטחה וקוד משופר — מודל AI קליל על CPU
שם המודל
pablo-guides-webrebuild-1.0
התקנות
Linux/WSL:
curl -fsSL https://ollama.com/install.sh | sh
python -m venv .venv
source .venv/bin/activate
pip install fastapi uvicorn pypdf python-docx tqdm requests numpy
משיכת מודלים קלים:
ollama pull qwen2.5:3b-instruct-q4
ollama pull bge-m3
			השגת נתוני אימון (האתר שלך בלבד)
Mirror חוקי של אתרים שבבעלותך” — פקודת wget
wget –mirror –convert-links –adjust-extension –page-requisites –no-parent https://example.com
-P ./site_mirror
			הכנת דאטה ל-RAG + דוגמאות few-shot (JSONL)
דוגמה ל-Instruction Tuning קליל (אם תרצה בהמשך), ולשימוש כ-few-shot בפרומפט:
data/rebuild_examples.jsonl
{"instruction":"שפר דף HTML ל-SEO","input":"<html>…</html>","output":"<!– הוספת meta, title, schema.org –>\n<html>…משופר…</html>\n# הסבר: הוספתי …"}
{"instruction":"הקשח כותרות אבטחה עבור Apache","input":"", "output":"Header set Content-Security-Policy "default-src 'self'" …"}
{"instruction":"המר JS inline לקובץ, הפחת JS blocking","input":"…","output":"…"}
			אינגסט ל-SQLite FTS5 (אינדוקס מהיר)
ingest_sqlite.py
import os, re, sqlite3, pathlib
from bs4 import BeautifulSoup
DB="db/idx.db"; SRC="site_mirror"
os.makedirs("db", exist_ok=True)
con=sqlite3.connect(DB); cur=con.cursor()
cur.execute("CREATE VIRTUAL TABLE IF NOT EXISTS chunks USING fts5(path, chunk_idx, text, tokenize='unicode61');")
def textify(html):
s=BeautifulSoup(html, "html.parser")
for tag in s(["script","style","noscript"]): tag.decompose()
return re.sub(r"\s+"," ", s.get_text(" ")).strip()
def chunk(t,size=2000,overlap=150):
out=[]; i=0; n=len(t)
while i<n:
j=min(i+size,n); out.append(t[i:j])
if j==n: break
i=max(0,j-overlap)
return out
i=0
for root,_,files in os.walk(SRC):
for fn in files:
if not fn.lower().endswith((".html",".htm")): continue
p=os.path.join(root,fn)
html=open(p,"r",encoding="utf-8",errors="ignore").read()
txt=textify(html)
for k,ch in enumerate(chunk(txt)):
cur.execute("INSERT INTO chunks(path,chunk_idx,text) VALUES (?,?,?)",(str(pathlib.Path(p)),k,ch))
i+=1
con.commit(); con.close(); print("✓ FTS5 ok", i, "chunks")
			שרת RAG (שליפה→ריראנק→יצירת קוד משופר)
server.py
from fastapi import FastAPI
from pydantic import BaseModel
import sqlite3, requests, numpy as np
DB="db/idx.db"; CHAT="qwen2.5:3b-instruct-q4"; EMB="bge-m3"
app=FastAPI(title="Web Rebuilder (SQLite)")
def emb(t: str):
r=requests.post("http://localhost:11434/api/embeddings",json={"model":EMB,"prompt":t},timeout=120)
r.raise_for_status(); return np.array(r.json()["embedding"],dtype=np.float32)
def cos(a,b): return float(np.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)+1e-9))
def retrieve(q: str, k=80):
con=sqlite3.connect(DB); con.row_factory=sqlite3.Row
cur=con.cursor(); cur.execute("SELECT path,chunk_idx,text FROM chunks WHERE text MATCH ? LIMIT ?",(q,k))
rows=[dict(x) for x in cur.fetchall()]; con.close(); return rows
def rerank(q: str, rows, top_k=6):
qe=emb(q); scored=[]
for r in rows:
e=emb(r["text"][:1200]); scored.append((cos(qe,e),r))
scored.sort(reverse=True,key=lambda x:x); return [x[1] for x in scored[:top_k]]
def ask_llm(q: str, ctx):
joined="\n\n".join([f"[{i+1}] {c['path']} #{c['chunk_idx']}\n{c['text']}" for i,c in enumerate(ctx)])
payload={"model":CHAT,"messages":[
{"role":"system","content":"ענה/י בעברית. שפר/י קוד ל-PHP 8.3 עם SEO+אבטחה. כלול/י מקורות בסוף."},
{"role":"user","content":f"קטעים רלוונטיים:\n{joined}\n\nבקשה: שפר/י את {q} ותן/י קוד PHP 8.3 משופר + הסבר."}
],"stream":False,"options":{"temperature":0.2,"num_ctx":2048}}
r=requests.post("http://localhost:11434/api/chat",json=payload,timeout=120)
r.raise_for_status(); return r.json()["message"]["content"]
class Req(BaseModel):
query: str; k: int=80; top_k: int=6
@app.post("/rebuild")
def rebuild(req: Req):
rows=retrieve(req.query,req.k); top=rerank(req.query,rows,req.top_k)
ans=ask_llm(req.query,top)
return {"ok":True,"answer":ans,"sources":[{"path":x,"chunk":x} for x in top]}
			דוגמת קוד PHP 8.3 (טופס קטן בעברית + הגנות כותרות)
<?php declare(strict_types=1); header("Content-Security-Policy: default-src 'self'; frame-ancestors 'none'; base-uri 'self'"); header("X-Frame-Options: DENY"); header("X-Content-Type-Options: nosniff"); header("Referrer-Policy: no-referrer"); function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } $success = null; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = trim($_POST['name'] ?? "); if ($name !== ") { $success = "שלום, " . h($name) . "!"; } } ?><!doctype html> <html lang="he" dir="rtl"><meta charset="utf-8"> <title>טופס דוגמה מאובטח (PHP 8.3)</title> <h1>טופס דוגמה</h1> <form method="post" autocomplete="off"> <label>שם מלא: <input name="name" required></label> <button type="submit">שליחה</button> </form> <?php if ($success) { echo "<p>".h($success)."</p>"; } ?> </html>
			הרצה
python ingest_sqlite.py
uvicorn server:app –port 8000 –reload
			שיפור מתמשך
- 
יומן שאלות → לזהות כשלים → להוסיף דוגמאות few-shot ל-SYSTEM/Modelfile.
 - 
Cache לאמבדינגים, כיוונון CHUNK/TOP-K, וכותרות אבטחה אוטומטיות בתבניות שהמודל מחזיר.
 
📊 נתוני צפיות
סה"כ צפיות: 22
מבקרים ייחודיים: 22
- 🧍 172.71.184.46 (
Russia) - 🧍 172.70.240.180 (
Germany) - 🧍 172.69.151.19 (
Germany) - 🧍 104.23.229.119 (
France) - 🧍 172.71.232.28 (
France) - 🧍 172.70.200.174 (
Israel) - 🧍 172.71.144.36 (
Germany) - 🧍 172.71.135.74 (
France) - 🧍 172.71.131.101 (
France) - 🧍 172.71.126.41 (
France) - 🧍 162.158.111.85 (
Germany) - 🧍 162.158.94.197 (
Germany) - 🧍 172.71.172.224 (
Germany) - 🧍 104.23.229.118 (
France) - 🧍 172.70.200.155 (
Israel) - 🧍 104.23.225.168 (
France) - 🧍 172.70.243.65 (
Germany) - 🧍 104.23.211.218 (
United States) - 🧍 172.68.150.69 (
United States) - 🧍 172.71.184.47 (
Russia) - 🧍 172.71.148.56 (
Germany) - 🧍 108.162.241.90 (
Canada) 
								
Russia)
Germany)
France)
Israel)
United States)
Canada)