1
00:00:00,160 --> 00:00:04,720
So, look, I don't know if you're anything like me, but I'm having something of a change of heart.
所以，听着，我不知道你是否和我一样，但我的想法正在改变。

2
00:00:04,960 --> 00:00:11,960
So I started this week quite clearly with OpenAI agents SDK as my favorite, and obviously with crew
因此，我本周一开始就非常明确地将 OpenAI 代理 SDK 作为我的最爱，当然还有工作人员

3
00:00:12,000 --> 00:00:17,000
as my second favorite, and being a little bit skeptical of Landgraf because you sign up for a lot.
作为我第二喜欢的，我对 Landgraf 有点怀疑，因为你注册了很多。

4
00:00:17,160 --> 00:00:18,680
But I'm coming around.
但我会过来。

5
00:00:18,720 --> 00:00:20,080
I'm having a really great time.
我玩得很开心。

6
00:00:20,080 --> 00:00:23,920
And what I've got to show you today, I feel like you're going to be there, right there with me.
今天我要向你展示的，我觉得你会在那里，就在我身边。

7
00:00:24,280 --> 00:00:27,480
I'm actually becoming a serious fan of Landgraf.
我实际上已经成为 Landgraf 的忠实粉丝了。

8
00:00:27,640 --> 00:00:30,920
Uh, and there's some really cool stuff, so see what you think.
呃，还有一些非常酷的东西，所以看看你的想法。

9
00:00:31,160 --> 00:00:35,760
Uh, I'm, uh, I'm suddenly feeling treacherous against OpenAI agents SDK.
呃，我，呃，我突然对 OpenAI 代理 SDK 感到不安。

10
00:00:36,160 --> 00:00:37,760
Uh, so, uh, welcome.
呃，所以，呃，欢迎。

11
00:00:37,760 --> 00:00:44,520
Welcome to week four, day four, introducing a new project sidekick, and I can't wait to tell you
欢迎来到第四周第四天，介绍一个新的项目伙伴，我迫不及待地想告诉你

12
00:00:44,520 --> 00:00:45,000
about it.
关于它。

13
00:00:45,120 --> 00:00:46,280
So what are we going to do today?
那么我们今天要做什么呢？

14
00:00:46,280 --> 00:00:47,560
How are we going to go deeper?
我们怎样才能更深入呢？

15
00:00:47,600 --> 00:00:49,960
You know, we always go a bit deeper with each of these.
你知道，我们总是对这些问题进行更深入的研究。

16
00:00:50,160 --> 00:00:55,600
So first of all I'm going to introduce I'm going to unveil a new tool which is going to be incredibly
首先，我要介绍一个新工具，它将令人难以置信

17
00:00:55,600 --> 00:00:59,520
powerful and which is going to allow us to do very different things.
强大，这将使我们能够做非常不同的事情。

18
00:00:59,760 --> 00:01:03,320
We're going to talk about structured outputs, something that we've I mean, it's been a recurring theme.
我们将讨论结构化输出，我的意思是，这是一个反复出现的主题。

19
00:01:03,320 --> 00:01:04,320
We've done that in each of these.
我们在每一个方面都做到了这一点。

20
00:01:04,320 --> 00:01:05,880
We'll use it here too.
我们也会在这里使用它。

21
00:01:06,220 --> 00:01:11,860
And we're also going to build a proper multi-agent workflow in Landgraaf so that you see it really coming
我们还将在 Landgraaf 中构建适当的多代理工作流程，以便您看到它真正的到来

22
00:01:11,900 --> 00:01:17,860
together, the equivalent of the handoff in OpenAI agents SDK, or having a crew of agents.
在一起，相当于 OpenAI 代理 SDK 中的切换，或者拥有一组代理。

23
00:01:17,860 --> 00:01:19,540
We will be doing that.
我们将会这样做。

24
00:01:20,020 --> 00:01:24,540
And as a reminder, on the diagram I did last time, that brings it all together.
提醒一下，在我上次做的图表上，它把所有的东西都整合在一起了。

25
00:01:24,540 --> 00:01:26,060
Remember the terminology?
还记得术语吗？

26
00:01:26,220 --> 00:01:33,380
A super step is a complete invocation of the graph, and each super step represents like one user input
超级步骤是对图的完整调用，每个超级步骤代表一个用户输入

27
00:01:33,380 --> 00:01:37,740
coming in and then flowing it through your graph of agents and tools.
进来，然后将其流过您的代理和工具图。

28
00:01:37,900 --> 00:01:42,420
And then those blue diagrams are representing the graph that gets executed.
然后那些蓝色图代表被执行的图。

29
00:01:42,420 --> 00:01:47,660
The state is managed through that graph, and reducers are called to make sure that the state object,
状态通过该图进行管理，并调用化简器以确保状态对象，

30
00:01:47,940 --> 00:01:52,340
which is an immutable object, is maintained and managed through that.
这是一个不可变的对象，通过它来维护和管理。

31
00:01:52,340 --> 00:01:58,300
But between the super steps, you use checkpointing as your way of maintaining state.
但在超级步骤之间，您可以使用检查点作为维护状态的方式。

32
00:01:58,300 --> 00:02:03,020
And checkpointing is very powerful, and it lets you do things like rewind the clock and put your state
检查点非常强大，它可以让你做一些事情，比如倒回时钟并放置你的状态

33
00:02:03,020 --> 00:02:05,140
back to any prior point.
回到之前的任何一点。

34
00:02:05,660 --> 00:02:08,620
So with that quick recap, let's go to the lab.
快速回顾一下，让我们进入实验室。

35
00:02:09,100 --> 00:02:09,620
All right.
好的。

36
00:02:09,620 --> 00:02:14,520
So we get started in week four and we're going to go to lab number three.
所以我们从第四周开始，我们将进入第三个实验室。

37
00:02:14,560 --> 00:02:14,960
Week four.
第四周。

38
00:02:15,000 --> 00:02:15,360
Day four.
第四天。

39
00:02:15,400 --> 00:02:16,120
Lab three.
实验室三。

40
00:02:16,480 --> 00:02:19,400
Uh, it's, as I say, the start of an awesome project.
呃，正如我所说，这是一个很棒的项目的开始。

41
00:02:19,400 --> 00:02:21,080
I am super happy with this.
我对此非常满意。

42
00:02:21,080 --> 00:02:22,520
I hope you will be too.
我希望你也会如此。

43
00:02:22,800 --> 00:02:24,520
We do some imports.
我们做一些进口。

44
00:02:25,200 --> 00:02:25,880
Takes a while.
需要一段时间。

45
00:02:25,880 --> 00:02:27,280
There's a lot of stuff to go.
有很多东西要去。

46
00:02:27,360 --> 00:02:28,800
And then we've got this empty cell here.
然后我们就得到了这个空单元格。

47
00:02:28,800 --> 00:02:29,640
Why have we got empty cell?
为什么我们有空单元格？

48
00:02:29,680 --> 00:02:31,520
Because of course we have to do load.
因为我们当然要加载。

49
00:02:31,560 --> 00:02:34,320
Dot override is true.
点覆盖是正确的。

50
00:02:35,280 --> 00:02:38,000
This is second nature to you at this point.
此时，这是你的第二天性。

51
00:02:38,320 --> 00:02:38,880
Okay.
好的。

52
00:02:38,880 --> 00:02:46,880
So I also I'm going to introduce this time asynchronous Landgraf using Landgraf in async mode, uh,
那么我这次也来介绍一下异步的Landgraf，在async模式下使用Landgraf，呃，

53
00:02:46,920 --> 00:02:48,600
which I promised was going to happen this week.
我承诺这将在本周发生。

54
00:02:49,080 --> 00:02:52,680
And it's very similar to using long chain in sync mode.
这与在同步模式下使用长链非常相似。

55
00:02:52,880 --> 00:03:02,960
Uh, when we used to call tools to run a tool, you can now call await tool dot to run the tool asynchronously,
呃，以前我们调用tools来运行一个工具，现在可以调用await tool dot来异步运行该工具了，

56
00:03:02,960 --> 00:03:04,240
but passing in the same inputs.
但传递相同的输入。

57
00:03:04,240 --> 00:03:05,480
Otherwise it's just the same.
否则就一样了。

58
00:03:05,760 --> 00:03:12,360
And to invoke the graph, if we would have said tool graph invoke state before, we can now say await
为了调用图表，如果我们之前说过工具图调用状态，那么现在我们可以说等待

59
00:03:12,400 --> 00:03:14,400
graph a invoke state.
绘制调用状态图。

60
00:03:14,600 --> 00:03:20,340
So that is just simply a way to run a graph in asynchronous mode.
所以这只是以异步模式运行图形的一种简单方法。

61
00:03:20,340 --> 00:03:21,940
And that is what we're going to be doing.
这就是我们要做的。

62
00:03:22,540 --> 00:03:26,820
Uh, for the state, I'm going to again be using a typed dict.
呃，对于国家来说，我将再次使用打字词典。

63
00:03:27,060 --> 00:03:31,540
So that means that it looks very much like when we use pydantic objects, you just have one field I'm
所以这意味着它看起来非常像当我们使用 pydantic 对象时，你只有一个字段

64
00:03:31,540 --> 00:03:33,220
going to have called messages.
将会有呼叫消息。

65
00:03:33,260 --> 00:03:34,420
It is annotated.
是有注释的。

66
00:03:34,420 --> 00:03:35,740
The type is a list.
类型是一个列表。

67
00:03:35,740 --> 00:03:41,660
And this is telling Landgraf we want it to use ad messages, which is a canned function that you can
这告诉 Landgraf 我们希望它使用广告消息，这是一个罐装功能，您可以

68
00:03:41,700 --> 00:03:42,220
import.
进口。

69
00:03:42,220 --> 00:03:47,660
We want that to be the reducer, which is going to keep on adding messages whenever we return that as
我们希望它成为减速器，每当我们将其返回为时，它将继续添加消息

70
00:03:47,660 --> 00:03:49,620
our state from a node.
我们的状态来自一个节点。

71
00:03:49,900 --> 00:03:53,140
And we will start a graph builder with that state.
我们将使用该状态启动一个图形生成器。

72
00:03:53,940 --> 00:03:54,580
Okay.
好的。

73
00:03:54,860 --> 00:03:55,900
So far so good.
到目前为止，一切都很好。

74
00:03:56,100 --> 00:03:56,620
Okay.
好的。

75
00:03:56,660 --> 00:04:00,300
Next up we are going to create a tool that we did last time.
接下来我们将创建一个我们上次创建的工具。

76
00:04:00,300 --> 00:04:01,620
So we can do it nice and quickly.
所以我们可以做得又好又快。

77
00:04:01,620 --> 00:04:04,780
Here it is the push notification tool.
这是推送通知工具。

78
00:04:05,020 --> 00:04:07,220
We define our function push.
我们定义我们的函数push。

79
00:04:07,220 --> 00:04:14,740
And then we wrap it package it in a tool called tool push which describes what it is it calls the function.
然后我们将它封装在一个名为 tool push 的工具中，该工具描述了它调用的函数是什么。

80
00:04:15,100 --> 00:04:19,060
And that is all we need to do okay.
这就是我们需要做的一切。

81
00:04:19,380 --> 00:04:21,610
Now now it gets exciting.
现在变得令人兴奋了。

82
00:04:22,090 --> 00:04:23,050
Playwright.
剧作家。

83
00:04:23,090 --> 00:04:24,210
Do you know what playwright is?
你知道什么是剧作家吗？

84
00:04:24,250 --> 00:04:28,130
Playwright is one of these browser automation bits of software.
Playwright 是这些浏览器自动化软件之一。

85
00:04:28,170 --> 00:04:34,090
It's considered the sort of the new the next generation of selenium, which many, many people have
它被认为是一种新的下一代硒，很多很多人都拥有它

86
00:04:34,090 --> 00:04:34,290
used.
用过的。

87
00:04:34,330 --> 00:04:35,530
I've used selenium an awful lot.
我已经使用了很多硒。

88
00:04:35,570 --> 00:04:42,290
Playwright is by Microsoft and it's a, it's a it's a very nice framework for running a browser.
Playwright 是 Microsoft 开发的，它是一个非常好的运行浏览器的框架。

89
00:04:42,290 --> 00:04:45,210
And it's traditionally originally used for testing.
它传统上最初用于测试。

90
00:04:45,210 --> 00:04:47,170
So it's used for test purposes.
因此它用于测试目的。

91
00:04:47,650 --> 00:04:52,610
And a lot of people also use it for web scraping, because if you just try and request a web page,
很多人也用它来抓取网页，因为如果你只是尝试请求一个网页，

92
00:04:52,610 --> 00:04:57,650
you just get back like the server content, if you use something like Selenium or Playwright, you can
你只是像服务器内容一样返回，如果你使用像 Selenium 或 Playwright 这样的东西，你可以

93
00:04:57,650 --> 00:05:03,450
actually render it in a browser, run the JavaScript, paint the page, and then use that to actually
实际上在浏览器中渲染它，运行 JavaScript，绘制页面，然后使用它来实际

94
00:05:03,450 --> 00:05:04,410
get the content.
获取内容。

95
00:05:04,730 --> 00:05:12,890
So playwright is a is a powerful tool for running a browser window, and it can do so what they call
所以 playwright 是一个运行浏览器窗口的强大工具，它可以做到他们所说的

96
00:05:12,890 --> 00:05:16,490
headless, which means you don't even see the browser windows, just like running behind the scenes
无头，这意味着你甚至看不到浏览器窗口，就像在幕后运行一样

97
00:05:16,690 --> 00:05:22,490
or not headless headful in which case you see the browser screen yourself and you can interact with
或者不是无头有头，在这种情况下，您自己可以看到浏览器屏幕，并且可以与

98
00:05:22,490 --> 00:05:22,850
it.
它。

99
00:05:23,010 --> 00:05:24,170
So that is playwright.
所以这就是剧作家。

100
00:05:24,170 --> 00:05:25,330
You may already know it.
你可能已经知道了。

101
00:05:25,370 --> 00:05:26,830
A lot of people use playwright.
很多人都用剧作家。

102
00:05:26,830 --> 00:05:28,230
This is how you install it.
这就是您安装它的方式。

103
00:05:28,230 --> 00:05:31,910
You type playwright install to do it on on Windows and Mac OS or on Linux.
您可以在 Windows 和 Mac OS 或 Linux 上键入 playwright install 来执行此操作。

104
00:05:31,950 --> 00:05:35,750
It's this longer command and it will then be installed.
这是一个较长的命令，然后将被安装。

105
00:05:35,750 --> 00:05:37,790
And if you have problems with that, then let me know.
如果您对此有疑问，请告诉我。

106
00:05:37,790 --> 00:05:38,870
But hopefully not.
但希望不是。

107
00:05:39,430 --> 00:05:41,350
Okay, one other thing to mention.
好吧，还有一件事要提。

108
00:05:41,350 --> 00:05:43,190
One other little detail here.
这里还有一个小细节。

109
00:05:43,230 --> 00:05:46,470
And this is just for running it in a notebook.
这只是为了在笔记本上运行它。

110
00:05:46,790 --> 00:05:53,550
Um, one of the problems, one of the challenges with async IO is that Asyncio runs an event loop.
嗯，问题之一，异步 IO 的挑战之一是 Asyncio 运行事件循环。

111
00:05:53,830 --> 00:05:58,430
Um, and when you when it runs an event loop, it runs this thing that's just constantly making sure
嗯，当你运行一个事件循环时，它会运行这个不断确保

112
00:05:58,430 --> 00:06:01,230
that it's running anything that's being awaited.
它正在运行任何正在等待的东西。

113
00:06:01,270 --> 00:06:05,190
And then when it's holding on IO, it runs something else that's being awaited.
然后当它持有 IO 时，它会运行其他正在等待的东西。

114
00:06:05,550 --> 00:06:10,510
Uh, and one of the problems is that that async IO only supports one event loop.
呃，问题之一是异步 IO 仅支持一个事件循环。

115
00:06:10,510 --> 00:06:15,590
And if there's an event loop running, you can't within that event loop, run another event loop.
如果正在运行一个事件循环，则您无法在该事件循环内运行另一个事件循环。

116
00:06:15,590 --> 00:06:20,630
And we're running an event loop as part of running, uh, this notebook right now.
我们正在运行一个事件循环，作为运行这个笔记本的一部分。

117
00:06:20,750 --> 00:06:24,990
And so that can cause problems when you try and kick off async processes within async processes.
因此，当您尝试在异步进程中启动异步进程时，这可能会导致问题。

118
00:06:25,230 --> 00:06:32,290
Uh, and so there is this package called nest async IO that's quite popular, which you can just simply
呃，所以有一个名为 Nest async IO 的软件包非常流行，您可以简单地使用它

119
00:06:32,290 --> 00:06:38,570
use this and then it like patches async IO so that you can have an event loop within an event loop.
使用它，然后像修补异步 IO 一样使用它，以便您可以在事件循环中拥有事件循环。

120
00:06:38,730 --> 00:06:42,890
And as you will soon understand from me prattling away, we're going to want that because we're going
正如你很快就会从我的喋喋不休中了解到的那样，我们会想要这样，因为我们要

121
00:06:42,890 --> 00:06:48,890
to want to run playwright asynchronously, because we're going to build an agent that can drive playwright.
想要异步运行 playwright，因为我们将构建一个可以驱动 playwright 的代理。

122
00:06:48,890 --> 00:06:52,090
And so we're going to need that concept of an event loop within an event loop.
因此，我们需要事件循环中的事件循环这一概念。

123
00:06:52,090 --> 00:06:55,250
But when we later put this into Python code, we actually won't need this anymore.
但是当我们稍后将其放入Python代码中时，我们实际上不再需要它了。

124
00:06:55,250 --> 00:06:56,410
But we'll need it for now.
但我们现在需要它。

125
00:06:56,650 --> 00:06:57,210
All right.
好的。

126
00:06:57,250 --> 00:06:58,730
That's a long sidebar.
这是一个很长的侧边栏。

127
00:06:58,730 --> 00:06:59,610
That's over.
就这样结束了。

128
00:06:59,770 --> 00:07:01,370
But now comes the magic.
但现在魔法来了。

129
00:07:01,570 --> 00:07:08,330
So one of the incredible things about Landgraf and Long Chain, I'm becoming a convert of both, is
因此，Landgraf 和 Long Chain 令人难以置信的事情之一是，我正在成为两者的皈依者。

130
00:07:08,330 --> 00:07:12,890
that they come with so many great tools out of the box.
他们配备了许多开箱即用的出色工具。

131
00:07:13,210 --> 00:07:15,850
Many of them are in the community package.
其中许多都包含在社区包中。

132
00:07:15,890 --> 00:07:20,410
There's actually a couple of different ways that you can run a playwright.
实际上，管理剧作家有几种不同的方式。

133
00:07:20,410 --> 00:07:22,050
There's two sets of tools.
有两套工具。

134
00:07:22,050 --> 00:07:25,050
One of them is a more simplistic one that's just a bit higher level.
其中一个是更简单的，只是级别更高一点。

135
00:07:25,210 --> 00:07:29,890
This one that I've got here, uh, the Playwright Browser Toolkit.
我这里有一个，呃，剧作家浏览器工具包。

136
00:07:29,890 --> 00:07:35,050
This is a lower level set of tools which provides a bunch of different tools.
这是一组较低级别的工具，提供了许多不同的工具。

137
00:07:35,090 --> 00:07:37,310
Let's just We're gonna create this.
让我们来创建这个。

138
00:07:37,310 --> 00:07:43,670
So this is this is, um, creating an asynchronous playwright browser, and then it's building a toolkit
所以这就是，嗯，创建一个异步剧作家浏览器，然后构建一个工具包

139
00:07:43,670 --> 00:07:45,030
from that browser.
从该浏览器。

140
00:07:45,030 --> 00:07:48,190
And now we've, we've got the tools into a variable tools.
现在我们已经将这些工具变成了可变工具。

141
00:07:48,190 --> 00:07:49,590
So I'm just going to print these.
所以我要把这些打印出来。

142
00:07:49,750 --> 00:07:53,630
And here are all of the tools that we get in this package.
这是我们在这个包中获得的所有工具。

143
00:07:53,630 --> 00:08:00,110
We get something that lets you uh, click on an element in a web page, navigate the browser to a particular
我们得到了一些东西，可以让你呃，点击网页中的一个元素，将浏览器导航到特定的

144
00:08:00,110 --> 00:08:06,750
web page, go to the previous web page like press the back button, extract text from a web page, extract
网页，转到上一个网页，例如按后退按钮，从网页中提取文本，提取

145
00:08:06,790 --> 00:08:10,830
hyperlinks, get elements, and then the current web page.
超链接，获取元素，然后是当前网页。

146
00:08:11,110 --> 00:08:17,150
Uh, so it gives you quite granular control over what's going on in this playwright browser.
呃，所以它可以让您非常精细地控制这个剧作家浏览器中发生的事情。

147
00:08:17,750 --> 00:08:22,310
So again, to recap, playwright allows you to launch a browser window.
再次回顾一下，剧作家允许您启动浏览器窗口。

148
00:08:22,510 --> 00:08:28,670
And then this Landgraaf or Lang chain set of tools gives us a series of tools that will allow us to
然后这套 Landgraaf 或 Lang 链工具为我们提供了一系列工具，使我们能够

149
00:08:28,710 --> 00:08:35,310
interact with that browser open windows, navigate, read the text, read the elements, do that kind
与该浏览器交互打开窗口、导航、阅读文本、阅读元素等

150
00:08:35,310 --> 00:08:35,870
of thing.
的东西。

151
00:08:36,070 --> 00:08:37,110
That's pretty cool.
太酷了。

152
00:08:37,110 --> 00:08:41,710
And that is something we're going to be able to arm our agent to be able to use.
这就是我们将能够武装我们的代理来使用的东西。
