Erol444 / gpt4-openai-api

Python package that provides (unofficial) API access to the GPT-4 through chat.openai.com. Works with langchain. Supports browsing, DALL-E 3, plugins, continuing generation.
162 stars 38 forks source link

Continue Generating #9

Closed shidevil closed 1 year ago

shidevil commented 1 year ago

ChatGPT now allows for continue generating. When the text is way longer.

image

3mora2 commented 1 year ago

in driver.py try replace send_message function

def send_message(self, message: str, html=False, stream: bool = False) -> dict:
    """
    Send a message to ChatGPT\n
    :param message: Message to send
    :param html: return Html response if `True`
    :return: Dictionary with keys `message` and `conversation_id`
    """
    self.logger.debug('Ensuring Cloudflare cookies...')
    self.__ensure_cf()
    # self.__check_blocking_elements()

    # Wait for page to load
    try:
        textbox = WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable(chatgpt_textbox)
        )
    except SeleniumExceptions.ElementClickInterceptedException():
        pass

    self.logger.debug('Sending message...')
    try:
        textbox = WebDriverWait(self.driver, 3).until(
            EC.element_to_be_clickable(chatgpt_textbox)
        )
        textbox.click()
    except SeleniumExceptions.ElementClickInterceptedException():
        self.__check_blocking_elements()
        textbox = WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable(chatgpt_textbox)
        )
        textbox.click()

    self.driver.execute_script(
        '''
    var element = arguments[0], txt = arguments[1];
    element.value += txt;
    element.dispatchEvent(new Event("change"));
    ''',
        textbox,
        message,
    )
    textbox.send_keys(Keys.ENTER)

    if stream:
        for i in self.__stream_message():
            print(i, end='')
            self.__sleep(0.1)
        return print()

    # Check whether GPT is generating the result
    # WebDriverWait(self.driver, 1000).until_not(
    #     EC.invisibility_of_element_located(stop_generating)
    # )

    continue_response = (By.XPATH, "//button[contains(., 'Continue generating')]")
    self.logger.debug('Waiting for completion...')
    while True:
        try:
            WebDriverWait(self.driver, 10).until(
                # When the "Stop generating" button is gone, it means the generation is done
                EC.presence_of_element_located(stop_generating)
            )
            continue

        except (SeleniumExceptions.NoSuchElementException, SeleniumExceptions.TimeoutException):
            self.logger.debug('Stop response button not found!')

        try:
            WebDriverWait(self.driver, 10).until(
                # When the "Continue response" button is available, click it to continue
                EC.element_to_be_clickable(continue_response)
            ).click()
            continue
        except (SeleniumExceptions.NoSuchElementException, SeleniumExceptions.TimeoutException):
            self.logger.debug('Continue response button not found!')
            break

    try:
        WebDriverWait(self.driver, 100).until(
            # When the "Regenerate response" button is available, it means the generation is done
            EC.presence_of_element_located(regenerate_response)
        )
    except SeleniumExceptions.NoSuchElementException:
        self.logger.debug('Regenerate response button not found!')

    self.logger.debug('Getting response...')
    responses = self.driver.find_elements(*chatgpt_big_response)
    if responses:
        response = responses[-1]
        if 'text-red' in response.get_attribute('class'):
            self.logger.debug('Response is an error')
            raise ValueError(response.text)
    response = self.driver.find_elements(*chatgpt_small_response)[-1]
    if html:
        content = response.get_attribute('innerHTML')
    else:
        content = markdownify(response.get_attribute('innerHTML')).replace(
            'Copy code`', '`'
        )

    pattern = re.compile(
        r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
    )
    matches = pattern.search(self.driver.current_url)
    if not matches:
        self.driver.refresh()
        self.__sleep(2)
        # self.__check_blocking_elements()
        self.driver.execute_script("arguments[0].click();", WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable(chatgpt_chats_list_first_node)
        ))
        self.__sleep(2)
        # print(self.driver.current_url)
        matches = pattern.search(self.driver.current_url)

    # get current url and print it
    # print(self.driver.current_url)
    # print(matches)

    conversation_id = matches.group()
    return {'message': content, 'conversation_id': conversation_id}
    # return {'message': content}
shidevil commented 1 year ago

Thanks, seems to be working. you should make a PR :D

Erol444 commented 1 year ago

@shidevil / @3mora2 Could you try with latest version (0.4.0), or perhaps share the prompt with me, so we can add this to the library?

3mora2 commented 1 year ago

self.chatbot = Chatbot({'access_token': self.token, 'model': self.model, 'plugin_ids': self.plugin_ids}, auto_continue=True)

add auto_continue for auto continue long text

Erol444 commented 1 year ago

@3mora2 can you share the prompt that requires auto continue?

3mora2 commented 1 year ago
text = """
I'm suggesting based on commercial and technical information available online for a product with a common name "Stainless Steel Heavy Duty Poultry Shears, Heavy Duty Spring Kitchen Shears for Meat, Poultry, Fish, Seafood Food and Barbecue Shears", with an explanation of what each answer looks like create all output in json:
A - Propose a long commercial name consisting of about 220 characters in the Arabic language, including the name of the store “برايم شوب”, key in json name_ar.
B - An attractive commercial description of the product consisting of about 800 characters in Arabic indicating the name of the store, key in json description_ar.
C - Determine the features of the product in seven points in Arabic, each point of approximately 120 characters, with paragraphs referring to the name of the store as the best supplier for the product, key in json features_ar and they will list type.
d - Mention the most important words of the product, with a maximum of 10 words in Arabic, key in json important_words_ar and they will list type.
E - Propose a long commercial name consisting of about 220 characters in the English language, including the name of the store "Prime.Shop", key in json name_en.
F - An attractive commercial description of the product consisting of about 800 characters in English indicating the name of the store, key in json description_en.
G - Determine the features of the product in seven points in English, each point of approximately 120 characters, with paragraphs referring to the name of the store as the best supplier for the product, key in json features_en and they will list type.
H - Mention the most important words of the product, with a maximum of 10 words in English, key in json important_words_en and they will list type.
"""
Erol444 commented 1 year ago

Hi @3mora2 , thanks for sharing, I'm looking into this..

Erol444 commented 1 year ago

@3mora2 this is now supported. Example here: https://github.com/Erol444/gpt4-openai-api/blob/main/test/test_continue_generating.py