From 1900a7a93ba03c4a708de75ab134100b1ca17d22 Mon Sep 17 00:00:00 2001 From: Naqi Syed Date: Tue, 3 Oct 2023 00:21:14 +0500 Subject: [PATCH] chat schema and apis are added and updated --- app/api/chat/init/route.ts | 30 ++++++++++ app/api/chat/route.ts | 58 +++++++++++++++++-- .../migration.sql | 20 +++++++ .../migration.sql | 8 +++ .../migration.sql | 9 +++ prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 9 +++ utils/chat.ts | 4 ++ 8 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 app/api/chat/init/route.ts create mode 100644 prisma/migrations/20231002122742_added_chat_history_table/migration.sql create mode 100644 prisma/migrations/20231002132845_added_title_column_in_chathistory_table/migration.sql create mode 100644 prisma/migrations/20231002133243_updated_chathistory_table/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 utils/chat.ts diff --git a/app/api/chat/init/route.ts b/app/api/chat/init/route.ts new file mode 100644 index 0000000..060c87a --- /dev/null +++ b/app/api/chat/init/route.ts @@ -0,0 +1,30 @@ +import { NextRequest, NextResponse } from "next/server" +import { initialChatMessage } from "@/utils/chat" + +import { createPrisma } from "@/lib/prisma" + +export async function POST(request: Request) { + const body = await request.json() + const { childId, childContext } = body + + const credentials = { + supabaseDatabaseUrl: process.env.DATABASE_URL, + } + + const childInitialContextMessage = [ + { + name: initialChatMessage.name, + text: `${initialChatMessage.text} ${childContext}`, + }, + ] + const prisma = createPrisma({ url: credentials.supabaseDatabaseUrl }) + const data = await prisma.chatHistory.create({ + data: { + childId: childId, + messages: childInitialContextMessage, + }, + }) + + return NextResponse.json({ data }) +} + diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 2952780..6f77b97 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,9 +1,12 @@ +import { NextRequest, NextResponse } from "next/server" +import { Prisma } from "@prisma/client" + import { getChain } from "@/lib/langchain/chain" import { ModelHandler } from "@/lib/langchain/model" import { getPineconeStore } from "@/lib/langchain/vectorstores/pinecone" -import { NextRequest, NextResponse } from "next/server" +import { createPrisma } from "@/lib/prisma" -export const runtime = "edge" +// export const runtime = "edge" export async function POST(request: NextRequest) { const body = await request.json() @@ -17,7 +20,7 @@ export async function POST(request: NextRequest) { supabaseUrl: process.env.SUPABASE_URL, supabaseBucket: process.env.SUPABASE_BUCKET, supabaseDatabaseUrl: process.env.DATABASE_URL, - supabaseDirectUrl: process.env.DIRECT_URL + supabaseDirectUrl: process.env.DIRECT_URL, } if ( !credentials || @@ -28,7 +31,22 @@ export async function POST(request: NextRequest) { return NextResponse.redirect("/credentials") } - const { prompt, messages: history } = body + const { prompt, chatId } = body + + //Get history from supabase against child id + const prisma = createPrisma({ url: credentials.supabaseDatabaseUrl }) + const historyFromDB = await prisma.chatHistory.findFirst({ + where: { + id: chatId, + }, + }) + + //Construct an array of message history to send it to model + let messageHistory = [] + const chatMessages = historyFromDB.messages as Prisma.JsonArray + chatMessages.map((message) => { + messageHistory.push(message) + }) // OpenAI recommends replacing newlines with spaces for best results const sanitizedQuestion = `${prompt.trim().replaceAll("\n", " ")}` @@ -41,7 +59,37 @@ export async function POST(request: NextRequest) { const modelHandler = new ModelHandler(writer) const model = modelHandler.getModel(credentials.openaiApiKey) - const response = getChain(model, vectorStore, sanitizedQuestion, history) + const response = getChain( + model, + vectorStore, + sanitizedQuestion, + messageHistory + ) + + // Push current prompt to message history array + messageHistory.push({ + name: "human", + text: prompt, + }) + + //Resolve the promise returned by langchain + Promise.resolve(response).then(async (res) => { + //Push response to message history array + messageHistory.push({ + name: "ai", + text: res.text, + }) + + //Update message history array in table against chatId + await prisma.chatHistory.update({ + where: { + id: chatId, + }, + data: { + messages: messageHistory, + }, + }) + }) return new NextResponse(stream.readable, { headers: { diff --git a/prisma/migrations/20231002122742_added_chat_history_table/migration.sql b/prisma/migrations/20231002122742_added_chat_history_table/migration.sql new file mode 100644 index 0000000..952a602 --- /dev/null +++ b/prisma/migrations/20231002122742_added_chat_history_table/migration.sql @@ -0,0 +1,20 @@ +-- CreateTable +CREATE TABLE "Documents" ( + "id" TEXT NOT NULL, + "name" TEXT, + "url" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Documents_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ChatHistory" ( + "id" TEXT NOT NULL, + "childId" TEXT, + "messages" JSONB NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ChatHistory_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/migrations/20231002132845_added_title_column_in_chathistory_table/migration.sql b/prisma/migrations/20231002132845_added_title_column_in_chathistory_table/migration.sql new file mode 100644 index 0000000..6c37b0f --- /dev/null +++ b/prisma/migrations/20231002132845_added_title_column_in_chathistory_table/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Added the required column `title` to the `ChatHistory` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "ChatHistory" ADD COLUMN "title" TEXT NOT NULL; diff --git a/prisma/migrations/20231002133243_updated_chathistory_table/migration.sql b/prisma/migrations/20231002133243_updated_chathistory_table/migration.sql new file mode 100644 index 0000000..a64cc60 --- /dev/null +++ b/prisma/migrations/20231002133243_updated_chathistory_table/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - Made the column `childId` on table `ChatHistory` required. This step will fail if there are existing NULL values in that column. + +*/ +-- AlterTable +ALTER TABLE "ChatHistory" ALTER COLUMN "childId" SET NOT NULL, +ALTER COLUMN "title" DROP NOT NULL; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d7b1204..c5cab1d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,4 +16,13 @@ model Documents { name String? url String created_at DateTime @default(now()) +} + +model ChatHistory { + id String @id @default(cuid()) + childId String + title String? + messages Json + created_at DateTime @default(now()) + updated_at DateTime @default(now()) } \ No newline at end of file diff --git a/utils/chat.ts b/utils/chat.ts new file mode 100644 index 0000000..a72bcb4 --- /dev/null +++ b/utils/chat.ts @@ -0,0 +1,4 @@ +export const initialChatMessage = { + name: "system", + text: "Act as an expert. Reply to questions about given data. Self reflect on your answers. Following is some of my child's information and you need to answer all my questions considering this context, ", +}