Spis treści:
Uruchamianie modeli językowych lokalnie wymaga nie tylko pobrania odpowiednich wag, ale również poprawnego skonfigurowania formatu promptu, parametrów generowania i ścieżek plików. Przedstawiony projekt łączy te zadania w jednej aplikacji Streamlit, która pobiera modele z Hugging Face, generuje pliki Modelfile i rejestruje modele w Ollama.
Rozwiązanie jest szczególnie przydatne dla osób, które chcą korzystać z modeli GGUF lub obsługiwanych modeli Safetensors bez ręcznego tworzenia konfiguracji i wpisywania wszystkich poleceń w terminalu. Jednocześnie kod pokazuje kilka ważnych problemów technicznych związanych z lokalnym uruchamianiem modeli.
Architektura projektu
Aplikacja składa się z dwóch głównych modułów. Plik download_model.py odpowiada za interpretowanie adresów Hugging Face, pobieranie plików oraz generowanie początkowego Modelfile. Z kolei app.py udostępnia graficzny interfejs zbudowany w Streamlit.
Przepływ pracy został podzielony na trzy etapy:
- pobranie modelu lub całego repozytorium z Hugging Face;
- konfiguracja parametrów generowania i szablonu promptu;
- utworzenie modelu w Ollama oraz sprawdzenie listy lokalnych modeli.
Podział na moduł pobierający i warstwę interfejsu jest rozsądny, ponieważ funkcje pobierania mogą być wykorzystane również z poziomu wiersza poleceń. Dzięki temu aplikacja nie jest jedynym sposobem obsługi projektu.
Element | Odpowiedzialność | Przykładowe dane |
|---|---|---|
download_model.py | pobieranie modeli i generowanie Modelfile | repozytorium, plik GGUF, token HF |
app.py | interfejs użytkownika | formularze, suwaki, zakładki |
models/ | lokalne pliki modeli | .gguf, .bin, .safetensors |
modelfiles/ | konfiguracje dla Ollama | pliki .modelfile |
Pobieranie modeli z Hugging Face
Funkcja parse_hf_url() pozwala podać zarówno identyfikator repozytorium, jak i adres URL. Obsługiwane są między innymi wartości w rodzaju autor/model oraz adresy zawierające ścieżkę blob lub resolve.
Jeżeli użytkownik poda konkretny plik, kod wywołuje hf_hub_download(). To właściwy wybór, gdy repozytorium zawiera wiele wariantów modelu, na przykład różne poziomy kwantyzacji GGUF. Biblioteka Hugging Face pobiera wskazany plik i zwraca lokalną ścieżkę, korzystając przy tym z mechanizmu cache’owania.
Gdy nazwa pliku nie zostanie podana, wywoływana jest funkcja snapshot_download(). Pobiera ona cały snapshot repozytorium. Oficjalna dokumentacja Hugging Face wskazuje, że można dodatkowo ograniczać zakres pobierania za pomocą wzorców allow_patterns i ignore_patterns. W analizowanym projekcie ta możliwość nie została jeszcze wykorzystana, więc pobranie całego repozytorium może zająć dużo miejsca. Dokumentacja pobierania Hugging Face
Pliki są zapisywane w katalogu wynikającym z identyfikatora repozytorium. Dla przykładowego repozytorium org/model powstanie katalog models/org_model. Takie rozwiązanie zapobiega mieszaniu plików pochodzących z różnych repozytoriów.
W przypadku dużych modeli warto pobierać konkretny plik kwantyzowany zamiast całego repozytorium.
Autoryzacja odbywa się przez token Hugging Face przekazany w interfejsie albo zapisany w zmiennej środowiskowej HF_TOKEN. To lepsze niż umieszczanie tokena bezpośrednio w kodzie. Token może być konieczny dla repozytoriów wymagających zaakceptowania licencji lub dodatkowych uprawnień.
Tworzenie pliku Modelfile
Modelfile jest instrukcją opisującą, jak Ollama ma zbudować i uruchamiać model. W projekcie jego zawartość powstaje w funkcji build_modelfile_content(). Funkcja przyjmuje ścieżkę bazowego modelu, parametry generowania, szablon rozmowy, tokeny zatrzymania oraz komunikat systemowy.
Najważniejsza instrukcja to FROM. W przypadku pliku GGUF powinna wskazywać ścieżkę absolutną albo ścieżkę względną wobec Modelfile. Dokumentacja Ollama pokazuje przykład wykorzystania pliku GGUF właśnie w tej formie. Ollama Modelfile Reference
Przykładowa konfiguracja może wyglądać następująco:
FROM ../models/org_model/model.Q4_K_M.gguf
PARAMETER num_ctx 8192
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER min_p 0.05
PARAMETER repeat_penalty 1.1
PARAMETER stop "<|im_start|>"
PARAMETER stop "<|im_end|>"
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
"""
SYSTEM """
Jesteś pomocnym i precyzyjnym asystentem AI.
"""Instrukcja PARAMETER wpływa na sposób generowania odpowiedzi. Aplikacja udostępnia między innymi rozmiar kontekstu, temperaturę, top_p, min_p, karę za powtórzenia i liczbę wątków CPU.
Parametr | Znaczenie | Praktyczny efekt |
|---|---|---|
num_ctx | rozmiar okna kontekstu | większa wartość pozwala uwzględnić dłuższy tekst, ale zwiększa zużycie pamięci |
temperature | poziom losowości | niższa wartość daje bardziej przewidywalne odpowiedzi |
top_p | filtrowanie według prawdopodobieństwa | niższa wartość ogranicza wybór tokenów |
min_p | odrzucanie tokenów o zbyt małym prawdopodobieństwie | może ograniczyć przypadkowe lub słabe kontynuacje |
repeat_penalty | kara za powtarzanie | wyższa wartość może zmniejszać zapętlenia |
num_thread | liczba wątków CPU | pozwala ręcznie dopasować obciążenie procesora |
Szablon promptu ma znaczenie
Jednym z najważniejszych elementów konfiguracji jest TEMPLATE. Model instruktażowy nie otrzymuje zwykłego tekstu, lecz strukturę zawierającą role, separatory i specjalne tokeny. Jeżeli szablon nie odpowiada formatowi użytemu podczas treningu, jakość odpowiedzi może wyraźnie spaść.
Aplikacja zawiera trzy gotowe warianty: format Mistral z oznaczeniami [INST], format ChatML z tokenami <|im_start|> oraz schemat używany przez modele Llama 3. Dostępna jest również opcja pustego lub własnego szablonu.
Ważne jest, aby tokeny zatrzymania odpowiadały tokenom kończącym poszczególne części rozmowy. Dla ChatML mogą to być <|im_start|> i <|im_end|>, natomiast dla Llama 3 typowe są tokeny związane z nagłówkami i końcem tury.
Nie należy wybierać szablonu wyłącznie na podstawie nazwy rodziny modelu. Najlepszym źródłem informacji jest karta konkretnego modelu, jego konfiguracja tokenizer’a oraz przykładowy sposób uruchamiania podany przez autora.
Interfejs Streamlit

Interfejs został podzielony na trzy zakładki. Pierwsza służy do pobierania modelu, druga do konfiguracji Modelfile, a trzecia do rejestracji modelu w Ollama.
W zakładce konfiguracji aplikacja skanuje katalog models/ i wyszukuje pliki z rozszerzeniami .gguf, .bin oraz .safetensors. Użytkownik wybiera model z listy, ustala nazwę Modelfile i zmienia parametry za pomocą kontrolek Streamlit.
Warto zwrócić uwagę na działanie st.tabs(). Domyślnie Streamlit wykonuje zawartość wszystkich zakładek, nawet jeśli użytkownik ogląda tylko jedną z nich. Przy kosztownych operacjach można zastosować śledzenie aktywnej zakładki przez on_change="rerun" i właściwość .open. Dokumentacja st.tabs
W analizowanym kodzie pobieranie uruchamia się dopiero po naciśnięciu przycisku, więc nie jest wykonywane przy każdym odświeżeniu aplikacji. Mimo to warto rozważyć przeniesienie operacji wymagających dużej ilości czasu do warunkowo renderowanej zakładki.
Rejestracja modelu w Ollama
Po zapisaniu Modelfile użytkownik może utworzyć model poleceniem:
ollama create nazwa-modelu -f modelfiles/model.modelfile
ollama run nazwa-modeluAplikacja wykonuje pierwsze polecenie za pomocą subprocess.run(), ustawia katalog roboczy projektu i pokazuje komunikat standardowego wyjścia lub błędu. Dostępny jest także przycisk wywołujący ollama list.
Takie podejście upraszcza pracę, ale zakłada, że program ollama znajduje się w zmiennej PATH. Jeśli Ollama nie jest zainstalowana albo działa pod niestandardową ścieżką, aplikacja zwróci błąd FileNotFoundError.
Przed rejestracją warto sprawdzić trzy rzeczy:
- czy ścieżka w instrukcji
FROMjest poprawna względem położenia Modelfile; - czy użyty format promptu odpowiada konkretnemu modelowi;
- czy komputer dysponuje wystarczającą ilością pamięci RAM lub VRAM.
Praktyczne zastosowania
Narzędzie może być użyte jako lokalny panel do zarządzania kilkoma modelami językowymi. Przykładowo można przygotować osobne konfiguracje dla modelu ogólnego, modelu programistycznego i modelu zoptymalizowanego do języka polskiego.
Zmiana parametrów bez edytowania pliku ręcznie ułatwia testy porównawcze. Dla generowania kodu można zastosować niższą temperaturę i większy kontekst, natomiast przy kreatywnym pisaniu sprawdzić nieco wyższą temperaturę.
Projekt może być także punktem wyjścia do rozbudowy o:
- wybór konkretnej rewizji repozytorium przez parametr
revision; - filtrowanie plików w
snapshot_download(); - walidację istnienia pliku wskazanego w
FROM; - podgląd rozmiaru modelu przed pobraniem;
- obsługę instrukcji
LICENSE,MESSAGEiADAPTER; - testowe wywołanie modelu po zakończeniu
ollama create.
Szczególnie przydatne byłoby dodanie trybu „dry run”. Hugging Face obsługuje sprawdzanie, jakie pliki i ile danych zostanie pobranych, bez rozpoczynania właściwego transferu. Pozwoliłoby to uniknąć przypadkowego pobrania kilku dużych wariantów modelu.
Ograniczenia i bezpieczeństwo
Najważniejszym ograniczeniem jest brak głębokiej walidacji danych wejściowych. Funkcja parsująca adres traktuje pierwsze dwa elementy ścieżki jako identyfikator repozytorium, dlatego nietypowe adresy lub ścieżki mogą wymagać dodatkowej obsługi.
Drugim problemem jest brak jawnego wyboru rewizji. Domyślnie pobierana jest najnowsza wersja repozytorium. W środowisku produkcyjnym lepiej przypiąć konkretny tag albo pełny hash commita, aby późniejsze zmiany repozytorium nie zmieniły nieoczekiwanie używanego modelu.
Token Hugging Face nie powinien być zapisywany w repozytorium ani wyświetlany w logach. Warto korzystać ze zmiennych środowiskowych, menedżera sekretów lub bezpiecznych ustawień środowiska uruchomieniowego.
Przed uruchomieniem pobranego modelu należy również sprawdzić jego licencję. Sam fakt dostępności pliku w publicznym repozytorium nie oznacza, że można go dowolnie modyfikować, rozpowszechniać lub wykorzystywać komercyjnie.
lowcyai/ollama-model-creator
by lowcyaiKreator i menedżer modeli dla Ollama – pobieranie z Hugging Face, konfigurator Modelfile i rejestracja





