Skip to main content

gheim

gheim (Python). PII round-trip for LLM APIs.

PyPI Python 3.11+ Apache 2.0

Detect PII in text, substitute it with stable sentinels (<PERSON_1>, <EMAIL_2>, ...), send the redacted text to any LLM, and restore the originals on the way back, including in streamed responses. The package is framework-agnostic and ships a drop-in openai client wrapper for zero-effort integration.

See the monorepo README for the cross-language overview and architecture.

Install

uv add gheim                          # core: pairs with a RemoteDetector or GHEIM_API_KEY
uv add "gheim[local]"                 # + torch and transformers for on-device detection
uv add "gheim[openai]"                # + drop-in OpenAI client
uv add "gheim[local,openai]"          # both

Model choice

LocalDetector runs a token-classification model in process. The package's default model is joelbarmettler/gheim-ch-560m — a 560M xlm-roberta-large fine-tune optimised for Swiss-market PII (test strict F1 0.910, char F1 0.946 on Swiss text, see MODEL_CARD.md). Any HuggingFace token-classification model that emits the same 33-class BIOES schema can be substituted via the model_id constructor arg.

Model Best for Parameters Notes
joelbarmettler/gheim-ch-560m (default) Production / commercial. Swiss court / parliament / web text with CH-format account numbers (IBAN, AHV, VAT-CHE) 560M Apache 2.0. Test strict F1 0.910, char F1 0.946.
joelbarmettler/gheim-ch-560m-research Research / non-commercial. Stronger cross-domain transfer on Swiss-news text (swissner PER char F1 0.90 vs 0.70 on the default) 560M CC BY-NC-SA 4.0 + Reuters research-only rider. In-distribution numbers identical to the default.
openai/privacy-filter English-first or general use, long-context (up to 128k tokens) 1.4B (50M active, MoE) Apache 2.0. Wider language coverage, larger weights.
from gheim import LocalDetector

# Default — Swiss-tuned, 560M, Apache 2.0:
det = LocalDetector()

# Stronger cross-domain transfer (research, non-commercial):
det = LocalDetector(model_id="joelbarmettler/gheim-ch-560m-research")

# Alternative for English or general use:
det = LocalDetector(model_id="openai/privacy-filter")

Drop-in OpenAI client

from gheim.openai import OpenAI

client = OpenAI()  # same constructor args as openai.OpenAI
r = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hi, my name is Joel"}],
)
# r.choices[0].message.content contains "Joel".
# OpenAI only ever saw "<PERSON_1>".

Custom endpoint or key (e.g. OpenRouter, local vLLM):

client = OpenAI(api_key="sk-or-...", base_url="https://openrouter.ai/api/v1")

Streaming:

stream = client.chat.completions.create(..., stream=True)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="", flush=True)

Async:

from gheim.openai import AsyncOpenAI
client = AsyncOpenAI()
r = await client.chat.completions.create(...)

Per-call overrides:

from gheim import Session
session = Session()  # reuse across calls for multi-turn coherent sentinels
r = client.chat.completions.create(
    model="gpt-4o",
    messages=[...],
    gheim_session=session,    # or gheim_detector=...
)

Framework-agnostic

from gheim import Session, LocalDetector, anonymize_text, deanonymize_text

session = Session(detector=LocalDetector())  # gheim-ch-560m by default
clean = anonymize_text("Hi, my name is Joel", session)
# ... call any LLM with clean ...
final = deanonymize_text(response_text, session)

Streaming deanonymizer:

from gheim import deanonymize_stream
for chunk in deanonymize_stream(my_chunk_iterator, session):
    print(chunk, end="", flush=True)

Chat-message helpers:

from gheim import anonymize_messages

redacted = anonymize_messages(messages, session)  # preserves role, name, tool_call_id

Wrapped endpoints

The drop-in OpenAI / AsyncOpenAI clients automatically protect every text-carrying endpoint: chat.completions, responses, completions (legacy), embeddings, moderations, audio.speech, audio.transcriptions, audio.translations, images.generate, images.edit. Tool-call arguments and SSE delta chunks are restored on the way back. See the monorepo README for the full coverage matrix and the embeddings caveat.

Strict mode

gheim_strict=True (default) raises RuntimeError if you call an unwrapped endpoint (beta.assistants, batches, files, uploads, fine_tuning, vector_stores). The error message names client.raw.<path> as the documented escape hatch.

client = OpenAI(gheim_strict=False)  # downgrade to one-time warnings
client.raw.beta.assistants.create(...)  # always works regardless of strict mode

Detector backends

import torch
from gheim import LocalDetector, RemoteDetector, default_detector

# Local inference. Weights download to the HF cache on first use.
# `model_id` defaults to "joelbarmettler/gheim-ch-560m"; pass
# `dtype=torch.bfloat16` for half-precision GPU inference.
det = LocalDetector(device="auto", dtype=torch.bfloat16)

# Remote inference against your own gheim-server or api.gheim.ch.
det = RemoteDetector(base_url="http://your-host:8080", api_key="...")

# default_detector() picks remote if GHEIM_API_KEY is set, else local.
det = default_detector()

For categories where structure is verifiable by checksum (CH-IBAN, AHV, VAT-CHE, credit cards, common token formats) the package ships a regex catalogue under gheim.detectors.composite that pairs with the model detector. The composite detector applies regex first, masks matched spans, then runs the model on the remainder. This pushes effective recall on account_number, private_phone, and private_url close to 1.0 with high precision; the underlying ML model handles person names, addresses, and dates.

Consulting

gheim is built and maintained by Souverana, a Swiss AI consulting business helping companies build secure, privacy-first AI systems — on-premise LLM deployments, PII/data-protection engineering, and Swiss-market NLP. If you need help integrating gheim or building compliant AI, get in touch at souverana.ch.

License

Apache 2.0. Bundled model weights are inherited from the upstream license of the model you select.

Metadata

Release files for gheim 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gheim 0.1.7
File Size Uploaded
gheim-0.1.7.tar.gz 42.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gheim 0.1.7
File Interpreter ABI Platform
gheim-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 96.6 kB

Release files / gheim-0.1.7.tar.gz

Download URL gheim-0.1.7.tar.gz
Size 42.1 kB
Tags Source
SHA-256 checksum
How to use checksums
38d795a32d92558888de6fb1856b249fb1237018d896333594e54f55418d0262
BLAKE2b-256 checksum
How to use checksums
04b4f2e9fb38b91fbdd7e27a9e92c8412e3fa7131448ca9dce82154493a7c0af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.

Transparency log

Release files / gheim-0.1.7-py3-none-any.whl

Download URL gheim-0.1.7-py3-none-any.whl
Size 54.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9375f6fd2f742d62faad0281f3b48ef95bdd52a0df3e92ccacb8b67dd038b241
BLAKE2b-256 checksum
How to use checksums
998b78c55f450d33cd69434d5fa43b0b9f05d1670c32ac02b2b3dbb1836a97d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page