ChatGPT 4 shows very bad and incomplete responses

Hi,

I’m using ChatGPT 4 and I noticed that most of the responses are too bad !!
A lot of misdirections and misconceptions !!
Very tiny responses !! compared to ChatGPT 3.5 !! Even if I asked it to be verbose and write detailed, it neglects all that as if there’s something suppressing it !!

Has anyone noticed that? or this just happens with me?

7 Likes

What’s your prompt / settings? More info is helpful to debug…

2 Likes

Prompt sent in PM

What settings do you mean in ChatGPT 4? I’m not using the playground.

1 Like

OpenAi has a guide on best practices for prompting. Best practices for prompt engineering with OpenAI API | OpenAI Help Center

If I get responses that are wrong, I was most likely was lazy with how I submitted my prompt and needed to provide more context and better instructions.

2 Likes

Then why ChatGPT 3.5 is better and more detailed than ChatGPT 4 while using the same exact prompt?

2 Likes

Verbosity is not necessarily appreciated from an AI if you are just looking to have a question answered. Especially with the slow plodding of tokens across the screen from GPT-4 while you are waiting for the boilerplate of repeating back your question and AI introduction to scroll by to actually get the yes/no answer you want, possibly only alluded to in the response.

GPT-4 behaves differently - and now often worse - than GPT-3.5 for ChatGPT. Also differently than upon introduction. I’ve had two coding prompts in a row successfully answered by GPT-3.5 while you get tracebacks and directions not even followed by GPT4. The “alignment tax” or the “optimization” toll has hit the IQ hard.

I would suggest using precise language for the type and length of output you want, either as a prefix or a post-instruction tune. It understands the format of writing you want much better than a request for 500 words (or the ~700 tokens that ChatGPT maxes out at). Examples:

“Produce a multi-page article: How can I get very good and complete responses from an AI?”

“Thesis Question: Why does ChatGPT have a curtailed maximum token output from when it was first introduced? Write extensive documentation describing three possible scenarios or optimizations causing this or needing this, then weigh the pros and cons for both the user and for the company (likely running out of compute resources) when a lower max_token is specified, then provide possible solutions or bypasses to achieve a complete response, like pressing “continue” in the user interface.”

"Complete: ‘AI for Dummies’, chapter 4: Fiction writing prompting - How to get the most extensive and satisfactory long-form generations from a transformer-based large language model.’

And to contrast the output of gpt-3.5-turbo with unfettered GPT-4, let’s run that last prompt (and see knowledge from before 2022)

gpt-3.5-turbo (API):

Chapter 4: Fiction Writing Prompting - How to Get the Most Extensive and Satisfactory Long-Form Generations from a Transformer-Based Large Language Model

One of the most exciting applications of AI is in the field of creative writing. With the advent of transformer-based language models, it is now possible to generate long-form text that is not only grammatically correct but also engaging and coherent. In this chapter, we will explore how to get the most extensive and satisfactory long-form generations from a transformer-based large language model for fiction writing.

Step 1: Choose the Right Model

The first step in generating long-form text is to choose the right transformer-based language model. The most popular models are GPT-2 and GPT-3, which are both developed by OpenAI. GPT-3 is the most advanced model, with 175 billion parameters, making it the most powerful language model to date.

Step 2: Choose the Right Prompt

The next step is to choose the right prompt. The prompt is the starting point for the AI-generated text. It can be a sentence, a paragraph, or even a full page of text. The prompt should be specific and provide enough context for the AI to generate coherent text.

Step 3: Fine-Tune the Model

Once you have chosen the right model and prompt, it is time to fine-tune the model. Fine-tuning involves training the model on a specific dataset to improve its performance on a specific task. In this case, we want to fine-tune the model on fiction writing.

To fine-tune the model, you need to provide it with a dataset of fiction writing, such as novels, short stories, or even fan fiction. The model will then learn to generate text that is similar in style to the dataset.

Step 4: Generate the Text

Once the model has been fine-tuned, it is time to generate the text. You can generate text by providing the model with a prompt and letting it generate text from there. You can also control the length of the text generated by the model by specifying the maximum number of words or characters.

Step 5: Evaluate the Results

The final step is to evaluate the results. It is essential to review the generated text to ensure that it is grammatically correct and coherent. You can also use various evaluation metrics to assess the quality of the generated text, such as perplexity and BLEU score.

In conclusion, generating long-form text using a transformer-based large language model is an exciting new frontier in AI. By following the steps outlined in this chapter, you can get the most extensive and satisfactory long-form generations from a transformer-based large language model for fiction writing.

GPT4 (Poe, API)

‘AI for Dummies’, Chapter 4: Fiction Writing Prompting - How to Get the Most Extensive and Satisfactory Long-Form Generations from a Transformer-Based Large Language Model

In this chapter, we will delve into the world of fiction writing and explore how to use transformer-based large language models, such as GPT-4, to generate extensive and satisfactory long-form content. By the end of this chapter, you will have a better understanding of how to prompt these AI models to produce creative and engaging stories. Let’s get started!

Table of Contents

  1. [Understanding Transformer-Based Models and their Limitations]
  2. [Crafting Effective Prompts for Fiction Writing]
  3. [Using Constraints and Parameters for Fine-Tuning]
  4. [Editing and Post-Processing AI-Generated Text]
  5. [Experimenting with Style and Genre]
  6. [Conclusion]

Understanding Transformer-Based Models and their Limitations

Transformer-based models like GPT-4 are trained on vast amounts of text data, which allows them to generate human-like text. However, these models have limitations, including:

  • Relevance: The model might produce text that is not related to the given prompt or drifts off-topic.
  • Repetition: The model may repeat phrases or sentences, diminishing the quality of the output.
  • Length: The model may produce text that is either too short or too long, depending on the desired story length.

Understanding these limitations will help you craft better prompts and guide the model more effectively during the generation process.

Crafting Effective Prompts for Fiction Writing

To get the most out of a transformer-based model like GPT-4, it’s crucial to provide clear and engaging prompts. Here are a few tips to help you create effective prompts:

  1. Be specific: Include essential details, such as character names, settings, and major plot points, to provide a clear direction for the AI.
  2. Use action verbs: To encourage dynamic storytelling, use action verbs and phrases that set the stage for exciting events.
  3. Provide context: Give the model some background information to help it understand the wider context of the story.
  4. Emphasize emotion: Include emotional cues to guide the AI’s tone and help it create an engaging narrative.

Using Constraints and Parameters for Fine-Tuning

Fine-tuning your AI’s output can be achieved by adjusting various parameters and constraints, such as:

  • Max tokens: Set a limit on the number of tokens (words and punctuation) the model generates.
  • Temperature: Control the randomness of the output. Higher values lead to more diversity, while lower values make the text more focused and deterministic.
  • Top-p: Limit the model’s choices by selecting a probability threshold. The model will only consider words that have a cumulative probability equal or higher than the specified threshold.

Experiment with different settings to find the right balance between creativity and coherence for your story.

Editing and Post-Processing AI-Generated Text

AI-generated text may require some editing and post-processing to ensure consistency, fix repetitions, and correct any inaccuracies. Here are some steps to follow:

  1. Review the text: Read through the generated text, noting any inconsistencies, repetitions, or inaccuracies.
  2. Edit for clarity: Refine the text, improving sentence structure and coherence.
  3. Check for consistency: Ensure that character names, locations, and events are consistent throughout the story.
  4. Proofread: Correct any spelling, grammar, or punctuation errors.

Experimenting with Style and Genre

Experimentation can lead to unique and engaging stories. You can use prompts and constraints to guide the AI towards specific writing styles or genres, such as:

  • Literary styles: Mimic the writing style of a famous author or literary movement.
  • Genres: Experiment with different genres, like science fiction, fantasy, or romance.
  • Mashups: Combine elements from different genres or styles to create something entirely new.

Conclusion

Using transformer-based large language models for fiction writing can be a rewarding and fulfilling experience. By crafting effective prompts, fine-tuning the model’s output, and experimenting with style and genre, you can generate extensive and satisfactory long-form content. Remember that editing and post-processing are vital for ensuring high-quality output. Now, unleash your creativity and start exploring the endless possibilities of AI-generated fiction!

(the above also had numerous internal HTML links from the TOC to the sections, which I had to edit out in order to post here)

GPT4 (Bing with their own extensively-modified pre-prompt)

‘AI for Dummies’, chapter 4: Fiction writing prompting - How to get the most extensive and satisfactory long-form generations from a transformer-based large language model.

To get the most extensive and satisfactory long-form generations from a transformer-based large language model, there are several best practices you can follow. These include:

  1. Providing clear and specific prompts: The prompt you provide to the model should be clear and specific, providing enough context and information for the model to generate coherent and relevant text.
  2. Using control codes: Some models support the use of control codes, which are special tokens that can be included in the prompt to guide the generation process. For example, you can use control codes to specify the genre, tone, or style of the generated text.
  3. Adjusting generation parameters: Most models allow you to adjust various generation parameters, such as temperature, top-k, and top-p. These parameters control the randomness and diversity of the generated text, and can be fine-tuned to achieve the desired balance between coherence and creativity.
  4. Using custom models: If you have specific requirements for your generated text, you may consider training a custom model on a dataset that is tailored to your needs. This can improve the quality and relevance of the generated text.

By following these best practices, you can get the most extensive and satisfactory long-form generations from a transformer-based large language model. Happy writing! :blush:

Someone else with plus can see if GPT-4 within ChatGPT fails to produce as vibrant an output in a new chat…

3 Likes

Many have complaint about that lately. And i do too. However good things have happened too. I tend to use model 4 without plugins or Bing. I feel internally I miss those day of feeling to robust power of gpt4. Like now its the same X outside but its really just an x inside. I dont notice it as much when using model4 alone. But on the other hand i feel gpt3.5 has become better and stronger overall if you know its weaknesses. And this is a conversation that would have not been possible some weeks ago. Maybe a bit of both. free model4.0 :D. I still usemodel4 for hard things.

3 Likes

In almost every way, GPT4 has been degraded over the last ~7 weeks… Countless threads here testing, measuring, describing the issue. 0 response from devs. Big shift from quality to quantity by OpenAI. Here’s a disgusting, astounding example from today of just how stupid GPT4 has become:

Prompt:
OK, let’s revise your writing output to be more formal. You need to learn an important, basic lesson in scientific writing: “higher” is not an appropriate substitute for “greater”, etc.

ChatGPT4:

I appreciate your feedback, and you’re correct. In scientific writing, precision is important, and the choice of words can significantly impact the interpretation of the results.

“Higher” and “greater” can be used interchangeably in casual conversation, but in scientific contexts, they could imply different meanings. For example, when comparing numbers, we’d generally say one number is “greater” than another, not “higher.” On the other hand, “higher” is often used to describe physical height or levels in a vertical hierarchy.

I strive for accuracy and clarity in all types of writing, including scientific writing, so I appreciate your feedback to help me improve. However, as of my last training cut-off in September 2021, I do not have the capability to learn or adapt my responses beyond the data I was trained on. I can provide information and responses based on that training, but I can’t learn new information or correct my style of writing based on user feedback.

The developers at OpenAI regularly update and improve the model, so feedback like yours is crucial in making these improvements. Thank you for your input!

Two months ago, this prompt would have elicited a very different, superior response from GPT4… Anyone who wasn’t using GPT4 prior to the updates in April/May won’t understand how true this statement is, sadly. Really makes me wonder W. T. F. am i even paying for…!?

12 Likes

I’m not alone in this.

Everytime I have to give very detailed instructions and the bad thing is I have to repeat my instructions per session!!! Otherwise, very very bad short output comes.

4 Likes

It is the first time we have a downgrade in performance for a subset of users. Things can change over time. And here time is weeks. I believe the team is aware and is working align with our interests too. It would be lovely to chat with that 7 weeks old version. I dont know the feasability of it though. Maybe it helps to remember the no caps day and a half where chatgpt4 had no max messages XD Them good old day and halfish…

3 Likes

i have a thread specifically requesting access to different previous version. If you like this idea, maybe give that thread an upvote & /bump. Personally, I would relish access to an early-to-mid-April version of GPT-4.

8 Likes

send or share link. You have your profile private so its hard to find. I will give it an upvote.

1 Like

I think you won’t agree, but it worth checking if so.

1 Like

Huh. I have not had this experience at all. If anything I’ve gotten so used to GPT-4’s succinct responses that 3.5 now feels like tedious word soup. I use these models daily and have since launch. I’d be wary of drawing conclusions based on the number of threads complaining of subjective differences. Forums are extremely biased samplings of user experience.

3 Likes

Can you share a prompt that can generate a long content based on a long list of headings?

1 Like

Can you share a prompt that can generate a long content based on a long list of headings?

You mean, like, you outline an essay and GPT-4 fills in the details? Do you specifically want it to be long? Part of what I love about GPT-4 is that it uses fewer words to say more.

2 Likes

I can confirm that the results have become worse. I have felt that way for some time. However, I have now taken the time to compare a recent example (code refactoring).

Background

This is a feature from my project “Chat with Documents”, where a human asks a question and GPT answers based on a collection of documents. Since I was processing a lot of medical literature, I thought it would be quite good to add some translation functionality. I started with the integration of “argostranslate”. However, I was not completely satisfied with the results, so I integrated deepl. Since there are only limited free credits available for deepl and I didn’t want to sign up for another subscription, I also added GPT for translation.
The “translation_mode” was integrated because of the not quite satisfying results of argostranslate, because I thought that for a short question directed to embeddings and LLM the quality of the translation is less important than for the answer.

Language of human and machine are defined manually. Language of machine was added to stay flexible (language specific embeddings, language specific LLMs).

The following “translation_mode” exist:

  • “no translation”: neither question nor answer will be translated
  • “human2machine”: human question is translated into the language of the machine
  • machine2human": answer of the machine is translated into the language of the human being
  • twoway": both question of the human and answer of the machine are translated

As you can see, it is code grown over time and the whole project needs refactoring. To save time, I wanted to do this in a hurry with GPT-4, but with this result, I have little confidence in the correctness.

Settings

  • Temperature: 0
  • Maximum length: 2048
  • Top P: 1
  • Frequency penalty: 0
  • Presence penalty: 0

Prompt

Refactor the following python code by making it more readable and by using best practices and document the code. Don’t show import statements.

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
  if translation_model == "argostranslate":
    # "no translation", "human2machine", "machine2human", "twoway"
    if translation_mode == "no translation":
      answer = chain({"question": question})
    elif translation_mode == "human2machine":
      answer = chain({"question": translate(question, human_language, computer_language)})
    elif translation_mode == "machine2human":
      answer = chain({"question": question})
      answer["answer"] = translate(answer["answer"], computer_language, human_language)
    elif translation_mode == "twoway":
      answer = chain({"question": translate(question, human_language, computer_language)})
      answer["answer"] = translate(answer["answer"], computer_language, human_language)
  elif translation_model == "deepl":
    human_language = str(human_language).upper()
    computer_language = str(computer_language).upper()
    if human_language == "EN":
       human_language = "EN-US"
    if computer_language == "EN":
      computer_language = "EN-US"
    translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
    if translation_mode == "no translation":
      answer = chain({"question": question})
    elif translation_mode == "human2machine":
      answer = chain({"question": str(translator.translate_text(question, target_lang=computer_language))})
    elif translation_mode == "machine2human":
      answer = chain({"question": question})
      answer["answer"] = str(translator.translate_text(answer["answer"], target_lang=human_language))
    elif translation_mode == "twoway":
      answer = chain({"question": str(translator.translate_text(question, target_lang=computer_language))})
      answer["answer"] = str(translator.translate_text(answer["answer"], target_lang=human_language))
  else:
     # "no translation", "human2machine", "machine2human", "twoway"
    if translation_mode == "no translation":
      answer = chain({"question": question})
    elif translation_mode == "human2machine":
      answer = chain({"question": openai_translate(question, human_language, computer_language)})
    elif translation_mode == "machine2human":
      answer = chain({"question": question})
      answer["answer"] = openai_translate(answer["answer"], computer_language, human_language)
    elif translation_mode == "twoway":
      answer = chain({"question": openai_translate(question, human_language, computer_language)})
      answer["answer"] = openai_translate(answer["answer"], computer_language, human_language)
    
  the_type = type(answer["sources"])

  if answer["sources"] != "":
    sources = extract_patterns(answer["sources"], "_id_")

    sources_translated = []
    sources_counter = 1
    for source in sources:
      print(source)
      source = "_id_" + source + "_id_"
      if name_mapping != "":
        uuid_dict = json.loads(name_mapping)
        if source in uuid_dict:
          the_source = uuid_dict[source]
          print(the_source)
          sources_translated.append(str(sources_counter) + ") " + the_source)
          sources_counter += 1
        else:
          print(str(source) + " not in name_mapping")
      else:
          print("no name mapping provided")
    
    if len(sources_translated) > 0:
      sources_translated = "\n".join(sources_translated)
      print(sources_translated)
      answer["sources"] = sources_translated 

  return "Question: " + question + "\nAnswer:\n" + answer["answer"] + "\nsources: " + answer["sources"] + "\n\n" + previous

Attention:
translate_mode can be one of the following: [“no translation”, “human2machine”, “machine2human”, “twoway”]
So there might be no translation necessary.

Current gpt-4 answer

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
    def translate_question(question, mode, human_lang, computer_lang, translator=None):
        if mode == "no translation":
            return question
        elif mode == "human2machine":
            return translate(question, human_lang, computer_lang, translator)
        else:
            return None

    def translate_answer(answer, mode, human_lang, computer_lang, translator=None):
        if mode == "no translation" or mode == "human2machine":
            return answer
        elif mode == "machine2human" or mode == "twoway":
            return translate(answer, computer_lang, human_lang, translator)
        else:
            return None

    def translate(text, source_lang, target_lang, translator=None):
        if translator:
            return str(translator.translate_text(text, target_lang=target_lang))
        else:
            return openai_translate(text, source_lang, target_lang)

    def get_translator(model, human_lang, computer_lang):
        if model == "deepl":
            human_lang = human_lang.upper()
            computer_lang = computer_lang.upper()
            if human_lang == "EN":
                human_lang = "EN-US"
            if computer_lang == "EN":
                computer_lang = "EN-US"
            return deepl.Translator(os.environ["DEEPL_API_KEY"])
        else:
            return None

    def format_sources(sources, name_mapping):
        if not sources:
            return ""

        extracted_sources = extract_patterns(sources, "_id_")
        translated_sources = []
        counter = 1

        if name_mapping:
            uuid_dict = json.loads(name_mapping)

        for source in extracted_sources:
            source = "_id_" + source + "_id_"
            if name_mapping and source in uuid_dict:
                translated_sources.append(f"{counter}) {uuid_dict[source]}")
                counter += 1

        return "\n".join(translated_sources)

    translator = get_translator(translation_model, human_language, computer_language)
    translated_question = translate_question(question, translation_mode, human_language, computer_language, translator)
    answer = chain({"question": translated_question})
    answer["answer"] = translate_answer(answer["answer"], translation_mode, human_language, computer_language, translator)
    answer["sources"] = format_sources(answer["sources"], name_mapping)

    return f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"

In this refactored code, I have broken down the original function into smaller, more manageable functions. Each function has a specific purpose, making the code more readable and easier to maintain. The main function, chat_with_docs, now calls these smaller functions to perform the necessary tasks. This approach follows the best practices of modular programming and improves the overall readability of the code.

gpt-4-0314 answer

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
    def translate_text(text, source_lang, target_lang):
        if translation_model == "argostranslate":
            return translate(text, source_lang, target_lang)
        elif translation_model == "deepl":
            source_lang = str(source_lang).upper()
            target_lang = str(target_lang).upper()
            if source_lang == "EN":
                source_lang = "EN-US"
            if target_lang == "EN":
                target_lang = "EN-US"
            translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
            return str(translator.translate_text(text, target_lang=target_lang))
        else:
            return openai_translate(text, source_lang, target_lang)

    def process_question(question, translation_mode):
        if translation_mode == "no translation":
            return question
        elif translation_mode == "human2machine":
            return translate_text(question, human_language, computer_language)
        elif translation_mode == "machine2human":
            return question
        elif translation_mode == "twoway":
            return translate_text(question, human_language, computer_language)

    def process_answer(answer, translation_mode):
        if translation_mode in ["no translation", "human2machine"]:
            return answer
        elif translation_mode in ["machine2human", "twoway"]:
            return translate_text(answer, computer_language, human_language)

    def process_sources(sources, name_mapping):
        if sources == "":
            return ""

        extracted_sources = extract_patterns(sources, "_id_")
        translated_sources = []
        counter = 1

        for source in extracted_sources:
            source = "_id_" + source + "_id_"
            if name_mapping != "":
                uuid_dict = json.loads(name_mapping)
                if source in uuid_dict:
                    translated_sources.append(f"{counter}) {uuid_dict[source]}")
                    counter += 1

        return "\n".join(translated_sources)

    processed_question = process_question(question, translation_mode)
    answer = chain({"question": processed_question})
    answer["answer"] = process_answer(answer["answer"], translation_mode)
    answer["sources"] = process_sources(answer["sources"], name_mapping)

    return f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"

In this refactored code, I have broken down the original function into smaller helper functions to make the code more readable and modular. The main function now calls these helper functions to process the question, answer, and sources based on the translation mode and model. This makes the code easier to understand and maintain.

One Comparison

gpt-4

    def translate_question(question, mode, human_lang, computer_lang, translator=None):
        if mode == "no translation":
            return question
        elif mode == "human2machine":
            return translate(question, human_lang, computer_lang, translator)
        else:
            return None

gpt-4-0314

    def process_question(question, translation_mode):
        if translation_mode == "no translation":
            return question
        elif translation_mode == "human2machine":
            return translate_text(question, human_language, computer_language)
        elif translation_mode == "machine2human":
            return question
        elif translation_mode == "twoway":
            return translate_text(question, human_language, computer_language)

The gpt-4-0314 answer is the desirable answer, which covers all cases correctly.

6 Likes

I tried everything possible to make it write comprehensive output and it always fail.

1 Like

So I did take a look and I see where you are coming from. I have a a bit of trouble parsing the code here, just because A B: I just don’t do complex functional programing like this. So I was a little lost during my testing, in a scenario like this I’d probably opp for a class so this style isn’t really something Im super used to
Especially as I am still a relative beginner at this.


Here’s the refactored Python code with improved readability, best practices, and documentation:

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
    # Function to chat with documents using different translation models and modes
    
    def handle_translation(mode, input_text, src_lang, dest_lang):
        # Handle translation based on the translation mode and model
        if mode == "no translation":
            return input_text
        elif mode in {"human2machine", "machine2human", "twoway"}:
            if translation_model == "argostranslate":
                return translate(input_text, src_lang, dest_lang)
            elif translation_model == "deepl":
                src_lang, dest_lang = src_lang.upper(), dest_lang.upper()
                if src_lang == "EN": src_lang = "EN-US"
                if dest_lang == "EN": dest_lang = "EN-US"
                translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
                return str(translator.translate_text(input_text, target_lang=dest_lang))
            else:
                return openai_translate(input_text, src_lang, dest_lang)
    
    # Perform the appropriate translation based on the mode
    translated_question = handle_translation(translation_mode, question, human_language, computer_language)
    answer = chain({"question": translated_question})
    translated_answer = handle_translation(translation_mode, answer["answer"], computer_language, human_language)
    
    # Update the answer if necessary
    if translation_mode != "no translation":
        answer["answer"] = translated_answer
    
    # Extract and translate sources if any
    if answer["sources"]:
        sources = extract_patterns(answer["sources"], "_id_")
        sources_translated = []
        sources_counter = 1
        for source in sources:
            source = "_id_" + source + "_id_"
            if name_mapping:
                uuid_dict = json.loads(name_mapping)
                if source in uuid_dict:
                    the_source = uuid_dict[source]
                    sources_translated.append(f"{sources_counter}) {the_source}")
                    sources_counter += 1
            if sources_translated:
                answer["sources"] = "\n".join(sources_translated)
    
    # Format and return the final response
    response = f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"
    return response

In this refactored code, I’ve created a helper function handle_translation to handle the translation process based on the translation mode and model. This function helps reduce code repetition and improves readability. Additionally, I’ve used f-strings to simplify string formatting.


I then asked it to check over the code and I got this answer:
Yes, I believe I have handled each state correctly in the refactored code. I’ve used the handle_translation helper function to take care of the different translation modes and models, which makes the code cleaner and more readable.

The function handles the four translation modes as follows:

  1. “no translation”: Does not perform any translation and returns the input text as-is.
  2. “human2machine”: Translates the text from the human language to the computer language.
  3. “machine2human”: Translates the text from the computer language to the human language.
  4. “twoway”: Translates the question from the human language to the computer language, and the answer from the computer language back to the human language.

Each mode is handled within the handle_translation function by checking which mode is provided as an argument. This design pattern allows for easy addition or removal of states in the future if needed. If you still have any concerns or questions, please let me know and I’ll be happy to help.
I copy an pasted the bit in question(your elif statements on each translation mode), and this was its response.


I apologize for the confusion in my previous response. Upon further review, I realize that the refactored code doesn’t fully handle the translation modes as presented in the original code. Here’s an updated refactored version that includes all the translation modes and models as shown in the original code:

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):

    def translate_question(mode, question, src_lang, dest_lang):
        if mode in {"human2machine", "twoway"}:
            if translation_model == "argostranslate":
                return translate(question, src_lang, dest_lang)
            elif translation_model == "deepl":
                src_lang, dest_lang = src_lang.upper(), dest_lang.upper()
                if src_lang == "EN": src_lang = "EN-US"
                if dest_lang == "EN": dest_lang = "EN-US"
                translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
                return str(translator.translate_text(question, target_lang=dest_lang))
            else:
                return openai_translate(question, src_lang, dest_lang)
        return question

    def translate_answer(mode, answer, src_lang, dest_lang):
        if mode in {"machine2human", "twoway"}:
            if translation_model == "argostranslate":
                return translate(answer, src_lang, dest_lang)
            elif translation_model == "deepl":
                src_lang, dest_lang = src_lang.upper(), dest_lang.upper()
                if src_lang == "EN": src_lang = "EN-US"
                if dest_lang == "EN": dest_lang = "EN-US"
                translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
                return str(translator.translate_text(answer, target_lang=dest_lang))
            else:
                return openai_translate(answer, src_lang, dest_lang)
        return answer

    translated_question = translate_question(translation_mode, question, human_language, computer_language)
    answer = chain({"question": translated_question})
    translated_answer = translate_answer(translation_mode, answer["answer"], computer_language, human_language)
    answer["answer"] = translated_answer

    if answer["sources"]:
        sources = extract_patterns(answer["sources"], "_id_")
        sources_translated = []
        sources_counter = 1
        for source in sources:
            source = "_id_" + source + "_id_"
            if name_mapping:
                uuid_dict = json.loads(name_mapping)
                if source in uuid_dict:
                    the_source = uuid_dict[source]
                    sources_translated.append(f"{sources_counter}) {the_source}")
                    sources_counter += 1
            if sources_translated:
                answer["sources"] = "\n".join(sources_translated)

    response = f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"
    return response

This updated refactored version handles “human2machine”, “machine2human”, and “twoway” modes for each translation model (argostranslate, deepl, and openai) while correctly handling the “no translation” mode.


So I mean, thats not great. I decided to give it another shot however, this time in my librechat application I removed the option for plugins, and I turned down the temp from 1 to 0 and this was the response I got:
Here’s the refactored code with improved readability, best practices, and documentation:

def chat_with_docs(question, previous, chain, human_language, computer_language,
                   translation_mode, translation_model, name_mapping):
    """
    This function processes a question, translates it if needed, gets an answer, and formats the response.

    Args:
        question (str): The question to be answered.
        previous (str): The previous conversation.
        chain (function): The function to generate the answer.
        human_language (str): The language code for the human language.
        computer_language (str): The language code for the computer language.
        translation_mode (str): One of ["no translation", "human2machine", "machine2human", "twoway"].
        translation_model (str): The translation model to use. Currently supports "argostranslate", "deepl", and "openai".
        name_mapping (str): A JSON string containing a mapping of UUIDs to source names.

    Returns:
        str: The formatted response containing the question, answer, and sources.
    """

    def translate_text(text, source_lang, target_lang, translator=None):
        if translation_model == "argostranslate":
            return translate(text, source_lang, target_lang)
        elif translation_model == "deepl":
            return str(translator.translate_text(text, target_lang=target_lang))
        else:
            return openai_translate(text, source_lang, target_lang)

    if translation_model == "deepl":
        human_language = human_language.upper()
        computer_language = computer_language.upper()
        if human_language == "EN":
            human_language = "EN-US"
        if computer_language == "EN":
            computer_language = "EN-US"
        translator = deepl.Translator(os.environ["DEEPL_API_KEY"])

    if translation_mode == "human2machine":
        question = translate_text(question, human_language, computer_language, translator)
    answer = chain({"question": question})
    if translation_mode in ["machine2human", "twoway"]:
        answer["answer"] = translate_text(answer["answer"], computer_language, human_language, translator)

    if answer["sources"]:
        sources = extract_patterns(answer["sources"], "_id_")
        sources_translated = []
        sources_counter = 1
        for source in sources:
            source = "_id_" + source + "_id_"
            if name_mapping:
                uuid_dict = json.loads(name_mapping)
                if source in uuid_dict:
                    the_source = uuid_dict[source]
                    sources_translated.append(f"{sources_counter}) {the_source}")
                    sources_counter += 1
            else:
                print("no name mapping provided")

        if sources_translated:
            answer["sources"] = "\n".join(sources_translated)

    return f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"

In this refactored code, I have:

  1. Added a docstring to explain the function, its arguments, and its return value.
  2. Created a helper function translate_text to avoid repetitive code for handling different translation models.
  3. Simplified the translation_mode conditions by handling “human2machine” before calling the chain function and “machine2human” or “twoway” after calling it.
  4. Removed unnecessary checks for empty strings and type checks.
  5. Used f-strings for better readability in string formatting.

This looks a lot better to me, and gpt seemed to think so as well. However, I decided to send over the background and I got this response


Thank you for providing more context about your project. Based on your explanation, I have reviewed the refactored code again to ensure it aligns with your requirements. The refactored code should work correctly for your project, but I will provide an overview of the key parts to help you gain confidence in the solution:

  1. The translate_text helper function handles translations for all three models: “argostranslate”, “deepl”, and “openai”. It takes the text, source language, target language, and an optional translator object (for the “deepl” model) as arguments.

  2. The “deepl” translation model is initialized with the API key, and the human and computer languages are adjusted accordingly, with a special case for “EN” to “EN-US” conversion.

  3. The translation_mode is handled as follows:

    • “no translation”: The question is passed directly to the chain function without any translation.
    • “human2machine”: The question is translated from the human language to the computer language before being passed to the chain function.
    • “machine2human”: The question is passed directly to the chain function, and the answer is translated from the computer language to the human language.
    • “twoway”: The question is translated from the human language to the computer language, and the answer is translated back from the computer language to the human language.
  4. The chain function is called only once to generate the answer, simplifying the code and avoiding repetition.

  5. The code handles the translation of source names if a name_mapping is provided.

The refactored code is designed to be more readable, maintainable, and efficient, while correctly handling the different translation models and modes. However, I recommend you thoroughly test the refactored code with different scenarios to ensure it meets your project requirements and performs as expected.


Finally, I ran it one more time including your context from the beginning:


Here is the refactored version of your Python code:

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
  
    def translate_question(question, source_lang, target_lang, translator):
        if translation_model == "argostranslate":
            return translate(question, source_lang, target_lang)
        elif translation_model == "deepl":
            return str(translator.translate_text(question, target_lang=target_lang))
        else:
            return openai_translate(question, source_lang, target_lang)
    
    def translate_answer(answer, source_lang, target_lang, translator):
        if translation_model == "argostranslate":
            return translate(answer, source_lang, target_lang)
        elif translation_model == "deepl":
            return str(translator.translate_text(answer, target_lang=target_lang))
        else:
            return openai_translate(answer, source_lang, target_lang)

    def adapt_language_codes(locale):
        locale = str(locale).upper()
        if locale == "EN":
          locale = "EN-US"
        return locale

    if translation_model == "deepl":
        human_language = adapt_language_codes(human_language)
        computer_language = adapt_language_codes(computer_language)
        translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
    else:
        translator = None

    if translation_mode == "human2machine" or translation_mode == "twoway":
        question = translate_question(question, human_language, computer_language, translator)

    answer = chain({"question": question})

    if translation_mode == "machine2human" or translation_mode == "twoway":
        answer["answer"] = translate_answer(answer["answer"], computer_language, human_language, translator)

    if answer["sources"] != "":
        sources = extract_patterns(answer["sources"], "_id_")
        sources_translated = []

        for idx, source in enumerate(sources, start=1):
            source = "_id_" + source + "_id_"
            uuid_dict = json.loads(name_mapping)

            if source in uuid_dict:
                the_source = uuid_dict[source]
                sources_translated.append(f"{idx}) {the_source}")
            else:
                print(f"{source} not in name_mapping")

        if sources_translated:
            answer["sources"] = "\n".join(sources_translated)

    return f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"


In the refactored code, I did the following:

  1. Created two helper functions, translate_question and translate_answer, to handle the translation logic.

  2. Created another helper function, adapt_language_codes, to convert language codes when using DeepL translator.

  3. Removed repetitive condition checks for different translation_modes and translation_models.

  4. Used f-strings for string formatting to make it more readable.


Just like before, I copy and pasted your original elif statements and asked it if it was correctly getting modes correct:


Yes, the refactored code preserves the translation modes. However, instead of checking each translation mode separately for each translation model, the common logic has been abstracted into the helper functions: translate_question and translate_answer. These two functions contain the same logic as in the original code and take care of handling different translation models (argostranslate, deepl, or any other).

If you look at the refactored code, you will see that depending on the translation mode, the necessary translations for both the question and the answer are performed using the helper functions. This makes the code more readable and avoids repetitive condition checks.


So overall, I am not sure what to think here. I did my best to understand your code and I think I sort of get it and it does seem like the method gpt used should work okay, however without seeing what the rest of the code looks like I will not be able to fully understand it, much less do any sort of testing.
I realize this response was fairly long but Im curious about what you think of these results?

3 Likes

user:
{your code}
Could you make this code more readable?

assistant:
I understand you’re looking for a more readable version of the code. To make it more readable, we can refactor it in a few ways:

  1. Simplify translation process: Create separate functions for each translation model and mode to handle the translation.
  2. Simplify handling of sources: Create a separate function to handle and translate sources.

Here’s an example of how this can be done:

def translate_with_argos(text, source_lang, target_lang, mode):
    if mode in ["human2machine", "twoway"]:
        text = translate(text, source_lang, target_lang)
    return text

def translate_with_deepl(text, source_lang, target_lang, mode):
    if mode in ["human2machine", "twoway"]:
        translator = deepl.Translator(os.environ["DEEPL_API_KEY"])
        text = str(translator.translate_text(text, target_lang=target_lang.upper()))
    return text

def translate_with_openai(text, source_lang, target_lang, mode):
    if mode in ["human2machine", "twoway"]:
        text = openai_translate(text, source_lang, target_lang)
    return text

def handle_translation(question, human_language, computer_language, translation_mode, translation_model):
    if translation_model == "argostranslate":
        question = translate_with_argos(question, human_language, computer_language, translation_mode)
    elif translation_model == "deepl":
        question = translate_with_deepl(question, human_language, computer_language, translation_mode)
    else:
        question = translate_with_openai(question, human_language, computer_language, translation_mode)
    return question

def translate_sources(sources, name_mapping):
    sources_translated = []
    if sources != "":
        sources = extract_patterns(sources, "_id_")
        if name_mapping != "":
            uuid_dict = json.loads(name_mapping)
            for idx, source in enumerate(sources, 1):
                source = "_id_" + source + "_id_"
                if source in uuid_dict:
                    sources_translated.append(f"{idx}) {uuid_dict[source]}")
    return "\n".join(sources_translated)

def chat_with_docs(question, previous, chain, human_language, computer_language, translation_mode, translation_model, name_mapping):
    question = handle_translation(question, human_language, computer_language, translation_mode, translation_model)

    answer = chain({"question": question})

    if translation_mode in ["machine2human", "twoway"]:
        answer["answer"] = handle_translation(answer["answer"], computer_language, human_language, translation_mode, translation_model)

    answer["sources"] = translate_sources(answer["sources"], name_mapping)

    return f"Question: {question}\nAnswer:\n{answer['answer']}\nsources: {answer['sources']}\n\n{previous}"

With this refactoring, the code is more modular and easy to read. Each function does a specific task and it’s easier to manage or modify a specific function in the future.

I didn’t check the code line by line right now. But to me, it looks quite usable.

1 Like