> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompt Templates & Message Structures

> Learn how to build string and chat-based prompt templates, manage message objects, and extract responses

## 💻 Practice Notebook

Master the concepts from this page with hands-on practice:
[💻 VS Code](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/prompt-engg/prompt-engg-templates-vscode.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/prompt-engg/prompt-engg-templates-colab.ipynb) | <a href="/public/notebooks/prompt-engg/prompt-engg-templates-vscode.ipynb" download>📥 Download Notebook</a>

When building LLM applications, managing prompts dynamically is essential. LangChain provides powerful abstractions like `PromptTemplate` and `ChatPromptTemplate` to build reusable prompts, manage conversation messages, and parse variables.

## 1. PromptTemplate (String-Based Prompts)

`PromptTemplate` is used to create simple, string-based prompts. It is ideal for non-conversational LLMs or basic text generation pipelines.

### 1.1 Code Examples

#### Example 1: Concept Explanation

```python theme={null}
from langchain_core.prompts import PromptTemplate
from langchain.chat_models import init_chat_model

# Define a template with a variable {concept}
template_str = "Explain the concept of {concept} in simple terms."
prompt_template = PromptTemplate.from_template(template_str)

# Fill in the variable
prompt = prompt_template.invoke({"concept": "machine learning"})

# 1. Print the formatted template string
print("--- Formatted Prompt ---")
print(prompt.to_string())

# 2. Initialize the chat model and invoke
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
response = llm.invoke(prompt)

print("\n--- LLM Response ---")
print(response.content)
```

**Output:**

```text theme={null}
Explain the concept of machine learning in simple terms.
```

#### Example 2: Automated Code Reviewer

Create a prompt template that takes `language` and `code` variables and instructs the model to review the code.

```python theme={null}
from langchain_core.prompts import PromptTemplate
from langchain.chat_models import init_chat_model

reviewer_template = PromptTemplate.from_template(
    "Review the following {language} code for security vulnerabilities and performance bottlenecks:\n\n\\`\\`\\`{language}\n{code}\n\\`\\`\\`"
)

# Paste the code manually
code_to_review = """
def read_file(filename):
    import os
    os.system('cat ' + filename)
"""

formatted_prompt = reviewer_template.format(
    language="Python", 
    code=code_to_review
)

# 1. Print the formatted template string
print("--- Formatted Prompt ---")
print(formatted_prompt)

# 2. Initialize the chat model and invoke
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
response = llm.invoke(formatted_prompt)

print("\n--- LLM Response ---")
print(response.content)
```

**Output:**

````text theme={null}
Review the following Python code for security vulnerabilities and performance bottlenecks:

```Python
def read_file(filename):
    import os
    os.system('cat ' + filename)
```
````

### 1.2 Exercises for PromptTemplate

#### Exercise 1: Recipe Generator

Define a `PromptTemplate` that takes an `ingredients` list (e.g., "tomato, cheese, basil") and a `cuisine` type (e.g., "Italian"), and prompts the model to generate a recipe.

<Accordion title="Solution">
  ```python theme={null}
  from langchain_core.prompts import PromptTemplate

  recipe_template = PromptTemplate.from_template(
      "Create a traditional {cuisine} recipe using these ingredients: {ingredients}."
  )
  prompt = recipe_template.invoke({"cuisine": "Italian", "ingredients": "tomato, cheese, basil"})
  print(prompt.to_string())
  ```
</Accordion>

#### Exercise 2: Technical Definition Writer

Define a `PromptTemplate` that takes a `term` and an `audience_level` (e.g., "5-year-old" or "PhD student") and generates a customized definition.

<Accordion title="Solution">
  ```python theme={null}
  from langchain_core.prompts import PromptTemplate

  definition_template = PromptTemplate.from_template(
      "Define the term '{term}' in a way that a {audience_level} can easily understand."
  )
  prompt = definition_template.invoke({"term": "Quantum Computing", "audience_level": "5-year-old"})
  print(prompt.to_string())
  ```
</Accordion>

## 2. Message Types & Chat Structures

Chat models communicate using lists of structured messages rather than a single block of text. This helps maintain role-based boundaries and conversational context.

LangChain provides three main message classes in `langchain_core.messages`:

* **`SystemMessage`**: Sets the behavior, persona, rules, or constraints for the assistant. This message is usually sent first.
* **`HumanMessage`**: Represents input sent by the user.
* **`AIMessage`**: Represents responses generated by the model.

### 2.1 Why Message Objects are Important

Message objects allow API providers (like Google Gemini, OpenAI, or Anthropic) to handle conversations structure-selectively. They let the backend know exactly who said what, which prevents the LLM from confusing system guardrails with user input.

### 2.2 Invoking ChatModels with Message Objects

You can pass a list of message objects directly to a Chat Model to initiate or continue a multi-turn conversation.

```python theme={null}
from langchain_core.messages import SystemMessage, HumanMessage
from langchain.chat_models import init_chat_model

# Initialize the chat model
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")

# Construct the dialogue using message objects
messages = [
    SystemMessage(content="You are a strict Python security auditor. Review the user's code for safety issues."),
    HumanMessage(content="Here is my code:\n\nx = input('Enter command: ')\neval(x)")
]

# Invoke the model directly with the list of message objects
response = llm.invoke(messages)

print("--- Auditor Response ---")
print(response.content)
```

## 3. ChatPromptTemplate (Message-Based Prompts)

`ChatPromptTemplate` structures conversation flows for Chat Models using lists of system, human, and AI instructions.

### 3.1 Code Examples

#### Example 1: Customer Service Ticket Auto-Classifier

Categorize customer support tickets into Hardware, Software, or Billing issues.

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model

chat_template = ChatPromptTemplate.from_messages([
    ("system", "You are an automated support classifier. Categorize the ticket into one of: Hardware, Software, Billing."),
    ("human", "Ticket: {ticket_description}")
])

prompt = chat_template.format_messages(ticket_description="My screen keeps flickering.")

# 1. Print the formatted template messages
print("--- Formatted Prompt ---")
for msg in prompt:
    print(f"{msg.type.upper()}: {msg.content}")

# 2. Initialize model and invoke
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
response = llm.invoke(prompt)

print("\n--- LLM Response ---")
print(response.content)
```

#### Example 2: Geography Expert (Few-Shot Chat)

Simulate flag color retrieval with few-shot examples embedded inside a chat dialogue.

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model

chat_template = ChatPromptTemplate.from_messages([
    ("system", "You are a geography expert that returns the colors present in a country's flag."),
    ("human", "France"),
    ("ai", "blue, white, red"),
    ("human", "{country}")
])

prompt = chat_template.invoke({"country": "Japan"})

# 1. Print the formatted template messages
print("--- Formatted Prompt ---")
for msg in prompt.to_messages():
    print(f"{msg.type.upper()}: {msg.content}")

# 2. Initialize model and invoke
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
response = llm.invoke(prompt)

print("\n--- LLM Response ---")
print(response.content)
```

### 3.2 Exercises for ChatPromptTemplate

#### Exercise 1: History Guide Roleplay

Create a `ChatPromptTemplate` simulating a historical dialogue.

* System message: `"You are \{historical_figure\}, a historical figure. Answer in their character."`
* Human: `"What was your greatest achievement?"`
* AI: `"My greatest achievement was \{achievement\}."`
* Human: `"Why was \{achievement\} important?"`

Invoke this template with `historical_figure="Julius Caesar"` and `achievement="crossing the Rubicon"`. Print the generated list of messages.

<Accordion title="Solution">
  ```python theme={null}
  from langchain_core.prompts import ChatPromptTemplate

  chat_template = ChatPromptTemplate.from_messages([
      ("system", "You are {historical_figure}, a historical figure. Answer in their character."),
      ("human", "What was your greatest achievement?"),
      ("ai", "My greatest achievement was {achievement}."),
      ("human", "Why was {achievement} important?")
  ])

  prompt = chat_template.invoke({
      "historical_figure": "Julius Caesar",
      "achievement": "crossing the Rubicon"
  })

  for msg in prompt.to_messages():
      print(f"{msg.type.upper()}: {msg.content}")
  ```
</Accordion>

#### Exercise 2: Code Translator

Create a `ChatPromptTemplate` representing a code translation engine.

* System message: `"You are an expert software engineer that translates source code from \{source_lang\} to \{target_lang\}."`
* Human: `"Translate this code:\n\n\{code\}"`

Invoke this template with `source_lang="Python"`, `target_lang="JavaScript"`, and `code="print('Hello World')"` and print the messages.

<Accordion title="Solution">
  ```python theme={null}
  from langchain_core.prompts import ChatPromptTemplate

  chat_template = ChatPromptTemplate.from_messages([
      ("system", "You are an expert software engineer that translates source code from {source_lang} to {target_lang}."),
      ("human", "Translate this code:\n\n{code}")
  ])

  prompt = chat_template.invoke({
      "source_lang": "Python",
      "target_lang": "JavaScript",
      "code": "print('Hello World')"
  })

  for msg in prompt.to_messages():
      print(f"{msg.type.upper()}: {msg.content}")
  ```
</Accordion>

## 4. Variable Passing Mechanisms

When invoking templates or chains, you pass variables depending on the count of placeholders:

* **Single-Variable Shortcut**: If the template has exactly one placeholder (e.g., `\{variable\}`), you can pass a raw string. LangChain maps it automatically.
  ```python theme={null}
  prompt = ChatPromptTemplate.from_template("Explain {topic}")
  prompt.invoke("Python") # Shortcut
  ```
* **Multi-Variable Dictionary**: If the template has multiple placeholders, you must pass a dictionary of key-value pairs.
  ```python theme={null}
  prompt = ChatPromptTemplate.from_template("Translate {text} to {lang}")
  prompt.invoke({"text": "Hello", "lang": "Spanish"})
  ```

## 5. Extracting Responses: `.content` vs `.text` vs Direct Output

Depending on the component you invoke, the returned value has different structures. It is crucial to know how to extract the raw text response:

### 5.1 Use `.content` (For ChatModels)

When you invoke a **Chat Model** (e.g., initialized using `init_chat_model` for Groq or Gemini), the return value is an `AIMessage` object. To access the generated text, you **must use `.content`**.

```python theme={null}
response = llm.invoke("Hi")
print(type(response))   # <class 'langchain_core.messages.ai.AIMessage'>
print(response.content) # Extracts the raw text string
```

### 5.2 Use `.text` (For Few-Shot / Legacy formatting and outputs)

When formatting older or specific templates (like `FewShotPromptTemplate`), the formatted result is a `PromptValue` object. In these cases, you access the raw string representation using `.text`.

Additionally, some legacy LLM completion model classes (as opposed to modern `ChatModel` classes) or generation results return response structures where the generated text output itself is accessed via `.text`.

```python theme={null}
# 1. Formatting templates via format_prompt() returns a PromptValue
prompt_val = few_shot_prompt.format_prompt(input="hello")
print(prompt_val.text) # Returns raw string representation

# 2. Legacy model outputs or raw generation lists sometimes expose .text
```

### 5.3 Direct Output

If you are invoking a local pipeline (e.g., `HuggingFacePipeline`) or a chain containing a **StrOutputParser**, the return value is already a plain Python string (`str`), so you can print or use it directly.

```python theme={null}
# Using a parser extracts the content automatically
chain = prompt | llm | StrOutputParser()
response = chain.invoke({"topic": "AI"})

print(type(response)) # <class 'str'>
print(response)       # Prints directly
```
