修改: app/api/bedrock.ts

删除:     app/api/bedrock/models.ts
	删除:     app/api/bedrock/utils.ts
	修改:     app/client/platforms/bedrock.ts
	删除:     app/components/chat-actions.tsx
	修改:     app/components/chat.tsx
	修改:     app/constant.ts
	删除:     app/icons/document.svg
This commit is contained in:
glay
2024-11-04 16:24:10 +08:00
parent dca4a0e48f
commit fc391168e9
8 changed files with 355 additions and 1158 deletions

View File

@@ -1,188 +0,0 @@
import { ChatActions as Actions } from "./chat";
import DocumentIcon from "../icons/document.svg";
import LoadingButtonIcon from "../icons/loading.svg";
import { ServiceProvider } from "../constant";
import { useChatStore } from "../store";
import { showToast } from "./ui-lib";
import { MultimodalContent, MessageRole } from "../client/api";
import { ChatMessage } from "../store/chat";
export function ChatActions(props: Parameters<typeof Actions>[0]) {
const chatStore = useChatStore();
const currentProviderName =
chatStore.currentSession().mask.modelConfig?.providerName;
const isBedrockProvider = currentProviderName === ServiceProvider.Bedrock;
async function uploadDocument() {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = ".pdf,.csv,.doc,.docx,.xls,.xlsx,.html,.txt,.md";
fileInput.onchange = async (event: any) => {
const file = event.target.files[0];
if (!file) return;
props.setUploading(true);
try {
// Get file extension and MIME type
const format = file.name.split(".").pop()?.toLowerCase() || "";
const supportedFormats = [
"pdf",
"csv",
"doc",
"docx",
"xls",
"xlsx",
"html",
"txt",
"md",
];
if (!supportedFormats.includes(format)) {
throw new Error("Unsupported file format");
}
// Map file extensions to MIME types
const mimeTypes: { [key: string]: string } = {
pdf: "application/pdf",
csv: "text/csv",
doc: "application/msword",
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
xls: "application/vnd.ms-excel",
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
html: "text/html",
txt: "text/plain",
md: "text/markdown",
};
// Convert file to base64
const base64 = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
if (!e.target?.result) return reject("Failed to read file");
// Get just the base64 data without the data URL prefix
const base64 = (e.target.result as string).split(",")[1];
resolve(base64);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
// Format file size
const size = file.size;
let sizeStr = "";
if (size < 1024) {
sizeStr = size + " B";
} else if (size < 1024 * 1024) {
sizeStr = (size / 1024).toFixed(2) + " KB";
} else {
sizeStr = (size / (1024 * 1024)).toFixed(2) + " MB";
}
// Create document content
const content: MultimodalContent[] = [
{
type: "text",
text: `Document: ${file.name} (${sizeStr})`,
},
{
type: "document",
document: {
format,
name: file.name,
source: {
bytes: base64,
media_type: mimeTypes[format] || `application/${format}`,
},
},
},
];
// Send content to Bedrock
const session = chatStore.currentSession();
const modelConfig = session.mask.modelConfig;
const api = await import("../client/api").then((m) =>
m.getClientApi(modelConfig.providerName),
);
// Create user message
const userMessage: ChatMessage = {
id: Date.now().toString(),
role: "user" as MessageRole,
content,
date: new Date().toLocaleString(),
isError: false,
};
// Create bot message
const botMessage: ChatMessage = {
id: (Date.now() + 1).toString(),
role: "assistant" as MessageRole,
content: "",
date: new Date().toLocaleString(),
streaming: true,
isError: false,
};
// Add messages to session
chatStore.updateCurrentSession((session) => {
session.messages.push(userMessage, botMessage);
});
// Make request
api.llm.chat({
messages: [userMessage],
config: { ...modelConfig, stream: true },
onUpdate(message) {
botMessage.streaming = true;
if (message) {
botMessage.content = message;
}
chatStore.updateCurrentSession((session) => {
session.messages = session.messages.concat();
});
},
onFinish(message) {
botMessage.streaming = false;
if (message) {
botMessage.content = message;
chatStore.onNewMessage(botMessage);
}
},
onError(error) {
botMessage.content = error.message;
botMessage.streaming = false;
userMessage.isError = true;
botMessage.isError = true;
chatStore.updateCurrentSession((session) => {
session.messages = session.messages.concat();
});
console.error("[Chat] failed ", error);
},
});
} catch (error) {
console.error("Failed to upload document:", error);
showToast("Failed to upload document");
} finally {
props.setUploading(false);
}
};
fileInput.click();
}
return (
<div className="chat-input-actions">
{/* Original actions */}
<Actions {...props} />
{/* Document upload button (only for Bedrock) */}
{isBedrockProvider && (
<div className="chat-input-action">
<div className="icon" onClick={uploadDocument}>
{props.uploading ? <LoadingButtonIcon /> : <DocumentIcon />}
</div>
<div className="text">Upload Document</div>
</div>
)}
</div>
);
}

View File

@@ -8,7 +8,7 @@ import React, {
Fragment,
RefObject,
} from "react";
import DocumentIcon from "../icons/document.svg";
import SendWhiteIcon from "../icons/send-white.svg";
import BrainIcon from "../icons/brain.svg";
import RenameIcon from "../icons/rename.svg";
@@ -548,91 +548,6 @@ export function ChatActions(props: {
);
}
}, [chatStore, currentModel, models]);
const isBedrockProvider = currentProviderName === ServiceProvider.Bedrock;
// ... (rest of the existing state and functions)
async function uploadDocument() {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = ".pdf,.csv,.doc,.docx,.xls,.xlsx,.html,.txt,.md";
fileInput.onchange = async (event: any) => {
const file = event.target.files[0];
if (!file) return;
props.setUploading(true);
try {
// Convert file to base64
const base64 = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
if (!e.target?.result) return reject("Failed to read file");
const base64 = (e.target.result as string).split(",")[1];
resolve(base64);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
// Get file extension
const format = file.name.split(".").pop()?.toLowerCase() || "";
const supportedFormats = [
"pdf",
"csv",
"doc",
"docx",
"xls",
"xlsx",
"html",
"txt",
"md",
];
if (!supportedFormats.includes(format)) {
throw new Error("Unsupported file format");
}
// Format file size
const size = file.size;
let sizeStr = "";
if (size < 1024) {
sizeStr = size + " B";
} else if (size < 1024 * 1024) {
sizeStr = (size / 1024).toFixed(2) + " KB";
} else {
sizeStr = (size / (1024 * 1024)).toFixed(2) + " MB";
}
// Create document content with only filename and size
const documentContent = {
type: "document",
document: {
format,
name: file.name,
size: sizeStr,
source: {
bytes: base64,
},
},
};
// Submit the document content as a JSON string but only display filename and size
const displayContent = `Document: ${file.name} (${sizeStr})`;
chatStore.onUserInput(displayContent);
// Store the actual document content separately if needed
// chatStore.updateCurrentSession((session) => {
// session.lastDocument = documentContent;
// });
} catch (error) {
console.error("Failed to upload document:", error);
showToast("Failed to upload document");
} finally {
props.setUploading(false);
}
};
fileInput.click();
}
return (
<div className={styles["chat-input-actions"]}>
@@ -665,14 +580,6 @@ export function ChatActions(props: {
icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}
/>
)}
{/* Add document upload button for Bedrock */}
{isBedrockProvider && (
<ChatAction
onClick={uploadDocument}
text={Locale.Chat.InputActions.UploadDocument}
icon={props.uploading ? <LoadingButtonIcon /> : <DocumentIcon />}
/>
)}
<ChatAction
onClick={nextTheme}
text={Locale.Chat.InputActions.Theme[theme]}