Geo

Some entities are places: a city, a country, a region, a landmark. With geo on, remember finds them and stores their coordinates next to the graph, so the graph knows where things are. It is optional and off by default.

What the stage does

The resolve_geo stage runs after the text (every chunk, for a long text) is stored and before the web search. It never fails the call: errors are logged, recorded in the trajectory and run log, and returned in geo of the result.

1. Candidates

The extracted entities that may be places (not a person, concept, product or event), at most 50, minus those that already have a row in gb_entity_geo. An entity is shared by every artifact that mentions it, so it is looked up once.

2. Detect

An LLM call (stage detect_geo) decides which candidates are places, their kind (country, region, city or place) and what to ask the resolver, such as "Paris, France". It prefers precision: "Bank of America" and "Paris Hilton" are not places.

3. Resolve

The geo resolver is asked for each place found (at most 25), one at a time. "Not found" is not a failure; the place is asked again the next time it is mentioned.

4. Store

One transaction writes the rows of gb_entity_geo.

detect_geo takes a model and a reasoning level like the other LLM stages. In an eval trajectory the stage shows as a select_geo_entities step, the detect_geo call, one resolve_geo step per place and a store_geo step.

The result

The geo field in the response of remember has one element per entity the LLM judged to be a place. resolved: false with no error means the resolver does not know the place; with an error, the resolver or the storage failed.

remember response (geo)
{
  "entity": "Paris", "entity_type": "place", "entity_id": 12,
  "kind": "city", "query": "Paris, France", "resolved": true,
  "latitude": 48.8588897, "longitude": 2.320041,
  "display_name": "Paris, Île-de-France, France", "country": "France",
  "country_code": "fr", "region": "Île-de-France", "provider": "nominatim"
}

Where it is stored

The table gb_entity_geo has one row per geo entity, keyed by entity_id (a foreign key to gb_entities; the row goes with the entity).

Nominatim

The built-in geocoder of gligabao. Nominatim is the geocoding engine behind the search box of openstreetmap.org.

Open source geocoding

Nominatim is free, open source software. You can use the public instance or run your own, so no API key or paid geocoding service is needed.

OpenStreetMap data

It searches the OpenStreetMap database, the open map of the world built by a community of contributors. Countries, regions, cities, streets and landmarks all come from it.

Finds places by name and address

It finds locations on Earth from a name ("Paris, France") or an address, and returns coordinates, a bounding box and the country and region the place lies in.

Geocoding

Geocoding turns text into coordinates. Gligabao asks Nominatim for each place the LLM detects, and stores the answer in gb_entity_geo with provider set to nominatim.

With geo = true gligabao uses the public Nominatim of OpenStreetMap: results are cached and requests are limited to one per second, as its usage policy asks. For heavier use, point geo.NewNominatim at your own instance.

Writing a resolver

Any type with these two methods works. geo.Cached(r) adds a cache, geo.NewNominatim(geo.NominatimOptions{BaseURL: ..., MinInterval: -1}) points at your own Nominatim instance, and geo.Func adapts a function. A resolver must be safe for concurrent use and return coordinates in range, or the answer is treated as a failure.

go
type Resolver interface {
	Name() string
	Resolve(ctx context.Context, q geo.Query) (*geo.Place, error) // geo.ErrNotFound if it knows no such place
}

Not used by query yet: geo is part of remember only for now. Questions like "near", "in" or distance are on the roadmap.

Turning it on

Off by default: it costs one more LLM call per text (an entity list is sent to the detect_geo stage) and it sends the names of places to a geocoder.

terminal
# in gligabao.toml
geo = true

# or on the command line
$ gligabao serve --geo