So, look, I don't know if you're anything like me, but I'm having something of a change of heart. 所以，听着，我不知道你是否和我一样，但我的想法正在改变。
So I started this week quite clearly with OpenAI agents SDK as my favorite, and obviously with crew 因此，我本周一开始就非常明确地将 OpenAI 代理 SDK 作为我的最爱，当然还有工作人员
as my second favorite, and being a little bit skeptical of Landgraf because you sign up for a lot. 作为我第二喜欢的，我对 Landgraf 有点怀疑，因为你注册了很多。
But I'm coming around. 但我会过来。
I'm having a really great time. 我玩得很开心。
And what I've got to show you today, I feel like you're going to be there, right there with me. 今天我要向你展示的，我觉得你会在那里，就在我身边。
I'm actually becoming a serious fan of Landgraf. 我实际上已经成为 Landgraf 的忠实粉丝了。
Uh, and there's some really cool stuff, so see what you think. 呃，还有一些非常酷的东西，所以看看你的想法。
Uh, I'm, uh, I'm suddenly feeling treacherous against OpenAI agents SDK. 呃，我，呃，我突然对 OpenAI 代理 SDK 感到不安。
Uh, so, uh, welcome. 呃，所以，呃，欢迎。
Welcome to week four, day four, introducing a new project sidekick, and I can't wait to tell you 欢迎来到第四周第四天，介绍一个新的项目伙伴，我迫不及待地想告诉你
about it. 关于它。
So what are we going to do today? 那么我们今天要做什么呢？
How are we going to go deeper? 我们怎样才能更深入呢？
You know, we always go a bit deeper with each of these. 你知道，我们总是对这些问题进行更深入的研究。
So first of all I'm going to introduce I'm going to unveil a new tool which is going to be incredibly 首先，我要介绍一个新工具，它将令人难以置信
powerful and which is going to allow us to do very different things. 强大，这将使我们能够做非常不同的事情。
We're going to talk about structured outputs, something that we've I mean, it's been a recurring theme. 我们将讨论结构化输出，我的意思是，这是一个反复出现的主题。
We've done that in each of these. 我们在每一个方面都做到了这一点。
We'll use it here too. 我们也会在这里使用它。
And we're also going to build a proper multi-agent workflow in Landgraaf so that you see it really coming 我们还将在 Landgraaf 中构建适当的多代理工作流程，以便您看到它真正的到来
together, the equivalent of the handoff in OpenAI agents SDK, or having a crew of agents. 在一起，相当于 OpenAI 代理 SDK 中的切换，或者拥有一组代理。
We will be doing that. 我们将会这样做。
And as a reminder, on the diagram I did last time, that brings it all together. 提醒一下，在我上次做的图表上，它把所有的东西都整合在一起了。
Remember the terminology? 还记得术语吗？
A super step is a complete invocation of the graph, and each super step represents like one user input 超级步骤是对图的完整调用，每个超级步骤代表一个用户输入
coming in and then flowing it through your graph of agents and tools. 进来，然后将其流过您的代理和工具图。
And then those blue diagrams are representing the graph that gets executed. 然后那些蓝色图代表被执行的图。
The state is managed through that graph, and reducers are called to make sure that the state object, 状态通过该图进行管理，并调用化简器以确保状态对象，
which is an immutable object, is maintained and managed through that. 这是一个不可变的对象，通过它来维护和管理。
But between the super steps, you use checkpointing as your way of maintaining state. 但在超级步骤之间，您可以使用检查点作为维护状态的方式。
And checkpointing is very powerful, and it lets you do things like rewind the clock and put your state 检查点非常强大，它可以让你做一些事情，比如倒回时钟并放置你的状态
back to any prior point. 回到之前的任何一点。
So with that quick recap, let's go to the lab. 快速回顾一下，让我们进入实验室。
All right. 好的。
So we get started in week four and we're going to go to lab number three. 所以我们从第四周开始，我们将进入第三个实验室。
Week four. 第四周。
Day four. 第四天。
Lab three. 实验室三。
Uh, it's, as I say, the start of an awesome project. 呃，正如我所说，这是一个很棒的项目的开始。
I am super happy with this. 我对此非常满意。
I hope you will be too. 我希望你也会如此。
We do some imports. 我们做一些进口。
Takes a while. 需要一段时间。
There's a lot of stuff to go. 有很多东西要去。
And then we've got this empty cell here. 然后我们就得到了这个空单元格。
Why have we got empty cell? 为什么我们有空单元格？
Because of course we have to do load. 因为我们当然要加载。
Dot override is true. 点覆盖是正确的。
This is second nature to you at this point. 此时，这是你的第二天性。
Okay. 好的。
So I also I'm going to introduce this time asynchronous Landgraf using Landgraf in async mode, uh, 那么我这次也来介绍一下异步的Landgraf，在async模式下使用Landgraf，呃，
which I promised was going to happen this week. 我承诺这将在本周发生。
And it's very similar to using long chain in sync mode. 这与在同步模式下使用长链非常相似。
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来异步运行该工具了，
but passing in the same inputs. 但传递相同的输入。
Otherwise it's just the same. 否则就一样了。
And to invoke the graph, if we would have said tool graph invoke state before, we can now say await 为了调用图表，如果我们之前说过工具图调用状态，那么现在我们可以说等待
graph a invoke state. 绘制调用状态图。
So that is just simply a way to run a graph in asynchronous mode. 所以这只是以异步模式运行图形的一种简单方法。
And that is what we're going to be doing. 这就是我们要做的。
Uh, for the state, I'm going to again be using a typed dict. 呃，对于国家来说，我将再次使用打字词典。
So that means that it looks very much like when we use pydantic objects, you just have one field I'm 所以这意味着它看起来非常像当我们使用 pydantic 对象时，你只有一个字段
going to have called messages. 将会有呼叫消息。
It is annotated. 是有注释的。
The type is a list. 类型是一个列表。
And this is telling Landgraf we want it to use ad messages, which is a canned function that you can 这告诉 Landgraf 我们希望它使用广告消息，这是一个罐装功能，您可以
import. 进口。
We want that to be the reducer, which is going to keep on adding messages whenever we return that as 我们希望它成为减速器，每当我们将其返回为时，它将继续添加消息
our state from a node. 我们的状态来自一个节点。
And we will start a graph builder with that state. 我们将使用该状态启动一个图形生成器。
Okay. 好的。
So far so good. 到目前为止，一切都很好。
Okay. 好的。
Next up we are going to create a tool that we did last time. 接下来我们将创建一个我们上次创建的工具。
So we can do it nice and quickly. 所以我们可以做得又好又快。
Here it is the push notification tool. 这是推送通知工具。
We define our function push. 我们定义我们的函数push。
And then we wrap it package it in a tool called tool push which describes what it is it calls the function. 然后我们将它封装在一个名为 tool push 的工具中，该工具描述了它调用的函数是什么。
And that is all we need to do okay. 这就是我们需要做的一切。
Now now it gets exciting. 现在变得令人兴奋了。
Playwright. 剧作家。
Do you know what playwright is? 你知道什么是剧作家吗？
Playwright is one of these browser automation bits of software. Playwright 是这些浏览器自动化软件之一。
It's considered the sort of the new the next generation of selenium, which many, many people have 它被认为是一种新的下一代硒，很多很多人都拥有它
used. 用过的。
I've used selenium an awful lot. 我已经使用了很多硒。
Playwright is by Microsoft and it's a, it's a it's a very nice framework for running a browser. Playwright 是 Microsoft 开发的，它是一个非常好的运行浏览器的框架。
And it's traditionally originally used for testing. 它传统上最初用于测试。
So it's used for test purposes. 因此它用于测试目的。
And a lot of people also use it for web scraping, because if you just try and request a web page, 很多人也用它来抓取网页，因为如果你只是尝试请求一个网页，
you just get back like the server content, if you use something like Selenium or Playwright, you can 你只是像服务器内容一样返回，如果你使用像 Selenium 或 Playwright 这样的东西，你可以
actually render it in a browser, run the JavaScript, paint the page, and then use that to actually 实际上在浏览器中渲染它，运行 JavaScript，绘制页面，然后使用它来实际
get the content. 获取内容。
So playwright is a is a powerful tool for running a browser window, and it can do so what they call 所以 playwright 是一个运行浏览器窗口的强大工具，它可以做到他们所说的
headless, which means you don't even see the browser windows, just like running behind the scenes 无头，这意味着你甚至看不到浏览器窗口，就像在幕后运行一样
or not headless headful in which case you see the browser screen yourself and you can interact with 或者不是无头有头，在这种情况下，您自己可以看到浏览器屏幕，并且可以与
it. 它。
So that is playwright. 所以这就是剧作家。
You may already know it. 你可能已经知道了。
A lot of people use playwright. 很多人都用剧作家。
This is how you install it. 这就是您安装它的方式。
You type playwright install to do it on on Windows and Mac OS or on Linux. 您可以在 Windows 和 Mac OS 或 Linux 上键入 playwright install 来执行此操作。
It's this longer command and it will then be installed. 这是一个较长的命令，然后将被安装。
And if you have problems with that, then let me know. 如果您对此有疑问，请告诉我。
But hopefully not. 但希望不是。
Okay, one other thing to mention. 好吧，还有一件事要提。
One other little detail here. 这里还有一个小细节。
And this is just for running it in a notebook. 这只是为了在笔记本上运行它。
Um, one of the problems, one of the challenges with async IO is that Asyncio runs an event loop. 嗯，问题之一，异步 IO 的挑战之一是 Asyncio 运行事件循环。
Um, and when you when it runs an event loop, it runs this thing that's just constantly making sure 嗯，当你运行一个事件循环时，它会运行这个不断确保
that it's running anything that's being awaited. 它正在运行任何正在等待的东西。
And then when it's holding on IO, it runs something else that's being awaited. 然后当它持有 IO 时，它会运行其他正在等待的东西。
Uh, and one of the problems is that that async IO only supports one event loop. 呃，问题之一是异步 IO 仅支持一个事件循环。
And if there's an event loop running, you can't within that event loop, run another event loop. 如果正在运行一个事件循环，则您无法在该事件循环内运行另一个事件循环。
And we're running an event loop as part of running, uh, this notebook right now. 我们正在运行一个事件循环，作为运行这个笔记本的一部分。
And so that can cause problems when you try and kick off async processes within async processes. 因此，当您尝试在异步进程中启动异步进程时，这可能会导致问题。
Uh, and so there is this package called nest async IO that's quite popular, which you can just simply 呃，所以有一个名为 Nest async IO 的软件包非常流行，您可以简单地使用它
use this and then it like patches async IO so that you can have an event loop within an event loop. 使用它，然后像修补异步 IO 一样使用它，以便您可以在事件循环中拥有事件循环。
And as you will soon understand from me prattling away, we're going to want that because we're going 正如你很快就会从我的喋喋不休中了解到的那样，我们会想要这样，因为我们要
to want to run playwright asynchronously, because we're going to build an agent that can drive playwright. 想要异步运行 playwright，因为我们将构建一个可以驱动 playwright 的代理。
And so we're going to need that concept of an event loop within an event loop. 因此，我们需要事件循环中的事件循环这一概念。
But when we later put this into Python code, we actually won't need this anymore. 但是当我们稍后将其放入Python代码中时，我们实际上不再需要它了。
But we'll need it for now. 但我们现在需要它。
All right. 好的。
That's a long sidebar. 这是一个很长的侧边栏。
That's over. 就这样结束了。
But now comes the magic. 但现在魔法来了。
So one of the incredible things about Landgraf and Long Chain, I'm becoming a convert of both, is 因此，Landgraf 和 Long Chain 令人难以置信的事情之一是，我正在成为两者的皈依者。
that they come with so many great tools out of the box. 他们配备了许多开箱即用的出色工具。
Many of them are in the community package. 其中许多都包含在社区包中。
There's actually a couple of different ways that you can run a playwright. 实际上，管理剧作家有几种不同的方式。
There's two sets of tools. 有两套工具。
One of them is a more simplistic one that's just a bit higher level. 其中一个是更简单的，只是级别更高一点。
This one that I've got here, uh, the Playwright Browser Toolkit. 我这里有一个，呃，剧作家浏览器工具包。
This is a lower level set of tools which provides a bunch of different tools. 这是一组较低级别的工具，提供了许多不同的工具。
Let's just We're gonna create this. 让我们来创建这个。
So this is this is, um, creating an asynchronous playwright browser, and then it's building a toolkit 所以这就是，嗯，创建一个异步剧作家浏览器，然后构建一个工具包
from that browser. 从该浏览器。
And now we've, we've got the tools into a variable tools. 现在我们已经将这些工具变成了可变工具。
So I'm just going to print these. 所以我要把这些打印出来。
And here are all of the tools that we get in this package. 这是我们在这个包中获得的所有工具。
We get something that lets you uh, click on an element in a web page, navigate the browser to a particular 我们得到了一些东西，可以让你呃，点击网页中的一个元素，将浏览器导航到特定的
web page, go to the previous web page like press the back button, extract text from a web page, extract 网页，转到上一个网页，例如按后退按钮，从网页中提取文本，提取
hyperlinks, get elements, and then the current web page. 超链接，获取元素，然后是当前网页。
Uh, so it gives you quite granular control over what's going on in this playwright browser. 呃，所以它可以让您非常精细地控制这个剧作家浏览器中发生的事情。
So again, to recap, playwright allows you to launch a browser window. 再次回顾一下，剧作家允许您启动浏览器窗口。
And then this Landgraaf or Lang chain set of tools gives us a series of tools that will allow us to 然后这套 Landgraaf 或 Lang 链工具为我们提供了一系列工具，使我们能够
interact with that browser open windows, navigate, read the text, read the elements, do that kind 与该浏览器交互打开窗口、导航、阅读文本、阅读元素等
of thing. 的东西。
That's pretty cool. 太酷了。
And that is something we're going to be able to arm our agent to be able to use. 这就是我们将能够武装我们的代理来使用的东西。