Files
agentic-codemod-pipeline/docs/adr/0005-backend-llm-per-platforma.md
2026-08-29 13:17:59 +02:00

3.8 KiB

ADR-0005: Backend LLM wybierany per platforma, atrapa jako test double

  • Status: przyjęty
  • Data: 2026-08-29

Kontekst

Docelowo pipeline korzysta z vLLM wystawionego na OpenShifcie. Do pracy nad samym pipeline'em potrzebny jest jednak model uruchamialny lokalnie - i tu kończy się jednorodność: nie istnieje jedna komenda uruchamiająca vLLM na Linuksie i na macOS.

  • Linux z GPU NVIDIA: kontener vllm/vllm-openai, ścieżka najbliższa produkcji.
  • macOS na Apple Silicon: Docker nie ma dostępu do Metala, więc kontener odpada. Zostaje natywny plugin społecznościowy vllm-project/vllm-metal (backend MLX), instalowany skryptem do własnego venva, wymagający arm64 Pythona 3.12 i Xcode CLT.
  • Maszyna bez GPU i bez Apple Silicon: żaden z powyższych nie ma sensu.

Osobny problem: testy. Tryb --offline sprawdza RuleBrain, ale nie dotyka tego, co jest w tym projekcie najbardziej kruche - budowy agentów z definicji APM, wywoływania narzędzi przez model i parsowania strukturalnych wyjść. Uzależnienie tego testu od GPU oznaczałoby, że nie uruchomi go nikt poza jedną maszyną.

Decyzja

Kontrakt jest jeden: endpoint zgodny z API OpenAI pod CODEMOD_LLM_BASE_URL. Backendy różnią się wyłącznie tym, jak ten endpoint powstaje. Konfiguracja mieszka w llm/models.yml (jedno źródło prawdy: adresy, modele per rola, argumenty serwera), a task llm:up wykrywa platformę i uruchamia właściwy wariant:

Backend Kiedy Jak
vllm-gpu Linux + NVIDIA + Docker docker compose --profile vllm-gpu
vllm-metal macOS Apple Silicon natywny plugin MLX, vllm serve
ollama awaryjnie, obie platformy natywnie (Metal) lub kontener
mock testy, CI llm/mock_server.py, stdlib, bez pobierania

Atrapa (mock) to test double, nie symulator modelu: odpowiada z góry ustalonymi wywołaniami narzędzi i strukturami zestrojonymi z fixture'em acme-app, a routing odpowiedzi opiera na nazwie agenta wstrzykiwanej przez agno do komunikatu systemowego. Dzięki niej tests/test_llm_path.py przepuszcza pełny przebieg przez LlmBrain na każdym MR, bez GPU i bez sieci.

Konsekwencje

Pozytywne

  • Projekt startuje od zera na Linuksie i na macOS jedną komendą; różnice platformowe są schowane za task llm:up, a nie rozsypane po README.
  • Ścieżka agentowa jest testowana automatycznie, nie tylko ręcznie na czyjejś maszynie.
  • Podmiana modelu lub backendu to zmiana w llm/models.yml, nie w kodzie.
  • Wszystkie backendy wymuszają --enable-auto-tool-choice z parserem hermes; bez tego vLLM zwraca opis wywołania w treści zamiast tool_calls i agent coder nie tknąłby żadnego pliku.

Negatywne

  • Cztery ścieżki uruchomieniowe do utrzymania. Ograniczamy koszt tym, że wiedza o nich jest w jednym pliku YAML plus jednym skrypcie, a nie w zadaniach.
  • vllm-metal jest pluginem społecznościowym - może się rozjechać z upstreamem vLLM. Dlatego Ollama zostaje jako wariant awaryjny na macOS.
  • Atrapa jest zestrojona z fixture'em: zmiana fixture'u wymaga aktualizacji scenariusza. To świadomy koszt - alternatywą jest brak testu tej ścieżki.
  • Model 4B wystarcza do sprawdzenia hydrauliki, ale nie do realnych migracji. Do pracy trzeba większego - stąd tabela rekomendacji per rola w llm/models.yml.

Rozważane alternatywy

  • Tylko vLLM, macOS niech używa zdalnego endpointu. Odpada: uniemożliwia pracę offline i uzależnia każdego developera od środowiska współdzielonego.
  • Tylko Ollama. Prostsze, ale rozjeżdża się z produkcją (inne API tool-callingu, inne kwantyzacje), więc testy przestałyby cokolwiek mówić o zachowaniu na vLLM.
  • Brak atrapy, testy tylko na realnym modelu. Niedeterministyczne i niedostępne w CI; test, który czasem przechodzi, jest gorszy niż brak testu.