joschan21 / quill

Quill - A Modern SaaS-Platform Built With Next.js 13
1.91k stars 514 forks source link

Type error: Argument of type 'Stream<ChatCompletionChunk>' is not assignable to parameter of type 'Response #5

Open kennedywee opened 1 year ago

kennedywee commented 1 year ago

Hi, I tried to deploy the project and then I encountered this error. Can anyone help me? Thank you

image
anand-mukul commented 1 year ago

PATH::\src\app\api\message\route.ts (Also read inline comment)

import { db } from '@/db'
import { openai } from '@/lib/openai'
import { getPineconeClient } from '@/lib/pinecone'
import { SendMessageValidator } from '@/lib/validators/SendMessageValidator'
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server'
import { OpenAIEmbeddings } from 'langchain/embeddings/openai'
import { PineconeStore } from 'langchain/vectorstores/pinecone'
import { NextRequest } from 'next/server'

import { OpenAIStream, StreamingTextResponse } from 'ai'

export const POST = async (req: NextRequest) => {
  // endpoint for asking a question to a pdf file

  const body = await req.json()

  const { getUser } = getKindeServerSession()
  const user = getUser()

  const { id: userId } = user

  if (!userId)
    return new Response('Unauthorized', { status: 401 })

  const { fileId, message } =
    SendMessageValidator.parse(body)

  const file = await db.file.findFirst({
    where: {
      id: fileId,
      userId,
    },
  })

  if (!file)
    return new Response('Not found', { status: 404 })

  await db.message.create({
    data: {
      text: message,
      isUserMessage: true,
      userId,
      fileId,
    },
  })

  // 1: vectorize message
  const embeddings = new OpenAIEmbeddings({
    openAIApiKey: process.env.OPENAI_API_KEY,
  })

  const pinecone = await getPineconeClient() //Must add this line and also check this in ..\src\app\api\uploadthing\core.ts
  const pineconeIndex = pinecone.Index('YourPineconeIndexName') //Replace it your pinecone index name

  const vectorStore = await PineconeStore.fromExistingIndex(
    embeddings,
    {
       //@ts-ignore
      pineconeIndex,
      namespace: file.id,
    }
  )

  const results = await vectorStore.similaritySearch(
    message,
    4
  )

  const prevMessages = await db.message.findMany({
    where: {
      fileId,
    },
    orderBy: {
      createdAt: 'asc',
    },
    take: 6,
  })

  const formattedPrevMessages = prevMessages.map((msg) => ({
    role: msg.isUserMessage
      ? ('user' as const)
      : ('assistant' as const),
    content: msg.text,
  }))

  const response = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    temperature: 0,
    stream: true,
    messages: [
      {
        role: 'system',
        content:
          'Use the following pieces of context (or previous conversaton if needed) to answer the users question in markdown format.',
      },
      {
        role: 'user',
        content: `Use the following pieces of context (or previous conversaton if needed) to answer the users question in markdown format. \nIf you don't know the answer, just say that you don't know, don't try to make up an answer.

  \n----------------\n

  PREVIOUS CONVERSATION:
  ${formattedPrevMessages.map((message) => {
    if (message.role === 'user')
      return `User: ${message.content}\n`
    return `Assistant: ${message.content}\n`
  })}

  \n----------------\n

  CONTEXT:
  ${results.map((r) => r.pageContent).join('\n\n')}

  USER INPUT: ${message}`,
      },
    ],
  })

  const stream = OpenAIStream(response, {
    async onCompletion(completion) {
      await db.message.create({
        data: {
          text: completion,
          isUserMessage: false,
          fileId,
          userId,
        },
      })
    },
  })

  return new StreamingTextResponse(stream)
}

Also ADD THIS::\src\lib\pinecone.ts

import { PineconeClient } from '@pinecone-database/pinecone'

  export const getPineconeClient = async () => {
    const client = new PineconeClient()

    await client.init({
      apiKey: process.env.PINECONE_API_KEY!,
      environment: 'asia-southeast1-gcp-free', //Replace it you Pinecone Environment, Check pinecone website
    })

    return client
  }
JiangShuuu commented 1 year ago

Ad-hoc solution

  // @ts-ignore    <-- add this
  const stream = OpenAIStream(response, {
    async onCompletion(completion) {
      await db.message.create({
        data: {
          text: completion,
          isUserMessage: false,
          fileId,
          userId
        }
      })
    }
  })