1. What Is Prompt Engineering, and Why Is It So Important?

1.1 Rethinking the Prompt

Many beginners understand Prompt Engineering as “writing a good paragraph so AI will answer well.” As an AI Application Engineer, however, you need to understand it at a deeper level.

An LLM is essentially a conditional-probability generator. Given preceding text—the prompt—it generates the most likely continuation one token at a time according to a learned probability distribution. The central question in Prompt Engineering is therefore: how do we construct an input sequence so that the model’s probability distribution shifts toward the output space we want?

Consider a simple analogy. Suppose you assign a task to a highly capable new colleague who knows nothing about your specific needs. The more ambiguous your instructions, the further the result will drift from your expectations. The more precise your instructions and the more concrete your references, the more likely the result is to match what you intended. Prompt Engineering is the technique of communicating with that precision.

1.2 The Place of a Prompt in AI Application Development

In a real AI application architecture, a prompt is not a sentence casually written by a user. It is an engineered module. A typical prompt contains:

System Prompt(系统指令)    → 定义模型的角色、行为边界、输出格式
Context(上下文)           → 提供背景信息、相关数据、历史对话
User Input(用户输入)       → 实际的问题或任务
Output Specification(输出规范) → 期望的格式、长度、风格

Together, these four components form the complete prompt sent to the LLM. As an AI Application Engineer, much of the code you write is actually assembling this prompt dynamically.


2. Clear Instructions

2.1 Core Principle

Clear Instructions are the most fundamental and important Prompt Engineering technique. The principle is intuitive: the clearer and more specific your instructions, the more deterministic the model’s output becomes and the less room it has to drift randomly.

From a probabilistic perspective, an ambiguous prompt leaves high probability on several possible output directions, making the result hard to control. A clear prompt greatly narrows the possible output distribution and concentrates generation on the content you want.

2.2 Six Practical Principles

Principle 1: Specify a Role and Identity (Role Setting)

# ❌ 模糊的 prompt
prompt = "帮我分析这段代码的问题"

# ✅ 清晰的 prompt
prompt = """你是一位拥有10年经验的 Python 后端工程师,专精代码审查。
请从以下维度分析这段代码的问题:
1. 逻辑正确性
2. 性能瓶颈
3. 安全隐患
4. 代码风格与可维护性"""

To understand why this works, recall what an LLM is: a conditional-probability model trained on an enormous body of text. Its training data contains text produced by many kinds of “roles” in many kinds of “situations”: the language physicians use in medical records, programmers’ phrasing in code reviews, and lawyers’ wording in legal opinions. Each belongs to a different text distribution.

When you write “you are a senior Python engineer” in the prompt, you are doing one thing: changing the model’s conditional-probability distribution. In mathematical terms, instead of computing P(output | task), the model computes P(output | role, task). These distributions can be very different.

What specifically happens inside the Transformer? Once the tokens for “senior Python engineer” enter the model, they become reference points for all other tokens in the self-attention layers. Every time the model generates a new token, attention looks back at those role-description tokens, biasing the entire generation process toward textual patterns that resemble what a senior engineer would write in the training data. This affects the choice of terminology, depth of analysis, areas of focus, and more.

Think of selecting the “medicine” section in a library search system before searching for “cold.” Selecting the section does not change the search term, but it sharply narrows the search space, making the returned results more specialized and focused. Role setting does the same thing: it directs the model’s “attention” toward an area of its training data associated with a particular role.

Another important point is that this explains why more specific role descriptions work better. “You are an engineer” activates a very broad distribution, while “you are a backend engineer with ten years of experience specializing in distributed systems” activates a much more precise subdistribution. More conditions concentrate the probability distribution, making the output more deterministic.

Principle 2: Define the Output Format

# ❌ 模糊的格式要求
prompt = "列出学习 Python 的资源"

# ✅ 精确指定格式
prompt = """请推荐 5 个学习 Python 的在线资源。
对每个资源,请按以下 JSON 格式输出:
{
  "name": "资源名称",
  "url": "链接",
  "level": "beginner | intermediate | advanced",
  "focus": "主要学习方向",
  "reason": "推荐理由(一句话)"
}
请以 JSON 数组形式返回所有结果。"""

This is critically important in AI application development. Your code must parse the model’s output. If the format is unstable, your parser will fail frequently. Specifying a structured format such as JSON, XML, or a Markdown table is essential to application reliability.

This principle uses the LLM’s most fundamental generation mechanism: autoregressive generation.

Recall that an LLM generates one token at a time, and the probability of each new token depends on every previously generated token. This means that once a model begins producing a particular format, subsequent tokens become “locked” onto that format’s path.

What happens when you specify “return JSON” and provide a concrete JSON structure? When generation begins, the first token is very likely {, because JSON begins with { and the prompt explicitly asks for JSON. Once { has been generated, the probability of "name" rises sharply, because { is usually followed by a quoted key in the training data. After "name" comes :, then ", and so on. Each generation step is constrained by the output of the preceding step, and the complete output moves along the JSON “track” like a train.

That is why format specification is so effective. You do not need to command the model at every step. You only need to place it on the correct format at the start, and the autoregressive mechanism helps preserve that format.

There is also a more advanced implication. This is the theoretical basis of Constrained Decoding. Some frameworks, such as Outlines and Guidance, directly restrict which tokens are legal at each decoding step—for example, JSON syntax may allow only " or } at a particular position—and thereby enforce the output format at the inference-engine level. This is more reliable than prompt-only specification, but the principle is related: both exploit the path dependence of autoregressive generation.

Principle 3: Provide Constraints

prompt = """请为一款面向日本市场的健康饮品写一段广告文案。

约束条件:
- 字数:100-150个日文字符
- 语调:温暖、亲切,面向30-40岁女性
- 必须包含:产品名"朝のめぐみ"
- 不得包含:与竞品的直接比较、夸大的健康声明
- 格式:一个主标题 + 一段正文"""

This concentrates probability mass in the desired output space.

The principle can be understood through a concept from probability theory: the concentration and dispersion of probability mass.

Without constraints, the model’s output distribution spans an enormous space. For a request such as “write an advertisement,” the space includes every combination of length, from 10 to 1,000 characters; tone, from formal and humorous to emotional and calm; and structure, from plain paragraphs to headings and lists. Probability mass is spread over that vast space, with each output style receiving some probability. The result is highly variable.

When you add constraints—“100–150 characters, a warm and friendly tone, for women aged 30–40, and the product name must appear”—you are effectively pushing probability mass away from regions that violate the conditions and toward regions that satisfy them. Incompatible output paths become less likely and compatible paths more likely. Probability mass ends up concentrated in a much smaller output space, so the output becomes more controllable and stable.

From the perspective of attention, every concrete requirement in the constraints, such as “100–150 characters” and “warm and friendly,” produces a strong signal. When generating each token, the model looks back at those constraint tokens and includes them in the probability calculation at every step.

An interesting consequence is that conflicting constraints confuse the model. If you request both “brief and concise” and “explain every point in detail,” the constraints pull probability mass in opposite directions, causing the output to oscillate between styles. Good constraint design therefore requires all conditions to be consistent rather than contradictory.

Principle 4: Isolate Content with Delimiters

prompt = """请将以下用三重反引号包裹的用户评论分类为"正面"、"负面"或"中性"。

用户评论:
\```
这家餐厅的拉面味道还不错,但是等了40分钟实在太久了。下次可能会考虑其他店。
\```

请只输出分类结果,不需要解释。"""

This uses attention’s recognition of structural boundaries.

The principle relies on the Transformer learning the semantic meaning of structured markers during training.

LLM training data contains vast amounts of structured text: HTML and XML tags, Markdown notation, quotes and brackets in code, and so on. Through statistical regularities, the model learns an important pattern: content inside structural markers and content outside them serve different semantic functions. Text inside an HTML <title> tag is a title, text inside <p> is body content, and text inside <code> is code.

When you use tags such as <user_input>...</user_input> in a prompt, you are exploiting the model’s learned knowledge of structural boundaries. Its attention mechanism recognizes these tags and tends to treat the content inside them as “data” rather than “instructions.”

Why can XML tags work better than ordinary quotes or triple backticks? In the training data, XML tags carry especially strong boundary signals. XML is designed to separate content from metadata strictly, whereas quotation marks in natural language are often used for emphasis and have weaker boundary semantics. Statistical patterns in the training data determine the model’s differing sensitivity to each delimiter.

One point must be emphasized: this boundary recognition is soft, not hard. Unlike programming-language syntax, where unmatched brackets cause an error, an LLM’s understanding of delimiters is probabilistic. A sufficiently clever attack can still cross the boundary. This is why the prompt-injection article repeatedly stresses that delimiters are not a universal defense. They reduce risk; they do not eliminate it.

Principle 5: Break Complex Tasks into Steps

prompt = """请按以下步骤分析这篇新闻文章:

步骤 1:用一句话总结文章的核心事件
步骤 2:识别文章中提到的所有人物及其角色
步骤 3:判断文章的情感倾向(正面/负面/中性),并给出依据
步骤 4:基于以上分析,生成 3 个关键标签

文章内容:
---
{article_text}
---

请按步骤编号依次输出结果。"""

This uses autoregressive intermediate output as working memory. Because an LLM is autoregressive, earlier output affects later generation. When the model summarizes first, analyzes second, and judges last, the output of each earlier step becomes context for the later steps and helps the model deepen its analysis progressively.

The principle is closely related to Chain-of-Thought, but at a more fundamental level it exploits a key architectural limitation of LLMs: a Transformer has limited computational capacity in a single forward pass.

In a Transformer, the input passes through multiple self-attention and feed-forward layers to produce an output. Each layer has a fixed amount of computation, determined by hyperparameters such as the number of layers, hidden dimension, and number of attention heads. Therefore, the reasoning complexity the model can complete in one step—one forward pass—has a limit.

One step is enough for a simple task. A complex task such as “analyze an article → extract entities → determine sentiment → generate tags,” however, may exceed a single pass.

When you divide a task in the prompt into Step 1, Step 2, and Step 3, you use a useful property of autoregressive generation: the output generated in Step 1 becomes input context for Step 2. Each output is like an intermediate result written on scratch paper, expanding the model’s effective computational depth.

In other words, if the Transformer has N layers, a direct answer must complete all reasoning within N layers. If the task has three generated steps and each requires an N-layer forward pass, the total computational depth becomes 3N. The model gains more “room to think.”

This also explains why the order of steps matters. Put information-extraction steps first, such as summarizing the central event and identifying people, and judgment and synthesis steps later, such as assessing sentiment and generating tags. Earlier outputs become context for later steps, so information must be extracted before subsequent steps can refer to it. This mirrors human cognition: you cannot assess an article’s sentiment before understanding its content.

Principle 6: Say What to Do, Not Only What Not to Do

# ❌ 只说不做什么
prompt = "回答用户的问题,不要编造信息,不要太长,不要太短"

# ✅ 明确说做什么
prompt = """回答用户的问题。
- 只基于提供的文档内容回答
- 如果文档中没有相关信息,回复"根据现有资料无法回答此问题"
- 回答长度控制在 2-3 个段落
- 在回答末尾引用具体的文档段落作为出处"""

This uses the activation-spreading characteristics of a language model. An LLM’s probabilistic generation mechanism handles “do not do X” less reliably than “do Y.” Tell the model “do not think about an elephant,” and elephant-related tokens may receive more weight.

The underlying mechanism is subtle: when processing a negative instruction, an LLM first activates the concept being negated, and only then attempts to suppress it.

When the model processes “do not mention competitors,” token representations associated with “competitors” are activated first, because the model has to “understand” what a competitor is before it can understand that it should not mention one. But once those representations have been activated in attention, they have already received greater attention weight, making competitor-related content easier to generate later.

The result is strikingly similar to the “white bear effect” in human psychology, or Ironic Process Theory. When you tell yourself not to think of a white bear, an image of one involuntarily appears. Although LLMs and human brains work through entirely different mechanisms, the result is similar: the central concept in a negative instruction is “remembered” by the model.

By contrast, a positive instruction such as “answer only from the provided document” activates the concepts of “document content” and “answer.” Attention is guided in the right direction without the contradiction of activating a concept and then suppressing it.

In practice, prompt design should follow this rule: replace negative prohibition with positive direction. Change “do not fabricate information” to “answer only from known facts”; “do not be too long” to “use two or three paragraphs”; and “do not use jargon” to “explain it in language a high-school student can understand.” Each rewrite redirects the model’s attention from the direction you do not want toward the direction you do want.

Summary

In one sentence, the common underlying mechanism behind all six principles is this: they manipulate the Transformer’s attention distribution and the probability paths of autoregressive generation.

Role setting and constraints shift the overall probability distribution through attention. Output formats use the path-locking effect of autoregression. Delimiters use structural-boundary recognition learned from training data. Task decomposition uses intermediate output as expanded working memory. Positive instructions exploit the direction of semantic activation. They approach the problem from different angles, but ultimately do the same thing: concentrate the model’s probability distribution on the output space you want.

2.3 Clear Instructions in Code

In real development, you organize these principles into templates:

def build_analysis_prompt(user_text: str, language: str = "zh") -> str:
    """
    构建一个结构化的文本分析 prompt。
    注意:这就是 AI Application Engineer 的日常工作之一 ——
    将 prompt engineering 原则封装成可复用的函数。
    """
    system_prompt = f"""你是一位专业的文本分析助手。
你的任务是对用户提供的文本进行结构化分析。
输出语言:{"中文" if language == "zh" else "English"}"""

    user_prompt = f"""请分析以下文本,按指定的 JSON 格式输出结果。

待分析文本:
---
{user_text}
---

输出格式:
{{
  "summary": "一句话摘要",
  "sentiment": "positive | negative | neutral",
  "confidence": 0.0-1.0,
  "key_entities": ["实体1", "实体2"],
  "topics": ["话题1", "话题2"]
}}

要求:
1. summary 不超过 50 个字
2. confidence 为你对 sentiment 判断的置信度
3. key_entities 最多提取 5 个
4. 只输出 JSON,不要添加任何其他文字"""

    return system_prompt, user_prompt

3. Few-Shot Prompting

3.1 Core Principle

Few-shot prompting provides the model with several input-to-output examples inside the prompt, allowing it to infer the intended pattern from those examples and apply the pattern to a new input.

The technique’s theoretical foundation comes from the 2020 GPT-3 paper Language Models are Few-Shot Learners. It found that large language models can “learn” new tasks without fine-tuning simply by seeing a small number of examples in the prompt. This ability is known as In-Context Learning.

Why does it work? From the perspective of Transformer attention, when the model processes a new input, self-attention looks back at the preceding examples. It detects the mapping pattern between the examples’ inputs and outputs—such as format, style, or logical rules—and reproduces that pattern when generating the new output. Few-shot prompting essentially uses attention for pattern matching and transfer.

3.2 Categories by Number of Shots

Zero-shot:  不给示例,直接给任务指令
One-shot:   给 1 个示例
Few-shot:   给 2-5 个示例(最常用)
Many-shot:  给更多示例(通常 10+ 个,在 context window 足够大时使用)

3.3 Practical Example: Sentiment Analysis

# Zero-shot(零样本)
zero_shot_prompt = """判断以下评论的情感倾向。

评论:这家店的服务态度真的很差,等了一个小时才上菜。
情感:"""
# 模型可能输出"负面",也可能输出"消极"、"不好"、"negative" —— 格式不可控

# Few-shot(少样本)
few_shot_prompt = """判断评论的情感倾向。

评论:今天天气真好,心情特别愉快!
情感:positive

评论:这个产品质量一般般,没什么特别的。
情感:neutral

评论:快递太慢了,包装还破了,非常失望。
情感:negative

评论:这家店的服务态度真的很差,等了一个小时才上菜。
情感:"""
# 模型现在非常明确地知道:输出只能是 positive / neutral / negative

Notice the difference. The three few-shot examples communicate several layers of information at once: there are only three outputs—positive, neutral, and negative; the output uses English labels instead of Chinese descriptions; and each label corresponds to a particular sentiment strength. None of these “rules” need to be explained in prose because the model infers them from the examples.

3.4 Advanced Few-Shot Techniques

Technique 1: Diversity Matters More Than Quantity

# ❌ 差的 few-shot:示例太相似
bad_examples = """
输入:苹果 → 类别:水果
输入:香蕉 → 类别:水果
输入:橙子 → 类别:水果
"""

# ✅ 好的 few-shot:覆盖不同类别和边界情况
good_examples = """
输入:苹果 → 类别:水果
输入:胡萝卜 → 类别:蔬菜
输入:三文鱼 → 类别:海鲜
输入:番茄 → 类别:蔬菜(注:虽然有时被归为水果,但在烹饪分类中属于蔬菜)
"""

The “tomato” example is important. It demonstrates how the model should handle an edge case and shows that an explanatory note may be added.

Technique 2: Example Order Affects Results

Research shows that the order of few-shot examples significantly affects the output. A common recommendation is to place the example most similar to the current input last, closest to the actual question, because an LLM’s attention tends to favor nearby content through recency bias.

Technique 3: Select Examples Dynamically in Code

import numpy as np
from typing import List, Tuple

class DynamicFewShotSelector:
    """
    动态 few-shot 示例选择器。
    核心思路:根据用户输入,从示例库中选择最相关的示例。
    这是 AI 应用开发中的高频模式 —— 不要硬编码示例,要动态检索。
    """

    def __init__(self, examples: List[Tuple[str, str]], embedding_func):
        """
        参数:
            examples: [(input_text, output_text), ...] 示例库
            embedding_func: 将文本转为向量的函数
        """
        self.examples = examples
        self.embedding_func = embedding_func
        # 预计算所有示例的 embedding
        self.example_embeddings = [
            embedding_func(inp) for inp, _ in examples
        ]

    def select(self, query: str, k: int = 3) -> List[Tuple[str, str]]:
        """
        选出与 query 最相似的 k 个示例。
        使用余弦相似度作为相似性度量。
        """
        query_embedding = self.embedding_func(query)

        # 计算 query 与每个示例的余弦相似度
        similarities = []
        for emb in self.example_embeddings:
            cos_sim = np.dot(query_embedding, emb) / (
                np.linalg.norm(query_embedding) * np.linalg.norm(emb)
            )
            similarities.append(cos_sim)

        # 取 top-k 最相似的示例
        top_k_indices = np.argsort(similarities)[-k:]

        # 返回示例,注意:最相似的放在最后(利用 recency bias)
        return [self.examples[i] for i in top_k_indices]

    def build_prompt(self, query: str, k: int = 3) -> str:
        """组装完整的 few-shot prompt"""
        selected = self.select(query, k)

        prompt_parts = []
        for inp, out in selected:
            prompt_parts.append(f"输入:{inp}\n输出:{out}")

        prompt_parts.append(f"输入:{query}\n输出:")

        return "\n\n".join(prompt_parts)

This pattern is known as Dynamic Few-Shot Selection, a sub-application of RAG, or Retrieval-Augmented Generation. In production, the example library may contain thousands of entries, and each request dynamically selects the three to five most relevant as few-shot examples.

3.5 Limitations of Few-Shot Prompting

Few-shot prompting is not universal. It has several clear limitations. First, it consumes tokens: every example uses context-window capacity and increases API cost. Second, it has limited effect on complex reasoning tasks: when a task requires multiple reasoning steps, input-output examples alone are not enough; the model needs to see the reasoning process, which is the problem Chain-of-Thought addresses. Third, example quality is critical: incorrect examples “teach” the model the wrong behavior.


4. Chain-of-Thought

4.1 Core Principle

Chain-of-Thought (CoT) prompting was introduced in 2022 by Jason Wei and colleagues at Google Brain. Its central idea is simple but highly effective: before giving the final answer, have the model output intermediate reasoning steps.

Why does this improve performance? Again, the answer lies in the autoregressive nature of LLMs. An LLM generates one token at a time, with each new token depending on all previously generated tokens. When the model answers directly, it has to complete all reasoning “in one step,” entirely within a forward pass of the neural network. But the model’s capacity for single-step computation is limited.

When you ask the model to write out reasoning steps first, those steps become context for subsequent generation, effectively providing “external working memory.” The model can focus on one subproblem at a time, write down the result, and use it as input to the next step. This resembles a human writing intermediate steps on scratch paper while solving a math problem.

4.2 A Basic CoT Example

# ❌ 不使用 CoT(直接要答案)
prompt_no_cot = """
餐厅账单是 180 元,需要加 10% 的服务费,三个人平分。
每人需要付多少钱?
"""
# 模型可能直接给出答案,但复杂数学问题时容易出错

# ✅ 使用 CoT(要求展示推理过程)
prompt_with_cot = """
餐厅账单是 180 元,需要加 10% 的服务费,三个人平分。
每人需要付多少钱?

请一步一步地思考这个问题,展示你的推理过程,最后给出答案。
"""
# 模型输出:
# 1. 原始账单:180 元
# 2. 服务费:180 × 10% = 18 元
# 3. 总计:180 + 18 = 198 元
# 4. 每人:198 ÷ 3 = 66 元
# 答案:每人需要付 66 元

4.3 Three Ways to Implement CoT

Method 1: Zero-Shot CoT, the Simplest

Add one effective sentence to the end of the prompt:

prompt = f"""
{your_question}

Let's think step by step.
"""

The phrase “Let’s think step by step” was validated as an effective zero-shot CoT trigger in the 2022 paper Large Language Models are Zero-Shot Reasoners. Why does it work? A large amount of reasoning text in the training data—textbooks, forum answers, and academic papers—contains similar stepwise patterns. The phrase triggers the model’s recall of those patterns.

Method 2: Few-Shot CoT with Examples

prompt = """请解决以下数学问题。

问题:小明有 5 个苹果,他给了小红 2 个,然后妈妈又给了他 3 个。小明现在有几个苹果?
推理过程:
- 初始:小明有 5 个苹果
- 给了小红 2 个后:5 - 2 = 3 个
- 妈妈给了 3 个后:3 + 3 = 6 个
答案:6 个

问题:一个图书馆有 3 层,每层有 4 个书架,每个书架有 5 层隔板,每层隔板放 8 本书。图书馆一共有多少本书?
推理过程:
- 每个书架的书:5 层 × 8 本 = 40 本
- 每层楼的书:4 个书架 × 40 本 = 160 本
- 整个图书馆:3 层 × 160 本 = 480 本
答案:480 本

问题:{new_question}
推理过程:"""

Notice that the examples show not only the input and answer but also the full reasoning chain. Compared with ordinary few-shot prompting, this adds one crucial piece of information: the method and format of reasoning.

Method 3: Structured CoT for Engineering

In AI application development, you often need the model’s reasoning process to be structured and parseable:

prompt = """你是一个医疗分诊助手。根据患者描述,进行初步分诊评估。

请严格按以下结构输出你的分析:

<reasoning>
<symptom_extraction>
[从描述中提取关键症状,列出每个症状]
</symptom_extraction>

<severity_assessment>
[评估每个症状的严重程度:轻微/中等/严重]
</severity_assessment>

<possible_conditions>
[基于症状组合,列出可能的病症,按可能性从高到低排列]
</possible_conditions>

<urgency_decision>
[综合判断:常规就诊/尽快就诊/紧急就医]
</urgency_decision>
</reasoning>

<final_answer>
[分诊建议(简洁版)]
</final_answer>

患者描述:{patient_description}"""

The value of structured CoT is that your code can parse reasoning and final_answer separately, store the reasoning process in logs for audit and debugging, and show only final_answer to the end user.

4.4 CoT in Code: Building an Analyzer with a Reasoning Chain

import json
import re
from dataclasses import dataclass
from typing import Optional


@dataclass
class ReasoningResult:
    """封装 CoT 输出的数据结构"""
    reasoning_steps: list[str]   # 推理步骤
    final_answer: str            # 最终答案
    confidence: float            # 置信度
    raw_output: str              # 模型原始输出


class ChainOfThoughtAnalyzer:
    """
    一个带有 Chain-of-Thought 推理能力的分析器。
    演示了如何在 AI 应用中工程化地使用 CoT。
    """

    def __init__(self, llm_client, model: str = "claude-sonnet-4-20250514"):
        self.client = llm_client
        self.model = model

    def analyze(self, question: str) -> ReasoningResult:
        """
        对问题进行 CoT 分析。
        关键设计:将推理过程和最终答案分离,方便下游处理。
        """
        prompt = self._build_cot_prompt(question)

        response = self.client.messages.create(
            model=self.model,
            max_tokens=2000,
            messages=[
                {"role": "system", "content": self._system_prompt()},
                {"role": "user", "content": prompt}
            ]
        )

        raw_output = response.content[0].text
        return self._parse_response(raw_output)

    def _system_prompt(self) -> str:
        return """你是一个严谨的分析助手。
在回答任何问题之前,你必须先展示完整的推理过程。
你的输出必须严格遵循指定的格式。"""

    def _build_cot_prompt(self, question: str) -> str:
        return f"""请分析以下问题。

问题:{question}

请按以下格式输出:

<reasoning>
步骤1: [第一步分析]
步骤2: [第二步分析]
...(根据需要添加更多步骤)
</reasoning>

<confidence>
[0.0 到 1.0 之间的数字,表示你对答案的置信度]
</confidence>

<answer>
[最终答案]
</answer>"""

    def _parse_response(self, raw: str) -> ReasoningResult:
        """
        解析模型的结构化输出。
        这就是为什么我们需要固定格式 —— 为了可靠地解析。
        """
        # 提取推理步骤
        reasoning_match = re.search(
            r'<reasoning>(.*?)</reasoning>', raw, re.DOTALL
        )
        reasoning_text = reasoning_match.group(1).strip() if reasoning_match else ""

        steps = [
            line.strip() for line in reasoning_text.split('\n')
            if line.strip() and line.strip().startswith('步骤')
        ]

        # 提取置信度
        conf_match = re.search(
            r'<confidence>(.*?)</confidence>', raw, re.DOTALL
        )
        try:
            confidence = float(conf_match.group(1).strip()) if conf_match else 0.5
        except ValueError:
            confidence = 0.5

        # 提取最终答案
        answer_match = re.search(
            r'<answer>(.*?)</answer>', raw, re.DOTALL
        )
        final_answer = answer_match.group(1).strip() if answer_match else raw

        return ReasoningResult(
            reasoning_steps=steps,
            final_answer=final_answer,
            confidence=confidence,
            raw_output=raw
        )

4.5 When to Use CoT

CoT is not needed in every situation. It is best suited to mathematical and logical problems requiring multiple reasoning steps, decisions that must combine several factors, complex text understanding and inference tasks, and applications requiring explainability in fields such as healthcare, law, and finance.

For other scenarios, CoT may be unnecessary: simple factual retrieval such as “What is the capital of France?”, creative writing and content generation, or simple format conversion and translation. In these cases, CoT consumes tokens, increasing cost and latency, without significantly improving quality.


5. Combining the Three Techniques

In real AI applications, these three techniques are almost always combined. The following example shows the prompt design for an automatic customer-email response system:

def build_email_reply_prompt(
    customer_email: str,
    customer_history: str,
    product_info: str
) -> tuple[str, str]:
    """
    综合运用 Clear Instructions + Few-Shot + CoT 的实战示例。
    场景:电商客服自动回复系统。
    """

    system_prompt = """你是"TechShop"的高级客服代表。
你的目标是:准确理解客户问题,提供有帮助的回复,维护品牌形象。

核心规则:
1. 始终保持礼貌和专业
2. 如果涉及退款,需要先验证订单信息
3. 如果问题超出你的处理范围,引导客户联系人工客服
4. 回复长度控制在 100-200 字"""  # ← Clear Instructions

    user_prompt = f"""请根据客户邮件生成回复。

=== 客户历史 ===
{customer_history}

=== 产品信息 ===
{product_info}

=== 参考示例 ===

【示例1】
客户邮件:我上周买的蓝牙耳机左耳没声音了,能换一个吗?
思考过程:
- 问题类型:产品质量问题
- 购买时间:一周内,在保修期
- 处理方式:应该提供换货服务
- 需要信息:订单号,以便查询
回复:您好!很抱歉听到您的耳机出现了问题。一周内的产品质量问题我们可以为您免费更换。麻烦您提供一下订单号,我会尽快为您安排换货流程。如有其他问题,随时联系我们!

【示例2】
客户邮件:你们能不能把我的订单地址改成大阪市?我下周要出差。
思考过程:
- 问题类型:订单修改(地址变更)
- 关键因素:需要确认订单是否已发货
- 处理方式:如果未发货可以修改,已发货需要拦截或转寄
- 需要信息:订单号,以便查询发货状态
回复:您好!地址变更没问题,不过需要先确认您的订单发货状态。请提供您的订单号,如果还未发货我们可以直接修改地址;如果已发货,我会帮您联系物流进行转寄。

=== 当前客户邮件 ===
{customer_email}

请先进行思考分析,然后生成回复。按以下格式输出:

思考过程:
[你的分析]

回复:
[给客户的回复]"""  # ← Few-Shot + CoT 组合

    return system_prompt, user_prompt

In this example, Clear Instructions define the role, rules, and constraints. Few-Shot provides two examples covering different scenarios and demonstrates the desired analysis method and response style. CoT requires analysis before the response so that the answer has a reasoned basis. Together, they form a reliable production-grade prompt.


6. Key Takeaways

Clear Instructions solve the problem of whether the model knows what you want. Precise instructions and constraints narrow the model’s output space and form the foundation of all prompt engineering.

Few-Shot solves the problem of whether the model knows what kind of result you want. Examples demonstrate the intended pattern and use the LLM’s in-context learning ability to make the model imitate that pattern.

Chain-of-Thought solves the problem of whether the model can reason through the task. Externalizing the reasoning process gives the model “room to think” and significantly improves accuracy on complex reasoning tasks.

As an AI Application Engineer, you need to combine these techniques flexibly for each scenario and find the best balance among quality, cost, and latency.