Created
October 8, 2023 06:33
-
-
Save anand-mukul/1a813bd686f7faff2e1793b6580fa539 to your computer and use it in GitHub Desktop.
Remember to replace PINECONE INDEX NAME AND ENVIRONMENT, also check .env with app.pinecone.io
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
import { db } from '@/db'; | |
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server'; | |
import { createUploadthing, type FileRouter } from 'uploadthing/next'; | |
import { PDFLoader } from 'langchain/document_loaders/fs/pdf'; | |
import { OpenAIEmbeddings } from 'langchain/embeddings/openai'; | |
import { PineconeStore } from 'langchain/vectorstores/pinecone'; | |
import { pinecone } from '@/lib/pinecone'; | |
import { getUserSubscriptionPlan } from '@/lib/stripe'; | |
import { PLANS } from '@/config/stripe'; | |
const f = createUploadthing(); | |
const middleware = async () => { | |
const { getUser } = getKindeServerSession(); | |
const user = getUser(); | |
if (!user || !user.id) throw new Error('Unauthorized'); | |
const subscriptionPlan = await getUserSubscriptionPlan(); | |
return { subscriptionPlan, userId: user.id }; | |
}; | |
const onUploadComplete = async ({ | |
metadata, | |
file, | |
}: { | |
metadata: Awaited<ReturnType<typeof middleware>>; | |
file: { | |
key: string; | |
name: string; | |
url: string; | |
}; | |
}) => { | |
const isFileExist = await db.file.findFirst({ | |
where: { | |
key: file.key, | |
}, | |
}); | |
if (isFileExist) return; | |
const createdFile = await db.file.create({ | |
data: { | |
key: file.key, | |
name: file.name, | |
userId: metadata.userId, | |
url: `https://uploadthing-prod.s3.us-west-2.amazonaws.com/${file.key}`, | |
uploadStatus: 'PROCESSING', | |
}, | |
}); | |
try { | |
const response = await fetch( | |
`https://uploadthing-prod.s3.us-west-2.amazonaws.com/${file.key}` | |
); | |
const blob = await response.blob(); | |
const loader = new PDFLoader(blob); | |
const pageLevelDocs = await loader.load(); | |
const pagesAmt = pageLevelDocs.length; | |
const { subscriptionPlan } = metadata; | |
const { isSubscribed } = subscriptionPlan; | |
const allowedPages = isSubscribed | |
? PLANS.find((plan) => plan.name === 'Pro')!.pagesPerPdf | |
: PLANS.find((plan) => plan.name === 'Free')!.pagesPerPdf; | |
if (pagesAmt > allowedPages) { | |
await db.file.update({ | |
data: { | |
uploadStatus: 'FAILED', | |
}, | |
where: { | |
id: createdFile.id, | |
}, | |
}); | |
} else { | |
const pineconeIndex = pinecone.Index('INDEXNAME'); //check on app.pinecone.io | |
const embeddings = new OpenAIEmbeddings({ | |
openAIApiKey: process.env.OPENAI_API_KEY, | |
}); | |
await PineconeStore.fromDocuments(pageLevelDocs, embeddings, { | |
pineconeIndex, | |
namespace: createdFile.id, | |
}); | |
await db.file.update({ | |
data: { | |
uploadStatus: 'SUCCESS', | |
}, | |
where: { | |
id: createdFile.id, | |
}, | |
}); | |
} | |
} catch (err) { | |
await db.file.update({ | |
data: { | |
uploadStatus: 'FAILED', | |
}, | |
where: { | |
id: createdFile.id, | |
}, | |
}); | |
} | |
}; | |
export const ourFileRouter: FileRouter = { | |
freePlanUploader: f({ pdf: { maxFileSize: '4MB' } }) | |
.middleware(middleware) | |
.onUploadComplete(onUploadComplete), | |
proPlanUploader: f({ pdf: { maxFileSize: '16MB' } }) | |
.middleware(middleware) | |
.onUploadComplete(onUploadComplete), | |
}; | |
export type OurFileRouter = typeof ourFileRouter; |
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
import { Pinecone } from '@pinecone-database/pinecone'; | |
export const pinecone = new Pinecone({ | |
apiKey: process.env.PINECONE_API_KEY!, | |
environment: 'ENVIRONMENTNAME', //check on app.pinecone.io | |
}); |
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
import { db } from '@/db'; | |
import { openai } from '@/lib/openai'; | |
import { pinecone } 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) => { | |
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, | |
}, | |
}); | |
const embeddings = new OpenAIEmbeddings({ | |
openAIApiKey: process.env.OPENAI_API_KEY, | |
}); | |
const pineconeIndex = pinecone.Index('INDEXNAME'); //check on app.pinecone.io | |
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 contextMessages = formattedPrevMessages.map((message) => { | |
if (message.role === 'user') { | |
return `User: ${message.content}\n`; | |
} | |
return `Assistant: ${message.content}\n`; | |
}); | |
const context = `PREVIOUS CONVERSATION:\n${contextMessages.join('')}\n\nCONTEXT:\n${results.map((r) => r.pageContent).join('\n\n')}\nUSER INPUT: ${message}`; | |
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 conversation if needed) to answer the user\'s question in markdown format.', | |
}, | |
{ | |
role: 'user', | |
content: context, | |
}, | |
], | |
}); | |
const stream = OpenAIStream(response, { | |
async onCompletion(completion) { | |
await db.message.create({ | |
data: { | |
text: completion, | |
isUserMessage: false, | |
fileId, | |
userId, | |
}, | |
}); | |
}, | |
}); | |
return new StreamingTextResponse(stream); | |
}; |
it still gives me the same error too many pages in pdf
same
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
having a error on pineconeIndex in core.ts how to solve