# Wywoływanie narzędzi i wyjście JSON z modelami o otwartych wagach

> Wywoływanie funkcji z modelami o otwartych wagach w formacie OpenAI: tools, tool_choice, pętla wywołania i odpowiedzi oraz response_format dla wyjścia JSON.

- URL: https://llmwithcrypto.com/pl/docs/tool-calling/
- Ostatnia aktualizacja: 2026-10-23
- Wydawca: LLMwithCrypto (https://llmwithcrypto.com)

Model może poprosić Twój kod o uruchomienie funkcji, a następnie użyć wyniku w swojej odpowiedzi; może też odpowiedzieć obiektem JSON, który Twój program odczytuje bezpośrednio. Oba podejścia korzystają z formatu zapytań OpenAI i oba zależą od wybranego modelu.

**Krótka odpowiedź — Jak działa wywoływanie narzędzi w LLMwithCrypto?**

Wyślij swoje funkcje w `tools`, w formacie OpenAI. Gdy model chce którejś użyć, **LLMwithCrypto** zwraca `finish_reason: "tool_calls"` z nazwą funkcji i argumentami w JSON; Twój kod ją uruchamia i odsyła wynik jako wiadomość `tool`. W przypadku odpowiedzi strukturalnych `response_format: {"type": "json_object"}` wymaga poprawnego JSON. Oba mechanizmy działają na modelach, które je obsługują, zgodnie z dokumentacją z 23 października 2026.

## Które modele obsługują narzędzia i JSON?

Streaming działa na każdym modelu; tool calling i wyjście JSON zależą od tego, co obsługuje sam model.

Przetestuj własny schemat na modelu, którego planujesz użyć, zanim zaczniesz na nim polegać. Model, który nie obsługuje narzędzi, odpowiada zwykłym tekstem zamiast wywoływać funkcję; model, który nie obsługuje trybu JSON, zwraca błąd `400` dla `response_format`.

## Czym jest pętla?

1. **Opisz funkcje** — Każde narzędzie ma name, description, które model czyta, aby zdecydować, kiedy go użyć, oraz parameters jako JSON Schema.
2. **Wyślij rozmowę z narzędziami** — Model albo odpowiada tekstem, albo zatrzymuje się z finish_reason: "tool_calls" i jednym lub kilkoma wywołaniami w message.tool_calls.
3. **Uruchom każde wywołanie** — Przeanalizuj function.arguments (ciąg JSON), uruchom swoją funkcję i nigdy nie ufaj argumentom bezwarunkowo: waliduj je jak każde dane wejściowe od użytkownika.
4. **Odeślij wyniki** — Dołącz wiadomość asystenta, a następnie po jednej wiadomości tool na każde wywołanie z jego tool_call_id i wynikiem jako tekstem. Wywołaj API ponownie; powtarzaj, aż model odpowie tekstem.

*Python: pełna pętla narzędzi z gpt-oss-120b*

```python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://llmwithcrypto.com/api/v1",
    api_key=os.environ["LLMWITHCRYPTO_API_KEY"],
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order_status",
            "description": "Return the delivery status of an order.",
            "parameters": {
                "type": "object",
                "properties": {"order_id": {"type": "string"}},
                "required": ["order_id"],
            },
        },
    }
]


def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped", "eta": "2026-10-25"}


messages = [{"role": "user", "content": "Where is my order A-1042?"}]
while True:
    resp = client.chat.completions.create(model="gpt-oss-120b", messages=messages, tools=tools, max_tokens=300)
    msg = resp.choices[0].message
    if not msg.tool_calls:
        print(msg.content)
        break
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_order_status(**args)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

```

## Jak wygląda wywołanie narzędzia w odpowiedzi?

Wiadomość asystenta nie ma tekstu, zawiera tablicę `tool_calls`, a wybór kończy się na `finish_reason: "tool_calls"`. Argumenty przychodzą jako ciąg JSON, a nie obiekt. Poniższe identyfikatory i liczby są przykładowe.

*Odpowiedź z prośbą o wywołanie funkcji (przykład)*

```json
{
  "id": "chatcmpl-3c9d27e1",
  "object": "chat.completion",
  "created": 1792742400,
  "model": "gpt-oss-120b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_7f31",
            "type": "function",
            "function": {
              "name": "get_order_status",
              "arguments": "{\"order_id\": \"A-1042\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 118,
    "completion_tokens": 22,
    "total_tokens": 140
  }
}

```

## Jak kontrolować, kiedy narzędzia są używane?

- **`"tool_choice": "auto"`** (domyślnie, gdy ustawiono `tools`): model decyduje.
- **`"tool_choice": "none"`**: model odpowiada tekstem, mimo że narzędzia są wymienione.
- **`"tool_choice": "required"`**: model musi wywołać co najmniej jedno narzędzie.
- **`{"type": "function", "function": {"name": "get_order_status"}}`**: model musi wywołać właśnie to narzędzie.

Każda definicja narzędzia jest wysyłana jako dane wejściowe przy każdym wywołaniu, więc długie opisy i wiele narzędzi zwiększają liczbę tokenów wejściowych. Trzymaj opisy krótko i wysyłaj tylko te narzędzia, których potrzebuje dany krok.

## Jak uzyskać poprawny JSON w odpowiedzi?

Ustaw `response_format` na `{"type": "json_object"}` i opisz oczekiwane klucze w wiadomości systemowej: tryb JSON gwarantuje, że odpowiedź da się sparsować, a nie że zawiera klucze, których chcesz. Utrzymuj niską wartość `temperature` dla stabilnych wyników i sprawdź sparsowany obiekt w kodzie, zanim go użyjesz.

*Node.js: odpowiedź JSON z response_format*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const resp = await client.chat.completions.create({
  model: 'gpt-oss-120b',
  messages: [
    { role: 'system', content: 'Reply with a JSON object {"sentiment": "positive" | "negative" | "neutral", "reason": string}.' },
    { role: 'user', content: 'The delivery was late but support fixed it in an hour.' },
  ],
  response_format: { type: 'json_object' },
  temperature: 0.2,
  max_tokens: 150,
});
const result = JSON.parse(resp.choices[0].message.content);
console.log(result.sentiment, '-', result.reason);

```

## Narzędzia i JSON: najczęstsze pytania

### Czy wywołania narzędzi kosztują dodatkowo?

Nie mają własnej opłaty. Definicje narzędzi, wywołanie i odsyłane wyniki to tokeny rozliczane jak każde inne. Płacisz za token z salda: tokeny wejściowe i wyjściowe są liczone przez tokenizer danego modelu i rozliczane według ceny tego modelu za 1M tokenów. Wywołanie zakończone błędem nic nie kosztuje.

### Czy model może wywołać kilka narzędzi naraz?

Niektóre modele zwracają więcej niż jedno wywołanie w `tool_calls`. Uruchom je wszystkie i wyślij po jednej wiadomości `tool` na każde wywołanie przed następnym zapytaniem.

### Czy API uruchamia moje funkcje?

Nie. Model jedynie wskazuje, którą funkcję wywołać i z jakimi argumentami; uruchamia ją Twój kod. Po naszej stronie nic nie jest wykonywane i nic z wymiany nie jest przechowywane: Nie przechowujemy Twoich promptów ani odpowiedzi modelu: gdy odpowiedź zostanie wysłana, jej tekst znika. Każde wywołanie zostawia jedną linię logu z czasem, kontem, modelem i liczbą tokenów, usuwaną po 30 dniach.

---

LLMwithCrypto: LLMwithCrypto to zgodne z OpenAI API LLM dla modeli z otwartymi wagami — DeepSeek V4 Pro, DeepSeek V4.1 Flash, DeepSeek R1, Qwen3.5 397B A17B, Qwen3 235B A22B Instruct, gpt-oss-120b, gpt-oss-20b, GLM-4.7, Llama 3.3 70B Instruct, Gemma 4 31B, Mistral Large 3, Mistral Small 4 — płatne za token z przedpłaconego salda kryptowalutowego, o 5% poniżej mediany ceny publicznych hostów. Bez KYC: bez dowodu, bez selfie, bez dokumentów. Prompty i odpowiedzi nie są przechowywane.
