IBM Cloud Docs
Implementazione delle risposte del dialogo in un'applicazione client

Implementazione delle risposte del dialogo in un'applicazione client

Un nodo di dialogo può rispondere agli utenti con una risposta che include testo, immagini o elementi interattivi come le opzioni su cui è possibile fare clic. Se si costruisce una propria applicazione client, è necessario implementare la corretta visualizzazione di tutti i tipi di risposta restituiti dalla finestra di dialogo. Per ulteriori informazioni sulle risposte alle finestre di dialogo, vedere Risposte.

Formato di output della risposta

Per impostazione predefinita, le risposte da un nodo di dialogo vengono specificate nell'oggetto output.generic nel JSON di risposta restituito dall'API /message. L'oggetto generic contiene un array di massimo 5 elementi di risposta destinati a qualsiasi canale. Il seguente esempio di JSON mostra una risposta che include del testo e un'immagine:

{
  "output": {
    "generic": [
      {
        "response_type": "text",
        "text": "OK, here's a picture of a dog."
      },
      {
        "response_type": "image",
        "source": "http://example.com/dog.jpg"
      }
    ],
    "text" : ["OK, here's a picture of a dog."]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

Come mostra questo esempio, anche la risposta di testo (OK, here's a picture of a dog.) viene restituita nell'array output.text. L'array è incluso per la compatibilità con le precedenti applicazioni che non supportano il formato output.generic.

È responsabilità dell'applicazione client gestire tutti i tipi di risposta. In questo caso, la tua applicazione deve visualizzare il testo specificato e l'immagine all'utente.

Tipi di risposta

Ogni elemento di una risposta è uno dei tipi di risposta supportati. Ogni tipo di risposta è specificato utilizzando un diverso insieme di proprietà JSON, pertanto le proprietà incluse per ogni risposta variano a seconda del tipo di risposta. Per informazioni complete sul modello di risposta dell'API /message, consultare il Riferimento API.

Questa sezione descrive i tipi di risposta disponibili e il modo in cui sono rappresentati nel JSON di risposta dell'API /message. Se si utilizza l'SDK di Watson, è possibile utilizzare le interfacce fornite per la propria lingua per accedere agli stessi oggetti.

Gli esempi in questa sezione mostrano il formato dei dati JSON restituiti da /message API al runtime ed è differente dal formato JSON utilizzato per definire le risposte all'interno di un nodo di dialogo. Puoi utilizzare il formato negli esempi per aggiornare output.generic con webhooks. Per aggiornare output.generic con l'editor JSON, vedi Definizione delle risposte utilizzando l'editor JSON).

Testo

Il tipo di risposta text (testo) viene utilizzato per le risposte di testo ordinarie provenienti dal dialogo:

{
  "output": {
    "generic":[
      {
        "response_type": "text",
        "text": "OK, you want to fly to Boston next Monday."
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

Per motivi di compatibilità, lo stesso testo è incluso anche nell'array output.text nella risposta del dialogo.

Immagine

Il tipo di risposta image (immagine) indica all'applicazione client di visualizzare un'immagine, accompagnata, facoltativamente, da un titolo e da una descrizione:

{
  "output": {
    "generic":[
      {
        "response_type": "image",
        "source": "http://example.com/image.jpg",
        "title": "Image example",
        "description": "This is an example image"
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

L'applicazione è responsabile del recupero dell'immagine specificata dalla proprietà source e della sua visualizzazione da parte dell'utente. Se vengono forniti un title e una description facoltativi, la tua applicazione può visualizzarli in qualsiasi modo sia appropriato (ad esempio, eseguendo il rendering del titolo dopo l'immagine e della descrizione come testo a comparsa).

Video

Il tipo di risposta video indica all'applicazione client di visualizzare un video, facoltativamente accompagnato da title, description e alt_text per l'accesso facilitato:

{
  "output": {
    "generic":[
      {
        "response_type": "video",
        "source": "http://example.com/video.mp4",
        "title": "Video example",
        "description": "This is an example video",
        "alt_text": "A video showing a great example",
        "channel_options": {
          "chat": {
            "dimensions": {
              "base_height": 180
            }
          }
        }
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

L'applicazione è responsabile del recupero del video specificato dalla proprietà source e della sua visualizzazione all'utente. Se vengono forniti title e description facoltativi, l'applicazione può visualizzarli in qualsiasi modo sia appropriato.

La proprietà facoltativa channel_options.chat.dimensions.base_height utilizza un numero che indica che il rendering del video viene eseguito a una larghezza di 360 pixel. La tua applicazione utilizza questo valore per mantenere il corretto rapporto di aspetto del video se viene eseguito il rendering in una dimensione non standard.

Audio

Il tipo di risposta audio indica all'applicazione client di riprodurre un file audio:

{
  "output": {
    "generic":[
      {
        "response_type": "audio",
        "source": "http://example.com/audio.mp3",
        "channel_options": {
          "voice_telephony": {
            "loop": true
          }
        }
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

L'applicazione è responsabile della riproduzione del file audio.

La proprietà facoltativa channel_options.voice_telephony.loop utilizza un valore booleano che indica se il file audio viene riprodotto come un loop continuo. Questa opzione viene generalmente utilizzata per la musica di attesa che potrebbe richiedere di continuare per un periodo di tempo indefinito.

iframe

Il tipo di risposta iframe indica all'applicazione client di visualizzare il contenuto in un elemento iframe integrato, facoltativamente accompagnato da un titolo:

{
  "output": {
    "generic":[
      {
        "response_type": "iframe",
        "source": "http://example.com/iframe.html",
        "title": "My IFrame"
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

L'applicazione è responsabile della visualizzazione del contenuto di iframe. Il contenuto in un iframe incorporato è utile per la visualizzazione di contenuto di terze parti o per il contenuto del proprio sito che non si desidera rescrivere utilizzando il tipo di risposta user_defined.

Pausa

Il tipo di risposta pause indica all'applicazione di attendere un intervallo di tempo specificato prima della risposta successiva:

{
  "output": {
    "generic":[
      {
        "response_type": "pause",
        "time": 500,
        "typing": false
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

Questa pausa potrebbe essere richiesta dalla finestra di dialogo per consentire il completamento di una richiesta o per imitare l'aspetto di un agente umano che potrebbe fare una pausa tra una risposta e l'altra. La durata massima della pausa può essere di 10 secondi.

Di norma, una risposta pause viene inviata insieme ad altre risposte. L'applicazione si ferma per l'intervallo specificato dalla proprietà time (in millisecondi) prima della risposta successiva nell'array. La proprietà opzionale typing richiede che l'applicazione client mostri un indicatore user is typing, se supportato, per simulare un agente in carne e ossa.

Opzione

Il tipo di risposta option (option) indica all'applicazione client di visualizzare un controllo dell'interfaccia utente che consenta all'utente di selezionare da un elenco di opzioni e quindi reinviare l'input all'assistente in base all'opzione selezionata:

{
  "output": {
    "generic":[
      {
        "response_type": "option",
        "title": "Available options",
        "description": "Please select one of the following options:",
        "preference": "button",
        "options": [
          {
            "label": "Option 1",
            "value": {
              "input": {
                "text": "option 1"
              }
            }
          },
          {
            "label": "Option 2",
            "value": {
              "input": {
                "text": "option 2"
              }
            }
          }
        ]
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

La tua applicazione può visualizzare le opzioni specificate utilizzando qualsiasi controllo utente adatto (ad esempio, una serie di pulsanti o un elenco a discesa). La proprietà opzionale preference indica il tipo di controllo preferito dall'applicazione ( button o dropdown ), se supportato. Per la miglior esperienza dell'utente, ti consigliamo di presentare massimo tre opzioni come pulsanti e più di tre opzioni come un elenco a discesa.

Per ogni opzione, la proprietà label specifica il testo dell'etichetta che appare per l'opzione nel controllo UI. La proprietà value specifica l'input che viene inviato all'assistente (utilizzando l'API /message ) quando l'utente seleziona l'opzione corrispondente.

Per un esempio di implementazione delle risposte option in un'applicazione client semplice, vedi Esempio: implementazione delle risposte option.

Suggerimento

Plus

Il tipo di risposta suggestion viene utilizzato dalla funzione di disambiguazione per suggerire possibili corrispondenze e chiarire ciò che l'utente vuole fare. Una risposta suggestion include un array di suggerimenti (suggestions), ciascuno dei quali corrisponde a un possibile nodo di dialogo corrispondente:

{
  "output": {
    "generic": [
      {
        "response_type": "suggestion",
        "title": "Did you mean:",
        "suggestions": [
          {
            "label": "I'd like to order a drink.",
            "value": {
              "intents": [
                {
                  "intent": "order_drink",
                  "confidence": 0.7330395221710206
                }
              ],
              "entities": [],
              "input": {
                "suggestion_id": "576aba3c-85b9-411a-8032-28af2ba95b13",
                "text": "I want to place an order"
              }
            },
            "output": {
              "text": [
                "I'll get you a drink."
              ],
              "generic": [
                {
                  "response_type": "text",
                  "text": "I'll get you a drink."
                }
              ],
              "nodes_visited_details": [
                {
                  "dialog_node": "node_1_1547675028546",
                  "title": "order drink",
                  "user_label": "I'd like to order a drink.",
                  "conditions": "#order_drink"
                }
              ]
            },
            "source_dialog_node": "root"
          },
          {
            "label": "I need a drink refill.",
            "value": {
              "intents": [
                {
                  "intent": "refill_drink",
                  "confidence": 0.2529746770858765
                }
              ],
              "entities": [],
              "input": {
                "suggestion_id": "6583b547-53ff-4e7b-97c6-4d062270abcd",
                "text": "I need a drink refill"
              }
            },
            "output": {
              "text": [
                "I'll get you a refill."
              ],
              "generic": [
                {
                  "response_type": "text",
                  "text": "I'll get you a refill."
                }
              ],
              "nodes_visited_details": [
                {
                  "dialog_node": "node_2_1547675097178",
                  "title": "refill drink",
                  "user_label": "I need a drink refill.",
                  "conditions": "#refill_drink"
                }
              ]
            },
            "source_dialog_node": "root"
          }
        ]
      }
    ],
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

La struttura di una risposta suggestion è simile a quella di una risposta option. Come per le opzioni, ogni suggerimento comprende un label che può essere visualizzato dall'utente e un value che specifica l'input che viene inviato all'assistente se l'utente sceglie il suggerimento corrispondente. Per implementare le risposte suggestion nella tua applicazione, puoi utilizzare lo stesso approccio che utilizzeresti per le risposte option.

Per ulteriori informazioni sulla funzione di disambiguazione, vedi Disambiguazione.

Definita dall'utente

Un tipo di risposta definita dall'utente può contenere fino a 5000 KB di dati per supportare un tipo di risposta implementata nel client. Ad esempio, è possibile definire un tipo di risposta definito dall'utente per visualizzare una speciale scheda codificata a colori o per formattare i dati in una tabella o in un grafico.

La proprietà user_defined della risposta è un oggetto che può contenere qualsiasi dato JSON valido:

{
  "output": {
    "generic":[
      {
        "response_type": "user_defined",
        "user_defined": {
          "field_1": "String value",
          "array_1": [
            1,
            2
          ],
          "object_1": {
            "property_1": "Another string value"
          }
        }
      }
    ]
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

La tua applicazione può analizzare e visualizzare i dati in qualsiasi modo tu scelga.

Esempio: implementazione delle risposte option

Per mostrare come un'applicazione client potrebbe gestire le risposte alle opzioni, che richiedono all'utente di selezionare da un elenco di scelte, possiamo estendere l'esempio di client utilizzato in Costruire un'applicazione client. L'esempio è un'applicazione client semplificata che utilizza input e output standard per gestire tre intenti (inviare un saluto, mostrare l'ora corrente e uscire dall'applicazione):

Welcome to the example!
>> hello
Good day to you.
>> what time is it?
The current time is 12:40:42 PM.
>> goodbye
OK! See you later.

Se vuoi provare il codice di esempio, configura lo spazio di lavoro richiesto e ottieni i dettagli API di cui hai bisogno. Per ulteriori informazioni, vedi Creazione di un'applicazione client.

Ricezione di una risposta option

La risposta option può essere utilizzata quando vuoi presentare all'utente un elenco finito di scelte piuttosto che interpretare l'input del linguaggio naturale. La risposta può essere utilizzata in qualsiasi situazione in cui si voglia consentire all'utente di scegliere rapidamente tra un insieme di opzioni non ambigue.

Nella nostra applicazione client semplificata, utilizziamo questa funzionalità per selezionare da un elenco le azioni supportate dall'assistente (saluti, visualizzazione dell'ora e uscita). Oltre ai tre intenti mostrati in precedenza (#hello, #time e #goodbye), lo spazio di lavoro di esempio supporta un quarto intento: #menu, che viene soddisfatto quando l'utente chiede di vedere un elenco delle azioni disponibili.

Quando lo spazio di lavoro riconosce l'intento #menu, il dialogo risponde con una risposta option:

{
  "output": {
    "generic": [
      {
        "title": "What do you want to do?",
        "options": [
          {
            "label": "Send greeting",
            "value": {
              "input": {
                "text": "hello"
              }
            }
          },
          {
            "label": "Display the local time",
            "value": {
              "input": {
                "text": "time"
              }
            }
          },
          {
            "label": "Exit",
            "value": {
              "input": {
                "text": "goodbye"
              }
            }
          }
        ],
        "response_type": "option"
      }
    ],
    "intents": [
      {
        "intent": "menu",
        "confidence": 0.6178638458251953
      }
    ],
    "entities": []
  },
  "user_id": "faf4a112-f09f-4a95-a0be-43c496e6ac9a"
}

La risposta option contiene più opzioni da presentare all'utente. Ciascuna opzione include due oggetti, label e value. label è una stringa rivolta all'utente che identifica l'opzione; value specifica il messaggio di input corrispondente che viene inviato all'assistente se l'utente sceglie l'opzione.

La nostra applicazione client deve utilizzare i dati contenuti in questa risposta per costruire l'output che mostriamo all'utente e per inviare il messaggio appropriato all'assistente.

Elenco delle opzioni disponibili

Il primo passo nella gestione di una risposta option consiste nel mostrare le opzioni all'utente utilizzando il testo specificato dalla proprietà label di ciascuna opzione. Puoi visualizzare le opzioni utilizzando qualsiasi tecnica supportata dalla tua applicazione, di norma un elenco a discesa o una serie di pulsanti su cui è possibile fare clic. La proprietà opzionale preference di una risposta all'opzione, se specificata, indica quale tipo di visualizzazione utilizza l'applicazione, se possibile.

Il nostro esempio semplificato utilizza l'input e l'output standard, quindi non abbiamo accesso a una IU reale. Invece, presentiamo le opzioni come un elenco numerato.

// Option example 1: lists options.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Set up Assistant service wrapper.
const service = new AssistantV2({
  version: '2019-02-28',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  })
});

const assistantId = '{assistant_id}'; // replace with assistant ID
let sessionId;

// Create session.
service
  .createSession({
    assistantId,
  })
  .then(res => {
    sessionId = res.result.session_id;
    sendMessage({
      messageType: 'text',
      text: '',  // start conversation with empty message
    });
  })
  .catch(err => {
    console.log(err); // something went wrong
  });

// Send message to assistant.
function sendMessage(messageInput) {
  service
    .message({
      assistantId,
      sessionId,
      input: messageInput,
    })
    .then(res => {
      processResponse(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the response.
function processResponse(response) {

  let endConversation = false;

  // Check for client actions requested by the assistant.
  if (response.output.actions) {
    if (response.output.actions[0].type === 'client'){
      if (response.output.actions[0].name === 'display_time') {
        // User asked what time it is, so we output the local system time.
        console.log('The current time is ' + new Date().toLocaleTimeString() + '.');
      } else if (response.output.actions[0].name === 'end_conversation') {
        // User said goodbye, so we're done.
        console.log(response.output.generic[0].text);
        endConversation = true;
      }
    }
  } else {
    // Display the output from assistant, if any. Supports only a single
    // response.
    if (response.output.generic) {
      if (response.output.generic.length > 0) {
        switch (response.output.generic[0].response_type) {
          case 'text':
            // It's a text response, so we just display it.
            console.log(response.output.generic[0].text);
            break;
          case 'option':
            // It's an option response, so we'll need to show the user
            // a list of choices.
            console.log(response.output.generic[0].title);
            const options = response.output.generic[0].options;
            // List the options by label.
            for (let i = 0; i < options.length; i++) {
              console.log((i+1).toString() + '. ' + options[i].label);
            }
            break;
        }
      }
    }
  }

  // If we're not done, prompt for the next round of input.
  if (!endConversation) {
    const newMessageFromUser = prompt('>> ');
    newMessageInput = {
      messageType: 'text',
      text: newMessageFromUser,
    }
    sendMessage(newMessageInput);
  } else {
    // We're done, so we delete the session.
    service
      .deleteSession({
        assistantId,
        sessionId,
      })
      .then(res => {
        return;
      })
      .catch(err => {
        console.log(err); // something went wrong
      });
  }
}

Guardiamo più attentamente il codice che genera l'output della risposta dall'assistente. Ora, invece di presupporre una risposta text, l'applicazione supporta sia il tipo di risposta text che option:

    // Display the output from assistant, if any. Supports only a single
    // response.
    if (response.output.generic) {
      if (response.output.generic.length > 0) {
        switch (response.output.generic[0].response_type) {
          case 'text':
            // It's a text response, so we just display it.
            console.log(response.output.generic[0].text);
            break;
          case 'option':
            // It's an option response, so we'll need to show the user
            // a list of choices.
            console.log(response.output.generic[0].title);
            const options = response.output.generic[0].options;
            // List the options by label.
            for (let i = 0; i < options.length; i++) {
              console.log((i+1).toString() + '. ' + options[i].label);
            }
            break;
        }
      }
    }

Se response_type = text, si visualizza l'output, come prima. Ma se response_type = option, dobbiamo fare un po' di lavoro in più. Per prima cosa, si visualizza il valore della proprietà title, che serve come testo introduttivo per introdurre l'elenco delle opzioni; quindi, si elencano le opzioni, utilizzando il valore della proprietà label per identificare ciascuna di esse. (Un'applicazione reale mostra queste etichette in un elenco a discesa o come etichette su pulsanti su cui è possibile fare clic.)

Puoi vedere il risultato attivando l'intento #menu:

Welcome to the example!
>> what are the available actions?
What do you want to do?
1. Send greeting
2. Display the local time
3. Exit
>> 2
Sorry, I have no idea what you're talking about.
>>

Come puoi vedere, ora l'applicazione sta gestendo correttamente la risposta option elencando le scelte disponibili. Tuttavia, non stiamo ancora traducendo la scelta dell'utente in un input significativo.

Selezione di un'opzione

Oltre all'oggetto label, ogni opzione della risposta include anche un oggetto value, che contiene i dati di input che vengono inviati all'assistente se l'utente sceglie l'opzione corrispondente. L'oggetto value.input è equivalente alla proprietà input dell'API /message, il che significa che possiamo inviare questo oggetto all'assistente così com'è.

Impostiamo un nuovo indicatore promptOption quando il client riceve una risposta option. Quando il valore di questo indicatore è true, sappiamo che vogliamo prendere il prossimo ciclo di input da value.input piuttosto che accettare l'input di testo in lingua naturale proveniente dall'utente. Anche in questo caso, non disponendo di una vera e propria interfaccia utente, chiediamo all'utente di selezionare un'opzione valida dall'elenco numerico.

// Option example 2: sends back selected option value.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Set up Assistant service wrapper.
const service = new AssistantV2({
  version: '2019-02-28',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  })
});

const assistantId = '{assistant_id}'; // replace with assistant ID
let sessionId;

// Create session.
service
  .createSession({
    assistantId,
  })
  .then(res => {
    sessionId = res.result.session_id;
    sendMessage({
      messageType: 'text',
      text: '',  // start conversation with empty message
    });
  })
  .catch(err => {
    console.log(err); // something went wrong
  });

// Send message to assistant.
function sendMessage(messageInput) {
  service
    .message({
      assistantId,
      sessionId,
      input: messageInput,
    })
    .then(res => {
      processResponse(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the response.
function processResponse(response) {

  let endConversation = false;
  let promptOption = false;

  // Check for client actions requested by the assistant.
  if (response.output.actions) {
    if (response.output.actions[0].type === 'client'){
      if (response.output.actions[0].name === 'display_time') {
        // User asked what time it is, so we output the local system time.
        console.log('The current time is ' + new Date().toLocaleTimeString() + '.');
      } else if (response.output.actions[0].name === 'end_conversation') {
        // User said goodbye, so we're done.
        console.log(response.output.generic[0].text);
        endConversation = true;
      }
    }
  } else {
    // Display the output from assistant, if any. Supports only a single
    // response.
    if (response.output.generic) {
      if (response.output.generic.length > 0) {
        switch (response.output.generic[0].response_type) {
          case 'text':
            // It's a text response, so we just display it.
            console.log(response.output.generic[0].text);
            break;
          case 'option':
              // It's an option response, so we'll need to show the user
              // a list of choices.
              console.log(response.output.generic[0].title);
              const options = response.output.generic[0].options;
              // List the options by label.
              for (let i = 0; i < options.length; i++) {
                console.log((i+1).toString() + '. ' + options[i].label);
              }
            promptOption = true;
            break;
        }
      }
    }
  }

  // If we're not done, prompt for the next round of input.
  if (!endConversation) {
    let messageInput;
    if (promptOption == true) {
      // Prompt for a valid selection from the list of options.
      let choice;
      do {
        choice = prompt('? ');
          if (isNaN(choice)) {
            choice = 0;
          }
      } while (choice < 1 || choice > response.output.generic[0].options.length);
      const value = response.output.generic[0].options[choice-1].value;
      // Use message input from the selected option.
      messageInput = value.input;
    } else {
      // We're not showing options, so we just prompt for the next
      // round of input.
      const newText = prompt('>> ');
      messageInput = {
        text: newText,
      }
    }
    sendMessage(messageInput);
  } else {
    // We're done, so we delete the session.
    service
      .deleteSession({
        assistantId,
        sessionId,
      })
      .then(res => {
        return;
      })
      .catch(err => {
        console.log(err); // something went wrong
      });
  }
}

Tutto ciò che si deve fare è usare l'oggetto value.input dalla risposta selezionata come prossimo input di messaggio, invece di costruire un nuovo oggetto input usando l'input di testo. L'assistente risponde esattamente come se l'utente avesse digitato direttamente il testo in ingresso.

Welcome to the example!
>> hi
Good day to you.
>> what are the choices?
What do you want to do?
1. Send greeting
2. Display the local time
3. Exit
? 2
The current time is 1:29:14 PM.
>> bye
OK! See you later.

Ora possiamo accedere a tutte le funzioni dell'assistente effettuando richieste in lingua naturale oppure effettuando una selezione da un menu di opzioni.

Lo stesso approccio viene utilizzato anche per le risposte di suggestion. Se il tuo piano supporta la funzione di disambiguazione, puoi utilizzare una logica simile per richiedere agli utenti di effettuare la selezione da un elenco quando non è chiaro quale delle diverse opzioni possibili sia corretta. Per ulteriori informazioni sulla funzione di disambiguazione, vedi Disambiguazione.