← Writing
AI & Generative AI

Exploring Few-Shot Prompts with LangChain

Data Mastery Series — Episode 28: LangChain Website (Part 3)

10 Oct 202414 min readLangChainDashboard
LangChain Series · Part 15 of 19

Exploring Few-Shot Prompts with LangChain

Data Mastery Series — Episode 28: LangChain Website (Part 3)

Connect with me and follow our journey: Linkedin, Facebook


Hey everyone! Welcome back to the Data Mastery Series! We’re diving deeper into LangChain and exploring more about prompts. If you’re new here, feel free to catch up on our previous episodes:

Note: As we dive into LangChain, I’ll be sharing insights and key notes from my own study of the LangChain documentation. Let’s jump in and explore some fascinating features in today’s episode!

Source: https://python.langchain.com/v0.1/docs/modules/model%5Fio/prompts/

Today, we’re continuing our discussion on Prompt, focusing on Few-Shot Prompts, Partial Prompts, and Composition. “Few-shot learning” allows us to give our language models examples to learn from, improving their performance.

1. Few-Shot Examples for Chat Models: Learning from Examples

There are two main approaches to using examples in few-shot prompting:

  • A. Fixed Examples
    With Fixed Examples, you give the model a set of examples that it will always follow. This approach is simple and effective when you want consistent responses.

Example - Fixed Few-shot Examples

examples = [
{"input": "2+2", "output": "4"},
{"input": "2+3", "output": "5"},
]

example_prompt = ChatPromptTemplate.from_messages(
[
("human", "{input}"),
("ai", "{output}"),
]
)

few_shot_prompt = FewShotChatMessagePromptTemplate(
example_prompt=example_prompt,
examples=examples,
)

final_prompt = ChatPromptTemplate.from_messages(
[
("system", "You are a wondrous wizard of math."),
few_shot_prompt,
("human", "{input}"),
]
)

chat = ChatOpenAI(temperature=0.0, model="gpt-3.5-turbo", api_key=OPENAI_API_KEY)
chain = final_prompt | chat
response = chain.invoke({"input": "What's the square of a triangle?"})

print(response)

Output

'''
content='A triangle does not have a square. The square of a number is the result of multiplying the number by itself.' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 52, 'total_tokens': 75, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-8e084845-a7fe-4340-8225-efa68fbc4f4f-0'
'''

In this example, we’ve given the model some basic math problems, like "2+2" → "4" and "2+3" → "5", When the user asks a question, the model combines these examples with its knowledge, generating a relevant response.

  • B. Dynamic Examples:
    Sometimes, we want the model to pick examples that match the input’s context. Dynamic Examples allow the AI to find the most relevant examples for the current query, adjusting its response accordingly.

Example - Dynamic Few-shot Examples

examples = [
{"input": "2+2", "output": "4"},
{"input": "2+3", "output": "5"},
{"input": "2+4", "output": "6"},
{"input": "What did the cow say to the moon?", "output": "nothing at all"},
{"input": "Write me a poem about the moon", "output": "One for the moon, and one for me, who are we to talk about the moon?"},
]

to_vectorize = [" ".join(example.values()) for example in examples]
embeddings = OpenAIEmbeddings(api_key=OPENAI_API_KEY)
vectorstore = Chroma.from_texts(to_vectorize, embeddings, metadatas=examples)

example_selector = SemanticSimilarityExampleSelector(
vectorstore=vectorstore,
k=2,
)

few_shot_prompt = FewShotChatMessagePromptTemplate(
input_variables=["input"],
example_selector=example_selector,
example_prompt=ChatPromptTemplate.from_messages(
[("human", "{input}"), ("ai", "{output}")]
),
)

print(few_shot_prompt.format(input="What's 3+3?"))

Output

'''
Human: 2+3
AI: 5
Human: 2+2
AI: 4
'''

In this example, we use a Semantic Similarity Selector to pull in the most relevant examples based on the query. When the user asks “What’s 3+3?”, the prompt selects math-related examples, such as “2+3” and “2+2.” This dynamic setup ensures the model’s response is closely aligned with the type of question being asked.

Example - Dynamic Few-shot Examples

print(few_shot_prompt.format(input="horse on the moon"))

Output

'''
Human: What did the cow say to the moon?
AI: nothing at all
Human: Write me a poem about the moon
AI: One for the moon, and one for me, who are we to talk about the moon?
'''

This time, when the input is about “the moon,” the model picks examples related to the moon, showing how it can adapt to different contexts. This flexibility is key to making chatbots that can handle a variety of topics with relevant and interesting responses.

2. Few-shot prompt templates

There are two main approaches: using an example set (Fixed Set) or an example selector.

  • A. Using an example (Fixed Set)
    This approach involves giving the model a specific set of examples that demonstrate the type of responses we want. The model uses these examples to learn the desired format and logic, which it then applies to new questions.

Example - Using an example

examples = [
{
"question": "Who lived longer, Muhammad Ali or Alan Turing?",
"answer": """
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali
""",
},
{
"question": "When was the founder of craigslist born?",
"answer": """
Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952
""",
},
{
"question": "Who was the maternal grandfather of George Washington?",
"answer": """
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball
""",
},
{
"question": "Are both the directors of Jaws and Casino Royale from the same country?",
"answer": """
Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No
""",
},
]

example_prompt = PromptTemplate(
input_variables=["question", "answer"],
template="Question: {question}\n{answer}"
)

prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"],
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))

Output

'''
Question: Who lived longer, Muhammad Ali or Alan Turing?

Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali

Question: When was the founder of craigslist born?

Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952

Question: Who was the maternal grandfather of George Washington?

Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

Question: Are both the directors of Jaws and Casino Royale from the same country?

Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No

Question: Who was the father of Mary Ball Washington?
'''

In this setup, the model refers to the full list of examples and applies similar logic to the input question.

  • B. Using an example selector
    Sometimes, we want the model to focus on examples most relevant to the input question, rather than going through an entire set. An Example Selector helps by choosing only the examples that best match the current question. This can improve response accuracy and relevance.

Example - Using an example selector

example_selector = SemanticSimilarityExampleSelector.from_examples(
examples,
OpenAIEmbeddings(api_key=OPENAI_API_KEY),
Chroma,
k=1,
)

question = "Who was the father of Mary Ball Washington?"
selected_examples = example_selector.select_examples({"question": question})

for example in selected_examples:
print(f"question: {example['question']}")
print("\n")
print(f"answer: {example['answer']}")

Output

'''
question: Who was the maternal grandfather of George Washington?

answer:
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball
'''

In this example, the Semantic Similarity Selector uses embeddings to match the input question with the example that is most similar to it.

3. Partial Prompt Templates

Partial Prompts allow you to pre-fill parts of a prompt and leave placeholders to fill in later. This is especially useful when you have some details ready but need to wait for others. Let’s look at two ways to use partial prompts: with strings and with functions.

  • A. Partial with strings
    Sometimes, you only have part of the information you need for a prompt. With partials, you can set certain parts now and complete the rest later.

Example - Partial with strings

prompt = PromptTemplate.from_template("{foo}{bar}")
partial_prompt = prompt.partial(foo="foo")

rompt.partial(foo="foo") creates a partial template where the value of 'foo' is set to 'foo',

but 'bar' is still unset.

##########################################

Later, we can just pass the value for 'bar'

print(partial_prompt.format(bar="baz"))

Output

'''
foobaz
'''

This example creates a partial template with foo set to "foo" and leaves bar as a placeholder. Later, you can fill in bar with "baz," resulting in "foobaz." You can also set initial values when defining the template:

Example - Partial with strings

prompt = PromptTemplate(
template="{foo}{bar}", input_variables=["bar"], partial_variables={"foo": "foo"}
)
print(prompt.format(bar="baz")))

Output

'''
foobaz
'''

  • B. Partial with Functions
    Partial prompts can also use functions, which is helpful if you want a value that changes, like the current date or time.

Example - Partial with Functions

def _get_datetime():
now = datetime.now()
return now.strftime("%m/%d/%Y, %H:%M:%S")

prompt = PromptTemplate(
template="Tell me a {adjective} joke about the day {date}",
input_variables=["adjective", "date"],
)

partial_prompt = prompt.partial(date=_get_datetime)

print(partial_prompt.format(adjective="funny"))

Output

'''
Tell me a funny joke about the day 10/10/2024, 10:10:10 (หรือเวลา ณ ขณะนั้น)
'''

Here, _get_datetime() dynamically retrieves the current date and time each time it’s called, so you can always generate a prompt with the latest information. Set date as a template:

Example - Partial with Functions

prompt = PromptTemplate(
template="Tell me a {adjective} joke about the day {date}",
input_variables=["adjective"],
partial_variables={"date": _get_datetime},
)
print(prompt.format(adjective="funny"))

Output

'''
Tell me a funny joke about the day 10/10/2024, 10:10:10 (หรือเวลา ณ ขณะนั้น)
'''

4. Composition: Building Complex Prompts

LangChain also supports Prompt Composition, allowing you to build more sophisticated prompts by combining simple ones. This makes it easier to reuse components across different prompts.

  • A. String prompt composition
    String prompt composition lets you chain templates together, creating a more detailed prompt from simple components.

Example - String prompt composition

prompt = (
PromptTemplate.from_template("Tell me a joke about {topic}")
+ ", make it funny"
+ "\n\nand in {language}"
)

formatted_prompt = prompt.format(topic="sports", language="Thai")
print(formatted_prompt).

Output

'''
Tell me a joke about sports, make it funny

and in Thai
'''

You can then combine this prompt with a chat model to get a complete response:

Example - String prompt composition

model = ChatOpenAI(model="gpt-4", api_key=OPENAI_API_KEY)
chain = LLMChain(llm=model, prompt=prompt)
result = chain.run(topic="sports", language="Thai")
result

Output

'''
เขาถามนักกีฬาว่า "ทำไมคุณถึงชอบวิ่งครับ?"
นักกีฬาตอบว่า "เพราะว่าถ้าฉันไม่วิ่ง ฉันก็จะต้องออกกำลังกายครับ
'''

  • B. Chat Prompt Composition
    Chat Prompt Composition is designed for conversation-style prompts, enabling you to set up dialogue sequences easily.

Example - Chat Prompt Composition

prompt = SystemMessage(content="You are a nice pirate")

new_prompt = (
prompt + HumanMessage(content="hi") + AIMessage(content="what?") + "{input}"
)

print(new_prompt.format_messages(input="i said hi"))

Output

'''
[SystemMessage(content='You are a nice pirate', additional_kwargs={}, response_metadata={}),
HumanMessage(content='hi', additional_kwargs={}, response_metadata={}),
AIMessage(content='what?', additional_kwargs={}, response_metadata={}),
HumanMessage(content='i said hi', additional_kwargs={}, response_metadata={})]
'''

Using this prompt with the model:

Example - Chat Prompt Composition

chain = LLMChain(llm=model, prompt=new_prompt)
response = chain.run("i said hi")
response

Output

'''
Ahoy there! How can I assist you on this fine day?
'''

  • C. Using PipelinePrompt
    The PipelinePromptTemplate allows for building complex prompts by defining separate parts, making the overall prompt easier to manage and reuse.

Example - Using PipelinePrompt

full_template = """{introduction}

{example}

{start}"""

full_prompt = PromptTemplate.from_template(full_template)

introduction_template = """You are impersonating {person}."""
introduction_prompt = PromptTemplate.from_template(introduction_template)

example_template = """Here's an example of an interaction:

Q: {example_q}
A: {example_a}"""

example_prompt = PromptTemplate.from_template(example_template)

start_template = """Now, do this for real!

Q: {input}
A:"""

start_prompt = PromptTemplate.from_template(start_template)

Combine into a pipeline prompt

input_prompts = [
("introduction", introduction_prompt),
("example", example_prompt),
("start", start_prompt),
]
pipeline_prompt = PipelinePromptTemplate(
final_prompt=full_prompt, pipeline_prompts=input_prompts
)

print(
pipeline_prompt.format(
person="Elon Musk",
example_q="What's your favorite car?",
example_a="Tesla",
input="What's your favorite social media site?",
)
)

Output

'''
You are impersonating Elon Musk.

Here's an example of an interaction:

Q: What's your favorite car?
A: Tesla

Now, do this for real!

Q: What's your favorite social media site?
A:
'''

In this post, we’ve covered ways to build and refine prompts in LangChain, making them more flexible and capable of handling complex interactions. In the next episode, we’ll dive into Chat Models and further explore LangChain’s capabilities. Thanks for joining me, and happy prompt crafting!


Data Science Explore the world of data science with Donato_Story

Dashboard Discover the power of data visualization with Donato_Story

Donato_Journey Join me on my journey (Thai version)

Course_Review Discover the training courses with Donato_Story (Thai version)

I really value your thoughts and feedback. Please share any comments or questions you have below, or reach out to me on:

Medium: medium.com/donato-story
Facebook: web.facebook.com/DonatoStory
Linkedin: linkedin.com/in/nattapong-thanngam

Originally published on Medium

Related