Etend le pipeline de detection de techniques (tech-step-matcher.ts) pour resoudre, par clause, les metadonnees qui accompagnent une technique detectee : - Ingredients : nouvelle fonction findIngredientMentions (ingredient-matcher.ts) qui scanne le texte d'une clause contre le catalogue Ingredient existant (reutilise INGREDIENT_LABELS_FR/EN deja utilise par matchIngredientName), avec extraction best-effort de la quantite+unite immediatement avant la mention. - Ustensiles : nouveau catalogue Utensil (Prisma) + second PhraseMatcher cote service Python (intent_service/utensil_vocabulary.py), independant du textcat des techniques (pas d'interpretation necessaire pour un ustensile). POST /v1/process distingue desormais chaque entite via un champ kind (technique|utensil). - Persistance : deux nouvelles tables StepTechStepIngredient/ StepTechStepUtensil, liees a StepTechStep par sa cle composite (stepId, order), peuplees au moment du matching (recipe.service.ts) et exposees via StepTechStepView (packages/shared). Aucune analyse syntaxique ajoutee (le parser spaCy reste exclu du pipeline) : l'association se fait par appartenance a la clause deja calculee par splitIntoClauses. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
49 lines
1.7 KiB
Python
49 lines
1.7 KiB
Python
"""`POST /v1/process` — appelé par `apps/api` (`IntentServiceClient.process`)
|
|
en remplacement direct de l'ancien `NlpManager.process(locale, text)`. Voir
|
|
`LocalePipeline.process` pour la sémantique exacte (locale non entraînée ou
|
|
`text` vide -> résultat vide, jamais une erreur).
|
|
"""
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from ..pipeline_registry import registry
|
|
from ..schemas import EntityPayload, ProcessRequest, ProcessResponse
|
|
from ..security import require_valid_secret
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(dependencies=[Depends(require_valid_secret)])
|
|
|
|
|
|
@router.post("/v1/process", response_model=ProcessResponse)
|
|
def process(request: ProcessRequest) -> ProcessResponse:
|
|
result = registry.process(request.locale, request.text)
|
|
|
|
# Une ligne par appel — input (`locale`/`text`) et output (`entities`/
|
|
# `intent`/`score`) réunis dans la même ligne JSON, pour pouvoir suivre
|
|
# exactement ce que le pipeline a décidé pour un texte donné (voir
|
|
# `logging_config.py` pour le format).
|
|
logger.info(
|
|
"tech-step NLP process",
|
|
extra={
|
|
"locale": request.locale,
|
|
"text": request.text,
|
|
"entities": [
|
|
{"uid": entity.uid, "start": entity.start, "end": entity.end, "kind": entity.kind}
|
|
for entity in result.entities
|
|
],
|
|
"intent": result.intent,
|
|
"score": result.score,
|
|
},
|
|
)
|
|
|
|
return ProcessResponse(
|
|
entities=[
|
|
EntityPayload(uid=entity.uid, start=entity.start, end=entity.end, kind=entity.kind)
|
|
for entity in result.entities
|
|
],
|
|
intent=result.intent,
|
|
score=result.score,
|
|
)
|