PL ▾
Pobierz klucz API

API Ollama w Pythonie i alternatywa hostowana

API Ollamy w Pythonie zajmuje około dziesięciu linii, a ta sama struktura kodu działa również z endpointem hostowanym. Ten artykuł pokazuje oba przypadki i wyjaśnia, kiedy wybrać który.

Zaktualizowano

Kluczowe punkty

  • Ollama nasłuchuje na porcie 11434 i oferuje natywne API oraz endpoint /v1 w stylu OpenAI.
  • Pakiet ollama, zwykłe requests i OpenAI SDK działają; OpenAI SDK jest najbardziej przenośny.
  • Przejście na API hostowane oznacza zmianę base URL, klucza i nazwy modelu.
  • Lokalne rozwiązanie jest najlepsze do pracy offline i przy stałym sprzęcie; hostowane jest prostsze, gdy nie masz GPU.
Lokalny komputer połączony świecącym kablem z serwerem w chmurze, reprezentujący lokalne i hostowane API LLM

Krótka wersja

Jeśli szukasz ollama api python, zwykle chcesz zrobić jedno z trzech: wywołać model działający na Twojej maszynie, strumieniować tokeny z niego lub sprawić, by ten sam skrypt działał gdzieś indziej. Ollama daje Ci wszystkie trzy opcje. Uruchamia lokalny serwer, domyślnie pod http://localhost:11434, a Ty komunikujesz się z nim za pomocą pakietu Pythona ollama, zwykłego HTTP lub dowolnego klienta OpenAI wskazującego na jego ścieżkę /v1.

Pułapką jest to, że model musi działać na Twoim sprzęcie. Laptop bez dobrego GPU będzie wolny z większymi modelami, a serwer bez niego jest słabym wyborem. W takim przypadku API kompatybilne z OpenAI hostowane jest prostszą drogą niż opcja lokalna, a ponieważ format zapytania jest ten sam, przełączenie kosztuje Cię trzy linie konfiguracji. Obie ścieżki zostały opisane poniżej z kodem, który możesz wkleić.

Wywoływanie lokalnego modelu pakietem ollama

Zainstaluj Ollamę, pobierz model i upewnij się, że serwer działa. Następnie zainstaluj klienta Pythona:

pip install ollama
ollama pull llama3.2

Podstawowe wywołanie czatu wygląda tak. Nazwa modelu to to, co pobrałeś; llama3.2 to tylko przykład.

import ollama

response = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "Explain DNS in two sentences."}],
)
print(response["message"]["content"])

Strumieniowanie

Przekaż stream=True i otrzymasz iterator fragmentów zamiast jednej odpowiedzi. Każdy fragment zawiera część odpowiedzi w message.content.

import ollama

stream = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "Write a haiku about servers."}],
    stream=True,
)
for chunk in stream:
    print(chunk["message"]["content"], end="", flush=True)
print()

Wskazanie klienta na inną maszynę

Jeśli Ollama działa na innym hoście, utwórz klienta z jawnym adresem, np. ollama.Client(host="http://192.168.1.20:11434"). Domyślnie serwer nasłuchuje tylko na lokalnej maszynie, więc dostęp zdalny wymaga świadomej konfiguracji po stronie serwera. Nie wystawiaj go do publicznego internetu bez proxy i uwierzytelnienia przed nim, ponieważ natywne API nie ma własnej weryfikacji klucza.

Zwykłe HTTP z requests

Wcale nie potrzebujesz pakietu. Natywny endpoint czatu to POST /api/chat. Strumieniowanie jest tam domyślne, a strumień to JSON podzielony znakami nowej linii, a nie SSE. Ustaw "stream": false, jeśli chcesz otrzymać jeden obiekt.

import requests

r = requests.post(
    "http://localhost:11434/api/chat",
    json={
        "model": "llama3.2",
        "messages": [{"role": "user", "content": "Name three HTTP status codes."}],
        "stream": False,
    },
    timeout=120,
)
r.raise_for_status()
print(r.json()["message"]["content"])

Ustaw wystarczająco długi timeout. Pierwsze zapytanie po pobraniu musi załadować model do pamięci, co może zająć znacznie więcej czasu niż późniejsze zapytania.

Odczyt strumienia ręcznie to tylko kilka dodatkowych linii. Wywołaj requests.post(..., stream=True), iteruj po r.iter_lines(), pomijaj puste linie i uruchamiaj json.loads na każdej z nich. Każdy obiekt zawiera małą część odpowiedzi, a ostatni ma "done": true. Jest to przydatne w minimalnym kontenerze, gdzie wolisz nie instalować kolejnego pakietu, i pokazuje, co robi dla Ciebie biblioteka. API hostowane strumieniuje inaczej, jako linie SSE zaczynające się od data:, co jest kolejnym powodem, by pozwolić OpenAI SDK parsować strumień dla Ciebie w przenośnym kodzie.

Używanie OpenAI SDK z Ollama

Ollama udostępnia również endpoint w stylu OpenAI pod /v1. Oznacza to, że działa oficjalny pakiet openai, jak i większość oprogramowania, które pozwala ustawić niestandardowy base URL. Klucz jest wymagany przez SDK, ale ignorowany przez lokalną Ollamę, więc wystarczy dowolny ciąg.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Give me a one-line summary of TCP."}],
)
print(resp.choices[0].message.content)

To najbardziej przydatna forma, ponieważ oddziela Twój kod od serwera. Ta sama funkcja może rozmawiać z lokalnym modelem dziś, a z czymś innym jutro, co jest tematem kolejnego rozdziału.

Ten sam kod z API hostowanym

Opcja hostowana to API kompatybilne z OpenAI z jednym modelem, uncensored, obsługiwane przez niezależnego dostawcę i dostrojone do odpowiadania bez odmów treści dla legalnego użytku dorosłego. Obsługuje tylko tekst. Base URL to https://api.ollamaapi.cc/v1, a uwierzytelniasz się kluczem Bearer ze strony klucza API.

Oto wersja, która odczytuje cel ze zmiennych środowiskowych, z wartościami hostowanymi jako domyślne. Aby wrócić do lokalnego serwera, wyeksportuj dwie zmienne i nic więcej nie zmieniaj.

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.getenv("LLM_BASE_URL", "https://api.ollamaapi.cc/v1"),
    api_key=os.getenv("LLM_API_KEY", "YOUR_API_KEY"),
)
MODEL = os.getenv("LLM_MODEL", "uncensored")

resp = client.chat.completions.create(
    model=MODEL,
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "List four uses of a message queue."},
    ],
    temperature=0.7,
)
print(resp.choices[0].message.content)

Dla uruchomień lokalnych ustaw LLM_BASE_URL=http://localhost:11434/v1, LLM_API_KEY=ollama i LLM_MODEL=llama3.2. Szybki start ma tę samą konfigurację w curl i Node.

Strumieniowanie, tryb JSON i narzędzia po stronie hostowanej

Endpoint hostowany obsługuje strumieniowanie przez SSE, tryb JSON, wywoływanie narzędzi oraz standardowe parametry próbkowania (temperature, top_p, stop, seed i kary). Strumieniowanie z SDK to ta sama pętla, którą napisałbyś dla dowolnego serwera w stylu OpenAI:

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Tell a two-paragraph story about a lighthouse."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Dla wyjścia strukturalnego ustaw response_format={"type": "json_object"} i wskaż w promptie, że chcesz JSON. Zawsze parsuj wewnątrz bloku try; model nadal może zwrócić coś, czego nie przewidziałeś.

Jedna różnica w stosunku do użycia lokalnego ma znaczenie w kodzie: limity. Pełny klucz pozwala na 8 równoległych zapytań i 300 zapytań na minutę, a strumieniowane zapytanie zajmuje swoje miejsce do końca strumienia. Jeśli rozdzielasz zapytania na wątki, ogranicz pulę do 8 i ponawiaj przy HTTP 429, używając nagłówka Retry-After, gdy jest obecny.

Kontynuowanie konwersacji

Żaden z endpointów czatu – lokalny ani hostowany – nie pamięta niczego między wywołaniami. Serwer widzi tylko wiadomości, które wysyłasz, więc bot czatu to lista, do której dodajesz i ponownie wysyłasz. Wzorzec jest identyczny dla obu celów, co jest kolejnym powodem, by utrzymać klienta w stylu OpenAI jako domyślny.

history = [{"role": "system", "content": "You are a helpful assistant."}]

def ask(text):
    history.append({"role": "user", "content": text})
    resp = client.chat.completions.create(model=MODEL, messages=history)
    answer = resp.choices[0].message.content
    history.append({"role": "assistant", "content": answer})
    return answer

print(ask("Pick a name for a hiking app."))
print(ask("Give me a tagline for it."))

Dwie praktyczne uwagi. Po pierwsze, modele lokalne mają długość okna kontekstu, którą ustawiasz i którą musi pomieścić pamięć; jeśli historia przekroczy ten limit, starsze zwroty są obcinane lub wywołanie się nie powiedzie, w zależności od ustawień. Model hostowany akceptuje okno 100 000 tokenów wliczając uzupełnienie, co jest znacznie więcej niż potrzebują większość czatów, ale długie historie nadal kosztują tokeny wejściowe przy każdym zwrocie. Po drugie, gdy historia się wydłuży, podsumuj najstarsze zwroty w jedną krótką wiadomość zamiast wysyłać je wszystkie ponownie. To utrzymuje opóźnienie i koszt na stałym poziomie w obu backendach.

Ponawianie uprzejmie

W API hostowanym tymczasowe przeciążenie zwraca HTTP 429 z nagłówkiem Retry-After: 5. Mały wrapper go obsługuje:

import time
from openai import RateLimitError

def chat_with_retry(messages, tries=4):
    for attempt in range(tries):
        try:
            return client.chat.completions.create(model=MODEL, messages=messages)
        except RateLimitError:
            time.sleep(5 * (attempt + 1))
    raise RuntimeError("still rate limited")

Lokalne Ollama nie limituje cię, ale kolejkuje zapytania, gdy model jest zajęty, więc ten sam wrapper nie zaszkodzi tam.

Lokalne czy hostowane: jak wybrać

Żaden wybór nie jest ogólnie lepszy. Użyj poniższych punktów jako listy kontrolnej.

  • Wybierz lokalną Ollamę, jeśli potrzebujesz pracy offline, jeśli dane nie mogą opuścić maszyny, jeśli posiadasz już wydajną kartę GPU, lub jeśli chcesz szybko wypróbować wiele różnych modeli open-weight.
  • Wybierz API hostowane, jeśli nie masz GPU, jeśli pracujesz na małym VPS lub w CI, jeśli kilka osób lub usług dzieli jeden backend, lub jeśli chcesz długie okno kontekstu bez ręcznego doboru pamięci. Model hostowany akceptuje do 100 000 tokenów promptu plus odpowiedź.
  • Używaj obu podczas rozwoju: iteruj lokalnie, a następnie w produkcji wskaż adres URL hostowany za pomocą zmiennych środowiskowych.

Korzystanie w chmurze jest rozliczane za tokeny, po $0,15 za 1 mln tokenów wejściowych i $0,50 za 1 mln tokenów wyjściowych, z przedpłaconego kredytu. Na stronie z cenami znajdziesz kwoty do doładowania, a nowe konta mogą jednym kliknięciem uzyskać $0,50 kredytu próbnego bez podawania karty. Prompty nie są używane do trenowania.

Błędy, na które napotkasz

ObjawPrawdopodobna przyczynaNaprawa
Odrzucenie połączenia na porcie 11434Serwer Ollama nie działaUruchom aplikację lub wykonaj ollama serve
Model nie znalezionyModel nigdy nie został pobrany lub nazwa ma literówkęUruchom ollama list, a następnie ollama pull nazwę, której używasz
Pierwsze wywołanie kończy się timeoutemModel wciąż się ładujeZwiększ limit czasu lub wyślij żądanie podgrzania
Błąd uwierzytelnienia na hostowanym APIBrakujący lub błędny klucz BearerSprawdź LLM_API_KEY i bazowy URL
HTTP 429 z kodem concurrencyWięcej niż 8 żądań w toku (2 na kluczu próbnym)Zmniejsz liczbę workerów
HTTP 429 z kodem rate_limitedPrzekroczenie limitu zapytań na minutęZwolnij i powtórz zapytanie

Nieudane lub odrzucone żądania po stronie hostowanej nie są rozliczane, więc logika ponawiania nie obciąży Cię za nieudane próby.

Pytania i odpowiedzi

Jaki jest domyślny adres Ollama API?

Lokalny serwer Ollama nasłuchuje na http://localhost:11434. Natywne endpointy znajdują się w /api, np. /api/chat, a endpoint w stylu OpenAI znajduje się w /v1.

Czy mogę użyć OpenAI Python SDK z Ollamą?

Tak. Ustaw base_url na http://localhost:11434/v1 i przekaż dowolny ciąg jako klucz API. SDK wysyła wtedy standardowe żądania uzupełnienia czatu do Twojego lokalnego modelu.

Jak przełączyć się z Ollama na hostowane API?

Zmień bazowy URL, klucz i nazwę modelu. Jeśli Twój kod odczytuje je ze zmiennych środowiskowych, nie jest potrzebna zmiana kodu.

Czy hostowane API działa bez GPU po mojej stronie?

Tak. Model działa u dostawcy, więc Twój skrypt potrzebuje tylko połączenia internetowego i klucza Bearer. Płacisz za tokeny z przedpłaconego kredytu.

Twój klucz jest o jeden formularz stąd

Utwórz konto, skopiuj klucz, zmień bazowy URL. To cała konfiguracja.

Pobierz klucz API