diff --git a/docs/README-USECASES.md b/docs/README-USECASES.md index 81d312f3..0cae4b79 100644 --- a/docs/README-USECASES.md +++ b/docs/README-USECASES.md @@ -98,7 +98,7 @@ Here is an example of a web app that leverages GPTScript to recognize ingredient ### Image Generation -Here is a GPTScript that takes a story prompt and generates an illustrated children's book: [story-book.gpt](../examples/story-book) +Here is a GPTScript that takes a story prompt and generates an illustrated children's book: [story-book.gpt](https://github.com/gptscript-ai/story-book) ## Memory Management diff --git a/examples/story-book/.gitignore b/examples/story-book/.gitignore deleted file mode 100644 index b8a88f6c..00000000 --- a/examples/story-book/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# Nuxt dev/build outputs -.output -.data -.nuxt -.nitro -.cache -dist - -# Node dependencies -node_modules - -# Logs -logs -*.log - -# Misc -.DS_Store -.fleet -.idea - -# Local env files -.env -.env.* -!.env.example - -# AI generated files -public/stories diff --git a/examples/story-book/README.md b/examples/story-book/README.md deleted file mode 100644 index 4cacd008..00000000 --- a/examples/story-book/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Story Book - -Story Book is a web application that has an interface for users to input a prompt and number of pages. This information then generates a story based on the prompt. All generation is done using GPTScript on the backend. - -## Usage Instructions - -1. Make sure you have at least Node v20.11.1 installed. If you don't, you can install it [here](https://nodejs.org/en/download). - -2. Navigate to the `examples/story-book` directory. - -```bash -cd examples/story-book -``` - -3. Start the Nuxt application by running the following commands: - -```bash -npm i -npm run dev -``` - -4. Navigate to `http://localhost:3000` in your browser. \ No newline at end of file diff --git a/examples/story-book/app.vue b/examples/story-book/app.vue deleted file mode 100644 index 38414fbe..00000000 --- a/examples/story-book/app.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/examples/story-book/components/DisplayMode.vue b/examples/story-book/components/DisplayMode.vue deleted file mode 100644 index 396697e6..00000000 --- a/examples/story-book/components/DisplayMode.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/examples/story-book/components/Nav.vue b/examples/story-book/components/Nav.vue deleted file mode 100644 index 934897b8..00000000 --- a/examples/story-book/components/Nav.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/story-book/components/New.vue b/examples/story-book/components/New.vue deleted file mode 100644 index 4f9532a6..00000000 --- a/examples/story-book/components/New.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - - \ No newline at end of file diff --git a/examples/story-book/components/Stories.vue b/examples/story-book/components/Stories.vue deleted file mode 100644 index 1a70a0a1..00000000 --- a/examples/story-book/components/Stories.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/story-book/lib/types.ts b/examples/story-book/lib/types.ts deleted file mode 100644 index 533463e9..00000000 --- a/examples/story-book/lib/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Pages = Record; - -export type Page = { - image_path: string; - content: string; -} diff --git a/examples/story-book/lib/unmangle.ts b/examples/story-book/lib/unmangle.ts deleted file mode 100644 index e639f193..00000000 --- a/examples/story-book/lib/unmangle.ts +++ /dev/null @@ -1,4 +0,0 @@ -const unmangleStoryName = (storyName: string): string => { - return storyName.replaceAll('-', ' ').replace(/\b\w/g, c => c.toUpperCase()); -} -export default unmangleStoryName; \ No newline at end of file diff --git a/examples/story-book/nuxt.config.ts b/examples/story-book/nuxt.config.ts deleted file mode 100644 index 7a8bc507..00000000 --- a/examples/story-book/nuxt.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -// https://nuxt.com/docs/api/configuration/nuxt-config -export default defineNuxtConfig({ - devtools: { enabled: true }, - modules: [ - '@nuxt/ui', - '@nuxtjs/tailwindcss', - '@pinia/nuxt', - ], -}) diff --git a/examples/story-book/package.json b/examples/story-book/package.json deleted file mode 100644 index 0f79be49..00000000 --- a/examples/story-book/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "nuxt-app", - "private": true, - "type": "module", - "scripts": { - "build": "nuxt build", - "dev": "nuxt dev", - "generate": "nuxt generate", - "preview": "nuxt preview", - "postinstall": "nuxt prepare" - }, - "dependencies": { - "@gptscript-ai/gptscript": "^0.2.0", - "@nuxt/ui": "^2.15.0", - "@pinia/nuxt": "^0.5.1", - "jspdf": "^2.5.1", - "nuxt": "^3.11.1", - "pinia": "^2.1.7", - "vue": "^3.4.21", - "vue-router": "^4.3.0" - } -} diff --git a/examples/story-book/pages/index.vue b/examples/story-book/pages/index.vue deleted file mode 100644 index 832a40a2..00000000 --- a/examples/story-book/pages/index.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/story-book/pages/story/[name].vue b/examples/story-book/pages/story/[name].vue deleted file mode 100644 index 10ae69c9..00000000 --- a/examples/story-book/pages/story/[name].vue +++ /dev/null @@ -1,95 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/story-book/public/favicon.ico b/examples/story-book/public/favicon.ico deleted file mode 100644 index 18993ad9..00000000 Binary files a/examples/story-book/public/favicon.ico and /dev/null differ diff --git a/examples/story-book/server/api/story/[name].delete.ts b/examples/story-book/server/api/story/[name].delete.ts deleted file mode 100644 index 51aadb1e..00000000 --- a/examples/story-book/server/api/story/[name].delete.ts +++ /dev/null @@ -1,30 +0,0 @@ -import fs from 'fs' - -export default defineEventHandler(async (event) => { - try { - let name = getRouterParam(event, 'name') - if (!name) { - throw createError({ - statusCode: 400, - statusMessage: 'name is required' - }); - } - - name = decodeURIComponent(name); - - await fs.promises.readdir(`public/stories/${name}`) - fs.promises.rm(`public/stories/${name}`, { recursive: true }) - } catch (error) { - // if the error is a 404 error, we can throw it directly - if ((error as any).code === 'ENOENT') { - throw createError({ - statusCode: 404, - statusMessage: 'story not found', - }) - } - throw createError({ - statusCode: 500, - statusMessage: `error removing story: ${error}`, - }) - } -}) \ No newline at end of file diff --git a/examples/story-book/server/api/story/[name].get.ts b/examples/story-book/server/api/story/[name].get.ts deleted file mode 100644 index bf6593d8..00000000 --- a/examples/story-book/server/api/story/[name].get.ts +++ /dev/null @@ -1,47 +0,0 @@ -import fs from 'fs' - -type Pages = Record; -type Page = { - image_path: string; - content: string; -} - -export default defineEventHandler(async (event) => { - try { - let name = getRouterParam(event, 'name'); - if (!name) { - throw createError({ - statusCode: 400, - statusMessage: 'name is required' - }); - } - - name = decodeURIComponent(name); - - const files = await fs.promises.readdir(`public/stories/${name}`) - - const pages: Pages = {}; - for (const file of files) { - if (!file.endsWith('.txt')) continue - const page = await fs.promises.readFile(`public/stories/${name}/${file}`, 'utf-8') - pages[ file.replace('.txt', '').replace('page', '')] = { - image_path: `/stories/${name}/${file.replace('.txt', '.png')}`, - content: page - } - } - - return pages - } catch (error) { - // if the error is a 404 error, we can throw it directly - if ((error as any).code === 'ENOENT') { - throw createError({ - statusCode: 404, - statusMessage: 'story found', - }) - } - throw createError({ - statusCode: 500, - statusMessage: `error fetching story: ${error}`, - }) - } -}) \ No newline at end of file diff --git a/examples/story-book/server/api/story/index.get.ts b/examples/story-book/server/api/story/index.get.ts deleted file mode 100644 index 63e101fd..00000000 --- a/examples/story-book/server/api/story/index.get.ts +++ /dev/null @@ -1,20 +0,0 @@ -import fs from 'fs' - -export default defineEventHandler(async (event) => { - try { - const stories = await fs.promises.readdir('public/stories') - return stories - } catch (error) { - // if the error is a 404 error, we can throw it directly - if ((error as any).code === 'ENOENT') { - throw createError({ - statusCode: 404, - statusMessage: 'no stories found', - }) - } - throw createError({ - statusCode: 500, - statusMessage: `error fetching stories: ${error}`, - }) - } -}) \ No newline at end of file diff --git a/examples/story-book/server/api/story/index.post.ts b/examples/story-book/server/api/story/index.post.ts deleted file mode 100644 index 88ba57c4..00000000 --- a/examples/story-book/server/api/story/index.post.ts +++ /dev/null @@ -1,50 +0,0 @@ -import gptscript from '@gptscript-ai/gptscript' -import { Readable } from 'stream' - -type Request = { - prompt: string; - pages: number; -} - -export type RunningScript = { - stdout: Readable; - stderr: Readable; - promise: Promise; -} - -export const runningScripts: Record= {} - -export default defineEventHandler(async (event) => { - const request = await readBody(event) as Request - - if (!request.prompt) { - throw createError({ - statusCode: 400, - statusMessage: 'prompt is required' - }); - } - - if (!request.pages) { - throw createError({ - statusCode: 400, - statusMessage: 'pages are required' - }); - } - - const {stdout, stderr, promise} = await gptscript.streamExecFile('story-book.gpt', `--story ${request.prompt} --pages ${request.pages}`, {}) - - setHeaders(event,{ - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Credentials': 'true', - 'Connection': 'keep-alive', - 'Content-Type': 'text/event-stream', - }) - - setResponseStatus(event, 202) - - runningScripts[request.prompt] = { - stdout: stdout, - stderr: stderr, - promise: promise - } -}) \ No newline at end of file diff --git a/examples/story-book/server/api/story/sse.get.ts b/examples/story-book/server/api/story/sse.get.ts deleted file mode 100644 index 00a1e4c3..00000000 --- a/examples/story-book/server/api/story/sse.get.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { runningScripts } from '@/server/api/story/index.post'; - -export default defineEventHandler(async (event) => { - const { prompt } = getQuery(event); - if (!prompt) { - throw createError({ - statusCode: 400, - statusMessage: 'prompt is required' - }); - } - - const runningScript = runningScripts[prompt as string]; - if (!runningScript) { - throw createError({ - statusCode: 404, - statusMessage: 'running script not found' - }); - } - - setResponseStatus(event, 200); - setHeaders(event, { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Credentials': 'true', - 'Connection': 'keep-alive', - 'Content-Type': 'text/event-stream', - }); - - let stdoutBuffer = ''; - runningScript.stdout.on('data', (data) => { - stdoutBuffer += data; - if (data.includes('\n')) { - event.node.res.write(`data: ${stdoutBuffer}\n\n`); - stdoutBuffer = ''; - } - }); - - let stderrBuffer = ''; - runningScript.stderr.on('data', (data) => { - stderrBuffer += data; - if (data.includes('\n')) { - event.node.res.write(`data: ${stderrBuffer}\n\n`); - stderrBuffer = ''; - } - }); - - event._handled = true; - await runningScript.promise.then(() => { - event.node.res.write('data: done\n\n'); - event.node.res.end(); - }).catch((error) => { - setResponseStatus(event, 500); - event.node.res.write(`data: error: ${error}\n\n`); - event.node.res.end(); - }); -}); \ No newline at end of file diff --git a/examples/story-book/server/tsconfig.json b/examples/story-book/server/tsconfig.json deleted file mode 100644 index b9ed69c1..00000000 --- a/examples/story-book/server/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../.nuxt/tsconfig.server.json" -} diff --git a/examples/story-book/store/index.ts b/examples/story-book/store/index.ts deleted file mode 100644 index 18cdf2ac..00000000 --- a/examples/story-book/store/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -// store/index.ts -import { defineStore } from 'pinia' - -export const useMainStore = defineStore({ - id: 'main', - state: () => ({ - pendingStories: {} as Record, - pendingStoryMessages: {} as Record, - stories: [] as string[] - }), - actions: { - addPendingStory(name: string, es: EventSource) { - this.pendingStories[name] = es - }, - removePendingStory(name: string) { - this.pendingStories[name].close() - delete this.pendingStories[name] - }, - addPendingStoryMessage(name: string, message: string) { - // implement a queue with a length of 10 that removes the oldest message when the length is reached - if (!this.pendingStoryMessages[name]) { - this.pendingStoryMessages[name] = [] - } - this.pendingStoryMessages[name].push(message) - if (this.pendingStoryMessages[name].length > 12) { - this.pendingStoryMessages[name].shift() - } - }, - addStory(name: string) { - this.stories.push(name) - }, - addStories(names: string[]) { - // only push if the story is not already in the list - names.forEach(name => { - if (!this.stories.includes(name)) { - this.stories.push(name) - } - }) - }, - removeStory(name: string) { - this.stories = this.stories.filter(s => s !== name) - }, - async fetchStories() { - if (Object.keys(this.pendingStories).length === 0) { - this.addStories(await $fetch('/api/story') as string[]) - } - } - - } -}) \ No newline at end of file diff --git a/examples/story-book/story-book.gpt b/examples/story-book/story-book.gpt deleted file mode 100644 index 57d80db8..00000000 --- a/examples/story-book/story-book.gpt +++ /dev/null @@ -1,47 +0,0 @@ -tools: story-writer, story-illustrator, mkdir, sys.write, sys.read, sys.download -description: Writes a children's book and generates illustrations for it. -args: story: The story to write and illustrate. Can be a prompt or a complete story. -args: pages: The number of pages to generate - -Do the following steps sequentially: - -1. Come up with an appropriate title for the story based on the ${prompt} -2. Create the `public/stories/${story-title}` directory if it does not already exist. -3. If ${story} is a prompt and not a complete children's story, call story-writer - to write a story based on the prompt. -4. Take ${story} and break it up into ${pages} logical "pages" of text. -5. For each page: - - For the content of the page, write it to `public/stories/${story-title}/page.txt and add appropriate newline - characters. - - Call story-illustrator to illustrate it. Be sure to include any relevant characters to include when - asking it to illustrate the page. - - Download the illustration to a file at `public/stories/${story-title}/page.png`. - ---- -name: story-writer -description: Writes a story for children -args: prompt: The prompt to use for the story -temperature: 1 - -Write a story with a tone for children based on ${prompt}. - ---- -name: story-illustrator -tools: github.com/gptscript-ai/image-generation -description: Generates a illustration for a children's story -args: text: The text of the page to illustrate - -Think of a good prompt to generate an image to represent $text. Make sure to -include the name of any relevant characters in your prompt. Then use that prompt to -generate an illustration. Append any prompt that you have with ". In an pointilism cartoon -children's book style with no text in it". Only return the URL of the illustration. - ---- -name: mkdir -tools: sys.write -description: Creates a specified directory -args: dir: Path to the directory to be created. Will create parent directories. - -#!bash - -mkdir -p "${dir}" diff --git a/examples/story-book/tailwind.config.ts b/examples/story-book/tailwind.config.ts deleted file mode 100644 index 63da7b5e..00000000 --- a/examples/story-book/tailwind.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Config } from 'tailwindcss' -import defaultTheme from 'tailwindcss/defaultTheme' -import typography from '@tailwindcss/typography' - -export default > { - content: [ - './src/components/**/*.{js,vue,ts}', - './src/layouts/**/*.vue', - './src/pages/**/*.vue', - './src/plugins/**/*.{js,ts}', - './src/app.vue', - './src/error.vue', - ], - - darkMode: 'class', - - plugins: [ - typography, - ], -} diff --git a/examples/story-book/tsconfig.json b/examples/story-book/tsconfig.json deleted file mode 100644 index a746f2a7..00000000 --- a/examples/story-book/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // https://nuxt.com/docs/guide/concepts/typescript - "extends": "./.nuxt/tsconfig.json" -}