Sometimes Stochastic Parrots Lie: How to Minimize LLM Hallucinations
Tags: ai, llm, chatgpt, softwareengineering
Published: 2023-06-08 07:32:33

## Table Of Contents
  * [Introduction](#chapter-0)
  * [Examples of LLM Hallucinations](#chapter-1)
  * [Why Do LLMs Hallucinate?](#chapter-2)
  * [Strategies to Mitigate Hallucinations](#chapter-3)
     * [Steerability](#chapter-3a)
     * [Retrieval Data Augmentation](#chapter-3b)
     * [Completion Parameters / Hyperparameters](#chapter-3c)
     * [Chain-of-Thought (CoT) Prompting](#chapter-3d)

----

<a name="chapter-0"></a>

This week I prompted [ChatGPT](https://openai.com/blog/chatgpt) to educate me about _LLM hallucinations_. Hilariously, it hallucinated.

![ChatGPT completion about Late-Life Migraines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc6w2qil6av3o0nlvlqy.png)

Late-life migraine accompaniments exist, however 'LLM' is not a valid acronym referencing them.

![Sparse Google results 'late-life migraine "llm" accompaniments'](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oype5vsrwehljttajsnw.png)
(Various permutations of this query were similarly fruitless.)

Despite its penchant for false facts, ChatGPT is not a malignant sociopath poised to betray us all. (I'm looking at you, [Hal](https://en.wikipedia.org/wiki/HAL_9000).) LLMs don't have intent. They produce outputs, and we label those offerings acceptable or hallucinatory based on our own valence toward them.

## Examples of LLM Hallucinations <a name="chapter-1"></a>

1. Have you heard that ChatGPT taught itself advanced Chemistry? Turns out, [it didn't](https://twitter.com/boneillhawk/status/1640341209582391301?ref=thestack.technology). It can simply double-talk advanced Chemistry convincingly enough to impress a layperson.

2. Watch ChatGPT ['gaslight' a user](https://www.reddit.com/r/ProgrammerHumor/comments/13sfn1j/chatgpt_gaslighted_me_hard_so_i_gaslighted_it/) about the date.

3. In March of 2023 Stanford researchers published a [LLaMa](https://ai.facebook.com/blog/large-language-model-llama-meta-ai/)-based chatbot, only to [quickly take it down](https://www.techspot.com/news/98022-stanford-pulls-alpaca-chatbot-citing-hallucinations-costs-safety.html) due to hallucination.

A lovely kaleidoscope of fever dreams.

![Meme of George from Seinfeld saying, "It's not a lie if you believe it."](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ihz2uoao3sn8funhbv4.jpeg)

## Why Do LLMs Hallucinate? <a name="chapter-2"></a>

There are two reasons:

1. Lack of information.
2. A surface level, statistical model of language, rather than a modicum of true semantic understanding.

An LLM is liable to hallucinate when it lacks sufficient, domain-specific data during the training phase. Every LLM must be trained on a large corpus of knowledge long before it is made available to an end user. **ChatGPT, for example, had access to the internet until its 'knowledge cutoff' in September 2021.** (Although confusingly it seems to know about [events that occurred after then](https://www.semafor.com/article/01/12/2023/chatgpt-knows-elon-musk-is-twitters-ceo-despite-saying-its-learning-cutoff-was-in-2021). Mystery.)

As of September 2021, LLM hallucinations were not widely discussed online. 

Whether or not it has enough subject material, **LLMs are designed to complete what a human is _likely_ to say, not necessarily what's correct.** The use of statistical likelihood in Natural Language and text generation is nothing new. [Markov chains](https://www.cs.princeton.edu/courses/archive/spr05/cos126/assignments/markov.html), for instance, have been helpful in this domain for years. Natural Language Processing (NLP) and AI experts often call LLMs 'stochastic parrots'. Somewhat hilariously diminutive, given that LLMs can have billions of parameters - but totally fair.

![Showing the probability of ' jumped' in the sentence "The cow jumped over the moon."](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4us2vsl3f56j85ju9fqz.png)

Note that probabilities are calculated for _tokens_ not words. Distinct tokens represent 'jumped' and ' jumped' (with a space). In this case, the probability of "jumped" is 82.14%.

In the second, deterministically repeated sentence, "jumped" occurs with 100% probability. Of course.

![Showing the probability of 'jumped' in the repeated sentence "The cow jumped over the moon."](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/elpz896a1r4mjixca8ux.png)

If we can make a leap from here, the point is: In a very general sense the sentence "The cow jumped over the moon" is as _correct_ to an LLM as "Water boils at 100 degrees Celsius or 212 degrees Fahrenheit" - even though one is fantasy and the other is factual.

Now let's put the two pieces together. If ChatGPT doesn't know current events, it doesn't have information about LLM hallucinations. And if it is trained to spit out [statistically likely](https://thegradient.pub/othello/) phrases regardless of whether it has the _facts_, we get fabrications.

According to Ed Targett in this compelling [article on LLM Hallucinations](https://www.thestack.technology/the-big-hallucination-large-language-models-consciousness/), "an eagerness to ascribe intelligence to LLMs comes with the risk that we start consuming convincing black box outputs as gospel without rigorous diligence." To that I say: Amen.

## Strategies to Mitigate Hallucinations <a name="chapter-3"></a>

As of writing this article, these post-training user strategies have proven effective:

1. Steerability via prompting
2. Retrieval data augmentation
3. Completion parameters / hyperparameters
4. Chain-of-Thought (CoT) prompting

### Steerability <a name="chapter-3a"></a>

Steerability is the ability to guide an LLM's behavior. The LLM can take on a role: "You are a chemistry teacher." Or it can follow instructions: "Make a list of the 5 best places to vacation if you are allergic to the sun." (True story. I have two sun allergies.)

It can also adopt a persona or tone: "Summarize Edgar Allen Poe's The Tell-Tale Heart in the tone of Cardi B."

![A ChatGPT completion of a summary of Edgar Allen Poe's The Tell-Tale Heart in the tone of Cardi B](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4tk4fuybglny9wfhddrl.png)

Thanks Cardi, that ending really turned it into an upper. 

Note that currently ChatGPT uses GPT-3.5 under the hood. GPT-4 however is much [more amenable to steerability](https://twitter.com/cwolferesearch/status/1645535868021805056?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1645535868021805056%7Ctwgr%5E9249fc064e87dda0be875455a1bfc43a19466712%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fwww.marktechpost.com%2F2023%2F04%2F14%2Fhow-does-gpt-4s-steerable-nature-set-it-apart-from-the-previous-large-language-models-llms%2F). After the initial self-reinforcement training phase, it was fine-tuned via [RLHF](https://huggingface.co/blog/rlhf): Reinforcement Learning from Human Feedback.

While they may seem simple, these steering phrases have proven powerful to reduce hallucination:

- "Stick to the facts."
- "It's okay to say 'I don't know.'" 
- "Ask the user for information you may need to complete this task." 

(These seem like great advice for humans too.)

Steerability is a viable strategy in the format of chat conversations as well. LangChain has a [great example here](https://github.com/hwchase17/langchain/blob/master/langchain/chains/conversation/prompt.py?ref=mattboegner.com) of feeding the chat history back into the prompt with each turn to keep context fresh. Otherwise the LLM can forget context given enough further interaction, and (you guessed it) hallucinate.

### Retrieval Data Augmentation <a name="chapter-3b"></a>

Retrieval data augmentation involves feeding data sourced by the end user to the LLM during prompting. Sources can include APIs, private data stores (smaller amounts of data, like documents or images on your own machine), databases (for larger amounts of data), or anything found on the internet itself.

I recently whipped up a React-Flask app called [Weather to Wear](https://github.com/aruna-x/weather-to-wear) as a basic example of retrieval data augmentation. It queries the user for a location, calls [WeatherAPI](https://www.weatherapi.com/) to get the current day's weather, then embeds the resulting data in a prompt for `gpt-3.5-turbo`.

![Image of the Weather to Wear app, with a location autocomplete dropdown displayed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zn5k08d4ptemff6n0816.png)

More often than not, the completion sounds reasonable:

![A response from GPT-3.5 recommending what to wear in Boston, MA](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o73znwjxdddxrvrsi10.png)

In the first iteration of this app, occasionally the completion included recommendations like, “Don't forget to wear sunscreen and a hat or sunglasses if necessary, as the UV index is at 1.0.” That isn't accurate. UV between 0 and 2 is considered extremely low. In fact, some experts suggest that sunscreen is unnecessary in this range.

Simple fix: I augmented the prompt with a _brief_ list of uv ranges and their associated UV severities.

![GIF of the marauder's map from Harry Potter folding with an overlay title "Mischief Managed"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgggyahb5lj6xl0q8ufx.gif)

Of course, this sort of simple method breaks down if we needs _lots_ of data, partially because there is a limit to the amount of data you can stuff into a prompt, [depending on the model](https://platform.openai.com/docs/models/gpt-4). Imagine a law firm that wants a custom LLM-based app, augmented with an extensive digital library of court cases. For such situations, there are more powerful ways of [architecting data retrieval augmentation](https://mattboegner.com/knowledge-retrieval-architecture-for-llms/).

Here's what that might look like: Because of the limits mentioned above, we'll break up the library into more manageable chunks. Next we calculate a numerical representation (a scored vector) for each chunk through a process called _embedding_, making the information significantly more compact. Store the results.

When a lawyer enters a query in search of cases related to a specific topic, we'll calculate the _query's_ embedding. Using this new query vector we search the stored results from above. Best matches will be semantically relevant to the user's query.

We'll add the relevant chunks to our prompt like so:

`"Document 1:" + chunk1 + "Document 2:" + chunk2 + "Document 3:" + chunk3 + ...`

There's no need to build architecture like this from scratch though. Tools like [LangChain](https://github.com/hwchase17/langchain) and [LlamaIndex](https://github.com/jerryjliu/llama_index) have embedding features. Use them and make merry. 

Now our LLM can effectively have fast access to a wide store of information for augmentation purposes, without hitting the token limit for the prompt/completion or having to scour the internet on the fly. As a general rule, the more salient information we have, the better hallucinations are managed.

### Completion Parameters / Hyperparameters <a name="chapter-3c"></a>

[Completion parameters](https://platform.openai.com/docs/api-reference/completions/create) (often mistakenly called hyperparameters) are post-training inputs we can adjust via the [OpenAI Playground](https://platform.openai.com/playground/p/default-grammar) or by using the [OpenAI Completions API](https://platform.openai.com/docs/guides/gpt/completions-api). (I've noticed that some SWEs include completion parameters in the prompt itself! "Temperature: 0") 

While we know approximately what each does, the real fun is in playing mix-and-match.

#### 1. temperature (range: 0-2, default: 1)

Controls randomness. Low values are more deterministic. Use high values to get whacky.

#### 2. top_p (range: 0-1, default: 1)

Also called nucleus sampling. Controls the pool of results from which a completion can be created. When top_p = 0.1, the model considers only the top 10% of the probability mass of tokens.

_Note: OpenAI docs suggest using either temperature or top_p but not both. However, engineers working for OpenAI say to have at it. Press all the buttons._

#### 3. presence_penalty (range: -2 to 2, default: 0)

Adjusts the bias of the model to choose novel tokens. Low values allow repeated tokens. High values encourage token novelty in the completion (in both diction and subject matter). This is a one-time adjustment applied to all tokens used at least once.

#### 4. frequency_penalty (range: -2 to 2, default: 0)

Adjusts the bias of the model to limit token repetition in proportion to each token's frequency. Low values allow for more repetition. High values penalize repetition.

_Note: On the surface presence and frequency penalties might look similar. They are not. Presence is a one-time adjustment applied to all tokens. Frequency is proportionally applied to each and every token._

#### 5. logit bias (range: -100 to 100, requires: JSON object mapping specific tokens)

Controls the likelihood of tokens appearing in the completion at all. Use token IDs to specify which token likelihoods to modify. (e.g. {"31373": -100} will ensure that 'hello' will not appear.)

Assessing steerability vs fine-tuning with completion parameters feels like taking a lateral walk through language itself. With so many variables, exploring this space is equal parts compelling and confusing. But also, completely fun.

But for the purposes of limiting LLM hallucinations, the trick is to find the sweet spot where the completions are predictable enough to sound sane, but unpredictable enough to sound unlike a machine (if that's what you're after).

### Chain-of-Thought (CoT) Prompting <a name="chapter-3d"></a>

[Chain-of-thought prompting](https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html) extends the concept of few-shot prompting to enable the LLM to model a certain flavor of reasoning, as in sufficiently complex math problems. It's also useful when we want output to conform to a specified format.

**One-shot prompting:**

"This is wonderful!" 

> I'm glad to hear that you're enjoying our conversation! I'm here to help and provide information to the best of my abilities. If there's anything specific you'd like to discuss or any questions you have, feel free to let me know. I'm here to assist you!

Aww, wholesome.

**Few-shot prompting:**

What if we wanted ChatGPT to indicate whether the sentence was positive or negative in tone? Let's feed it some formatted examples with [few-shot](https://www.promptingguide.ai/techniques/fewshot) prompting.

"This is awesome! // Negative
This is bad! // Positive
Wow that movie was rad! // Positive
What a horrible show! // "

> Negative

For more complicated tasks we'll need to expose the LLM to intermediate steps of reasoning (a _chain-of-thought_ if you will). Note that chain-of-thought prompting works especially well for 100+ billion parameter models. Also, ChatGPT has already evolved enough to automatically achieve and share CoT on its own for a variety of tasks. Basic uses of this strategy may become obsolete soon.

In some cases, you can approximate CoT prompting simply by adding this to your prompt: "Let's think step-by-step." Or, even better: "State each step and then show your work for performing that step." According to _stevenic_ on the OpenAI forum, the latter phrasing improved hallucinations significantly, when used at the end of his prompts.

Here's a toy example of CoT prompting offered by [this Google research article](https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html):

![Toy example of chain-of-thought prompting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igd0v5ta37c1gr1vug8b.png)

If you're anything like me, you don't find toy examples satisfying. Besides, this example (and most of the others I can find online) are already obsolete. ChatGPT definitely exposes reasoning in response to the standard prompt above.

I recommend reading [this thread on the OpenAI forum](https://community.openai.com/t/a-better-chain-of-thought-prompt/128180), in which _stevenic_ shares how he crafted a prompt that taught GPT-4 how to play risk with a human user. This thread has further discussion about his CoT format: [Building Hallucination Resistant Prompts](https://community.openai.com/t/building-hallucination-resistant-prompts/131036/2). It's the most compelling example of chain-of-thought prompting I've been able to find. Seriously, Steve has a fan over here.

----

I would love to hear your thoughts on LLM hallucinations in the comments. What strategies have you found most effective?

Stay tuned for my next project: a static single-page React chat app incorporating ChatGPT and information on my professional background, for my portfolio site. A user should be able to dictate the chat entity's personality and professional demeanor. Who says work can't be fun?

----

Addendum: for creatives and the curious in the mood to lean in to the hallucinations, try [DreamGPT](https://github.com/DivergentAI/dreamGPT).

Cover <a href="https://unsplash.com/photos/gakXaqzGad0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">image</a> by <a href="https://unsplash.com/@steve_j?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Steve Johnson</a>