Groq acceptă trei moduri de folosire a uneltelor: unelte built-in executate de Groq, servere MCP la distanță (vezi Responses API și MCP) și tool calling local. La cel local, trimiți definițiile în tools (nume, descriere, parametri ca JSON Schema), modelul întoarce tool_calls cu id, function.name și function.arguments (un șir JSON pe care îl parsezi), codul tău execută funcția și trimite rezultatul ca mesaj cu role: "tool" și același tool_call_id. Bucla continuă până când modelul nu mai cere unelte.
Toate modelele găzduite acceptă tool use, dar apelurile paralele (mai multe tool_calls într-un răspuns) nu sunt acceptate de GPT-OSS 20B, GPT-OSS 120B și GPT-OSS-Safeguard 20B; le acceptă, de exemplu, qwen/qwen3.8-27b. tool_choice poate fi auto (implicit), required, none sau o funcție anume. Dacă modelul nu respectă alegerea sau generează un apel invalid, API-ul întoarce 400, cu textul generat în failed_generation; documentația recomandă reîncercarea cu temperatură mai mică.
Structured Outputs (response_format cu type: "json_schema") are două moduri. Cu strict: true, decodarea constrânsă garantează că răspunsul respectă schema; este disponibil pe openai/gpt-oss-20b, openai/gpt-oss-120b, qwen/qwen3.8-27b și meta-models/muse-spark-open și cere ca toate câmpurile să fie în required, iar fiecare obiect să aibă additionalProperties: false (câmpurile opționale se scriu ca uniune cu null). Cu strict: false (implicit), schema este respectată de obicei, dar pot apărea erori 400. Streaming-ul și tool use nu sunt acceptate împreună cu Structured Outputs. JSON Object Mode ({"type": "json_object"}) dă doar JSON valid sintactic, fără schemă, și cere instrucțiuni explicite de JSON în prompt.
Concepte cheie și caracteristici
| Concept / Parametru | Descriere practică |
|---|---|
tools |
Lista funcțiilor: type: "function", name, description, parameters (JSON Schema). |
tool_choice="auto" |
Implicit; modelul decide dacă apelează o unealtă. |
tool_choice="required" |
Cel puțin un apel; altfel 400. |
tool_choice="none" |
Fără apeluri; unele modele pot încerca totuși, caz în care primești 400. |
tool_choice={"type": "function", "function": {"name": ...}} |
Obligă apelul unei funcții anume. |
parallel_tool_calls |
Implicit true; are efect doar pe modelele care acceptă apeluri paralele. |
role: "tool", tool_call_id |
Mesajul cu rezultatul funcției, legat de id-ul apelului. |
response_format json_schema, strict: true |
Schemă garantată prin decodare constrânsă (GPT-OSS 20B / 120B, Qwen 3.8 27B, Muse Spark Open). |
response_format json_schema, strict: false |
Best-effort; poate întoarce 400 „Generated JSON does not match the expected schema”. |
response_format json_object |
JSON valid, fără schemă; promptul trebuie să ceară JSON. |
failed_generation |
Câmpul din eroarea 400 cu apelul invalid generat de model. |
Exemple practice și scenarii reale
Exemplul 1: Bucla completă de tool calling local
import json
from groq import Groq
client = Groq()
MODEL = "openai/gpt-oss-120b"
def verifica_stoc(cod_sku, cantitate=1):
stoc = {"PROD-8899": 3} # în realitate: interogare în baza de date
disponibil = stoc.get(cod_sku, 0)
return {"cod_sku": cod_sku, "disponibil": disponibil, "suficient": disponibil >= cantitate}
unelte = [{
"type": "function",
"function": {
"name": "verifica_stoc",
"description": "Verifică stocul unui produs după codul SKU.",
"parameters": {
"type": "object",
"properties": {
"cod_sku": {"type": "string", "description": "Codul produsului, de exemplu PROD-8899"},
"cantitate": {"type": "integer", "description": "Bucăți cerute"},
},
"required": ["cod_sku"],
},
},
}]
functii = {"verifica_stoc": verifica_stoc}
mesaje = [{"role": "user", "content": "Mai avem 5 bucăți din PROD-8899?"}]
for _ in range(5): # limită de iterații
r = client.chat.completions.create(model=MODEL, messages=mesaje, tools=unelte, tool_choice="auto")
msg = r.choices[0].message
if not msg.tool_calls:
print(msg.content)
break
mesaje.append(msg)
for apel in msg.tool_calls:
argumente = json.loads(apel.function.arguments)
rezultat = functii[apel.function.name](**argumente)
mesaje.append({"role": "tool", "tool_call_id": apel.id, "content": json.dumps(rezultat)})
Exemplul 2: Schemă JSON garantată (strict: true)
r = client.chat.completions.create(
model="openai/gpt-oss-20b",
messages=[
{"role": "system", "content": "Extrage datele recenziei."},
{"role": "user", "content": "Am cumpărat căștile X200. Bateria ține o zi, sunetul e clar. Nota mea: 4 din 5."},
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "recenzie",
"strict": True,
"schema": {
"type": "object",
"properties": {
"produs": {"type": "string"},
"nota": {"type": "number"},
"pret": {"type": ["number", "null"]},
},
"required": ["produs", "nota", "pret"],
"additionalProperties": False,
},
},
},
)
date = json.loads(r.choices[0].message.content)
Exemplul 3: JSON Object Mode, fără schemă
r = client.chat.completions.create(
model="openai/gpt-oss-20b",
messages=[
{"role": "system", "content": "Răspunzi doar cu un obiect JSON cu cheile sentiment și scor."},
{"role": "user", "content": "Livrarea a întârziat trei zile."},
],
response_format={"type": "json_object"},
)
Greșeli frecvente și capcane
- Aștepți mai multe
tool_callsîntr-un singur răspuns de la GPT-OSS. Aceste modele nu acceptă apeluri paralele; modelul cere unealta de mai multe ori, în pași succesivi. - Folosești
strict: truecu o schemă care are câmpuri opționale sau fărăadditionalProperties: false. Cererea este respinsă; scrie câmpurile opționale ca uniune cunull. - Combini
response_formatjson_schema custream=Truesau cutools. Combinația nu este acceptată. - Execuți argumentele primite de la model fără validare. Verifică tipurile și valorile înainte de a atinge baza de date sau un API extern.