{"id":95,"date":"2025-03-23T20:42:43","date_gmt":"2025-03-23T20:42:43","guid":{"rendered":"https:\/\/neocloud05.com\/neo\/?page_id=95"},"modified":"2025-03-25T06:51:56","modified_gmt":"2025-03-25T06:51:56","slug":"laboratorio-modelo-conversacional","status":"publish","type":"page","link":"https:\/\/neocloud05.com\/neo\/laboratorio-modelo-conversacional\/","title":{"rendered":"Laboratorio 2.0.1 Modelo Conversacional"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"95\" class=\"elementor elementor-95\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dead8d3 e-flex e-con-boxed e-con e-parent\" data-id=\"dead8d3\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-41ce17a elementor-widget elementor-widget-heading\" data-id=\"41ce17a\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Neo 2.0 Beta<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-9f96e12 e-flex e-con-boxed e-con e-parent\" data-id=\"9f96e12\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ef60ff3 elementor-widget elementor-widget-html\" data-id=\"ef60ff3\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!--\nconst OPENAI_API_KEY = 'Bearer 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'; \/\/ Reemplaza con tu API Key\n-->\n\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n  <title>Asistente AI con Voz Continua<\/title>\n  <style>\n    body {\n      background: #f0f2f5;\n      font-family: 'Segoe UI', sans-serif;\n      margin: 0;\n      padding: 20px;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .chat-container {\n      background: #fff;\n      width: 100%;\n      max-width: 600px;\n      height: 80vh;\n      border-radius: 12px;\n      box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n    }\n\n    .chat-header {\n      background: #4f46e5;\n      color: white;\n      padding: 16px;\n      font-size: 18px;\n      font-weight: bold;\n    }\n\n    .chat-body {\n      flex: 1;\n      padding: 16px;\n      overflow-y: auto;\n      background: #f9fafb;\n    }\n\n    .message {\n      margin-bottom: 12px;\n    }\n\n    .user {\n      text-align: right;\n    }\n\n    .bot {\n      text-align: left;\n    }\n\n    .message p {\n      display: inline-block;\n      padding: 10px 14px;\n      border-radius: 20px;\n      max-width: 80%;\n    }\n\n    .user p {\n      background: #4f46e5;\n      color: white;\n    }\n\n    .bot p {\n      background: #e5e7eb;\n      color: #111827;\n    }\n\n    .chat-input {\n      display: flex;\n      padding: 10px;\n      border-top: 1px solid #e5e7eb;\n      background: #fff;\n    }\n\n    .chat-input input {\n      flex: 1;\n      padding: 10px;\n      border: 1px solid #d1d5db;\n      border-radius: 8px;\n      margin-right: 10px;\n      font-size: 16px;\n    }\n\n    .chat-input button {\n      padding: 10px;\n      background: #4f46e5;\n      color: white;\n      border: none;\n      border-radius: 8px;\n      cursor: pointer;\n      font-weight: bold;\n      margin-left: 5px;\n    }\n\n    .chat-input button:hover {\n      background: #4338ca;\n    }\n\n    .voice-controls {\n      margin-top: 15px;\n      display: flex;\n      gap: 10px;\n    }\n\n    .test-voice-button, .continuous-button {\n      padding: 10px 20px;\n      font-weight: bold;\n      background: #10b981;\n      color: white;\n      border: none;\n      border-radius: 8px;\n      cursor: pointer;\n    }\n\n    .test-voice-button:hover, .continuous-button:hover {\n      background: #059669;\n    }\n  <\/style>\n<\/head>\n<body>\n\n  <div class=\"chat-container\">\n    <div class=\"chat-header\">\ud83e\udd16 Asistente IA con Voz<\/div>\n    <div class=\"chat-body\" id=\"chat-body\"><\/div>\n    <div class=\"chat-input\">\n      <input type=\"text\" id=\"user-input\" placeholder=\"Escribe o habla tu mensaje...\" \/>\n      <button onclick=\"sendMessage()\">Enviar<\/button>\n      <button id=\"mic-button\" title=\"Hablar por micr\u00f3fono\">\ud83c\udf99\ufe0f<\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"voice-controls\">\n    <button class=\"test-voice-button\" onclick=\"probarVoz()\">\ud83d\udd0a Probar Voz<\/button>\n    <button class=\"continuous-button\" id=\"toggle-continuous\">\ud83c\udfa4 Activar Conversaci\u00f3n<\/button>\n  <\/div>\n\n  <script>\n    const chatBody = document.getElementById('chat-body');\n    const userInput = document.getElementById('user-input');\n    const micButton = document.getElementById('mic-button');\n    const toggleContinuous = document.getElementById('toggle-continuous');\n    let chatHistory = [];\n    let voces = [];\n    let continuousMode = false;\n    let speaking = false;\n\n    const recognition = window.SpeechRecognition ? new SpeechRecognition() : new webkitSpeechRecognition();\n\n    recognition.lang = 'es-ES';\n    recognition.interimResults = false;\n    recognition.continuous = false;\n\n    speechSynthesis.onvoiceschanged = () => {\n      voces = speechSynthesis.getVoices();\n    };\n\n    async function sendMessage(text = null) {\n      const message = text || userInput.value.trim();\n      if (!message) return;\n\n      appendMessage('user', message);\n      chatHistory.push({ role: 'user', content: message });\n      userInput.value = '';\n      chatBody.scrollTop = chatBody.scrollHeight;\n\n      appendMessage('bot', '\ud83e\udde0 Pensando...');\n\n      try {\n        const response = await fetch('https:\/\/api.openai.com\/v1\/chat\/completions', {\n          method: 'POST',\n          headers: {\n            'Authorization': 'Bearer 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', \/\/ \u2190 Reemplaza con tu API key\n            'Content-Type': 'application\/json'\n          },\n          body: JSON.stringify({\n            model: 'gpt-3.5-turbo',\n            messages: [...chatHistory]\n          })\n        });\n\n        const data = await response.json();\n        const reply = data.choices?.[0]?.message?.content || 'No se obtuvo respuesta.';\n\n        removeLastBotThinking();\n        appendMessage('bot', reply);\n        chatHistory.push({ role: 'assistant', content: reply });\n        speakText(reply);\n        chatBody.scrollTop = chatBody.scrollHeight;\n\n      } catch (error) {\n        removeLastBotThinking();\n        appendMessage('bot', '\u274c Error al conectarse a la IA.');\n        console.error(error);\n      }\n    }\n\n    function appendMessage(sender, text) {\n      const messageDiv = document.createElement('div');\n      messageDiv.className = `message ${sender}`;\n      const messageText = document.createElement('p');\n      messageText.innerText = text;\n      messageDiv.appendChild(messageText);\n      chatBody.appendChild(messageDiv);\n    }\n\n    function removeLastBotThinking() {\n      const messages = chatBody.querySelectorAll('.bot');\n      if (messages.length > 0) {\n        const lastBotMsg = messages[messages.length - 1];\n        if (lastBotMsg.textContent.includes('Pensando')) {\n          chatBody.removeChild(lastBotMsg);\n        }\n      }\n    }\n\n    function speakText(text) {\n      const mensaje = new SpeechSynthesisUtterance(text);\n      const voz = voces.find(v => v.lang === 'es-MX') ||\n                  voces.find(v => v.lang === 'es-ES') ||\n                  voces.find(v => v.lang.includes('es'));\n\n      mensaje.voice = voz;\n      mensaje.lang = voz?.lang || 'es-ES';\n      mensaje.rate = 1;\n      mensaje.pitch = 1;\n\n      mensaje.onstart = () => {\n        speaking = true;\n        if (continuousMode) recognition.stop(); \/\/ \ud83d\udd07 Detiene micr\u00f3fono mientras habla\n      };\n\n      mensaje.onend = () => {\n        speaking = false;\n        if (continuousMode) recognition.start(); \/\/ \ud83d\udd01 Retoma la escucha\n      };\n\n      speechSynthesis.speak(mensaje);\n    }\n\n    function probarVoz() {\n      const prueba = new SpeechSynthesisUtterance(\"Hola, soy tu asistente con voz. Estoy listo para ayudarte.\");\n      const voz = voces.find(v => v.lang === 'es-MX') ||\n                  voces.find(v => v.lang === 'es-ES') ||\n                  voces.find(v => v.lang.includes('es'));\n      prueba.voice = voz;\n      prueba.lang = voz?.lang || 'es-ES';\n      prueba.rate = 1;\n      prueba.pitch = 1;\n      speechSynthesis.speak(prueba);\n      setTimeout(() => {\n        if (!speechSynthesis.speaking) {\n          alert(\"\u26a0\ufe0f La voz no se reprodujo. Revisa el navegador o el volumen.\");\n        }\n      }, 2000);\n    }\n\n    micButton.addEventListener('click', () => {\n      recognition.start();\n      micButton.textContent = '\ud83c\udfa7';\n    });\n\n    recognition.onresult = (event) => {\n      const transcript = event.results[0][0].transcript;\n      userInput.value = transcript;\n\n      if (continuousMode) {\n        recognition.stop();\n        sendMessage(transcript);\n      }\n    };\n\n    recognition.onend = () => {\n      if (continuousMode && !speaking) {\n        recognition.start();\n      } else {\n        micButton.textContent = '\ud83c\udf99\ufe0f';\n      }\n    };\n\n    recognition.onerror = (event) => {\n      console.error('Reconocimiento de voz error:', event.error);\n      if (!continuousMode) {\n        micButton.textContent = '\ud83c\udf99\ufe0f';\n      }\n    };\n\n    toggleContinuous.addEventListener('click', () => {\n      continuousMode = !continuousMode;\n      toggleContinuous.textContent = continuousMode ? '\u23f9\ufe0f Detener Conversaci\u00f3n' : '\ud83c\udfa4 Activar Conversaci\u00f3n';\n\n      if (continuousMode) {\n        recognition.continuous = true;\n        recognition.start();\n      } else {\n        recognition.stop();\n        speechSynthesis.cancel(); \/\/ \ud83d\uded1 Detiene la voz del bot si est\u00e1 hablando\n      }\n    });\n\n    userInput.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter') sendMessage();\n    });\n  <\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Neo 2.0 Beta Asistente AI con Voz Continua \ud83e\udd16 Asistente IA con Voz Enviar \ud83c\udf99\ufe0f \ud83d\udd0a Probar Voz \ud83c\udfa4 Activar [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-95","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/pages\/95","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/comments?post=95"}],"version-history":[{"count":72,"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/pages\/95\/revisions"}],"predecessor-version":[{"id":232,"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/pages\/95\/revisions\/232"}],"wp:attachment":[{"href":"https:\/\/neocloud05.com\/neo\/wp-json\/wp\/v2\/media?parent=95"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}