1
00:00:00,160 --> 00:00:05,120
Well, I'm back, although it took slightly longer than I expected, so the run that I had just kicked
嗯，我回来了，虽然比我预想的要长一些，所以我刚刚踢的跑步

2
00:00:05,120 --> 00:00:09,440
off actually ended up taking several minutes, and it appeared to lose its way.
结果实际上花了几分钟，而且它似乎迷了路。

3
00:00:09,480 --> 00:00:13,840
Going back again and again to get more and more emails generated.
一次又一次地返回以生成越来越多的电子邮件。

4
00:00:13,840 --> 00:00:17,080
So I actually cancelled it and ran it a second time and it ran fine.
所以我实际上取消了它并第二次运行它并且运行良好。

5
00:00:17,080 --> 00:00:18,120
But it is interesting.
但这很有趣。

6
00:00:18,120 --> 00:00:24,760
It's a it's a cautionary tale to reflect on the fact that by their very nature, these autonomous agents
这是一个警示故事，让我们反思这样一个事实：从本质上来说，这些自主代理

7
00:00:24,760 --> 00:00:25,520
are made.
被制作。

8
00:00:25,520 --> 00:00:30,720
This statement here, and this was the answer to the, the challenge from from last time that I say
这里的声明，这是对我上次所说的挑战的答案

9
00:00:30,720 --> 00:00:34,240
you can use the tools multiple times if you're not satisfied with the results.
如果您对结果不满意，可以多次使用这些工具。

10
00:00:34,240 --> 00:00:40,360
And that's really giving this kind of autonomy and potentially an infinite loop to the agent.
这确实为代理提供了这种自主权和潜在的无限循环。

11
00:00:40,360 --> 00:00:44,720
And sure enough, we I don't know if it was infinite, but we certainly had some kind of a loop going
果然，我们不知道它是否是无限的，但我们肯定有某种循环在进行

12
00:00:44,720 --> 00:00:45,000
on.
在。

13
00:00:45,000 --> 00:00:47,360
But I ran it a second time and it was fine.
但我又跑了第二次，就很好了。

14
00:00:47,520 --> 00:00:50,920
If I bring up the trace, here come the traces.
如果我提出痕迹，痕迹就来了。

15
00:00:51,160 --> 00:00:53,440
This this is the one that was going wrong.
这就是出了问题的地方。

16
00:00:53,440 --> 00:00:59,120
You can see it had run 14 tools and it was taking more than 300 seconds.
您可以看到它运行了 14 个工具，并且花费了超过 300 秒的时间。

17
00:00:59,120 --> 00:01:03,390
If I bring it up, you'll see that it was going through sales agents one, two and three and then back
如果我提起它，您会发现它正在通过销售代理一、二和三，然后返回

18
00:01:03,390 --> 00:01:04,790
to one, two and three again.
又到一、二、三。

19
00:01:04,790 --> 00:01:06,670
And I can load more and on.
我还可以加载更多内容。

20
00:01:06,830 --> 00:01:08,110
So it kept going.
所以它继续下去。

21
00:01:08,470 --> 00:01:11,070
Now you'll see, of course, that agent one is deep seek.
现在您当然会看到，第一个代理正在深度寻找。

22
00:01:11,110 --> 00:01:12,310
Agent two is Gemini.
二号经纪人是双子座。

23
00:01:12,350 --> 00:01:14,950
Agent three is llama 3.3.
三号代理是 llama 3.3。

24
00:01:15,230 --> 00:01:19,910
One other thing that I didn't point out last time that I would like to mention is that you can see that
上次我没有指出但我想提的另一件事是你可以看到

25
00:01:19,910 --> 00:01:22,070
these are running in parallel.
这些是并行运行的。

26
00:01:22,070 --> 00:01:27,790
They are running, of course asynchronously because again, because they're very I o bound, they are
它们当然是异步运行的，因为它们非常受限制，它们是

27
00:01:27,790 --> 00:01:34,030
doing they're waiting for information to come back from the API call that allows async IO to be running
他们正在等待从允许异步 IO 运行的 API 调用返回的信息

28
00:01:34,070 --> 00:01:35,550
multiple in parallel.
多个并联。

29
00:01:35,550 --> 00:01:39,990
But of course the three run and then it needs to sort of wait for.
但当然，这三个人都跑了，然后需要等待。

30
00:01:40,030 --> 00:01:46,470
Then the sales manager will review those three runs and decide whether it wants to run them again,
然后销售经理将审查这三轮运行并决定是否要再次运行它们，

31
00:01:46,510 --> 00:01:48,870
which apparently it did lots of times.
显然它已经做了很多次了。

32
00:01:48,910 --> 00:01:52,750
And llama 3.3 for some reason took a really long time on one of them.
由于某种原因，llama 3.3 在其中一个上花了很长时间。

33
00:01:52,750 --> 00:01:59,390
So you can see there is inherent instability with these autonomous agent frameworks.
所以你可以看到这些自主代理框架存在固有的不稳定性。

34
00:01:59,390 --> 00:02:02,550
And that's something that you need to code explicitly for.
这就是您需要明确编码的内容。

35
00:02:02,550 --> 00:02:02,580
Four.
四。

36
00:02:03,420 --> 00:02:07,820
Okay, but now let's just go back and look at the trace that did better.
好的，但现在让我们回过头来看看效果更好的跟踪。

37
00:02:07,980 --> 00:02:09,580
So this is the trace that just ran.
这就是刚刚运行的跟踪。

38
00:02:09,580 --> 00:02:12,260
And it took a rather more pleasing amount of time.
这花费了相当令人愉快的时间。

39
00:02:12,260 --> 00:02:15,940
And you can see that this time it only ran each agent once.
您可以看到，这次每个代理只运行一次。

40
00:02:15,980 --> 00:02:18,940
Deep seek Gemini and Llama 3.3.
深寻双子座和骆驼3.3。

41
00:02:19,140 --> 00:02:20,420
Each one ran.
一个个都跑了。

42
00:02:20,460 --> 00:02:22,580
Each one came back with a response.
每个人都带着回应回来了。

43
00:02:22,780 --> 00:02:28,940
That response was of course went to our handoff, went to the email manager that wrote the subject,
该回复当然会发送给我们，发送给撰写该主题的电子邮件管理器，

44
00:02:28,980 --> 00:02:34,420
wrote the email, and then an email arrived right here in my inbox.
写了电子邮件，然后一封电子邮件就到达了我的收件箱。

45
00:02:34,620 --> 00:02:37,700
So all has worked well in the end.
所以最终一切都很顺利。

46
00:02:38,620 --> 00:02:42,180
So I went through that code very fast because it's something that we saw before yesterday, so hopefully
所以我很快地浏览了这段代码，因为这是我们昨天之前看到的，所以希望

47
00:02:42,180 --> 00:02:43,460
it was somewhat familiar.
这有点熟悉。

48
00:02:43,500 --> 00:02:48,900
The new angle was that we were calling multiple models, and it was very easy because they are all models
新的角度是我们调用多个模型，这很容易，因为它们都是模型

49
00:02:48,900 --> 00:02:51,820
which have OpenAI compatible endpoints.
具有 OpenAI 兼容端点。

50
00:02:52,100 --> 00:02:57,620
Now, you may have noticed that there is one model that was missing there in the form of Anthropic's
现在，您可能已经注意到，其中缺少一个模型，即 Anthropic 的形式

51
00:02:57,620 --> 00:03:02,740
Claude and anthropic does not offer an OpenAI compatible endpoint.
Claude 和 anthropic 不提供 OpenAI 兼容端点。

52
00:03:02,740 --> 00:03:10,060
And so I understand that there isn't, as of today, an easy way to use Anthropic's Claude in lieu of
所以我明白，截至今天，还没有一种简单的方法可以使用 Anthropic 的 Claude 来代替

53
00:03:10,220 --> 00:03:13,180
those other models that have an OpenAI compatible endpoint.
具有 OpenAI 兼容端点的其他模型。

54
00:03:13,460 --> 00:03:14,980
But there are plenty of workarounds.
但有很多解决方法。

55
00:03:14,980 --> 00:03:19,820
So there is, for example, a third party provider called Open Router that people are probably a lot
例如，有一个名为 Open Router 的第三方提供商，人们可能很多

56
00:03:19,820 --> 00:03:26,340
of people use that, and it allows you to to set up your keys for other models, including Anthropic's
的人使用它，它允许您为其他模型设置密钥，包括 Anthropic 的

57
00:03:26,340 --> 00:03:26,900
Claude.
克劳德.

58
00:03:26,940 --> 00:03:30,380
And it has an open AI compatible endpoint.
它有一个开放的人工智能兼容端点。

59
00:03:30,380 --> 00:03:32,860
So you can go through open router to use Claude.
所以你可以通过开放路由器来使用Claude。

60
00:03:33,220 --> 00:03:39,060
Also, anthropic has the incredible MCP protocol, which we'll be talking about in the last week.
另外，anthropic 有令人难以置信的 MCP 协议，我们将在上周讨论它。

61
00:03:39,060 --> 00:03:44,020
And that gives us another route to be using anthropic through MCP.
这为我们提供了通过 MCP 使用人择的另一条途径。

62
00:03:44,220 --> 00:03:45,980
So more will come on that later.
所以稍后会有更多内容。

63
00:03:46,020 --> 00:03:51,460
In the meantime, the easiest way to do this is to use models other than anthropic for this purpose.
同时，最简单的方法是使用人择模型以外的模型来实现此目的。

64
00:03:51,460 --> 00:03:56,380
And perhaps quite soon Anthropic's Claude will be available through the OpenAI SDK direct.
也许很快 Anthropic 的 Claude 将可以通过 OpenAI SDK 直接使用。

65
00:03:56,980 --> 00:04:03,020
Anyway, the next thing we're going to do is talk about both structured outputs and guardrails.
不管怎样，我们接下来要做的就是讨论结构化输出和护栏。

66
00:04:03,020 --> 00:04:09,610
We're going to do them together Other, and guardrails are ways that you can put a constraint around
我们要一起做其他的，护栏是你可以施加约束的方式

67
00:04:09,610 --> 00:04:10,930
your agent platform.
您的代理平台。

68
00:04:10,930 --> 00:04:12,730
It's a test that you will do.
这是你要做的一个测试。

69
00:04:12,730 --> 00:04:18,250
And the cool thing about guardrails, I mean, you might think if guardrails were simply like a check
我的意思是，关于护栏的最酷的事情，你可能会认为护栏是否只是像一张支票

70
00:04:18,290 --> 00:04:23,650
of, of like, um, checking that something has given the right kind of results, you could just write
的，就像，嗯，检查某些东西是否给出了正确的结果，你可以这样写

71
00:04:23,650 --> 00:04:24,530
that in Python code.
Python 代码中的内容。

72
00:04:24,530 --> 00:04:30,130
You can just obviously look test whether the results have a certain property in them or not, and throw
您可以明显地查看测试结果是否具有某种属性，然后抛出

73
00:04:30,130 --> 00:04:31,370
an exception if they don't.
如果他们不这样做，则例外。

74
00:04:31,810 --> 00:04:37,450
The special thing about guardrails here is that guardrails can themselves be agents, which means that
这里护栏的特别之处在于护栏本身可以是代理，这意味着

75
00:04:37,450 --> 00:04:43,330
you can use an LLM to be checking that things look good at any point in your flow.
您可以使用法学硕士来检查流程中任何一点的情况是否良好。

76
00:04:43,610 --> 00:04:44,850
Well, actually, that's not quite true.
嗯，实际上，这并不完全正确。

77
00:04:44,850 --> 00:04:51,930
When I say at any point, guardrails actually can only be applied either to the input at the very beginning,
当我说在任何时候，护栏实际上只能应用于一开始的输入，

78
00:04:51,930 --> 00:04:56,810
the input of the first agent or the output of the last agent.
第一个智能体的输入或最后一个智能体的输出。

79
00:04:56,850 --> 00:04:59,730
You can't insert guardrails all over the place.
不能到处都加护栏。

80
00:04:59,730 --> 00:05:01,690
You just have them at the very beginning or the very end.
你只是在开始或结束时拥有它们。

81
00:05:01,690 --> 00:05:07,600
And they're designed to protect your model against getting an input, which is inappropriate or not.
它们旨在保护您的模型免受不适当或不适当的输入。

82
00:05:07,640 --> 00:05:09,120
Not what it's intended for.
不是它的目的。

83
00:05:09,560 --> 00:05:15,240
And also to protect it against producing an output which should not be shown to the user.
并且还可以防止它产生不应向用户显示的输出。

84
00:05:15,320 --> 00:05:16,840
So it's those two extremes.
所以这是两个极端。

85
00:05:16,840 --> 00:05:18,880
That's where you can implement guardrails.
这就是您可以实施护栏的地方。

86
00:05:18,880 --> 00:05:21,520
And we're going to implement an input guardrail right now.
我们现在要实施一个输入护栏。

87
00:05:21,520 --> 00:05:25,520
But as you'll see it's it's basically exactly the same thing either way.
但正如您将看到的，无论哪种方式，基本上都是完全相同的。

88
00:05:25,520 --> 00:05:28,360
And I'll leave a challenge for you to add an output one afterwards.
我将给你留下一个挑战，让你在之后添加一个输出。

89
00:05:29,000 --> 00:05:36,120
So the first thing I do because we're going to be working with structured outputs is I define an a class
所以我做的第一件事是定义一个 a 类，因为我们将使用结构化输出

90
00:05:36,160 --> 00:05:38,360
called name check output.
称为名称检查输出。

91
00:05:38,400 --> 00:05:42,800
We're going to be saying we're going to be checking for names for people's names because we don't want
我们会说我们要检查人们的名字，因为我们不想

92
00:05:42,800 --> 00:05:44,040
people's names in our emails.
我们的电子邮件中的人员姓名。

93
00:05:44,040 --> 00:05:47,360
We decided so we're going to have a name check output.
我们决定，我们将有一个名称检查输出。

94
00:05:47,360 --> 00:05:50,320
And this is one of these pedantic objects.
这就是这些迂腐的东西之一。

95
00:05:50,320 --> 00:05:55,560
If you remember, this is where you have objects classes which are designed to reflect a particular
如果您还记得的话，这就是您拥有旨在反映特定对象的对象类的地方。

96
00:05:55,560 --> 00:05:57,080
schema of data.
数据模式。

97
00:05:57,200 --> 00:06:02,960
So what we want is that we want the name check output to be something which has two fields is name in
所以我们想要的是，我们希望名称检查输出具有两个字段： name in

98
00:06:03,000 --> 00:06:09,430
message, which is a boolean where true should mean that there is a name in this message and name.
message，这是一个布尔值，其中 true 应该意味着此消息和名称中有一个名称。

99
00:06:09,470 --> 00:06:12,790
A string would be the name if there is a name in the message.
如果消息中有名称，则字符串将是名称。

100
00:06:13,310 --> 00:06:17,990
Okay, so this is all we're doing here is we're sort of defining we're defining a schema.
好的，这就是我们在这里所做的一切，我们正在定义一个模式。

101
00:06:17,990 --> 00:06:23,190
We're saying this is a particular structure of class that we want to to think of.
我们说这是我们想要考虑的特定类结构。

102
00:06:23,590 --> 00:06:26,150
And now we're going to define an agent.
现在我们要定义一个代理。

103
00:06:26,150 --> 00:06:27,870
And I'm naming it guardrail agent.
我将其命名为护栏代理。

104
00:06:27,870 --> 00:06:28,990
You can name it whatever you want.
您可以将其命名为任何您想要的名称。

105
00:06:29,030 --> 00:06:31,230
We are going to use this in a guardrail.
我们将在护栏中使用它。

106
00:06:31,230 --> 00:06:34,670
But this is just as of now just another agent we're creating.
但这只是我们现在正在创建的另一个代理。

107
00:06:34,830 --> 00:06:36,750
It's name is going to be name check.
其名称将进行名称检查。

108
00:06:36,990 --> 00:06:43,390
The instructions are check if the user is including someone's personal name in what they want you to
这些说明是检查用户是否在他们希望您添加的内容中包含某人的个人姓名

109
00:06:43,390 --> 00:06:43,870
do.
做。

110
00:06:44,550 --> 00:06:46,710
The output type this.
输出类型为this。

111
00:06:46,710 --> 00:06:48,670
This is the structured outputs piece.
这是结构化输出部分。

112
00:06:48,670 --> 00:06:54,670
We are telling this agent we don't want you to output text, which is what you normally do by default.
我们告诉该代理我们不希望您输出文本，这是您通常默认执行的操作。

113
00:06:54,670 --> 00:07:02,110
All of these are outputting just strings of data, but rather we want you to output a name check output.
所有这些都仅输出数据字符串，但我们希望您输出名称检查输出。

114
00:07:02,110 --> 00:07:07,070
We want you to output an object that conforms to this schema.
我们希望您输出符合此架构的对象。

115
00:07:07,390 --> 00:07:09,580
And you can use this for any of your agents.
您可以将其用于您的任何代理。

116
00:07:09,580 --> 00:07:13,700
So we could go back and use this as a way to structure our emails better.
所以我们可以回去使用它来更好地构建我们的电子邮件。

117
00:07:13,700 --> 00:07:18,900
So we could use this so that rather than emails being just strings, they could actually already have
所以我们可以使用它，这样电子邮件就不再只是字符串，而是实际上已经有了

118
00:07:18,940 --> 00:07:21,100
a subject, a recipient, a body.
主体、接受者、身体。

119
00:07:21,140 --> 00:07:22,940
We could do it that way from the get go.
我们可以从一开始就这样做。

120
00:07:22,940 --> 00:07:24,060
And that would be much nicer.
那会好得多。

121
00:07:24,060 --> 00:07:26,140
And that is in the challenges at the end.
这就是最后的挑战。

122
00:07:26,540 --> 00:07:29,780
But for here we specify the output type is name check output.
但这里我们指定输出类型是名称检查输出。

123
00:07:29,780 --> 00:07:34,260
And as before we specify a model GPT four mini.
和之前一样，我们指定了 GPT 4 mini 型号。

124
00:07:34,460 --> 00:07:37,820
And that brings us simply to the guardrail.
这就把我们带到了护栏上。

125
00:07:37,980 --> 00:07:42,220
So a guardrail is it's like an asynchronous.
所以护栏就像是异步的。

126
00:07:42,260 --> 00:07:43,340
It's a coroutine.
这是一个协程。

127
00:07:43,380 --> 00:07:44,340
It's going to say a function.
它会说一个函数。

128
00:07:44,340 --> 00:07:46,980
But it is of course strictly speaking a coroutine.
但严格来说它当然是一个协程。

129
00:07:47,340 --> 00:07:54,820
And you simply decorate it with input guardrail to say, I'm going to be using this as an input guardrail.
你只需用输入护栏装饰它，就可以说，我将使用它作为输入护栏。

130
00:07:54,860 --> 00:07:57,340
It's a bit like decorating something to be a tool.
这有点像装饰某物以使其成为工具。

131
00:07:57,740 --> 00:08:03,180
And there's a completely analogous one called output guardrail, which is what you would use if it was
还有一种完全类似的称为输出护栏，如果它是

132
00:08:03,180 --> 00:08:04,940
to be used as a guardrail for the output.
用作输出的护栏。

133
00:08:05,420 --> 00:08:11,700
You can call it whatever you want and it takes the context is a bunch of data that you can pass between
你可以随意称呼它，它的上下文是一堆你可以在之间传递的数据

134
00:08:11,700 --> 00:08:15,380
agents that we we haven't made use of the agent itself.
代理我们还没有使用代理本身。

135
00:08:15,540 --> 00:08:18,420
And this is the input, the input that's coming in.
这就是输入，即将到来的输入。

136
00:08:18,500 --> 00:08:19,540
I've called it message.
我把它称为消息。

137
00:08:19,780 --> 00:08:25,380
And so what we can do right here is we can as part of implementing this guardrail, we can actually
所以我们在这里可以做的是，作为实施这个护栏的一部分，我们实际上可以

138
00:08:25,420 --> 00:08:27,940
kick off this guardrail agent.
踢掉这个护栏代理。

139
00:08:27,940 --> 00:08:29,980
We can run this guardrail agent.
我们可以运行这个护栏代理。

140
00:08:30,540 --> 00:08:33,580
And it will it will be giving it these instructions.
它将给予它这些指示。

141
00:08:33,620 --> 00:08:39,540
It will be passing in the message and it will be expecting a name check output to come out of that.
它将传入消息，并期望从中产生名称检查输出。

142
00:08:40,220 --> 00:08:43,380
So this is basically going to do just what it says on the tin.
所以这基本上就是按照罐头上说的做的。

143
00:08:43,380 --> 00:08:49,340
It's going to check if someone's personal name is being included in the message.
它将检查消息中是否包含某人的个人姓名。

144
00:08:50,140 --> 00:08:55,740
And then you have to return that the rule about writing these guardrails is you have to return something
然后你必须返回编写这些护栏的规则是你必须返回一些东西

145
00:08:55,740 --> 00:08:58,780
called a guardrail function output.
称为护栏函数输出。

146
00:08:59,140 --> 00:09:05,180
That's that's always a thing you return, which is informing the system whether or not there is a problem.
这就是您始终返回的东西，即通知系统是否存在问题。

147
00:09:05,380 --> 00:09:07,100
And it has two, two things.
它有两件事。

148
00:09:07,140 --> 00:09:14,450
Output info is just a dictionary of stuff that might be useful for tracing and trip wire triggered is
输出信息只是可能对跟踪有用的内容的字典，触发的绊线是

149
00:09:14,450 --> 00:09:15,530
a boolean.
一个布尔值。

150
00:09:15,530 --> 00:09:16,410
It's true.
这是真的。

151
00:09:16,410 --> 00:09:19,130
If there's a problem you pass in true here.
如果有问题你可以在这里传递 true 。

152
00:09:19,130 --> 00:09:25,450
If something has happened which should trip the trip wire and alert the guardrail has not been met.
如果发生了一些事情，应该触发绊线并警告护栏没有被碰到。

153
00:09:25,450 --> 00:09:26,850
And there is a problem.
但有一个问题。

154
00:09:26,850 --> 00:09:34,130
So what we're doing here is we're saying if this agent that we just ran, this agent produced an object
所以我们在这里所做的是，如果我们刚刚运行的代理生成了一个对象

155
00:09:34,130 --> 00:09:41,730
of type name check output, if that has is name and message set to true, which means that this agent
类型名称检查输出，如果名称和消息设置为 true，则意味着该代理

156
00:09:41,730 --> 00:09:49,050
reckons that there's someone's personal name in the instructions, then that should trigger the trip
认为说明中有某人的个人姓名，那么应该会触发行程

157
00:09:49,090 --> 00:09:49,570
wire.
金属丝。

158
00:09:49,730 --> 00:09:52,810
That should cause this guardrail to fail.
这应该会导致这个护栏失效。

159
00:09:52,810 --> 00:09:54,250
And there should be a problem.
而且应该有问题。

160
00:09:54,730 --> 00:09:56,010
That's that's the key.
这就是关键。

161
00:09:56,010 --> 00:09:57,170
That's how it works.
这就是它的工作原理。

162
00:09:57,170 --> 00:09:58,290
I hope that makes sense.
我希望这是有道理的。

163
00:09:58,290 --> 00:10:00,490
And you could use exactly this structure.
你完全可以使用这个结构。

164
00:10:00,490 --> 00:10:04,570
And then of course, for output guardrails, it's pretty much the same thing.
当然，对于输出护栏来说，这几乎是一样的。

165
00:10:04,570 --> 00:10:07,490
But instead of message you would put the output there.
但您可以将输出放在那里，而不是消息。

166
00:10:07,530 --> 00:10:08,970
Otherwise exactly the same.
否则完全一样。

167
00:10:09,450 --> 00:10:11,170
All right let's give this a try.
好吧，让我们尝试一下。
