Bielik MCP
Materiał przygotowany z pomocą AI
Lokalny polski model językowy Bielik zintegrowany z Claude Code jako narzędzie MCP (Model Context Protocol). Pozwala Claude’owi wywoływać Bielika w trakcie sesji — np. do generowania tekstów po polsku, tłumaczeń czy redakcji treści.
Architektura
Claude Code
|
| stdio (MCP protocol)
|
bielik.py (FastMCP server)
|
| HTTP (OpenAI-compatible API)
|
LM Studio (127.0.0.1:1234)
|
bielik-4.5b-v3.0-instruct-mlx
Przepływ: Claude Code uruchamia skrypt bielik.py jako proces potomny (transport stdio). Skrypt wystawia narzędzie ask_bielik przez protokół MCP. Gdy Claude wywołuje to narzędzie, skrypt wysyła zapytanie HTTP do LM Studio, które serwuje model Bielik lokalnie.
Komponenty
Model
- Bielik 4.5B v3.0 Instruct — polski LLM oparty na Mistral 7B, dostrojony na polskich danych
- Wariant MLX (kwantyzacja dla Apple Silicon)
- Serwowany przez LM Studio na
127.0.0.1:1234(API kompatybilne z OpenAI)
Skrypt MCP
Plik: ~/.claude/mcp-servers/bielik.py
#!/usr/bin/env python3
"""MCP server exposing a local Bielik model (via LM Studio) as a tool."""
import json, os, urllib.request, urllib.error
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("bielik")
API_BASE = os.environ.get("LLM_API_BASE", "http://localhost:1234/v1")
MODEL = os.environ.get("LLM_MODEL", "bielik-4.5b-v3.0-instruct-mlx")
def _chat(prompt, system="", temperature=0.7, max_tokens=2048,
top_p=None, min_p=None, top_k=None,
repeat_penalty=None, seed=None, stop=None):
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
body = {
"model": MODEL,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens,
}
if top_p is not None: body["top_p"] = top_p
if min_p is not None: body["min_p"] = min_p
if top_k is not None: body["top_k"] = top_k
if repeat_penalty is not None: body["repeat_penalty"] = repeat_penalty
if seed is not None: body["seed"] = seed
if stop is not None: body["stop"] = stop
payload = json.dumps(body).encode()
req = urllib.request.Request(
f"{API_BASE}/chat/completions",
data=payload,
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=120) as resp:
data = json.loads(resp.read())
return data["choices"][0]["message"]["content"]
@mcp.tool()
def ask_bielik(prompt, system="", temperature=0.7, max_tokens=2048,
top_p=None, min_p=None, top_k=None,
repeat_penalty=None, seed=None, stop=None):
"""Ask the local Bielik model (Polish LLM) a question."""
try:
return _chat(prompt, system, temperature, max_tokens,
top_p, min_p, top_k, repeat_penalty, seed, stop)
except urllib.error.URLError as e:
return f"Error connecting to LLM server at {API_BASE}: {e}"
except Exception as e:
return f"Error: {e}"
if __name__ == "__main__":
mcp.run(transport="stdio")Cechy skryptu:
- Timeout 120 s na odpowiedź z LM Studio
- Parametry modelu (
API_BASE,MODEL) konfigurowane zmiennymi środowiskowymi - Dodatkowe parametry samplingu (
top_p,min_p,top_k,repeat_penalty,seed,stop) — opcjonalne, przekazywane do API tylko gdy ustawione
Konfiguracja MCP w Claude Code
Konfiguracja musi znajdować się w ~/.claude.json w sekcji projects:
{
"projects": {
"//Users/username/workspace": {
"mcpServers": {
"bielik": {
"type": "stdio",
"command": "/Users/username/.pyenv/versions/3.12.12/bin/python3",
"args": ["/Users/username/.claude/mcp-servers/bielik.py"],
"env": {
"LLM_API_BASE": "http://127.0.0.1:1234/v1",
"LLM_MODEL": "bielik-4.5b-v3.0-instruct-mlx"
}
}
}
}
}
}Dodawanie z CLI:
claude mcp add-json bielik '{
"type": "stdio",
"command": "/Users/username/.pyenv/versions/3.12.12/bin/python3",
"args": ["/Users/username/.claude/mcp-servers/bielik.py"],
"env": {
"LLM_API_BASE": "http://127.0.0.1:1234/v1",
"LLM_MODEL": "bielik-4.5b-v3.0-instruct-mlx"
}
}'Wymagania
- LM Studio uruchomione z załadowanym modelem Bielik
- Python 3.12+ z pakietem
mcp(pip install mcp) - Claude Code z konfiguracją MCP w
~/.claude.json
Wnioski z wdrożenia
- Konfiguracja MCP działa tylko z
~/.claude.json(kluczprojects→ ścieżka projektu →mcpServers). Pliki~/.claude/mcp.jsoni~/.claude/settings.jsonsą ignorowane. Claude wielokrotnie sugerował tę ścieżkę rozwiązania problemu. - Po zmianie konfiguracji MCP wymagany jest restart Claude Code.
- Subagenty Claude Code dziedziczą połączenia MCP z sesji nadrzędnej — nie mogą testować nowych serwerów MCP.
- Transport
stdiojest prostszy niż HTTP/SSE — Claude Code sam zarządza cyklem życia procesu. - Alternatywą dla LM Studio jest Ollama. Nie testowałem tego, ponieważ wymagałoby to ponownego pobrania modelu.
Zastosowania
- Generowanie i redakcja tekstów po polsku
- Weryfikacja poprawności językowej
Test: korekta językowa bazy wiedzy
Bielik został przetestowany jako korektor tekstów technicznych w języku polskim. Zadaniem było sprawdzenie 30 plików Markdown bazy wiedzy pod kątem błędów ortograficznych, gramatycznych i stylistycznych.
Metodyka
Pliki były wysyłane fragmentami (po 3-8 akapitów), z pominięciem frontmatter YAML i wikilinków. Każde zapytanie zawierało:
- System prompt:
"Jesteś korektorem tekstów technicznych w języku polskim. Sprawdzasz wyłącznie poprawność językową: ortografię, gramatykę, interpunkcję i styl. Nie zmieniasz treści merytorycznej ani terminologii technicznej." - Temperatura: 0.2 (niska, dla determinizmu)
- Max tokens: 512
- Instrukcja w prompcie:
"Wypisz TYLKO znalezione błędy w formacie: BŁĄD: [fragment z błędem] → [poprawna wersja]. Jeśli nie ma błędów, napisz OK."
Przykładowy prompt:
Sprawdź poniższy tekst pod kątem błędów gramatycznych,
ortograficznych i stylistycznych. Wypisz TYLKO znalezione
błędy w formacie: "BŁĄD: [fragment] → [poprawka]".
Jeśli nie ma błędów, napisz "OK".
Tekst (plik: GIS.md):
---
Wiedza domenowa: systemy informacji geograficznej, analizy
przestrzenne, dane rastrowe i wektorowe.
Ta sekcja jest w trakcie budowy. Nowe materialy beda
dodawane sukcesywnie.
Powiazane opracowania
[...]
Zobacz takze
---
Wyniki
1. Brak wykrywania brakujących polskich znaków diakrytycznych
Tekst GIS.md zawierał 5 słów bez polskich znaków: materialy (materiały), beda (będą), Powiazane (Powiązane), narzedzia (narzędzia), takze (także). Bielik nie rozpoznał żadnego z nich jako błędu:
BŁĄD: "Ta sekcja jest w trakcie budowy. Nowe materialy beda
dodawane sukcesywnie."
→ OK (tekst poprawny)
[...analogicznie dla każdego akapitu...]
Tekst jest poprawny pod względem gramatycznym, ortograficznym
i stylistycznym. Nie zawiera błędów.
2. Format odpowiedzi
Model nie stosował się do instrukcji formatu. Zamiast zwięzłego OK lub listy błędów, generował rozbudowane odpowiedzi, w których wypisywał każde zdanie wejściowe jako pozycję, a następnie oznaczał je jako poprawne. Typowa odpowiedź na 5 akapitów poprawnego tekstu miała 15-20 linii zamiast jednego słowa OK.
3. Fałszywe sugestie
Dla pliku Bielik MCP.md model zasugerował m.in.:
Claude'owi→Claude'a— błędna sugestia zamiany celownika na dopełniaczzintegrowany→zintegrowanego— błędna forma- Zgłaszanie brakujących spacji w identyfikatorach kodu (
bielik.py,ask_bielik) — fałszywe alarmy wynikające z nierozpoznania formatowania Markdown
4. Poprawne rozpoznania
Dla pliku Hydrologia.md model zasugerował zamianę dwukropka na kropkę w zdaniu Główne punkty styku między cyklami:. Sugestia dyskusyjna — dwukropek jest poprawny jako wprowadzenie do tabeli.
Podsumowanie testu
| Aspekt | Ocena |
|---|---|
| Wykrywanie brakujących diakrytyków | Brak — model nie rozróżnia takze od także |
| Wykrywanie błędów gramatycznych | Ograniczone — generuje fałszywe alarmy |
| Przestrzeganie formatu odpowiedzi | Słabe — ignoruje instrukcje o zwięzłości |
| Rozpoznawanie składni Markdown | Brak — traktuje identyfikatory kodu jako tekst |
Model bielik-4.5b-v3.0-instruct w wariancie MLX nie sprawdza się w roli korektora tekstu polskiego. Główne ograniczenie to brak rozróżniania słów z diakrytykami i bez nich, co czyni go nieprzydatnym do wykrywania najczęstszego typu błędów w plikach pisanych na klawiaturze bez polskiego układu. Wszystkie realne błędy (ok. 30 poprawek w 10 plikach) zostały wykryte przez Claude’a bezpośrednio.
Możliwe kierunki poprawy: testowanie większych modeli Bielik (11B, 20B). Prompt few-shot i dodatkowe parametry samplingu zostały przetestowane w teście 3 — nie przyniosły przełomu.
Test 2: wpływ parametrów na wykrywalność
Dodatkowy test sprawdzający, czy zmiana parametrów max_tokens i temperature poprawia wykrywalność brakujących diakrytyków. Ten sam tekst testowy (GIS.md z 5 celowymi błędami: materialy, beda, Powiazane, Narzedzia, takze) został wysłany 20 razy — dla każdej kombinacji parametrów.
Metodyka
- max_tokens: 1024, 2048, 4096, 8192, 16384
- temperature: 0.2, 0.4, 0.6, 0.8
- System prompt i prompt użytkownika: identyczne jak w teście 1
- Łącznie 20 wywołań (5 × 4)
Wyniki — liczba jawnie zgłoszonych błędów (z 5)
| max_tokens | T=0.2 | T=0.4 | T=0.6 | T=0.8 |
|---|---|---|---|---|
| 1024 | 2/5 | 4/5 ¹ | ~2/5 ² | 4/5 ¹ |
| 2048 | 2/5 | 0/5 ³ | 5/5 | 4/5 ¹ |
| 4096 | 2/5 | 1/5 | 5/5 ⁴ | 5/5 ⁵ |
| 8192 | ~4/5 ⁶ | 0/5 ³ | 1/5 ⁷ | 3/5 |
| 16384 | 3/5 | 0/5 ⁸ | 5/5 ⁵ | 3/5 |
¹ Powiazane → Połączone — błędna poprawka (zmiana znaczenia zamiast dodania diakrytyku)
² Sprzeczny wynik: pisze „OK” a potem „warto rozważyć zmianę”
³ Wszystkie 5 błędów oznaczone jako „poprawne”
⁴ Halucynacje formatowania (dodawanie kursywy, myślników, zmiana struktury tekstu)
⁵ Błędne opisy poprawek („brak spacji” zamiast „brak diakrytyku”)
⁶ Fałszywa edycja nagłówka „Wiedza domenowa” (zmiana na formę w nawiasie)
⁷ Fałszywa sugestia: dane rastrowe i wektorowe → dane rastrowe oraz wektorowe
⁸ Najgorszy wynik: 0/5 + fałszywa poprawka domenowa → domena
Obserwacje
-
Brak stabilności — identyczny prompt daje od 0/5 do 5/5 w zależności od parametrów. Model jest niedeterministyczny nawet przy T=0.2.
-
T=0.2 konsekwentnie słabe — zawsze wykrywa tylko
materialy+beda(2/5) niezależnie od max_tokens. Niska temperatura blokuje rozpoznanie pozostałych błędów. -
T=0.4 niestabilne — daje 0/5 (2048, 8192, 16384) albo 4/5 (1024). Najgorsza temperatura.
-
T=0.6 najlepsza — 5/5 w trzech konfiguracjach (2048, 4096, 16384), ale 1/5 przy 8192.
-
T=0.8 przyzwoite ale z fałszywkami — 3-5/5 wykrywalności, ale generuje błędne poprawki (
Połączone,Podane materiały,brak spacji). -
max_tokens nie ma wpływu — wyniki nie poprawiają się systematycznie ze wzrostem limitu tokenów. 1024 daje porównywalne rezultaty do 16384.
-
Sprzeczność wewnętrzna — w 6/20 przypadków model pisze „OK” przy błędach, ale poprawia je w „wersji poprawionej” na końcu odpowiedzi.
-
Fałszywe poprawki — w 8/20 przypadków model generuje przynajmniej jedną fałszywą sugestię (zmiana znaczenia, dodawanie kropek do nagłówków, „brak spacji” jako opis brakującego diakrytyku).
Podsumowanie testu 2
Najlepsza konfiguracja: T=0.6, max_tokens 2048 — jedyna dająca 5/5. Niestabilność wyników oznacza jednak, że nawet ta konfiguracja nie jest wiarygodna jako narzędzie korektorskie. Zwiększanie max_tokens powyżej 2048 nie poprawia jakości detekcji.
Test 3: dodatkowe parametry samplingu
Test wpływu parametrów top_p, min_p, top_k i repeat_penalty na wykrywalność brakujących diakrytyków. Bazowa konfiguracja z testu 2: T=0.6, max_tokens=2048. Zmieniano jeden parametr na raz. Ten sam tekst testowy (5 celowych błędów) i ten sam system prompt co w testach 1-2. Łącznie 22 wywołania w 3 fazach.
Faza 1: Pojedyncze parametry (12 testów)
| # | Parametr | Wartość | Wykryte/5 | Prawidłowe | Fałszywe | Uwagi |
|---|---|---|---|---|---|---|
| 1 | top_p | 0.5 | 0 (jawnie) | — | 0 | Każdy fragment „OK”, ale poprawiony tekst na końcu ma 5/5. |
| 2 | top_p | 0.7 | 2/5 | 2 | 0 | Pominął materialy, beda, Powiazane. |
| 3 | top_p | 0.9 | 5/5 | 4 + 1 wątpliwy | 0 | Drugi najlepszy wynik. |
| 4 | min_p | 0.02 | ~3/5 | Chaotyczne | 1 | Fałszywa poprawka Wiedza→Wiedzy. |
| 5 | min_p | 0.05 | 3/5 | 3 | 0 | Pominął Powiazane. |
| 6 | min_p | 0.1 | ~4/5 | — | 1 | Zignorował format, podał tekst zamiast listy. |
| 7 | top_k | 20 | 0 (jawnie) | — | 0 | Jak top_p=0.5: „OK” + poprawiony tekst. |
| 8 | top_k | 40 | 4/5 | 4 | 1 | domenowa→domenaowa (nowy błąd w poprawce). |
| 9 | top_k | 80 | 3/5 | 3 | 2+ | Fałszywe uwagi o spacjach, małych literach. |
| 10 | repeat_penalty | 1.05 | 5/5 | 5 | 0 | Najlepszy wynik. Jedyny czysty 5/5. |
| 11 | repeat_penalty | 1.1 | 4/5 | 4 | 1 | domenowa→domenalna (zmiana terminologii). |
| 12 | repeat_penalty | 1.2 | ~1/5 | — | 1 | domenowa→domniemana (zmiana znaczenia). |
Faza 2: Kombinacje (6 testów)
| # | Parametry | Wykryte/5 | Fałszywe | Uwagi |
|---|---|---|---|---|
| 1 | top_p=0.9 + repeat_penalty=1.05 | 5/5 | 1 | „Zbędny myślnik” — fałszywy alarm. |
| 2 | top_p=0.9 + min_p=0.05 | 1 (jawnie) | 0 | „OK” + poprawiony tekst. |
| 3 | repeat_penalty=1.05 + min_p=0.05 | 2/5 | 2 | min_p pogorszyło wynik. |
| 4 | top_p=0.9 + rp=1.05 + min_p=0.05 | 1 (jawnie) | 0 | Trzy parametry = konfuzja formatu. |
| 1 bis | powtórzenie testu 1 | ~3/5 | 3+ | Halucynacje: „Zwiazane”, „taze→tez”. |
| — | powtórzenie samego rp=1.05 (Faza 1 #10) | 4/5 | 0 | takze→również (zmiana znaczenia, nie diakrytyk). |
Wniosek: Łączenie parametrów nie poprawia wyników. repeat_penalty=1.05 sam daje najstabilniejsze rezultaty (5/5 lub 4/5, 0 fałszywych).
Faza 3: Długi tekst (~41 brakujących diakrytyków)
Konfiguracja: T=0.6, max_tokens=2048, repeat_penalty=1.05. Tekst hydrologiczny (4 akapity, ~80 słów).
Prompt standardowy (3 próby):
| # | Poprawione w tekście | Jawnie wylistowane | Fałszywe | Uwagi |
|---|---|---|---|---|
| 1 | ~30+ | 6 grupowych | 1 | niepokrywajacy→nieprzykrywający (zmiana znaczenia) |
| 2 | ~38 | 7+13 szczegółowych | 2 | intercepcje→intercepcji, ewapotranspiracje→ewaporacyjno-transpiracji |
| 3 | ~35 | 7 grupowych | 3 | Zmieniał treść merytoryczną mimo instrukcji. |
Prompt few-shot (3 próby):
| # | Poprawione w tekście | Jawnie wylistowane | Fałszywe | Uwagi |
|---|---|---|---|---|
| 1 | ~30+ | 7 | 0 | Format zdezorientowany — „poprawna forma” zamiast wskazania błędu. |
| 2 | ~38 | 13 szczegółowych | 2 | Najlepszy wynik few-shot, zbieżny ze standardowym #2. |
| 3 | ~35 | 9 | 4 | Fiksował się na przykładach z promptu zamiast na tekście. |
Obserwacje testu 3
-
repeat_penalty=1.05to jedyny parametr dający czyste 5/5 na krótkim tekście bez fałszywych alarmów. Pozostałe parametry albo pogarszają wyniki, albo są niestabilne. -
Ranking parametrów: repeat_penalty=1.05 > top_p=0.9 > top_k=40 > min_p (wszystkie wartości pogarszają). repeat_penalty 1.1 wprowadza halucynacje.
-
Niskie wartości top_p ( 0.7) i top_k (=20) powodują, że model „widzi” błędy (poprawia w tekście końcowym), ale nie potrafi ich wylistować w żądanym formacie.
-
Model lepiej generuje poprawiony tekst niż listuje błędy. Na długim tekście naprawia 75-93% diakrytyków w poprawionym tekście, ale w jawnej liście grupuje i gubi pozycje.
-
Prompt few-shot nie poprawił wyników — w jednym przypadku model fiksował się na przykładach z promptu zamiast analizować tekst.
-
Niestabilność pozostaje problemem — nawet najlepsza konfiguracja daje różne wyniki przy powtórzeniach. Parametr
seednie zapewnił deterministyczności (prawdopodobnie ograniczenie backendu MLX w LM Studio).
Podsumowanie testu 3
Optymalna konfiguracja Bielika 4.5B jako korektora: T=0.6, max_tokens=2048, repeat_penalty=1.05. Dla dłuższych tekstów lepsze podejście to generowanie poprawionej wersji i porównanie diff, zamiast oczekiwania listy błędów. Model nie nadaje się jako samodzielny korektor — zawsze wymaga weryfikacji człowieka.
Zobacz także
- IT — indeks narzędzi informatycznych
- Komendy terminala - Linux i macOS — uruchamianie skryptu MCP z poziomu powłoki
- MCP — Model Context Protocol — specyfikacja protokołu
- Bielik — SpeakLeash — modele Bielik na HuggingFace