Fra un documento appoggiato in un container e un indice interrogabile succedono parecchie cose, e le domande di questo dominio chiedono quasi sempre dove succede una certa cosa: nell’indexer, nello skillset, nella mappatura dei campi o fuori da Azure AI Search. La catena (sorgente, crawler, arricchimento, proiezione sull’indice) va tenuta a mente per intero: ogni anello ha parametri propri, un punto di rottura e un costo.

Push e pull: come entra il contenuto

Azure AI Search accetta contenuto in due modi. Con il push l’applicazione chiama l’API di indicizzazione e carica documenti già pronti: nessun vincolo sulla sorgente, controllo totale sull’istante in cui il dato entra, ma estrazione, chunking e vettorizzazione restano a carico tuo.

Con il pull lavora l’indexer, un crawler gestito che si collega a una data source supportata (Blob Storage, ADLS Gen2, SQL, Cosmos DB e altre), legge i documenti, mappa i campi omonimi e scrive nell’indice. Servono una data source, un indice di destinazione e, facoltativo, uno skillset; l’esecuzione è on demand oppure pianificata con la proprietà schedule e i suoi interval e startTime. L’indexer fa change detection e rielabora solo ciò che è cambiato: è la ragione principale per preferirlo al push.

Sotto stress contano due parametri: batchSize, la dimensione dei lotti, e la coppia maxFailedItems / maxFailedItemsPerBatch, che stabilisce se un documento malformato viene saltato o fa fallire l’esecuzione; a zero, un solo file corrotto ferma la pipeline. I field mapping, infine, agiscono prima dell’arricchimento e trasformano i campi della sorgente con sourceFieldName, targetFieldName e una mappingFunction: il caso ricorrente è base64Encode sulla chiave, perché il percorso di un blob contiene caratteri che una document key non ammette.

Skillset ed enrichment tree

Lo skillset è la parte di AI enrichment: una sequenza di skill eseguite durante l’indicizzazione per ricavare testo e struttura da contenuti che di per sé non sono ricercabili. Il modello mentale è l’enrichment tree: ogni documento entra come nodo /document e ogni skill vi appende rami. Ogni skill dichiara un context, cioè il nodo su cui gira — per esempio /document oppure /document/normalized_images/* per iterare su una collezione — più input espressi come path nell’albero e output che diventano nuovi nodi. L’ordine di esecuzione non lo scrivi tu: il servizio lo deriva dalle dipendenze fra input e output.

L’albero però non è l’indice. Per portare un nodo arricchito su un campo dell’indice serve un output field mapping, da non confondere con i field mapping visti sopra. Se lo skillset produce chunk, cioè più frammenti per documento, serve invece un’index projection: scrive ogni chunk come documento a sé in un indice figlio, con parentKeyFieldName a tenere il legame con il padre e l’opzione di non indicizzare il padre. Terza destinazione è il knowledge store, che persiste l’output in Azure Storage come tabelle e blob per l’analisi a valle.

Testo, immagini, layout: quale skill e quale si paga

Le skill built-in coprono i casi comuni: OCR, analisi immagini, riconoscimento entità, traduzione, split del testo, embedding. Le custom skill sono endpoint HTTP tuoi che il servizio chiama rispettando un contratto rigido (array values, un recordId per record, un oggetto data, liste errors e warnings) e che ricevono batch, non singoli documenti.

import azure.functions as func, json

def main(req: func.HttpRequest) -> func.HttpResponse:
    out = []
    for record in req.get_json()["values"]:      # arriva un batch
        out.append({
            "recordId": record["recordId"],      # va restituito tale e quale
            "data": {"codici": estrai_codici(record["data"]["text"])},
            "errors": [], "warnings": [],
        })
    return func.HttpResponse(json.dumps({"values": out}),
                             mimetype="application/json")

Sul testo la skill più usata nel RAG è il Text Split, con textSplitMode a pages o sentences, maximumPageLength e pageOverlapLength. Sulle immagini lavora l’OCR skill, con detectOrientation, defaultLanguageCode e lineEnding, che restituisce sia text sia layoutText con le coordinate; presupposto spesso ignorato: se le immagini sono incorporate in un PDF, l’indexer va configurato per estrarle e normalizzarle, altrimenti la skill riceve un input vuoto e non protesta. Il layout — paragrafi, tabelle multipagina, intestazioni di sezione, ordine di lettura — da un OCR puro non esce: serve un’analisi documentale vera, eseguita a monte oppure richiamata dallo skillset come passo dedicato.

Sul costo la regola è netta: le skill che invocano modelli di AI sono fatturabili e pretendono una risorsa fatturabile collegata allo skillset, nella stessa regione del servizio di ricerca, con chiave o identità gestita; la quota giornaliera gratuita di arricchimenti serve al collaudo, non alla produzione. Il Text Split invece non si paga, ed è il motivo per cui il chunking si fa lì. La skill di embedding si paga sul deployment del modello.

Quando l’indexer non basta

Documenti e immagini l’indexer li tratta; audio e video no. Per quelli il percorso passa da Azure Content Understanding in Foundry Tools, che ha modalità dedicate con trascrizione, diarizzazione e segmentazione automatica: si indicizza il risultato (trascritto, riassunto, campi estratti), non il file.

Per il collaudo c’è la debug session nel portale: esegue lo skillset su un singolo documento e mostra l’enrichment tree nodo per nodo, con input e output correggibili. In esercizio contano lo stato dell’indexer (In Progress, Success, Failed, Reset), l’execution history (solo le 50 esecuzioni più recenti) e le metriche di documenti processati e invocazioni delle skill.

Da ricordare per l’esame

  • L’indexer è la strada pull, con change detection e schedule; il push serve quando la sorgente non è supportata o quando vuoi decidere tu l’istante di ingresso del dato.
  • I field mapping agiscono prima dell’arricchimento, gli output field mapping dopo, e i chunk arrivano nell’indice figlio solo tramite index projection.
  • Le skill che chiamano modelli di AI sono fatturabili e richiedono una risorsa fatturabile collegata nella stessa regione; Text Split non si paga, ed è la skill di chunking.
  • Una custom skill deve rispettare il contratto values / recordId / data / errors / warnings e gestire batch: rispondere con un solo record a una richiesta multipla rompe l’associazione.
  • Audio e video non li indicizza l’indexer: si passa da Content Understanding e si indicizza il suo output.