feat: copilot context menu for tool

This commit is contained in:
n4ze3m
2024-08-03 23:00:57 +05:30
parent 9c7ebc8778
commit ac9c9ca887
14 changed files with 696 additions and 132 deletions

View File

@@ -13,7 +13,8 @@ export const saveMessageOnError = async ({
selectedModel,
setHistoryId,
isRegenerating,
message_source = "web-ui"
message_source = "web-ui",
message_type
}: {
e: any
setHistory: (history: ChatHistory) => void
@@ -26,6 +27,7 @@ export const saveMessageOnError = async ({
setHistoryId: (historyId: string) => void
isRegenerating: boolean
message_source?: "copilot" | "web-ui"
message_type?: string
}) => {
if (
e?.name === "AbortError" ||
@@ -55,7 +57,8 @@ export const saveMessageOnError = async ({
userMessage,
[image],
[],
1
1,
message_type
)
}
await saveMessage(
@@ -65,7 +68,8 @@ export const saveMessageOnError = async ({
botMessage,
[],
[],
2
2,
message_type
)
await setLastUsedChatModel(historyId, selectedModel)
} else {
@@ -78,7 +82,8 @@ export const saveMessageOnError = async ({
userMessage,
[image],
[],
1
1,
message_type
)
}
await saveMessage(
@@ -88,7 +93,8 @@ export const saveMessageOnError = async ({
botMessage,
[],
[],
2
2,
message_type
)
setHistoryId(newHistoryId.id)
await setLastUsedChatModel(newHistoryId.id, selectedModel)
@@ -109,7 +115,8 @@ export const saveMessageOnSuccess = async ({
image,
fullText,
source,
message_source = "web-ui"
message_source = "web-ui",
message_type
}: {
historyId: string | null
setHistoryId: (historyId: string) => void
@@ -119,7 +126,8 @@ export const saveMessageOnSuccess = async ({
image: string
fullText: string
source: any[]
message_source?: "copilot" | "web-ui"
message_source?: "copilot" | "web-ui",
message_type?: string
}) => {
if (historyId) {
if (!isRegenerate) {
@@ -130,7 +138,8 @@ export const saveMessageOnSuccess = async ({
message,
[image],
[],
1
1,
message_type
)
}
await saveMessage(
@@ -140,7 +149,8 @@ export const saveMessageOnSuccess = async ({
fullText,
[],
source,
2
2,
message_type
)
await setLastUsedChatModel(historyId, selectedModel!)
} else {
@@ -152,7 +162,8 @@ export const saveMessageOnSuccess = async ({
message,
[image],
[],
1
1,
message_type
)
await saveMessage(
newHistoryId.id,
@@ -161,7 +172,8 @@ export const saveMessageOnSuccess = async ({
fullText,
[],
source,
2
2,
message_type
)
setHistoryId(newHistoryId.id)
await setLastUsedChatModel(newHistoryId.id, selectedModel!)

View File

@@ -0,0 +1,29 @@
import { useState, useEffect } from "react"
interface Message {
from: string
type: string
text: string
}
function useBackgroundMessage() {
const [message, setMessage] = useState<Message | null>(null)
useEffect(() => {
const messageListener = (request: Message) => {
if (request.from === "background") {
setMessage(request)
}
}
browser.runtime.connect({ name: 'pgCopilot' })
browser.runtime.onMessage.addListener(messageListener)
return () => {
browser.runtime.onMessage.removeListener(messageListener)
}
}, [])
return message
}
export default useBackgroundMessage

View File

@@ -31,6 +31,7 @@ import { useStoreChatModelSettings } from "@/store/model"
import { getAllDefaultModelSettings } from "@/services/model-settings"
import { getSystemPromptForWeb } from "@/web/web"
import { pageAssistModel } from "@/models"
import { getPrompt } from "@/services/application"
export const useMessage = () => {
const {
@@ -51,8 +52,10 @@ export const useMessage = () => {
isSearchingInternet
} = useStoreMessageOption()
const [chatWithWebsiteEmbedding] = useStorage("chatWithWebsiteEmbedding", true)
const [chatWithWebsiteEmbedding] = useStorage(
"chatWithWebsiteEmbedding",
true
)
const [maxWebsiteContext] = useStorage("maxWebsiteContext", 4028)
const {
@@ -857,13 +860,206 @@ export const useMessage = () => {
}
}
const presetChatMode = async (
message: string,
image: string,
isRegenerate: boolean,
messages: Message[],
history: ChatHistory,
signal: AbortSignal,
messageType: string
) => {
setStreaming(true)
const url = await getOllamaURL()
const userDefaultModelSettings = await getAllDefaultModelSettings()
if (image.length > 0) {
image = `data:image/jpeg;base64,${image.split(",")[1]}`
}
const ollama = await pageAssistModel({
model: selectedModel!,
baseUrl: cleanUrl(url),
keepAlive:
currentChatModelSettings?.keepAlive ??
userDefaultModelSettings?.keepAlive,
temperature:
currentChatModelSettings?.temperature ??
userDefaultModelSettings?.temperature,
topK: currentChatModelSettings?.topK ?? userDefaultModelSettings?.topK,
topP: currentChatModelSettings?.topP ?? userDefaultModelSettings?.topP,
numCtx:
currentChatModelSettings?.numCtx ?? userDefaultModelSettings?.numCtx,
seed: currentChatModelSettings?.seed
})
let newMessage: Message[] = []
let generateMessageId = generateID()
if (!isRegenerate) {
newMessage = [
...messages,
{
isBot: false,
name: "You",
message,
sources: [],
images: [image],
messageType: messageType
},
{
isBot: true,
name: selectedModel,
message: "▋",
sources: [],
id: generateMessageId
}
]
} else {
newMessage = [
...messages,
{
isBot: true,
name: selectedModel,
message: "▋",
sources: [],
id: generateMessageId
}
]
}
setMessages(newMessage)
let fullText = ""
let contentToSave = ""
try {
const prompt = await getPrompt(messageType)
let humanMessage = new HumanMessage({
content: [
{
text: prompt.replace("{text}", message),
type: "text"
}
]
})
if (image.length > 0) {
humanMessage = new HumanMessage({
content: [
{
text: prompt.replace("{text}", message),
type: "text"
},
{
image_url: image,
type: "image_url"
}
]
})
}
const chunks = await ollama.stream([humanMessage], {
signal: signal
})
let count = 0
for await (const chunk of chunks) {
contentToSave += chunk.content
fullText += chunk.content
if (count === 0) {
setIsProcessing(true)
}
setMessages((prev) => {
return prev.map((message) => {
if (message.id === generateMessageId) {
return {
...message,
message: fullText + "▋"
}
}
return message
})
})
count++
}
setMessages((prev) => {
return prev.map((message) => {
if (message.id === generateMessageId) {
return {
...message,
message: fullText
}
}
return message
})
})
setHistory([
...history,
{
role: "user",
content: message,
image,
messageType
},
{
role: "assistant",
content: fullText
}
])
await saveMessageOnSuccess({
historyId,
setHistoryId,
isRegenerate,
selectedModel: selectedModel,
message,
image,
fullText,
source: [],
message_source: "copilot",
message_type: messageType
})
setIsProcessing(false)
setStreaming(false)
} catch (e) {
const errorSave = await saveMessageOnError({
e,
botMessage: fullText,
history,
historyId,
image,
selectedModel,
setHistory,
setHistoryId,
userMessage: message,
isRegenerating: isRegenerate,
message_source: "copilot",
message_type: messageType
})
if (!errorSave) {
notification.error({
message: t("error"),
description: e?.message || t("somethingWentWrong")
})
}
setIsProcessing(false)
setStreaming(false)
} finally {
setAbortController(null)
}
}
const onSubmit = async ({
message,
image,
isRegenerate,
controller,
memory,
messages: chatHistory
messages: chatHistory,
messageType
}: {
message: string
image: string
@@ -871,6 +1067,7 @@ export const useMessage = () => {
messages?: Message[]
memory?: ChatHistory
controller?: AbortController
messageType?: string
}) => {
let signal: AbortSignal
if (!controller) {
@@ -882,39 +1079,52 @@ export const useMessage = () => {
signal = controller.signal
}
if (chatMode === "normal") {
if (webSearch) {
await searchChatMode(
message,
image,
isRegenerate || false,
messages,
memory || history,
signal
)
} else {
await normalChatMode(
message,
image,
isRegenerate,
chatHistory || messages,
memory || history,
signal
)
}
} else {
const newEmbeddingController = new AbortController()
let embeddingSignal = newEmbeddingController.signal
setEmbeddingController(newEmbeddingController)
await chatWithWebsiteMode(
// this means that the user is trying to send something from a selected text on the web
if (messageType) {
await presetChatMode(
message,
image,
isRegenerate,
chatHistory || messages,
memory || history,
signal,
embeddingSignal
messageType
)
} else {
if (chatMode === "normal") {
if (webSearch) {
await searchChatMode(
message,
image,
isRegenerate || false,
messages,
memory || history,
signal
)
} else {
await normalChatMode(
message,
image,
isRegenerate,
chatHistory || messages,
memory || history,
signal
)
}
} else {
const newEmbeddingController = new AbortController()
let embeddingSignal = newEmbeddingController.signal
setEmbeddingController(newEmbeddingController)
await chatWithWebsiteMode(
message,
image,
isRegenerate,
chatHistory || messages,
memory || history,
signal,
embeddingSignal
)
}
}
}
@@ -982,7 +1192,8 @@ export const useMessage = () => {
image: lastMessage.image || "",
isRegenerate: true,
memory: newHistory,
controller: newController
controller: newController,
messageType: lastMessage.messageType
})
}
}