docs: position addrkit as a universal address service
- core = address normalization/resolution (universal, no EDDS coupling) - "events by house" (outages) framed as an optional plugin module - README: positioning, API table marks /v1/outages optional, selfcheck section, updated typo numbers and LLM variant-guard note
This commit is contained in:
@@ -1,13 +1,29 @@
|
|||||||
# addrkit
|
# addrkit
|
||||||
|
|
||||||
**Детерминированный сервис нормализации и поиска адресов** с подключаемым
|
**Универсальный детерминированный сервис нормализации и поиска адресов.**
|
||||||
внешним слоем отключений. Разбирает вольные реплики (дроби, литеры, корпуса,
|
Разбирает вольные реплики (дроби, литеры, корпуса, строения, опечатки),
|
||||||
строения, опечатки), сопоставляет их с каноническим реестром и отдаёт ответ
|
сопоставляет их с каноническим реестром и отдаёт ответ **только из данных** —
|
||||||
**только из данных** — LLM не участвует в пути корректности.
|
LLM не участвует в пути корректности.
|
||||||
|
|
||||||
|
Ядро продукта — **только адрес**: оно не привязано ни к ЕДДС, ни к отключениям.
|
||||||
|
Опциональный модуль «**события по дому**» (отключения, аварии, плановые работы —
|
||||||
|
данные, привязанные к конкретному дому) подключается отдельно; ЕДДС — лишь один
|
||||||
|
из его потребителей.
|
||||||
|
|
||||||
Проект на Go, живёт офлайн (один статический бинарь + SQLite), без MCP в
|
Проект на Go, живёт офлайн (один статический бинарь + SQLite), без MCP в
|
||||||
рантайме.
|
рантайме.
|
||||||
|
|
||||||
|
## Позиционирование
|
||||||
|
|
||||||
|
- **Ядро (универсальное):** нормализация, структурирование и поиск адреса по
|
||||||
|
реестру, статусы `found/partial/ambiguous/not_found`, версия данных.
|
||||||
|
Годится для колл-центра, доставки, CRM, аналитики, любого робота.
|
||||||
|
- **Опциональный модуль «события по дому»:** получает канонический адрес из
|
||||||
|
ядра и отдаёт события, **привязанные к этому дому** (совпадение дома, дроби,
|
||||||
|
литеры и корпуса; строение игнорируется). Источник — plug-in
|
||||||
|
(`outages.Source`): сегодня ArcGIS-портал ЕДДС, завтра любой фид (ES, SQL,
|
||||||
|
API). Ядро про события ничего не знает.
|
||||||
|
|
||||||
## Зачем
|
## Зачем
|
||||||
|
|
||||||
Существующая логика поиска адреса в диалоговом сценарии страдала от
|
Существующая логика поиска адреса в диалоговом сценарии страдала от
|
||||||
@@ -22,13 +38,13 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
cmd/addrkitd сервис (HTTP)
|
cmd/addrkitd сервис (HTTP)
|
||||||
cmd/addrkit CLI: seed | verify | resolve
|
cmd/addrkit CLI: seed | verify | resolve | eval | selfcheck
|
||||||
internal/
|
internal/
|
||||||
domain/address нормализация и разбор адреса (чистые функции)
|
domain/address нормализация и разбор адреса (чистые функции)
|
||||||
domain/match сопоставление с индексом, статусы
|
domain/match сопоставление с индексом, статусы ← ядро
|
||||||
domain/outages выборка отключений по дому (чистая логика)
|
domain/outages «события по дому»: фильтр по дому ← опциональный модуль
|
||||||
adapters/registrystore SQLite (modernc, без CGO)
|
adapters/registrystore SQLite (modernc, без CGO)
|
||||||
adapters/arcgis клиент портала (timeout/retry)
|
adapters/arcgis клиент источника событий (timeout/retry) ← пример plug-in
|
||||||
adapters/llm опциональный rewriter (OpenAI-совместимый)
|
adapters/llm опциональный rewriter (OpenAI-совместимый)
|
||||||
adapters/httpapi версионированный JSON API
|
adapters/httpapi версионированный JSON API
|
||||||
config конфиг + ${VAR}
|
config конфиг + ${VAR}
|
||||||
@@ -41,7 +57,7 @@ internal/
|
|||||||
"2-я Станционная улица 1/1 стр."
|
"2-я Станционная улица 1/1 стр."
|
||||||
-> address.Parse -> {ordinal:2, name:станционная, house:1, frac:1}
|
-> address.Parse -> {ordinal:2, name:станционная, house:1, frac:1}
|
||||||
-> match.Resolve -> exact street -> exact house -> FOUND
|
-> match.Resolve -> exact street -> exact house -> FOUND
|
||||||
-> (опц.) outages.Source -> фильтр по дому -> ответ
|
-> (опц. модуль «события по дому») -> фильтр по дому -> ответ
|
||||||
```
|
```
|
||||||
|
|
||||||
## Быстрый старт
|
## Быстрый старт
|
||||||
@@ -66,14 +82,15 @@ CLI без сервиса:
|
|||||||
```bash
|
```bash
|
||||||
./bin/addrkit resolve -db registry.db "кошурникова 11/1"
|
./bin/addrkit resolve -db registry.db "кошурникова 11/1"
|
||||||
./bin/addrkit verify -db registry.db
|
./bin/addrkit verify -db registry.db
|
||||||
|
./bin/addrkit selfcheck -db registry.db
|
||||||
```
|
```
|
||||||
|
|
||||||
## API v1
|
## API v1
|
||||||
|
|
||||||
| Метод | Путь | Назначение |
|
| Метод | Путь | Назначение |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| POST | `/v1/resolve` | адрес → `{status, address, district, confidence, candidates[]}` |
|
| POST | `/v1/resolve` | **[ядро]** адрес → `{status, address, district, confidence, candidates[]}` |
|
||||||
| POST | `/v1/outages` | адрес → канонический адрес + отключения по дому |
|
| POST | `/v1/outages` | **[опц. модуль]** адрес → канонический адрес + события/отключения по дому |
|
||||||
| GET | `/v1/healthz` | живость |
|
| GET | `/v1/healthz` | живость |
|
||||||
| GET | `/v1/readyz` | готовность (индекс загружен) |
|
| GET | `/v1/readyz` | готовность (индекс загружен) |
|
||||||
| GET | `/v1/version` | версия данных |
|
| GET | `/v1/version` | версия данных |
|
||||||
@@ -100,7 +117,12 @@ CLI без сервиса:
|
|||||||
`partial`, а не «похожий» дом.
|
`partial`, а не «похожий» дом.
|
||||||
- **LLM — опция, выключена по умолчанию.** `adapters/llm` лишь предлагает
|
- **LLM — опция, выключена по умолчанию.** `adapters/llm` лишь предлагает
|
||||||
варианты записи адреса; результат всегда берётся из реестра, поэтому модель
|
варианты записи адреса; результат всегда берётся из реестра, поэтому модель
|
||||||
не может «выдумать» адрес.
|
не может «выдумать» адрес. Вариант принимается только если он исправляет
|
||||||
|
*написание* улицы, не меняя слова, порядковый и дом (`compatibleVariant`).
|
||||||
|
- **Ядро универсально, события по дому — опциональный модуль.** Ядро
|
||||||
|
(`domain/address`, `domain/match`) не знает ни про ЕДДС, ни про отключения;
|
||||||
|
источник событий — plug-in (`outages.Source`), поэтому модуль переиспользуем
|
||||||
|
для любых данных, привязанных к дому.
|
||||||
- **Данные.** Сервис владеет своим индексом, построенным из дампа реестра.
|
- **Данные.** Сервис владеет своим индексом, построенным из дампа реестра.
|
||||||
Источник истины и регламент обновления — предмет отдельного согласования.
|
Источник истины и регламент обновления — предмет отдельного согласования.
|
||||||
- **Часовой пояс.** Даты отключений трактуются в `Asia/Novosibirsk` (UTC+7).
|
- **Часовой пояс.** Даты отключений трактуются в `Asia/Novosibirsk` (UTC+7).
|
||||||
@@ -145,7 +167,7 @@ ADDRKIT_REGISTRY=/path/to/address_registry.ndjson \
|
|||||||
| type_front | `улица Станционная 1` | 100 % |
|
| type_front | `улица Станционная 1` | 100 % |
|
||||||
| corpus_synonym | `корпус` вместо `к` | 100 % |
|
| corpus_synonym | `корпус` вместо `к` | 100 % |
|
||||||
| structure_drop | без `стр.` | 100 % |
|
| structure_drop | без `стр.` | 100 % |
|
||||||
| **typo** | опечатка в названии улицы | ~70–75 % (остальное — `ambiguous`) |
|
| **typo** | опечатка в названии улицы | ~78–82 % (остальное — `ambiguous`) |
|
||||||
| drop_ordinal / drop_letter / drop_fraction | потеря `2-я` / литеры / дроби | потери (lossy) |
|
| drop_ordinal / drop_letter / drop_fraction | потеря `2-я` / литеры / дроби | потери (lossy) |
|
||||||
|
|
||||||
Ключевой результат: **0 случаев, когда сервис подставил неверный дом**
|
Ключевой результат: **0 случаев, когда сервис подставил неверный дом**
|
||||||
@@ -153,6 +175,23 @@ ADDRKIT_REGISTRY=/path/to/address_registry.ndjson \
|
|||||||
распознаются, либо честно уходят в `ambiguous`/`not_found`, но не превращаются
|
распознаются, либо честно уходят в `ambiguous`/`not_found`, но не превращаются
|
||||||
в чужой адрес.
|
в чужой адрес.
|
||||||
|
|
||||||
|
С подключённым LLM-rewriter'ом (опция, `llm.enabled`) точность на опечатках
|
||||||
|
поднимается до **~90 %** при том же нуле неверных адресов (вариант модели
|
||||||
|
принимается только если исправляет лишь *написание* улицы — см. «Принятые
|
||||||
|
решения»).
|
||||||
|
|
||||||
|
## Самопроверка (`addrkit selfcheck`)
|
||||||
|
|
||||||
|
Прогоняет **весь** реестр на самого себя (не выборку):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/addrkit selfcheck -db registry.db
|
||||||
|
```
|
||||||
|
|
||||||
|
На реестре 72 825 записей: **72 811 (99.98 %) резолвятся точно**, 14 — `partial`
|
||||||
|
(битые форматы дома: `27с1`, `32 к 1/4-1/6`, `112с729`), 0 `not_found`,
|
||||||
|
0 неверных.
|
||||||
|
|
||||||
## Локальный dev
|
## Локальный dev
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user