Skip to content
Open
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
7 changes: 7 additions & 0 deletions packages/sie_server/src/sie_server/types/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,19 @@ class Relation(TypedDict):
tail: Tail entity text.
relation: Relation type label.
score: Confidence score.
head_idx: Index of the head entity in the same item's entities list, when the
adapter can supply it. Lets a consumer recover the head's character offsets
without duplicating them here, which is the only way to attribute a relation
when the same surface text occurs more than once in the input.
tail_idx: Index of the tail entity in the same item's entities list.
"""

head: str
tail: str
relation: str
score: float
head_idx: NotRequired[int]
tail_idx: NotRequired[int]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. The problem is real and index-by-reference is the right shape: no duplicated span data, and it also links bbox-only image entities that carry no character offsets at all. Happy to take it, but it needs to land as a working slice rather than a type declaration alone. As submitted nothing produces the fields, and every boundary between an adapter and a consumer rebuilds relations from the four existing keys, so the indices cannot reach a caller.

What the PR needs to be complete:

  1. Server API layer. api/extract.py rebuilds each relation with head, tail, relation and score only. Carry head_idx and tail_idx through when present. This also keeps the direct path consistent with the queue path, which passes adapter dicts through unchanged.
  2. Published contract. Add the fields to RelationModel in types/openapi.py and to the Relation struct in sie_gateway/src/openapi.rs, then regenerate both committed specs with mise run openapi.
  3. SDKs. Both Relation types (sie_sdk/types.py, sie_ts_sdk/src/types.ts) and both parsers (client/_shared.py, internal/parsing.ts) drop the keys today.
  4. A producer. GLiREL is the natural first one. _relation_entity_text already finds the matching entity by walking zip(entities, ner_input), and the adapter echoes input entities in order, so the index into the response's entities list is well-defined. GLiNER2 will have to omit the fields because upstream returns text only, which is worth stating in the description.
  5. Tests. A GLiREL case with duplicated surface text (the "Dr Chen" fixture from the description) asserting the indices, plus coverage that the fields survive the API layer and both SDK parsers.



class Classification(TypedDict):
Expand Down