Skip to content

Commit

Permalink
update model selector
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Oct 21, 2023
1 parent a5e18a1 commit e31d69a
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 130 deletions.
24 changes: 24 additions & 0 deletions app/src/assets/ui.less
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
}

.select-group-item {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.35rem 0.8rem;
border: 1px solid hsl(var(--border));
border-radius: 4px;
Expand All @@ -34,6 +37,27 @@
background: hsl(var(--text));
border-color: hsl(var(--border-hover));
color: hsl(var(--background));

.badge {
background: hsl(var(--background)) !important;
color: hsl(var(--text));

&:hover {
background: hsl(var(--background)) !important;
}
}
}

.badge {
user-select: none;
transition: .2s;
padding-left: 0.45rem;
padding-right: 0.45rem;
background: hsl(var(--primary)) !important;

&:hover {
background: hsl(var(--primary)) !important;
}
}
}
}
34 changes: 18 additions & 16 deletions app/src/components/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
Copy,
File,
Loader2,
MousePointerSquare, Power, RotateCcw,
MousePointerSquare,
Power,
RotateCcw,
} from "lucide-react";
import {
ContextMenu,
Expand Down Expand Up @@ -165,21 +167,21 @@ function MessageContent({ message, end, onEvent }: MessageProps) {
<Loader2 className={`h-5 w-5 m-1 animate-spin`} />
)}
</div>
{
(message.role === "assistant" && end === true) && (
<div className={`message-toolbar`}>
{
(message.end !== false) ?
<RotateCcw className={`h-4 w-4 m-0.5`} onClick={() => (
onEvent && onEvent("restart")
)} /> :
<Power className={`h-4 w-4 m-0.5`} onClick={() => (
onEvent && onEvent("stop")
)} />
}
</div>
)
}
{message.role === "assistant" && end === true && (
<div className={`message-toolbar`}>
{message.end !== false ? (
<RotateCcw
className={`h-4 w-4 m-0.5`}
onClick={() => onEvent && onEvent("restart")}
/>
) : (
<Power
className={`h-4 w-4 m-0.5`}
onClick={() => onEvent && onEvent("stop")}
/>
)}
</div>
)}
</div>
);
}
Expand Down
118 changes: 90 additions & 28 deletions app/src/components/SelectGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,113 @@ import {
} from "./ui/select";
import { mobile } from "../utils.ts";
import { useEffect, useState } from "react";
import { Badge } from "./ui/badge.tsx";

export type SelectItemProps = {
name: string;
value: string;
badge?: string;
tag?: any;
};

type SelectGroupProps = {
current: string;
list: string[];
current: SelectItemProps;
list: SelectItemProps[];
onChange?: (select: string) => void;
maxElements?: number;
};

function SelectGroup(props: SelectGroupProps) {
const [state, setState] = useState(mobile);
useEffect(() => {
window.addEventListener("resize", () => {
setState(mobile);
});
}, []);
function GroupSelectItem(props: SelectItemProps) {
return (
<>
{props.value}
{props.badge && <Badge className="badge ml-1">{props.badge}</Badge>}
</>
);
}

return state ? (
function SelectGroupDesktop(props: SelectGroupProps) {
const max: number = props.maxElements || 5;
const range = props.list.length > max ? max : props.list.length;
const display = props.list.slice(0, range);
const hidden = props.list.slice(range);

return (
<div className={`select-group`}>
{display.map((select: SelectItemProps, idx: number) => (
<div
key={idx}
onClick={() => props.onChange?.(select.name)}
className={`select-group-item ${
select == props.current ? "active" : ""
}`}
>
<GroupSelectItem {...select} />
</div>
))}

{props.list.length > max && (
<Select
defaultValue={"..."}
value={props.current?.name || "..."}
onValueChange={(value: string) => props.onChange?.(value)}
>
<SelectTrigger
className={`w-max gap-1 select-group-item ${
hidden.includes(props.current) ? "active" : ""
}`}
>
<SelectValue asChild>
<span>
{hidden.includes(props.current) ? props.current.value : "..."}
</span>
</SelectValue>
</SelectTrigger>
<SelectContent>
{hidden.map((select: SelectItemProps, idx: number) => (
<SelectItem key={idx} value={select.name}>
<GroupSelectItem {...select} />
</SelectItem>
))}
</SelectContent>
</Select>
)}
</div>
);
}

function SelectGroupMobile(props: SelectGroupProps) {
return (
<Select
value={props.current}
value={props.current.name}
onValueChange={(value: string) => props.onChange?.(value)}
>
<SelectTrigger className="select-group mobile">
<SelectValue placeholder={props.current} />
<SelectValue placeholder={props.current.value} />
</SelectTrigger>
<SelectContent>
{props.list.map((select: string, idx: number) => (
<SelectItem key={idx} value={select}>
{select}
{props.list.map((select: SelectItemProps, idx: number) => (
<SelectItem key={idx} value={select.name}>
<GroupSelectItem {...select} />
</SelectItem>
))}
</SelectContent>
</Select>
);
}

function SelectGroup(props: SelectGroupProps) {
const [state, setState] = useState(mobile);
useEffect(() => {
window.addEventListener("resize", () => {
setState(mobile);
});
}, []);

return state ? (
<SelectGroupMobile {...props} />
) : (
<div className={`select-group`}>
{props.list.map((select: string, idx: number) => (
<div
key={idx}
onClick={() => props.onChange?.(select)}
className={`select-group-item ${
select == props.current ? "active" : ""
}`}
>
{select}
</div>
))}
</div>
<SelectGroupDesktop {...props} />
);
}

Expand Down
56 changes: 56 additions & 0 deletions app/src/components/home/ModelSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import SelectGroup, { SelectItemProps } from "../SelectGroup.tsx";
import { supportModels } from "../../conf.ts";
import { selectModel, setModel } from "../../store/chat.ts";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { selectAuthenticated } from "../../store/auth.ts";
import { useToast } from "../ui/use-toast.ts";
import { useEffect } from "react";
import { Model } from "../../conversation/types.ts";

function GetModel(name: string): Model {
return supportModels.find((model) => model.id === name) as Model;
}

function ModelSelector() {
const { t } = useTranslation();
const dispatch = useDispatch();
const { toast } = useToast();

const model = useSelector(selectModel);
const auth = useSelector(selectAuthenticated);

useEffect(() => {
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
}, [auth]);

const list = supportModels.map(
(model: Model): SelectItemProps => ({
name: model.id,
value: model.name,
badge: model.free ? "free" : undefined,
}),
);

return (
<SelectGroup
current={list.find((item) => item.name === model) as SelectItemProps}
list={list}
maxElements={6}
onChange={(value: string) => {
const model = GetModel(value);
console.debug(`[model] select model: ${model.name} (id: ${model.id})`);

if (!auth && model.auth) {
toast({
title: t("login-require"),
});
return;
}
dispatch(setModel(value));
}}
/>
);
}

export default ModelSelector;
55 changes: 41 additions & 14 deletions app/src/conf.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from "axios";
import { Model } from "./conversation/types.ts";

export const version = "3.4.5";
export const version = "3.4.6";
export const deploy: boolean = true;
export let rest_api: string = "http://localhost:8094";
export let ws_api: string = "ws://localhost:8094";
Expand All @@ -11,19 +12,45 @@ if (deploy) {
}

export const tokenField = deploy ? "token" : "token-dev";
export const supportModels: string[] = [
"GPT-3.5",
"GPT-3.5-16k",
"GPT-4",
"GPT-4-32k",
"Claude-2",
"Claude-2-100k",
"SparkDesk 讯飞星火",
"Palm2",
"New Bing",
"智谱 ChatGLM Pro",
"智谱 ChatGLM Std",
"智谱 ChatGLM Lite",
export const supportModels: Model[] = [
// openai models
{ id: "gpt-3.5-turbo", name: "GPT-3.5", free: true, auth: false },
{ id: "gpt-3.5-turbo-16k", name: "GPT-3.5-16k", free: true, auth: true },
{ id: "gpt-4", name: "GPT-4", free: false, auth: true },
{ id: "gpt-4-32k", name: "GPT-4-32k", free: false, auth: true },

// anthropic models
{ id: "claude-1", name: "Claude-2", free: true, auth: false },
{ id: "claude-2", name: "Claude-2-100k", free: false, auth: true }, // not claude-2-100k

// spark desk
{ id: "spark-desk", name: "SparkDesk 讯飞星火", free: false, auth: true },

// google palm2
{ id: "chat-bison-001", name: "Palm2", free: true, auth: true },

// new bing
{ id: "bing-creative", name: "New Bing", free: true, auth: true },

// zhipu models
{
id: "zhipu-chatglm-pro",
name: "智谱 ChatGLM Pro",
free: false,
auth: true,
},
{
id: "zhipu-chatglm-std",
name: "智谱 ChatGLM Std",
free: false,
auth: true,
},
{
id: "zhipu-chatglm-lite",
name: "智谱 ChatGLM Lite",
free: true,
auth: true,
},
];

export const supportModelConvertor: Record<string, string> = {
Expand Down
9 changes: 5 additions & 4 deletions app/src/conversation/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ export class Connection {
}, 500);
}
} catch {
if (t !== undefined) this.triggerCallback({
message: t("request-failed"),
end: true,
});
if (t !== undefined)
this.triggerCallback({
message: t("request-failed"),
end: true,
});
}
}

Expand Down
Loading

0 comments on commit e31d69a

Please sign in to comment.