And I've come into Ladysmith one more time just to show you. 我再次来到莱迪史密斯只是为了向您展示。
I think I've read from the wrong place that the final output from GPT was right down here. 我想我从错误的地方读到 GPT 的最终输出就在这里。
I have sent you a push notification with the current USD GP exchange rate. 我已向您发送了包含当前美元 GP 汇率的推送通知。
So that's where you saw the end of the whole of the trace right down at the bottom there. 这就是您在底部看到整个迹线的末端的地方。
Okay, so here we are back in this chat. 好的，我们回到本次聊天。
And now let me just show you something. 现在让我向您展示一些东西。
Despite its incredible intelligence with this conversation, what we can now say is, uh, my name's 尽管这次对话具有令人难以置信的智慧，但我们现在可以说的是，呃，我的名字
Ed. 埃德。
Uh, nice to meet you, Ed. 呃，很高兴认识你，艾德。
How can I assist you today? 今天我能为您提供什么帮助？
And I can say, what's my name? 我可以说，我叫什么名字？
And it says I don't have access to your personal information. 它说我无权访问您的个人信息。
Uh, so I use this as a way of showing you that, uh, despite the fact that we have all of this state 呃，所以我用这个来向你展示，呃，尽管我们拥有所有这些状态
management, despite the fact that we've we've built up this, this, um, these reducers and this clever 管理，尽管事实上我们已经建立了这个，这个，嗯，这些减速器和这个聪明的
structure, it doesn't have any memory. 结构，它没有任何记忆。
It doesn't have the ability to remember between the different conversations. 它没有能力记住不同的对话。
And you might be thinking, well, I guess you're not thinking because I explained it already, but 你可能会想，好吧，我猜你没有在想，因为我已经解释过了，但是
but if I hadn't explained it, you might be thinking. 但如果我没有解释的话，你可能会想。
But but hang on. 但是，坚持住。
Uh, why? 呃，为什么？
Uh, we've got all these reducers. 呃，我们有所有这些减速器。
We've got all of this stuff to handle state and to add in state. 我们已经拥有所有这些东西来处理状态并添加状态。
Then why, why isn't it, why isn't it just naturally remembering what's happening? 那为什么，为什么不是，为什么它不能自然地记住正在发生的事情呢？
And yes, it's all down to super steps. 是的，这一切都取决于超级步骤。
The point is that every invocation, every time we call this graph, it's like a separate fresh invocation 关键是每次调用，每次我们调用这个图，它就像一个单独的新鲜调用
and state is managed and maintained within any one invocation. 并且状态是在任何一次调用中管理和维护的。
That's what that's what it's there for. 这就是它存在的目的。
It's to handle so that you could have multiple nodes running in parallel. 它的作用是让多个节点并行运行。
You could have all sorts of stuff happening, and the state would be managed through the whole graph 你可能会发生各种各样的事情，并且状态将通过整个图表进行管理
in a, in a reproducible way. 以一种可重复的方式。
That's the power of the state management part. 这就是状态管理部分的权力。
But that doesn't help you between separate super steps. 但这对您在单独的超级步骤之间没有帮助。
Each super step is a different invocation of the graph. 每个超级步骤都是对图的不同调用。
And the way that you do this is you use checkpointing. 执行此操作的方法是使用检查点。
That's how you add memory. 这就是添加内存的方法。
Well, I have to tell you, I have some misgivings about Landgraaf from time to time. 好吧，我必须告诉你，我有时对兰德格拉夫有些疑虑。
How heavyweight it can be on occasion with some of the things we have to learn. 有时我们必须学习的一些东西是多么重要。
But this is one case where I am very impressed indeed, and it's a moment for me when I get it. 但这确实是一个让我印象非常深刻的案例，当我明白这一点时，这对我来说是一个时刻。
I realise why people like this so much and I can really appreciate the power of it. 我明白为什么人们如此喜欢这个，我真的很欣赏它的力量。
Checkpointing is very elegant, very simple and it leads to robust, repeatable processes. 检查点非常优雅、非常简单，并且可以带来稳健、可重复的流程。
And you will see that too. 你也会看到这一点。
And I imagine you'll be impressed like me at the end of it. 我想你最终会像我一样印象深刻。
So we begin by creating a new object called memory saver. 因此，我们首先创建一个名为内存保护程序的新对象。
And a memory saver doesn't mean like a saving memories. 内存保护程序并不意味着保存内存。
It's talking about saving to to to in-memory stores, to in-memory, rather than to disk or to to a 它谈论的是保存到内存中的存储，保存到内存中，而不是保存到磁盘或保存到
database. 数据库。
It's a bit confusing. 这有点令人困惑。
So that's what Memory Saver means then. 这就是 Memory Saver 的含义。
This is the same code we had before. 这与我们之前的代码相同。
Exactly the same code. 完全相同的代码。
I put in a print statement so we can see what it's doing and otherwise. 我放入了打印语句，以便我们可以看到它在做什么以及其他情况。
The only change is when we compile the graph, we pass in check pointer equals memory. 唯一的变化是当我们编译图时，我们传入检查指针等于内存。
We're passing in that memory object. 我们正在传递该内存对象。
But there's our graph. 但这是我们的图表。
It looks identical exactly the same. 它看起来一模一样，一模一样。
And now this is where we actually run the code. 现在这是我们实际运行代码的地方。
There's a little bit of stuff here which is a bit hacky a bit hokey, but but the the idea is you have 这里有一些东西有点老套，有点做作，但你的想法是
to create this object called config. 创建这个名为 config 的对象。
It's a dictionary with one field configurable, and then that field you have to put in a thread ID and 它是一本字典，其中一个字段是可配置的，然后您必须在该字段中放入线程 ID 并
thread ID doesn't mean like a technical thread, it's meant to be like a conversation thread, like 线程 ID 并不意味着像技术线程，它意味着像对话线程，例如
it's something that refers to this, this thread of memories that needs to be connected together. 它指的是这一点，这条需要连接在一起的记忆线。
And so that's how you specify that, that this is this particular grouping in memory. 这就是您指定的方式，这是内存中的特定分组。
And then when you invoke the graph you have to pass in that config. 然后，当您调用图表时，您必须传入该配置。
That's how you make sure that when you're invoking the graph, it's being associated with the right 这就是如何确保当您调用图表时，它与正确的关联
sort of slot in memory. 内存中的某种插槽。
And that is all there is to it. 这就是全部内容。
So with that, let's bring this up and we say hi there. 那么，让我们提出这个问题并打个招呼。
Hello. 你好。
How can I assist you today? 今天我能为您提供什么帮助？
My name is Ed. 我的名字是艾德。
Nice to meet you, Ed. 很高兴认识你，艾德。
How can I help you? 我怎么帮你？
What's my name? 我叫什么名字？
I think it's gonna get it. 我想它会得到它。
Your name is Ed. 你的名字是艾德。
How can I help you further? 我该如何进一步帮助您？
Ha, ha. 哈，哈。
And no surprise, you can see down here the print statement that I mentioned is printing out the the, 毫不奇怪，您可以在这里看到我提到的打印语句正在打印，
uh, the inputs. 呃，输入。
And we're getting the full history each time, and that is all there is to it. 我们每次都会获得完整的历史记录，这就是全部。
That is checkpointing in action, maintaining memory between each of the calls, each of the super steps. 这就是实际的检查点，在每个调用、每个超级步骤之间维护内存。
Now, I know what you're thinking. 现在，我知道你在想什么。
You're thinking, okay, what's the big deal? 你在想，好吧，有什么大不了的？
Why are you so impressed by this? 为什么你对此印象如此深刻？
I mean, it's just like you could also get there just by storing that list of disks. 我的意思是，就像您也可以通过存储该磁盘列表来到达那里一样。
Or we could take it from Gradio UI here and put it in a global link and keep playing it in. 或者我们可以从此处的 Gradio UI 中获取它并将其放入全局链接中并继续播放。
Well, look, look at some of this stuff. 好吧，看看，看看其中的一些东西。
So you can call graph the compile graph paragraph. 所以你可以将graph称为编译图段。
Getstate. 获取状态。
Given that the the config and we get back this thing called a state snapshot, and this has in it the 考虑到配置，我们得到了一个称为状态快照的东西，其中包含
messages and then the complete history the conversation so far. 消息，然后是迄今为止对话的完整历史记录。
Yeah. 是的。
All right. 好的。
So so it's like a, like a global that that has this in it. 所以它就像一个全局变量，里面有这个。
But there's more you can get get state history for our config. 但您还可以获取更多配置的状态历史记录。
And what we get now is each step in time, every super step, every time we invoke the graph, the complete, 我们现在得到的是时间上的每一步，每一个超级步骤，每次我们调用图表时，完整的，
uh, snapshot at that moment, starting from most recent at the top and then going back in time. 呃，那一刻的快照，从顶部最近的开始，然后回到过去。
And this is where it gets cool. 这就是它变得很酷的地方。
And it's not like it's super sophisticated, but it's definitely a cool construct. 它并不是超级复杂，但它绝对是一个很酷的结构。
Langshan allows you to step back in time to any prior moment. 狼山可以让你回到过去的任何时刻。
When you're passing in that config, the configurable thread ID you can pass in a checkpoint ID to kind 当您传递该配置时，您可以传递检查点 ID 来配置可配置的线程 ID
of rewind to a previous moment, and then replay that through the graph. 快退到前一时刻，然后通过图表重播该时刻。
Uh, and this, this gives you this ability to basically do what they call a time travel. 呃，这，这给了你基本上做他们所谓的时间旅行的能力。
That's the Landgraf official name for it, which is really to be able to move back, get your snapshot 这是Landgraf的官方名称，真正的意思是能够向后移动，获取快照
at any point in time and be able to rerun it from there. 在任何时间点并能够从那里重新运行它。
And this is this is really great because it allows you to build systems that are repeatable and robust. 这真的很棒，因为它允许您构建可重复且稳健的系统。
If something falls over, you can restart it from any snapshot, any point in time. 如果出现故障，您可以从任何快照、任何时间点重新启动它。
And you've got this kind of full tracking on everything that happened. 并且您可以对所发生的一切进行全面跟踪。
So yeah, it's it's it's simple but it's elegant. 是的，它很简单，但很优雅。
And this is a case of, of an abstraction that really makes sense to me. 这是一个对我来说真正有意义的抽象案例。
Uh, and is definitely something that I think is very valuable. 呃，而且绝对是我认为非常有价值的东西。
And I just want to show you as well that this has got nothing to do with, with gradio and with kind 我只是想告诉你，这与 gradio 和 kind 无关
of variables. 变量。
I can come back in and I can I can just relaunch my Gradio UI right here and I can say like, hi there. 我可以回来，我可以，我可以在这里重新启动我的 Gradio UI，我可以说，你好。
It says hi again, and I was going to say, what's my name? 它又打招呼了，我正想说，我叫什么名字？
But I don't need to. 但我不需要。
You can see right away it's got the memory. 你可以立即看到它有记忆。
It's still got that memory. 它仍然保留着那段记忆。
It's got nothing to do with the the information stored in radio's chat UI, which is what we've always 这与我们一直以来保存在电台聊天 UI 中的信息无关
used in the past with, with gradio, but rather it is the memory, the checkpointing that's happening 过去与 gradio 一起使用，而是内存，正在发生的检查点
inside this, uh, this memory object. 在这个，呃，这个内存对象里面。
And then I can actually I can come back and if I recreate, I can I can create a fresh new memory saver 然后我实际上可以回来，如果我重新创建，我可以我可以创建一个全新的内存保护程序
object and come in and then I have to re rebuild my graph with, with, uh, the new memory right there 对象并进来，然后我必须用那里的新内存重新重建我的图表
and then re bring up my chat interface. 然后重新调出我的聊天界面。
And now if I say uh hi there. 现在如果我在那里打个招呼。
And what's my name. 我叫什么名字。
It's obviously not going to know it. 显然它不会知道。
So that just explains that by recreating a new memory object we've reset everything. 所以这只是解释了通过重新创建一个新的内存对象我们重置了一切。
And that's, that gives you a good sense of what's going on. 也就是说，这可以让您很好地了解正在发生的事情。
My name's Ed. 我叫艾德。
Nice to meet you. 很高兴见到你。
How can I assist you today? 今天我能为您提供什么帮助？
Uh, what's my name? 呃，我叫什么名字？
Just to prove the point, your name is Ed. 为了证明这一点，你的名字叫艾德。
And then let me just show one more thing here. 然后让我在这里再展示一件事。
We can also change the thread ID to two. 我们还可以将线程ID更改为2。
Let's rerun this and, uh, take a look here. 让我们重新运行一下，呃，看看这里。
Say hi there. 在那里打个招呼。
Hello. 你好。
How can I assist you? 我该如何帮助您？
What's my name? 我叫什么名字？
And it says it doesn't know because the thread is two. 它说它不知道，因为线程是两个。
If we now go back to the thread is one. 如果我们现在回到线程就是其中之一。
I know you get this, but it's worth saying. 我知道你明白这一点，但值得一说。
And now. 现在。
Hi there. 你好呀。
Hello again. 又好。
Ha ha. 哈哈。
So there. 就这样。
You see it? 你看到了吗？
It's a nice, elegant. 这是一个很好的，优雅的。
It's it's relatively lightweight and simple, but very powerful. 它相对轻量且简单，但功能非常强大。
And that's a nice combination that I can get behind. 这是一个很好的组合，我可以支持。
And you can come in and look of course at the different checkpoints for either thread number one or 当然，您可以进来查看线程一或线程的不同检查点
thread number two. 第二个线程。
Uh, using the same this, this same structure. 呃，使用同样的这个，同样的结构。