Pressing on. 继续压下去。
So what we're now going to do is call this. 所以我们现在要做的就是调用它。
It looks like I'm going to need to import async IO there. 看来我需要在那里导入异步 IO。
Hang on. 不挂断。
Let's do that. 让我们这样做吧。
Missed an import at the start. 一开始就错过了导入。
Actually let's do this properly. 实际上让我们正确地做到这一点。
I'm going to take this out just so that it's nice and clean for you. 我要把这个拿出来，这样对你来说又漂亮又干净。
I'm going to put that async import right up at the top there and rerun that cell. 我将把异步导入放在顶部并重新运行该单元格。
I like to do my imports at the top. 我喜欢在顶部进行导入。
I know people have different views on this stuff. 我知道人们对这件事有不同的看法。
Okay, so we are now going to say we want to write a cold sales email. 好的，我们现在要说的是，我们想写一封冷冰冰的销售电子邮件。
That's going to be our instruction. 这将是我们的指示。
And what we're going to do now is we're going to call this async IO. 我们现在要做的就是调用异步 IO。
Do you remember this? 你还记得这个吗？
I showed this to you back when we had the async briefing, that this is where you start to see the power 当我们进行异步简报时，我向您展示了这一点，这就是您开始看到力量的地方
of async IO. 异步IO。
We're going to be running three different runs at the same time. 我们将同时运行三个不同的运行。
And of course again it's not multithreading. 当然，这也不是多线程。
It's not like the CPU is actually time slicing between them in some ways. CPU实际上并没有以某种方式在它们之间进行时间切片。
But but rather it's going to be using an event loop, which will run each one, and whenever it's pausing 但相反，它将使用一个事件循环，它将运行每个循环，并且每当它暂停时
waiting on I o it will let another one run. 等待我 o 它会让另一个运行。
And because most of what these things are doing is pausing on I o that will allow all three of them 因为这些东西正在做的大部分事情都在 I o 上暂停，这将允许它们全部三个
to sort of alternate and be talking to to an LLM to open AI in parallel, and then we will collect back 有点交替并与法学硕士交谈以并行开放人工智能，然后我们将收集回来
the results. 结果。
What comes back from this await gather is a collection of results. 从这个等待收集返回的是结果的集合。
And we will call final output on each one and print it. 我们将调用每一个的最终输出并打印它。
So we will let that run. 所以我们会让它运行。
And you can see that I've wrapped all of this in a trace, which means that we should see all of this 你可以看到我已经将所有这些都封装在一个跟踪中，这意味着我们应该看到所有这些
in one trace. 一丝一毫。
We will do in a little bit, but no surprise. 我们稍后会做，但并不奇怪。
Hopefully what you'll see down here is I have to click here to get a scrollable element, and you'll 希望您在这里看到的是我必须单击此处才能获取可滚动元素，然后您将
see that we can scroll through and read a bunch of emails. 看到我们可以滚动浏览并阅读一堆电子邮件。
And the third one, of course, is very concise because we asked our third email writer to be concise. 当然，第三封电子邮件非常简洁，因为我们要求第三位电子邮件撰写者保持简洁。
Okay, so so far all we've really done is multiple calls to LMS. 好的，到目前为止我们所做的只是多次调用 LMS。
And now the final piece of the puzzle. 现在是拼图的最后一块了。
This is just a simple workflow of calling LMS. 这只是调用LMS的一个简单的工作流程。
See if you can remember which one of the patterns this is, but it's a sort of variety of one of them. 看看你是否能记住这是哪一种模式，但它是其中一种模式的变体。
And we are going to create a new agent called sales picker. 我们将创建一个名为 sales picker 的新代理。
And sales picker picks the best cold sales email from the given options. 销售选择器从给定的选项中挑选最好的冷销售电子邮件。
Imagine you're a customer. 想象一下您是一位客户。
Pick the one you're most likely to respond to. 选择您最有可能做出回应的一个。
Don't give an explanation. 不给解释。
Reply with the email you select only. 仅回复您选择的电子邮件。
It's a classic kind of prompting. 这是一种经典的提示。
You know that you often end with the constraint. 你知道你常常以约束结束。
With any limitation is a good way to end a system prompt. 任何限制都是结束系统提示的好方法。
All right. 好的。
So that's the message the user prompt writer called sales email. 这就是用户提示作者称为销售电子邮件的消息。
We again we have this same construct. 我们再次拥有相同的构造。
We're going to run three agents in parallel to craft three messages. 我们将并行运行三个代理来制作三个消息。
We're going to gather the outputs and then we just simply call another agent. 我们将收集输出，然后只需调用另一个代理即可。
So this is just Python code step by step. 所以这只是一步一步的Python 代码。
Call three agents in parallel. 并行呼叫三个代理。
Take the output. 获取输出。
Call another agent. 致电另一位代理。
It's just a Python script that runs these things in order, and it will then print the best email at 它只是一个按顺序运行这些事情的 Python 脚本，然后它会打印出最好的电子邮件：
the end of it. 结束了。
And because we've got the whole thing under one trace, we hope to see all of this in a single trace. 因为我们已经将所有内容都放在一条跟踪中，所以我们希望在一条跟踪中看到所有这些。
So this is probably going to take I think like 30s in total. 所以我认为这可能总共需要 30 秒。
So I'll have to keep the sentence running if we want to see this live. 因此，如果我们想看到这一点，我就必须继续说下去。
And at the end of it we'll be able to go into the trace is run. 最后我们将能够进入跟踪运行情况。
So here is a single email that's been returned. 这是一封已返回的电子邮件。
And it is apparently the best one. 这显然是最好的。
But let's now go and have a look at the trace to see if we believe it. 但现在让我们去看看痕迹，看看我们是否相信它。
Okay. 好的。
So this was our email. 这就是我们的电子邮件。
Now this is a link to go to see the traces in OpenAI. 现在这是一个链接，可以查看 OpenAI 中的痕迹。
Here it comes. 它来了。
So at the top trace is selection from salespeople. 因此，最上面的痕迹是销售人员的选择。
Let's go and have a look into this trace. 让我们去看看这个痕迹。
What you'll see is that, sure enough, it called the professional sales agent, and you can read the 你会看到，果然，它打电话给专业的销售代理，你可以阅读
actual prompts that went in it called the engaging sales agent. 其中的实际提示称为参与销售代理。
It called the Busy sales agent, and then it called the sales picker. 它呼叫忙碌的销售代理，然后呼叫销售选择器。
And you can go through this in the trace and see what's going on. 您可以在跟踪中查看这一点，看看发生了什么。
So it's worth pointing out that we've really not done anything very magical so far. 因此值得指出的是，到目前为止我们还没有做任何非常神奇的事情。
It's nice. 很好。
It's elegant that we've had these wrappers, these agent constructs around things, but they're very 我们拥有这些包装器，这些代理围绕事物构建，这很优雅，但它们非常
lightweight wrappers. 轻质包装纸。
We've essentially simply called a total of four LMS. 我们本质上只是简单地调用了总共四个 LMS。
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 以选择其首选的电子邮件。
And it's sort of elegant that you can go into the traces and see what's going on. 你可以进入痕迹并看看发生了什么，这有点优雅。
But now it's time to get a bit more agentic and start talking about tools. 但现在是时候变得更加主动并开始谈论工具了。
So as we get into tools, let me remind you, have a think back to what we did in week one, when we 因此，当我们进入工具时，让我提醒您，回想一下我们在第一周所做的事情，当我们
had to build some boilerplate JSON to describe a function that we wanted to use as like a tool. 必须构建一些样板 JSON 来描述我们想要像工具一样使用的函数。
It's quite chunky JSON that described the parameters and various other things about it. 它是相当厚重的 JSON，描述了参数和相关的各种其他内容。
And then we had to write a function called handle tool calls, which is the one that had the the hokey 然后我们必须编写一个名为“处理工具调用”的函数，该函数具有做作的功能
if statement that I then tried to write into something a bit more fancy, but which was still a fair 然后我尝试将 if 语句写成更奇特的东西，但这仍然是一个公平的
amount of sort of gunk, to use a technical word. 用专业术语来说，就是大量的垃圾。
And what we're now going to see is how that whole stuff can be, can be super simplified without taking 我们现在要看到的是，整个东西如何可以超级简化，而无需采取任何措施
any flexibility away from us. 任何灵活性都离我们而去。
So first of all, we're just going to recap. 首先，我们要回顾一下。
We've got these three sales agents the professional, the engaging and the busy ones. 我们拥有这三位销售代理，他们专业、敬业且忙碌。
And there they are. 他们就在那里。
And let me just look at one of these sales agents. 让我看看其中一位销售代理。
So if I look into it you can see that it's got a name. 所以如果我看一下它你就会发现它有一个名字。
It's got the instructions. 它有说明。
And you can see that it has things like tool choice tools, and it has like a list of tools that it 你可以看到它有工具选择工具之类的东西，它有一个工具列表
has access to, which right now is empty. 可以访问，但现在是空的。
So just to give you a sense of what's going on under the covers, it's perfectly simple. 因此，为了让您了解幕后发生的事情，这非常简单。
But these are the constructs we're working with. 但这些是我们正在研究的结构。
So what we're now going to do is have a tool. 所以我们现在要做的就是拥有一个工具。
So this is a function send email. 所以这是一个发送电子邮件的函数。
It takes an email body which is a string. 它需要一个电子邮件正文，它是一个字符串。
And it has a like a doc string. 它有一个类似文档字符串。
Send out an email with the given body to all sales prospects. 向所有潜在销售人员发送一封包含指定正文的电子邮件。
Now what I've got in here is the from email. 现在我收到的是来自电子邮件的信息。
And this email needs to be what's called the verified sender, the email address that you've set up 此电子邮件必须是所谓的已验证发件人，即您设置的电子邮件地址
in SendGrid that you're allowed to send from. 在允许您发送的 SendGrid 中。
Otherwise it won't actually send. 否则实际上不会发送。
So you'll need to update this and then two email. 因此，您需要更新这封电子邮件，然后更新两封电子邮件。
You should put that to be an email where you don't mind it receiving an email. 您应该将其设置为您不介意接收电子邮件的电子邮件。
I would prefer that you change it from my Gmail here. 我希望您可以在此处从我的 Gmail 更改它。
Otherwise I will get flooded with emails from people doing this. 否则我会收到大量来自这样做的人的电子邮件。
So maybe I'll change it before I commit this to GitHub. 所以也许我会在将其提交到 GitHub 之前更改它。
But yes, send that to another of your email addresses. 但是，可以，将其发送到您的另一个电子邮件地址。
Or you could probably just send it to yourself. 或者您也可以将其发送给自己。
I'm not sure, but send it to somewhere where you don't mind receiving cold sales emails, there'll 我不确定，但是将其发送到您不介意收到冷销售电子邮件的地方，就会有
only be 1 or 2. 只能是1或2。
We're not going to send a mass of them. 我们不会派出大量的人员。
And then this is Sendgrid's API. 这就是Sendgrid 的API。
It's perfectly simple. 这非常简单。
It's SendGrid. 这是发送网格。
And you give it a body so you can look through this. 你给它一个实体，这样你就可以看透它。
But it's honestly it's just a boilerplate to send an email to a recipient and we respond with success. 但老实说，这只是向收件人发送电子邮件的样板，我们会成功回复。
So this is very much like the tools that we wrote last time. 所以这非常像我们上次编写的工具。
It's like a function to do it. 这就像一个函数来做到这一点。
And if you remember, the next step was to write a ton of JSON to describe this. 如果您还记得的话，下一步就是编写大量 JSON 来描述这一点。
But all we need to do with OpenAI is put one of these decorators above it at function tool. 但我们需要对 OpenAI 做的就是将这些装饰器之一放在函数工具的上方。
If you're not sure how decorators work, again, that's in the guides, or just ask ChatGPT to explain 如果您不确定装饰器如何工作，请再次参阅指南，或者只是询问 ChatGPT 来解释
it. 它。
But that allows OpenAI to write some code to sort of do something with this function. 但这允许 OpenAI 编写一些代码来使用此函数执行某些操作。
And but all we need to care about is we simply put that decorator above the function that we want to 但我们需要关心的是我们只需将该装饰器放在我们想要的函数之上
treat as a tool. 当作工具来对待。
And so we will just simply define that function doesn't look like we've done anything, but let's look 因此，我们只是简单地定义该函数，看起来我们什么也没做，但让我们看看
at this thing called send email. 在这个叫做发送电子邮件的事情上。
Now we think it's a function, right? 现在我们认为它是一个函数，对吗？
But no, it's not a function because we have this decorator. 但不，它不是一个函数，因为我们有这个装饰器。
It's been converted into something called a function tool. 它已被转换成一种称为功能工具的东西。
It has a name send email. 它有一个名称发送电子邮件。
It has a description. 它有一个描述。
And that description is taken from the docstring comment we had right here. 该描述取自我们此处的文档字符串注释。
Look at that. 看看那个。
It's just turned that into a tool description. 它只是将其变成了工具描述。
And then and this is the great stuff params JSON schema. 然后，这就是 params JSON 模式的重要内容。
This stuff is all of the boilerplate JSON that we had to write last time. 这些东西是我们上次必须编写的所有样板 JSON。
It's just done it for us because it's read this and it's figured out what's needed. 它只是为我们完成了这件事，因为它读了这篇文章并找出了我们需要什么。
And and that's basically it. 基本上就是这样。
So just by simply adding that decorator function tool, all of the work of faffing around with these 因此，只需添加装饰器功能工具，所有与这些相关的工作就完成了
JSON objects has been taken away from us, which is great. JSON 对象已经从我们身边消失了，这很棒。
That's what a good framework should do. 这就是一个好的框架应该做的事情。
Take out the boilerplate but leave us in full control. 去掉样板，但让我们完全控制。