Forum in maintenance, we will back soon 🙂
How to build a tool like CHatPDF
How to build a tool like CHatPDF, which lets the user upload a file and can chat with the same. I would like to know if we can do it on wordpress and make it work like a saas.
@ravi-shekar you could create the frontend side in WordPress but you would need the backend to be a Python API. Have you taken the SaaS course?
Regards,
Earnie Boyd, CEO
Seasoned Solutions Advisor LLC
Schedule 1-on-1 help
Join me on Slack
@ravi-shekar Can you please explain more about what you're looking for, it isn't very clear.
I want to develop a tool that can help students. I should be able to upload pdf/pdfs on to the tool and I can interact with my files, like ask questions on any topic in the pdf and it responds appropriately. Ex. chatpdf.com
@ssadvisor Yes. I have. I have the idea, but I am bit unaware of how to implement it.
@google-ravishekarn You'll need to apply something called RAG (Retrieval-Augmented Generation) which is a technique in natural language processing that combines the retrieval of documents, with an LLM to produce more informative and accurate responses.
So, you can apply it from your code to read the pdfs given and use OpenAI's API to respond to questions based on the pdf.
As @husein mentioned, this is RAG.
You will need to create two functions, one for uploading the PDF and embedding it.
And another one to chat with. I am working on a similar project, I think it will be ready next month
Hi @admin is the similar project ready which you have mentioned in last post, i am also looking to build similar project - where clients can chat with ebooks , take a summary, ask a random chapter i mean there are many possibilities we can explore
@aditya-ganediwal almost done, I will announce it
@admin Hi, i need a small help, can you please provide the css code (updated ui) just for the hook generator so i can reverse eng it and learn with chat gpt to code similar ui for the other tools also - idea is to add as many tools as possible but keep the css, html, script for all page (tool) differently
right now provided css code has many tools included in it. i tried filtering out but failed miserably also tried to ask chat gpt but the code is too long so free version does not allow it - this will help a lot to me with something i want to try 🙂
Thanks
Aditya
@aditya-ganediwal I have the paid version, so i tried to do so using it. Here's the updated CSS script it gave me. So, try it and let me know if it works.
@husein Thanks so much - will update you shortly - also can you please share prompt you use to create this css code - i tried but failed with compiling the prompt itself
Hi, I tried, But is not looking as expected few things still are broken, i am sharing complete css code with the script and ui below - can you please help to fix the things
- generate button is not in blue and at the left side ,(i tried changing flex with space-between to flex end, but it dint work) also the spacing between the button and the container is not there
- result table and its spacing
here is the link how its looking now - https://aitools.gpltube.com/youtube-title-creator/
@admin does the prompt engineering course will help to create such css codes for the tools from the scratch and is it compulsory to have chatgpt pro while using it for coding thing ? anyway will subscribe or a month until the tool website is ready to pro
<style> /* Importing the Google Fonts stylesheet for the Poppins font family */ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"); /* Defining CSS variables */ :root { --lws-blue: #0d2451; --lws-black: #262626; --lws-gray: #757575; --lws-light-blue: #258dc7; --lws-border-radius: 8px; --lws-font-medium: 24px; --lws-font-normal: 18px; --lws-font-small: 14px; } *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "Poppins"; overflow-x: hidden !important; } .lws-tool { color: var(--lws-black); } .tool-container { box-shadow: 2px 2px 20px 2px rgba(0, 0, 0, 0.1); background-color: white; border-radius: var(--lws-border-radius); max-width: 1200px; margin: 2rem auto auto auto; } section { max-width: 1200px; width: 90%; margin: auto; } .lws-tool .counter { font-size: var(--lws-font-small); font-weight: 500; color: rgb(48, 238, 48); margin: 1rem 0; display: none; } .textarea-container { padding: 0.5rem; border: 0px solid var(--lws-gray); border-radius: var(--lws-border-radius); } .content-type-container { margin-top: 1rem; color: var(--lws-black); font-size: var(--lws-font-normal); } .content-types { display: flex; flex-direction: column; gap: 0.5rem; } .selected-type { font-weight: 500; color: var(--lws-blue); } .list { display: none; position: absolute; background-color: white; box-shadow: 0 2px 5px rgba(0,0,0,0.2); width: 100%; z-index: 10; padding: 0.5rem; } .popup { background: rgba(0, 0, 0, 0.5); width: 100vw; height: 100vh; position: fixed; display: flex; justify-content: center; align-items: center; text-align: center; display: none; top: 0; left: 0; right: 0; z-index: 9999; } /* Importing the Google Fonts stylesheet for the Poppins font family */ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"); /* Defining CSS variables */ :root { --lws-blue: #0d2451; --lws-black: #262626; --lws-gray: #757575; --lws-light-blue: #258dc7; --lws-border-radius: 8px; --lws-font-medium: 24px; --lws-font-normal: 18px; --lws-font-small: 14px; } *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "Poppins"; overflow-x: hidden !important; } .lws-tool { color: var(--lws-black); } .tool-container { box-shadow: 2px 2px 20px 2px rgba(0, 0, 0, 0.1); background-color: white; border-radius: var(--lws-border-radius); max-width: 1200px; margin: 2rem auto auto auto; } section { max-width: 1200px; width: 90%; margin: auto; } .flex-justify { display: flex; justify-content: space-between; gap: 1rem; } .flex-center { display: flex; align-items: center; gap: 1rem; } .lws-tool .counter { font-size: var(--lws-font-small); font-weight: 500; color: rgb(48, 238, 48); margin: 1rem 0; display: none; } .textarea-container { padding: 0.5rem; border: 1px solid var(--lws-gray); border-radius: var(--lws-border-radius); } .content-type-container { margin-top: 1rem; color: var(--lws-black); font-size: var(--lws-font-normal); } .content-types { display: flex; flex-direction: column; gap: 0.5rem; } .selected-type { font-weight: 500; color: var(--lws-blue); } .list { display: none; position: absolute; background-color: white; box-shadow: 0 2px 5px rgba(0,0,0,0.2); width: 100%; z-index: 10; padding: 0.5rem; } .popup { background: rgba(0, 0, 0, 0.5); width: 100vw; height: 100vh; position: fixed; display: flex; justify-content: center; align-items: center; text-align: center; display: none; top: 0; left: 0; right: 0; z-index: 9999; } @media (max-width: 920px) { section { width: 95%; } } .placeholder-container img { max-width: 180px; margin-top: 1rem; } .lws-tool-copy-icon { position: relative; } .lws-tool .copy-alert { position: absolute; font-size: 14px; top: -20px; font-weight: 400; display: none; font-weight: 600; font-size: 12px; background: white; padding: 0.5rem 1rem; box-shadow: 2px 2px 20px 2px rgba(0, 0, 0, 0.1); color: #353535 !important; } .sub-line .tool-container, .hook-generator .tool-container, .content-idea .tool-container, .keyword-difficulty .tool-container, .web-management .tool-container{ padding: 1.5rem 1.2rem; } .sub-line input, .hook-generator .textarea-container, .content-idea input, .keyword-difficulty input, .web-management input { border: 2px solid rgba(0, 0, 0, 0.2); } .sub-line input:hover, .hook-generator .textarea-container:hover, .hook-generator .content-types:hover .content-idea input:hover, .keyword-difficulty input:hover, .web-management input:hover { border: 2px solid rgba(0, 0, 0, 0.4); } .sub-line input:focus, .content-idea input:focus, .keyword-difficulty input:focus, .web-management input:focus{ border: 2px solid var(--lws-blue) !important; } .sub-line input, .sub-line button, .hook-generator input, .hook-generator button, .content-idea input, .content-idea button, .keyword-difficulty input, .keyword-difficulty button, .web-management button{ border-radius: 0; } .sub-line .loading, .content-idea .loading, .hook-generator .loading, .keyword-difficulty .loading, .web-management .loading { box-shadow: none; color: rgba(0, 0, 0, 0.7); max-height: 300px; } .sub-line .lws-tool-result, .keyword-difficulty .lws-tool-result, .content-idea .lws-tool-result{ margin-top: 4rem; } .sub-line .box { padding: 2rem 1.5rem; } .sub-line .box .flex-center, .sub-line .box .flex { gap: 6%; } .sub-line .score, .sub-line .emojis { color: #65B733; font-size: 56px; font-weight: 600; display: flex; justify-content: center; align-items: center; width: 20%; border-right: 1px solid #d9d9d9; } .sub-line .all-caps-words { font-size: 18px; font-weight: 500; width: calc(20% + 56px); } .sub-line .emojis { border: none; } .sub-line .emojis img { width: 125px; } .sub-line .box-title { color: var(--lws-black); font-size: 28px; font-weight: 500; } .sub-line .scorebar-container { position: relative; background: rgba(0, 0, 0, 0.1); width: 100%; height: 10px; border-radius: 50px; margin-top: 2rem; overflow: hidden; margin-bottom: 0.3rem; } .sub-line .scorebar { background: #B83830; height: 10px; border-radius: 50px; width: 0%; transition: all 3s ease-in-out; } .sub-line .score-num { justify-content: space-between; display: flex; color: rgba(0, 0, 0, 0.7); font-size: 14px; } .sub-line .tone { padding: 1rem; color: rgb(255, 166, 0); background: rgb(255, 235, 197); font-size: 32px; } .sub-line .p-tone{ color: #65b733; background: rgb(209, 255, 209); } .sub-line .n-tone{ color: #B83830; background: #ffbfba; } .sub-line ul>li { font-weight: 500; font-size: 18px; display: flex; gap: 1rem; align-items: center; } .sub-line ul div { background: #B83830; width: 8px; height: 8px; } .sub-line .impact { padding: 4px 20px; border-radius: 8px; background: #C4D8FF; color: rgba(32, 84, 187, 1); font-size: 12px; font-weight: 500; margin-bottom: 0.5rem; width: fit-content; } .sub-line .alt-sub-lines, .sub-lines { padding: 0 1.5rem !important; } .sub-line .alt-sub-lines>div, .sub-lines>div { font-size: 18px; font-weight: 500; margin-top: 1rem; } .sub-line .alt-sub-lines>div div, .sub-lines>div div{ color: rgba(0, 0, 0, 0.7); font-size: 14px; margin-top: 0.5rem; padding-bottom: 1rem; border-bottom: 1px solid #d9d9d9; } .sub-line .sub-copy-alert, .lws-tool .sub-copy-alert{ top: -0.4rem; left: 78px; font-weight: 600; font-size: 12px; background: white; padding: 0.5rem 1rem; box-shadow: 2px 2px 20px 2px rgba(0, 0, 0, 0.1); position: absolute; display: none; color: #353535 !important; } .hook-generator .btn-container{ margin-top: 1rem; display: flex; justify-content: flex-end;} .hook-generator textarea{ border: none; outline: none; resize: none; padding: 0.8rem; font-family: 'Poppins'; font-size: 16px; font-weight: 400; display: block; } .hook-generator .counter{ margin: 4px 0 -0.5rem 0; font-size: 12px; } .hook-generator .textarea-container:focus-within { border: 2px solid var(--lws-blue); } .hook-generator .content-type-container>p{ color: rgba(0, 0, 0, 0.3); font-size: 12px; font-weight: 500; } .hook-generator .content-types{ position: relative; border: 2px solid rgba(0, 0, 0, 0.2); margin-top: 6px; padding: 6px 10px; cursor: pointer; } .hook-generator .selected-type{ font-size: 14px; font-weight: 500; } .hook-generator .list{ position: absolute; background: white; z-index: 1; padding: 6px 0; width: 200px; left: 0; top: 2.5rem; font-size: 14px; font-weight: 500; display: none; box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; } .hook-generator .list>p{ padding: 6px 10px; cursor: pointer; } .hook-generator .list>p:hover{ background: rgb(240, 240, 240); } .hook-generator .generated-hooks{ padding: 0 1rem; } .hook-generator .generated-hooks>div{ margin-top: 1rem; padding-bottom: 1rem; border-bottom: 1px solid #d9d9d9; } .hook-generator .hook-type{ font-weight: 600; font-size: 14px; margin-bottom: 4px; } .hook-generator .copy-icon{ font-size: 14px; opacity: 0.9; margin-top: 4px; } @media (max-width: 920px) { section { width: 95%; } } </style> <main class="lws-tool"> <div class="popup"></div> <section class="hook-generator"> <div class="tool-container"> <div> <form onsubmit="onFormSubmit(event)"> <div> <div class="textarea-container"> <textarea required name="hook-topic" rows="2" oninput="handleInputChange(event)" placeholder='Describe your next idea briefly'></textarea> </div> <p class="counter">1 / 150</p> <button disabled type="submit">Generate</button> </div> </div> </form> </div> <div class="tool-container loading"> </div> <div class="lws-tool-result" style="display: block;"> </div> </div> </section> </main> <script> const button = document.querySelector(".hook-generator").querySelector('button'); const loading = document.querySelector(".loading"); const result = document.querySelector(".lws-tool-result"); const popup = document.querySelector(".popup"); const selectedType = document.querySelector(".selected-type"); const list = document.querySelector(".list"); const counter = document.querySelector(".counter"); let inputVal = '' let popupClose = ""; let balanceElem = ""; let response = ""; let data = ""; let copyAll = ""; let contentType = "Short Video"; let emoji = [] const API_BASE_URL = "https://aitools.gpltube.com/wp-admin/admin-ajax.php"; const loadingTemplate = `<div> <p>Generating Hooks...</p> </div>`; // Handle Form Submit function onFormSubmit(event) { event.preventDefault(); button.disabled = true; emoji = []; copyAll = "" response = ""; loading.innerHTML = loadingTemplate; result.innerHTML = ""; result.style.display = "none"; loading.style.display = "flex"; var formData = new FormData(); formData.append("action", "openai_generate_text_basic"); formData.append("topic", inputVal); formData.append("usage", contentType); console.log(inputVal, contentType, "to be fetched") fetchData(formData); } // Data Fetching async function fetchData(formData) { try { response = await fetch(`${API_BASE_URL}`, { method: "POST", body: formData, }); if (response.ok) { data = await response.json(); console.log("Data from Api", data); button.disabled = false; loading.style.display = "none"; result.style.display = "block"; if (data == "LOGIN_FIRST") { loginPopup(); return; } else if (data == "NO_BALANCE") { noBalPopup(); return; } data = JSON.parse(data); showResultUI(data); } else { button.disabled = false throw new Error("Request failed. Please try again!"); } } catch (error) { button.disabled = false console.error("Error occurred:", error); loading.innerHTML = ` <div class="error-msg"> <img src="https://tools-backend.learnwithhasan.com/assets/images/error-img.png" alt="Error"> <p class="text-medium">Uh Oh!</p> <p>Something went wrong! Please try again</p> </div>`; return; } } // Result UI function showResultUI(data) { data.map((item) => { copyAll += item.hook + '\n'; if (item.hook_type.includes("Strong")) { emoji.push('💪'); } else if (item.hook_type.includes("Intriguing")) { emoji.push('🤔'); } else if (item.hook_type.includes("Fact")) { emoji.push('📚'); } else if (item.hook_type.includes("Metaphor")) { emoji.push('🌈'); } else if (item.hook_type.includes("Story")) { emoji.push('📜'); } else if (item.hook_type.includes("Statistical")) { emoji.push('📈'); } else if (item.hook_type.includes("Quotation")) { emoji.push('💬'); } else if (item.hook_type.includes("Challenge")) { emoji.push('🏋️♂️'); } else if (item.hook_type.includes("Visual")) { emoji.push('👀'); } else if (item.hook_type.includes("Action")) { emoji.push('🏃♂️'); } else if (item.hook_type.includes("Historical")) { emoji.push('✍🏻'); } else if (item.hook_type.includes("Anecdotal")) { emoji.push('😄'); } else if (item.hook_type.includes("Humorous")) { emoji.push('😂'); } else if (item.hook_type.includes("Controversial")) { emoji.push('🤷♂️'); } else if (item.hook_type.includes("Rhetorical")) { emoji.push('❓'); } else { emoji.push(''); } }) result.insertAdjacentHTML("beforeend", ` <div class="mt-48"> <p class="result-title mtb-18">Hooks Generated</p> <div class="border box generated-hooks"> ${data.map((item, index) => ( ` <div class="relative"> <p class="hook-type">${emoji[index]} ${item.hook_type}</p> <p>${item.hook}</p> <div class="copy-icon relative" onclick="copyToClipboard('${index}')"> <p class="sub-copy-alert">Copied</p> <i class="fa-regular fa-copy"></i> <span> Copy</span> </div> </div> ` )).join("") } <p class="copy-all" onclick="copyToClipboard('All')">Copy all</p> </div> </div> `); } // Handle Input function handleInputChange(event) { inputVal = event.target.value.trim(); const maxLength = 150; if (inputVal.length !== 0) { button.disabled = false; } else { button.disabled = true; } counter.style.display = "block"; if (inputVal.length > maxLength) { event.target.value = inputVal.substring(0, maxLength); inputVal = event.target.value.trim(); } const charCount = inputVal.length; counter.textContent = `${charCount} / ${maxLength}`; } // Copy function copyToClipboard(index) { let copy = "" const copyAllElem = document.querySelector(".copy-all"); copy = data[index]?.hook; console.log(copy, index) if (index == 'All') { copy = copyAll; copyAllElem.innerHTML = "Copied All"; setTimeout(() => { copyAllElem.innerHTML = "Copy all"; }, 2000); } const tempTextarea = document.createElement("textarea"); tempTextarea.value = copy; document.body.appendChild(tempTextarea); tempTextarea.select(); tempTextarea.setSelectionRange(0, 99999); document.execCommand("copy"); document.body.removeChild(tempTextarea); const copyAlerts = document.getElementsByClassName("sub-copy-alert"); if (index != 'All') { copyAlerts[index].style.display = "block"; setTimeout(() => { copyAlerts[index].style.display = "none"; }, 2000); } } // Handle Content Type DropDown function handleDropDownClick() { console.log("clicked") list.classList.toggle("active"); } // Handle Content Type Selection function handleContentTypeSelection(event) { console.log(event.target.innerText); contentType = event.target.innerText; selectedType.innerText = contentType; list.classList.toggle("active") } function loginPopup() { popup.innerHTML = ` <div class='popup-container'> <i class="close fa-solid fa-xmark"></i> <div><img src="no-access.png" alt="Login Error"></div> <p>You need to login first!</p> <a target="_blank" href="https://learnwithhasan.com/user-login">Login</a> </div> `; popup.style.display = "flex"; popupClose = document.querySelector(".close"); document .querySelector(".popup") .addEventListener("click", function (event) { if ( event.target === this || event.target.contains(popupClose) ) { this.style.display = "none"; } }); } function noBalPopup() { popup.innerHTML = ` <div class='popup-container'> <i class="close fa-solid fa-xmark"></i> <div><img src="no-balance.png" alt="Balance Error"></div> <p>Not Enough Power Points!</p> <a target="_blank" href="https://learnwithhasan.com/points-system">Recharge Me</a> </div> `; popup.style.display = "flex"; popupClose = document.querySelector(".close"); document .querySelector(".popup") .addEventListener("click", function (event) { if ( event.target === this || event.target.contains(popupClose) ) { this.style.display = "none"; } }); } </script>
Posted by: @husein@aditya-ganediwal I have the paid version, so i tried to do so using it. Here's the updated CSS script it gave me. So, try it and let me know if it works.
-- attachment is not available --
@huseinhusein - Hi, sharing the updated code file please check this - i have extracted few more css code from the original one and added - i just wanted single input container - keyword counter, generate button and the result table an as for many of my prompt tool this code i can use it easily please guide updated
@aditya-ganediwal I didnt use a one-shot prompt and kept asking the model to update the CSS to my liking, but i didn't try it myself.
Since it didn't work, I'll try another prompt and share the new CSS code.
In addition, please, when you want to attach long codes, don't attach them as you did before; instead, use the "Attach Files" button.