01 — Introduction to Prompt Engineering¶
Learn the foundations of Prompt Engineering and understand how instructions, context, constraints, examples, and output requirements influence Large Language Model (LLM) behavior.
📖 Overview¶
Large Language Models (LLMs) provide a powerful natural-language interface to software systems. Instead of interacting only through traditional APIs and predefined forms, users and applications can communicate with models using natural-language instructions.
However, an LLM does not automatically know what the application expects from every request.
Consider:
The model may produce a technically correct response, but the result could vary in:
- Level of detail
- Target audience
- Structure
- Terminology
- Examples
- Output format
- Length
- Focus
A better instruction might be:
Explain microservices to a senior Java backend engineer.
Cover:
1. Service boundaries
2. Communication patterns
3. Data ownership
4. Failure handling
Use a production-oriented example and keep the explanation
under 500 words.
The second instruction provides much more information about the desired behavior.
This is the foundation of Prompt Engineering.
Prompt Engineering is the practice of designing and refining instructions and contextual inputs so that an LLM produces outputs that are useful, reliable, consistent, and appropriate for a particular task.
1. What Is Prompt Engineering?¶
Prompt Engineering is the systematic design of inputs provided to an LLM to guide its behavior toward a desired outcome.
A prompt can contain:
A simplified model is:
flowchart LR
A["Instructions"] --> F["Prompt"]
B["Context"] --> F
C["Examples"] --> F
D["Constraints"] --> F
E["Input Data"] --> F
F --> G["LLM"]
G --> H["Generated Output"]
The objective is not simply to write a longer prompt.
The objective is to provide the right information in the right structure.
2. Why Prompt Engineering Matters¶
An LLM generates responses based on the information and patterns available in its input context.
A vague request gives the model more freedom to interpret the task.
A well-defined request reduces ambiguity.
Compare:
Basic Prompt¶
More Specific Prompt¶
Explain Kubernetes to a Java backend engineer
who already understands Docker and microservices.
Cover:
- Pods
- Deployments
- Services
- ConfigMaps
- Secrets
Use one production-oriented example.
Keep the response under 600 words.
The second prompt establishes:
3. Prompt Engineering Is Not Model Training¶
Prompt Engineering and model fine-tuning are different techniques.
| Technique | Main Idea |
|---|---|
| Prompt Engineering | Change the input instructions |
| Few-shot Prompting | Provide examples in the prompt |
| RAG | Provide external context |
| Fine-Tuning | Update model parameters |
| PEFT / LoRA | Efficiently update a subset of parameters |
| Model Pretraining | Train the model on large-scale data |
Conceptually:
flowchart TD
A["Base LLM"] --> B["Prompt Engineering"]
A --> C["RAG"]
A --> D["Fine-Tuning"]
B --> E["Change Input"]
C --> F["Add External Context"]
D --> G["Change Model Parameters"]
E --> H["Application Behavior"]
F --> H
G --> H
Prompt Engineering changes how we communicate with the model.
Fine-tuning changes the model itself.
4. Prompt vs Prompt Engineering¶
A prompt is the input provided to a model.
Prompt Engineering is the process of designing, testing, evaluating, and improving those inputs.
For example:
Prompt Engineering asks:
Who is the summary for?
How long should it be?
What information matters?
What format should be returned?
Should unsupported claims be excluded?
Should technical terminology be preserved?
Therefore:
5. Anatomy of a Prompt¶
A production prompt may contain several components.
flowchart TD
A["System Instructions"] --> G["Complete Prompt"]
B["Task Instructions"] --> G
C["Context"] --> G
D["Examples"] --> G
E["Constraints"] --> G
F["User Input"] --> G
G --> H["LLM"]
H --> I["Output"]
The exact structure depends on the model API and application.
Common components include:
System Instructions¶
Define high-level behavior.
Task Instructions¶
Define what the model needs to do.
Context¶
Provide information needed for the task.
Constraints¶
Limit or guide the response.
Output Requirements¶
Define the expected format.
User Input¶
The actual request or variable data.
6. System, User, and Assistant Messages¶
Modern conversational LLM APIs commonly represent conversations using roles.
A simplified structure is:
For example:
[
{
"role": "system",
"content": "You are a senior Java architect."
},
{
"role": "user",
"content": "Explain event-driven architecture."
}
]
The exact message format depends on the model provider and API.
7. System Instructions¶
System instructions establish high-level rules for the model.
Example:
You are an enterprise AI architecture assistant.
Your audience is experienced backend engineers.
Prefer production-oriented explanations.
When discussing architecture:
- identify major components
- explain communication patterns
- discuss failure handling
- mention operational considerations
This creates a reusable behavioral foundation.
8. User Instructions¶
User instructions provide the task.
Example:
Compare synchronous REST communication
with asynchronous Kafka-based communication
for a payment processing system.
The complete interaction becomes:
sequenceDiagram
participant U as User
participant A as Application
participant L as LLM
U->>A: User request
A->>L: System instructions + user request
L->>A: Generated response
A->>U: Response
9. Context¶
Context gives the model information that is relevant to the task.
For example:
System Context:
The application is a payment platform.
Requirements:
- 10,000 TPS
- high availability
- idempotent processing
- asynchronous event processing
- auditability
Then:
The model now has information that can influence the answer.
10. Constraints¶
Constraints reduce ambiguity.
Examples:
Use Java and Spring Boot.
Do not introduce Kubernetes.
Use Kafka for asynchronous communication.
Return the architecture as a Mermaid diagram.
Keep the explanation below 800 words.
Constraints can cover:
11. Output Requirements¶
LLM output should often be designed for downstream software.
Instead of:
an application might request:
Return:
{
"sentiment": "positive|neutral|negative",
"confidence": 0.0-1.0,
"reason": "short explanation"
}
This is particularly important when the LLM is part of a software pipeline.
12. Prompt Engineering for Software Systems¶
A traditional application might look like:
flowchart LR
A["Application"] --> B["Business Logic"]
B --> C["Database"]
C --> D["Response"]
An LLM-powered application adds a probabilistic language-processing component:
flowchart LR
A["Application"] --> B["Prompt Construction"]
B --> C["LLM"]
C --> D["Output Validation"]
D --> E["Business Logic"]
E --> F["Response"]
This creates additional engineering concerns:
13. Prompt Engineering as an Interface¶
A useful way to think about a prompt is as an interface contract between the application and the LLM.
Traditional API:
LLM application:
The less ambiguous this contract is, the easier the application becomes to test and operate.
14. From Vague Prompt to Structured Prompt¶
Consider:
This leaves many questions unanswered.
A structured version:
Analyze the customer feedback below.
Task:
Classify the sentiment.
Possible values:
- positive
- neutral
- negative
Also identify the main topic.
Return JSON with:
{
"sentiment": "...",
"topic": "...",
"confidence": 0.0
}
Customer feedback:
{{feedback}}
The second prompt defines:
15. Prompt Variables¶
Production applications usually construct prompts dynamically.
For example:
customer_feedback = """
The payment failed twice but support resolved the issue quickly.
"""
prompt = f"""
Analyze the following customer feedback.
Return:
- sentiment
- primary topic
- short reason
Customer feedback:
{customer_feedback}
"""
This separates:
16. Prompt Templates¶
A reusable template might look like:
prompt_template = """
You are a {role}.
Analyze the following {document_type}.
Task:
{task}
Constraints:
{constraints}
Document:
{document}
"""
The application can provide different values:
prompt = prompt_template.format(
role="financial analyst",
document_type="annual report",
task="identify major revenue risks",
constraints="Return five bullet points.",
document=report_text
)
This is a fundamental pattern for production LLM applications.
17. Prompt Composition¶
Complex applications rarely have only one piece of prompt text.
They may combine:
System Instructions
+
Task Instructions
+
Retrieved Context
+
Conversation History
+
User Input
+
Output Requirements
Conceptually:
flowchart TD
A["System Instructions"] --> G["Prompt Builder"]
B["Task"] --> G
C["Retrieved Context"] --> G
D["Conversation History"] --> G
E["User Input"] --> G
F["Output Requirements"] --> G
G --> H["LLM"]
H --> I["Response"]
This becomes especially important when building RAG systems in later chapters.
18. Prompt Engineering and RAG¶
Prompt Engineering provides the instructions.
RAG provides external context.
Together:
flowchart LR
A["User Query"] --> B["Retrieval"]
B --> C["Relevant Context"]
C --> D["Prompt"]
A --> D
D --> E["LLM"]
E --> F["Answer"]
The prompt might contain:
System Instructions
You are an enterprise knowledge assistant.
Use only the supplied context.
If the answer cannot be found in the context,
say that the information is unavailable.
Context:
{{retrieved_context}}
Question:
{{user_question}}
This pattern will be explored in depth later in Part IV.
19. Prompt Engineering and Grounding¶
A model may generate information that is not present in the supplied context.
For knowledge-intensive applications, prompts can establish grounding instructions.
Example:
Answer the question using only the provided context.
Do not introduce facts that are not supported by the context.
If the context does not contain enough information,
respond with:
"I don't have enough information to answer this."
However, prompt instructions alone do not guarantee factuality.
Production systems should combine:
20. Prompt Engineering Is an Iterative Process¶
A prompt should not be considered production-ready after writing it once.
A practical workflow is:
flowchart TD
A["Define Task"] --> B["Create Initial Prompt"]
B --> C["Test"]
C --> D["Evaluate"]
D --> E["Identify Failure Modes"]
E --> F["Refine Prompt"]
F --> C
C --> G["Production Candidate"]
The key word is evaluation.
Without evaluation, prompt optimization becomes subjective.
21. Prompt Evaluation¶
A prompt can be evaluated using:
For example:
| Metric | Question |
|---|---|
| Accuracy | Is the answer correct? |
| Relevance | Does it address the task? |
| Completeness | Are important points covered? |
| Consistency | Does it behave similarly across inputs? |
| Groundedness | Is it supported by available context? |
| Format Compliance | Does it follow the required schema? |
| Latency | Is the response fast enough? |
| Cost | Is token usage acceptable? |
22. Prompt Test Cases¶
Do not test a prompt using only one example.
Create a dataset:
For example:
test_cases = [
{
"input": "Payment succeeded",
"expected": "positive"
},
{
"input": "Payment failed",
"expected": "negative"
},
{
"input": "Payment is still processing",
"expected": "neutral"
}
]
Then evaluate the prompt against all cases.
23. Prompt Regression Testing¶
Changing a prompt can improve one scenario while breaking another.
Therefore:
flowchart LR
A["Prompt v1"] --> B["Evaluation Suite"]
B --> C["Baseline Metrics"]
D["Prompt v2"] --> B
B --> E["New Metrics"]
C --> F["Compare"]
E --> F
F --> G{"Improved?"}
G -->|Yes| H["Candidate"]
G -->|No| I["Reject / Refine"]
This is the beginning of PromptOps thinking.
24. Prompt Versioning¶
Treat important prompts like source code.
Example:
prompts/
├── customer-support/
│ ├── v1.txt
│ ├── v2.txt
│ └── v3.txt
│
├── document-summary/
│ ├── v1.txt
│ └── v2.txt
│
└── classification/
├── v1.txt
└── v2.txt
A production system should be able to identify which prompt version generated a response.
25. Prompt Metadata¶
A production prompt may have metadata such as:
{
"prompt_name": "customer-support-classification",
"version": "3",
"model": "validated-model-version",
"owner": "ai-platform",
"purpose": "customer sentiment classification"
}
This improves traceability.
26. Prompt Engineering and Model Parameters¶
Prompt behavior is influenced not only by the prompt itself but also by generation configuration.
Common parameters include:
A simplified generation pipeline is:
flowchart LR
A["Prompt"] --> B["LLM"]
C["Generation Parameters"] --> B
B --> D["Generated Tokens"]
Generation strategies are covered in more detail in the LLM chapters of Part III.
27. Prompt Length and Context¶
LLMs operate within a context window.
A simplified representation is:
Context Window
┌─────────────────────────────────────────┐
│ System Instructions │
│ Conversation History │
│ Retrieved Context │
│ User Input │
│ Output Space │
└─────────────────────────────────────────┘
The application must manage available context carefully.
Adding more text does not automatically improve the answer.
28. More Context Is Not Always Better¶
Consider:
versus:
The second may increase:
Therefore:
Prompt Engineering is also context engineering.
The goal is to provide the model with the information required for the task without unnecessary noise.
29. Prompt Injection Awareness¶
LLM applications may receive untrusted text.
For example, a retrieved document could contain:
The application must distinguish between:
and:
A conceptual architecture is:
flowchart TD
A["Trusted System Instructions"] --> C["Prompt Construction"]
B["Untrusted User / Document Content"] --> C
C --> D["LLM"]
D --> E["Output Validation"]
Prompt Engineering therefore has a security dimension.
Detailed enterprise AI security and agent security are covered in later modules.
30. Prompt Injection vs Prompt Engineering¶
Prompt Engineering asks:
Prompt Injection asks:
They are related but different problems.
A production AI system needs both:
31. Prompt Engineering and Application Boundaries¶
An important engineering principle is:
Do not rely on the prompt as the only security boundary.
For example, this is not sufficient:
If the model has access to a deletion tool, the application should independently enforce authorization.
Better:
flowchart LR
A["LLM Decision"] --> B["Tool Request"]
B --> C["Application Validation"]
C --> D["Authorization"]
D --> E["Tool Execution"]
The prompt provides guidance.
The application enforces policy.
32. Prompt Engineering for Backend Engineers¶
Backend engineers can think of prompts similarly to APIs.
Traditional API design:
LLM application:
The major difference is that LLM output is probabilistic.
Therefore, the application should not blindly trust it.
33. LLM Output Validation¶
Suppose the application expects:
The application should validate:
Is the response valid JSON?
↓
Are required fields present?
↓
Are values allowed?
↓
Are types correct?
↓
Can the application safely continue?
This pattern will be explored further in the Structured Outputs & Output Parsing chapter.
34. A Simple Python LLM Prompt Example¶
A generic provider SDK may expose an interface similar to:
system_prompt = """
You are a senior backend architecture assistant.
Provide concise, production-oriented answers.
"""
user_prompt = """
Explain when to use synchronous REST
and when to use asynchronous messaging.
"""
messages = [
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": user_prompt
}
]
# client.chat(...) or the provider-specific API
# would send the messages to the selected LLM.
The exact API depends on the model provider.
The important concept is:
35. A Reusable Prompt Builder¶
A simple application can encapsulate prompt construction.
def build_prompt(topic: str, audience: str) -> str:
return f"""
You are a technical instructor.
Audience:
{audience}
Task:
Explain the following topic:
{topic}
Requirements:
- Use clear technical terminology.
- Include one practical example.
- Focus on production considerations.
"""
Usage:
This is a simple example of treating prompt construction as application code.
36. Prompt Template with Context¶
A RAG-oriented application may use:
def build_rag_prompt(question: str, context: str) -> str:
return f"""
You are an enterprise knowledge assistant.
Answer the question using only the supplied context.
If the context does not contain enough information,
state that the information is unavailable.
Context:
{context}
Question:
{question}
"""
This pattern will become central to the RAG chapters later in this module.
37. Framework Example: LangChain¶
Frameworks can simplify prompt construction.
A conceptual LangChain example:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
(
"system",
"You are a senior backend architecture assistant."
),
(
"human",
"Explain {topic} for {audience}."
)
])
messages = prompt.invoke({
"topic": "event-driven architecture",
"audience": "Java backend engineers"
})
The important concept is not the framework syntax.
The underlying pattern is:
Dedicated LangChain concepts and framework architecture are covered later in Part VIII.
38. Framework Example: LlamaIndex¶
A similar prompt-template concept can be implemented using LlamaIndex.
For example:
from llama_index.core import PromptTemplate
template = PromptTemplate(
"""
Explain {topic} for {audience}.
Include:
- definition
- architecture
- production considerations
"""
)
prompt = template.format(
topic="event-driven architecture",
audience="backend engineers"
)
Again, the underlying concept is:
The framework is simply one implementation mechanism.
39. Prompt Engineering Workflow¶
A practical engineering workflow is:
flowchart TD
A["Define Business Task"] --> B["Identify Required Output"]
B --> C["Design Initial Prompt"]
C --> D["Create Test Dataset"]
D --> E["Run Evaluation"]
E --> F["Analyze Failures"]
F --> G["Refine Prompt"]
G --> E
E --> H["Version Prompt"]
H --> I["Deploy"]
I --> J["Monitor"]
J --> K["Collect Feedback"]
K --> G
This is more reliable than manually changing prompts until the output "looks good."
40. Production Prompt Engineering¶
A production prompt should ideally have:
Clear Objective
+
Defined Audience
+
Relevant Context
+
Explicit Constraints
+
Expected Output
+
Validation
+
Evaluation
+
Versioning
+
Observability
Conceptually:
flowchart TD
A["Prompt Definition"] --> B["Version Control"]
B --> C["Evaluation"]
C --> D["Deployment"]
D --> E["Observability"]
E --> F["Feedback"]
F --> A
41. Prompt Engineering in an Enterprise AI Platform¶
flowchart TD
A["User / Application"] --> B["Prompt Template"]
B --> C["Context Builder"]
C --> D["LLM"]
D --> E["Output Validation"]
E --> F["Business Logic"]
F --> G["Response"]
B --> H["Prompt Registry"]
D --> I["LLM Observability"]
E --> J["Evaluation"]
This illustrates that prompt engineering is not isolated prompt writing.
It becomes part of the application engineering lifecycle.
42. Common Prompt Engineering Mistakes¶
Mistake 1 — Being Too Vague¶
Better:
Explain relational databases to a Java backend engineer.
Cover:
- tables
- indexes
- transactions
- isolation levels
Include one production example.
Mistake 2 — Overloading the Prompt¶
A prompt containing excessive irrelevant instructions can introduce noise.
Prefer:
over:
Mistake 3 — No Output Contract¶
If downstream software expects structured data, define the expected format.
Mistake 4 — No Evaluation¶
A prompt that works for one example may fail for many others.
Mistake 5 — Treating the LLM as Deterministic¶
LLM outputs can vary.
Production systems need:
Mistake 6 — Putting Security Only in the Prompt¶
Prompts are not authorization systems.
Use application-level security controls.
Mistake 7 — Ignoring Cost¶
Long prompts increase token consumption.
Track:
Mistake 8 — Ignoring Latency¶
Prompt size, model choice, generation length, and application architecture can affect latency.
43. Prompt Engineering Quality Checklist¶
Before deploying a prompt, ask:
[ ] Is the objective clear?
[ ] Is the intended audience defined?
[ ] Is the relevant context included?
[ ] Are unnecessary instructions removed?
[ ] Are constraints explicit?
[ ] Is the expected output format clear?
[ ] Has the prompt been tested against multiple examples?
[ ] Are failure cases included?
[ ] Is the prompt version controlled?
[ ] Are outputs validated?
[ ] Are quality metrics defined?
[ ] Are latency and token costs measured?
[ ] Are security risks considered?
[ ] Can the prompt be rolled back?
44. Prompt Engineering vs Context Engineering¶
Prompt Engineering traditionally focuses on designing instructions.
Modern LLM applications also require careful management of:
This broader concern can be thought of as context engineering.
For the foundational concepts in this handbook:
As RAG and agentic systems become more complex, context management becomes increasingly important.
45. Prompt Engineering and the LLM Application Stack¶
flowchart TD
A["User"] --> B["Application API"]
B --> C["Prompt / Context Builder"]
C --> D["LLM"]
D --> E["Output Parser"]
E --> F["Business Logic"]
F --> G["Response"]
C --> H["Retrieval"]
C --> I["Conversation Context"]
C --> J["Application Data"]
Prompt Engineering therefore sits between:
and:
46. Production Workflow¶
A production-oriented Prompt Engineering workflow can be summarized as:
1. Define the task.
2. Identify the intended users.
3. Define the desired output.
4. Identify required context.
5. Write an initial prompt.
6. Add explicit constraints.
7. Create representative test cases.
8. Evaluate the prompt.
9. Identify failure modes.
10. Refine the prompt.
11. Version the prompt.
12. Validate model output.
13. Measure quality, latency, and cost.
14. Deploy the prompt.
15. Monitor production behavior.
16. Collect feedback.
17. Re-evaluate and improve.
47. Key Takeaways¶
- Prompt Engineering is the systematic design and optimization of inputs provided to an LLM.
- A prompt can contain instructions, context, examples, constraints, input data, and output requirements.
- Prompt Engineering is different from fine-tuning because it changes the input rather than model parameters.
- Clear prompts reduce ambiguity.
- Context provides information required for a task.
- Constraints help control scope and behavior.
- Output requirements make LLM responses easier for applications to consume.
- Prompt templates allow applications to reuse prompt structures with dynamic data.
- Production prompts should be versioned and evaluated.
- Prompt quality should be measured using representative test cases rather than a single example.
- LLM output should be validated before being used by application logic.
- Prompts should not be treated as security boundaries.
- Prompt injection is an important security consideration when processing untrusted content.
- Prompt length affects context usage, latency, and cost.
- More context does not automatically mean better results.
- RAG combines prompt instructions with retrieved external context.
- LangChain and LlamaIndex can be used as implementation examples, but understanding the underlying concept is more important than learning a framework API.
- Production Prompt Engineering is an iterative engineering lifecycle:
48. Chapter Navigation¶
Part IV — Prompt Engineering & RAG Fundamentals¶
Previous Chapter: Part III — Foundation Models, Large Language Models & Generative AI
Current Chapter: 01 — Introduction to Prompt Engineering
Next Chapter: 02. Prompt Engineering Fundamentals
Part IV Chapters¶
- 01. Introduction to Prompt Engineering
- 02. Prompt Engineering Fundamentals
- 03. Advanced Prompt Engineering
- 04. Prompt Design Patterns
- 05. Zero-shot, One-shot & Few-shot Prompting
- 06. Chain-of-Thought Prompting
- 07. ReAct Prompting
- 08. Structured Outputs & Output Parsing
- 09. Function Calling & Tool Calling
- 10. Embeddings in Practice
- 11. Document Processing & Vectorization
- 12. Document Chunking Strategies
- 13. Vector Database Fundamentals
- 14. Similarity Search Techniques
- 15. RAG Pipeline Components
- 16. Retrieval & Generation Pipeline
- 17. Vector Databases in RAG
- 18. Building Your First RAG Pipeline
- 19. RAG Evaluation Fundamentals
- 20. Enterprise Generative AI Application Architecture
- 21. Deploying AI Applications with Gradio
References¶
- Hugging Face — Transformers Documentation: https://huggingface.co/docs/transformers/
- Hugging Face — Prompting Documentation: https://huggingface.co/docs/transformers/
- OpenAI — API Documentation: https://platform.openai.com/docs/
- Anthropic — API Documentation: https://docs.anthropic.com/
- Google — Gemini API Documentation: https://ai.google.dev/
- LangChain — Documentation: https://python.langchain.com/
- LlamaIndex — Documentation: https://docs.llamaindex.ai/
- Gradio — Documentation: https://www.gradio.app/docs
- OpenAI — Best practices for prompt engineering: https://help.openai.com/
- Brown et al. — Language Models are Few-Shot Learners
- Wei et al. — Chain-of-Thought Prompting Elicits Reasoning in Large Language Models
- Yao et al. — ReAct: Synergizing Reasoning and Acting in Language Models
Enterprise AI Engineering Handbook
Building Production-Grade Enterprise AI Systems — One Chapter at a Time.