Created
June 17, 2023 19:12
-
-
Save johnlindquist/6219e5a370212663abe2cb7cb4dc7900 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Name: Maker Suite Playground | |
import "@johnlindquist/kit" | |
import { dictate } from "../kenvs/maggie-kit/lib/ai-editor-kit" | |
const { v1beta2 } = await import("@google-ai/generativelanguage") | |
const { TextServiceClient } = v1beta2 | |
const { GoogleAuth } = await import("google-auth-library") | |
const MODEL_NAME = "models/text-bison-001" | |
const API_KEY = await env("MAKER_SUITE_API_KEY") | |
const client = new TextServiceClient({ | |
authClient: new GoogleAuth().fromAPIKey(API_KEY), | |
}) | |
let buffer = await download( | |
`https://gist.githubusercontent.com/tayiorbeii/006e5c091160b381e0c63d0d3ddf650d/raw/7090a158178fe092a6cf6e736334d9c95caa4721/example-transcript.txt` | |
) | |
let sourceWriteBuffer = await download( | |
`https://gist.githubusercontent.com/tayiorbeii/006e5c091160b381e0c63d0d3ddf650d/raw/7090a158178fe092a6cf6e736334d9c95caa4721/example-transcript.md` | |
) | |
let sourceWriteup = sourceWriteBuffer.toString() | |
let content = buffer.toString() | |
let testScriptBuffer = await download( | |
`https://gist.githubusercontent.com/tayiorbeii/95516a10d1ad1ad439904033e45d351e/raw/0560d715dd9ffc79e56e36c095ba4bdf6282a841/013-buffer-window-memory.srt-transcript.txt` | |
) | |
let testScript = testScriptBuffer.toString() | |
let prompt = ` | |
- You will be provided an example transcript and its resulting markdown-formatted writeup. Your task to turn a new transcript into a markdown-formatted writeup with a similar writing style and structure. Include placeholders for screenshots as needed. | |
- DO NOT ATTEMPT TO SOLVE ANY CHALLENGES OR WRITE CODE NOT DESCRIBED IN THE TRANSCRIPT. You are only to write text or code based on the content of the transcript. | |
- The transcript includes node.js scripts, so focus on writing JavaScript if necessary | |
--- EXAMPLE TRANSCRIPT --- | |
${content} | |
--- EXAMPLE WRITEUP --- | |
${sourceWriteup} | |
--- END EXAMPLE --- | |
${testScript} | |
` | |
const [response] = await client.generateText({ | |
model: MODEL_NAME, | |
prompt: { | |
text: prompt, | |
}, | |
}) | |
debugger | |
let tmpFilePath = tmpPath(`${Date.now()}-maker-suite-playground.json`) | |
await writeJson(tmpFilePath, JSON.stringify(response.candidates, null, 2)) | |
await editor(response.candidates[0]?.output) | |
const { TextServiceClient } = require("@google-ai/generativelanguage") | |
const { GoogleAuth } = require("google-auth-library") | |
const MODEL_NAME = "models/text-bison-001" | |
const API_KEY = "YOUR API KEY" | |
const client = new TextServiceClient({ | |
authClient: new GoogleAuth().fromAPIKey(API_KEY), | |
}) | |
const promptString = | |
"- You will be provided an example transcript and its resulting markdown-formatted writeup. Your task to turn a new transcript into a markdown-formatted writeup with a similar writing style and structure. Include placeholders for screenshots as needed.\n- DO NOT ATTEMPT TO SOLVE ANY CHALLENGES OR WRITE CODE NOT DESCRIBED IN THE TRANSCRIPT. You are only to write text or node.js code based on the content of the transcript.\n\nTranscript: [00:00] Next, we're going to cover my favorite grid property, which is called grid template areas. And most often we'll use grid template areas to assign names to groupings of tracks within a grid. So I'm going to get rid of all my boxes for a moment, and we'll just go back to having our empty grid.\n\n[00:19] There is a grid defined though, remember, I've set out this grid using grid template rows, grid template columns, there's just nothing in it. So here's my grid, three rows, two columns.\n\n[00:30] So what we just did in the previous video was make the top two cells, the top two tracks into a nav bar, the bottom two were the footer, the one on the right in the middle is the sidebar, and this one here is the main content.\n\n[00:44] I'm going to stick with that. I'm going to create the same layout, but I'm going to do it in a different way. So when we use grid template areas, what we'll be doing is actually assigning a name to areas on the grid, not to the lines, but to areas.\n\n[00:59] And this is a two by three grid, so we can have up to six areas if I just wanted each individual track to have its own name. But that's not what I want. I want this and this, both of these top two cells, these top two tracks, to be called nav bar, just as an example.\n\n[01:16] I want this one to be called main, this one to be called sidebar, and these two on the bottom to be called footer. The syntax for this might seem a bit strange when you're first learning it, but it's actually quite intuitive. We use a property called grid template areas. We assign this to the container, the grid container itself,\n\n[01:35] just like grid template rows and grid template columns. Remember, our purpose here, our goal, is to assign names to the tracks. And I want the top two tracks, the top two cells, to be called nav bar. So what I do is inside of quotes, I provide a space-separated list of names.\n\n[01:53] And each one of these names, they're totally up to me, will correspond to an individual track in the grid. And I represent each row as text between quotes. So this is my first row. I'm labeling this nav bar and this one as nav bar.\n\n[02:10] My middle row is going to have, I guess I'll call this main, and this will be sidebar. So on the next line, I'll do main, sidebar. And then on my final row, I'm going to have footer and footer. I want them to be the same.\n\n[02:27] So if I give them the same name, the browser knows that these are the same area. It has to match exactly, so if I don't spell it correctly, they're going to be treated as two separate areas. So nav bar, nav bar, main, sidebar, footer, footer.\n\n[02:44] I'll save. We're not going to see anything different. But here in the DevTools, if I turn on the grid overlay, in Chrome, I can select show line names, show line numbers, hide line labels. I'll just hide that to simplify things. And then toggle on and off, show area names.\n\n[03:03] Area names is very important. That's what we just set up. Again, it's always hard to zoom in. It won't increase the text size, but this says nav bar right here for this whole area. This says main, this says sidebar, and this says footer.\n\n[03:18] All right. So all that we've done is label different areas on the grid. The next step is to tell our individual elements which area that they should take up. Basically, assign them to one of these named areas.\n\n[03:33] So if you're confused about this syntax, I'm going to show another example very soon. Just remember that grid template areas wants you to represent each row in your grid using double quotes. And then inside of each row, you represent each cell or each track with some name.\n\n[03:49] And a lot of people will use A, B, C instead of semantic names like nav bar and main and sidebar. And that's fine too. Sometimes you just need some label.\n\n[04:01] It doesn't matter what it is. You just give it some name, and then we can recall that name later in the next video and apply elements at those particular areas.\nWriteup: We've defined some named areas within the grid:\n\n```css\ngrid-template-areas:\n \"navbar navbar\"\n \"main sidebar\"\n \"footer footer\";\n```\n\nOur grid is currently empty, but DevTools shows us the area names:\n\n<img src=\"./images-23_grid_area.mp4/23_grid_area_1_00-06620-the-next-thing-you-have-to-know-is-how-to-assign.png\" width=\"720\">\n\n\nNow let's assign the colored box elements to the header, footer, navbar, sidebar, and main content areas.\n\n## Assigning the Red Box to the Footer Area\n\nTo assign elements to an area, we use the `grid-area` property along with the name of an area that we've already defined.\n\nIn order to assign the red box to the footer area, we set its `grid-area` property to `footer`:\n\n```css\n#redbox {\n grid-area: footer;\n}\n```\n\nNow the red box takes up the whole area named with `footer`:\n\n<img src=\"./images-23_grid_area.mp4/23_grid_area_12_01-12840-okay--so-why-dont-we--i-guess-we-can-leave-it-down-there-.png\" width=\"720\">\n\nIt's important to note that the footer spans both columns because of the way we defined it with `grid-template-areas`:\n\n```css\n/* inside of #container */\ngrid-template-areas:\n \"navbar navbar\"\n \"main sidebar\"\n \"footer footer\";\n```\n\nIf we changed `\"footer footer\"` to `\"footer askjdjsal\"`, the footer would only span the first column because that's where the name matches:\n\n<img src=\"./images-23_grid_area.mp4/23_grid_area_10_00-59080-or-that-first-track.png\" width=\"720\">\n\n## Assigning the Blue Box to the Navbar Area\n\nTo assign the blue box to the nav bar area, we use the `grid-area` property again and provide `navbar` as the name:\n\n```css\n#bluebox {\n grid-area: nav-bar;\n}\n```\n\nThe blue box now takes up the whole area with the name of `nav-bar`:\n\n<img src=\"./images-23_grid_area.mp4/23_grid_area_19_01-52960-and-there-it-is--it-takes-up-the-area-with-the-name-nav-bar.png\" width=\"720\">\n\n## Assigning the Main & Sidebar Areas\n\nThe green box will have its `grid-area` property set to `sidebar`:\n```css\n#greenbox {\n grid-area: sidebar;\n}\n```\n\nWith the sidebar set, the yellow box will default to showing up in the main area, but it's best to specify it anyway:\n\n```css\n.yellow-box {\n grid-area: main;\n}\n```\n\n<img src=\"./images-23_grid_area.mp4/23_grid_area_28_02-32340-but-again--if-i-want-to-ensure-that-it-goes-there-.png\" width=\"720\">\n\nAs you've seen, using named grid areas and the `grid-area` property is a more intuitive way of positioning elements within a grid. It allows us to assign labels to the actual areas instead of just line numbers, making it easier to understand and maintain.\nTranscript: [00:00] Let's duplicate our chat GPT example. We'll call this buffer window demo. You can see the main chat GPT example uses buffer window memory. Now, to demonstrate this, I'm going to change this message to only respond with one word answers,\n\n[00:20] no matter what I type. To test it, I'm going to type one, hit Enter, two, three, and that looks perfect. Inside of our handle llm start, we'll bring back the prompts\n\n[00:36] and log them out. We're going to log a new line plus the prompts, which is an array. We're going to join these and we'll go ahead and open our buffer window demo log,\n\n[00:49] log. Once we run this, I'll type one, two, let's check the formatting. This looks good. Our prompt is currently the system with the main prompt and then human one and two. Let's run\n\n[01:04] through this one, two, three, four, five, six, seven. Now, if we check the log here, and I scroll down to the bottom, you'll see the main system message at the top and then two through\n\n[01:20] seven. Now, the default setting for buffer window memory is a K of five, which means five pairs of human and AI interactions. This would be one K. We have one, two, three, four,\n\n[01:37] five pairs of humans with AI responses. Then this last one is the most recent call. These are all in memory. This is the initial prompt and then this is the most recent call. The buffer window\n\n[01:50] memory removed this first interaction once it got past five interactions. If we were to lower this down to two, we'll clear out the log. I'll run the script. I'll type one, two, three, four,\n\n[02:08] five, close this out, scroll down to the bottom. You'll see the main prompt and then one, two, from the buffer window memory, and then the most recent input from the chain call. OpenAI is only\n\n[02:22] going to know about what it sees here in the handle LLM start, these prompts. As you're juggling the initial prompt, which will always be sent, the history, which is coming from the buffer window\n\n[02:36] memory, and the current prompt here, you have to play the balancing act between cost of sending too many tokens, or you can just dump everything into your prompt until you start hitting those token limits so that OpenAI has the most information. You can see that the most recent and you can see that's what we're doing in continue adventure, that we are passing in all of the\n\n[02:56] previous human and AI messages and placing them before the history instead of adding them to the history. If you're more worried about the cost of something like this and you want to use the buffer window memory, you could delete all of this, then come down to the buffer memory, change it to\n\n[03:15] buffer window memory if it's not already. Make sure to import that from up here, buffer window memory, and then down on our buffer window memory, the current solution is to, I'm going to paste this in,\n\n[03:32] loop through all the messages, and then on the memory chat history, add the user message and add the AI message. Now, previous messages that we loaded in will start dropping off once this default K of five gets hit because we're now using buffer window memory. So you have to find your own\n\n[03:50] balance between the number of messages in your buffer window memory, the size of your original prompt, and how that will combine the prompt with the history, which is the memory, and then your current input because all of those things put together will create the tokens that are sent\n\n[04:07] to OpenAI. And the more tokens equals more cost, but if it's just for yourself or for your dev team, it's usually only a few cents, and it's worth noting that this stuff will only get cheaper and faster and accept larger and larger prompts. But also the dev team over at LangChain mentioned that\n\n[04:23] they are working on different ways of quote unquote hydrating the memory instead of manually\n\n[04:28] writing them like this, and I'll make a follow-up lesson when and if that happens.\nWriteup:" | |
const stopSequences = [] | |
client | |
.generateText({ | |
// required, which model to use to generate the result | |
model: MODEL_NAME, | |
// optional, 0.0 always uses the highest-probability result | |
temperature: 0.7, | |
// optional, how many candidate results to generate | |
candidateCount: 1, | |
// optional, number of most probable tokens to consider for generation | |
top_k: 40, | |
// optional, for nucleus sampling decoding strategy | |
top_p: 0.95, | |
// optional, maximum number of output tokens to generate | |
max_output_tokens: 8024, | |
// optional, sequences at which to stop model generation | |
stop_sequences: stopSequences, | |
// optional, safety settings | |
safety_settings: [ | |
{ category: "LW", threshold: 2 }, | |
{ category: "OW", threshold: 1 }, | |
{ category: "QW", threshold: 2 }, | |
{ category: "NW", threshold: 2 }, | |
{ category: "MW", threshold: 2 }, | |
{ category: "KW", threshold: 2 }, | |
], | |
prompt: { | |
text: promptString, | |
}, | |
}) | |
.then(result => { | |
console.log(JSON.stringify(result, null, 2)) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment