Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ One SIE cluster runs the inference behind a whole agent. Each task is a handful
| **Search** | Embed, match, and rerank to retrieve the right context. | [`bge-m3`](packages/sie_server/models/BAAI__bge-m3.yaml), [`splade-v3`](packages/sie_server/models/naver__splade-v3.yaml), [`colbertv2`](packages/sie_server/models/colbert-ir__colbertv2.0.yaml), [`qwen3-reranker`](packages/sie_server/models/Qwen__Qwen3-Reranker-4B.yaml) |
| **Document to markdown** | PDFs, Office files, and scans become clean markdown. | [`lightonocr`](packages/sie_server/models/lightonai__LightOnOCR-2-1B.yaml), [`glm-ocr`](packages/sie_server/models/zai-org__GLM-OCR.yaml), [`mineru`](packages/sie_server/models/opendatalab__MinerU2.5-Pro-2604-1.2B.yaml), [`paddleocr-vl`](packages/sie_server/models/PaddlePaddle__PaddleOCR-VL-1.5.yaml), [`docling`](packages/sie_server/models/docling.yaml) |
| **Structured output** | Schema-valid JSON, extracted or generated. | [`gliner2`](packages/sie_server/models/fastino__gliner2-large-v1.yaml), [`gliner-relex`](packages/sie_server/models/knowledgator__gliner-relex-large-v1.0.yaml), [`gliformer`](packages/sie_server/models/knowledgator__gliformer-large-v1.yaml), [`nuner-zero`](packages/sie_server/models/numind__NuNER_Zero.yaml), [`qwen3.8-27b`](packages/sie_server/models/Qwen__Qwen3.8-27B-FP8.yaml), [`qwen3.6-27b`](packages/sie_server/models/Qwen__Qwen3.6-27B.yaml) |
| **Decide** | Choice, yes/no, and score answers with probabilities to typed questions about a text or JSON state. | [`laya`](packages/sie_server/models/convaiinnovations__laya.yaml), [`laya-multilingual`](packages/sie_server/models/convaiinnovations__laya-multilingual.yaml), [`laya-typed-decisions`](packages/sie_server/models/convaiinnovations__laya-typed-decisions.yaml) |
| **Decide** | Choice, yes/no, and score answers with probabilities to typed questions about a text or JSON state. | [`laya`](packages/sie_server/models/convaiinnovations__laya.yaml), [`laya-multilingual`](packages/sie_server/models/convaiinnovations__laya-multilingual.yaml), [`laya-typed-decisions`](packages/sie_server/models/convaiinnovations__laya-typed-decisions.yaml), [`gliner2.5-decide`](packages/sie_server/models/fastino__GLiNER2.5-Decide.yaml), [`gliner2.5-multi-decide`](packages/sie_server/models/fastino__GLiNER2.5-multi-Decide.yaml), [`gliner2.5-decide-1b`](packages/sie_server/models/fastino__GLiNER2.5-Decide-1B.yaml) |
| **Classify** | Zero-shot labels, with several label groups answered in one call. The instruct models also follow a task instruction and few-shot examples. | [`gliclass-large-v3`](packages/sie_server/models/knowledgator__gliclass-large-v3.0.yaml), [`gliclass-instruct-large`](packages/sie_server/models/knowledgator__gliclass-instruct-large-v1.0.yaml), [`gliclass-multilang-mini`](packages/sie_server/models/knowledgator__gliclass-multilang-mini.yaml) |
| **Guard content** | A safety verdict: Yes/No with the threshold set in the model config, or safe/unsafe and policy-label scores with the threshold chosen per request. | [`granite-guardian-2b`](packages/sie_server/models/ibm-granite__granite-guardian-3.0-2b.yaml), [`opir-multitask-large`](packages/sie_server/models/knowledgator__opir-multitask-large-v1.0.yaml), [`opir-edge`](packages/sie_server/models/knowledgator__opir-edge-v1.0.yaml) |
| **Run the agent loop** | Plan steps and call tools with an open LLM, streaming included. | [`qwen3.8-27b`](packages/sie_server/models/Qwen__Qwen3.8-27B-FP8.yaml), [`qwen3.6-27b`](packages/sie_server/models/Qwen__Qwen3.6-27B.yaml) |
Expand All @@ -69,7 +69,7 @@ docker run --gpus all -p 8080:8080 \
-v sie-hf-cache:/app/.cache/huggingface \
ghcr.io/superlinked/sie-server:latest-cuda12-default

# Linux, NVIDIA GPU: Transformers 5 OCR models (LightOnOCR and GLM-OCR)
# Linux, NVIDIA GPU: Transformers 5 models (LightOnOCR, GLM-OCR, and the GLiNER2.5-Decide models)
docker run --gpus all -p 8080:8080 \
-v sie-hf-cache:/app/.cache/huggingface \
ghcr.io/superlinked/sie-server:latest-cuda12-transformers5
Expand All @@ -87,7 +87,8 @@ docker run -p 8080:8080 \

Docker images are bundle-specific so dependency-incompatible model families stay isolated. Use the
`sglang-vision-extract` image for LightOnOCR, GLM-OCR, and PaddleOCR-VL, or the `transformers5` image for the
`:transformers` profiles of LightOnOCR and GLM-OCR; the `default` image intentionally does not advertise them.
`:transformers` profiles of LightOnOCR and GLM-OCR and for the GLiNER2.5-Decide models; the `default` image
intentionally does not advertise them.

```bash
# in a second terminal
Expand Down Expand Up @@ -182,6 +183,30 @@ print(result["data"]["department"]) # values are illustrative and rounded
# {'type': 'choice', 'choice': 'billing', 'probabilities': {'billing': 0.987, 'technical': 0.013}, 'confidence': 0.9}
```

The GLiNER2.5-Decide models (`fastino/GLiNER2.5-Decide` for English, `GLiNER2.5-multi-Decide`, and
`GLiNER2.5-Decide-1B`), served by the `transformers5` image from step 1, take the same questions, GLiClass-style `options={"label_groups": {...}}`, or plain `labels`,
and return every option's probability. They read all of a call's questions next to the document in one row per item:
one forward pass answers them all, and each question's probabilities depend on the other questions sent with it. A
`score` question is read as the ordinal labels `"0"` to `"k-1"`, each described by its criterion; a `noul` question as
`"yes"`/`"no"`. `usage.input_tokens` counts the document tokens the model reads plus the questions' instructions and
criteria text; question ids and label names are not counted.

```python
result = client.extract(
"fastino/GLiNER2.5-Decide",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Item(text="Guest in room 1408 says the AC has been out since yesterday and wants to move rooms tonight."),
output_schema={
"intent": {"type": "choice", "instructions": "What does the guest want?",
"criteria": {"room_change": "move to another room", "maintenance": "fix something", "checkout": None}},
"needs_human": {"type": "noul", "instructions": "Must a person act on this?"},
"urgency": {"type": "score", "instructions": "How urgent is this?", "criteria": ["low", "normal", "high", "urgent"]},
},
)
print(result["data"]["intent"]) # values are illustrative and rounded
# {'type': 'choice', 'choice': 'room_change',
# 'probabilities': {'room_change': 0.871, 'maintenance': 0.085, 'checkout': 0.045}, 'confidence': 0.57}
```

Text generation runs on the GPU generation image; stop the first server, then start this one on the same port:

```bash
Expand Down
39 changes: 39 additions & 0 deletions packages/sie_sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,45 @@ graphs by default: their probabilities differed from eager execution by up to
turn graphs on. See the server README for each model's measurements and the
memory graphs use.

## Typed decisions

Typed-decision models answer typed questions about each item and return a
probability for every option. The Laya models and the GLiNER2.5-Decide models
take the same question mapping as `output_schema`: `choice` (pick one of the
criteria), `noul` (yes or no), and `score` (an ordinal scale, index 0 first).
Answers come back in `data`, keyed by question id.

```python
result = client.extract(
"fastino/GLiNER2.5-Decide",
Item(text="This is the third time I have explained the same missing refund. Get me a person."),
output_schema={
"intent": {
"type": "choice",
"instructions": "What does the customer want?",
"criteria": {"refund_request": "money back", "cancel": None, "complaint": "unhappy with service"},
},
"handoff": {"type": "noul", "instructions": "Should a person take over?"},
"frustration": {"type": "score", "instructions": "How frustrated is the customer?",
"criteria": ["calm", "annoyed", "angry"]},
},
)
answers = result["data"]
print(answers["intent"]["choice"], answers["intent"]["probabilities"])
# e.g. refund_request {'refund_request': 0.59, 'cancel': 0.07, 'complaint': 0.34}
print(answers["handoff"]["answer"], answers["handoff"]["noul"]) # True 0.99 (the probability of yes)
print(answers["frustration"]["score"]) # e.g. 1.13, the expected level from 0 to 2
```

`choice` and `score` answers carry `probabilities` and `confidence`
(`1 - entropy / log(number of options)`); a `noul` answer carries `noul`, the
probability of yes, `answer`, and `confidence` (`max(p, 1 - p)`). The
GLiNER2.5-Decide models also accept `options={"label_groups": {...}}` with
`"classification_type": "multi-label"` for independent per-label scores, and
plain `labels`, which return every label in `classifications`. They read all
of a call's questions in one row per item, so each question's probabilities
depend on the other questions sent with it.

## Generation prompts and guard verdicts

`generate` and `stream_generate` treat text-only prompts as raw continuation
Expand Down
39 changes: 38 additions & 1 deletion packages/sie_server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@ pip install sie-server
pip install sie-server "transformers<5"
```

- **OCR-VLM bundle** (LightOnOCR, GLM-OCR) — requires `transformers` 5.x, and is served with `-b transformers5`:
- **Transformers 5 bundle** (LightOnOCR, GLM-OCR, GLiGuard, and the GLiNER2.5-Decide models) — requires
`transformers` 5.x, and is served with `-b transformers5`. The GLiNER2.5-Decide models also need `gliner2`
2.x. `sie-server` itself asks for `gliner2<2`, which the default bundle's GLiNER2 models need, so pip
reports that conflict when the second command below installs 2.x; the transformers5 bundle's GLiNER2
models are verified on 2.0.0:

```bash
pip install sie-server "transformers>=5,<6"
pip install "gliner2==2.0.0" # only for the GLiNER2.5-Decide models
sie-server serve -b transformers5
```

Expand Down Expand Up @@ -169,6 +174,38 @@ largest shape on `gliclass-large-v1.0`. On a GPU shared with other models,
leave memory headroom, or enable graphs only where the model has the GPU to
itself. Usage and billing do not change.

### GLiNER2.5-Decide usage and limits

The GLiNER2.5-Decide models (`fastino/GLiNER2.5-Decide`, `GLiNER2.5-multi-Decide`,
`GLiNER2.5-Decide-1B`) run on `gliner2` 2.x, which the transformers5 bundle
Comment thread
coderabbitai[bot] marked this conversation as resolved.
pins (the `transformers5` image, or a native install as described above). Each
item is one encoder row: every question's (or label group's) name,
instruction, and labels, then the document. One forward pass answers them all,
so the questions of a request are not independent: adding or changing one can
change another's probabilities and score. `usage.input_tokens` counts the
document tokens the model reads plus the tokens of the instructions and label
descriptions (criteria) sent with the item, as Laya and GLiClass count
instructions and criteria. Question ids, group names, and label names are not
counted, and an item that returns an error counts nothing.

A request takes at most 64 questions or label groups, 64 options per question,
and 1,024 options in total. Question ids and group names may have 128
characters, labels 256, and each instruction or description 2,048, with 65,536
characters in all. Strings that contain one of the model's prompt markers
(`[L]`, `[P]`, `[DESCRIPTION]`, ...) are refused. The questions may take at most
512 tokens, or half the model's window when that is less: 256 of
`GLiNER2.5-Decide`'s 512 tokens, 512 of the others' 2,048. This bounds the
uncounted question and label tokens read with each item; a request needing more
fails with `INPUT_TOO_LONG`. The
document is read up to the whole words that fit in the rest of the window; a
word longer than 4,096 characters, text past 64 characters per token of the
window, or 4 words per token of the window also ends what is read. Words are
split as gliner2 splits them, in linear time. A conversation (a list state) is
read from its newest turn back; a run of more than 4,096 characters without a
space is read only in its last 4,096 characters, and reading stops there. An item none of whose words fits, or that does
not fit whole with `options={"overflow_policy": "error"}`, returns a per-item
`INPUT_TOO_LONG` error while the other items succeed.

## Configuration

`sie-server` reads its config from `SIE_*` environment variables (Pydantic
Expand Down
5 changes: 4 additions & 1 deletion packages/sie_server/bundles/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ deps:
requests: ''
# gliner, gliner_bi (0.2.26: first release that loads the relex checkpoints)
gliner: '>=0.2.26,<1'
# gliner2
# gliner2. Held at 1.x: gliner2 2.0 changes gliner2-base/large-v1 outputs
# (every repeated NER mention is returned, and structured extraction is
# rescored). The GLiNER2.5-Decide models, which need 2.x, are served from
# the transformers5 bundle.
gliner2: '>=1.3.1,<2'
# glirel
glirel: '>=1.0,<2'
Expand Down
10 changes: 8 additions & 2 deletions packages/sie_server/bundles/transformers5.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ adapters:
- sie_server.adapters.lighton_ocr.adapter
- sie_server.adapters.glm_ocr
- sie_server.adapters.gliner2.classification
- sie_server.adapters.gliner2.decide
- sie_server.adapters.st_sparse_vision.adapter
deps:
# Transformers 5.x for models requiring newer architecture support
Expand All @@ -30,5 +31,10 @@ deps:
# unsatisfiable against that pin and broke `uv run` resolution.
# Let transformers drive the version.
pillow: ''
# gliguard-LLMGuardrails-300M uses GLiNER2 classification APIs.
gliner2: '>=1.3.1,<2'
# gliguard-LLMGuardrails-300M uses GLiNER2 classification APIs, and the
# GLiNER2.5-Decide models need gliner2 2.x (AutoExtractor, boundary
# architecture). Exact: the Decide adapter builds the task prompt with the
# package's processor. GLiGuard's outputs are unchanged from 1.3.2. gliner2
# 2.0 declares transformers<5 only for its `local` extra, which is not used;
# the multilingual and 1B Decide checkpoints were saved with transformers 5.
gliner2: '==2.0.0'
38 changes: 38 additions & 0 deletions packages/sie_server/models/fastino__GLiNER2.5-Decide-1B.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# GLiNER2.5-Decide-1B: typed-decision classifier on the Ettin 1B encoder
# (jhu-clsp/ettin-enc-from-dec-1b, ModernBERT; span architecture), loaded through
# gliner2 2.x AutoExtractor. Served from the transformers5 bundle, which pins gliner2 2.x.
#
# Checkpoint caveat: the weights at this revision are the step-285000 checkpoint
# (upload commit eac5ac1e). The 59.6% fast-decisions score on the model card was
# measured on an earlier step-195000 checkpoint (stated in that revision's card);
# the uploaded weights had not been re-evaluated.
#
# The encoder config stores its RoPE bases only in the transformers-5
# rope_parameters form (160000 for full and sliding-window layers). The adapter
# checks the bases the loaded encoder actually uses, and under transformers 4
# writes them where that version reads them (it would otherwise run the
# sliding-window layers at 10000).
sie_id: fastino/GLiNER2.5-Decide-1B
hf_id: fastino/GLiNER2.5-Decide-1B
hf_revision: 52c94d3b698bf6d2619df9d898bdc1523ea3f1ca
inputs:
text: true
image: false
audio: false
video: false
tasks:
encode: null
score: null
extract: {}
# Tokens per item: every question's prompt and labels, then the document. The
# Ettin encoder config sets max_position_embeddings 7999 and the tokenizer
# model_max_length 8192; 2048 tokens stays within both.
max_sequence_length: 2048
profiles:
default:
max_batch_tokens: 16384
compute_precision: float16
adapter_path: sie_server.adapters.gliner2.decide:GLiNER2DecideAdapter
adapter_options:
loadtime: {}
runtime: {}
28 changes: 28 additions & 0 deletions packages/sie_server/models/fastino__GLiNER2.5-Decide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# GLiNER2.5-Decide: English typed-decision classifier (DeBERTa-v3-large encoder,
# span architecture), loaded through gliner2 2.x AutoExtractor. Served from the
# transformers5 bundle, which pins gliner2 2.x.
sie_id: fastino/GLiNER2.5-Decide
hf_id: fastino/GLiNER2.5-Decide
hf_revision: 7ee5da4c2415e32259bcdc0b1a7367c32ce8d6f6
inputs:
text: true
image: false
audio: false
video: false
tasks:
encode: null
score: null
extract: {}
# Tokens per item: every question's prompt and labels, then the document. 512,
# as for fastino/gliner2-large-v1, this model's base: its DeBERTa-v3-large encoder
# was pretrained on 512 positions (max_position_embeddings), and neither the model
# card nor the checkpoint config (max_len null) gives a longer length.
max_sequence_length: 512
profiles:
default:
max_batch_tokens: 16384
compute_precision: float16
adapter_path: sie_server.adapters.gliner2.decide:GLiNER2DecideAdapter
adapter_options:
loadtime: {}
runtime: {}
27 changes: 27 additions & 0 deletions packages/sie_server/models/fastino__GLiNER2.5-multi-Decide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# GLiNER2.5-multi-Decide: multilingual typed-decision classifier (mDeBERTa-v3-base
# encoder, boundary architecture; trained with max_len 4096 words), loaded through
# gliner2 2.x AutoExtractor. Served from the transformers5 bundle, which pins gliner2 2.x.
sie_id: fastino/GLiNER2.5-multi-Decide
hf_id: fastino/GLiNER2.5-multi-Decide
hf_revision: 6bc1d43d201b0691e733626389af8c57eea3ea68
inputs:
text: true
image: false
audio: false
video: false
tasks:
encode: null
score: null
extract: {}
# Tokens per item: every question's prompt and labels, then the document. The
# checkpoint config sets max_len 4096 (gliner2 counts it in words), and the
# tokenizer sets no length limit; 2048 tokens stays within both.
max_sequence_length: 2048
profiles:
default:
max_batch_tokens: 16384
compute_precision: float16
adapter_path: sie_server.adapters.gliner2.decide:GLiNER2DecideAdapter
adapter_options:
loadtime: {}
runtime: {}
2 changes: 2 additions & 0 deletions packages/sie_server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ dependencies = [
# never shipped, killing three extract cells at model load (#2873).
# 0.2.26 is the first release that loads the joint entity-relation checkpoints.
"gliner>=0.2.26,<1",
# gliner2 stays on 1.x with the default bundle (2.0 changes gliner2-base/large
# outputs); the transformers5 bundle overlays the 2.x pin its GLiNER2.5 models need.
"gliner2>=1.3.1,<2",
"glirel>=1.0,<2",
# 0.1.17 adds the cross-attention scorer and pass-through pooling used by
Expand Down
Loading
Loading