|
| 1 | +# Location Tagger Agent |
| 2 | + |
| 3 | +The **Location Tagger** is a built-in, global default agent that automatically |
| 4 | +finds place names in a document and turns them into *geocoded* annotations: |
| 5 | +`OC_COUNTRY`, `OC_STATE`, and `OC_CITY`. Each annotation it creates carries the |
| 6 | +resolved coordinates and administrative codes in its `data` payload, so the |
| 7 | +places show up as pins on the **Discover** and **Corpus Home** maps. |
| 8 | + |
| 9 | +It is wired to run through the ordinary |
| 10 | +[corpus-actions](../walkthrough/step-9-corpus-actions.md) framework — the |
| 11 | +same execution path used by the built-in Document Assistant and Corpus |
| 12 | +Assistant — so you configure it once on a corpus and it runs automatically. |
| 13 | + |
| 14 | +## What it does |
| 15 | + |
| 16 | +For every place mention it recognises, the agent calls the |
| 17 | +`add_annotations_from_exact_strings` tool with the appropriate label and a set |
| 18 | +of *hints*. When the label is one of the geographic labels |
| 19 | +(`OC_COUNTRY` / `OC_STATE` / `OC_CITY`), the tool routes the string through the |
| 20 | +offline geocoding service ([#1819](https://github.com/Open-Source-Legal/cite/issues/1819)) |
| 21 | +and stores the result on the annotation: |
| 22 | + |
| 23 | +```json |
| 24 | +{ |
| 25 | + "canonical_name": "Austin", |
| 26 | + "lat": 30.2672, |
| 27 | + "lng": -97.7431, |
| 28 | + "admin_codes": { "iso_alpha2": "US", "admin1": "TX" }, |
| 29 | + "geocoded": true |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +Non-geographic labels are unaffected — the `hints` field is simply ignored for |
| 34 | +them, so existing callers of the tool keep working unchanged. |
| 35 | + |
| 36 | +## Configuration walkthrough |
| 37 | + |
| 38 | +1. **Migrate.** After deploying, run migrations. The Location Tagger appears as |
| 39 | + a global, public agent in the agent picker: |
| 40 | + |
| 41 | + ```bash |
| 42 | + docker compose -f production.yml --profile migrate up migrate |
| 43 | + ``` |
| 44 | + |
| 45 | + > **Note — the migration is a one-time snapshot.** It copies |
| 46 | + > `DEFAULT_LOCATION_TAGGER_INSTRUCTIONS` from settings into the agent's |
| 47 | + > `system_instructions` column at creation time. If you later improve the |
| 48 | + > prompt in `config/settings/base.py`, **existing databases keep the old |
| 49 | + > prompt** — update the `Location Tagger` agent record via the Django admin |
| 50 | + > (or a follow-up data migration) to pick up the revision. |
| 51 | +
|
| 52 | +2. **Add a corpus action.** On the corpus you want tagged, create a |
| 53 | + `CorpusAction` that points at the **Location Tagger** agent and choose a |
| 54 | + trigger: |
| 55 | + |
| 56 | + | Trigger | When it fires | Use it to… | |
| 57 | + | -------------- | ------------------------------------------ | ----------------------------------- | |
| 58 | + | `ADD_DOCUMENT` | Every time a document is added to the corpus | Auto-tag new uploads as they arrive | |
| 59 | + | `MANUAL_BATCH` | When you run the action on demand | Back-fill an existing corpus | |
| 60 | + |
| 61 | +3. **Upload or back-fill.** With `ADD_DOCUMENT`, upload a document containing |
| 62 | + place mentions and the action fires automatically. With `MANUAL_BATCH`, |
| 63 | + trigger the action to sweep documents already in the corpus. |
| 64 | + |
| 65 | +4. **See the pins.** Open **Corpus Home** (or **Discover**) and switch to the |
| 66 | + map view; the geocoded annotations render as pins. |
| 67 | + |
| 68 | +## Worked example |
| 69 | + |
| 70 | +Given a paragraph such as: |
| 71 | + |
| 72 | +> "The summit was held in **Paris, France**, with follow-up meetings in |
| 73 | +> **Austin, Texas** and **Paris, Texas**." |
| 74 | +
|
| 75 | +the agent emits three city annotations, disambiguated via hints: |
| 76 | + |
| 77 | +| Mention | Label | `hints` sent by the agent | Resolved `admin_codes` | |
| 78 | +| --------------- | ----------- | ---------------------------------- | --------------------------------- | |
| 79 | +| Paris, France | `OC_CITY` | `{ "country": "FR" }` | `{ "iso_alpha2": "FR" }` | |
| 80 | +| Austin, Texas | `OC_CITY` | `{ "country": "US", "state": "TX" }` | `{ "iso_alpha2": "US", "admin1": "TX" }` | |
| 81 | +| Paris, Texas | `OC_CITY` | `{ "country": "US", "state": "TX" }` | `{ "iso_alpha2": "US", "admin1": "TX" }` | |
| 82 | + |
| 83 | +Without the `state` hint, "Paris" would be ambiguous; the hint lets the |
| 84 | +geocoder pick **Paris, TX** over **Paris, France**. |
| 85 | + |
| 86 | +## Limitations |
| 87 | + |
| 88 | +- **Offline reference dataset.** Resolution uses the bundled reference data |
| 89 | + (ISO 3166-1 countries, US states, and a curated set of cities). Places not in |
| 90 | + the dataset cannot be geocoded and are skipped. |
| 91 | +- **No ambiguous-name resolution beyond hints.** Disambiguation relies on the |
| 92 | + `country` / `state` hints the agent supplies. A bare, ambiguous place name |
| 93 | + resolves to the dataset's best single match. |
| 94 | +- **Exact-string matching.** Annotations are created only where the place name |
| 95 | + appears verbatim in the document text. |
| 96 | +- **Re-runs are not deduplicated yet.** Running the tagger again over an |
| 97 | + already-tagged document may create duplicate annotations; idempotent |
| 98 | + re-tagging is a planned follow-up. |
| 99 | + |
| 100 | +## Related |
| 101 | + |
| 102 | +- [#1819](https://github.com/Open-Source-Legal/cite/issues/1819) — geocoding foundation (`resolve_place`, `OC_*` labels) |
| 103 | +- [#1820](https://github.com/Open-Source-Legal/cite/issues/1820) / [#1821](https://github.com/Open-Source-Legal/cite/issues/1821) — the Discover and Corpus Home map views |
0 commit comments