CodeWorlds
Powrót do kolekcji
Przewodnik14 min czytaniaZespół CodeWorlds

Jina AI, wagi modeli na licencji niekomercyjnej

Modele osadzeń i rerankery Jina AI mają wagi na Hugging Face, ale niemal wszystkie z tagiem cc-by-nc-4.0. Licencja, cennik za token i czyste HTTP zamiast SDK.

Jina AI, wagi modeli na licencji niekomercyjnej

Jina AI wydaje modele osadzeń tekstu i rerankery dostępne zarówno przez płatne API, jak i jako wagi na Hugging Face. Wagi wyglądają na otwarte, ale niemal cała bieżąca rodzina ma tag cc-by-nc-4.0, czyli licencję zakazującą użycia komercyjnego. To pierwsza rzecz do sprawdzenia, zanim ktokolwiek w zespole zaplanuje uruchomienie tych modeli na własnym sprzęcie.

Co Jina AI dzisiaj sprzedaje

Publiczny wykaz modeli pod adresem api.jina.ai/v1/models zwraca 29 pozycji i to jest najlepszy pojedynczy obraz oferty, bo strona marketingowa nie renderuje się bez JavaScriptu. W wykazie siedzą cztery grupy.

Pierwsza to modele osadzeń tekstu: jina-embeddings-v5-text-small i jina-embeddings-v5-text-nano, wcześniejsze jina-embeddings-v4 i jina-embeddings-v3, cała rodzina jina-embeddings-v2-base-* w wariantach angielskim, niemieckim, hiszpańskim, chińskim i kodowym, oraz osobne jina-code-embeddings-0.5b i jina-code-embeddings-1.5b. Druga to rerankery: jina-reranker-v3.5, jina-reranker-v3, jina-reranker-m0 przyjmujący obraz razem z tekstem, jina-reranker-v2-base-multilingual i trzy stare warianty v1. Trzecia to modele multimodalne: jina-clip-v2, jina-embeddings-v5-omni-small oraz jina-embeddings-v5-omni-nano przyjmujące tekst, obraz, wideo i dźwięk, a także jina-vlm. Czwarta to modele od zamiany HTML na markdown: ReaderLM-v2, reader-lm-0.5b i reader-lm-1.5b.

Okna kontekstu różnią się mocno i to bywa zaskoczeniem przy migracji między wersjami. jina-embeddings-v3 przyjmuje 8192 tokeny, jina-embeddings-v4 i jina-embeddings-v5-text-small po 32768, a jina-embeddings-v5-text-nano znowu 8192. Rerankery mają najwięcej: jina-reranker-v3 deklaruje 134144 tokeny, a jina-reranker-v3.5 131072. Stary jina-reranker-v2-base-multilingual ma tylko 1024 tokeny, co przy typowym fragmencie dokumentacji oznacza obcięcie w połowie. ReaderLM-v2 deklaruje 524288 tokenów, bo jego zadaniem jest przełknięcie całej surowej strony.

Do tego dochodzą dwie usługi bez modelu w nazwie: czytnik stron pod r.jina.ai i wyszukiwarka pod s.jina.ai.

Licencja wag, czyli sedno sprawy

Sprawdziłem metadane na Hugging Face przez publiczne API i wynik jest jednoznaczny. Tag license:cc-by-nc-4.0 noszą jina-embeddings-v3, jina-embeddings-v5-text-small, jina-embeddings-v5-text-nano, jina-embeddings-v5-omni-small, jina-reranker-v3, jina-reranker-v3.5, jina-reranker-v2-base-multilingual, jina-clip-v2, jina-colbert-v2, jina-code-embeddings-1.5b, jina-vlm, ReaderLM-v2 oraz reader-lm-1.5b. Creative Commons Uznanie autorstwa i Użycie niekomercyjne 4.0 zabrania wykorzystania utworu w sposób nakierowany na korzyść handlową. Produkcyjne wyszukiwanie w płatnym produkcie mieści się w tym zakazie.

Wyjątkiem jest generacja druga z 2023 roku. jina-embeddings-v2-base-en i jina-embeddings-v2-small-en mają tag license:apache-2.0. To najstarsze i najsłabsze modele w rodzinie, ale jedyne, które wolno uruchomić u siebie w produkcie zarobkowym bez pytania nikogo o zgodę.

Osobny przypadek to jina-embeddings-v4. W metadanych Hugging Face nie ma w ogóle tagu licencji, więc automat zbierający zależności zobaczy puste pole i najczęściej przemilczy sprawę. W repozytorium leży natomiast plik LICENSE, a w nim tekst zatytułowany „Qwen RESEARCH LICENSE AGREEMENT" z datą wydania 19 września 2024 roku, wystawiony przez Alibaba Cloud. Punkt 2a przyznaje prawa „FOR NON-COMMERCIAL PURPOSES ONLY", a punkt 1i definiuje „Non-Commercial" jako użycie wyłącznie badawcze lub ewaluacyjne. Model powstał na bazie Qwen2.5-VL, więc odziedziczył licencję modelu bazowego. Brak tagu jest tu gorszy niż tag zakazujący komercji, bo usypia czujność.

Jest jeszcze druga strona tej samej niespójności. Modele z tagiem cc-by-nc-4.0 w większości nie mają w repozytorium żadnego pliku licencyjnego. Wylistowałem zawartość repozytoriów jina-embeddings-v3 i jina-reranker-v3: są tam wagi, tokenizer, konfiguracja i README, ale pliku LICENSE nie ma. Licencja istnieje wyłącznie jako pole w nagłówku karty modelu. Jeśli ktoś pobiera wagi skryptem i archiwizuje katalog, w archiwum nie zostaje żaden ślad ograniczenia.

Warto sprawdzić to samodzielnie przed każdą aktualizacją modelu, bo pole potrafi się zmienić między wydaniami.

Code
Bash
# tag licencji z metadanych, pole license z karty modelu i pliki licencyjne w repozytorium
for m in jinaai/jina-embeddings-v5-text-small \
         jinaai/jina-embeddings-v4 \
         jinaai/jina-embeddings-v3 \
         jinaai/jina-embeddings-v2-base-en \
         jinaai/jina-reranker-v3.5; do
  echo "== $m"
  curl -s "https://huggingface.co/api/models/$m" \
    | jq -r '[
        (.tags[] | select(startswith("license"))) // "BRAK-TAGU",
        (.cardData.license // "brak-pola"),
        ([.siblings[].rfilename | select(test("LICEN";"i"))] | join(",") // "brak-pliku")
      ] | @tsv'
done

Praktyczny wniosek jest prosty. Wagi Jina AI nadają się do porównania jakości w notatniku, do pracy badawczej i do prototypu, którego nikt nie sprzedaje. Do produktu zarobkowego zostaje płatne API albo model bazowy innego dostawcy. Firma prowadzi sprzedaż licencji komercyjnych przez formularz kontaktowy, ale cennik takiej licencji nie jest publiczny, więc nie da się go tu podać.

Pakiet jina to dawny framework, nie SDK

Osoba szukająca biblioteki klienckiej trafia najczęściej na pakiet PyPI o nazwie jina i to jest ślepa uliczka. Najnowsza wersja tego pakietu to 3.34.0 wgrana 24 marca 2025 roku, czyli ponad rok bez wydania. Opis w rejestrze brzmi „Multimodal AI services and pipelines with cloud-native stack: gRPC, Kubernetes, Docker, OpenTelemetry, Prometheus, Jaeger", co nie ma nic wspólnego z wywołaniem modelu osadzeń. To framework do budowania rozproszonych usług wielomodalnych, produkt z wcześniejszego etapu życia firmy.

Adres podany w polu home_page prowadzi do github.com/jina-ai/jina, a ten przekierowuje do github.com/jina-ai/serve. Repozytorium zostało przemianowane, a kanał wydań potwierdza, że ostatnim tagiem jest v3.34.0 z 24 marca 2025 roku. Pole license w rejestrze PyPI ma wartość „Apache 2.0" i zgadza się to z plikiem LICENSE w repozytorium: pełny tekst Apache 2.0 na 193 liniach, poprzedzony nagłówkiem „Copyright 2020-2021 Jina AI Limited". Tu akurat trzy źródła mówią to samo.

Po stronie npm jest gorzej. Pakiet o nazwie jina w rejestrze npm nie pochodzi od tej firmy: należy do konta alismithy, ma wersję 1.0.22 i licencję ISC. Instalacja go w projekcie nie da żadnego dostępu do modeli. Oficjalny klient JavaScript nazywa się jinaai, ma wersję 0.2.20 wydaną 25 stycznia 2024 roku, licencję Apache-2.0 i jedną zależność, tslib w zakresie ^2.5.3. Repozytorium jina-ai/jinaai-js istnieje i zawiera plik LICENSE z tekstem Apache 2.0. Dwa i pół roku bez wydania oznacza jednak, że pakiet nie zna modeli v4 ani v5.

Po stronie Pythona nie ma dziś oficjalnego klienta w ogóle. Nazwy jina-ai, jina-embeddings i jina-reranker zwracają w PyPI kod 404.

Jak dzisiaj się integrować

Skoro pakietu nie ma, zostaje czyste HTTP i to jest odpowiedź na pytanie o SDK. Nie jest to obejście ani prowizorka, tylko dzisiejsza droga podstawowa. Oba końcowe punkty wymagają nagłówka Authorization i zwracają bez niego kod 401 z treścią AUTH_MISSING_API_KEY.

Code
Bash
# osadzenia: model, input, task, oraz opcjonalne embedding_type i normalized
curl -s https://api.jina.ai/v1/embeddings \
  -H "Authorization: Bearer $JINA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jina-embeddings-v3",
    "task": "retrieval.passage",
    "embedding_type": "float",
    "normalized": true,
    "input": [
      "Reranker przestawia kolejność wynikow zwroconych przez wyszukiwarke.",
      "Osadzenia zamieniaja tekst na wektor liczb zmiennoprzecinkowych."
    ]
  }'

Pole task przyjmuje jedną z pięciu wartości i nie są to nazwy wymyślone przez dokumentację. Plik config.json modelu jina-embeddings-v3 wymienia je w polu lora_adaptations: retrieval.query, retrieval.passage, separation, classification oraz text-matching. Każda odpowiada osobnemu adapterowi LoRA doszytemu do wspólnego rdzenia o 24 warstwach i rozmiarze ukrytym 1024. Zapytanie i dokument należy kodować różnymi wartościami, retrieval.query dla pierwszego i retrieval.passage dla drugiego, inaczej traci się cały zysk z tego rozwiązania. Ten sam plik konfiguracji wymienia w polu matryoshka_dimensions dopuszczalne skrócenia wektora: 32, 64, 128, 256, 512, 768 i 1024.

Reranking działa na osobnym adresie i przyjmuje inny zestaw pól.

Code
Bash
# reranking: model, query, documents, top_n, return_documents
curl -s https://api.jina.ai/v1/rerank \
  -H "Authorization: Bearer $JINA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jina-reranker-v3",
    "query": "jak skrocic wektor osadzen",
    "top_n": 3,
    "return_documents": false,
    "documents": [
      "Matryoshka pozwala obciac wektor do 256 wymiarow.",
      "Kontener Dockera buduje sie poleceniem docker build.",
      "Adapter LoRA zmienia zachowanie modelu bez zmiany wag rdzenia."
    ]
  }'

Ustawienie return_documents na false zmniejsza odpowiedź do samych indeksów i wyników, co przy pięćdziesięciu kandydatach robi wyraźną różnicę w wielkości ładunku. Pole top_n obcina listę po stronie serwera, ale nie zmienia rozliczenia, bo policzone zostaną wszystkie przesłane tokeny.

Uruchomienie wag lokalnie, jeżeli licencja na to pozwala, wygląda tak. Poniższy przykład korzysta z parametrów udokumentowanych w karcie modelu jina-embeddings-v3.

Code
Python
from sentence_transformers import SentenceTransformer

# trust_remote_code jest wymagany, bo repozytorium dostarcza wlasny modul custom_st.py
model = SentenceTransformer("jinaai/jina-embeddings-v3", trust_remote_code=True)

# task wybiera adapter LoRA, truncate_dim skraca wektor zgodnie z matryoshka_dimensions
passages = model.encode(
    ["Osadzenia zamieniaja tekst na wektor liczb."],
    task="retrieval.passage",
    truncate_dim=256,
)

query = model.encode(["czym sa osadzenia"], task="retrieval.query", truncate_dim=256)
print(passages.shape, query.shape)

Wektory z tego modelu trafiają potem do bazy wektorowej, na przykład do Qdranta albo do pgvectora, jeśli dane i tak leżą w PostgreSQL. Wybór skróconego wymiaru trzeba podjąć przed założeniem kolekcji, bo zmiana wymiaru wymaga przeliczenia całego zbioru od nowa.

Reader, czyli strona zamieniona na markdown

Czytnik pod adresem r.jina.ai jest najbardziej dostępną częścią oferty, bo działa bez klucza. Sprawdziłem to bezpośrednim wywołaniem: adres https://r.jina.ai/https://example.com zwraca kod 200 i markdown gotowy do podania modelowi językowemu. Wyszukiwarka pod s.jina.ai klucza już wymaga i bez niego zwraca 401 z nazwą błędu AuthenticationRequiredError.

Zachowanie czytnika steruje się nagłówkami. Poniżej nazwy odczytane z panelu klienta, nie z pamięci.

Code
Bash
# markdown z podsumowaniem linkow, z pominieciem cache i z wycieciem elementu strony
curl -s "https://r.jina.ai/https://example.com" \
  -H "X-Respond-With: markdown" \
  -H "X-With-Links-Summary: true" \
  -H "X-Target-Selector: main" \
  -H "X-Remove-Selector: nav, footer" \
  -H "X-No-Cache: true" \
  -H "X-Token-Budget: 4000" \
  -H "X-Timeout: 20"

# ta sama tresc jako JSON zamiast zwyklego tekstu
curl -s "https://r.jina.ai/https://example.com" -H "Accept: application/json"

Odpowiedź w formacie JSON ma ustaloną strukturę i pole data.usage.tokens z liczbą tokenów, którą warto logować od pierwszego dnia.

Code
JSON
{
  "code": 200,
  "status": 20000,
  "data": {
    "title": "Example Domain",
    "url": "https://example.com/",
    "content": "This domain is for use in documentation examples...",
    "publishedTime": "Tue, 18 Aug 2026 20:06:42 GMT",
    "warning": "This is a cached snapshot of the original page, consider retry with caching opt-out.",
    "httpStatus": 200,
    "usage": { "tokens": 29 }
  }
}

Pole warning w tej odpowiedzi jest istotne. Domyślnie czytnik oddaje zapisaną kopię strony, a nie świeże pobranie. Data w publishedTime w moim teście była o cztery dni starsza od dnia wywołania. Do zbierania treści zmieniających się często trzeba użyć X-No-Cache albo X-Cache-Tolerance z liczbą sekund. Zestaw nagłówków obejmuje też X-Wait-For-Selector dla stron budowanych po stronie przeglądarki, X-Proxy-Url dla własnego pośrednika, X-Locale i X-Set-Cookie dla treści za logowaniem oraz osobną grupę X-Md-Heading-Style, X-Md-Link-Style, X-Md-Bullet-List-Marker, X-Md-Em-Delimiter i X-Md-Hr, sterującą formatowaniem wyniku.

Jeśli zadaniem jest przejście po całej witrynie, a nie po pojedynczym adresie, czytnik Jiny nie ma harmonogramu ani kolejki i lepiej sięgnąć po Firecrawla. Jina wypada dobrze tam, gdzie lista adresów jest już znana.

Cennik i rachunek za milion tokenów

Tu pojawia się problem z weryfikacją, który trzeba nazwać wprost. Publiczna strona z cennikiem jest aplikacją jednostronicową i w surowym HTML nie ma ani jednej kwoty. Jedyna liczba, jaką da się z niej wyciągnąć, to ustawienie automatycznego doładowania opisane jako „Top up when < 1M Tokens", czyli próg dokupienia, a nie wielkość planu darmowego. Wielkości planu darmowego ani zachowania po jego wyczerpaniu nie potwierdziłem i nie będę zgadywał.

Ceny jednostkowe są natomiast dostępne maszynowo. Wykaz /v1/models zwraca dla każdego modelu obiekt pricing, a w nim pole prompt. Dla 27 z 29 modeli, w tym dla wszystkich osadzeń v3, v4 i v5-small oraz dla wszystkich rerankerów, wartość wynosi 0.00000005. Dla jina-embeddings-v5-text-nano i jina-embeddings-v5-omni-nano wynosi 0.00000002. Pole completion we wszystkich przypadkach to zero, więc rozliczane są wyłącznie tokeny wejściowe. Ta liczba pochodzi z jednego źródła, samego API, i nie mam drugiej publicznej wartości do porównania.

Przeliczenie na milion tokenów: 1 000 000 razy 0,00000005 daje 0,05 dolara. Zaindeksowanie miliona tokenów tekstu kosztuje pięć centów, a modelem nano dwa centy. Milion tokenów to około siedmiuset tysięcy słów, czyli mniej więcej dziesięć średniej wielkości książek albo spora dokumentacja produktu.

Reranking rozlicza się z tej samej stawki, ale zachowuje się zupełnie inaczej, bo indeksowanie robi się raz, a reranking przy każdym zapytaniu. Przy pięćdziesięciu kandydatach po pięćset tokenów każdy jedno zapytanie zużywa 25 000 tokenów, czyli 0,00125 dolara. Tysiąc zapytań dziennie to 1,25 dolara dziennie i około 37,50 dolara za trzydziestodniowy miesiąc. Rachunek za reranking przerasta rachunek za indeksowanie już przy niewielkim ruchu i to jest właściwa oś planowania kosztu, a nie cena zaindeksowania korpusu.

Jina AI na tle innych rodzin osadzeń

Wszystkie rodziny w tym zestawieniu zamieniają tekst na wektor i różnice w jakości między nimi są dziś niewielkie oraz szybko się zmieniają. Trwała różnica leży gdzie indziej: w tym, czy da się w ogóle uciec od rachunku za tokeny, uruchamiając model u siebie.

RodzinaWagi publicznieLicencja wagKomercja u siebieAPI dostawcy
Jina v5, v4, v3takcc-by-nc-4.0, dla v4 Qwen Researchnietak
Jina v2 z 2023 rokutakApache 2.0taktak
BGE od BAAItakMITtakbrak własnego
all-MiniLM i pokrewnetakApache 2.0takbrak własnego
Voyage AIniebrak wagnie dotyczytak
Cohere Embedniebrak wagnie dotyczytak
OpenAI Embeddingsniebrak wagnie dotyczytak

Sprawdziłem tagi licencji trzech modeli porównawczych: BAAI/bge-m3 i BAAI/bge-large-en-v1.5 mają license:mit, a sentence-transformers/all-MiniLM-L6-v2 ma license:apache-2.0. Rodziny opisane w tekstach o BGE i Sentence Transformers są zatem jedynymi w tym zestawieniu, które dają zarazem publiczne wagi i licencję dopuszczającą sprzedaż produktu.

Voyage AI, Cohere Embed i OpenAI Embeddings nie udostępniają wag bieżących modeli w ogóle. Ich pozycja jest przynajmniej uczciwa: płacisz za każdy token i wiesz o tym od początku, bez złudzenia, że kiedyś przeniesiesz to na własny sprzęt. Jina zajmuje miejsce pośrednie i najbardziej mylące, bo wagi są do pobrania jednym poleceniem, a wolno na nich zbudować wyłącznie prototyp.

Ryzyko przywiązania do dostawcy jest przy każdym płatnym API takie samo i nie zależy od tego, ile pól ma żądanie. Migracja polega na przeliczeniu całego korpusu innym modelem, bo wektory dwóch różnych modeli nie są porównywalne. Koszt migracji to koszt ponownego zaindeksowania, więc pięć centów za milion tokenów jest zarazem ceną wejścia i ceną wyjścia.

Typowe błędy

Instalacja pakietu jina z npm w nadziei na klienta API. Ten pakiet nie pochodzi od Jina AI, ma innego autora i licencję ISC. Oficjalny klient JavaScript nazywa się jinaai i od stycznia 2024 roku nie dostał wydania.

Instalacja pakietu jina z PyPI z tym samym zamiarem. To framework do usług wielomodalnych, ostatnie wydanie z marca 2025 roku, repozytorium przemianowane na jina-ai/serve. Do wywołania modelu osadzeń nie służy.

Założenie, że brak tagu licencji przy jina-embeddings-v4 oznacza brak ograniczeń. W repozytorium leży plik LICENSE z tekstem Qwen Research License, który dopuszcza wyłącznie użycie badawcze i ewaluacyjne.

Kodowanie zapytania i dokumentu tą samą wartością task. Model ma pięć osobnych adapterów LoRA i mieszanie ich znosi zysk z asymetrycznego kodowania.

Poleganie na domyślnym zachowaniu czytnika przy treściach zmiennych. Bez X-No-Cache albo X-Cache-Tolerance dostaje się zapisaną kopię, o czym informuje pole warning w odpowiedzi JSON.

Planowanie budżetu wyłącznie po koszcie indeksowania. Reranking rozlicza się z tej samej stawki za token, ale powtarza się przy każdym zapytaniu i to on decyduje o rachunku.

Zmiana wartości truncate_dim po założeniu kolekcji w bazie wektorowej. Wymiar wektora jest częścią schematu i jego zmiana wymusza przeliczenie całego zbioru.

FAQ

Czy wolno użyć wag Jina AI w płatnym produkcie?

W przypadku bieżących modeli nie. Generacje v3, v4 i v5 oraz wszystkie rerankery poza wariantami v1 mają licencję niekomercyjną, przy czym v4 dodatkowo licencję Qwen Research zamiast Creative Commons. Komercyjnie wolno użyć wag jina-embeddings-v2-base-en i jina-embeddings-v2-small-en na Apache 2.0 albo wykupić dostęp do API.

Czy istnieje oficjalny pakiet SDK?

Dla Pythona nie ma żadnego, nazwy jina-ai, jina-embeddings i jina-reranker zwracają w PyPI kod 404. Dla JavaScriptu istnieje jinaai w wersji 0.2.20 z 25 stycznia 2024 roku, który nie zna modeli v4 ani v5. Dzisiejsza droga to zwykłe wywołania HTTP na api.jina.ai/v1/embeddings i api.jina.ai/v1/rerank.

Ile kosztuje zaindeksowanie miliona tokenów?

Pięć centów przy stawce 0.00000005 za token, którą zwraca wykaz /v1/models dla osadzeń v3, v4 i v5-small. Modelem jina-embeddings-v5-text-nano dwa centy. Wielkości planu darmowego nie potwierdziłem, bo strona z cennikiem nie renderuje się bez JavaScriptu.

Czy czytnik stron działa bez klucza API?

Tak, adres r.jina.ai zwraca treść bez nagłówka Authorization, co sprawdziłem bezpośrednio. Wyszukiwarka s.jina.ai klucza wymaga i bez niego zwraca 401. Czytnik domyślnie oddaje zapisaną kopię strony i sygnalizuje to polem warning.

Czym różni się reranker od modelu osadzeń?

Model osadzeń koduje każdy tekst osobno i wektory można policzyć raz, a potem trzymać w bazie. Reranker ogląda parę zapytanie plus dokument naraz, daje lepszą kolejność, ale nie da się go policzyć wcześniej. W praktyce łączy się oba: osadzenia wybierają kilkadziesiąt kandydatów, reranker układa je od nowa.

Co się dzieje z pakietem jina i repozytorium jina-ai/jina?

Repozytorium zostało przemianowane na jina-ai/serve i stary adres przekierowuje pod nowy. Pakiet PyPI jina stoi na wersji 3.34.0 z 24 marca 2025 roku. To osobny produkt, framework do usług wielomodalnych, a nie klient do dzisiejszych modeli osadzeń.

Czytaj dalej

Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie