iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0

昨天我們用 Python + LLM API 做出了第一個 Chatbot。它已經可以接收我們的輸入、把 Request 送到模型,再把 Response 顯示在 Terminal。

目前的程式大概是這樣:

from openai import OpenAI

client = OpenAI()

while True:
    user_input = input("You: ")

    if user_input.lower() == "exit":
        break

    response = client.responses.create(
        model="gpt-5-mini",
        input=user_input
    )

    print("AI:", response.output_text)

它能回答問題,但有一個很明顯的問題:它沒有自己的角色。

我問 Python,它就講 Python;問英文,它就講英文;叫它寫故事,它也可以直接寫故事。對一個通用 Chatbot 來說沒有問題,但我最後想做的 Memora 是 Personal Learning Agent,所以我需要開始控制它「應該怎麼回答」。

今天要加入的第一個東西,就是 Prompt

Prompt 不只是「我問 AI 的那句話」

平常我們講 Prompt,很容易把它理解成使用者輸入的那句話。例如:

請解釋 present perfect。

這當然是一種 Prompt,但在真正開發 LLM Application 時,Prompt 通常不只包含使用者的問題。例如我希望模型知道:

你是一位英文學習助理。

使用者目前程度是 B1。

請用容易理解的方式回答。

避免一次解釋太多文法術語。

每次至少提供一個例句。

然後使用者真正輸入的是:

What is present perfect?

這時模型收到的就不只是「What is present perfect?」,而是同時有「這個 AI 應該怎麼工作」以及「使用者現在問了什麼」。

所以可以把它先分成兩個部分:

Instructions
「你應該怎麼回答?」

+

User Input
「使用者現在想問什麼?」

這樣就比單純把所有文字塞成一大段容易管理很多。

先做一個實驗:同一句話,不同 Prompt

假設我固定問模型同一個問題:

Explain the present perfect.

如果完全沒有額外設定:

response = client.responses.create(
    model="gpt-5-mini",
    input="Explain the present perfect."
)

模型可能會給出一個一般性的說明。

但現在我加上一個角色設定:

You are an English teacher.

回答通常就會開始偏向教學。

如果再更進一步:

You are an English teacher for B1 learners.
Use simple English.
Avoid difficult grammar terminology when possible.
Always provide two short examples.

同樣一句:

Explain the present perfect.

得到的回答方式就可能變得完全不同。也就是:

Same User Input
      +
Different Instructions
      ↓
Different Response

這也是 Prompt 很有意思的地方。模型沒有換,但我們改變了它回答問題時所依據的指示。

加入 System Prompt

在概念上,通常會把這種用來設定 AI 整體角色、行為與規則的內容稱為 System Prompt。例如 Memora 的第一版 System Prompt 可以很簡單:

You are a personal English learning assistant.

Help the user learn English clearly and patiently.
Use examples whenever they help understanding.

如果使用 OpenAI 目前的 Responses API,我可以透過 instructions 把這類高層指示交給模型。官方 API 文件將 instructions 描述為插入模型 Context 的 system / developer 類型訊息,而 developer 或 system 層級的指示會比 user message 有更高的指令優先級。

所以昨天的程式可以改成:

from openai import OpenAI

client = OpenAI()

SYSTEM_PROMPT = """
You are a personal English learning assistant.

Help the user learn English clearly and patiently.
Use examples whenever they help understanding.
"""

while True:
    user_input = input("\nYou: ")

    if user_input.lower() == "exit":
        print("Bye!")
        break

    response = client.responses.create(
        model="gpt-5-mini",
        instructions=SYSTEM_PROMPT,
        input=user_input
    )

    print("AI:", response.output_text)

現在架構就從昨天的:

User Input
    ↓
LLM
    ↓
Response

變成:

System Instructions
        +
   User Input
        ↓
       LLM
        ↓
    Response

這幾行程式看起來沒有差很多,但 Memora 已經第一次開始有「角色」了。

System Prompt 和 User Prompt 不一樣

這裡有一個蠻重要的差別。假設 System Prompt 是:

You are a personal English learning assistant.
Use simple English suitable for B1 learners.

User Input 是:

Explain the difference between "have gone" and "have been".

兩者負責的事情其實不一樣。

System Prompt 比較像:

這個 AI 是誰,以及它應該怎麼工作。

User Input 則是:

使用者這一次要它做什麼。

可以整理成:

類型 主要功能 例子
System / Developer Instructions 定義 AI 的角色、規則與行為 你是一位 B1 英文學習助理
User Input 使用者目前的任務 解釋 have gone 和 have been

在目前 OpenAI 的 Responses API 裡,instructions 就可以用來放這類高層指示;官方文件也指出,輸入 Message 可以帶有 user、assistant、system 或 developer 等角色。

所以之後如果看到不同 API 或 Framework 使用:

system
developer
instructions

不用急著把它們當成三個完全無關的概念。對我們目前的學習階段來說,最重要的是理解:

應用程式需要有一層高於單次 User Input 的指示,用來定義 AI 的行為。

只有一句「你是一位英文老師」夠嗎?

很多 Prompt 教學的第一個例子都會寫:

You are an English teacher.

這確實有效,但如果我要做的是一個真正的產品,我不太希望 Prompt 永遠只有一句角色扮演。因為「英文老師」其實還是非常模糊。

到底是哪一種英文老師?是教幼兒?高中生?IELTS?商用英文?還是語言學?回答要多長?要不要糾正文法?要不要翻譯?需要例句嗎?使用者程度不同時怎麼辦?

所以比起只寫:

You are an English teacher.

可以逐漸把 Prompt 寫成比較明確的規格。例如:

You are a personal English learning assistant.

Your goal is to help the user understand and practice English.

Guidelines:
- Use language appropriate for a B1 learner.
- Keep explanations concise.
- Explain difficult grammar in simple terms.
- Give short examples when useful.
- If the user makes a language mistake, explain it without interrupting the main task.

這時它就不再只是一句「扮演某個角色」,而開始接近真正的 Prompt Design

Prompt Engineering 到底在 Engineering 什麼?

我以前看到 Prompt Engineering 這個詞,很容易聯想到:

是不是要找到某些神奇句型,AI 才會突然變厲害?

但在做應用時,我覺得更實際的理解是:

Prompt Engineering 是把需求轉換成模型能清楚遵循的指示。

也就是我必須把腦中的:

「我希望這是一個好用的英文學習助理。」

拆成比較明確的要求。例如:

角色是什麼?
↓
Personal English Learning Assistant

目標是什麼?
↓
幫助使用者理解與練習英文

使用者是誰?
↓
B1 learner

回答原則是什麼?
↓
簡單、清楚、不過度冗長

有什麼限制?
↓
避免不必要的高階語言學術語

輸出有什麼要求?
↓
適合時提供例句

所以一個比較完整的 Prompt,可以拆成幾個部分:

Role
Task / Goal
Context
Constraints
Output Requirements

這比尋找某一句「魔法咒語」實際很多。

我會怎麼寫 Memora 的 Prompt?

目前還是 Day 4,先不用把 Prompt 寫得太複雜。因為後面 Memora 還會加入 User Profile、Memory、學習紀錄,現在很多資料根本還不存在。

所以第一版我會先寫:

SYSTEM_PROMPT = """
You are Memora, a personal English learning assistant.

Your goal is to help the user learn English clearly and efficiently.

Guidelines:
- Explain concepts in simple language.
- Keep answers focused on the user's question.
- Use short examples when they are helpful.
- Avoid unnecessary technical grammar terminology.
- Encourage learning, but do not add unrelated motivational text.
"""

這個版本已經開始有幾個清楚的部分。

Role

You are Memora, a personal English learning assistant.

告訴模型現在扮演什麼角色。

Goal

Your goal is to help the user learn English clearly and efficiently.

定義這個 Assistant 的主要目標。

Guidelines

Explain concepts in simple language.
Keep answers focused on the user's question.
...

設定回答時應該遵守的原則。所以我會把第一版 Prompt 結構整理成:

Role
 ↓
Goal
 ↓
Guidelines

等到系統變複雜之後,再逐漸加入其他部分。

同一句問題,做三次比較

我覺得學 Prompt 最好的方法不是只看 Prompt 本身,而是固定 User Input,只改 Instructions。例如固定測試:

Explain present perfect.

Version A:沒有額外 Prompt

response = client.responses.create(
    model="gpt-5-mini",
    input="Explain present perfect."
)

這是最一般的回答。

Version B:只有角色

response = client.responses.create(
    model="gpt-5-mini",
    instructions="You are an English teacher.",
    input="Explain present perfect."
)

這時回答可能開始比較像教學。

Version C:完整一些的 Prompt

response = client.responses.create(
    model="gpt-5-mini",
    instructions="""
    You are Memora, a personal English learning assistant.

    The learner is approximately B1 level.

    Guidelines:
    - Use simple English.
    - Keep the explanation concise.
    - Give two short examples.
    - Avoid advanced grammar terminology when possible.
    """,
    input="Explain present perfect."
)

這時回答就更容易符合我們真正想要的形式。我會把這個實驗理解成:

Model 不變
User Input 不變
Prompt 改變
      ↓
Response 的行為改變

這也是 Prompt Engineering 最值得實際測試的地方。

Prompt 要具體,但不是越長越好

知道 Prompt 可以控制模型之後,很容易走到另一個極端:把所有想到的規則全部塞進去。例如:

你是一位英文老師。
你要友善。
你要簡單。
你要詳細。
你要精簡。
你要完整。
不要太長。
每個地方都要解釋。
不要解釋太多。
...

這樣反而會開始出現問題。尤其:

要非常詳細

和:

回答一定要簡短

本身就可能產生衝突。

所以 Prompt Engineering 不只是「加更多 Instructions」,而是要讓 Instructions:

明確
一致
有優先順序
可以測試

我自己會用一個很簡單的原則檢查:

如果連人看到這些規則都不知道該怎麼同時遵守,那模型也很難穩定地做到。

不要把使用者資料全部寫死在 System Prompt

這裡也開始和後面的 Memory 有一點關係。現在為了測試,我可以直接寫:

The learner is B1 level.

但這不是最終架構。因為未來可能有另一個使用者是:

A2

另一個是:

C1

如果我直接把:

User level = B1

寫死在 System Prompt 裡,那這個 Chatbot 就只能服務某一個固定使用者。最終比較合理的架構會是:

Static Instructions
「Memora 應該怎麼工作」
        +
Dynamic User Context
「這個使用者目前是誰」
        +
Current User Message
「他現在問什麼」

也就是:

System Prompt
+
User Profile
+
Relevant Memory
+
Current Question
        ↓
       LLM

但目前我們還沒有 User Profile,也沒有 Memory,所以 Day 4 先不要急著做。

今天只處理其中第一塊:

Static Instructions

也就是「Memora 本身應該怎麼工作」。

Prompt 不是 Memory

這裡還有一個非常重要的地方。假設我的 System Prompt 寫:

You are Memora.
Always answer as a personal English learning assistant.

這不代表它開始有 Memory。

甚至我寫:

The user's English level is B1.

也不是模型「記住使用者是 B1」。只是我每一次 Request 都重新告訴它使用者是 B1

例如:

Request 1

Instructions:
User is B1.

Input:
Explain present perfect.

下一次:

Request 2

Instructions:
User is B1.

Input:
Give me a reading exercise.

它每次知道 B1,是因為我每次都把這項資訊送進去。

而後面做 Memory 時,我們要處理的是:

以前使用者說過 B1
        ↓
保存這項資訊
        ↓
之後需要時找回
        ↓
加入新的 Context

而不是把所有資訊永遠寫死在 System Prompt。

現在的 Memora v0.2

把今天的內容整合起來,chatbot.py 可以改成:

from openai import OpenAI

client = OpenAI()

SYSTEM_PROMPT = """
You are Memora, a personal English learning assistant.

Your goal is to help the user learn English clearly and efficiently.

Guidelines:
- Explain concepts in simple language.
- Keep answers focused on the user's question.
- Use short examples when helpful.
- Avoid unnecessary technical grammar terminology.
- Do not add unrelated motivational text.
"""

print("Memora v0.2")
print("輸入 exit 可以結束對話。")

while True:
    user_input = input("\nYou: ")

    if user_input.lower() == "exit":
        print("Bye!")
        break

    response = client.responses.create(
        model="gpt-5-mini",
        instructions=SYSTEM_PROMPT,
        input=user_input
    )

    print("Memora:", response.output_text)

OpenAI 官方目前的 Python Quickstart 使用 client.responses.create() 建立模型回應;Responses API 也支援透過 instructions 放入 system / developer 類型的指示。

現在 Memora 已經從:

Day 03

Generic Stateless Chatbot

變成:

Day 04

Prompted Stateless Chatbot

也就是:

System Instructions
        +
   Current User Input
        ↓
       LLM
        ↓
    Response

它已經知道自己要扮演什麼角色,但仍然沒有 Conversation History。

最後做一個記憶測試

今天最後,我還是用昨天的方式測一次。

You:
我的英文程度是 B1,請記住。

Memora:
好的,我會以 B1 程度來協助你。

接著:

You:
我的英文程度是多少?

如果我們目前每一次 Request 都只有:

response = client.responses.create(
    model="gpt-5-mini",
    instructions=SYSTEM_PROMPT,
    input=user_input
)

那第二次 Request 仍然沒有第一句:

我的英文程度是 B1。

所以就算 System Prompt 寫得再漂亮,這個 Chatbot 還是沒有真正的 Conversation Memory。它現在只是:

固定知道「自己是誰」

但不知道:

「我們剛剛聊了什麼」

這兩件事需要分開。

可以畫成:

System Prompt
      ↓
定義 AI 的行為
      ↓
每次 Request 都存在


Conversation History
      ↓
保存我們聊過什麼
      ↓
目前還不存在

這也剛好留下明天要處理的問題。

Day 4 小結

今天第一次開始控制 Memora 的「個性」與「工作方式」。

Prompt 不只是使用者打進去的一句問題,而可以包含一組更高層的 Instructions,用來定義角色、目標、規則和輸出方式。在目前使用的 Responses API 中,我們透過 instructions 把這些高層指示加入模型的 Context。

整理今天最重要的觀念有這些:

  1. User Input 告訴模型「現在要做什麼」。
  2. System / Developer Instructions 告訴模型「應該怎麼做」。
  3. Prompt Engineering 不是找魔法句型,而是把需求寫成清楚、沒有互相衝突、可以測試的 Instructions。
  4. Prompt 可以改變 AI 的行為,但不等於增加 Memory。
  5. 把使用者資料寫死在 Prompt 裡,也不等於模型真的記住使用者。

目前 Memora 已經走到:

Day 03
LLM API
↓
Generic Stateless Chatbot

Day 04
System Prompt
↓
Prompted Stateless Chatbot

它開始像一個英文學習助理了,但還有一個從第一天就一直存在的問題:

它還是不知道上一輪到底聊了什麼。

明天就來把這件事情徹底拆開。

Day 05|為什麼 LLM API 聊完就忘?理解 Stateless API

我們目前的程式裡有 while Loop,也有固定的 System Prompt,畫面看起來完全就是一個 Chatbot。但每次我送出新的 User Input,前一次 User Message 和 Assistant Response 到底去了哪裡?下一篇我們來直接檢查每一次 Request,看看目前的 Chatbot 實際送了什麼給模型,並用程式驗證:

「可以一直聊天」為什麼不代表「系統有保存對話狀態」。

這會是 Chapter 1 最後一塊拼圖。等搞懂 Stateless API 之後,Day 6 才會正式開始替 Memora 加上第一種真正的記憶:Conversation History


上一篇
Day 03|用 Python + LLM API 做第一個 Chatbot
下一篇
Day 05|為什麼 LLM API 聊完就忘?理解 Stateless API
系列文
從 Stateless LLM 到 Agentic Memory:30 天打造會記憶的 AI Agent7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言