Twin Creator Partner

Formazione Client

Nicola Zambello

Lead Frontend Developer

nzambello

Core team

Programma di oggi

  1. Integrazione web con embed
    1. Creazione widget e personalizzazione
    2. Embed
    3. Personalizzazioni dinamiche
    4. Parametri aggiuntivi al widget
  2. Panoramica conversazione ed API
  3. Estendiamo la conversazione
    1. Default e messaggio di benvenuto
    2. Suggerimenti e timeout
    3. Contesti
    4. Snippet eseguibili
    5. Intenti
  4. Realizzare un client
  5. SDK e librerie di integrazione
  6. VR e Metaversi

1

Integrazione web

1. Integrazione web

1. Integrazione web

Creiamo un layout web

1. Integrazione web

Personalizziamolo

1. Integrazione web

Embeddiamolo

  <style>
    :root, .memori.memori-widget,
    #headlessui-portal-root, memori-client {
      --memori-primary: rgb(255, 0, 0);
      --memori-primary-text: #fff;
      --memori-inner-content-pad: 1rem;
      --memori-inner-bg: #fff;
      --memori-chat-bubble-bg: #ffffff60;
      --memori-text-color: #000;
      --memori-button-bg: #fff;
      --memori-button-text: #000;
      --memori-button-padding: 0.5rem 1.5rem;
      --memori-button-border-color: #d9d9d9;
      --memori-button-radius: 15px;
      --memori-button-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.02);
      --memori-blur-background: 5px;
      --memori-drawer--width: 100%;
      --memori-drawer--width--md: 80%;
      --memori-drawer--width--lg: 60%;
      --memori-modal--width: 100%;
      --memori-modal--width--md: 80%;
      --memori-error-color: #ff4d4f;
    }
  </style>

1. Integrazione web

Personalizziamolo dinamicamente

1. Integrazione web

<memori-client
  memoriName="Memori"
  ownerUserName="nunziofiore"
  tenantID="app.memorytwin.com"
  showShare="true"
  apiURL="https://backend.memori.ai"
  baseURL="https://app.memorytwin.com"
  uiLang="IT"
  spokenLang="IT"
  tag="🍻"
  pin="123456"
  context="VAR1:VALUE1,VAR2:VALUE2"
  initialQuestion="Initial question"
/>

1. Integrazione web

Parametri aggiuntivi avanzati

1. Integrazione web

Layout disponibili

FULLPAGE

TOTEM

CHAT

<memori-client
  memoriName="Memori"
  ownerUserName="nunziofiore"
  tenantID="app.memorytwin.com"
  showShare="true"
  apiURL="https://backend.memori.ai"
  baseURL="https://app.memorytwin.com"
  uiLang="it"
  tag="🍻"
  pin="123456"
  context="VAR1:VALUE1,VAR2:VALUE2"
  initialQuestion="Initial question"
  layout="CHAT"
/>

1. Integrazione web

Integrazione web

ESERCIZIO

Create dallo stesso agente, più integrazioni.

Pensando ad un caso d'uso, create un widget e pensate a persone o contesti da associarvi

2

CONVERSAZIONE E API

2. CONVERSAZIONE E API

2. CONVERSAZIONE E API

INIT

SESSIONE

TEXT
ENTERED

sessionID

memoriID

tag, pin

initialContext

password

state

hints

media

emission

sessionID

text

CURRENT

STATE

sessionID

(la sessione scade)

birthDate

2. CONVERSAZIONE E API

Postman

Postman

2. CONVERSAZIONE E API

Note su ID, nomi e pagina pubblica

2. CONVERSAZIONE E API

GET
https://backend.memori.ai/api/v2/Memori/TENANT/USER_NAME/MEMORI_NAME

Otteniamo i dati di un Memori (Twin)

GET
https://backend.memori.ai/api/v2/MemoriByID/TENANT/USER_ID/MEMORI_ID

2. CONVERSAZIONE E API

POST
https://engine.memori.ai/memori/v2/Session

Iniziamo una sessione

{
  "memoriId": "ENGINE_MEMORI_ID",
  "birthDate": "YYYY-MM-DDHH:mm:ss.dddZ"
}

2. CONVERSAZIONE E API

POST
https://engine.memori.ai/memori/v2/Session

Iniziamo una sessione
con parametri aggiuntivi

{
  "memoriId": "ENGINE_MEMORI_ID"
  "tag": "🍻",
  "pin": "123456",
  "initialQuestion": "Initial question",
  "initialContextVars": "VAR1:VALUE1",
  "birthDate": "YYYY-MM-DDHH:mm:ss.dddZ"
}

2. CONVERSAZIONE E API

DELETE
https://engine.memori.ai/memori/v2/Session/SESSION_ID

Altre operazioni su una sessione

GET
https://engine.memori.ai/memori/v2/Session/SESSION_ID

2. CONVERSAZIONE E API

POST
https://engine.memori.ai/memori/v2/TextEnteredEvent/SESSION_ID
{
  "text": "INSERT_TEXT_HERE"
}

Inviamo del testo

2. CONVERSAZIONE E API

POST
https://engine.memori.ai/memori/v2/TagChangedEvent/SESSION_ID

Altri eventi accettati

(occhio agli accepts)

POST
https://engine.memori.ai/memori/v2/PlaceChangedEvent/SESSION_ID
POST
https://engine.memori.ai/memori/v2/TimeoutEvent/SESSION_ID

2. CONVERSAZIONE E API

Es:

https://assets.memori.ai/api/v2/asset/ea79664c-dd90-4d19-a956-a090e6cbdc4b.jpg

Nota sugli asset

I media sono associati ai contenuti sono protetti, per accedervi serve il sessionID



https://assets.memori.ai/api/v2/asset/ea79664c-dd90-4d19-a956-a090e6cbdc4b.jpg/SESSION_ID

SDK TypeScript

2. CONVERSAZIONE E API

yarn add @memori.ai/memori-api-client
const { sessionID, currentState, ...resp } = await memori.initSession(
  '768b9654-e781-4c3c-81fa-ae1529d1bfbe',
);

const { currentState: dialogState, ...resp } = await memori.postTextEnteredEvent(
  sessionID,
  'Ciao, Memori!'
);
// utility
memori.asset.getResourceUrl({
  type: 'avatar',
  resourceURI: '768b9654-e781-4c3c-81fa-ae1529d1bfbe.png',
  mediaType: 'image/png',
  sessionId: 'be2e4a44-890b-483b-a26a-f6e122f36e2b',
});

2. CONVERSAZIONE E API

CONVERSAZIONE E API

ESERCIZIO

Con l'uso di Postman o un client REST a scelta,

avviare una sessione e proseguire una conversazione.

3

Estendere la conversazione

3. Estendere la conversazione

Messaggio di benvenuto e risposte di default

3. Estendere la conversazione

Gestione suggerimenti e timeout

3. Estendere la conversazione

Gestione contesti

3. Estendere la conversazione

Snippet eseguibili

3. Estendere la conversazione

Snippet eseguibili

<div id="extension"></div>

3. Estendere la conversazione

Esiste un div con id "extension" nella colonna dell'avatar, usabile per aggiungere markup in integrazioni o estensioni della chat, magari tramite snippet eseguibili

Estensioni

3. Estendere la conversazione

const state = getMemoriState();
const sessionID = state.sessionID;
const extension = document.getElementById('extension');

extension.innerHTML = '';

const wrapper = document.createElement('div');
wrapper.id = 'memori-media-wrapper';
extension.appendChild(wrapper);

const images = state.media.filter((m) => m.mimeType.startsWith('image'));
images.forEach((m) => {
  const image = document.createElement('img');
  image.src = `${m.url}/${sessionID}`;
  image.alt = m.name || '';

  wrapper.appendChild(image);
});

Ecco un esempio dove è utilizzato per nascondere le immagini dalla chat e invece mostrarle in griglia sopra all'avatar

Prendiamo lo stato corrente con getMemoriState() e quindi le immagini da esso con un filtro per MIMEType, da quelle generiamo gli elementi del DOM

NOTA: per ripulire da eventuali altri elementi, prima svuotiamo il div

3. Estendere la conversazione

const styles = document.createElement('style');
styles.innerHTML = `
#memori-media-wrapper {
  display: flex;
  flex-wrap: wrap;
  position: absolute;
  top: 2rem;
  z-index: 1000;
}
#memori-media-wrapper img {
  width: 100%;
  padding: 0.5rem;
}
.memori-media-widget {
  display: none;
}
`;

extension.appendChild(styles);

Aggiungiamo del CSS per mostrarlo bene e appendiamo il tutto

3. Estendere la conversazione

document.addEventListener('MemoriEndSpeak', () => {
    extension.innerHTML = '';
})

Ripuliamo #extension al prossimo evento, in modo da non creare conflitti

3. Estendere la conversazione

Gestione intenti

4

REALIZZARE UN CLIENT

4. Realizzare un client

const startConversation = () => {
  fetch("https://engine.memori.ai/memori/v2/session", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      memoriId: "1afe57c6-1b69-4a61-96ea-52bf7b8d158e",
    }),
  })
    .then((response) => response.json())
    .then((result) => {
      state = result;

      if (state.currentState.emission)
        console.log(`Nunzio: ${state.currentState.emission}`);

      handleConversation();
    })
    .catch((error) => console.log("error", error));
};
const sendMessage = (question) => {
  fetch(
    `https://engine.memori.ai/memori/v2/TextEnteredEvent/${state.sessionID}`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        text: question,
      }),
    }
  )
  .then((response) => response.json())
  .then((result) => {
    state = result;

    if (state.currentState.emission)
      console.log(`Nunzio: ${state.currentState.emission}`);
  })
  .catch((error) => console.log("error", error));
}

4. Realizzare un client

4. Realizzare un client

5

SDK E LIBRERIE

5. SDK e LIBRERIE

SDK TypeScript

yarn add @memori.ai/memori-api-client
const { sessionID, currentState, ...resp } = await memori.initSession(
  '768b9654-e781-4c3c-81fa-ae1529d1bfbe',
);

const { currentState: dialogState, ...resp } = await memori.postTextEnteredEvent(
  sessionID,
  'Ciao, Memori!'
);
// utility
memori.asset.getResourceUrl({
  type: 'avatar',
  resourceURI: '768b9654-e781-4c3c-81fa-ae1529d1bfbe.png',
  mediaType: 'image/png',
  sessionId: 'be2e4a44-890b-483b-a26a-f6e122f36e2b',
});

5. SDK e LIBRERIE

Libreria React

5. SDK e LIBRERIE

yarn add @memori.ai/memori-react
import Memori from '@memori.ai/memori-react';
import '@memori.ai/memori-react/dist/styles.css';

const App = () => (
  <Memori
    memoriName="Memori"
    ownerUserName="nunziofiore"
    tenantID="app.memorytwin.com"
    apiURL="https://backend.memori.ai"
    baseURL="https://app.memorytwin.com"
    uiLang="it"
    showShare
    height="100vh"
  />
);

5. SDK e LIBRERIE

WebComponent

5. SDK e LIBRERIE

<script
  type="module"
  src="https://esm.run/@memori.ai/memori-webcomponent/dist/memori-webcomponent.js"
></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@memori.ai/memori-react/dist/styles.min.css"
/>

<memori-client
  memoriName="Memori"
  ownerUserName="nunziofiore"
  tenantID="app.memorytwin.com"
  showShare
  apiURL="https://backend.memori.ai"
  baseURL="https://app.memorytwin.com"
  uiLang="it"
  height="100vh"
/>

5. SDK e LIBRERIE

let dialogState = getMemoriState();
let sessionID = getMemoriState().sessionID;

// in case you have multiple widgets on the same page
let dialogState = getMemoriState(myWidgetIntegrationId); 

5. SDK e LIBRERIE

typeMessage('Hello World!')

// waits for previous message to be read, default: true
const waitForPrevious = true 
// message is not visible to the user, only the response is, default: false
const hidden = true

typeMessage('Hello World!', waitForPrevious, hidden)
typeMessageHidden('Hello World!', waitForPrevious)

// alias to
typeMessage('Hello World!', waitForPrevious, true)
typeBatchMessages([
  {
    message: 'percorso libero',
    hidden: true,
    waitForPrevious: true,
    useLoaderTextAsMsg: true,
    typingText: 'Preparo il cartamodello...',
  },
  {
    message: 'imposta lo scollo a v',
    hidden: true,
    waitForPrevious: true,
    useLoaderTextAsMsg: true,
    typingText: 'Cucio lo scollo come preferisci...'
  },
  ...
])

5. SDK e LIBRERIE

5. SDK e LIBRERIE

onStateChange

5. SDK e LIBRERIE

SDK e librerie

ESERCIZIO

Creare un'applicazione React e installare il componente

Creare un layout custom e mostrare lo stato e le variazioni
Pensare ad un'integrazione di sistemi e ragioniamoci insieme

5

Realtà virtuale

METAVERSI

5. Realtà virtuale e metaversi

TwinCreator VR

5. Realtà virtuale e metaversi

DOMANDE?

Ora o quando volete

Memori AI: formazione client

By Nicola Zambello

Memori AI: formazione client

  • 201