LLM-Cookbook学习——面向开发者的提示工程>聊天机器人 Chatbot

学习内容:

Datawhale《面向开发者的 LLM 入门教程》第一部分第八章——聊天机器人 Chatbot。


一、从单轮 Prompt 到多轮 Chatbot

在前面的章节中,我们学习的大多数任务都可以理解为:

输入
 ↓
LLM
 ↓
输出

例如:

Summarizing
长文本 → 摘要
Inferring
文本 → 情感 / 标签 / 实体
Transforming
文本 → 另一种语言 / 风格 / 格式
Expanding
已有信息 → 更完整的文本

这些任务很多都可以通过一次模型调用完成。

但是聊天机器人不同。

聊天机器人的典型形式是:

User:
什么是AXI?

Assistant:
AXI是一种AMBA高性能总线协议……

User:
那AXI4和AXI3有什么区别?

Assistant:
AXI4相比AXI3主要……

第二个问题:

“那AXI4和AXI3有什么区别?”

依赖前面的聊天内容。

也就是说,Chatbot 不只是:

单次输入
→
单次输出

而是:

多轮输入
+
历史上下文
→
连续对话

Datawhale 本章正是从聊天模型接收“一系列消息”这一机制出发,介绍如何构建多轮对话系统。


二、聊天模型的核心:Messages

聊天模型并不是只接收一个字符串。

更加典型的输入结构是:

messages = [
    {
        "role": "system",
        "content": "..."
    },
    {
        "role": "user",
        "content": "..."
    },
    {
        "role": "assistant",
        "content": "..."
    }
]

每一条消息通常包含两个核心字段:

role

和:

content

2.1 role

role 表示:

这条消息是谁说的?

常见角色:

system
user
assistant

2.2 content

content 表示:

这条消息具体说了什么?

例如:

{
    "role": "user",
    "content": "什么是UVM?"
}

可以理解成:

User:
什么是UVM?

所以聊天模型的输入本质上可以理解为:

一段带有说话人身份的对话记录

三、三种核心角色

聊天中最重要的三个角色是:

system
user
assistant

它们的关系可以表示为:

            Messages
               │
    ┌──────────┼──────────┐
    │          │          │
    ▼          ▼          ▼
 system       user     assistant
    │          │          │
    ▼          ▼          ▼
系统规则     用户输入     模型回答

四、System:定义机器人的行为

system 可以理解成整个 Chatbot 的:

最高层配置

例如:

messages = [
    {
        "role": "system",
        "content": "你是一名数字IC验证专家。"
    }
]

这条消息主要告诉模型:

你是谁?
你负责什么?
应该怎样回答?
需要遵守什么规则?

Datawhale 原章通过修改系统角色,让模型以特定身份和语言风格进行回复,由此说明 System Message 会持续影响后续回答。


五、System Prompt 不只是“角色扮演”

最简单的 System Prompt:

你是一名客服助手。

当然可以使用。

但是实际项目中,一个更完整的 System Prompt 往往还包括:

角色
+
任务
+
流程
+
规则
+
输出方式
+
禁止事项

例如:

system_prompt = """
你是一名芯片Datasheet分析助手。

你的任务是帮助工程师分析芯片手册中的测试信息。

回答要求:

1. 优先根据用户提供的信息回答。
2. 不确定的信息必须明确说明。
3. 不允许虚构芯片参数。
4. 如果用户询问测试项,尽量整理:
   - 测试项名称
   - 参数名称
   - 测试条件
   - 测试步骤
   - 判定标准

回答风格:

技术、准确、清晰。
"""

这里的 System Prompt 实际已经承担了:

机器人的岗位说明书

六、User:表示用户输入

user 就是:

用户当前发送的消息

例如:

{
    "role": "user",
    "content": "AXI中的4KB边界是什么意思?"
}

在聊天过程中,User 会不断:

提出问题
补充信息
修改要求
继续追问

例如:

User:
什么是AXI Cache?

Assistant:
AXCACHE是……

User:
那为什么读写高两位含义看起来不一样?

第二个问题依赖第一轮对话。

所以用户输入必须和历史上下文结合起来理解。


七、Assistant:模型历史回答

assistant 表示:

模型此前输出的内容

例如:

{
    "role": "assistant",
    "content": "AXI是一种高性能片上总线协议……"
}

为什么模型自己之前说过的话还要保存?

因为下一轮用户可能会说:

你刚才第三点是什么意思?

这里:

“第三点”

到底是什么?

必须查看上一轮 Assistant 的回答才能知道。

因此,一段完整聊天通常是:

messages = [
    system,
    user_1,
    assistant_1,
    user_2,
    assistant_2,
    user_3
]

然后模型根据这一整组消息生成:

assistant_3

八、聊天机器人为什么“能记住”前面的内容?

这是本章最重要的概念之一。

我们经常会感觉:

ChatGPT记住了前面说过的话。

但基础 Chatbot 实现中,更准确的理解应该是:

程序保存历史对话
+
下一轮调用模型时重新发送历史信息

九、一个典型实验

第一次:

messages = [
    {
        "role": "user",
        "content": "你好,我叫Isa。"
    }
]

模型回答:

你好Isa,很高兴认识你。

然后重新创建一个新的消息列表:

messages = [
    {
        "role": "user",
        "content": "我的名字是什么?"
    }
]

这时模型并不知道:

Isa

因为当前输入里没有:

“我叫Isa”

这一信息。

Datawhale 原章正是用类似实验说明:模型若要利用前面的信息,就需要把相关历史消息放进当前消息列表中。


十、加入历史消息

如果改成:

messages = [
    {
        "role": "user",
        "content": "你好,我叫Isa。"
    },

    {
        "role": "assistant",
        "content": "你好Isa,很高兴认识你。"
    },

    {
        "role": "user",
        "content": "我的名字是什么?"
    }
]

模型就可以看到:

User:
我叫Isa。

Assistant:
你好Isa。

User:
我的名字是什么?

因此能够回答:

你的名字是Isa。

这里的关键就是:

Context
上下文

十一、什么是 Context?

可以把 context 理解成:

当前这场聊天中,
模型需要看到的历史消息集合。

例如:

context = [
    {
        "role": "system",
        "content": "你是一名友好的AI助手。"
    }
]

第一次用户输入:

你好,我叫小明。

加入:

context.append(
    {
        "role": "user",
        "content": "你好,我叫小明。"
    }
)

模型回答:

你好小明!

继续加入:

context.append(
    {
        "role": "assistant",
        "content": "你好小明!"
    }
)

这时:

context

就包含:

System:
你是一名友好的AI助手。

User:
你好,我叫小明。

Assistant:
你好小明!

十二、下一轮继续累积 Context

用户说:

我现在正在学习UVM。

执行:

context.append(
    {
        "role": "user",
        "content": "我现在正在学习UVM。"
    }
)

模型回复:

好的。

继续保存:

context.append(
    {
        "role": "assistant",
        "content": "好的。"
    }
)

如果下一轮问:

我刚才说我正在学什么?

模型可以根据 context 找到:

UVM

所以 Chatbot 的基础记忆机制可以总结成:

对话
↓
保存历史
↓
再次发送历史
↓
模型理解上下文

十三、context.append() 的作用

这一章代码中一个非常重要的操作就是:

context.append(...)

例如:

context.append(
    {
        "role": "user",
        "content": user_input
    }
)

意思是:

把用户刚刚说的话
放到历史聊天记录最后面。

假设原来:

context = [
    {
        "role": "system",
        "content": "你是订餐机器人。"
    }
]

执行:

context.append(
    {
        "role": "user",
        "content": "我要一个披萨。"
    }
)

以后变成:

[
    {
        "role": "system",
        "content": "你是订餐机器人。"
    },

    {
        "role": "user",
        "content": "我要一个披萨。"
    }
]

然后模型回答:

请问需要什么尺寸?

再执行:

context.append(
    {
        "role": "assistant",
        "content": "请问需要什么尺寸?"
    }
)

最终变成:

System
User
Assistant

十四、为什么 User 和 Assistant 都要保存?

假设只保存 User:

User:
我要一个披萨。

User:
大份。

“大份”是什么意思?

只有看到 Assistant:

请问需要大份、中份还是小份?

语义才完整。

真实对话往往包含:

是
不要
大份
第一个
刚才那个
第二种

这些表达本身都依赖上一轮内容。

因此 Chatbot 的 Context 应该保存:

用户消息
+
模型回复

而不是只保存用户输入。


十五、封装一个多轮消息调用函数

可以写:

def get_completion_from_messages(
    client,
    model_id,
    messages,
    temperature=0.0
):
    """
    根据完整对话消息调用模型。
    """

    response = client.chat.completions.create(
        model=model_id,
        messages=messages,
        temperature=temperature
    )

    return response.choices[0].message.content

和前几章单轮调用相比,关键变化在:

messages=messages

而不是:

只发送一个Prompt字符串

Datawhale 本章同样专门定义了 get_completion_from_messages,用于接收一组角色化消息。


十六、实现一轮聊天

可以继续封装:

def chat(
    client,
    model_id,
    context,
    user_input
):
    """
    完成一轮多轮聊天。
    """

    # 1. 保存用户输入
    context.append(
        {
            "role": "user",
            "content": user_input
        }
    )

    # 2. 将完整Context发送给模型
    response = get_completion_from_messages(
        client=client,
        model_id=model_id,
        messages=context,
        temperature=0.0
    )

    # 3. 保存模型回答
    context.append(
        {
            "role": "assistant",
            "content": response
        }
    )

    # 4. 返回回答
    return response

整个过程:

User输入
   ↓
context.append(User)
   ↓
发送整个context
   ↓
LLM生成回答
   ↓
context.append(Assistant)
   ↓
等待下一轮

这就是最基本的 Chatbot 循环。


十七、Chatbot最核心的程序结构

真正值得记住的只有下面几步:

context = [
    {
        "role": "system",
        "content": system_prompt
    }
]

然后每一轮:

context.append(
    {
        "role": "user",
        "content": user_input
    }
)

response = get_completion_from_messages(
    client,
    model_id,
    context
)

context.append(
    {
        "role": "assistant",
        "content": response
    }
)

也就是:

初始化System
      ↓
加入User
      ↓
调用LLM
      ↓
加入Assistant
      ↓
加入下一轮User
      ↓
继续……

十八、Context 还承担业务状态

Context 不只是:

聊天历史

它还隐含保存:

当前任务进行到哪一步

例如订餐:

User:
我要一个辣香肠披萨。

Assistant:
什么尺寸?

User:
大份。

Assistant:
需要添加配料吗?

User:
加蘑菇。

从这些聊天记录中,可以推断出:

商品:
辣香肠披萨

尺寸:
大

配料:
蘑菇

所以:

Context

实际上同时承担:

Conversation History
+
Task State

即:

聊天历史
+
任务状态

十九、本章核心案例:OrderBot

Datawhale 本章最终构建了一个:

OrderBot
订餐机器人

它负责自动帮助披萨店收集订单。

主要流程包括:

问候用户
   ↓
询问商品
   ↓
确定尺寸
   ↓
确定额外配料
   ↓
确认是否还需要其他商品
   ↓
询问自取还是配送
   ↓
配送则询问地址
   ↓
总结订单
   ↓
生成订单信息

课程使用 System Message 同时描述机器人的业务流程、菜单、尺寸和价格,并让 context 随聊天不断增长。


二十、OrderBot 的 System Prompt

可以写成:

ORDERBOT_SYSTEM_PROMPT = """
你是OrderBot,
是一家披萨餐厅的自动订餐机器人。

你的任务是帮助顾客完成订单。

流程:

1. 首先问候顾客。

2. 收集顾客需要购买的商品。

3. 如果商品存在尺寸,
   必须询问具体尺寸。

4. 如果是披萨,
   需要确认是否添加额外配料。

5. 每次完成一个商品后,
   询问顾客是否还需要其他商品。

6. 订单结束后,
   询问顾客自取还是配送。

7. 如果是配送,
   必须询问配送地址。

8. 最后总结订单。

要求:

- 回答简短
- 语气友好
- 不得提供菜单外商品
- 必须确认所有必要选项

菜单:

意式辣香肠披萨:
大 12.95
中 10.00
小 7.00

芝士披萨:
大 10.95
中 9.25
小 6.50

茄子披萨:
大 11.95
中 9.75
小 6.75

薯条:
大 4.50
小 3.50

希腊沙拉:
7.25

配料:

额外奶酪 2.00
蘑菇 1.50
香肠 3.00
加拿大熏肉 3.50
辣椒 1.00

饮料:

可乐:
大 3.00
中 2.00
小 1.00

雪碧:
大 3.00
中 2.00
小 1.00

瓶装水:
5.00
"""

二十一、初始化 OrderBot

context = [
    {
        "role": "system",
        "content": ORDERBOT_SYSTEM_PROMPT
    }
]

此时模型已经知道:

自己是谁
↓
OrderBot
要完成什么
↓
收集订单
有哪些商品
↓
菜单
下一步应该做什么
↓
根据当前聊天状态决定

二十二、一次完整点餐过程

第一轮

用户:

你好。

机器人:

你好!欢迎光临,请问今天想点些什么?

第二轮

用户:

我要一个意式辣香肠披萨。

机器人根据 System Prompt 发现:

尺寸还没有确定

因此:

请问需要大份、中份还是小份?

第三轮

用户:

大份。

机器人:

好的,一个大份意式辣香肠披萨。
需要额外添加配料吗?

第四轮

用户:

加蘑菇和额外奶酪。

机器人:

好的,已经添加蘑菇和额外奶酪。
还需要其他食物或饮料吗?

第五轮

用户:

再来一杯中杯可乐。

机器人:

好的,一杯中杯可乐。
还需要其他商品吗?

第六轮

用户:

不用了。

机器人:

好的,请问订单是自取还是配送?

第七轮

用户:

配送。

机器人:

请提供配送地址。

这就是:

System规则
+
Context当前状态
+
用户当前输入
↓
决定下一步回复

二十三、collect_messages() 在做什么?

Datawhale 原章定义了一个:

collect_messages()

核心逻辑就是:

读取用户输入
↓
加入context
↓
调用模型
↓
拿到回复
↓
回复加入context
↓
显示回复

课程再通过 Panel 搭建简单 GUI,从输入框收集信息并调用这个函数。

简化版本:

def collect_messages(
    client,
    model_id,
    context,
    user_input
):
    """
    收集并处理一轮消息。
    """

    context.append(
        {
            "role": "user",
            "content": user_input
        }
    )

    response = get_completion_from_messages(
        client=client,
        model_id=model_id,
        messages=context,
        temperature=0.0
    )

    context.append(
        {
            "role": "assistant",
            "content": response
        }
    )

    return response

二十四、Panel 是什么?

课程中使用:

import panel as pn

Panel 的作用主要是:

创建一个简单的图形聊天界面

例如:

inp = pn.widgets.TextInput(
    placeholder="请输入内容..."
)

button = pn.widgets.Button(
    name="发送"
)

然后用户可以直接:

输入消息
↓
点击发送
↓
显示机器人回复

需要注意:

Panel不是Chatbot的核心

Chatbot 的核心是:

Messages
+
Context
+
LLM

Panel 只负责:

UI展示

也就是说,未来完全可以替换成:

网页
App
微信
Slack
命令行

而不改变核心聊天逻辑。


二十五、对话越长,Context 也会越长

第一轮:

System
User1
Assistant1

第二轮:

System
User1
Assistant1
User2
Assistant2

第十轮:

System
User1
Assistant1
...
User10
Assistant10

所以:

对话越长
↓
输入消息越多
↓
Token消耗越大

真实 Chatbot 中不能无限:

context.append(...)

而不做管理。


二十六、工程中如何管理长 Context?

实际项目通常会考虑:

最近几轮消息
+
历史摘要
+
关键事实

例如:

System Prompt

+ 最近10轮聊天

+ 历史聊天摘要

+ 用户关键状态

而不是永远发送从第一句话开始的所有内容。

这实际上开始涉及:

Conversation State Management

即:

对话状态管理

二十七、自然语言订单最终还不能直接交给系统

假设对话结果是:

用户点了一个大份辣香肠披萨,
加蘑菇和奶酪,
还点了一杯中杯可乐。

人可以理解。

但真实订单系统更希望得到:

{
  "pizza": {
    "name": "意式辣香肠披萨",
    "size": "大"
  },
  "toppings": [
    "蘑菇",
    "额外奶酪"
  ],
  "drinks": [
    {
      "name": "可乐",
      "size": "中"
    }
  ]
}

因此,本章最后一步是:

聊天记录
↓
结构化JSON

Datawhale 原章专门在完整 context 后追加一条新的指令,让模型根据之前的订餐记录生成 JSON 摘要。


二十八、为什么要 context.copy()?

课程中类似:

messages = context.copy()

然后:

messages.append(...)

为什么不直接修改原来的:

context

因为:

context

代表:

原始聊天状态

而:

生成JSON

属于一次额外处理任务。

所以:

context
↓
copy
↓
messages

然后在:

messages

中临时增加:

请生成JSON订单摘要

更合理。


二十九、生成 JSON 订单摘要

例如:

messages = context.copy()

messages.append(
    {
        "role": "system",
        "content": """
根据前面的订单对话,
生成订单JSON摘要。

字段:

pizza
toppings
drinks
sides
delivery_type
address
total_price

要求:

1. 只记录顾客实际购买的商品。
2. 包含商品尺寸。
3. 每件商品包含价格。
4. 没有的列表使用[]。
5. 自取时address为null。
6. 只输出合法JSON。
7. 不要输出Markdown代码块。
"""
    }
)

调用:

response = get_completion_from_messages(
    client=client,
    model_id=model_id,
    messages=messages,
    temperature=0.0
)

三十、为什么这里 Temperature 设置低一些?

第七章学习过:

低Temperature
↓
生成更加稳定

JSON 订单任务追求的不是:

创造力

而是:

字段稳定
格式稳定
结果可解析

所以更适合:

temperature=0.0

Datawhale 原示例在创建 JSON 订单摘要时也使用了较低 temperature。


三十一、解析 JSON

模型输出:

{
  "pizza": {
    "name": "意式辣香肠披萨",
    "size": "大",
    "price": 12.95
  },
  "toppings": [
    {
      "name": "蘑菇",
      "price": 1.50
    },
    {
      "name": "额外奶酪",
      "price": 2.00
    }
  ],
  "drinks": [
    {
      "name": "可乐",
      "size": "中",
      "price": 2.00
    }
  ],
  "sides": [],
  "delivery_type": "配送",
  "address": "上海市XX路XX号",
  "total_price": 18.45
}

Python:

import json

try:

    order_data = json.loads(
        response
    )

except json.JSONDecodeError as error:

    print(
        f"JSON解析失败:{error}"
    )

成功以后:

print(
    order_data["total_price"]
)

即可得到:

18.45

这就实现了:

自然语言
↓
结构化数据
↓
业务系统

三十二、Chatbot真正开始和软件系统连接

现在整个流程已经变成:

用户自然语言
      ↓
多轮Chatbot
      ↓
Context
      ↓
收集完整业务信息
      ↓
JSON结构化
      ↓
Python程序
      ↓
数据库 / 订单系统 / API

所以 Chatbot 不应该只是:

陪用户聊天

而可以作为:

自然语言接口

连接后端软件。


三十三、一个完整的简化 OrderBot

import json

from openai import OpenAI


class OrderBot:

    def __init__(
        self,
        client,
        model_id
    ):

        self.client = client
        self.model_id = model_id

        self.context = [
            {
                "role": "system",
                "content": """
你是一家披萨餐厅的订餐机器人。

任务:

1. 问候顾客。
2. 收集商品。
3. 确认尺寸。
4. 确认配料。
5. 确认是否继续添加商品。
6. 询问自取或配送。
7. 配送时询问地址。
8. 最后总结订单。

回答风格:

简短、友好。

菜单:

辣香肠披萨:
大 12.95
中 10.00
小 7.00

芝士披萨:
大 10.95
中 9.25
小 6.50

额外奶酪:
2.00

蘑菇:
1.50

可乐:
大 3.00
中 2.00
小 1.00
"""
            }
        ]


    def chat(
        self,
        user_input
    ):

        # 添加User
        self.context.append(
            {
                "role": "user",
                "content": user_input
            }
        )

        # 调用模型
        response = (
            self.client
            .chat
            .completions
            .create(
                model=self.model_id,
                messages=self.context,
                temperature=0.2
            )
        )

        content = (
            response
            .choices[0]
            .message
            .content
        )

        # 添加Assistant
        self.context.append(
            {
                "role": "assistant",
                "content": content
            }
        )

        return content


    def create_order_json(
        self
    ):

        messages = self.context.copy()

        messages.append(
            {
                "role": "system",
                "content": """
根据之前的订单对话,
输出订单JSON。

字段:

pizza
toppings
drinks
delivery_type
address

要求:

只输出合法JSON。
"""
            }
        )

        response = (
            self.client
            .chat
            .completions
            .create(
                model=self.model_id,
                messages=messages,
                temperature=0.0
            )
        )

        content = (
            response
            .choices[0]
            .message
            .content
        )

        return json.loads(
            content
        )

三十四、为什么 Chatbot 很适合使用 Class?

前几章很多任务使用:

def

即可。

但是 Chatbot 特别适合:

class

原因是 Chatbot 有一个会不断变化的:

状态

最典型就是:

self.context

每次聊天:

self.context

都会增加新的 User 和 Assistant 消息。

所以:

函数

更适合:

执行一个动作

而:

Class

适合:

表示一个长期存在、
内部状态不断变化的对象

Chatbot 正好属于后者。


三十五、self.context 的意义

例如:

bot_a = OrderBot(...)
bot_b = OrderBot(...)

那么:

bot_a.context

记录:

用户A的聊天

而:

bot_b.context

记录:

用户B的聊天

两者不能混在一起。

这与真实 Chatbot 中:

每个用户拥有独立Session

完全一致。


三十六、真实系统还需要 Session

如果系统同时有很多用户:

User A
User B
User C

就需要:

Session A
Session B
Session C

可以简单理解为:

sessions = {
    "user_a": context_a,
    "user_b": context_b,
    "user_c": context_c
}

请求到达:

读取用户ID
↓
找到对应context
↓
追加消息
↓
调用LLM
↓
更新context

这就是:

多用户Chatbot

的基础。


三十七、教学版和工程版 Chatbot 的区别

教学版 OrderBot:

System Prompt中写入菜单
↓
LLM理解订单
↓
LLM计算价格
↓
JSON

真实工程中,更推荐:

用户聊天
↓
LLM识别商品
↓
结构化数据
↓
程序查询数据库
↓
程序验证商品
↓
程序计算价格
↓
程序确认库存
↓
LLM生成自然语言回复

原因是:

语言理解

很适合交给 LLM。

但:

价格
库存
支付
权限
金额计算

更适合交给确定性代码。


三十八、LLM和普通程序如何分工?

LLM适合

理解自然语言
识别用户意图
理解上下文
处理模糊表达
生成自然语言回复

Python / 后端程序适合

精确计算
价格查询
数据库操作
权限判断
库存判断
支付处理
数据格式校验

所以一个可靠系统不应该:

什么都交给LLM

而应该:

LLM
+
传统程序

协同完成。


三十九、Chatbot 与前面几章如何组合?

Chatbot 实际可以把前面的能力全部组织起来。

例如用户:

My blender broke after six months.
I'm really angry.
What should I do?

Transforming

英文
↓
中文

Inferring

是否愤怒:
true

Summarizing

核心问题:
搅拌机使用半年后损坏。

Expanding

生成完整客服回复。

Chatbot

用户继续:

我的订单号是123456。

Assistant:

好的,我继续根据这个订单帮助您……

这时候:

Context

使整个过程保持连续。


四十、从第三章到第八章

现在整个 Prompt Engineering 第一部分可以串起来:

Iterative
↓
优化Prompt
Summarizing
↓
压缩信息
Inferring
↓
判断信息
Transforming
↓
转换信息
Expanding
↓
扩展信息
Chatbot
↓
把这些能力组织成多轮交互

也就是说:

第三~七章
主要研究LLM“能做什么”

而:

第八章
开始研究怎样把这些能力
组织成真正的应用程序

四十一、本章思维导图

Chatbot
│
├── 1. Messages
│   │
│   ├── role
│   └── content
│
├── 2. Roles
│   │
│   ├── system
│   │   ├── 定义身份
│   │   ├── 定义任务
│   │   ├── 定义规则
│   │   └── 定义风格
│   │
│   ├── user
│   │   └── 用户输入
│   │
│   └── assistant
│       └── 模型历史输出
│
├── 3. Context
│   │
│   ├── 保存User
│   ├── 保存Assistant
│   ├── 保持上下文
│   └── 保存任务状态
│
├── 4. Multi-turn Chat
│   │
│   ├── append User
│   ├── 调用LLM
│   ├── append Assistant
│   └── 循环
│
├── 5. OrderBot
│   │
│   ├── 商品
│   ├── 尺寸
│   ├── 配料
│   ├── 饮料
│   ├── 自取/配送
│   └── 地址
│
├── 6. JSON
│   │
│   ├── context.copy()
│   ├── 添加结构化指令
│   ├── temperature降低
│   └── json.loads()
│
├── 7. UI
│   │
│   └── Panel
│
└── 8. Engineering
    │
    ├── Session
    ├── Context管理
    ├── 数据库
    ├── API
    ├── 精确业务逻辑
    └── Agent扩展

四十二、本章总结

第八章最核心的第一个知识点是:

Messages

聊天模型真正接收的是:

System
+
User
+
Assistant

组成的消息序列。


第二个重点是:

Context

Chatbot 能够连续理解用户的原因,本质上是:

程序保存历史
+
下一轮重新提供历史

因此:

多轮记忆
首先是Context管理问题。

第三个重点:

System Prompt

它不仅可以定义:

“你是一名机器人”

还应该定义:

角色
任务
流程
规则
菜单
约束
回答风格

第四个重点:

自然语言
↓
结构化数据

OrderBot 最终不能停留在:

“用户点了一个披萨”

而应该进一步转换成:

{
  "pizza": "...",
  "size": "...",
  "toppings": []
}

才能真正交给软件系统。


第五个重点:

LLM负责理解,
程序负责确定性逻辑。

一个可靠 Chatbot 更合理的架构应该是:

用户
 ↓
Chatbot
 ↓
Context
 ↓
LLM理解意图
 ↓
JSON / Structured Data
 ↓
Python / Database / API
 ↓
业务结果
 ↓
LLM生成自然语言
 ↓
用户

所以这一章真正需要掌握的,不只是:

“怎样调用聊天模型”

而是:

怎样使用System规定机器人的行为,
使用Context维护连续对话,
使用User和Assistant保存交互历史,
最后把自然语言交流转换成
程序能够真正使用的结构化业务数据。

到这里,我们已经从:

Prompt Engineering

逐渐进入:

LLM Application Development

也就是:

真正的大语言模型应用开发。
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐