Dlaczego LLMOps potrzebuje starego dobrego Jenkinsa?
W świecie generatywnej sztucznej inteligencji narzędzia pojawiają się i znikają z dnia na dzień. Langfuse wyrósł na standard w obszarze obserwowalności (observability) i ewaluacji LLM, ale nie działa w próżni. Jeśli Twoja organizacja opiera swoją infrastrukturę na Jenkinsie, nie ma sensu wymyślać koła na nowo i stawiać osobnych serwerów CI tylko dla modułów AI. Integracja Langfuse z Jenkinsem pozwala wpleść testy promptów i modeli w istniejący cykl wytwórczy oprogramowania.
Poniżej znajdziesz konkretną konfigurację, która pozwoli Ci uruchomić śledzenie (tracing) i ewaluację w ramach pipeline’u Jenkinsa, unikając typowych pułapek początkującego.
Krok 1: Bezpieczne zarządzanie poświadczeniami
Największym błędem, jaki można popełnić na starcie, jest hardcodowanie kluczy API w kodzie repozytorium lub bezpośrednio w skrypcie pipeline'u. Langfuse wymaga trzech zmiennych środowiskowych do poprawnego działania SDK:
LANGFUSE_SECRET_KEYLANGFUSE_PUBLIC_KEYLANGFUSE_HOST(zazwyczajhttps://cloud.langfuse.comlub adres Twojej instancji self-hosted)
W Jenkinsie użyj pluginu Credentials Binding. Przejdź do Manage Jenkins -> Credentials i dodaj nowe wpisy typu "Secret text". Nazwij je intuicyjnie, np. langfuse-secret-key-prod. Dzięki temu Twoje klucze nigdy nie wyciekną do logów konsoli (Jenkins automatycznie je maskuje).
Krok 2: Konfiguracja Jenkinsfile
Poniżej znajduje się przykład deklaratywnego pipeline'u, który uruchamia testy Pythonowe (np. przy użyciu pytest), jednocześnie wysyłając ślady (traces) do Langfuse. Zakładamy, że masz już skonfigurowany agent z Pythonem.
pipeline {
agent any
environment {
// Mapowanie credentials z Jenkinsa na zmienne środowiskowe wymagane przez Langfuse SDK
LANGFUSE_SECRET_KEY = credentials('langfuse-secret-key')
LANGFUSE_PUBLIC_KEY = credentials('langfuse-public-key')
LANGFUSE_HOST = 'https://cloud.langfuse.com'
OPENAI_API_KEY = credentials('openai-api-key') // Jeśli używasz OpenAI
}
stages {
stage('Setup') {
steps {
sh 'pip install -r requirements.txt'
sh 'pip install langfuse'
}
}
stage('LLM Evaluation') {
steps {
// Uruchomienie testów, które generują traces
sh 'pytest tests/test_llm_logic.py'
}
}
}
}
Krok 3: Obsługa asynchroniczności (Flush)
To jest moment, w którym 90% początkujących napotyka problem. SDK Langfuse (zarówno Python jak i JS/TS) wysyłają zdarzenia asynchronicznie w tle, aby nie spowalniać głównego wątku aplikacji. W środowisku CI, takim jak Jenkins, kontener jest zabijany natychmiast po zakończeniu komendy pytest.
Jeśli proces zakończy się zbyt szybko, SDK nie zdąży wysłać danych do serwera Langfuse. Efekt? Zielony build w Jenkinsie, ale brak danych w dashboardzie Langfuse.
Rozwiązanie
W swoich testach lub skryptach ewaluacyjnych musisz wymusić wysłanie danych przed zakończeniem procesu. W Pythonie użyj metody flush():
from langfuse import Langfuse
langfuse = Langfuse()
# ... Twój kod testowy i generowanie trace'ów ...
# Na samym końcu testu lub w fixture teardown:
langfuse.flush()
Dobrą praktyką jest umieszczenie langfuse.flush() w pytest fixture z zasięgiem sesji (session-scoped fixture), aby upewnić się, że dane zostaną wysłane po wszystkich testach.
Najlepsze praktyki: Tagowanie Buildów
Gdy Twój Jenkins zacznie mielić buildy, w Langfuse szybko zrobi się bałagan. Nie będziesz wiedział, który trace pochodzi z produkcji, który z lokalnego developmentu, a który z CI.
Wykorzystaj zmienne środowiskowe Jenkinsa, aby automatycznie tagować każdy trace. Jenkins udostępnia zmienną BUILD_NUMBER oraz GIT_COMMIT. Przekaż je do SDK Langfuse przy inicjalizacji lub poprzez atrybuty trace'a.
trace = langfuse.trace(
name="LLM-CI-Test",
tags=["jenkins", f"build-{os.environ.get('BUILD_NUMBER')}", "staging"]
)
Dzięki temu w panelu Langfuse będziesz mógł filtrować wyniki po konkretnym numerze builda z Jenkinsa, co drastycznie skraca czas debugowania regresji.
Bramki jakości (Quality Gates)
Samo wysłanie danych to za mało. Jenkins powinien wiedzieć, czy model działa poprawnie. Nie polegaj tylko na tym, czy kod rzucił wyjątek. Zaimplementuj asercje oparte na wynikach ewaluacji (scores).
Jeśli używasz ewaluacji model-based (np. inny LLM oceniający odpowiedź), Twój skrypt testowy powinien pobrać wynik tej oceny i zwrócić kod błędu (exit code 1), jeśli wynik spadnie poniżej progu. Wtedy Jenkins oznaczy build jako FAILED, blokując potencjalnie wadliwe wdrożenie na produkcję.