This document describes how to call the create_chat_completion endpoint implemented by
extensions/business/edge_inference_api/llm_inference_api.py, with special focus on
response_format for structured synthetic data generation.
- Method: POST
- Path:
/create_chat_completion - Behavior: Synchronous alias for
/predict. Internally it registers a request, dispatches to the loopback LLM engine, then blocks until the request completes or times out.
Notes:
- The FastAPI layer is generated by
naeural_coreand returns wrapped responses by default (unlessRESPONSE_FORMATis set toRAWin the plugin config). - The plugin defaults to loopback local-only mode with tunneling disabled, which allows anonymous access. If tunneling is enabled or auth is required, you must pass a token.
The request body is JSON with these fields (all are optional unless noted):
messages(required): list of{ role, content }dicts.rolemust be one of:system,user,assistant,tool.contentmust be a non-empty string. Leading/trailing whitespace is trimmed.
temperature(default0.7): float in[0.0, 1.5].max_tokens(default512): int in[16, 4096].top_p(default1.0): float in(0, 1].repeat_penalty(default1.0): float; forwarded to the LLM backend.response_format(defaultnull): structured output control (see below).metadata(default{}): stored with the request; returned only by/request_status?return_full=true.authorization(optional): bearer token string. You can pass either:"Bearer <token>", or"<token>"(no prefix).
extras(optional): a dict of extra params. If provided, it is merged into the request parameters via**kwargs(advanced/experimental).
Validation failures return an error payload and the HTTP layer raises a 500 by default
(because the FastAPI template treats any error key as a server error).
response_format is validated and normalized in LLMInferenceApiPlugin.check_and_normalize_response_format.
It accepts null, a dict, or a JSON string representing a dict.
A) llama-cpp-python form (preferred by this API)
{
"type": "json_object"
}or
{
"type": "json_object",
"schema": { /* JSON Schema */ }
}B) llama.cpp server alternative form (normalized to json_object)
{
"type": "json_schema",
"json_schema": {
"schema": { /* JSON Schema */ }
}
}or
{
"type": "json_schema",
"schema": { /* JSON Schema */ }
}- If
response_formatis a string, it is parsed as JSON. Empty string is treated asnull. typeis required and must be a string.- Supported types:
json_object,json_schema. - For
json_schema, the API rewrites it to:
{
"type": "json_object",
"schema": { /* extracted schema */ }
}This is because llama-cpp uses json_object to drive grammar-based JSON constraints.
schema(orjson_schema.schema) must be a JSON object (dict) and JSON-serializable.- If
typeisjson_schemaand no schema is provided, the request is rejected.
The response_format is passed through to llama_cpp.Llama.create_chat_completion(...).
When type == "json_object", llama-cpp builds a JSON grammar and constrains output to valid JSON
(and to your schema if provided). This is the key mechanism for synthetic data generation.
{
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Write a short greeting."}
]
}{
"messages": [
{"role": "system", "content": "Return a JSON object only."},
{"role": "user", "content": "Generate a simple profile."}
],
"response_format": {"type": "json_object"}
}{
"messages": [
{"role": "system", "content": "Output must match the schema."},
{"role": "user", "content": "Create a synthetic customer record."}
],
"response_format": {
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"customer_id": {"type": "string"},
"age": {"type": "integer"},
"segment": {"type": "string"}
},
"required": ["customer_id", "age", "segment"],
"additionalProperties": false
}
}
}{
"messages": [
{"role": "system", "content": "Return only schema-valid JSON."},
{"role": "user", "content": "Generate a synthetic record."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"schema": {
"type": "object",
"properties": {
"id": {"type": "string"},
"label": {"type": "string"}
},
"required": ["id", "label"],
"additionalProperties": false
}
}
}
}By default, FastAPI responses are wrapped with extra node metadata:
{
"result": {
"REQUEST_ID": "<uuid>",
"MODEL_NAME": "<model_name>",
"TEXT_RESPONSE": ["..."],
"FULL_OUTPUT": [ { /* raw llama_cpp response */ } ]
},
"server_node_addr": "...",
"evm_network": "...",
"ee_node_alias": "...",
"ee_node_address": "...",
"ee_node_eth_address": "...",
"ee_node_network": "...",
"ee_node_ver": "..."
}Important notes:
TEXT_RESPONSEandFULL_OUTPUTare typically lists, even for a single request.FULL_OUTPUTcontains the raw llama-cpp response object(s), which includes the structured JSON text inchoices[0].message.content.metadatais not included in this result; it is available only via/request_status?request_id=<id>&return_full=true.
If RESPONSE_FORMAT is set to RAW in config, the response body is just:
{
"REQUEST_ID": "<uuid>",
"MODEL_NAME": "<model_name>",
"TEXT_RESPONSE": ["..."],
"FULL_OUTPUT": [ { /* raw llama_cpp response */ } ]
}- Use
response_formatwith a strict JSON schema andadditionalProperties: falseto prevent drift and keep outputs parseable. - Consider low temperature (e.g.,
0.0to0.2) to reduce randomness in schema-constrained outputs. - Validate outputs downstream even with schema constraints, since generation can still fail in edge cases (timeouts, model errors, etc.).
extensions/business/edge_inference_api/llm_inference_api.pyextensions/business/edge_inference_api/base_inference_api.pyextensions/serving/default_inference/nlp/llama_cpp_base.py/usr/local/lib/python3.10/dist-packages/naeural_core/business/default/web_app/fast_api_web_app.py/usr/local/lib/python3.10/dist-packages/llama_cpp/llama_chat_format.py