Asosiy qismga o'tish

Admin panel — brauzerdan boshqarish

16-bob 8 kod bloki 807 so'z

Hozirgacha hamma narsani terminaldan qildik. Endi brauzerdan.

Bu talaba uchun katta farq: PDF yuklaydi, tugma bosadi, natijani ko'radi. python -m scraper.embedder yozish shart emas.

Yetti endpoint

app/routes/admin.py da:

Diqqat: bu yo'llar ILDIZDA, /admin/ prefiksisiz. main.py da include_router(admin.router) — prefix berilmagan.

Endpoint Vazifasi
GET / dashboard — statistika
GET /documents hujjatlar ro'yxati
POST /scrape saytdan yig'ish
POST /upload-pdf PDF yuklash
POST /chunk-all hammasini chunklash
POST /embed-all hammasini embedding
GET/POST /settings sozlamalar

Dashboard

python12 qator
@router.get("/")
def dashboard(request: Request, db: Session = Depends(get_db)):
    stats = {
        "documents": db.execute(text(
            "SELECT count(*) FROM rag.documents")).scalar(),
        "chunks": db.execute(text(
            "SELECT count(*) FROM rag.chunks")).scalar(),
        "embedded": db.execute(text(
            "SELECT count(embedding_local) FROM rag.chunks")).scalar(),
    }
    return templates.TemplateResponse(
        "dashboard.html", {"request": request, "stats": stats})

Uchta son — butun tizim holati:

  • documents — nechta hujjat
  • chunks — nechta bo'lak
  • embedded — nechtasida vektor bor

Eng muhimi uchinchisi. Agar chunks = 100 va embedded = 0 bo'lsa — qidiruv ishlamaydi. Dashboard buni darhol ko'rsatadi.

Darsda shuni ayting: bu uch son bir-biriga yaqin bo'lishi kerak. embedded < chunks bo'lsa — embed-all bosish kerak.

Uch bosqichli oqim

Admin panel RAG ni uch tugmaga bo'ladi:

python2 qator
[Yuklash]  ->  [Chunklash]  ->  [Embedding]
  PDF/URL       bo'laklarga      vektorlarga

Nega uchta alohida tugma, bitta emas?

Chunki har biri turli vaqt oladi va turli sababdan buziladi:

  • Yuklash — sekund, tarmoq muammosi
  • Chunklash — tez, xatosi kam
  • Embedding — daqiqalar, Ollama kerak

Bitta tugma bo'lsa, embedding bosqichida uzilganda hammasini qaytadan qilishga to'g'ri keladi.

POST /scrape

python18 qator
class ScrapeSorovi(BaseModel):
    url: str = Field(min_length=8, max_length=2000)
    css_selector: str | None = None


@router.post("/scrape")
def scrape_url(sorov: ScrapeSorovi, db: Session = Depends(get_db)):
    try:
        natija = scrape_page(sorov.url, sorov.css_selector)
    except Exception as e:
        raise HTTPException(400, f"Sahifa olinmadi: {type(e).__name__}")

    if not natija["text"].strip():
        raise HTTPException(400,
            "Sahifadan matn chiqmadi. CSS selector ko'rsating "
            "yoki sayt JavaScript bilan yuklanadi.")

    return {"title": natija["title"], "length": len(natija["text"])}

Ikkinchi tekshiruv juda muhim. Ko'p zamonaviy saytlar JavaScript bilan yuklanadi — HTML da matn YO'Q. httpx faqat boshlang'ich HTML ni oladi.

Bunday saytlar uchun playwright kerak (brauzerni ishga tushiradi). Bu kitob doirasidan tashqarida, lekin talabaga aytib qo'ying — ular albatta uchratadi.

POST /embed-all

python4 qator
@router.post("/embed-all")
def embed_all(db: Session = Depends(get_db)):
    natija = embed_all_chunks(db)
    return {"embedded": natija}

Diqqat: bu SEKIN. 1000 chunk = bir necha daqiqa. HTTP so'rovi kutib turadi va timeout bo'lishi mumkin.

Production'da bu fon vazifasi bo'lishi kerak:

python7 qator
# parcha
from fastapi import BackgroundTasks

@router.post("/embed-all")
def embed_all(bg: BackgroundTasks, db: Session = Depends(get_db)):
    bg.add_task(embed_all_chunks, db)
    return {"status": "boshlandi"}

Darsda oddiy variantni ko'rsating, keyin muammoni tushuntiring.

Sozlamalar

python4 qator
class SozlamaSorovi(BaseModel):
    top_k: int = Field(ge=1, le=50)
    rerank_top: int = Field(ge=1, le=30)
    similarity_threshold: float = Field(ge=0.0, le=1.0)

Bu — dars uchun eng qiziqarli qism. Talaba threshold ni brauzerdan o'zgartirib, natija qanday o'zgarishini darhol ko'radi.

Tajriba qildiring:

  • threshold = 0.1 — hamma narsa topiladi, ko'pi keraksiz
  • threshold = 0.8 — deyarli hech narsa topilmaydi

Shunda ular o'zlari tushunadi: to'g'ri qiymat o'rtada va uni o'lchash kerak.

Ishga tushiring

bash1 qator
python run.py

Brauzerda:

  • http://localhost:8000/ — dashboard
  • http://localhost:8000/documents — hujjatlar
  • http://localhost:8000/chat — suhbat

Shablon va route KELISHUVI

Bu bobni yozishda uchta xato topildi — hammasi bir sababdan: shablon bir nomni kutadi, route boshqasini beradi.

Shablon kutgan Route bergan Natija
stats.total_documents doc_count 'stats' is undefined
settings.llm_model rag 'settings' is undefined
url_for('static', path=) filename= (Flask) NoMatchFound

Uchalasi ham 500 xato beradi va sahifa umuman ochilmaydi.

Nega topilmagan: hech kim sahifani BROWSERDA ochmagan. Kod "to'g'ri ko'rinadi", testlar yo'q, xato faqat ishga tushirganda chiqadi.

Saboq: har bir sahifani ochib ko'ring. Bitta curl yetadi:

bash4 qator
for y in / /documents /settings /chat; do
  printf "%s " "$y"
  curl -s -o /dev/null -w "%{http_code}\n" "http://localhost:8000$y"
done

Hammasi 200 bo'lishi kerak. 500 chiqsa — shablon va route nomlari mos emas.


Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar