services/api/src/modules/interpretation/real-estate-lexicon.js
Descripción general
Este módulo define el léxico inmobiliario inicial en es-MX. Toma formas lingüísticas como sinónimos, abreviaturas y errores ortográficos registrados, y las vincula con valores ya existentes del dominio. El archivo no crea dominios nuevos; solo reconoce texto y marca explícitamente lo que queda fuera de contrato o fuera de alcance.
[!IMPORTANT] Este módulo solo reconoce términos. No decide intenciones ni extrae parámetros. Esa capa de reglas pertenece a NLU-02, según el propio encabezado del archivo.
Cómo funciona
flowchart TD
Input[Texto original]
Norm[text normalization]
Forms[LEXICON_ENTRIES]
Index[FORM_INDEX]
Match[findLexiconMatches]
Output[Matches ordenados]
Forms --> Index
Input --> Norm
Norm --> Match
Index --> Match
Match --> Output
El flujo empieza con un texto original. Luego, el módulo normaliza el texto y cada forma del léxico. Después, construye un índice plano de formas normalizadas, ordenado de la más larga a la más corta. Por último, findLexiconMatches recorre ese índice, verifica límites de palabra, evita solapes y devuelve coincidencias con su fragmento original. fileciteturn0file18turn0file19
Componentes clave
listLexiconForms [badge:public]
{
"title": "listLexiconForms",
"content": "Devuelve una lista plana de formas del l\u00e9xico para auditor\u00eda y pruebas. Cada elemento incluye entryId, text, variant y normalized.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/real-estate-lexicon.js",
"badges": [
"public"
]
}
Esta función expone la superficie declarativa del léxico en formato plano. Sirve para inspección y verificación, sin modificar la estructura interna. El propio archivo la describe como una lista para auditoría y pruebas.
findLexiconMatches [badge:public]
{
"title": "findLexiconMatches",
"content": "Reconoce t\u00e9rminos del l\u00e9xico dentro de un texto y devuelve coincidencias ordenadas por posici\u00f3n. Emite facetas o lecturas ambiguas, seg\u00fan la entrada.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/real-estate-lexicon.js",
"badges": [
"public"
]
}
Esta función es el núcleo operativo del módulo. Usa coincidencia exacta sobre la forma normalizada, con límites de palabra y sin coincidencia difusa. También conserva la procedencia exacta del fragmento original mediante toOriginalSpan. fileciteturn0file18turn0file19
LEXICON_ENTRIES
Es el catálogo principal de entradas. El módulo lo congela con Object.freeze, y también congela cada entrada individual. Las entradas combinan id, forms y facets, o bien id, forms y readings cuando el término es ambiguo.
FORM_VARIANTS
Contiene las variantes declaradas para cada forma textual. El módulo acepta exactamente estas tres: synonym, abbreviation y misspelling. Las funciones internas convierten cualquier forma en string al variant synonym.
LEXICON_VERSION
Esta constante fija la versión declarativa del léxico en "1". Las pruebas de versionado la tratan como una superficie independiente del contrato y del registro de capacidades. fileciteturn0file0turn0file17
Datos y campos
[
{
"name": "LEXICON_VERSION",
"type": "string",
"required": true,
"description": "Versión declarativa del léxico. El archivo exporta \"1\"."
},
{
"name": "FORM_VARIANTS",
"type": "string[]",
"required": true,
"description": "Variantes permitidas para una forma: synonym, abbreviation y misspelling."
},
{
"name": "LEXICON_ENTRIES",
"type": "Array<LexiconEntry>",
"required": true,
"description": "Catálogo congelado de entradas del léxico."
},
{
"name": "LexiconEntry",
"type": "object",
"required": true,
"description": "Entrada declarativa que agrupa formas y facetas, o formas y lecturas ambiguas.",
"children": [
{
"name": "id",
"type": "string",
"required": true,
"description": "Identificador estable de la entrada."
},
{
"name": "forms",
"type": "Array<string | FormRecord>",
"required": true,
"description": "Formas reconocidas por el índice."
},
{
"name": "facets",
"type": "Array<Facet>",
"description": "Facetas aplicadas a todas las formas de la entrada."
},
{
"name": "readings",
"type": "Array<Array<Facet>>",
"description": "Lecturas alternativas para términos ambiguos."
}
]
},
{
"name": "FormRecord",
"type": "object",
"required": true,
"description": "Forma marcada como abreviatura o error ortográfico.",
"children": [
{
"name": "text",
"type": "string",
"required": true,
"description": "Texto literal de la forma."
},
{
"name": "variant",
"type": "string",
"required": true,
"description": "Una de synonym, abbreviation o misspelling."
}
]
},
{
"name": "Facet",
"type": "object",
"required": true,
"description": "Etiqueta semántica asociada a una coincidencia.",
"children": [
{
"name": "category",
"type": "string",
"required": true,
"description": "Categoría semántica."
},
{
"name": "value",
"type": "string | number | object | boolean",
"required": true,
"description": "Valor asociado a la categoría."
}
]
}
]
forms
Cada entrada acepta una lista de formas. Una forma puede ser un string simple o un objeto { text, variant }. El archivo usa los helpers ab y typo para marcar abreviaturas y faltas ortográficas registradas.
facets
Cuando una entrada no es ambigua, sus facets aplican a todas las formas. Esas facetas apuntan a valores del dominio ya existentes. El archivo las organiza por categoría semántica, no por reglas de interpretación.
readings
Cuando una forma es ambigua, la entrada usa readings. En ese caso, exactamente una lectura debe aplicar, y la capa superior debe pedir aclaración. El módulo no elige entre lecturas alternativas.
propertyTypehouseapartmentlandofficecommercialindustrialbuilding
operationTypesalerenttemporary_rentpresaleexchangeauctiontransfer
featurebedroomshalfBathroomsbathroomsparkingSpots
areaUnit{ unit: "m2", factor: 1 }{ unit: "m2", factor: 10000 }para hectáreas
areaQualifierconstructionArealandArea
amenitypoolgymevent_roomelevatorsecuritygreen_areasroof_gardenvisitor_parkingpet_friendly_common_area
pethasPetspetFriendlyRequired
currencyMXNUSDEUR
magnitudemultiplier: 1000multiplier: 1000000multiplier: 1000000, impliedCurrency: "MXN"
amountWord500000
numberWord- valores escritos desde
0hasta900
- valores escritos desde
budgetBoundmaxminrangeapprox
periodicitymonthweekday
roleseekofferambiguous
intentCue- valores como
discover.search,publish.start_offer,discover.refine,discover.save,discover.allow_recommendations,discover.show_matches,discover.recover,discover.select_existing,listing.inspect,publish.continue,attend.leads,attend.activity,nav.wall,system.help
- valores como
contextRef{ ref: "visibleResults", ordinal }{ ref: "activeSearch" }
negationtrue
locationCuetrue
unsupportedField- texto descriptivo de la limitación
outOfScope- texto descriptivo de la solicitud fuera de alcance
bodegapropertyType: warehouseamenity: storage
cerca debudgetBound: approxlocationCue: true
$currency: MXNcurrency: USD
mascotapet: hasPetspet: petFriendlyRequired
el cuartocontextRef: visibleResults ordinal 4feature: bedrooms
jardinamenity: green_areasunsupportedField: Jardin privado
unsupportedFieldamuebladoplanta bajavista al marcuarto de servicioa estrenarcerca del metro
outOfScopecompararagendar una visitacuanto valenegociarcreditocontrato de arrendamiento
Comportamientos
ab(text)— Construye una forma convariant: "abbreviation".typo(text)— Construye una forma convariant: "misspelling".toFormRecord(form)— Normaliza una forma textual simple a{ text, variant: "synonym" }.listLexiconForms()— Devuelve una vista plana del índice para auditoría y pruebas.findLexiconMatches(text)— Devuelve coincidencias ordenadas por posición, confacetsoreadingssegún corresponda. fileciteturn0file0turn0file18
Reglas internas de coincidencia
El módulo construye FORM_INDEX a partir de todas las entradas. Luego, ordena las formas normalizadas de la más larga a la más corta. Así, una forma más específica gana frente a una más corta. El propio comentario del archivo lo ejemplifica con estacionamiento de visitas frente a estacionamiento.
Procedencia textual
Cada coincidencia conserva el span sobre el texto original y el matched exacto. El módulo usa toOriginalSpan para regresar desde el texto normalizado al texto escrito por la persona. Esa trazabilidad es parte del contrato del sistema. fileciteturn0file18turn0file19
Flujo
1. Cargar entradas | `LEXICON_ENTRIES` agrupa todos los términos reconocidos.
2. Expandir formas | Cada forma se convierte en un registro normalizado en `FORM_INDEX`.
3. Normalizar texto | `normalizeForMatching` prepara el texto para búsqueda.
4. Buscar coincidencias | `findLexiconMatches` recorre las formas de mayor a menor longitud.
5. Verificar límites | `hasBoundaries` evita coincidencias dentro de otras palabras.
6. Reservar fragmentos | El índice `occupied` impide solapes entre coincidencias.
7. Restaurar span original | `toOriginalSpan` devuelve el fragmento exacto del texto de entrada.
8. Emitir resultado | El módulo devuelve coincidencias ordenadas por posición.
Casos límite y comportamiento sensible
[!WARNING]
findLexiconMatchesno hace coincidencia difusa. Solo reconoce errores ortográficos que ya están registrados en el catálogo.
[!WARNING] Las coincidencias no se solapan. Si una forma larga ocupa un tramo, las formas más cortas de ese tramo se descartan. El índice
occupiedimpone esa regla.
[!IMPORTANT] Una entrada con
readingsno producefacets. Produce una coincidencia ambigua, y la capa superior debe resolverla.
[!NOTE] El módulo evita términos demasiado generales para la ubicación. Por ejemplo,
enyporno forman parte del léxico. La extracción de ubicación se reserva para una etapa estructural posterior.
[!CAUTION] Las solicitudes marcadas como
unsupportedFieldooutOfScopeno se fuerzan a un campo existente. El archivo las conserva como limitaciones explícitas.
Relacionado
Este archivo se integra con services/api/src/modules/interpretation/text-normalization.js, que normaliza acentos, mayúsculas, espacios y símbolos como ², y mantiene el mapa de posiciones al texto original. También se relaciona con services/api/src/modules/interpretation/deterministic-interpreter.js, que importa LEXICON_VERSION y findLexiconMatches para construir la interpretación determinista. fileciteturn0file19turn0file14
Las pruebas del módulo confirman que el léxico carga sin variables de entorno, que detecta formas como Busco depto en renta, y que su versión participa en la política de versionado independiente de contrato y registro de capacidades. fileciteturn0file7turn0file8turn0file17