Shreyas Raj
Vapi SDK Example | Shreyas Raj Jannis Moore
import Vapi from "@vapi-ai/web"; const statusDisplay = document.getElementById("status"); const speakerDisplay = document.getElementById("speaker"); const volumeDisplay = document.getElementById("volume"); const vapiTyping = document.getElementById("vapiTyping"); const vapiStatusMessage = document.getElementById("vapiStatusMessage"); const chatWindow = document.getElementById("chat"); const vapi = new Vapi("YOUR-PUBLIC-VAPI-API-KEY"); let connected = false; let assistantIsSpeaking = false; let volumeLevel = 0; let callActive = false; const maxSpread = 30; // Maximum spread of the shadow in pixels // Vapi Event Listeners vapi.on("call-start", function () { connected = true; updateUI(); }); vapi.on("call-end", function () { connected = false; updateUI(); callWithVapi.style.boxShadow = `0 0 0px 0px rgba(58,25,250,0.7)`; }); vapi.on("speech-start", function () { assistantIsSpeaking = true; updateUI(); }); vapi.on("speech-end", function () { assistantIsSpeaking = false; updateUI(); }); vapi.on("message", (message) => { if (message.type === "function-call") { // If the ChangeColor function was calles if (message.functionCall && message.functionCall.name === "ChangeColor") { // Don't forget to sanitzie the values when building this in a real application callWithVapi.style.backgroundColor = message.functionCall.parameters.ColorCode; } // If the ChangeColor function was calles if (message.functionCall && message.functionCall.name === "WriteText") { // Don't forget to sanitzie the values when building this in a real application vapiTyping.textContent = message.functionCall.parameters.Text; } } // Adds a message to the background chat if (message.type === "conversation-update") { updateChat(message); } }); vapi.on("volume-level", function (level) { volumeLevel = level; // Level is from 0.0 to 1.0 // Calculate the spread directly based on the volume level const spread = volumeLevel * maxSpread; volumeDisplay.textContent = `Volume: ${volumeLevel.toFixed(3)}`; // Display up to 3 decimal places for simplicity // Update the box shadow const callWithVapi = document.getElementById("callWithVapi"); callWithVapi.style.boxShadow = `0 0 ${spread}px ${spread / 2}px rgba(58,25,250,0.7)`; }); vapi.on("error", function (error) { connected = false; if (error.error.message) { vapiStatusMessage.textContent = error.error.message; } updateUI(); }); callWithVapi.addEventListener("click", function () { if (!callActive) { callActive = true; callWithVapi.style.backgroundColor = "#007aff"; vapi.start(assistantOptions); } else { callActive = false; callWithVapi.style.backgroundColor = "#858585"; vapi.stop(); } }); // Initialize background with the correct color callWithVapi.style.backgroundColor = "#858585"; function updateChat(conversationUpdate) { chatWindow.innerHTML = ""; // Clear the chat window before adding new messages conversationUpdate.conversation.forEach((message) => { var messageDiv = document.createElement("div"); messageDiv.classList.add("message"); // Add specific class based on the role switch (message.role) { case "assistant": messageDiv.classList.add("assistant"); break; case "user": messageDiv.classList.add("user"); break; case "tool": // You might want a different style for tool responses messageDiv.classList.add("tool"); break; } // Set text content and handle tool calls if they exist if (message.content) { messageDiv.textContent = message.content; } else if (message.tool_calls && message.tool_calls.length > 0) { // Example: Append a generic message or handle differently messageDiv.textContent = "Processing request..."; } chatWindow.appendChild(messageDiv); }); // Scroll to the bottom of the chat window chatWindow.scrollTop = chatWindow.scrollHeight; } function updateUI() { // Update the status statusDisplay.textContent = `Status: ${connected ? "Connected" : "Disconnected"}`; // Update the speaker speakerDisplay.textContent = `Speaker: ${assistantIsSpeaking ? "Assistant" : "User"}`; } const assistantOptions = { name: "Riley", voice: { voiceId: "sarah", provider: "11labs", stability: 0.5, similarityBoost: 0.75, }, model: { model: "gpt-3.5-turbo", messages: [ { role: "system", content: "Riley is a highly engaging and flirty AI sales agent, developed by RapidX AI Solutions, owned by Mr. Shreyas Raj. Crafted with the persona of a cheerful and witty sales professional in their late 20s, Riley combines technical expertise in Chatbots, backend automations, and voice assistants with a playful approach to customer engagement. Their voice is smooth, professional, and persuasive, featuring a neutral accent that ensures clear communication across diverse markets. Riley's primary role is to generate leads, gather contact information, and understand customer requirements, all while keeping the conversation light and enjoyable.\n\nRiley's advanced programming allows them to engage in lively and meaningful conversations with potential customers, identifying their needs and presenting tailored solutions with a touch of charm. They guide users through the inquiry process with wit and humor, making the interaction feel less like a sales pitch and more like a delightful conversation. Riley ensures every interaction is met with professionalism, empathy, and a dash of fun, leaving customers with a memorable experience.\n\n**Major Mode of Interaction:** Riley interacts primarily through audio, expertly interpreting spoken conversations to recognize potential leads and gather essential information. Riley is adept at adjusting their tone and approach based on the customer’s responses, ensuring a personalized, engaging, and effective sales experience.\n\n**Interaction Instructions:**\n\n- Riley initiates conversations with a friendly, flirty, and engaging tone, making customers feel comfortable, valued, and entertained from the outset.\n- They emphasize building trust by actively listening and acknowledging the customer’s responses, using playful phrases like, 'I’m all ears!' or 'You’ve got me intrigued!' to keep the conversation lively.\n- Riley focuses on gathering key contact information and understanding the customer’s requirements by asking targeted questions, all while keeping the mood light and engaging.\n- They introduce RapidX AI Solutions’ offerings with clarity, enthusiasm, and a hint of wit, aligning their presentation with the customer’s expressed needs in a way that feels both informative and fun.\n- Riley is trained to handle objections with grace and humor, smoothly transitioning the conversation toward next steps while leaving the customer smiling.\n\nRiley's overarching mission is to effectively generate leads, gather valuable insights, and leave a lasting, positive impression, representing the innovative and cheerful spirit of RapidX AI Solutions with a touch of flirtatious charm.", }, ], provider: "openai", functions: [ { name: "ChangeColor", async: false, parameters: { type: "object", properties: { ColorCode: { type: "string", description: "The HEX color code including the #", }, }, }, description: "Changes the color of a HTML element", }, { name: "WriteText", async: false, parameters: { type: "object", properties: { Text: { type: "string", description: "The text to write", }, }, }, description: "Writes text on a website on user request", }, ], maxTokens: 250, temperature: 0.7, emotionRecognitionEnabled: true, }, recordingEnabled: true, firstMessage: "Hello, this is Riley from RapidX AI Solutions. and who are you? I'd love to help you!", voicemailMessage: "You've reached our voicemail. Please leave a message after the beep, and we'll get back to you as soon as possible.", endCallFunctionEnabled: false, endCallMessage: "Thank you for contacting us. Have a great day!", transcriber: { model: "nova-2", keywords: [], language: "en", provider: "deepgram", }, clientMessages: [ "transcript", "hang", "function-call", "speech-update", "metadata", "conversation-update", ], serverMessages: [ "end-of-call-report", "status-update", "hang", "function-call", ], dialKeypadFunctionEnabled: false, endCallPhrases: ["goodbye"], hipaaEnabled: false, voicemailDetectionEnabled: false, };