Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions app/api/document/[datasetId]/[documentId]/route.ts

This file was deleted.

2 changes: 1 addition & 1 deletion app/chatrooms/[chatroomId]/components/message-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ const MessageArea = ({
const askResult = await askLLM(classroomInfo, chatroomId, chatClient);
if (!askResult.clientCreationSuccess) {
if (!askResult.failedBecauseEmptyDataset) {
// TODO: ask result has more detailed error differntiations if we want to tell the user
// TODO: ask result has more detailed error differentiations if we want to tell the user
toast.error("Error sending communicating with LLM", {
description: "Please refresh and try again",
});
Expand Down
122 changes: 122 additions & 0 deletions app/classrooms/[classroomId]/augment/AugmentNotes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"use client";
import { useState, useRef } from "react";

import { Button } from "@shared/components/ui/button";
import { Input } from "@shared/components/ui/input";

import { FileText, Upload } from "lucide-react";
import { toast } from "sonner";

import pdfToText from "react-pdftotext";

import NotesViewer from "./NotesViewer";

export default function AugmentComponent({
classroomId,
}: {
classroomId: string;
}) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [isProcessing, setIsProcessing] = useState(false);
const [file, setFile] = useState<File | null>(null);
const inputFile = useRef<HTMLInputElement>(null);

const [notesContent, setNotesContent] = useState<string[]>([]);

const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const selectedFile = event.target.files?.[0];
if (!selectedFile) return;

// Double-check that file passed by user is markdown or pdf
const fileExtension = selectedFile.name.split(".").at(-1)?.toLowerCase();
if (
fileExtension !== "pdf" &&
fileExtension !== "md" &&
fileExtension !== "txt"
) {
toast.error("Invalid file format", {
description:
"Please upload a Markdown (.md), PDF (.pdf), or TXT (.txt) file",
});
return;
}

setFile(selectedFile);
};

const handleUpload = async () => {
if (file != null) {
const fileExtension = file.name.split(".").at(-1)?.toLowerCase();

let splitByLines: string[] = [];

// if txt or md
if (fileExtension == "txt" || fileExtension == "md") {
const endText: string = await file.text();
endText.replaceAll("\r", "");
splitByLines = endText.split("\n");
Comment thread
chenxin-yan marked this conversation as resolved.
Outdated

// if pdf
} else if (fileExtension == "pdf") {
splitByLines = await pdfToText(file)
.then((text) => {
return text.split(" ");
})
.catch((error) => {
console.error("Failed to extract text from pdf", error);
return [""];
});
}

setNotesContent(splitByLines);
}
};

return (
<div className="flex flex-col items-center justify-center gap-4 p-8">
<h1 className="text-3xl font-bold">Augment Notes</h1>

<p className="text-muted-foreground">
Upload your notes to get AI-powered enhancements and improvements
</p>

{notesContent.length == 0 ? (
<div className="flex items-center gap-2">
<Input
type="file"
onChange={handleFileChange}
ref={inputFile}
className="hidden"
accept=".md,.pdf,.txt"
/>
<Button
variant="outline"
size="lg"
className="cursor-pointer"
disabled={isProcessing}
onClick={() => inputFile.current?.click()}
>
{isProcessing ? (
<Upload className="mr-2 h-4 w-4 animate-spin" />
) : (
<FileText className="mr-2 h-4 w-4" />
)}
Upload Notes
</Button>
{file && (
<Button
variant="default"
size="lg"
onClick={handleUpload}
disabled={isProcessing}
>
Process Notes
</Button>
)}
</div>
) : (
<NotesViewer notesContent={notesContent} classroomId={classroomId} />
)}
</div>
);
}
152 changes: 152 additions & 0 deletions app/classrooms/[classroomId]/augment/AugumentActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"use server";

import { createClient } from "@shared/utils/supabase/server";
import {
ChatClientWithSession,
createChatClient,
sendMessage,
} from "@shared/lib/ragflow/chat/chat-client";

import { getUserAndClassroomData } from "@shared/lib/userContext/contextFetcher";

import { AugmentConfigTemplate } from "@shared/lib/ragflow/chat/chat-configs";

// import { revalidatePath } from "next/cache";
// import {
// ChatClientWithSession,
// createChatClient,
// deleteSession,
// sendMessage,
// } from "@shared/lib/ragflow/chat/chat-client";
// import { createDatasetClient } from "@shared/lib/ragflow/dataset-client";

export async function createNotesClient(classroomId: string) {
//create a session for that set of notes

//first get the dataset ID
const supabase = await createClient();
const { data, error } = await supabase
.from("Classrooms")
.select()
.eq("id", Number(classroomId))
.single();

if (error) {
console.error("Error fetching classroom data:", error);
throw new Error("Error fetching classroom data");
}

const datasetId: string = data?.ragflow_dataset_id || "";

// console.log("datasetId", datasetId);
// console.log("classroomId", classroomId);

// const params = { dataset_ids: [datasetId], name: datasetId };

// const res = await fetch(`${process.env.RAGFLOW_API_URL}/v1/chats`, {
// method: "POST", // or 'PUT'
// headers: {
// Authorization: `Bearer ${process.env.RAGFLOW_API_KEY}`,
// "Content-Type": "application/json",
// },
// body: JSON.stringify(params),
// });

// console.log("res", res);

const userAndClassData = await getUserAndClassroomData();

const resClient = await createChatClient(
{
...AugmentConfigTemplate,
associatedClassroomName: "Classroom",
primaryKeyValuesAssistant: [{ key: "id", value: classroomId }],
primaryKeyValuesSession: [
{ key: "classroom_id", value: classroomId },
{ key: "user_id", value: userAndClassData?.userData.id },
],
datasets: [datasetId],
}
// classroomInfo.chat_assistant_id
);

if (!resClient.client) {
console.error("Client is null");
throw new Error("Invalid chat client instance");
}

if (!("sessionId" in resClient.client)) {
console.error("Client not of correct type");
throw new Error("Invalid chat client instance: Missing sessionId");
}
const chatClient: ChatClientWithSession = resClient.client;

// console.log(
// "chatClient",
// chatClient.clientConfig.modelSettings.promptSettings
// );

// console.log("datasetId", datasetId);

return chatClient;
}

export async function reviseNotesLine(
chatClient: ChatClientWithSession,
passedLine: string
) {
const passMessage: string = `Below is a line of text notes taken by a student.
Please augment these notes with you comments and revise them primarily based on accuracy.
Only change the parts you want to revise.
Do not rewrite the notes, simply make small edits for correctness.
Do not make style and diction revisions.
Return the notes exactly as given if they are already correct.
If they notes are accurate, leave them exactly as is.
Also, please do not use any markdown formatting.
${passedLine}
`;

const messageResponse = await sendMessage(chatClient, passMessage);

if (!messageResponse.ragflowCallSuccess) {
console.error("Error sending message");
throw new Error("Error sending message");
}

const revisedNotes: string = messageResponse.response
.replace("Notes: ", "")
.replaceAll("##0$$\n", "");
// console.log("revisedNotes", revisedNotes);

const reason: string = await getAugmentReason(
chatClient,
passedLine,
revisedNotes
);

return [revisedNotes, reason];
}

export async function getAugmentReason(
chatClient: ChatClientWithSession,
originalNotes: string,
augmentedNotes: string
) {
const passMessage: string = `In a previous message, you augmented the following notes:
"${originalNotes}"
to
"${augmentedNotes}"

Can you explain why you made this change?
Please do not use any markdown formatting in your response.
`;

const messageResponse = await sendMessage(chatClient, passMessage);

if (!messageResponse.ragflowCallSuccess) {
console.error("Error getting explanation");
throw new Error("Error getting explanation");
}

return messageResponse.response;
}
Empty file.
Loading
Loading