Giter Club home page Giter Club logo

nextjs-openai-doc-search's Introduction

Next.js OpenAI Doc Search Starter

This starter takes all the .mdx files in the pages directory and processes them to use as custom context within OpenAI Text Completion prompts.

Deploy

Deploy this starter to Vercel. The Supabase integration will automatically set the required environment variables and configure your Database Schema. All you have to do is set your OPENAI_KEY and you're ready to go!

Deploy with Vercel

Technical Details

Building your own custom ChatGPT involves four steps:

  1. [👷 Build time] Pre-process the knowledge base (your .mdx files in your pages folder).
  2. [👷 Build time] Store embeddings in Postgres with pgvector.
  3. [🏃 Runtime] Perform vector similarity search to find the content that's relevant to the question.
  4. [🏃 Runtime] Inject content into OpenAI GPT-3 text completion prompt and stream response to the client.

👷 Build time

Step 1. and 2. happen at build time, e.g. when Vercel builds your Next.js app. During this time the generate-embeddings script is being executed which performs the following tasks:

sequenceDiagram
    participant Vercel
    participant DB (pgvector)
    participant OpenAI (API)
    loop 1. Pre-process the knowledge base
        Vercel->>Vercel: Chunk .mdx pages into sections
        loop 2. Create & store embeddings
            Vercel->>OpenAI (API): create embedding for page section
            OpenAI (API)->>Vercel: embedding vector(1536)
            Vercel->>DB (pgvector): store embedding for page section
        end
    end

In addition to storing the embeddings, this script generates a checksum for each of your .mdx files and stores this in another database table to make sure the embeddings are only regenerated when the file has changed.

🏃 Runtime

Step 3. and 4. happen at runtime, anytime the user submits a question. When this happens, the following sequence of tasks is performed:

sequenceDiagram
    participant Client
    participant Edge Function
    participant DB (pgvector)
    participant OpenAI (API)
    Client->>Edge Function: { query: lorem ispum }
    critical 3. Perform vector similarity search
        Edge Function->>OpenAI (API): create embedding for query
        OpenAI (API)->>Edge Function: embedding vector(1536)
        Edge Function->>DB (pgvector): vector similarity search
        DB (pgvector)->>Edge Function: relevant docs content
    end
    critical 4. Inject content into prompt
        Edge Function->>OpenAI (API): completion request prompt: query + relevant docs content
        OpenAI (API)-->>Client: text/event-stream: completions response
    end

The relevant files for this are the SearchDialog (Client) component and the vector-search (Edge Function).

The initialization of the database, including the setup of the pgvector extension is stored in the supabase/migrations folder which is automatically applied to your local Postgres instance when running supabase start.

Local Development

Configuration

  • cp .env.example .env
  • Set your OPENAI_KEY in the newly created .env file.
  • Set NEXT_PUBLIC_SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY run:

    Note: You have to run supabase to retrieve the keys.

Start Supabase

Make sure you have Docker installed and running locally. Then run

supabase start

To retrieve NEXT_PUBLIC_SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY run:

supabase status

Start the Next.js App

In a new terminal window, run

pnpm dev

Using your custom .mdx docs

  1. By default your documentation will need to be in .mdx format. This can be done by renaming existing (or compatible) markdown .md file.
  2. Run pnpm run embeddings to regenerate embeddings.

    Note: Make sure supabase is running. To check, run supabase status. If is not running run supabase start.

  3. Run pnpm dev again to refresh NextJS localhost:3000 rendered page.

Learn More

Video: How I Built Supabase’s OpenAI Doc Search

Licence

Apache 2.0

nextjs-openai-doc-search's People

Contributors

adiologydev avatar chartpath avatar dependabot[bot] avatar gregnr avatar kiwicopple avatar mildtomato avatar musashi-garami avatar saltcod avatar sd0xdev avatar thorwebdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nextjs-openai-doc-search's Issues

Chat list is not up to date / not working

Bug report

Context: Testing using 2 different google accounts (ari.font on chrome) and barceloneta (on safari).

Issue: when I go to chat list after having chatted between these 2 accounts, I see a spinning wheel form ari.font (chrome) and it does not show me the list of chats, and for barceloneta I don’t see ari.font on the list of chats, which is the last person I talked to from there (just Pablo and Juan, not in order of last talked to)

See screenshots below:
Screenshot 2023-04-11 at 11 57 43
Screenshot 2023-04-11 at 11 59 11

list of users do not appear in order

Context: Testing using 2 different google accounts (ari.font on chrome) and barceloneta (on safari).

Issue: For barceloneta, list of users do not appear in order at all, for ari.font at least the last one does, but 2nd one should be Juan…

last chat should be Ariadna Font and then Juan for each of these
Screenshot 2023-04-11 at 11 57 43
but instead I get this:
Screenshot 2023-04-11 at 11 57 56

Not able to make this starter project work

Bug report

Describe the bug

I followed the exact same steps to locally deploy this starter project but it gives an error

A clear and concise description of what the bug is.
I added my OpenAI key and supabase keys, started my docker and then supabase. I can see the embeddings in the supabase and the openAI API is also working as I can see the usage increasing in the dashboard.

I am not able to get the response as in the screenshot attached -
Screenshot 2023-05-26 at 1 25 03 PM

The error is -
CustomEvent {isTrusted: false, data: '{"error":"There was an error processing your request"}', source: SSE, detail: null, type: 'error', …}

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

Clone this repo
Did npm i to install dependencies
Got the API keys and added them to .env
Set up docker and supabase
then run pnpm dev

Expected behavior

Recieve an error like I am getting

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: [e.g. macOS, Windows]
  • Browser (if applies) [e.g. chrome, safari]
  • Version of supabase-js: [e.g. 6.0.2]
  • Version of Node.js: [e.g. 10.10.0]

Additional context

I am not much familiar with supabase and openAI so not sure about this error. Would really appreciate help on this. Also if there is discord support available I can hop there too. I am building a project with very same usecase. Followed @gregnr 's video on youtube

Page *page-name* or one/multiple of its page sections failed to store properly. Page has been marked with null checksum to indicate that it needs to be re-generated.

This happens when running pnpm run embeddings locally and when deploying to Vercel. The NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY and OPENAI_KEY are in both the .env and in the Vercel vars.
  details: 'TypeError: fetch failed\n' +
    '    at Object.fetch (node:internal/deps/undici/undici:11576:11)\n' +
    '    at generateEmbeddings
(lib\generate-embeddings.ts:319:61)\n' +
    '    at main
lib\generate-embeddings.ts:487:3)',
  hint: '',
  code: ''
}
Here's the Generate-embeddings.tsx, for reference.
`
import { createClient } from '@supabase/supabase-js'
import { createHash } from 'crypto'
import dotenv from 'dotenv'
import { ObjectExpression } from 'estree'
import { readdir, readFile, stat } from 'fs/promises'
import GithubSlugger from 'github-slugger'
import { Content, Root } from 'mdast'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { mdxFromMarkdown, MdxjsEsm } from 'mdast-util-mdx'
import { toMarkdown } from 'mdast-util-to-markdown'
import { toString } from 'mdast-util-to-string'
import { mdxjs } from 'micromark-extension-mdxjs'
import 'openai'
import { Configuration, OpenAIApi } from 'openai'
import { basename, dirname, join } from 'path'
import { u } from 'unist-builder'
import { filter } from 'unist-util-filter'
import { inspect } from 'util'
import yargs from 'yargs'

dotenv.config()

const ignoredFiles = ['pages/404.mdx']

/**

  • Extracts ES literals from an estree ObjectExpression
  • into a plain JavaScript object.
    */
    function getObjectFromExpression(node: ObjectExpression) {
    return node.properties.reduce<
    Record<string, string | number | bigint | true | RegExp | undefined>

((object, property) => {
if (property.type !== 'Property') {
return object
}

const key = (property.key.type === 'Identifier' && property.key.name) || undefined
const value = (property.value.type === 'Literal' && property.value.value) || undefined

if (!key) {
  return object
}

return {
  ...object,
  [key]: value,
}

}, {})
}

/**

  • Extracts the meta ESM export from the MDX file.
  • This info is akin to frontmatter.
    */
    function extractMetaExport(mdxTree: Root) {
    const metaExportNode = mdxTree.children.find((node): node is MdxjsEsm => {
    return (
    node.type === 'mdxjsEsm' &&
    node.data?.estree?.body[0]?.type === 'ExportNamedDeclaration' &&
    node.data.estree.body[0].declaration?.type === 'VariableDeclaration' &&
    node.data.estree.body[0].declaration.declarations[0]?.id.type === 'Identifier' &&
    node.data.estree.body[0].declaration.declarations[0].id.name === 'meta'
    )
    })

if (!metaExportNode) {
return undefined
}

const objectExpression =
(metaExportNode.data?.estree?.body[0]?.type === 'ExportNamedDeclaration' &&
metaExportNode.data.estree.body[0].declaration?.type === 'VariableDeclaration' &&
metaExportNode.data.estree.body[0].declaration.declarations[0]?.id.type === 'Identifier' &&
metaExportNode.data.estree.body[0].declaration.declarations[0].id.name === 'meta' &&
metaExportNode.data.estree.body[0].declaration.declarations[0].init?.type ===
'ObjectExpression' &&
metaExportNode.data.estree.body[0].declaration.declarations[0].init) ||
undefined

if (!objectExpression) {
return undefined
}

return getObjectFromExpression(objectExpression)
}

/**

  • Splits a mdast tree into multiple trees based on

  • a predicate function. Will include the splitting node

  • at the beginning of each tree.

  • Useful to split a markdown file into smaller sections.
    */
    function splitTreeBy(tree: Root, predicate: (node: Content) => boolean) {
    return tree.children.reduce<Root[]>((trees, node) => {
    const [lastTree] = trees.slice(-1)

    if (!lastTree || predicate(node)) {
    const tree: Root = u('root', [node])
    return trees.concat(tree)
    }

    lastTree.children.push(node)
    return trees
    }, [])
    }

type Meta = ReturnType

type Section = {
content: string
heading?: string
slug?: string
}

type ProcessedMdx = {
checksum: string
meta: Meta
sections: Section[]
}

/**

  • Processes MDX content for search indexing.
  • It extracts metadata, strips it of all JSX,
  • and splits it into sub-sections based on criteria.
    */
    function processMdxForSearch(content: string): ProcessedMdx {
    const checksum = createHash('sha256').update(content).digest('base64')

const mdxTree = fromMarkdown(content, {
extensions: [mdxjs()],
mdastExtensions: [mdxFromMarkdown()],
})

const meta = extractMetaExport(mdxTree)

// Remove all MDX elements from markdown
const mdTree = filter(
mdxTree,
(node) =>
![
'mdxjsEsm',
'mdxJsxFlowElement',
'mdxJsxTextElement',
'mdxFlowExpression',
'mdxTextExpression',
].includes(node.type)
)

if (!mdTree) {
return {
checksum,
meta,
sections: [],
}
}

const sectionTrees = splitTreeBy(mdTree, (node) => node.type === 'heading')

const slugger = new GithubSlugger()

const sections = sectionTrees.map((tree) => {
const [firstNode] = tree.children

const heading = firstNode.type === 'heading' ? toString(firstNode) : undefined
const slug = heading ? slugger.slug(heading) : undefined

return {
  content: toMarkdown(tree),
  heading,
  slug,
}

})

return {
checksum,
meta,
sections,
}
}

type WalkEntry = {
path: string
parentPath?: string
}

async function walk(dir: string, parentPath?: string): Promise<WalkEntry[]> {
const immediateFiles = await readdir(dir)

const recursiveFiles = await Promise.all(
immediateFiles.map(async (file) => {
const path = join(dir, file)
const stats = await stat(path)
if (stats.isDirectory()) {
// Keep track of document hierarchy (if this dir has corresponding doc file)
const docPath = ${basename(path)}.mdx

    return walk(
      path,
      immediateFiles.includes(docPath) ? join(dirname(path), docPath) : parentPath
    )
  } else if (stats.isFile()) {
    return [
      {
        path: path,
        parentPath,
      },
    ]
  } else {
    return []
  }
})

)

const flattenedFiles = recursiveFiles.reduce(
(all, folderContents) => all.concat(folderContents),
[]
)

return flattenedFiles.sort((a, b) => a.path.localeCompare(b.path))
}

abstract class BaseEmbeddingSource {
checksum?: string
meta?: Meta
sections?: Section[]

constructor(public source: string, public path: string, public parentPath?: string) {}

abstract load(): Promise<{
checksum: string
meta?: Meta
sections: Section[]
}>
}

class MarkdownEmbeddingSource extends BaseEmbeddingSource {
type: 'markdown' = 'markdown'

constructor(source: string, public filePath: string, public parentFilePath?: string) {
const path = filePath.replace(/^pages/, '').replace(/.mdx?$/, '')
const parentPath = parentFilePath?.replace(/^pages/, '').replace(/.mdx?$/, '')

super(source, path, parentPath)

}

async load() {
const contents = await readFile(this.filePath, 'utf8')

const { checksum, meta, sections } = processMdxForSearch(contents)

this.checksum = checksum
this.meta = meta
this.sections = sections

return {
  checksum,
  meta,
  sections,
}

}
}

type EmbeddingSource = MarkdownEmbeddingSource

async function generateEmbeddings() {
const argv = await yargs.option('refresh', {
alias: 'r',
description: 'Refresh data',
type: 'boolean',
}).argv

const shouldRefresh = argv.refresh

if (
!process.env.NEXT_PUBLIC_SUPABASE_URL ||
!process.env.SUPABASE_SERVICE_ROLE_KEY ||
!process.env.OPENAI_KEY
) {
return console.log(
'Environment variables NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, and OPENAI_KEY are required: skipping embeddings generation'
)
}

const supabaseClient = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY,
{
auth: {
persistSession: false,
autoRefreshToken: false,
},
}
)

const embeddingSources: EmbeddingSource[] = [
...(await walk('pages'))
.filter(({ path }) => /.mdx?$/.test(path))
.filter(({ path }) => !ignoredFiles.includes(path))
.map((entry) => new MarkdownEmbeddingSource('guide', entry.path)),
]

console.log(Discovered ${embeddingSources.length} pages)

if (!shouldRefresh) {
console.log('Checking which pages are new or have changed')
} else {
console.log('Refresh flag set, re-generating all pages')
}

for (const embeddingSource of embeddingSources) {
const { type, source, path, parentPath } = embeddingSource

try {
  const { checksum, meta, sections } = await embeddingSource.load()

  // Check for existing page in DB and compare checksums
  const { error: fetchPageError, data: existingPage } = await supabaseClient
    .from('nods_page')
    .select('id, path, checksum, parentPage:parent_page_id(id, path)')
    .filter('path', 'eq', path)
    .limit(1)
    .maybeSingle()

  if (fetchPageError) {
    throw fetchPageError
  }

  type Singular<T> = T extends any[] ? unknown : T

  // We use checksum to determine if this page & its sections need to be regenerated
  if (!shouldRefresh && existingPage !== null && existingPage.checksum === checksum) {
    const existingParentPage = existingPage.parentPage?.length === 1 ? existingPage.parentPage[0] : undefined;
    // If parent page changed, update it
    if (typeof existingParentPage?.path === 'string' && existingParentPage?.path !== parentPath) {
      console.log(`[${path}] Parent page has changed. Updating to '${parentPath}'...`)
      const { error: fetchParentPageError, data: parentPage } = await supabaseClient
        .from('nods_page')
        .select()
        .filter('path', 'eq', parentPath)
        .limit(1)
        .maybeSingle()

      if (fetchParentPageError) {
        throw fetchParentPageError
      }

      const { error: updatePageError } = await supabaseClient
        .from('nods_page')
        .update({ parent_page_id: parentPage?.id })
        .filter('id', 'eq', existingPage.id)

      if (updatePageError) {
        throw updatePageError
      }
    }
    continue
  }

  if (existingPage) {
    if (!shouldRefresh) {
      console.log(
        `[${path}] Docs have changed, removing old page sections and their embeddings`
      )
    } else {
      console.log(`[${path}] Refresh flag set, removing old page sections and their embeddings`)
    }

    const { error: deletePageSectionError } = await supabaseClient
      .from('nods_page_section')
      .delete()
      .filter('page_id', 'eq', existingPage.id)

    if (deletePageSectionError) {
      throw deletePageSectionError
    }
  }

  const { error: fetchParentPageError, data: parentPage } = await supabaseClient
    .from('nods_page')
    .select()
    .filter('path', 'eq', parentPath)
    .limit(1)
    .maybeSingle()

  if (fetchParentPageError) {
    throw fetchParentPageError
  }

  // Create/update page record. Intentionally clear checksum until we
  // have successfully generated all page sections.
  const { error: upsertPageError, data: page } = await supabaseClient
    .from('nods_page')
    .upsert(
      {
        checksum: null,
        path,
        type,
        source,
        meta,
        parent_page_id: parentPage?.id,
      },
      { onConflict: 'path' }
    )
    .select()
    .limit(1)
    .single()

  if (upsertPageError) {
    throw upsertPageError
  }

  console.log(`[${path}] Adding ${sections.length} page sections (with embeddings)`)
  for (const { slug, heading, content } of sections) {
    // OpenAI recommends replacing newlines with spaces for best results (specific to embeddings)
    const input = content.replace(/\n/g, ' ')

    try {
      const configuration = new Configuration({
        apiKey: process.env.OPENAI_KEY,
      })
      const openai = new OpenAIApi(configuration)

      const embeddingResponse = await openai.createEmbedding({
        model: 'text-embedding-ada-002',
        input,
      })

      if (embeddingResponse.status !== 200) {
        throw new Error(inspect(embeddingResponse.data, false, 2))
      }

      const [responseData] = embeddingResponse.data.data

      const { error: insertPageSectionError, data: pageSection } = await supabaseClient
        .from('nods_page_section')
        .insert({
          page_id: page.id,
          slug,
          heading,
          content,
          token_count: embeddingResponse.data.usage.total_tokens,
          embedding: responseData.embedding,
        })
        .select()
        .limit(1)
        .single()

      if (insertPageSectionError) {
        throw insertPageSectionError
      }
    } catch (err) {
      // TODO: decide how to better handle failed embeddings
      console.error(
        `Failed to generate embeddings for '${path}' page section starting with '${input.slice(
          0,
          40
        )}...'`
      )

      throw err
    }
  }

  // Set page checksum so that we know this page was stored successfully
  const { error: updatePageError } = await supabaseClient
    .from('nods_page')
    .update({ checksum })
    .filter('id', 'eq', page.id)

  if (updatePageError) {
    throw updatePageError
  }
} catch (err) {
  console.error(
    `Page '${path}' or one/multiple of its page sections failed to store properly. Page has been marked with null checksum to indicate that it needs to be re-generated.`
  )
  console.error(err)
}

}

console.log('Embedding generation complete')
}

async function main() {
await generateEmbeddings()
}

main().catch((err) => console.error(err))

`

Modify code to implement streaming (for serverless)

Feature request

Streaming implementation when hosted on vercel

Is your feature request related to a problem? Please describe.

Vercel Serverless doesn't inherently provide streaming capabilities. So when deploying to vercel the response does not stream in (like it does on local dev environment)

A clear and concise description of what you want and what your use case is.
For the same streaming capabilities I see on local dev to work when hosted on vercel.

Describe the solution you'd like

Vercel Solution
The above appears to be the explanation of how to make streaming work.. However I'm not able to implement this, As we are using this "useCompletion" hook here, so not sure how to modify code to get this to work.

Reply with images

Feature request

Being able to display actual markdown would be cool, nice to have image links in the docs mdx files, and then ask gpt to try include markdown image links where appropriate.

I can get GPT to include the ![Alt text](URL or file path) images, but the response isn't actually displaying markdown.

Usage of gpt-3.5-turbo model

Hello,

I was trying to see if I can modify the model from text-davinci-003 to gpt-3.5-turbo in vector search but noticed that the app doesn't work anymore and keep getting search errors.
Is it any error from my end or some other issue that I am unaware of

Cannot generate embeddings

Bug report

antonio@Antonios-MacBook-Pro nextjs-openai-doc-search % pnpm run embeddings

> [email protected] embeddings /Users/antonio/Desktop/nextjs-openai-doc-search
> tsx lib/generate-embeddings.ts

Discovered 1 pages
Checking which pages are new or have changed
Page '/docs/openai_embeddings' or one/multiple of its page sections failed to store properly. Page has been marked with null checksum to indicate that it needs to be re-generated.
{
  code: 'PGRST116',
  details: 'The result contains 0 rows',
  hint: null,
  message: 'JSON object requested, multiple (or no) rows returned'
}
Embedding generation complete

Describe the bug

Cannot generate embeddings when running pnpm run embeddings.

To Reproduce

  1. Set up a local project that is connected to a remote Supabase project.
  2. Run pnpm run embeddings locally.

Expected behavior

Successful generation of embeddings.

System information

  • OS: macOS
  • Version of supabase-js: ^2.13.0
  • Version of Node.js: 18.15.10

Long replies breaks the app

If the app gives a lengthy reply, the dialogue goes full screen, but is not scrollable nor is the browser zoomable.

I've tried using some tailwinds overflow-auto and overflow-scrolls. but doesn't seem to change anything.

Surely this has been experienced by other users when lengthy replies are given >?

Sorry, I don't know how to help with that.

Bug report

Describe the bug

Followed setup instructions and the only responses I get are "Sorry, I don't know how to help with that."

Additional context

There are no additional error messages in the console.

image

Addressing Runtime Error on Initial Project Setup

Hello,

I cloned and set up the project following the provided instructions. However, upon running the project, I encountered a runtime error as shown below:

Unhandled Runtime Error
Error: {"error":"There was an error processing your request"}

Call Stack
eval
node_modules/.pnpm/[email protected][email protected]/node_modules/ai/react/dist/index.mjs (301:0)
Generator.next
<anonymous>
fulfilled
node_modules/.pnpm/[email protected][email protected]/node_modules/ai/react/dist/index.mjs (22:0)

It seems like there might be a missing step in the setup instructions regarding resolving this error. I believe it would be helpful for other developers if the documentation could be updated to address this issue. I appreciate the effort on this project and thank you in advance for looking into this!

Best regards

Error: `Failed to match page sections: {"code":"PGRST301","details":null,"hint":null,"message":"JWSError JWSInvalidSignature"}`

First, thanks for the awesome template - I learned a bunch in a very short time!

Everything works perfectly for me, apart from running the instance locally.

After running all the steps in the README, I get this error when submitting a query: Failed to match page sections: "code":"PGRST301","details":null,"hint":null,"message":"JWSError JWSInvalidSignature"}

I cant fix seem to fix it until now and any help is appreciated!

Error: Cannot find module 'openai'

Bug report

The Deploy to Vercel build comes up with the following error:

const err = new Error(message);
Error: Cannot find module 'openai'
Require stack:
- /vercel/path0/lib/generate-embeddings.ts
at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15)
at u.default._resolveFilename (/vercel/path0/node_modules/.pnpm/@[email protected]/node_modules/@esbuild-kit/cjs-loader/dist/index.js:1:1519)
at Module._load (node:internal/modules/cjs/loader:920:27)
at Module.require (node:internal/modules/cjs/loader:1141:19)
at require (node:internal/modules/cjs/helpers:110:18)
at updatePageError (/vercel/path0/lib/generate-embeddings.ts:13:8)
at Object.<anonymous> (/vercel/path0/lib/generate-embeddings.ts:493:41)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Object.F (/vercel/path0/node_modules/.pnpm/@[email protected]/node_modules/@esbuild-kit/cjs-loader/dist/index.js:1:941)
at Module.load (node:internal/modules/cjs/loader:1117:32) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/vercel/path0/lib/generate-embeddings.ts' ]
}
Node.js v18.15.0
ELIFECYCLE  Command failed with exit code 1.

To Fix

  • clone your fork
  • pnpm install openai
  • git push

Comments

  • Noticed that "openai-edge": "^1.1.0" was installed and not "openai": "^3.3.0"
  • Builds runs fine on Vercel after the fix
    • 1 warning '39:6 Warning: React Hook React.useEffect has a missing dependency: 'handleModalToggle'. Either include it or remove the dependency array. react-hooks/exhaustive-deps'
Running build in Cleveland, USA (East) – cle1
--
Cloning github.com/windhamdavid/nextjs-openai-doc-search-starter (Branch: main, Commit: 2b7881b)
Previous build cache not available
Cloning completed: 518.09ms
Running "vercel build"
Vercel CLI 30.2.3
Detected `pnpm-lock.yaml` version 6 generated by pnpm 8...
Installing dependencies...
Lockfile is up to date, resolution step is skipped
Progress: resolved 1, reused 0, downloaded 0, added 0
Packages: +525
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /vercel/.local/share/pnpm/store/v3
Virtual store is at:             node_modules/.pnpm
Progress: resolved 525, reused 0, downloaded 57, added 53
Progress: resolved 525, reused 0, downloaded 138, added 133
Progress: resolved 525, reused 0, downloaded 301, added 294
Progress: resolved 525, reused 0, downloaded 411, added 410
Progress: resolved 525, reused 0, downloaded 513, added 507
Progress: resolved 525, reused 0, downloaded 521, added 521
Progress: resolved 525, reused 0, downloaded 523, added 523
Progress: resolved 525, reused 0, downloaded 524, added 523
.../[email protected]/node_modules/es5-ext postinstall$  node -e "try{require('./_postinstall')}catch(e){}" \|\| exit 0
.../node_modules/bufferutil install$ node-gyp-build
.../node_modules/utf-8-validate install$ node-gyp-build
.../[email protected]/node_modules/es5-ext postinstall: Done
.../node_modules/utf-8-validate install: Done
.../node_modules/bufferutil install: Done
.../[email protected]/node_modules/esbuild postinstall$ node install.js
Progress: resolved 525, reused 0, downloaded 525, added 525, done
.../[email protected]/node_modules/esbuild postinstall: Done
 
dependencies:
+ @radix-ui/react-dialog 1.0.3
+ @radix-ui/react-label 2.0.1
+ @supabase/supabase-js 2.13.0
+ @types/node 18.15.10
+ @types/react 18.0.30
+ @types/react-dom 18.0.11
+ ai 2.1.3
+ class-variance-authority 0.4.0
+ clsx 1.2.1
+ cmdk 0.2.0
+ common-tags 1.8.2
+ eslint 8.36.0
+ eslint-config-next 13.2.4
+ github-slugger 2.0.0
+ gpt3-tokenizer 1.1.5
+ lucide-react 0.128.0
+ mdast 3.0.0
+ mdast-util-from-markdown 1.3.0
+ mdast-util-mdx 2.0.1
+ mdast-util-to-markdown 1.5.0
+ mdast-util-to-string 3.1.1
+ micromark-extension-mdxjs 1.0.0
+ next 13.2.4
+ openai 3.3.0
+ openai-edge 1.1.0
+ react 18.2.0
+ react-dom 18.2.0
+ tailwind-merge 1.10.0
+ tailwindcss-animate 1.0.5
+ typescript 4.9.5
+ unist-builder 3.0.1
+ unist-util-filter 4.0.1
+ yargs 17.7.2
 
devDependencies:
+ @types/common-tags 1.8.1
+ @types/estree 1.0.0
+ @types/mdast 3.0.11
+ @types/yargs 17.0.24
+ autoprefixer 10.4.14
+ dotenv 16.0.3
+ postcss 8.4.21
+ prettier 2.8.7
+ tailwindcss 3.2.7
+ tsx 3.12.6
 
Done in 9.7s
Detected Next.js version: 13.2.4
Running "pnpm run build"
 
> [email protected] build /vercel/path0
> pnpm run embeddings && next build
 
 
> [email protected] embeddings /vercel/path0
> tsx lib/generate-embeddings.ts
 
Discovered 1 pages
Checking which pages are new or have changed
[/docs/openai_embeddings] Adding 2 page sections (with embeddings)
Embedding generation complete
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
 
info  - Linting and checking validity of types...
 
./components/SearchDialog.tsx
39:6  Warning: React Hook React.useEffect has a missing dependency: 'handleModalToggle'. Either include it or remove the dependency array.  react-hooks/exhaustive-deps
 
info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
info  - Creating an optimized production build...
<w> [webpack.cache.PackFileCacheStrategy] Serializing big strings (1673kiB) impacts deserialization performance (consider using Buffer instead and decode when needed)
info  - Compiled successfully
info  - Collecting page data...
info  - Generating static pages (0/3)
info  - Generating static pages (3/3)
info  - Finalizing page optimization...
 
Route (pages)                              Size     First Load JS
┌ ○ /                                      30 kB           103 kB
├   └ css/bff950a31bfd5d70.css             1.34 kB
├   /_app                                  0 B            73.5 kB
├ ○ /404                                   182 B          73.7 kB
└ ℇ /api/vector-search                     0 B            73.5 kB
+ First Load JS shared by all              78.1 kB
├ chunks/framework-ac88a2a245aea9ab.js   45.2 kB
├ chunks/main-3c0baa89327dc7f7.js        27 kB
├ chunks/pages/_app-6653cdf85263f45a.js  298 B
├ chunks/webpack-5146130448d8adf7.js     944 B
└ css/0b6a4193ead184fe.css               4.64 kB
 
ℇ  (Streaming)  server-side renders with streaming (uses React 18 SSR streaming or Server Components)
○  (Static)     automatically rendered as static HTML (uses no initial props)
 
Collected static files (public/, static/, .next/static): 3.486ms
Build Completed in /vercel/output [34s]
Deploying outputs...
Deployment completed
Uploading build cache [86.90 MB]...
Build cache uploaded: 2.141s


Anway to ask it what it knows?

Feature request

I think it would be neat if there was a way I could ask it what it Knows. Is there anyway I could do this, I assume i would need a way to put the data in the DB dyamically of the pages it knows?

Deployment Fails When Trying to Deploy Template From Vercel.ai Page

Bug report

Describe the bug

When I go to vercel.ai and choose this template to deploy, and start the process, it fails immediately and wont deploy with alteration to build step or change in code. If I change it to look to the right directory, the pages directory, I get another build error in api/vector-search.js because there are unsupported modules

To Reproduce

  1. Go to vercel.ai
  2. Scroll down to and click on 'OpenAI Doc Search Start'
  3. Click Deploy
  4. Go through deployment steps on the vercel dashboard (set up a supabase project and then get an openai key)
  5. Then deploy
  6. In a second or so you will see build failed due 'The specified Root Directory 'app' does not exist'
  7. Go into the project settings for you newly created project
  8. Adjust the root directory to be pages
  9. Redeploy
  10. You will then see, after a few promising seconds, The edge function 'api/vector-search.js' is referencing unsupported modules'

Expected behavior

  • The template to be deployed.

Screenshots

  • Build Fail 1

Screen Shot 2023-04-08 at 10 36 09 AM

  • Build Fail 2

Screen Shot 2023-04-08 at 10 35 47 AM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.