OGuardAI
Guides

Address Detection for Any Language

How OGuardAI detects addresses across languages, and how to extend detection to any locale without recompiling

OGuardAI detects and tokenizes addresses in any language, and you can extend structural detection to any locale through configuration, with no code change and no hardcoded ceiling.

The layers

  1. NER (language-agnostic). The advanced NER detector recognizes addresses in text of any language and tokenizes them. This is the primary path and needs no per-locale configuration.
  2. Built-in regex floor. A set of built-in address patterns ships for DE, US, FR, IT, ES, NL, and UK, giving high-precision detection for those common formats even without NER.
  3. Config-declared locale patterns. detector.vocab.extra_pattern_specs (and the simpler extra_patterns) let you add address regex for any locale. Overlays are additive (they can only add spans, never suppress a built-in one) and fail closed (invalid config aborts startup).

Detection is the protection boundary: once an address is detected and tokenized, policy controls how (or whether) it is restored. Component-level structural parsing (splitting street/city) is a restore-quality feature, not required for protection.

Adding a locale

The ready-to-use examples/address-locale-pack.yaml extends the floor to JP, CN, KR, BR (CEP), IN (PIN), RU, PL, and SE. Merge its detector.vocab.extra_pattern_specs.address list into your oguardai.yaml, or add your own:

detector:
  vocab:
    extra_pattern_specs:
      address:
        # A distinctive marker needs no gating.
        - pattern: '〒\d{3}-\d{4}'          # Japan postal code
          description: "JP postal"
        # A broad shape is gated on a nearby address keyword so it does not over-detect.
        - pattern: '\d{2}-\d{3}'            # Poland postal (NN-NNN)
          context_required: true
          context_words: ["adres", "kod pocztowy"]

Each spec accepts:

FieldMeaning
patternThe regex (linear-time Rust regex; length-capped). Required.
confidenceBase confidence in [0, 1] (default 0.8).
context_wordsBoost/gate words for this pattern.
context_requiredOnly emit a match when a context_word is within the window. Requires non-empty context_words.
context_window_charsOverride the gate window (characters).
value_groupTokenize only this capture group (validated against the regex, fail closed).
descriptionOperator note, ignored by the engine.

extra_patterns (a bare list of regex strings per label) still works for simple cases; extra_pattern_specs adds context gating and capture-group scoping, which is what broad address shapes need.

Regex safety rules

  • Anchor broad shapes. A pattern that matches arbitrary text (for example \d+, \w+, .*, or [A-Za-z]+) is rejected at startup. A fixed-width shape like \d{5} is accepted, but it over-detects every 5-digit run, so still anchor it on a script-specific postal marker (, 邮编, индекс, CEP, PIN) or set context_required: true with context_words so it only fires near an address keyword.
  • Avoid \b for CJK/Thai. Word boundaries do not behave as expected across scripts; anchor on markers, punctuation, or bounded character classes instead.
  • Keep it conservative. Prefer postal markers and address keywords with bounded tails over "anything after the city". Overlays are additive, so a narrow pattern that misses is safer than a broad one that over-detects.
  • Bounds are enforced. Pattern length, patterns-per-entity, and entity-type counts are capped; an invalid regex, an out-of-range value_group, or context_required without context_words aborts startup rather than degrading silently.

Testing a new locale

  1. Add the spec to detector.vocab.extra_pattern_specs.address.
  2. Start the server (it fails closed if the config is invalid).
  3. POST /v1/detect with a representative sample and confirm an address entity is returned with the expected span.
  4. Confirm a non-address sample of the same shape is NOT matched (tune context_required if it over-detects).