mirror of
https://github.com/coaidev/coai.git
synced 2025-05-20 05:20:15 +09:00
add settings feature
This commit is contained in:
parent
df6e13d54d
commit
ebc5edcdc8
@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.4",
|
"@radix-ui/react-alert-dialog": "^1.0.4",
|
||||||
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-context-menu": "^2.1.4",
|
"@radix-ui/react-context-menu": "^2.1.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.4",
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||||
|
31
app/pnpm-lock.yaml
generated
31
app/pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ dependencies:
|
|||||||
'@radix-ui/react-alert-dialog':
|
'@radix-ui/react-alert-dialog':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-checkbox':
|
||||||
|
specifier: ^1.0.4
|
||||||
|
version: 1.0.4(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-context-menu':
|
'@radix-ui/react-context-menu':
|
||||||
specifier: ^2.1.4
|
specifier: ^2.1.4
|
||||||
version: 2.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
version: 2.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
||||||
@ -1759,6 +1762,34 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.33)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.33)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.33)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.33)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-size': 1.0.1(@types/react@18.2.33)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.33
|
||||||
|
'@types/react-dom': 18.2.14
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -333,11 +333,14 @@
|
|||||||
|
|
||||||
.input-box {
|
.input-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
|
||||||
color: hsl(var(--text));
|
color: hsl(var(--text));
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
padding: 0 2.5rem;
|
padding: 0 2.5rem;
|
||||||
|
|
||||||
|
&.align {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: hsl(var(--text-secondary));
|
color: hsl(var(--text-secondary));
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
30
app/src/assets/settings.less
Normal file
30
app/src/assets/settings.less
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
.settings-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 1.5rem 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
color: hsl(var(--text));
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
transition: .1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .item {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import {
|
|||||||
} from "@/store/chat.ts";
|
} from "@/store/chat.ts";
|
||||||
import { manager } from "@/conversation/manager.ts";
|
import { manager } from "@/conversation/manager.ts";
|
||||||
import { formatMessage } from "@/utils/processor.ts";
|
import { formatMessage } from "@/utils/processor.ts";
|
||||||
import { triggerInstallApp } from "@/utils/app.ts";
|
|
||||||
import ChatInterface from "@/components/home/ChatInterface.tsx";
|
import ChatInterface from "@/components/home/ChatInterface.tsx";
|
||||||
import { Button } from "@/components/ui/button.tsx";
|
import { Button } from "@/components/ui/button.tsx";
|
||||||
import router from "@/router.tsx";
|
import router from "@/router.tsx";
|
||||||
@ -44,6 +43,7 @@ import { clearHistoryState, getQueryParam } from "@/utils/path.ts";
|
|||||||
import { forgetMemory, popMemory, setMemory } from "@/utils/memory.ts";
|
import { forgetMemory, popMemory, setMemory } from "@/utils/memory.ts";
|
||||||
import { useToast } from "@/components/ui/use-toast.ts";
|
import { useToast } from "@/components/ui/use-toast.ts";
|
||||||
import { ToastAction } from "@/components/ui/toast.tsx";
|
import { ToastAction } from "@/components/ui/toast.tsx";
|
||||||
|
import {alignSelector, contextSelector, openDialog} from "@/store/settings.ts";
|
||||||
|
|
||||||
function ChatSpace() {
|
function ChatSpace() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@ -115,6 +115,9 @@ function ChatWrapper() {
|
|||||||
const web = useSelector(selectWeb);
|
const web = useSelector(selectWeb);
|
||||||
const messages = useSelector(selectMessages);
|
const messages = useSelector(selectMessages);
|
||||||
const target = useRef(null);
|
const target = useRef(null);
|
||||||
|
const context = useSelector(contextSelector);
|
||||||
|
const align = useSelector(alignSelector);
|
||||||
|
|
||||||
manager.setDispatch(dispatch);
|
manager.setDispatch(dispatch);
|
||||||
|
|
||||||
function clearFile() {
|
function clearFile() {
|
||||||
@ -126,10 +129,15 @@ function ChatWrapper() {
|
|||||||
auth: boolean,
|
auth: boolean,
|
||||||
model: string,
|
model: string,
|
||||||
web: boolean,
|
web: boolean,
|
||||||
|
context: boolean,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const message: string = formatMessage(file, data);
|
const message: string = formatMessage(file, data);
|
||||||
if (message.length > 0 && data.trim().length > 0) {
|
if (message.length > 0 && data.trim().length > 0) {
|
||||||
if (await manager.send(t, auth, { message, web, model, type: "chat" })) {
|
if (await manager.send(t, auth, {
|
||||||
|
message, web, model,
|
||||||
|
ignore_context: !context,
|
||||||
|
type: "chat",
|
||||||
|
})) {
|
||||||
forgetMemory("history");
|
forgetMemory("history");
|
||||||
clearFile();
|
clearFile();
|
||||||
return true;
|
return true;
|
||||||
@ -140,7 +148,7 @@ function ChatWrapper() {
|
|||||||
|
|
||||||
async function handleSend(auth: boolean, model: string, web: boolean) {
|
async function handleSend(auth: boolean, model: string, web: boolean) {
|
||||||
// because of the function wrapper, we need to update the selector state using props.
|
// because of the function wrapper, we need to update the selector state using props.
|
||||||
if (await processSend(input, auth, model, web)) {
|
if (await processSend(input, auth, model, web, context)) {
|
||||||
setInput("");
|
setInput("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,7 +161,7 @@ function ChatWrapper() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!init) return;
|
if (!init) return;
|
||||||
const query = getQueryParam("q").trim();
|
const query = getQueryParam("q").trim();
|
||||||
if (query.length > 0) processSend(query, auth, model, web).then();
|
if (query.length > 0) processSend(query, auth, model, web, context).then();
|
||||||
clearHistoryState();
|
clearHistoryState();
|
||||||
}, [init]);
|
}, [init]);
|
||||||
|
|
||||||
@ -215,7 +223,7 @@ function ChatWrapper() {
|
|||||||
)}
|
)}
|
||||||
<Input
|
<Input
|
||||||
id={`input`}
|
id={`input`}
|
||||||
className={`input-box`}
|
className={`input-box ${align && 'align'}`}
|
||||||
ref={target}
|
ref={target}
|
||||||
value={input}
|
value={input}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@ -259,7 +267,10 @@ function ChatWrapper() {
|
|||||||
<div className={`version`}>
|
<div className={`version`}>
|
||||||
<svg
|
<svg
|
||||||
className={`app`}
|
className={`app`}
|
||||||
onClick={triggerInstallApp}
|
onClick={() => {
|
||||||
|
// triggerInstallApp();
|
||||||
|
dispatch(openDialog());
|
||||||
|
}}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
@ -5,7 +5,6 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { selectAuthenticated } from "@/store/auth.ts";
|
import { selectAuthenticated } from "@/store/auth.ts";
|
||||||
import { useToast } from "@/components/ui/use-toast.ts";
|
import { useToast } from "@/components/ui/use-toast.ts";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { Model } from "@/conversation/types.ts";
|
import { Model } from "@/conversation/types.ts";
|
||||||
import { modelEvent } from "@/events/model.ts";
|
import { modelEvent } from "@/events/model.ts";
|
||||||
import { isSubscribedSelector } from "@/store/subscription.ts";
|
import { isSubscribedSelector } from "@/store/subscription.ts";
|
||||||
@ -30,11 +29,6 @@ function ModelSelector(props: ModelSelectorProps) {
|
|||||||
const subscription = useSelector(isSubscribedSelector);
|
const subscription = useSelector(isSubscribedSelector);
|
||||||
const student = useSelector(teenagerSelector);
|
const student = useSelector(teenagerSelector);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (auth && model === "gpt-3.5-turbo-0613")
|
|
||||||
dispatch(setModel("gpt-3.5-turbo-16k-0613"));
|
|
||||||
}, [auth]);
|
|
||||||
|
|
||||||
modelEvent.bind((target: string) => {
|
modelEvent.bind((target: string) => {
|
||||||
if (supportModels.find((m) => m.id === target)) {
|
if (supportModels.find((m) => m.id === target)) {
|
||||||
if (model === target) return;
|
if (model === target) return;
|
||||||
|
28
app/src/components/ui/checkbox.tsx
Normal file
28
app/src/components/ui/checkbox.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||||
|
import { Check } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/components/ui/lib/utils"
|
||||||
|
|
||||||
|
const Checkbox = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<CheckboxPrimitive.Indicator
|
||||||
|
className={cn("flex items-center justify-center text-current")}
|
||||||
|
>
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
</CheckboxPrimitive.Indicator>
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
|
))
|
||||||
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
||||||
|
|
||||||
|
export { Checkbox }
|
@ -8,7 +8,7 @@ import {
|
|||||||
} from "@/utils/env.ts";
|
} from "@/utils/env.ts";
|
||||||
import { getMemory } from "@/utils/memory.ts";
|
import { getMemory } from "@/utils/memory.ts";
|
||||||
|
|
||||||
export const version = "3.6.0";
|
export const version = "3.6.1";
|
||||||
export const dev: boolean = getDev();
|
export const dev: boolean = getDev();
|
||||||
export const deploy: boolean = true;
|
export const deploy: boolean = true;
|
||||||
export let rest_api: string = getRestApi(deploy);
|
export let rest_api: string = getRestApi(deploy);
|
||||||
|
@ -15,6 +15,7 @@ export type ChatProps = {
|
|||||||
message: string;
|
message: string;
|
||||||
model: string;
|
model: string;
|
||||||
web?: boolean;
|
web?: boolean;
|
||||||
|
ignore_context?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StreamCallback = (message: StreamMessage) => void;
|
type StreamCallback = (message: StreamMessage) => void;
|
||||||
|
51
app/src/dialogs/Settings.tsx
Normal file
51
app/src/dialogs/Settings.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import "@/assets/settings.less";
|
||||||
|
import {useTranslation} from "react-i18next";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import {alignSelector, contextSelector, dialogSelector, setAlign, setContext, setDialog} from "@/store/settings.ts";
|
||||||
|
import {Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle} from "@/components/ui/dialog.tsx";
|
||||||
|
import {Checkbox} from "@/components/ui/checkbox.tsx";
|
||||||
|
|
||||||
|
function Settings() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const open = useSelector(dialogSelector);
|
||||||
|
|
||||||
|
const align = useSelector(alignSelector);
|
||||||
|
const context = useSelector(contextSelector);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={(open) => dispatch(setDialog(open))}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{t("settings.title")}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
<div className={`settings-container`}>
|
||||||
|
<div className={`settings-wrapper`}>
|
||||||
|
<div className={`item`}>
|
||||||
|
<div className={`name`}>
|
||||||
|
{t('settings.align')}
|
||||||
|
</div>
|
||||||
|
<div className={`grow`} />
|
||||||
|
<Checkbox className={`value`} checked={align} onCheckedChange={(state: boolean) => {
|
||||||
|
dispatch(setAlign(state));
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
<div className={`item`}>
|
||||||
|
<div className={`name`}>
|
||||||
|
{t('settings.context')}
|
||||||
|
</div>
|
||||||
|
<div className={`grow`} />
|
||||||
|
<Checkbox className={`value`} checked={context} onCheckedChange={(state: boolean) => {
|
||||||
|
dispatch(setContext(state));
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Settings;
|
@ -5,6 +5,7 @@ import Package from "./Package.tsx";
|
|||||||
import Subscription from "./Subscription.tsx";
|
import Subscription from "./Subscription.tsx";
|
||||||
import ShareManagement from "./ShareManagement.tsx";
|
import ShareManagement from "./ShareManagement.tsx";
|
||||||
import Invitation from "./Invitation.tsx";
|
import Invitation from "./Invitation.tsx";
|
||||||
|
import Settings from "@/dialogs/Settings.tsx";
|
||||||
|
|
||||||
function DialogManager() {
|
function DialogManager() {
|
||||||
return (
|
return (
|
||||||
@ -16,6 +17,7 @@ function DialogManager() {
|
|||||||
<Subscription />
|
<Subscription />
|
||||||
<ShareManagement />
|
<ShareManagement />
|
||||||
<Invitation />
|
<Invitation />
|
||||||
|
<Settings />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -420,6 +420,11 @@ const resources = {
|
|||||||
contact: {
|
contact: {
|
||||||
title: "联系我们",
|
title: "联系我们",
|
||||||
},
|
},
|
||||||
|
settings: {
|
||||||
|
title: "设置",
|
||||||
|
context: "保留上下文",
|
||||||
|
align: "聊天框居中",
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ru: {
|
ru: {
|
||||||
|
@ -8,6 +8,7 @@ import subscriptionReducer from "./subscription";
|
|||||||
import apiReducer from "./api";
|
import apiReducer from "./api";
|
||||||
import sharingReducer from "./sharing";
|
import sharingReducer from "./sharing";
|
||||||
import invitationReducer from "./invitation";
|
import invitationReducer from "./invitation";
|
||||||
|
import settingsReducer from "./settings";
|
||||||
|
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@ -20,6 +21,7 @@ const store = configureStore({
|
|||||||
api: apiReducer,
|
api: apiReducer,
|
||||||
sharing: sharingReducer,
|
sharing: sharingReducer,
|
||||||
invitation: invitationReducer,
|
invitation: invitationReducer,
|
||||||
|
settings: settingsReducer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
48
app/src/store/settings.ts
Normal file
48
app/src/store/settings.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import {createSlice} from "@reduxjs/toolkit";
|
||||||
|
import {getMemory, setMemory} from "@/utils/memory.ts";
|
||||||
|
import {RootState} from "@/store/index.ts";
|
||||||
|
|
||||||
|
export const settingsSlice = createSlice({
|
||||||
|
name: "settings",
|
||||||
|
initialState: {
|
||||||
|
dialog: false,
|
||||||
|
context: getMemory("context") !== "false",
|
||||||
|
align: getMemory("align") !== "false",
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
toggleDialog: (state) => {
|
||||||
|
state.dialog = !state.dialog;
|
||||||
|
},
|
||||||
|
setDialog: (state, action) => {
|
||||||
|
state.dialog = action.payload as boolean;
|
||||||
|
},
|
||||||
|
openDialog: (state) => {
|
||||||
|
state.dialog = true;
|
||||||
|
},
|
||||||
|
closeDialog: (state) => {
|
||||||
|
state.dialog = false;
|
||||||
|
},
|
||||||
|
setContext: (state, action) => {
|
||||||
|
state.context = action.payload as boolean;
|
||||||
|
setMemory("context", String(action.payload));
|
||||||
|
},
|
||||||
|
setAlign: (state, action) => {
|
||||||
|
state.align = action.payload as boolean;
|
||||||
|
setMemory("align", String(action.payload));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const {
|
||||||
|
toggleDialog,
|
||||||
|
setDialog,
|
||||||
|
openDialog,
|
||||||
|
closeDialog,
|
||||||
|
setContext,
|
||||||
|
setAlign,
|
||||||
|
} = settingsSlice.actions;
|
||||||
|
export default settingsSlice.reducer;
|
||||||
|
|
||||||
|
export const dialogSelector = (state: RootState): boolean => state.settings.dialog;
|
||||||
|
export const contextSelector = (state: RootState): boolean => state.settings.context;
|
||||||
|
export const alignSelector = (state: RootState): boolean => state.settings.align;
|
@ -18,6 +18,7 @@ type Conversation struct {
|
|||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
EnableWeb bool `json:"enable_web"`
|
EnableWeb bool `json:"enable_web"`
|
||||||
Shared bool `json:"shared"`
|
Shared bool `json:"shared"`
|
||||||
|
IgnoreContext bool `json:"ignore_context"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FormMessage struct {
|
type FormMessage struct {
|
||||||
@ -25,6 +26,7 @@ type FormMessage struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Web bool `json:"web"`
|
Web bool `json:"web"`
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
|
IgnoreContext bool `json:"ignore_context"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAnonymousConversation() *Conversation {
|
func NewAnonymousConversation() *Conversation {
|
||||||
@ -35,6 +37,7 @@ func NewAnonymousConversation() *Conversation {
|
|||||||
Name: "anonymous",
|
Name: "anonymous",
|
||||||
Message: []globals.Message{},
|
Message: []globals.Message{},
|
||||||
Model: globals.GPT3Turbo,
|
Model: globals.GPT3Turbo,
|
||||||
|
IgnoreContext: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +87,10 @@ func (c *Conversation) IsEnableWeb() bool {
|
|||||||
return c.EnableWeb
|
return c.EnableWeb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Conversation) IsIgnoreContext() bool {
|
||||||
|
return c.IgnoreContext
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Conversation) SetModel(model string) {
|
func (c *Conversation) SetModel(model string) {
|
||||||
if len(model) == 0 {
|
if len(model) == 0 {
|
||||||
model = globals.GPT3Turbo
|
model = globals.GPT3Turbo
|
||||||
@ -95,6 +102,10 @@ func (c *Conversation) SetEnableWeb(enable bool) {
|
|||||||
c.EnableWeb = enable
|
c.EnableWeb = enable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Conversation) SetIgnoreContext(ignore bool) {
|
||||||
|
c.IgnoreContext = ignore
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Conversation) GetName() string {
|
func (c *Conversation) GetName() string {
|
||||||
return c.Name
|
return c.Name
|
||||||
}
|
}
|
||||||
@ -129,6 +140,14 @@ func (c *Conversation) GetMessageLength() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conversation) GetMessageSegment(length int) []globals.Message {
|
func (c *Conversation) GetMessageSegment(length int) []globals.Message {
|
||||||
|
if c.IsIgnoreContext() {
|
||||||
|
if len(c.Message) >= 1 {
|
||||||
|
// get latest message
|
||||||
|
return []globals.Message{c.Message[len(c.Message)-1]}
|
||||||
|
}
|
||||||
|
// empty
|
||||||
|
return []globals.Message{}
|
||||||
|
}
|
||||||
if length > len(c.Message) {
|
if length > len(c.Message) {
|
||||||
return c.Message
|
return c.Message
|
||||||
}
|
}
|
||||||
@ -203,6 +222,7 @@ func (c *Conversation) AddMessageFromByte(data []byte) (string, error) {
|
|||||||
c.AddMessageFromUser(form.Message)
|
c.AddMessageFromUser(form.Message)
|
||||||
c.SetModel(form.Model)
|
c.SetModel(form.Model)
|
||||||
c.SetEnableWeb(form.Web)
|
c.SetEnableWeb(form.Web)
|
||||||
|
c.SetIgnoreContext(form.IgnoreContext)
|
||||||
return form.Message, nil
|
return form.Message, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +234,7 @@ func (c *Conversation) AddMessageFromForm(form *FormMessage) error {
|
|||||||
c.AddMessageFromUser(form.Message)
|
c.AddMessageFromUser(form.Message)
|
||||||
c.SetModel(form.Model)
|
c.SetModel(form.Model)
|
||||||
c.SetEnableWeb(form.Web)
|
c.SetEnableWeb(form.Web)
|
||||||
|
c.SetIgnoreContext(form.IgnoreContext)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user