From 66f4cef90da3fe56019d6e4fabf53bb4d06e3a7d Mon Sep 17 00:00:00 2001 From: addrkit Date: Fri, 9 Oct 2026 20:57:20 +0700 Subject: [PATCH] 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 --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 974ef1b..1e6341a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,29 @@ # addrkit -**Детерминированный сервис нормализации и поиска адресов** с подключаемым -внешним слоем отключений. Разбирает вольные реплики (дроби, литеры, корпуса, -строения, опечатки), сопоставляет их с каноническим реестром и отдаёт ответ -**только из данных** — LLM не участвует в пути корректности. +**Универсальный детерминированный сервис нормализации и поиска адресов.** +Разбирает вольные реплики (дроби, литеры, корпуса, строения, опечатки), +сопоставляет их с каноническим реестром и отдаёт ответ **только из данных** — +LLM не участвует в пути корректности. + +Ядро продукта — **только адрес**: оно не привязано ни к ЕДДС, ни к отключениям. +Опциональный модуль «**события по дому**» (отключения, аварии, плановые работы — +данные, привязанные к конкретному дому) подключается отдельно; ЕДДС — лишь один +из его потребителей. Проект на 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/addrkit CLI: seed | verify | resolve +cmd/addrkit CLI: seed | verify | resolve | eval | selfcheck internal/ domain/address нормализация и разбор адреса (чистые функции) - domain/match сопоставление с индексом, статусы - domain/outages выборка отключений по дому (чистая логика) + domain/match сопоставление с индексом, статусы ← ядро + domain/outages «события по дому»: фильтр по дому ← опциональный модуль adapters/registrystore SQLite (modernc, без CGO) - adapters/arcgis клиент портала (timeout/retry) + adapters/arcgis клиент источника событий (timeout/retry) ← пример plug-in adapters/llm опциональный rewriter (OpenAI-совместимый) adapters/httpapi версионированный JSON API config конфиг + ${VAR} @@ -41,7 +57,7 @@ internal/ "2-я Станционная улица 1/1 стр." -> address.Parse -> {ordinal:2, name:станционная, house:1, frac:1} -> match.Resolve -> exact street -> exact house -> FOUND - -> (опц.) outages.Source -> фильтр по дому -> ответ + -> (опц. модуль «события по дому») -> фильтр по дому -> ответ ``` ## Быстрый старт @@ -64,16 +80,17 @@ curl -s localhost:6171/v1/outages -d '{"address":"станционная 30а к CLI без сервиса: ```bash -./bin/addrkit resolve -db registry.db "кошурникова 11/1" -./bin/addrkit verify -db registry.db +./bin/addrkit resolve -db registry.db "кошурникова 11/1" +./bin/addrkit verify -db registry.db +./bin/addrkit selfcheck -db registry.db ``` ## API v1 | Метод | Путь | Назначение | |---|---|---| -| POST | `/v1/resolve` | адрес → `{status, address, district, confidence, candidates[]}` | -| POST | `/v1/outages` | адрес → канонический адрес + отключения по дому | +| POST | `/v1/resolve` | **[ядро]** адрес → `{status, address, district, confidence, candidates[]}` | +| POST | `/v1/outages` | **[опц. модуль]** адрес → канонический адрес + события/отключения по дому | | GET | `/v1/healthz` | живость | | GET | `/v1/readyz` | готовность (индекс загружен) | | GET | `/v1/version` | версия данных | @@ -100,7 +117,12 @@ CLI без сервиса: `partial`, а не «похожий» дом. - **LLM — опция, выключена по умолчанию.** `adapters/llm` лишь предлагает варианты записи адреса; результат всегда берётся из реестра, поэтому модель - не может «выдумать» адрес. + не может «выдумать» адрес. Вариант принимается только если он исправляет + *написание* улицы, не меняя слова, порядковый и дом (`compatibleVariant`). +- **Ядро универсально, события по дому — опциональный модуль.** Ядро + (`domain/address`, `domain/match`) не знает ни про ЕДДС, ни про отключения; + источник событий — plug-in (`outages.Source`), поэтому модуль переиспользуем + для любых данных, привязанных к дому. - **Данные.** Сервис владеет своим индексом, построенным из дампа реестра. Источник истины и регламент обновления — предмет отдельного согласования. - **Часовой пояс.** Даты отключений трактуются в `Asia/Novosibirsk` (UTC+7). @@ -145,7 +167,7 @@ ADDRKIT_REGISTRY=/path/to/address_registry.ndjson \ | type_front | `улица Станционная 1` | 100 % | | corpus_synonym | `корпус` вместо `к` | 100 % | | structure_drop | без `стр.` | 100 % | -| **typo** | опечатка в названии улицы | ~70–75 % (остальное — `ambiguous`) | +| **typo** | опечатка в названии улицы | ~78–82 % (остальное — `ambiguous`) | | drop_ordinal / drop_letter / drop_fraction | потеря `2-я` / литеры / дроби | потери (lossy) | Ключевой результат: **0 случаев, когда сервис подставил неверный дом** @@ -153,6 +175,23 @@ ADDRKIT_REGISTRY=/path/to/address_registry.ndjson \ распознаются, либо честно уходят в `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 ```bash