Strona główna / Artykuły

Uruchamianie lokalnych agentów kodowania na Macu z oMLX: wyjaśnienie pamięci cache KV zapisywanej na dysku

oMLX przechowuje prefiksy poleceń w pamięci SSD, dzięki czemu lokalne narzędzia programistyczne działają szybko na platformie Apple Silicon. Zainstaluj go i połącz z nim Claude Code, Codex, Cursor oraz OpenCode.

Wydawca: REACTAPP.TOP9 min czytania2103 słów

Źródła: oMLX is Quietly Becoming the Best Way to Run Local AI Agents On a Mac

Po dwunastu minutach sesji programistycznej lokalny model przestaje zachowywać się jak agent i zaczyna zachowywać się jak maszyna faksowa. Wcześniejsze wywołania narzędzi zwracały wyniki w ciągu dwóch sekund. Teraz każda tura trwa trzydzieści, a czasem nawet dziewięćdziesiąt sekund. Zadanie się nie zmieniło – kontekst po prostu się wydłużył, a lokalny serwer za każdym razem od nowa oblicza całą rozmowę od zera.

To objaw, czyli powolne rozpoczynanie pracy, a nie powolna przetwarzanie tokenów, miał zostać usunięty dzięki małemu projekcie opartemu na Apple Silicon o nazwie oMLX. Nie jest to model ani agent – to serwer do inferencji z jedną konkretną obietnicą: wszystko, co agent już przeczytał, pozostaje w pamięci cache, nawet gdy sesja się wydłuża, dzięki czemu dwunasta tura wydaje się taką samą jak pierwsza. Prawdziwym testem nie jest efektowna demonstracja, lecz to, jak system radzi sobie w czterdziestej turze rzeczywistej, działającej sesji na sprzęcie, który faktycznie posiadasz.

Dlaczego Maci mają trudności z agentami programistycznymi

Na papierze Apple Silicon to potężna platforma do lokalnej inferencji. Zintegrowana pamięć zapewnia CPU i GPU wspólny zasób, dzięki czemu zkwantyzowany model znajduje się w RAM-ie bez konieczności przesyłania danych przez szynę komunikacyjną, a framework MLX firmy Apple został zaprojektowany właśnie do tego typu zadań.

Problemy pojawiają się, gdy rozmowa przeradza się w pracę agenta. Agent kodujący niemal przy każdej kolejnej akcji ponownie czyta większość wcześniejszego kontekstu, wywołuje narzędzie, otrzymuje wynik dołączony do promptu i powtarza to dziesiątki razy. Przedrostek, czyli wspólny początek promptu, prawie identycznie odpowiada poprzedniej akcji, z wyjątkiem jednego nowego wyniku z narzędzia na końcu.

Większość lokalnych serwerów interpretuje takie bliskie dopasowanie jako całkowite niezgodność, usuwa pamięć cache klucz-wartość i przelicza dane od zera. Przy krótkich zapytaniach nikt tego nie zauważa. Natomiast w sesji trwającej 20 000 tokenów powoduje to różnicę między odpowiedzią trwającą dwa sekundy a taką trwającą dziewięćdziesiąt sekund. Twórca projektu dokładnie to określił jako motywację na forum dyskusyjnym Apple MLX: agenci programistyczne wysyłają żądania, których prefiksy się zmieniają, a każdy istniejący serwer MLX unieważnia pamięć cache i przelicza wszystko, gdy to się zdarza.

Czym jest oMLX

oMLX to serwer do wykonywania inferencji o otwartym kodzie źródłowym, zbudowany na bazie rozwiązań Apple MLX i mlx-lm. Dostępny jest jako aplikacja w menu macOS oraz jako narzędzie wiersza poleceń w Pythonie. Stworzył go programista o imieniu Jun Kim, a projekt znajduje się na GitHubie pod adresem jundot/omlx pod licencją Apache 2.0. W momencie pisania tego tekstu miał około 18 600 gwiazdek, 1 600 forków oraz ponad dwa tysiące komitetów.

Nic z tego nie dowodzi niezawodności. Gwiazdki mierzą poziom uwagi, a nie dojrzałość, a projekt, który publikuje kilka wersji roboczych miesięcznie, wciąż szuka swojej drogi. Popularność jest powodem do przetestowania go, a nie zamiennikiem samego testowania.

Jeden proces obsługuje dwa style API: kompletowanie wiadomości kompatybilne z OpenAI oraz natywną trasę w stylu Anthropic /v1/messages, wraz z funkcjami kompletowania, embeddingów i przeliczania rankingów. Może utrzymywać w pamięci modele językowe, modele języka obrazkowego, modele OCR oraz narzędzia do przeliczania rankingów, wykorzystując mechanizm usuwania najrzadziej używanych elementów oraz fiksację poszczególnych modeli. Dla agentów ważne jest to, co dzieje się pod tą powierzchnią.

Przedrostki są zapisywane na dysku, a nie w koszu

Zwykła inferencja MLX przechowuje pamięć tymczasową rozmowy wyłącznie w pamięci GPU, dopóki prefiks pozostaje zgodny. Kluczową koncepcją oMLX jest dwuwarstwowa pamięć tymczasowa, która przetrwa zarówno zmiany prefiksu, jak i ponowne uruchomienia. Często używane bloki pozostają w warstwie szybkiej pamięci. Gdy ta się wypełni, bloki są zapisywane do warstwy wolniejszej na SSD w formacie safetensors, zarządzane blok po bloku przy użyciu współdzielenia prefiksów i mechanizmu kopiowania przy zapisie. Jeśli późniejszy prompt odpowiada prefiksowi zapisanemu na dysku, te bloki są odczytywane ponownie, a nie obliczane od nowa.

Przykładem może być bibliotekarz, który nigdy nie przestawia książki, którą niedawno wypożyczyłeś. Zapytaj ponownie później, nawet po ponownym otwarciu biblioteki – książka będzie już na półce.

SSD to nie RAM, więc przywracanie dużego bufora nadal zajmuje czas rzeczywisty, choć jest to o wiele tańsze niż ponowne obliczanie każdego tokena. Największe korzyści przynosi tu wcześniej opisany wzorzec agenta: długie, głównie powtarzane prefiksy z niewielką zmianą na końcu. Serwer realizuje również ciągłe grupowanie zadań za pomocą BatchGeneratora z mlx-lm, obsługując jednoczesne żądania zamiast je układać w kolejce, przy czym poziom tego funkcjonowania można skonfigurować z linii poleceń lub z panelu administracyjnego.

Najważniejsze są dwa parametry. Czas do pierwszego tokena określa, jak długo trwa, zanim cokolwiek zostanie przesłane w strumieniu. Szybkość generowania pokazuje, jak szybko pojawiają się tokeny po rozpoczęciu pracy. Ponowne wykorzystanie bufora odnosi się do elementów po pierwszym tokenie, pozostawiając drugi nietknięty. Model, który generuje powoli, nadal będzie generował powoli, ale zacznie odpowiadać wcześniej.

Instalacja na Apple Silicon

Wymagania to macOS 15 (Sequoia) lub nowsza wersja, Python w wersjach od 3.11 do 3.13 oraz chip z rodzin M1, M2, M3 lub M4. Istnieją trzy sposoby, z których pierwszy nadaje się dla większości osób.

Zalecanym rozwiązaniem jest aplikacja dla macOS. Pobierz podpisany i notaryzowany plik .dmg z GitHub Releases, przenieś go do folderu Applications i uruchom. Ekran powitalny pomoże wybrać katalog modelu, uruchomi serwer oraz dokona pierwszego pobierania, a aplikacja zainstaluje mały shim do linii poleceń.

Z użyciem Homebrew:

brew tap jundot/omlx https://github.com/jundot/omlx
brew install omlx
omlx start

Z źródła:

git clone https://github.com/jundot/omlx.git
cd omlx
pip install -e .            # core
pip install -e ".[mcp]"     # optional MCP support

Każdy, kto planuje używać GLM-5.2, MiniMax M3 lub Qwen3.5, powinien wiedzieć, że zwykłe polecenie pip install pomija ich własne, dostosowane jądra, w wyniku czego dotknięte modele automatycznie korzystają z znacznie wolniejszej ścieżki. Projekt informuje, że jego połączone jądro prefill jest około 30 razy szybsze na urządzeniu M3 Ultra w przypadku jednego z modeli. Budowa takich jąder wymaga pełnej wersji Xcode, a nie tylko narzędzi Command Line Tools – to najprostszy argument za użyciem pliku DMG.

Zanim cokolwiek podłączysz, upewnij się, że serwer jest aktywny:

curl -s http://localhost:8000/v1/models

Pusta lista jest w porządku, jeśli jeszcze nie został ustawiony żaden katalog modeli.

Ładowanie pierwszego modelu

oMLX automatycznie wykrywa modele językowe, modele języka i obrazu, modele embeddingowe oraz narzędzia do ponownego sortowania w katalogu, na który jest wskazany. Czyta również istniejącą pamięć cache Hugging Face oraz folder LM Studio bezpośrednio, więc nie trzeba niczego ściągać dwukrotnie.

omlx serve --model-dir ~/models

Model powinien być dostosowany do ilości pamięci maszyny, a nie do największego dostępnego pliku. Zostaw cztery lub pięć gigabajtów pamięci dla macOS, a resztę przeznacz na wagi modelu oraz wzrost pamięci cache. Model o wielkości 9B w formacie 4-bit nadaje się dla maszyn z 16 do 32 GB pamięci. Modele klasy 30 do 40B wymagają co najmniej 64 GB pamięci. Największe modele z własnych testów projektu potrzebują pamięci Mac Studio przekraczającej 400 GB.

Modele można pobrać z przeglądarki Hugging Face wbudowanej w panel administracyjny pod adresem http://localhost:8000/admin lub za pomocą dowolnego istniejącego procesu pobierania plików typu hf skierowanego do katalogu z modelami. Prosta prośba o pobranie wygląda jak zwykłe uzupełnienie rozmowy w OpenAI:

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "your-model-name", "messages": [{"role": "user", "content": "Say hi in five words."}]}'

Jeśli powraca kompletacja, oznacza to, że punkt końcowy funkcjonuje poprawnie.

Łączenie Claude Code, Codex, Cursor i OpenCode

Istnieją dwa sposoby, w jakie oMLX łączy się z agentami, a to, który z nich jest stosowany, zależy od tego, w jaki sposób agent przechowuje swoją konfigurację, a nie od stopnia jego obsługi.

Narzędzia z plikiem konfiguracyjnym

OpenClaw, OpenCode, Codex i Pi czytają plik konfiguracyjny, do którego oMLX może uzyskać bezpośredni dostęp – JSON w przypadku pierwszych dwóch oraz TOML w przypadku Codex. Adaptatory integracji zapisują dane do tego pliku, a zakładka Integracje na panelu administracyjnym przekazuje jeden polecenie:

omlx-cli launch codex --model your-model-name --api-key your-key
omlx-cli launch opencode --model your-model-name --api-key your-key
omlx-cli launch pi --model your-model-name --api-key your-key

Uruchomienie tego procesu aktualizuje konfigurację narzędzia i uruchamia agenta w jednym kroku. Wszystkie istniejące ustawienia są najpierw zapisywane jako plik .bak z datą i godziną, dzięki czemu zmiany można odwrócić, jeśli coś pójdzie nie tak.

Hermes Agent i pozycja Copilot

Oba pojawiają się na liście dostępnej za jednym kliknięciem w dokumencie README, a własna dokumentacja Hermes Agenta potwierdza to osobno: wiciarz konfiguracji oferuje opcję dostosowanego punktu końcowego kompatybilnego z OpenAI, umożliwiającą skierowanie go na dowolny lokalny serwer, w tym oMLX. Aby pominąć panel sterowania, należy ręcznie skierować go na http://localhost:8000/v1.

Warto przyjrzeć się ponownie rozwiązaniu Copilot, zanim ktoś będzie na nie polegał. Prawdziwy Copilot Chat od GitHuba autoryzuje się za pomocą OAuth wobec api.githubcopilot.com i nie jest zaprojektowany tak, by przyjmować dowolną lokalną adresację bazową. Dlatego integracja Copilot w jednym kliknięciu albo odnosi się do innego narzędzia o tej samej nazwie, albo wykorzystuje mechanizm, którego nie potwierdza dokumentacja publiczna. Sprawdź zakładkę Integracje bezpośrednio, zanim założysz, że funkcjonuje ona zgodnie z tym, co sugeruje nazwa.

Claude Code

Claude Code odczytuje swój adres serwera podczas uruchamiania z zmiennej środowiskowej ANTHROPIC_BASE_URL, a nie z pliku, który oMLX może edytować, więc ta operacja pozostaje ręczna. Ponieważ oMLX obsługuje domyślną ścieżkę /v1/messages, nie jest potrzebny żaden proxy do tłumaczenia:

export ANTHROPIC_BASE_URL="http://localhost:8000"
export ANTHROPIC_AUTH_TOKEN="local"
export ANTHROPIC_DEFAULT_SONNET_MODEL="your-model-name"
export ANTHROPIC_DEFAULT_OPUS_MODEL="your-model-name"
claude

oMLX oferuje również funkcje przeznaczone specjalnie dla Claude Code. Raporty dotyczące skalowania kontekstu pokazują liczbę tokenów, dzięki czemu funkcja automatycznego skracania działa prawidłowo przy mniejszym oknie kontekstu lokalnego, a mechanizm SSE keep-alive zapobiega przekroczeniu czasu oczekiwania podczas długiego wczytywania danych. Są to rzeczywiste szczegóły specyficzne dla danego agenta, a nie ogólna opcja kompatybilności.

Kursor

Ustawienia lokalnego modelu w Cursor znajdują się w jego interfejsie graficznym, więc nie ma pliku, do którego oMLX mogłoby zapisać dane. W zakładce Ustawienia, pod sekcją Modele, znajdź część dotyczącą API OpenAI i włącz przycisk Override Base URL. Cursor wcześniej zmieniał nazwę tego przycisku, więc jego etykieta może się różnić w zależności od wersji. Wpisz http://localhost:8000/v1 i wpisz dowolną niepustą ścieżkę tekstową do pola API key, ponieważ serwer na localhost jej nie sprawdza. Dodaj załadowany model do sekcji Custom Models podając dokładną nazwę z pliku oMLX, a także wyłącz domyślne modele Cursor, aby nie próbował on również weryfikacji na serwerach OpenAI.

Sprawdzenie poprawności działania

Podczas rzeczywistej sesji panele cache „gorącego” i „zimnego” na panelu administracyjnym powinny stale gromadzić bloki, a nie być resetowane przy każdej próbie. Reset przy każdej próbie zazwyczaj oznacza, że treść z promptu systemowego lub schematu narzędzia jest przestawiana pomiędzy wywołaniami, co zakłóca poprawne funkcjonowanie systemu.

Pomiar szybkości działania cache „gorącego” i „zimnego”

Zamiast przyjmować twierdzenia dostawcy jako fakt, można przeprowadzić test lokalnie. Ustal odpowiednie ustawienia modelu, kwantyzacji, długości kontekstu oraz promptu we wszystkich narzędziach, a następnie zapisz czas rozruchu z zimnego startu, czas potrzebny na uzyskanie pierwszego tokena przy zimnym startu, czas potrzebny na uzyskanie pierwszego tokena przy gorącym startie przy powtarzanym prefiksie, stałą szybkość generowania, maksymalną ilość pamięci używanej, zachowanie systemu po 15–20 symulowanych próbach, czas konfiguracji oraz to, czy wywołania narzędzi nadal są poprawnie interpretowane przez całą sesję.

Oficjalne dane publikowane przez projekt, uzyskane przy użyciu urządzenia M3 Ultra o pojemności 512 GB i wyraźnie należącego do producenta, pokazują szybkość generowania około 45 do 59 tokenów na sekundę dla modelu Qwen3-Coder-Next o rozdzielczości 8 bitów w kontekstach od 1k do 32k. Ciągłe grupowanie zapytań przynosi przyspieszenie szybkości generowania o około 4,14 raza przy ośmiu jednoczesnych zapytaniach w porównaniu z jednym. Jest to górna granica dla najnowocześniejszego sprzętu i nie odzwierciedla wyników, jakie uzyska MacBook Air o pojemności 16 GB.

Jeden z niezależnych artykułów donosi, że przetworzenie kontekstu zawierającego 8700 tokenów zajęło około dwudziestu sekund przy zwykłym MLX, natomiast odpowiedź z wykorzystaniem ciepłej pamięci cache wróciła tak szybko, że autor przeprowadził test ponownie, aby się upewnić. Jest to relacja pochodząca od osób trzecich, a nie kontrolowany test, więc warto go powtórzyć przed zaufaniem tym danym.

Czas rozruchu od zera do pierwszego tokena nie różni się znacząco od przypadku surowego MLX, ponieważ jeszcze nie ma nic do ponownego użycia. Cała korzyść polega na sesjach z powtarzanymi prefiksami, które stanowią większość czasu pracy agenta kodującego.

Kierowanie serwerem

Rozpoczynanie, zatrzymywanie i ponowne uruchamianie, przy czym wersja w tle jest podłączona do terminala:

omlx start          # background service, auto-restarts on crash
omlx stop
omlx restart
omlx serve --model-dir ~/models   # foreground, attached to this terminal

Upewnij się, że jest uruchomiony i serwuje model:

curl -s http://localhost:8000/v1/models

Zapobiegaj konfliktom pomiędzy zużyciem pamięci a resztą systemu:

omlx serve --model-dir ~/models --memory-guard safe
omlx serve --model-dir ~/models --memory-guard-gb 48

Ustawiaj pamięć cache dwuwarstwową bezpośrednio:

omlx serve --model-dir ~/models --paged-ssd-cache-dir ~/.omlx/cache
omlx serve --model-dir ~/models --hot-cache-max-size 20%

Zwiększ współbieżność, gdy kilka agentów łączy się z serwerem jednocześnie:

omlx serve --model-dir ~/models --max-concurrent-requests 16

Instalacje Homebrew przechodzą przez ten sam cykl życia za pomocą brew services:

brew services start omlx
brew services stop omlx
brew services info omlx