Skip to content

Server CLI reference

Package: piighost-api

piighost-api is the command line of the companion server. serve starts the HTTP server. The dataset commands build and score a detection dataset from observation traces.

piighost-api serve [--config SOURCE] [--host HOST] [--port PORT] [--log-level LEVEL]
piighost-api dataset extract --output FILE [--since DATE] [--until DATE] [--mode MODE] [--limit N]
piighost-api dataset metrics --input FILE [--output FILE] [--output-format FORMAT] [--match-mode MODE] [--iou-threshold FLOAT] [--source SOURCE]

The server requires Python 3.12 or later and piighost>=2.0,<3. Its extras add optional features:

ExtraAdds
gliner2piighost[gliner2], for a configuration that runs a GLiNER2 detector
observationthe OpenTelemetry SDK and OTLP exporter, for exporting traces
datasetthe Langfuse SDK and python-dotenv, for dataset extract
pip install "piighost-api[gliner2,observation]"

piighost-api serve

Builds the pipeline once and serves the API endpoints with uvicorn, in a single process.

piighost-api serve --config catalog:piighost/support-en --host 0.0.0.0 --port 8000
OptionDefaultDescription
--config, -cPIIGHOST_CONFIGA TOML or JSON pipeline config file, or a catalog reference such as catalog:piighost/support-en
--host127.0.0.1Bind host
--port8000Bind port
--log-levelinfodebug, info, warning or error
  • With neither --config nor PIIGHOST_CONFIG, the command prints Missing --config or PIIGHOST_CONFIG. with a usage hint and exits 1. A file path that does not exist exits 1 with Configuration file not found:.
  • A catalog reference loads the whole configuration the piighost catalog publishes under that name. A reference pinned to a commit is fetched on the first start and read from the disk cache afterwards.
  • A configuration that declares no [memory] section is served with the in-process memory, in_memory. Its threads live in the server process, so every instance holds its own. Several instances behind a load balancer need a shared redis or sqlalchemy memory, see Multi-instance deployment.
  • Any top-level section can be overridden with a PIIGHOST_ variable holding a JSON object, as for a file, see Environment overrides. PIIGHOST_MEMORY thus adds a shared memory to a catalog configuration. The memory in the example below needs piighost[crypto] for its cipher.
  • Without a key in an API_KEY_ variable, the server refuses to start unless PIIGHOST_ALLOW_ANONYMOUS is set.
export PIIGHOST_MEMORY='{"type": "redis", "url": "redis://redis:6379/0", "hasher": {"type": "argon2"}, "cipher": {"type": "aesgcm"}}'
piighost-api serve --config catalog:piighost/support-en

Environment variables

VariableDefaultEffect
PIIGHOST_CONFIGnoneConfig file or catalog reference, read when --config is absent
API_KEY_<NAME>noneOne accepted API key per variable. The value is one printed by keyshield generate
SECRET_PEPPERkeyshield's built-in pepper, with a warningPepper of the Argon2 hash the server keeps of each key, printed by keyshield pepper
PIIGHOST_ALLOW_ANONYMOUSoff1, true, yes or on lets the server start with no key, every route then open. Also applies when the keys fail to load
PIIGHOST_MAX_BODY_BYTES1000000Largest request body accepted, beyond it 413
PIIGHOST_RATE_LIMIToff<unit>:<count> per client, unit one of second, minute, hour, day, such as minute:300. A malformed value stops the server at start
PIIGHOST_OPENAI_UPSTREAMhttps://api.openai.com/v1Upstream of /openai/v1 when a request names none
PIIGHOST_ANTHROPIC_UPSTREAMhttps://api.anthropic.com/v1Upstream of /anthropic/v1 when a request names none
PIIGHOST_ANTHROPIC_ANONYMIZE_SYSTEMfalse1, true, yes or on de-identifies the system prompt too
PIIGHOST_ANTHROPIC_PLACEHOLDER_NOTEempty, no notedefault adds the built-in note on placeholders. Any other text is used as the note itself
PIIGHOST_ANTHROPIC_NOTE_PLACEMENTsystemuser puts the note in the first user message, any other value in the system prompt
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINTnoneAn OTLP endpoint turns on trace export. When both are set, the first one listed wins. Needs the observation extra
OTEL_SERVICE_NAMEpiighost-apiService name of the exported traces
LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEYnoneCredentials of dataset extract

The pipeline reads its own secrets (PIIGHOST_HASH_PEPPER, PIIGHOST_CIPHER_KEY, PIIGHOST_DATABASE_URL and MISTRAL_API_KEY). PIIGHOST_CATALOG_URL names a private catalog. These variables are listed in the TOML reference. The other OTEL_* variables, headers included, are read by the OpenTelemetry exporter itself, see Observation.

The Docker image reads four more, listed in Deploy a production pipeline.


piighost-api dataset extract

Reads traces from Langfuse and writes one JSONL record per trace. It needs the dataset extra and LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY, read from the environment or from a .env file in the working directory. Without them, it exits 1.

piighost-api dataset extract --output dataset.jsonl --since 2026-09-01 --limit 1000
OptionDefaultDescription
--output, -orequiredJSONL file to write
--sincenoneSkip traces older than this date, %Y-%m-%d, %Y-%m-%dT%H:%M:%S or %Y-%m-%d %H:%M:%S
--untilnoneSkip traces newer than this date, same formats
--modeallhitl, model-only or all
--limitnoneStop after this many records
--modeTrace name readentities taken from
hitlpiighost.hitl_correctionthe trace output's detections, the human correction
model-onlypiighost.anonymizethe output detections of its piighost.detect child
allbothper trace

A trace without input text, or a model trace without its piighost.detect child, is skipped. The command ends with Wrote N records to FILE (M skipped).

{
  "text": "Hi Jane Doe, from Acme in Boston",
  "entities": [[3, 11, "PERSON"], [18, 22, "ORGANIZATION"], [26, 32, "LOCATION"]],
  "model_entities": [[3, 11, "PERSON"], [18, 22, "LOCATION"]],
  "labels_universe": [],
  "source": "hitl",
  "trace_id": "...",
  "session_id": "...",
  "created_at": "..."
}
FieldContent
entitiesThe reference spans as [start, end, label]. They are the human correction for a hitl record, and the model output for a model record
model_entitiesThe model's spans, equal to entities on a model record
labels_universeThe labels of a correction trace's input, empty on a model record
sourcehitl or model

piighost-api dataset metrics

Scores the model against the reference of a JSONL file written by dataset extract, label by label. It needs no extra.

piighost-api dataset metrics --input dataset.jsonl
OptionDefaultDescription
--input, -irequiredJSONL file to read
--output, -ostdoutFile to write the report to
--output-formattabletable, csv or json
--match-modestrictstrict matches span and label exactly, lenient matches a same-label span whose overlap ratio reaches --iou-threshold
--iou-threshold0.5Overlap floor in lenient mode
--sourceallhitl, model or all, the records to score

On the record above, the table reads:

label                    tp     fp     fn      P      R     F1
--------------------------------------------------------------
LOCATION                  0      1      1   0.00   0.00   0.00
ORGANIZATION              0      0      1   0.00   0.00   0.00
PERSON                    1      0      0   1.00   1.00   1.00
--------------------------------------------------------------
macro avg                 -      -      -   0.33   0.33   0.33
micro avg                 -      -      -   0.50   0.33   0.40

Label confusion (model -> human, same span):
  LOCATION -> ORGANIZATION: 1

tp counts a model span the reference holds, fp a model span it lacks, fn a reference span the model missed. P, R and F1 are the precision, the recall and their harmonic mean. The confusion section lists the spans where model and reference agree on the offsets and differ on the label.


See also