1
00:00:00,360 --> 00:00:01,440
Pressing on.
继续压下去。

2
00:00:01,760 --> 00:00:06,040
So what we're now going to do is call this.
所以我们现在要做的就是调用它。

3
00:00:06,080 --> 00:00:10,040
It looks like I'm going to need to import async IO there.
看来我需要在那里导入异步 IO。

4
00:00:10,080 --> 00:00:10,640
Hang on.
不挂断。

5
00:00:10,680 --> 00:00:11,640
Let's do that.
让我们这样做吧。

6
00:00:12,640 --> 00:00:14,240
Missed an import at the start.
一开始就错过了导入。

7
00:00:14,640 --> 00:00:15,960
Actually let's do this properly.
实际上让我们正确地做到这一点。

8
00:00:15,960 --> 00:00:18,360
I'm going to take this out just so that it's nice and clean for you.
我要把这个拿出来，这样对你来说又漂亮又干净。

9
00:00:18,360 --> 00:00:23,240
I'm going to put that async import right up at the top there and rerun that cell.
我将把异步导入放在顶部并重新运行该单元格。

10
00:00:23,560 --> 00:00:25,120
I like to do my imports at the top.
我喜欢在顶部进行导入。

11
00:00:25,120 --> 00:00:27,520
I know people have different views on this stuff.
我知道人们对这件事有不同的看法。

12
00:00:27,960 --> 00:00:33,520
Okay, so we are now going to say we want to write a cold sales email.
好的，我们现在要说的是，我们想写一封冷冰冰的销售电子邮件。

13
00:00:33,520 --> 00:00:35,240
That's going to be our instruction.
这将是我们的指示。

14
00:00:35,240 --> 00:00:38,720
And what we're going to do now is we're going to call this async IO.
我们现在要做的就是调用异步 IO。

15
00:00:39,920 --> 00:00:40,640
Do you remember this?
你还记得这个吗？

16
00:00:40,640 --> 00:00:46,800
I showed this to you back when we had the async briefing, that this is where you start to see the power
当我们进行异步简报时，我向您展示了这一点，这就是您开始看到力量的地方

17
00:00:46,800 --> 00:00:47,800
of async IO.
异步IO。

18
00:00:47,920 --> 00:00:52,520
We're going to be running three different runs at the same time.
我们将同时运行三个不同的运行。

19
00:00:52,720 --> 00:00:54,680
And of course again it's not multithreading.
当然，这也不是多线程。

20
00:00:54,680 --> 00:00:58,200
It's not like the CPU is actually time slicing between them in some ways.
CPU实际上并没有以某种方式在它们之间进行时间切片。

21
00:00:58,400 --> 00:01:03,900
But but rather it's going to be using an event loop, which will run each one, and whenever it's pausing
但相反，它将使用一个事件循环，它将运行每个循环，并且每当它暂停时

22
00:01:03,900 --> 00:01:06,420
waiting on I o it will let another one run.
等待我 o 它会让另一个运行。

23
00:01:06,420 --> 00:01:11,820
And because most of what these things are doing is pausing on I o that will allow all three of them
因为这些东西正在做的大部分事情都在 I o 上暂停，这将允许它们全部三个

24
00:01:11,820 --> 00:01:20,820
to sort of alternate and be talking to to an LLM to open AI in parallel, and then we will collect back
有点交替并与法学硕士交谈以并行开放人工智能，然后我们将收集回来

25
00:01:20,860 --> 00:01:21,860
the results.
结果。

26
00:01:21,900 --> 00:01:27,300
What comes back from this await gather is a collection of results.
从这个等待收集返回的是结果的集合。

27
00:01:27,300 --> 00:01:30,660
And we will call final output on each one and print it.
我们将调用每一个的最终输出并打印它。

28
00:01:30,980 --> 00:01:32,820
So we will let that run.
所以我们会让它运行。

29
00:01:33,020 --> 00:01:39,220
And you can see that I've wrapped all of this in a trace, which means that we should see all of this
你可以看到我已经将所有这些都封装在一个跟踪中，这意味着我们应该看到所有这些

30
00:01:39,260 --> 00:01:40,420
in one trace.
一丝一毫。

31
00:01:40,460 --> 00:01:43,500
We will do in a little bit, but no surprise.
我们稍后会做，但并不奇怪。

32
00:01:43,500 --> 00:01:49,420
Hopefully what you'll see down here is I have to click here to get a scrollable element, and you'll
希望您在这里看到的是我必须单击此处才能获取可滚动元素，然后您将

33
00:01:49,420 --> 00:01:53,660
see that we can scroll through and read a bunch of emails.
看到我们可以滚动浏览并阅读一堆电子邮件。

34
00:01:54,460 --> 00:02:00,260
And the third one, of course, is very concise because we asked our third email writer to be concise.
当然，第三封电子邮件非常简洁，因为我们要求第三位电子邮件撰写者保持简洁。

35
00:02:01,040 --> 00:02:05,280
Okay, so so far all we've really done is multiple calls to LMS.
好的，到目前为止我们所做的只是多次调用 LMS。

36
00:02:05,320 --> 00:02:07,640
And now the final piece of the puzzle.
现在是拼图的最后一块了。

37
00:02:07,640 --> 00:02:11,680
This is just a simple workflow of calling LMS.
这只是调用LMS的一个简单的工作流程。

38
00:02:11,720 --> 00:02:17,520
See if you can remember which one of the patterns this is, but it's a sort of variety of one of them.
看看你是否能记住这是哪一种模式，但它是其中一种模式的变体。

39
00:02:17,560 --> 00:02:20,560
And we are going to create a new agent called sales picker.
我们将创建一个名为 sales picker 的新代理。

40
00:02:20,840 --> 00:02:26,240
And sales picker picks the best cold sales email from the given options.
销售选择器从给定的选项中挑选最好的冷销售电子邮件。

41
00:02:26,560 --> 00:02:27,720
Imagine you're a customer.
想象一下您是一位客户。

42
00:02:27,720 --> 00:02:30,400
Pick the one you're most likely to respond to.
选择您最有可能做出回应的一个。

43
00:02:30,560 --> 00:02:31,920
Don't give an explanation.
不给解释。

44
00:02:31,920 --> 00:02:35,000
Reply with the email you select only.
仅回复您选择的电子邮件。

45
00:02:35,040 --> 00:02:37,080
It's a classic kind of prompting.
这是一种经典的提示。

46
00:02:37,240 --> 00:02:40,040
You know that you often end with the constraint.
你知道你常常以约束结束。

47
00:02:40,040 --> 00:02:44,480
With any limitation is a good way to end a system prompt.
任何限制都是结束系统提示的好方法。

48
00:02:44,920 --> 00:02:45,800
All right.
好的。

49
00:02:45,920 --> 00:02:50,600
So that's the message the user prompt writer called sales email.
这就是用户提示作者称为销售电子邮件的消息。

50
00:02:50,840 --> 00:02:53,080
We again we have this same construct.
我们再次拥有相同的构造。

51
00:02:53,080 --> 00:02:59,560
We're going to run three agents in parallel to craft three messages.
我们将并行运行三个代理来制作三个消息。

52
00:02:59,560 --> 00:03:04,820
We're going to gather the outputs and then we just simply call another agent.
我们将收集输出，然后只需调用另一个代理即可。

53
00:03:04,980 --> 00:03:07,740
So this is just Python code step by step.
所以这只是一步一步的Python 代码。

54
00:03:07,780 --> 00:03:09,340
Call three agents in parallel.
并行呼叫三个代理。

55
00:03:09,380 --> 00:03:10,260
Take the output.
获取输出。

56
00:03:10,300 --> 00:03:11,540
Call another agent.
致电另一位代理。

57
00:03:11,580 --> 00:03:18,220
It's just a Python script that runs these things in order, and it will then print the best email at
它只是一个按顺序运行这些事情的 Python 脚本，然后它会打印出最好的电子邮件：

58
00:03:18,220 --> 00:03:19,140
the end of it.
结束了。

59
00:03:19,500 --> 00:03:26,780
And because we've got the whole thing under one trace, we hope to see all of this in a single trace.
因为我们已经将所有内容都放在一条跟踪中，所以我们希望在一条跟踪中看到所有这些。

60
00:03:27,700 --> 00:03:31,860
So this is probably going to take I think like 30s in total.
所以我认为这可能总共需要 30 秒。

61
00:03:31,860 --> 00:03:35,060
So I'll have to keep the sentence running if we want to see this live.
因此，如果我们想看到这一点，我就必须继续说下去。

62
00:03:35,380 --> 00:03:39,100
And at the end of it we'll be able to go into the trace is run.
最后我们将能够进入跟踪运行情况。

63
00:03:39,140 --> 00:03:41,980
So here is a single email that's been returned.
这是一封已返回的电子邮件。

64
00:03:42,140 --> 00:03:45,220
And it is apparently the best one.
这显然是最好的。

65
00:03:45,380 --> 00:03:48,620
But let's now go and have a look at the trace to see if we believe it.
但现在让我们去看看痕迹，看看我们是否相信它。

66
00:03:49,060 --> 00:03:49,500
Okay.
好的。

67
00:03:49,500 --> 00:03:51,020
So this was our email.
这就是我们的电子邮件。

68
00:03:51,060 --> 00:03:54,540
Now this is a link to go to see the traces in OpenAI.
现在这是一个链接，可以查看 OpenAI 中的痕迹。

69
00:03:54,860 --> 00:03:55,820
Here it comes.
它来了。

70
00:03:56,020 --> 00:03:59,540
So at the top trace is selection from salespeople.
因此，最上面的痕迹是销售人员的选择。

71
00:03:59,540 --> 00:04:01,680
Let's go and have a look into this trace.
让我们去看看这个痕迹。

72
00:04:01,680 --> 00:04:07,160
What you'll see is that, sure enough, it called the professional sales agent, and you can read the
你会看到，果然，它打电话给专业的销售代理，你可以阅读

73
00:04:07,200 --> 00:04:10,840
actual prompts that went in it called the engaging sales agent.
其中的实际提示称为参与销售代理。

74
00:04:10,880 --> 00:04:15,160
It called the Busy sales agent, and then it called the sales picker.
它呼叫忙碌的销售代理，然后呼叫销售选择器。

75
00:04:15,320 --> 00:04:18,280
And you can go through this in the trace and see what's going on.
您可以在跟踪中查看这一点，看看发生了什么。

76
00:04:18,840 --> 00:04:22,560
So it's worth pointing out that we've really not done anything very magical so far.
因此值得指出的是，到目前为止我们还没有做任何非常神奇的事情。

77
00:04:23,000 --> 00:04:23,680
It's nice.
很好。

78
00:04:23,680 --> 00:04:28,200
It's elegant that we've had these wrappers, these agent constructs around things, but they're very
我们拥有这些包装器，这些代理围绕事物构建，这很优雅，但它们非常

79
00:04:28,200 --> 00:04:29,160
lightweight wrappers.
轻质包装纸。

80
00:04:29,160 --> 00:04:32,720
We've essentially simply called a total of four LMS.
我们本质上只是简单地调用了总共四个 LMS。

81
00:04:32,720 --> 00:04:38,200
We've called the three sales LMS, and then we've called the one at the end to pick the email it preferred.
我们将三个销售 LMS 称为“销售 LMS”，然后调用最后一个销售 LMS 以选择其首选的电子邮件。

82
00:04:38,200 --> 00:04:41,800
And it's sort of elegant that you can go into the traces and see what's going on.
你可以进入痕迹并看看发生了什么，这有点优雅。

83
00:04:41,800 --> 00:04:46,000
But now it's time to get a bit more agentic and start talking about tools.
但现在是时候变得更加主动并开始谈论工具了。

84
00:04:46,840 --> 00:04:52,200
So as we get into tools, let me remind you, have a think back to what we did in week one, when we
因此，当我们进入工具时，让我提醒您，回想一下我们在第一周所做的事情，当我们

85
00:04:52,200 --> 00:04:58,520
had to build some boilerplate JSON to describe a function that we wanted to use as like a tool.
必须构建一些样板 JSON 来描述我们想要像工具一样使用的函数。

86
00:04:58,800 --> 00:05:04,050
It's quite chunky JSON that described the parameters and various other things about it.
它是相当厚重的 JSON，描述了参数和相关的各种其他内容。

87
00:05:04,050 --> 00:05:10,050
And then we had to write a function called handle tool calls, which is the one that had the the hokey
然后我们必须编写一个名为“处理工具调用”的函数，该函数具有做作的功能

88
00:05:10,090 --> 00:05:14,810
if statement that I then tried to write into something a bit more fancy, but which was still a fair
然后我尝试将 if 语句写成更奇特的东西，但这仍然是一个公平的

89
00:05:14,810 --> 00:05:17,650
amount of sort of gunk, to use a technical word.
用专业术语来说，就是大量的垃圾。

90
00:05:17,690 --> 00:05:23,690
And what we're now going to see is how that whole stuff can be, can be super simplified without taking
我们现在要看到的是，整个东西如何可以超级简化，而无需采取任何措施

91
00:05:23,690 --> 00:05:25,370
any flexibility away from us.
任何灵活性都离我们而去。

92
00:05:25,930 --> 00:05:28,530
So first of all, we're just going to recap.
首先，我们要回顾一下。

93
00:05:28,530 --> 00:05:34,130
We've got these three sales agents the professional, the engaging and the busy ones.
我们拥有这三位销售代理，他们专业、敬业且忙碌。

94
00:05:34,130 --> 00:05:35,210
And there they are.
他们就在那里。

95
00:05:35,450 --> 00:05:38,850
And let me just look at one of these sales agents.
让我看看其中一位销售代理。

96
00:05:38,930 --> 00:05:41,850
So if I look into it you can see that it's got a name.
所以如果我看一下它你就会发现它有一个名字。

97
00:05:41,850 --> 00:05:43,610
It's got the instructions.
它有说明。

98
00:05:43,610 --> 00:05:50,850
And you can see that it has things like tool choice tools, and it has like a list of tools that it
你可以看到它有工具选择工具之类的东西，它有一个工具列表

99
00:05:50,850 --> 00:05:53,130
has access to, which right now is empty.
可以访问，但现在是空的。

100
00:05:53,290 --> 00:05:57,370
So just to give you a sense of what's going on under the covers, it's perfectly simple.
因此，为了让您了解幕后发生的事情，这非常简单。

101
00:05:57,370 --> 00:05:59,450
But these are the constructs we're working with.
但这些是我们正在研究的结构。

102
00:05:59,950 --> 00:06:03,910
So what we're now going to do is have a tool.
所以我们现在要做的就是拥有一个工具。

103
00:06:04,350 --> 00:06:07,550
So this is a function send email.
所以这是一个发送电子邮件的函数。

104
00:06:07,550 --> 00:06:10,470
It takes an email body which is a string.
它需要一个电子邮件正文，它是一个字符串。

105
00:06:10,710 --> 00:06:13,830
And it has a like a doc string.
它有一个类似文档字符串。

106
00:06:13,990 --> 00:06:17,830
Send out an email with the given body to all sales prospects.
向所有潜在销售人员发送一封包含指定正文的电子邮件。

107
00:06:18,150 --> 00:06:21,950
Now what I've got in here is the from email.
现在我收到的是来自电子邮件的信息。

108
00:06:21,950 --> 00:06:28,710
And this email needs to be what's called the verified sender, the email address that you've set up
此电子邮件必须是所谓的已验证发件人，即您设置的电子邮件地址

109
00:06:28,710 --> 00:06:31,230
in SendGrid that you're allowed to send from.
在允许您发送的 SendGrid 中。

110
00:06:31,270 --> 00:06:33,030
Otherwise it won't actually send.
否则实际上不会发送。

111
00:06:33,110 --> 00:06:36,230
So you'll need to update this and then two email.
因此，您需要更新这封电子邮件，然后更新两封电子邮件。

112
00:06:36,230 --> 00:06:40,030
You should put that to be an email where you don't mind it receiving an email.
您应该将其设置为您不介意接收电子邮件的电子邮件。

113
00:06:40,070 --> 00:06:42,910
I would prefer that you change it from my Gmail here.
我希望您可以在此处从我的 Gmail 更改它。

114
00:06:42,910 --> 00:06:46,350
Otherwise I will get flooded with emails from people doing this.
否则我会收到大量来自这样做的人的电子邮件。

115
00:06:46,350 --> 00:06:49,990
So maybe I'll change it before I commit this to GitHub.
所以也许我会在将其提交到 GitHub 之前更改它。

116
00:06:49,990 --> 00:06:52,670
But yes, send that to another of your email addresses.
但是，可以，将其发送到您的另一个电子邮件地址。

117
00:06:52,670 --> 00:06:54,430
Or you could probably just send it to yourself.
或者您也可以将其发送给自己。

118
00:06:54,470 --> 00:07:00,290
I'm not sure, but send it to somewhere where you don't mind receiving cold sales emails, there'll
我不确定，但是将其发送到您不介意收到冷销售电子邮件的地方，就会有

119
00:07:00,290 --> 00:07:00,970
only be 1 or 2.
只能是1或2。

120
00:07:00,970 --> 00:07:02,730
We're not going to send a mass of them.
我们不会派出大量的人员。

121
00:07:03,210 --> 00:07:05,730
And then this is Sendgrid's API.
这就是Sendgrid 的API。

122
00:07:05,770 --> 00:07:07,170
It's perfectly simple.
这非常简单。

123
00:07:07,170 --> 00:07:07,890
It's SendGrid.
这是发送网格。

124
00:07:10,290 --> 00:07:13,130
And you give it a body so you can look through this.
你给它一个实体，这样你就可以看透它。

125
00:07:13,130 --> 00:07:20,890
But it's honestly it's just a boilerplate to send an email to a recipient and we respond with success.
但老实说，这只是向收件人发送电子邮件的样板，我们会成功回复。

126
00:07:21,130 --> 00:07:24,410
So this is very much like the tools that we wrote last time.
所以这非常像我们上次编写的工具。

127
00:07:24,410 --> 00:07:25,570
It's like a function to do it.
这就像一个函数来做到这一点。

128
00:07:25,610 --> 00:07:29,930
And if you remember, the next step was to write a ton of JSON to describe this.
如果您还记得的话，下一步就是编写大量 JSON 来描述这一点。

129
00:07:29,930 --> 00:07:36,650
But all we need to do with OpenAI is put one of these decorators above it at function tool.
但我们需要对 OpenAI 做的就是将这些装饰器之一放在函数工具的上方。

130
00:07:36,770 --> 00:07:41,850
If you're not sure how decorators work, again, that's in the guides, or just ask ChatGPT to explain
如果您不确定装饰器如何工作，请再次参阅指南，或者只是询问 ChatGPT 来解释

131
00:07:41,850 --> 00:07:42,290
it.
它。

132
00:07:42,290 --> 00:07:48,290
But that allows OpenAI to write some code to sort of do something with this function.
但这允许 OpenAI 编写一些代码来使用此函数执行某些操作。

133
00:07:48,330 --> 00:07:54,930
And but all we need to care about is we simply put that decorator above the function that we want to
但我们需要关心的是我们只需将该装饰器放在我们想要的函数之上

134
00:07:54,970 --> 00:07:56,530
treat as a tool.
当作工具来对待。

135
00:07:57,050 --> 00:08:03,110
And so we will just simply define that function doesn't look like we've done anything, but let's look
因此，我们只是简单地定义该函数，看起来我们什么也没做，但让我们看看

136
00:08:03,150 --> 00:08:05,150
at this thing called send email.
在这个叫做发送电子邮件的事情上。

137
00:08:05,190 --> 00:08:07,270
Now we think it's a function, right?
现在我们认为它是一个函数，对吗？

138
00:08:07,510 --> 00:08:10,870
But no, it's not a function because we have this decorator.
但不，它不是一个函数，因为我们有这个装饰器。

139
00:08:10,870 --> 00:08:14,670
It's been converted into something called a function tool.
它已被转换成一种称为功能工具的东西。

140
00:08:15,110 --> 00:08:17,390
It has a name send email.
它有一个名称发送电子邮件。

141
00:08:17,710 --> 00:08:19,030
It has a description.
它有一个描述。

142
00:08:19,030 --> 00:08:24,070
And that description is taken from the docstring comment we had right here.
该描述取自我们此处的文档字符串注释。

143
00:08:24,070 --> 00:08:24,870
Look at that.
看看那个。

144
00:08:24,870 --> 00:08:27,150
It's just turned that into a tool description.
它只是将其变成了工具描述。

145
00:08:27,150 --> 00:08:31,790
And then and this is the great stuff params JSON schema.
然后，这就是 params JSON 模式的重要内容。

146
00:08:32,030 --> 00:08:37,990
This stuff is all of the boilerplate JSON that we had to write last time.
这些东西是我们上次必须编写的所有样板 JSON。

147
00:08:37,990 --> 00:08:42,190
It's just done it for us because it's read this and it's figured out what's needed.
它只是为我们完成了这件事，因为它读了这篇文章并找出了我们需要什么。

148
00:08:42,390 --> 00:08:44,230
And and that's basically it.
基本上就是这样。

149
00:08:44,390 --> 00:08:51,790
So just by simply adding that decorator function tool, all of the work of faffing around with these
因此，只需添加装饰器功能工具，所有与这些相关的工作就完成了

150
00:08:51,790 --> 00:08:55,430
JSON objects has been taken away from us, which is great.
JSON 对象已经从我们身边消失了，这很棒。

151
00:08:55,430 --> 00:08:56,950
That's what a good framework should do.
这就是一个好的框架应该做的事情。

152
00:08:56,990 --> 00:08:59,990
Take out the boilerplate but leave us in full control.
去掉样板，但让我们完全控制。
