| import os |
| import json |
| import uuid |
| from datetime import datetime, timezone |
| from io import BytesIO |
|
|
| import gradio as gr |
| from huggingface_hub import HfApi |
|
|
| HF_TOKEN = os.environ.get("HF_TOKEN") |
| if not HF_TOKEN: |
| raise RuntimeError( |
| "Brak sekretu HF_TOKEN. Dodaj token z uprawnieniem zapisu w " |
| "Settings -> Variables and secrets -> New secret (nazwa: HF_TOKEN) " |
| "zanim formularz zacznie działać." |
| ) |
|
|
| DATASET_REPO_ID = "Mati83moni/quantization-requests" |
| api = HfApi(token=HF_TOKEN) |
|
|
| VALID_FORMATS = ["GGUF", "AWQ", "EXL3"] |
| VALID_HARDWARE = [ |
| "CPU (lokalnie)", |
| "Pojedyncze GPU konsumenckie (8-24GB VRAM)", |
| "Wiele GPU / serwer", |
| "Nie wiem / potrzebuję porady", |
| ] |
| VALID_CONTEXT = ["4k", "8k", "16k", "32k", "128k", "Inny / oryginalny z modelu"] |
| VALID_YESNO = ["Tak", "Nie"] |
| VALID_VISIBILITY = ["Publiczny", "Prywatny / gated (wymaga dostępu)"] |
| VALID_DELIVERABLE = ["Tylko pliki wynikowe", "Pliki + instrukcja wdrożenia"] |
|
|
|
|
| def submit_request( |
| model_link: str, |
| quant_format: str, |
| hardware: str, |
| context_length: str, |
| needs_benchmark: str, |
| needs_hf_publish: str, |
| deadline: str, |
| model_visibility: str, |
| deliverable_type: str, |
| contact_email: str, |
| notes: str, |
| ): |
| model_link = (model_link or "").strip() |
| contact_email = (contact_email or "").strip() |
| notes = (notes or "").strip() |
| deadline = (deadline or "").strip() |
|
|
| if not model_link.startswith("https://huggingface.co/"): |
| return gr.update( |
| value="❌ Podaj pełny link do modelu na Hugging Face " |
| "(np. https://huggingface.co/meta-llama/Llama-3.1-8B).", |
| visible=True, |
| ) |
| if quant_format not in VALID_FORMATS: |
| return gr.update(value="❌ Wybierz format kwantyzacji.", visible=True) |
| if hardware not in VALID_HARDWARE: |
| return gr.update(value="❌ Wybierz docelowy sprzęt.", visible=True) |
| if context_length not in VALID_CONTEXT: |
| return gr.update(value="❌ Wybierz wymaganą długość kontekstu.", visible=True) |
| if needs_benchmark not in VALID_YESNO: |
| return gr.update(value="❌ Zaznacz czy potrzebujesz benchmarku jakości.", visible=True) |
| if needs_hf_publish not in VALID_YESNO: |
| return gr.update(value="❌ Zaznacz czy chcesz publikację na HF.", visible=True) |
| if model_visibility not in VALID_VISIBILITY: |
| return gr.update(value="❌ Zaznacz czy model źródłowy jest publiczny czy prywatny.", visible=True) |
| if deliverable_type not in VALID_DELIVERABLE: |
| return gr.update(value="❌ Zaznacz zakres zlecenia (tylko pliki, czy pliki + wdrożenie).", visible=True) |
| if not deadline: |
| return gr.update( |
| value="❌ Podaj deadline (albo wpisz 'brak konkretnego terminu').", |
| visible=True, |
| ) |
| if "@" not in contact_email or "." not in contact_email.split("@")[-1]: |
| return gr.update(value="❌ Podaj prawidłowy adres e-mail kontaktowy.", visible=True) |
| if model_visibility == "Prywatny / gated (wymaga dostępu)" and "dostęp" not in notes.lower() and "token" not in notes.lower(): |
| return gr.update( |
| value="❌ Model jest oznaczony jako prywatny/gated — opisz w Dodatkowych uwagach, " |
| "jak przekażesz dostęp (np. link z tokenem, zaproszenie do repo).", |
| visible=True, |
| ) |
|
|
| record_id = str(uuid.uuid4()) |
| record = { |
| "id": record_id, |
| "submitted_at_utc": datetime.now(timezone.utc).isoformat(), |
| "model_link": model_link, |
| "format": quant_format, |
| "hardware": hardware, |
| "context_length": context_length, |
| "needs_benchmark": needs_benchmark, |
| "needs_hf_publish": needs_hf_publish, |
| "deadline": deadline, |
| "model_visibility": model_visibility, |
| "deliverable_type": deliverable_type, |
| "contact_email": contact_email, |
| "notes": notes, |
| "status": "new", |
| } |
|
|
| payload = json.dumps(record, ensure_ascii=False, indent=2).encode("utf-8") |
|
|
| try: |
| api.upload_file( |
| path_or_fileobj=BytesIO(payload), |
| path_in_repo=f"data/{record_id}.json", |
| repo_id=DATASET_REPO_ID, |
| repo_type="dataset", |
| commit_message=f"New request from {contact_email}", |
| ) |
| except Exception as e: |
| return gr.update( |
| value=f"❌ Błąd zapisu zgłoszenia, spróbuj ponownie za chwilę. ({type(e).__name__})", |
| visible=True, |
| ) |
|
|
| return gr.update( |
| value="✅ Zgłoszenie przyjęte. Odezwę się na podany e-mail w ciągu 24h z wyceną i terminem.", |
| visible=True, |
| ) |
|
|
|
|
| with gr.Blocks(title="Custom Model Quantization") as demo: |
| gr.Markdown( |
| """ |
| # Custom Model Quantization — GGUF / AWQ / EXL3 |
| |
| Kwantyzuję dowolny model z Hugging Face do wybranego formatu. |
| Portfolio: [PLLuM-12B-chat-2512-EXL3](https://huggingface.co/Mati83moni/PLLuM-12B-chat-2512-EXL3) |
| (4.5bpw, SQNR ~33dB). |
| |
| ### Orientacyjny cennik |
| | Zakres | Cena | |
| |---|---| |
| | Mały model (≤3B parametrów) | Starting from **£15** | |
| | Średni model (3B–13B parametrów) | From **£30** | |
| | Duży / złożony model (>13B, MoE, custom architecture) | **Custom quote** — wyceniam indywidualnie | |
| |
| **Dodatki (osobno płatne):** |
| Benchmark jakości (porównanie z oryginałem) · Publikacja gotowego modelu na Twoim koncie HF · |
| Instrukcja wdrożenia / support po dostawie · Rush (dostawa <48h) |
| |
| Finalna wycena zależy od rozmiaru modelu, formatu, i zakresu z formularza poniżej — |
| odpowiadam z dokładną kwotą i terminem w ciągu 24h. |
| """ |
| ) |
|
|
| model_link = gr.Textbox( |
| label="Link do modelu (Hugging Face)", |
| placeholder="https://huggingface.co/...", |
| ) |
| quant_format = gr.Radio(choices=VALID_FORMATS, label="Docelowy format kwantyzacji") |
| hardware = gr.Radio(choices=VALID_HARDWARE, label="Docelowy sprzęt (na czym model ma działać)") |
| context_length = gr.Radio(choices=VALID_CONTEXT, label="Wymagana długość kontekstu") |
| needs_benchmark = gr.Radio( |
| choices=VALID_YESNO, |
| label="Czy potrzebujesz benchmarku jakości (porównanie z oryginałem)?", |
| ) |
| needs_hf_publish = gr.Radio( |
| choices=VALID_YESNO, |
| label="Czy chcesz publikację gotowego modelu na Twoim koncie HF?", |
| ) |
| model_visibility = gr.Radio( |
| choices=VALID_VISIBILITY, |
| label="Widoczność modelu źródłowego", |
| ) |
| deliverable_type = gr.Radio( |
| choices=VALID_DELIVERABLE, |
| label="Zakres zlecenia", |
| ) |
| deadline = gr.Textbox( |
| label="Deadline", |
| placeholder="np. 15.08.2026, albo 'brak konkretnego terminu'", |
| ) |
| contact_email = gr.Textbox(label="Twój e-mail kontaktowy") |
| notes = gr.Textbox( |
| label="Dodatkowe uwagi (opcjonalnie)", |
| lines=3, |
| placeholder="np. docelowy bpw, sposób przekazania dostępu do modelu prywatnego, itd.", |
| ) |
|
|
| submit_btn = gr.Button("Wyślij zgłoszenie", variant="primary") |
| status = gr.Markdown(visible=False) |
|
|
| submit_btn.click( |
| fn=submit_request, |
| inputs=[ |
| model_link, quant_format, hardware, context_length, |
| needs_benchmark, needs_hf_publish, deadline, |
| model_visibility, deliverable_type, contact_email, notes, |
| ], |
| outputs=status, |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |