tinymce / tinymce-react

Offical TinyMCE React component
MIT License
938 stars 151 forks source link

How would I change the following code to take the text from TinyMCE editor, and add the formatted GPT3 output into the same TinyMCE editor instead of an `<input></input>` box? #421

Closed NorkzYT closed 1 year ago

NorkzYT commented 1 year ago
  How would I change the following code to take the text from TinyMCE editor, and add the formatted GPT3 output into the same TinyMCE editor instead of an `<input></input>` box?

I could not come up with or find a solution to this for the past week, and any help would be much appreciated.

For reproduction, the following link contains the GitHub repository. https://github.com/harish-garg/nextjs-reactjs-gpt-3/blob/main/pages/index.js

import Head from "next/head";
import styles from "../styles/Home.module.css";
import { useState, useEffect } from 'react';

export default function Home() {
  const [data, setData] = useState( { text:'' });
  const [query, setQuery] = useState();
  const [search, setSearch] = useState();
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      if (search) {
      setIsLoading(true);
      const res = await fetch(`/api/openai`, {
        body: JSON.stringify({
          name: search
        }),
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'POST'
      })
      const data = await res.json();
      setData(data);
      setIsLoading(false);
    }};

    fetchData();
  }, [search]);
  return (
    <div className={styles.container}>
      <Head>
        <title>GPT-3 App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          <a>AI Lyrics Generator</a>
        </h1>

        <p className={styles.description}>Built with NextJS & GPT-3 API</p>

        <div className={styles.grid}>
          <div className={styles.card}>
            <h3>Enter Artist:</h3>
            <input
          type="text"
          value={query}
          onChange={event => setQuery(event.target.value)}
        />
        <button
          type="button"
          onClick={() =>
            setSearch(query)
          }
        >
          Generate
        </button>

          <h4>Lyrics</h4>  
          {isLoading ? (
            <div>Loading ...</div>
         ) : (
           <span>
           {data.text}
           </span>
           )}

          </div>
        </div>
      </main>
    </div>
  );
}

I made the following function to activate when a button is clicked, and <input></input> box contains the input content, in which GPT3 output goes into the TinyMCE editor only after clicking the button twice which is not something I want. It would be best to have the output appear after GPT3 outputs which could take a couple of seconds depending on how big the input was.

   function generateResponse() {
    setSearch(query);
    openai_content(data.text);
  }

  async function openai_content() {
    await tinymce.activeEditor.setContent(
      tinymce.activeEditor.getContent() + data.text,
    );
  }

I could always add the following wait function, but that is not what is needed, something like a isLoading ? would be better.

   function wait(milliseconds) {
    const date = Date.now();
    let currentDate = null;
    do {
      currentDate = Date.now();
    } while (currentDate - date < milliseconds);
  }

When outputting the GPT3 output into the tinymce editor, the format in which the output was in, is removed which I do not know how to fix it, although when it is outputted into a <input></input> box, the format stays the same.

E.g.

Incorrect format put into TinyMCE Editor.

Hello,Are there any spots left? My son was able to secure a grant through his school for the program. I need to know the exact total and how to pay for it Jane

Correct format that is put into the <input></input> box.

Hello,

Are there any spots left? My son was able to secure a grant through his school for the program. I need to know the exact total and how to pay for it 

Jane

Originally posted by @NorkzYT in https://github.com/tinymce/tinymce-react/discussions/420

exalate-issue-sync[bot] commented 1 year ago

Ref: INT-3073

yacodes commented 1 year ago

@NorkzYT Thanks for taking interest in Tiny editor. However it is not exactly clear how your problem relates to this repository. Please, provide a minimal example of the issue at codepen or a similar service.

NorkzYT commented 1 year ago

@yacodes

Here you go mate. As to what I want to do, I want to have the output of the GPT-3 API to go inside of the TinyMCE editor once I click on the Generate button.

https://codesandbox.io/p/github/NorkzYT/NextjsTinyMCEGPT3

NorkzYT commented 1 year ago

The following code would output the GPT3-API into the TinyMCE editor when I click on the button at least 3 times or more, and it goes into the TinyMCE editor with the wrong format as well, there is no indentation, and all the text is close together.

How would I fix this issue?

  function generateResponse() {
    const generatedText = setSearch(query);
    openai_content(generatedText);
  }

  async function openai_content() {
    tinymce.activeEditor.setContent(
      tinymce.activeEditor.getContent() + data.text,
    );
  }
          <button className="generatebtn" onClick={generateResponse}>
            Generate
          </button>
yacodes commented 1 year ago

@NorkzYT Please try passing an additional format parameter to the getContent function.

tinymce.activeEditor.getContent({ format: "text" }); // raw | text | html | tree

This may help.

I will close this issue though, because it has nothing to do with the React integration.

NorkzYT commented 1 year ago

Understood, thank you for your help. I will post a solution here once I make this work.

NorkzYT commented 1 year ago

Solution:

const query = "I am a professional";

var response = "";
var gen1 = "";

function gen() {
  openai(query);
}

async function openai() {
  // Promt values
  const beforePrompt = `\n Give a prompt:`;
  const endPrompt = `Profesional`;
  const breakPoint = `\n\n'''\n\n`;
  const randomUUID = uuidv4().toString();

  // Construct the prompt
  let prompt;

  prompt = `${randomUUID} ${beforePrompt} ${breakPoint} ${query} ${breakPoint} ${endPrompt} ${breakPoint}`;

  var model = "https://api.openai.com/v1/completions";
  var xhr = new XMLHttpRequest();
  xhr.open("POST", model);

  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.setRequestHeader("Authorization", `Bearer ${API_TOKEN}`);

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      response = xhr.response;
      gen1 = response
        .split('{"text":"')[1]
        .split('","index"')[0]
        .split("\\n")
        .join("<br />");
      setIsLoading(false);
      tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + gen1);
    }
  };

  var data = JSON.stringify({
    prompt: `${prompt}`,
    model: "text-davinci-003",
    temperature: 0.6,
    max_tokens: 400,
    top_p: 1,
    frequency_penalty: 0,
    presence_penalty: 0,
  });

  xhr.send(data);
}