Bee Agent Framework: Build AI Agents Fast π₯ β
Other VideosAgingπ
2024-12-09
Build Process β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BUILD CHATBOT WORKFLOW β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β PLANNING β
β ββββββββ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Define βββββΊβ Choose βββββΊβ Setup β β
β β Scope β β Stack β β Project β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β
β βΌ β
β DEVELOPMENT β
β βββββββββββ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Build βββββΊβ Add AI βββββΊβ Test & β β
β β Features β β Logic β β Debug β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β
β βΌ β
β DEPLOYMENT β
β ββββββββββ β
β βββββββββββββββ βββββββββββββββ β
β β Deploy βββββΊβ Chatbot β βββ LIVE! β
β β to Cloud β β Running β β
β βββββββββββββββ βββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββKey Components β
- Project architecture
- Core features implementation
- Best practices
Transcript β
[00:00] Today, we're having a look at an exciting new open source framework for creating scalable agentic applications. The B Agent framework was developed by IBM Research and offers a simple, type-safe approach to building performant and scalable agentic solutions. In this complete tutorial, you will learn the basics of using the B Agent framework, from building a simple chatbot using pretty much any AllaalM provider to an advanced AI agent with access to several tools. And
[00:32] as an added bonus, I will show you how to add your agent to a Next.js application where you can have a conversation with your tool agent, and this will also show you the individual steps and reasoning by the agent. Before we get started, I do want to mention that you can download all the source code from this video by visiting this GitHub repo. You will find the link in the description of this video. In terms of prerequisites, I do recommend some JavaScript experience. By the end of this video, we will move our code to TypeScript when
[01:03] we add our solution to Next.js. To get started, open up a new folder in your code editor. Then open up your terminal and instantiate a new node environment by calling npm init y. This will create a package.json file, and I'm actually going to add one more command just below main called type and module. Let's save this change and close this file. Now back in the terminal, let's also install the B Agent framework. Of course, you can use npm or yarn or bun or whatever you
[01:36] prefer, but I'm going to use pnpm install b agent framework. I'm also going to install .env, which will allow us to use environment variables. And let's press enter. Right now in our project folder, let's create a new file and let's call it listen-01.js. Let's start by adding an LLM to our application. So at the top of the file, let's enter import something from B Agent framework slash
[02:06] adapters. And within adapters, we can see all sorts of LLM providers. In order for you to be able to follow along, we will be using Grok, which is a fantastic service. Or if you want to run all of this locally, you can definitely use Olama as well. So I'll select Grok. And within Grok, we want to access the chat models. And what we want to import is the grok chat LLM class. In order to use this class, we'll create a new variable called LLM, which is
[02:38] equal to a new instance of the grok chat LLM class. This class takes in an object as input, and the property that we need to specify is the model ID. Here we can give the name of the exact model that we'd like to use. So we can see all the supported models offered by Grok by going to this page. And I think for this demo, we can use the LLM 3.2 3 billion parameter model. So let's paste that into this field. Now in order to use Grok, we do need to provide
[03:09] an API key as well. And there's no way to pass it into the class directly. Instead, we will use environment variables. And this is ideally what you want to do in a production system as well, as you don't want to hardcode these type of keys in the code itself. So in the root of the project, let's create a new file called .env. And in this file, let's create a new variable called grok underscore API underscore key, which is equal to. And now we need to get this API key. And we can
[03:40] get that by going to grok.com, then click on dev console and after signing in, you can go to API keys, then click on create API key. And let's call it something like be agent framework. Let's submit this, then let's copy the key. And I will delete this key after this recording. So please use your own. And let's add it to the environment variable file. Great, now that Grok has been set up, we should be able to interact with this LLM to send a message
[04:10] to an LLM. All we have to do is call LLM dot generate. Generate takes in an array of messages, like the user message, the assistant message or the system message. Each of these messages are an object with at least two properties, a role like user and text, which can be anything like hello. Now, of course, we could pass in the messages like this, but this is not type safe and definitely not the best approach within the be agent framework. So
[04:42] what we can do instead is import something from the be agent framework. So let's import from be agent framework, then LLMs within LLMs, we can go to primitives and message. And now from this package, we can import the base message class as well as the roles. And this role object actually gives us access to the available roles like assistant, system and user. Now how do we use this? Instead of passing the message like
[05:12] this, what we can do instead is say base message dot of. And if I do an input help, we can see all the available fields like role, text and meta. Let's select role. And for the value of role, we can now use this role object that we imported earlier. And on this object, we can now access assistant, system or user. Then secondly, let's pass in the text property and with the value of hello. Now we can assign this response to
[05:42] a variable. So let's say cons response equals, and this actually returns a promise. So we do have to await the response. Finally, it's console log response. Now in the terminal, we can run node lesson one dot j s. And this gives us this error saying it can't find package grok SDK. So I did this intentionally, as I kind of want to show you how to work through this process. In order to use this grok package, we first need to install the grok SDK.
[06:13] And this is true for the other providers as well, like OpenAI, Olama, etc. So if you use the different provider than I did, simply look at the missing package, copy its name, p NPM, install, and that package name. Great. If we try running this file again, we now get this message saying that the API key is missing. And this was intentional as well, as I wanted to show you how I figured out what the name of this environment variable should be. And this message is telling us that it was expecting the variable to be called grok API
[06:44] key. Now, of course, the code can't see this key because we haven't imported it. So all we have to do is add this line at the top of the code. And everything should now be working. So let's run that file again. And this time we do get some output from our allol M. Now, we don't want to output the entire structure. Instead, we just want to text output. So on response, let's call get text content like so. Now if we run this again, we get our response back. How awesome is that? Now let's convert this into a chatbot so
[07:16] that we can pass our messages into the terminal instead of hard coding it like this. The first thing we'll do is wrap this generate logic in a function. So let's write const process message, which is equal to an async function like so. And let's move all of this code into the function, the function will receive a message as input, and we can replace this hard coding with message. Then below this, let's create another function that we can use to start this conversation. This function
[07:48] will be called start chat, which is equal to an async function. And this function will actually run in an infinite loop until the user exits the conversation. So I will just simply write while this is true, let's grab the message from somewhere. And what we want to do is grab the message from the terminal. In order to allow the user to enter values through the terminal, we will use the read line package from node. So at the top of the code, let's import read line from read line
[08:19] slash promises, then below this list enter const read line equals read line dot create interface. And this takes in an object with two values and input value, which is process dot standard in and output, which is equal to process and standard out. This object simply allows us to grab input from the terminal and write values back to the terminal. That's really all this is doing. So this
[08:50] means we can actually get the message by calling oh wait, read line dot question. And we can actually append it with something like you. Now watch what happens when we call start chat like so. And let's run this in the terminal, we can see the text you and we are able to enter any input into the terminal. And we can exit out of this by pressing Ctrl and C or command C if you're on Mac. All right, now let's continue with this logic. Now once we get the message from the user, we want to
[09:21] call await process message, and we'll pass in our message variable, like so process message is this function that we defined up here, which calls the LLM and then writes the response back to the console, we can make this look slightly better as well by adding assistant colon, and then we can just add a comment to separate out these two values. Now let's run this again in the terminal. So we get the message you let's say something like hello, how are you? And look at that, we
[09:52] now get a response back from the assistant and we can send additional messages as well. It's also allowed the user to enter the word by in order to stop the conversation. So just below cons message, let's type if message dot to lowercase is equal to by, then we'll do a few things. First, we'll console log a new message from the assistant, like goodbye, then we can close our connection with the read line object, and we can break out of this while loop.
[10:25] So if we try that again in the terminal, I can simply type by and the assistant will say goodbye. Great. Now at the moment, this assistant is returning all the text in one big chunk. But for longer messages, you might want to stream the response back instead of waiting for the entire thing to be returned. Thankfully, adding streaming to the B agent framework is really simple as well. I'm actually going to copy this file and let's rename this to lesson zero two. Now let's go ahead and add streaming to this application. With the
[10:55] in process message, let's actually remove all of this logic. And instead, let's call LLM dot stream. So instead of generate, we can call the stream method. And as with the generate method, we can pass in an array of messages. So again, I'll use base message dot of and for the role, it's called role dot user. And for the text property, let's pass in the message input that we get from over here. Now what this three method will do is return the response in
[11:27] chunks. So we can't simply assign a variable to this as that won't work. Instead, we want to call this in a loop and then output the chunks as we get them back. Now that's really simple to implement. We can call for away and we can add a bracket here. And we can also add a closing bracket towards the end here. Then before LLM stream, we can create a variable for each of these chunks. And we can simply add the word of. So this is simply saying that this loop will continue as long as we keep
[11:59] receiving chunks back from the stream. And at the end of this for statement, we can add curly braces, and then we can write our code. So first, let's try to write these chunks to the console. So I'll simply say chunk and watch what happens when we run this file. So I'll change this from 01 to 02. And let's enter something like why is the sky blue? Right. So what happened is we actually receive quite a few chunks back. Now we don't want to up with these entire objects, but we just
[12:29] want to grab the text from each of these chunks. So on chunk, we can call get text content like so let's try running this again, let's expand this window and let's run lesson two, let's enter why is the sky blue? And we should now see the response streaming back. That was incredibly quick, but we can definitely see each of these chunks being written to a new line, which isn't very user friendly. So instead of using console log, we can use process or standard out instead. So we can enter
[13:01] process standard out dot write. And within this we can pass chunk dot get text content like so I am going to add two more lines of code. So I'm actually going to copy this and we want to prefix the assistance message with the word assistant. So I'll actually just replace this with assistant. And once this output is done, we want to add a few new lines just to create some space between the assistance response and the user's output. So we'll just add backslash in backslash in like so right
[13:35] now in the terminal, let's try this again. So I'll just clear the terminal is run lesson two, let's try something very simple like hello. And let's try something with a longer response like write a poem about AI. And we should see the response streaming back, although very quickly because grok is super, super fast. If you've never used it before, then I highly recommend testing it out. But we now have a fully functional AI chatbot with response streaming. Next,
[14:05] let's create a tool agent that will show its reasoning steps and have access to custom tools and existing tools offered by the agent framework. And if you are enjoying this video, then please hit the like button and subscribe to my channel. I'm actually going to copy this file, it's pasted and let's rename this to lesson three. The first thing I'm going to do is to remove all the logic from this process message function. And I'm also going to select a different model as agents to require more advanced models to work
[14:37] properly. So I'm going to replace llama 3.2 with llama 3.1 70 billion parameter model. And if you are using open AI, then definitely use a GPT for model or greater. In order to use agents in the B agent framework, we need to import an agent class by typing import from B agent framework slash agents slash B slash agent. And what we want to import is the B
[15:07] agent class. Let's instantiate our agent just below the LLM by typing const agent, which is equal to a new instance of the B agent class and B agent text in an object as input. And we need to provide at least three of these properties. We need to supply an LLM, which we created up here. And because we named it the same, I'll just drop off LLM. We also need to provide a memory instance. And we also need to provide
[15:38] tools. Now let's have a look at memory first. When we have conversations with the agent, these conversations will be stored in memory. This is how the agent will keep track of our conversation history. So from the B agent framework, let's import. So let's go to B agent framework, let's go to memory and let's select token memory. There are different memory classes that you can select from like the summarize memory, which will effectively summarize the conversation as you continuing or
[16:09] unconstrained that's basically got no token limit, but I'm going to select a token memory class. And it's also import token memory from this package. Then let's create a new variable called memory, which is equal to the new token memory class. And this class takes in an LLM as input. So we can pass in our LLM that we defined up here. The reason this token memory class requires an LLM is because each LLM model out there has some sort of context window
[16:40] limit. And this class will automatically determine what the limit is based on the model being used and then limit the conversation history to fit inside of the context window. So if all the messages are going to exceed the context window, they will simply not be included in the conversation history. So now that we have memory defined, we just have to define tools. Let's create a new variable called tools, but I'll simply leave this as an empty array for now. Within process message, let's do the following. We can pass
[17:10] messages to an agent by calling agent dot run and run takes in an object as input with one property called prom and prompt will simply be our message. So this guy over here, run returns a promise, which we need to await. And it's assigned this response to a variable as well. So I'll create a variable called response. And to output the response from the agent, we can call console log is enter assistant. And it's also at response
[17:42] dot result dot text. Now we should be able to try this out already. So in the terminal, let's run this in three, let's type hello. And we are getting a response back from our agent. Now what's cool about agents is we can assign all sorts of tools to them. For instance, we can give our assistant the ability to search the web by assigning a duck duck go tool or the ability to find the weather based on a weather tool, or we can even build custom tools. So let's start by adding a few
[18:14] existing tools that come out of the box with the be agent framework is enter import from be agent framework is go to tools. And within tools, you'll find all sorts of tools. But what we're interested in is the search tool. And within search, we can use the duck duck go search tool, which we simply need to import from this package that I'm also going to import another tool so that we can get the weather and that we can get from be agent framework tools. And
[18:44] we can go to this weather package and open meteor. And from this we want to import the open meteor tool. In order to give our agent access to these tools, we can simply add these values to our tools array by calling new duck duck go search tool like so. And it's also called new open meteor tool like so. Now we should be able to ask our agent questions about the weather like what is the latest weather in New York is talking about a second or two to complete and we got this
[19:15] response back. Now of course, simply looking at this response, there's no way of knowing whether or not the agent actually used the tool. But thankfully with the be agent framework, we can output the reasoning process as well. Let's actually do that now. So in our code, let's go to process message. And after this run method, we can append another method called observe. And this observe method actually gives us a callback function. And this callback function gives us access to an emitter object. And
[19:48] we can use this emitter object to see what exactly is happening behind the scenes with our agent. For instance, we can watch for certain events and then do something with the output of that event. For example, we can call emitter dot on. And now we can tell it which event we want to look out for all simply pass in the updated event. But of course, if you do a search help here, you can see all the different options. And this error event could be very useful as well. I'm interested in the update event. So whenever anything happens, I actually
[20:19] want to output this to the console as well. The second property here is actually a callback function. And this callback gives us access to three different objects, data, update, and meta. I'm not going to do anything crazy here, I simply want to update the contents of this update object, I'm going to prefix this with agent and we can output update dot key, then colon. And it's also output update dot value.
[20:50] Now this is actually going to make a big difference when we execute this logic, it simply type Hello. And now you can see the agents thought and some of the agents reasoning here, as well as the final answer. Now let's try using one of those tools like what is the weather in New York. And this gives us way more useful information. Now we can see the thought saying that the agent needs to use a tool to retrieve this information, and then decided to use the open Meteor tool, we can also see the tools input,
[21:21] as well as the tool output. And then finally, we get our answer. This is really cool, but it doesn't end there. We can also build custom tools. And this is stupidly easy using the B agent framework. To keep this code nice and clean, I'm going to create a separate file for my custom tools. I'll call this file custom tools dot chis. We do need to install one more dependency if we want to build custom tools in the terminal, let's install a zod.
[21:52] Great, then at the top of the cart, let's import z from zod. Then after that, let's import something from the B agent framework, then tools and base. And what we want to import is the dynamic tool, as well as the string tool output. Now we can define any function that we want. And in this example, I want to build a tool that will allow the user to pass in an issue. And this tool will
[22:22] create a support ticket and return the support ticket number. So let's call this function create support ticket, which is equal to new dynamic tool. And this takes in an object as input. And the first property that we need to define is the name of the tool, which we can call create support ticket, then it's also provide a description. This description is really important as this will tell the LLM how and when to use this tool. I'll just call this create a
[22:52] support ticket. Then we need to define the input schema. So the input required by this tool for this tool, we need the user to pass in a description of the issue. So it's only one field. But of course, this can be as complex as you want it to be. And in order to make this type safe, the B agent framework uses zod. So to define this input schema, we can enter z dot object and within object, we can define the name of the field that will be passed in. I'll simply
[23:22] call it description. And this is of type z dot string, like so now after we have to find our input schema, all we have to do now is provide an async handler function. And this takes in input, and we can now add any code to this handler function. So this handler function will receive input from the LLM using this input schema. And we can then access any of the values within the schema by entering something like input dot description, as you can see here. Now we're
[23:53] simply going to mock this out and not create an actual ticket. So what I'll do is simply randomly generate a number by using math dot floor. And within this I'll enter math dot random times and a bunch of zeros. Now finally, to return the response back from the handler function, we can return a new instance of the string tool output clause, which we also imported from up here. And now we can pass back any string that we want, like ticket, ticket number
[24:26] created successfully. Now to make this tool available to our application, we'll simply export it, then back in this file, we can now import that tool. So I'll simply import something from custom tools dot JS, like so. And from this we want to import our create support ticket tool. We can add that tool to our tool array. Now that should be it. Let's try this in the terminal and let's say something like, please assist in creating a
[24:57] support ticket. Now what's really cool about this is the agent determined that we haven't actually provided the description of the issue. Therefore it's saying to create a support ticket, please provide a description of the issue. So let's provide a description of the issue, like my PC is not switching on. And now it's saying that your support ticket number this was created successfully. And really, that's how easy it is to build advanced applications using the B agent framework. Now finally, let's see how we can implement
[25:28] this code in the real world Next.js application. Now this is not a Next.js tutorial. So what I want you to do is to download this code from this GitHub repo. The link is in the description. So you can do that by clicking on code and download zip, or you can simply git clone this project. And in fact, that's what I'm going to do. So I'm going to git clone and add the URL to that GitHub repo. And we can then cd into this project by entering cd, followed by the folder name. Then what
[25:59] you need to do is run npm install, or I'm just going to use pnpm install. And you can then open that folder in your code editor. The first thing you need to do is rename this example.env.local file to just p.env.local. And what you then need to do is copy over your grok API key, and then save and close that environment variable file. In your terminal, you can start this project by running pnpm run dev. And you can
[26:29] then control click this URL to open it up in the browser. And you can send a message like, hey, and if you did everything correctly, you should see the response showing up over here, along with the user steps. So let's have a quick look at this code. Like I said, this is not a Next.js tutorial. So I'm not going to go into too much depth on what's going on on the front end. And what we can do is have a look at this route file. This should seem very familiar to you, as we're simply importing the b-agent class, the token memory, and the tools that we
[27:01] already had a look at. We're then instantiating our LLM, we're creating our agent, and all the logic then sets in this post function, where we're getting the message from the user. And this is from the front end, and we're then running the message passing in that prompt. So it's nothing new. And we're using the ometer to get all those updates. So all the individual steps, the only difference is we are now taking the contents of those steps and the pending them to an array so that finally we can return the text response
[27:32] from the agent, along with an array of individual steps. And that is really it. If you would like to see more content on the b-agent framework, or if you would like me to cover any other frameworks, then please let me know down in the description below. Thank you for watching this video, and for all the support. I'll see you guys in the next one. Bye bye.