Opérations de chat
Écrit par Stanislas
Dernière mise à jour Il y a 7 mois
Apprenez à envoyer des messages en continu, à régénérer les réponses, à interrompre la génération de messages et à utiliser les fonctions de synthèse vocale.
Présentation
Les opérations de chat constituent les interactions centrales d'une conversation. Vous pouvez envoyer des messages pour déclencher des réponses IA, écouter les réponses en streaming en temps réel, régénérer les réponses insatisfaisantes, arrêter les générations longues et convertir les réponses en audio. Ce guide couvre toutes les mutations et requêtes dont vous avez besoin pour une expérience de chat complète.
Chaque message envoyé peut éventuellement déclencher une réponse de l'IA. Les réponses sont diffusées caractère par caractère, ce qui permet aux utilisateurs d'obtenir un retour immédiat. Vous pouvez également utiliser des requêtes synchrones si vous avez besoin de la réponse complète avant de continuer.
Prérequis
Avant d'effectuer des opérations de chat, assurez-vous que vous disposez des éléments suivants :
Vous êtes authentifié avec l'API — Suivez le guide Guide d'authentification et d'installation pour obtenir votre
accessTokenet votreworkspaceIdCréé ou récupéré une session — Suivez les instructions Guide de gestion des sessions de chat pour obtenir un
sessionIdConfiguré votre client GraphQL — Votre client Apollo doit inclure les en-têtes d'authentification requis
Configuré les abonnements (facultatif) — Pour le streaming en temps réel, suivez les instructions disponibles à l'adresse Guide des abonnements en temps réel
Pour commencer
Voici la configuration minimale pour envoyer un message et recevoir une réponse :
Étape 1 : envoyer un message
Envoyez un message au bot et déclenchez une réponse en streaming.
import { gql } from '@apollo/client';
const SEND_MESSAGE = gql`
mutation SendNewMessage($newMessageData: NewMessageInput!) {
sendNewMessage(newMessageData: $newMessageData) {
id
message
createdAt
sessionId
sentBy {
id
firstName
}
isBotReply
}
}
`;
const sendMessage = async (client, sessionId, messageText) => {
const { data } = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: messageText,
sessionId: sessionId,
isForAiReply: true, // Trigger AI response
},
},
});
return data.sendNewMessage;
};
// Usage
const userMessage = await sendMessage(client, 67890, 'What is your pricing?');
console.log('Message sent:', userMessage.id);
Étape 2 : abonnez-vous aux réponses en streaming
Écoutez la réponse de l'IA en streaming en temps réel.
const MESSAGE_STREAM = gql`
subscription OnMessageStream($sessionId: Float!) {
onMessageStream(sessionId: $sessionId) {
messageChunk
botResponseMessageId
isStoppable
}
}
`;
const subscribeToStream = (client, sessionId, onChunk) => {
let fullMessage = '';
return client
.subscribe({
query: MESSAGE_STREAM,
variables: { sessionId },
})
.subscribe({
next: ({ data }) => {
fullMessage += data.onMessageStream.messageChunk;
onChunk(fullMessage, data.onMessageStream);
},
error: (error) => {
console.error('Stream error:', error);
},
complete: () => {
console.log('Stream complete');
},
});
};
// Usage
const subscription = subscribeToStream(client, 67890, (fullMessage, data) => {
console.log('Streaming:', fullMessage);
if (data.isStoppable) {
console.log('User can stop generation');
}
});
// Cleanup when done
// subscription.unsubscribe();
Étape 3 : Arrêter la génération si nécessaire
Si la réponse prend trop de temps, arrêtez la génération.
const STOP_AI_RESPONSE = gql`
mutation StopAIResponse($sessionId: Float!, $botId: Float!) {
stopAIResponse(sessionId: $sessionId, botId: $botId)
}
`;
const stopGeneration = async (client, sessionId, botId) => {
const { data } = await client.mutate({
mutation: STOP_AI_RESPONSE,
variables: { sessionId, botId },
});
return data.stopAIResponse;
};
// Usage
const stopped = await stopGeneration(client, 67890, 123);
console.log('Generation stopped:', stopped);
Envoi de messages
Envoyez un nouveau message
Envoyez un message à la session et déclenchez éventuellement une réponse de l'IA.
Mutation GraphQL :
mutation SendNewMessage($newMessageData: NewMessageInput!) {
sendNewMessage(newMessageData: $newMessageData) {
id
message
createdAt
sessionId
sentBy {
id
firstName
lastName
}
isBotReply
}
}
Paramètres d'entrée :
Retourne : l'objet message créé
Exemple de base :
const SEND_MESSAGE = gql`
mutation SendNewMessage($newMessageData: NewMessageInput!) {
sendNewMessage(newMessageData: $newMessageData) {
id
message
createdAt
isBotReply
}
}
`;
// Simple message without AI response
const message1 = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: 'Just saving this note',
sessionId: 67890,
},
},
});
// Message that triggers AI response
const message2 = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: 'What can you do for me?',
sessionId: 67890,
isForAiReply: true,
},
},
});
Avec pièces jointes :
const sendMessageWithFiles = async (client, sessionId, messageText, fileIds) => {
const { data } = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: messageText,
sessionId,
fileIds, // Array of file IDs
isForAiReply: true,
},
},
});
return data.sendNewMessage;
};
// Usage
const message = await sendMessageWithFiles(
client,
67890,
'Please analyze these documents',
[101, 102, 103]
);
Avec fil de discussion (réponse à un message spécifique) :
const sendReplyToMessage = async (client, sessionId, messageText, parentMessageId) => {
const { data } = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: messageText,
sessionId,
parentMessageId, // Reply to this message
isForAiReply: true,
},
},
});
return data.sendNewMessage;
};
// Usage
const reply = await sendReplyToMessage(
client,
67890,
'Can you elaborate on that?',
12345 // ID of the message to reply to
);
À l'aide d'une invite prédéfinie :
const sendWithPrompt = async (client, sessionId, botPromptId) => {
const { data } = await client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
sessionId,
botPromptId, // Use a predefined prompt instead of typing
isForAiReply: true,
},
},
});
return data.sendNewMessage;
};
// Usage - useful for quick actions like "Summarize" or "Translate"
const summary = await sendWithPrompt(client, 67890, 456);
Demandes synchrones
Envoyer un message et attendre la réponse complète
Pour les questions-réponses simples sans streaming, utilisez le point de terminaison synchrone pour obtenir immédiatement la réponse complète.
Mutation GraphQL :
mutation SyncBotRequest($newMessageData: NewMessageInput!) {
syncBotRequest(newMessageData: $newMessageData) {
text
botId
botSlug
isBotError
sessionId
files
sourceMetadatas
sources
responseJson
jobId
}
}
Paramètres d'entrée : identiques à ceux d'SendNewMessage
Retourne : réponse complète avec métadonnées
Exemple :
const SYNC_BOT_REQUEST = gql`
mutation SyncBotRequest($newMessageData: NewMessageInput!) {
syncBotRequest(newMessageData: $newMessageData) {
text
isBotError
sources
botSlug
}
}
`;
const syncMessage = async (client, sessionId, messageText) => {
const { data } = await client.mutate({
mutation: SYNC_BOT_REQUEST,
variables: {
newMessageData: {
message: messageText,
sessionId,
},
},
});
return data.syncBotRequest;
};
// Usage
const response = await syncMessage(client, 67890, 'What is 2 + 2?');
console.log('Bot response:', response.text);
console.log('Sources used:', response.sources);
if (response.isBotError) {
console.error('Bot encountered an error');
}
Quand utiliser les requêtes synchrones :
Questions-réponses simples où vous avez besoin de la réponse complète avant de continuer
Traitement par lots de plusieurs messages
Lorsque vous n'avez pas besoin d'un retour en temps réel
Intégrations API où vous avez besoin d'une réponse complète immédiatement
Gestion des réponses
Régénérer une réponse
Si la réponse du bot n'était pas satisfaisante, régénérez-la.
Mutation GraphQL :
mutation RegenerateResponse($messageId: Float!) {
regenerateResponse(messageId: $messageId) {
id
message
createdAt
}
}
Paramètres :
messageId(obligatoire) — ID du message de réponse du bot à régénérer
Retourne : Le nouveau message de réponse
Exemple :
const REGENERATE_RESPONSE = gql`
mutation RegenerateResponse($messageId: Float!) {
regenerateResponse(messageId: $messageId) {
id
message
createdAt
}
}
`;
const regenerateResponse = async (client, messageId) => {
const { data } = await client.mutate({
mutation: REGENERATE_RESPONSE,
variables: { messageId },
});
return data.regenerateResponse;
};
// Usage
const newResponse = await regenerateResponse(client, 54321);
console.log('New response generated:', newResponse.id);
Workflow avec régénération :
// User sends a message
const userMessage = await sendMessage(client, sessionId, 'Explain quantum computing');
// Subscribe to streaming response
let botMessageId;
subscribeToStream(client, sessionId, (fullMessage, data) => {
botMessageId = data.botResponseMessageId;
updateUI(fullMessage);
});
// Later, user clicks "Regenerate" button
const newResponse = await regenerateResponse(client, botMessageId);
console.log('Response regenerated');
Arrêter la réponse IA
Arrête la génération de réponse IA en cours.
Mutation GraphQL :
mutation StopAIResponse($sessionId: Float!, $botId: Float!) {
stopAIResponse(sessionId: $sessionId, botId: $botId)
}
Paramètres :
sessionId(obligatoire) — ID de sessionbotId(obligatoire) — ID du bot
Retourne : Booléen (vrai si l'arrêt a réussi)
Exemple :
const STOP_AI_RESPONSE = gql`
mutation StopAIResponse($sessionId: Float!, $botId: Float!) {
stopAIResponse(sessionId: $sessionId, botId: $botId)
}
`;
const stopGeneration = async (client, sessionId, botId) => {
const { data } = await client.mutate({
mutation: STOP_AI_RESPONSE,
variables: { sessionId, botId },
});
return data.stopAIResponse;
};
// Usage
const stopped = await stopGeneration(client, 67890, 123);
if (stopped) {
console.log('Generation stopped by user');
}
Implémentation de l'interface utilisateur avec bouton d'arrêt :
let isGenerating = false;
let currentBotId = 123;
const startGeneration = async (sessionId) => {
isGenerating = true;
showStopButton();
subscribeToStream(client, sessionId, (fullMessage, data) => {
updateMessageUI(fullMessage);
if (!data.isStoppable) {
hideStopButton();
}
});
};
const handleStopClick = async (sessionId) => {
if (isGenerating) {
await stopGeneration(client, sessionId, currentBotId);
isGenerating = false;
hideStopButton();
}
};
Réessayer le message ayant échoué
Réessayer d'envoyer un message qui a échoué.
Mutation GraphQL :
mutation RetryBotMessage($sessionId: Float!) {
retryBotMessage(sessionId: $sessionId)
}
Paramètres :
sessionId(obligatoire) — ID de session
Retourne : Booléen (vrai si la nouvelle tentative a réussi)
Exemple
const RETRY_MESSAGE = gql`
mutation RetryBotMessage($sessionId: Float!) {
retryBotMessage(sessionId: $sessionId)
}
`;
const retryMessage = async (client, sessionId) => {
const { data } = await client.mutate({
mutation: RETRY_MESSAGE,
variables: { sessionId },
});
return data.retryBotMessage;
};
// Usage
const success = await retryMessage(client, 67890);
if (success) {
console.log('Message retry successful');
}
Synthèse vocale
Convertir un message en audio
Convertit un message en audio à l'aide de la synthèse vocale.
Requête GraphQL :
query GetSpeechFromText($messageId: Float!) {
getSpeechFromText(messageId: $messageId)
}
Paramètres :
messageId(obligatoire) — ID du message à convertir
Renvoie : Chaîne URL audio
Exemple :
const GET_SPEECH = gql`
query GetSpeechFromText($messageId: Float!) {
getSpeechFromText(messageId: $messageId)
}
`;
const getAudioUrl = async (client, messageId) => {
const { data } = await client.query({
query: GET_SPEECH,
variables: { messageId },
});
return data.getSpeechFromText;
};
// Usage
const audioUrl = await getAudioUrl(client, 12345);
const audio = new Audio(audioUrl);
audio.play();
Avec interface utilisateur du lecteur audio :
const playMessageAudio = async (client, messageId) => {
try {
const audioUrl = await getAudioUrl(client, messageId);
const audio = new Audio(audioUrl);
audio.addEventListener('ended', () => {
console.log('Audio playback finished');
});
audio.play();
return audio;
} catch (error) {
console.error('Failed to play audio:', error);
}
};
// Usage in UI
const audioElement = await playMessageAudio(client, messageId);
Classe complète de gestionnaire de chat
Voici une classe réutilisable qui encapsule toutes les opérations de chat :
class ChatManager {
constructor(client, sessionId) {
this.client = client;
this.sessionId = sessionId;
this.currentBotId = null;
this.isGenerating = false;
}
async sendMessage(messageText, options = {}) {
const SEND_MESSAGE = gql`
mutation SendNewMessage($newMessageData: NewMessageInput!) {
sendNewMessage(newMessageData: $newMessageData) {
id
message
createdAt
sessionId
isBotReply
}
}
`;
const { data } = await this.client.mutate({
mutation: SEND_MESSAGE,
variables: {
newMessageData: {
message: messageText,
sessionId: this.sessionId,
isForAiReply: true,
...options,
},
},
});
return data.sendNewMessage;
}
async sendSyncMessage(messageText, options = {}) {
const SYNC_REQUEST = gql`
mutation SyncBotRequest($newMessageData: NewMessageInput!) {
syncBotRequest(newMessageData: $newMessageData) {
text
isBotError
sources
botId
}
}
`;
const { data } = await this.client.mutate({
mutation: SYNC_REQUEST,
variables: {
newMessageData: {
message: messageText,
sessionId: this.sessionId,
...options,
},
},
});
return data.syncBotRequest;
}
subscribeToStream(onChunk, onComplete) {
const MESSAGE_STREAM = gql`
subscription OnMessageStream($sessionId: Float!) {
onMessageStream(sessionId: $sessionId) {
messageChunk
botResponseMessageId
isStoppable
botId
}
}
`;
let fullMessage = '';
return this.client
.subscribe({
query: MESSAGE_STREAM,
variables: { sessionId: this.sessionId },
})
.subscribe({
next: ({ data }) => {
fullMessage += data.onMessageStream.messageChunk;
this.currentBotId = data.onMessageStream.botId;
this.isGenerating = true;
onChunk(fullMessage, data.onMessageStream);
},
error: (error) => {
console.error('Stream error:', error);
this.isGenerating = false;
},
complete: () => {
this.isGenerating = false;
if (onComplete) onComplete(fullMessage);
},
});
}
async stopGeneration() {
if (!this.isGenerating || !this.currentBotId) {
return false;
}
const STOP = gql`
mutation StopAIResponse($sessionId: Float!, $botId: Float!) {
stopAIResponse(sessionId: $sessionId, botId: $botId)
}
`;
const { data } = await this.client.mutate({
mutation: STOP,
variables: {
sessionId: this.sessionId,
botId: this.currentBotId,
},
});
this.isGenerating = false;
return data.stopAIResponse;
}
async regenerateResponse(messageId) {
const REGENERATE = gql`
mutation RegenerateResponse($messageId: Float!) {
regenerateResponse(messageId: $messageId) {
id
message
}
}
`;
const { data } = await this.client.mutate({
mutation: REGENERATE,
variables: { messageId },
});
return data.regenerateResponse;
}
async retryMessage() {
const RETRY = gql`
mutation RetryBotMessage($sessionId: Float!) {
retryBotMessage(sessionId: $sessionId)
}
`;
const { data } = await this.client.mutate({
mutation: RETRY,
variables: { sessionId: this.sessionId },
});
return data.retryBotMessage;
}
async getAudioUrl(messageId) {
const GET_SPEECH = gql`
query GetSpeechFromText($messageId: Float!) {
getSpeechFromText(messageId: $messageId)
}
`;
const { data } = await this.client.query({
query: GET_SPEECH,
variables: { messageId },
});
return data.getSpeechFromText;
}
async playAudio(messageId) {
const audioUrl = await this.getAudioUrl(messageId);
const audio = new Audio(audioUrl);
audio.play();
return audio;
}
}
// Usage example
const chatManager = new ChatManager(client, 67890);
// Send a message and listen to streaming
await chatManager.sendMessage('Tell me a story');
const subscription = chatManager.subscribeToStream(
(fullMessage, data) => {
console.log('Streaming:', fullMessage);
updateUI(fullMessage);
},
(finalMessage) => {
console.log('Response complete');
}
);
// User clicks stop button
await chatManager.stopGeneration();
// User clicks regenerate
await chatManager.regenerateResponse(messageId);
// User clicks speaker icon
await chatManager.playAudio(messageId);
Cas d'utilisation pratiques
Interface utilisateur de chat en temps réel
Créez une interface de chat avec des réponses en streaming :
const chatManager = new ChatManager(client, sessionId);
// User types and sends message
const handleSendMessage = async (userInput) => {
// Display user message immediately
addMessageToUI(userInput, 'user');
// Send message and start streaming
await chatManager.sendMessage(userInput);
// Create placeholder for bot response
let botMessageElement = addMessageToUI('', 'bot');
// Subscribe to streaming
chatManager.subscribeToStream(
(fullMessage) => {
// Update bot message as it streams
updateMessageContent(botMessageElement, fullMessage);
},
() => {
// Finalize when complete
finalizeMessage(botMessageElement);
}
);
};
Réponse rapide sans streaming
Pour les questions-réponses simples, obtenez immédiatement la réponse complète :
const handleQuickQuestion = async (question) => {
try {
const response = await chatManager.sendSyncMessage(question);
if (response.isBotError) {
showError('Bot encountered an error');
return;
}
displayAnswer(response.text);
if (response.sources) {
displaySources(response.sources);
}
} catch (error) {
showError('Failed to get answer');
}
};
Lecture audio pour l'accessibilité
Permettez aux utilisateurs d'écouter les réponses :
const handleAudioButton = async (messageId) => {
try {
showLoadingSpinner();
const audio = await chatManager.playAudio(messageId);
hideLoadingSpinner();
audio.addEventListener('ended', () => {
console.log('Audio finished');
});
} catch (error) {
hideLoadingSpinner();
showError('Failed to play audio');
}
};
Meilleures pratiques
Définissez toujours l'
isForAiReply: truelorsque vous souhaitez une réponse de l'IA ; sinon, le message est simplement stocké sans déclencher la génération.Utilisez le streaming pour une meilleure expérience utilisateur — Le streaming affiche les réponses caractère par caractère, offrant un retour immédiat. N'utilisez le mode synchrone que pour les cas simples.
Gérez l'arrêt avec élégance : affichez un bouton d'arrêt pendant la génération et gérez l'action d'arrêt de manière propre.
Stockez les identifiants des messages — Conservez les identifiants des messages pour la régénération et les fonctionnalités audio.
Validez les entrées avant l'envoi — Vérifiez la longueur et le contenu des messages avant l'envoi afin d'éviter les erreurs.
Implémentez la gestion des erreurs — Enveloppez toujours les mutations dans des blocs try-catch et affichez des messages d'erreur conviviaux.
Utilisez les pièces jointes à bon escient — Ne joignez des fichiers que lorsque cela est nécessaire ; validez les identifiants de fichiers avant l'envoi.
Mettre en cache les URL audio — Stockez les URL audio générées pour éviter de régénérer plusieurs fois le même fichier audio.