Skip to content

Commit

Permalink
PDF upload
Browse files Browse the repository at this point in the history
  • Loading branch information
msveshnikov committed Mar 19, 2024
1 parent f44dc72 commit a7523d4
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ALLCHAT

Node.js backend and a React MUI frontend for an application that interacts with the Gemini Pro model, with history, image painting via Amazon Titan and markdown support. Written fully by _Claude 3 Sonnet_.
Node.js backend and a React MUI frontend for an application that interacts with the Gemini Pro model, with history, image painting by Amazon Titan, PDF upload and markdown support. Written fully by _Claude 3 Sonnet_.

![image](https://github.com/msveshnikov/allchat/assets/8682996/42b2e4f2-b91b-4712-8ef2-630ebb8919e9)

Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
Binary file modified public/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 19 additions & 2 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@ import rateLimit from "express-rate-limit";
import { getTextGemini } from "./gemini.js";
import { getImageTitan } from "./aws.js";
import hasPaintWord from "./paint.js";
import pdfParser from "pdf-parse";

const MAX_CONTEXT_LENGTH = 4000;

const app = express();
app.use(cors());
app.use(express.json());
app.use(express.json({ limit: "10mb" }));

morgan.token("body", (req, res) => {
const body = req.body;
if (body && typeof body === "object" && "pdfBytesBase64" in body) {
const clonedBody = { ...body };
clonedBody.pdfBytesBase64 = "<PDF_BYTES_REDACTED>";
return JSON.stringify(clonedBody);
}
return JSON.stringify(body);
});

morgan.token("body", (req) => JSON.stringify(req.body));
const loggerFormat = ":method :url :status :response-time ms - :res[content-length] :body";
app.use(morgan(loggerFormat));

Expand All @@ -26,8 +36,15 @@ app.post("/interact", async (req, res) => {
let userInput = req.body.input;
const chatHistory = req.body.chatHistory || [];
const temperature = req.body.temperature || 0.5;
const pdfBytesBase64 = req.body.pdfBytesBase64;

try {
if (pdfBytesBase64) {
const pdfBytes = Buffer.from(pdfBytesBase64, "base64");
const data = await pdfParser(pdfBytes);
userInput = data.text;
}

const contextPrompt = `${chatHistory
.map((chat) => `${chat.user}\n${chat.assistant}`)
.join("\n")}\n\nHuman: ${userInput}\nAssistant:`.slice(-MAX_CONTEXT_LENGTH);
Expand Down
33 changes: 32 additions & 1 deletion server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dotenv": "^16.4.5",
"express": "^4.18.3",
"express-rate-limit": "^7.2.0",
"morgan": "^1.10.0"
"morgan": "^1.10.0",
"pdf-parse": "1.1.1"
}
}
Empty file.
35 changes: 34 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Drawer from "@mui/material/SwipeableDrawer";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemText from "@mui/material/ListItemText";
import PDFUploader from "./PDFUploader";

const APP_URL =
process.env.NODE_ENV === "production" ? "https://allchat.online/api/interact" : "http://localhost:5000/interact";
Expand Down Expand Up @@ -138,6 +139,33 @@ function App() {
setDrawerOpen(false);
};

const handlePDFUpload = async (pdfData) => {
const pdfBytesBase64 = pdfData.split(",")[1];

// Send the base64-encoded PDF bytes to the server
const response = await fetch(APP_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
pdfBytesBase64,
chatHistory: chatHistory.map((h) => ({ user: h.user, assistant: h.assistant })),
}),
});

if (response.ok) {
const data = await response.json();
const newChatHistory = [
...chatHistory,
{ user: "PDF Document", assistant: data.textResponse, image: data.imageResponse },
];
setChatHistory(newChatHistory);
} else {
console.error("Error:", response.status);
}
};

return (
<>
<AppBar position="static">
Expand All @@ -162,7 +190,11 @@ function App() {
</ListItem>
))}
</List>
<ListItem button onClick={clearAllChatHistory} style={{ color:"white", backgroundColor: "#F50057" }}>
<ListItem
button
onClick={clearAllChatHistory}
style={{ color: "white", backgroundColor: "#F50057" }}
>
<ListItemText primary="Clear All" />
</ListItem>
</div>
Expand Down Expand Up @@ -213,6 +245,7 @@ function App() {
}
}}
/>
<PDFUploader onPDFUpload={handlePDFUpload} />
<Button variant="contained" color="primary" onClick={handleSubmit} style={{ marginLeft: 8 }}>
Send
</Button>
Expand Down
28 changes: 28 additions & 0 deletions src/PDFUploader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { IconButton, Tooltip } from "@mui/material";
import AttachFileIcon from "@mui/icons-material/AttachFile";

const PDFUploader = ({ onPDFUpload }) => {
const handleFileChange = (event) => {
const file = event.target.files[0];

if (file) {
const reader = new FileReader();
reader.onload = () => {
onPDFUpload(reader.result);
};
reader.readAsDataURL(file);
}
};

return (
<Tooltip title="Upload PDF">
<IconButton component="label" color="primary">
<input accept="application/pdf" type="file" onChange={handleFileChange} style={{ display: "none" }} />
<AttachFileIcon />
</IconButton>
</Tooltip>
);
};

export default PDFUploader;

0 comments on commit a7523d4

Please sign in to comment.