From bb783f04b294f3d5b899408dc26fae73a7d565c2 Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Tue, 21 Nov 2023 21:58:44 +0800 Subject: [PATCH] update buffer and vision image counter --- adapter/adapter.go | 7 +- adapter/chatgpt/chat.go | 3 +- adapter/chatgpt/processor.go | 13 +- adapter/chatgpt/struct.go | 3 +- adapter/oneapi/chat.go | 3 +- adapter/oneapi/globals.go | 12 -- adapter/oneapi/handler.go | 36 ------ adapter/oneapi/processor.go | 13 +- adapter/sparkdesk/chat.go | 18 ++- adapter/sparkdesk/types.go | 3 +- addition/generation/prompt.go | 1 + app/.env.deeptrain | 2 + app/index.html | 2 +- app/src/api/connection.ts | 1 + app/src/api/conversation.ts | 3 + app/src/api/file.ts | 4 +- app/src/api/types.ts | 1 + app/src/assets/globals.less | 2 +- app/src/assets/pages/chat.less | 1 + app/src/components/Message.tsx | 2 +- .../admin/assemblies/BroadcastTable.tsx | 38 +++--- app/src/components/app/MenuBar.tsx | 11 +- app/src/components/home/ChatSpace.tsx | 17 +-- app/src/components/home/ModelMarket.tsx | 4 +- app/src/conf.ts | 8 +- app/src/dialogs/ApikeyDialog.tsx | 3 +- app/src/dialogs/QuotaDialog.tsx | 3 +- app/src/utils/env.ts | 21 ++- app/vite.config.ts | 10 ++ auth/rule.go | 2 +- globals/types.go | 1 + globals/variables.go | 121 +++++++++--------- manager/chat.go | 14 +- manager/completions.go | 3 +- manager/transhipment.go | 7 +- utils/base.go | 14 ++ utils/buffer.go | 65 +++++++--- utils/image.go | 63 +++++++++ utils/tokenizer.go | 6 +- 39 files changed, 340 insertions(+), 201 deletions(-) delete mode 100644 adapter/oneapi/handler.go create mode 100644 app/.env.deeptrain create mode 100644 utils/image.go diff --git a/adapter/adapter.go b/adapter/adapter.go index 33115e1..06d918a 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -42,13 +42,13 @@ type ChatProps struct { TopK *int Tools *globals.FunctionTools ToolChoice *interface{} + Buffer utils.Buffer } func createChatRequest(props *ChatProps, hook globals.Hook) error { if oneapi.IsHit(props.Model) { - return oneapi.HandleRequest(&oneapi.AdapterProps{ + return oneapi.NewChatInstanceFromConfig().CreateStreamChatRequest(&oneapi.ChatProps{ Model: props.Model, - Plan: props.Plan, Message: props.Message, Token: utils.Multi( props.Token == 0, @@ -61,6 +61,7 @@ func createChatRequest(props *ChatProps, hook globals.Hook) error { TopP: props.TopP, Tools: props.Tools, ToolChoice: props.ToolChoice, + Buffer: props.Buffer, }, hook) } else if globals.IsChatGPTModel(props.Model) { @@ -82,6 +83,7 @@ func createChatRequest(props *ChatProps, hook globals.Hook) error { TopP: props.TopP, Tools: props.Tools, ToolChoice: props.ToolChoice, + Buffer: props.Buffer, }, hook) } else if globals.IsClaudeModel(props.Model) { @@ -102,6 +104,7 @@ func createChatRequest(props *ChatProps, hook globals.Hook) error { Temperature: props.Temperature, TopK: props.TopK, Tools: props.Tools, + Buffer: props.Buffer, }, hook) } else if globals.IsPalm2Model(props.Model) { diff --git a/adapter/chatgpt/chat.go b/adapter/chatgpt/chat.go index 194e4fa..1f9d650 100644 --- a/adapter/chatgpt/chat.go +++ b/adapter/chatgpt/chat.go @@ -17,6 +17,7 @@ type ChatProps struct { TopP *float32 Tools *globals.FunctionTools ToolChoice *interface{} + Buffer utils.Buffer } func (c *ChatInstance) GetChatEndpoint(props *ChatProps) string { @@ -113,7 +114,7 @@ func (c *ChatInstance) CreateStreamChatRequest(props *ChatProps, callback global c.GetHeader(), c.GetChatBody(props, true), func(data string) error { - data, err := c.ProcessLine(instruct, buf, data) + data, err := c.ProcessLine(props.Buffer, instruct, buf, data) chunk += data if err != nil { diff --git a/adapter/chatgpt/processor.go b/adapter/chatgpt/processor.go index 06757b1..c9f5861 100644 --- a/adapter/chatgpt/processor.go +++ b/adapter/chatgpt/processor.go @@ -106,7 +106,15 @@ func getCompletionChoices(form *CompletionResponse) string { return form.Data.Choices[0].Text } -func (c *ChatInstance) ProcessLine(instruct bool, buf, data string) (string, error) { +func getToolCalls(form *ChatStreamResponse) *globals.ToolCalls { + if len(form.Data.Choices) == 0 { + return nil + } + + return form.Data.Choices[0].Delta.ToolCalls +} + +func (c *ChatInstance) ProcessLine(obj utils.Buffer, instruct bool, buf, data string) (string, error) { item := processFormat(buf + data) if isDone(item) { return "", nil @@ -122,7 +130,7 @@ func (c *ChatInstance) ProcessLine(instruct bool, buf, data string) (string, err // recursive call if len(buf) > 0 { - return c.ProcessLine(instruct, "", buf+item) + return c.ProcessLine(obj, instruct, "", buf+item) } if err := processChatErrorResponse(item); err == nil || err.Data.Error.Message == "" { @@ -133,6 +141,7 @@ func (c *ChatInstance) ProcessLine(instruct bool, buf, data string) (string, err } } else { + obj.SetToolCalls(getToolCalls(form)) return getChoices(form), nil } } diff --git a/adapter/chatgpt/struct.go b/adapter/chatgpt/struct.go index 8135aa1..feafe4a 100644 --- a/adapter/chatgpt/struct.go +++ b/adapter/chatgpt/struct.go @@ -52,7 +52,8 @@ func NewChatInstanceFromModel(props *InstanceProps) *ChatInstance { globals.GPT432k, globals.GPT432k0613, globals.GPT432k0314: return NewChatInstanceFromConfig("gpt4") - case globals.GPT3Turbo1106, globals.GPT41106Preview, globals.GPT4Vision, globals.GPT4Dalle, globals.Dalle3, globals.GPT4All: + case globals.GPT3Turbo1106, globals.GPT41106Preview, globals.GPT41106VisionPreview, + globals.GPT4Vision, globals.GPT4Dalle, globals.Dalle3, globals.GPT4All: return NewChatInstanceFromConfig("reverse") case globals.GPT3Turbo, globals.GPT3TurboInstruct, globals.GPT3Turbo0613, globals.GPT3Turbo0301, diff --git a/adapter/oneapi/chat.go b/adapter/oneapi/chat.go index f55ecba..ec22c4f 100644 --- a/adapter/oneapi/chat.go +++ b/adapter/oneapi/chat.go @@ -17,6 +17,7 @@ type ChatProps struct { TopP *float32 `json:"top_p"` Tools *globals.FunctionTools `json:"tools"` ToolChoice *interface{} `json:"tool_choice"` // string or object + Buffer utils.Buffer } func (c *ChatInstance) GetChatEndpoint() string { @@ -69,7 +70,7 @@ func (c *ChatInstance) CreateStreamChatRequest(props *ChatProps, callback global c.GetHeader(), c.GetChatBody(props, true), func(data string) error { - data, err := c.ProcessLine(buf, data) + data, err := c.ProcessLine(props.Buffer, buf, data) if err != nil { if strings.HasPrefix(err.Error(), "oneapi error") { diff --git a/adapter/oneapi/globals.go b/adapter/oneapi/globals.go index d1e0804..f3d5531 100644 --- a/adapter/oneapi/globals.go +++ b/adapter/oneapi/globals.go @@ -12,18 +12,6 @@ var HitModels = []string{ globals.CodeLLaMa34B, globals.CodeLLaMa13B, globals.CodeLLaMa7B, } -func (c *ChatInstance) Process(data string) string { - return data -} - -func (c *ChatInstance) FormatMessage(message []globals.Message) []globals.Message { - return message -} - -func (c *ChatInstance) FormatModel(model string) string { - return model -} - func (c *ChatInstance) GetToken(model string) int { switch model { case globals.Claude1, globals.Claude2: diff --git a/adapter/oneapi/handler.go b/adapter/oneapi/handler.go deleted file mode 100644 index 278d481..0000000 --- a/adapter/oneapi/handler.go +++ /dev/null @@ -1,36 +0,0 @@ -package oneapi - -import ( - "chat/globals" -) - -type AdapterProps struct { - Model string - Plan bool - Infinity bool - Message []globals.Message - Token *int - PresencePenalty *float32 - FrequencyPenalty *float32 - Temperature *float32 - TopP *float32 - Tools *globals.FunctionTools - ToolChoice *interface{} -} - -func HandleRequest(props *AdapterProps, hook globals.Hook) error { - instance := NewChatInstanceFromConfig() - return instance.CreateStreamChatRequest(&ChatProps{ - Model: instance.FormatModel(props.Model), - Message: instance.FormatMessage(props.Message), - Token: props.Token, - PresencePenalty: props.PresencePenalty, - FrequencyPenalty: props.FrequencyPenalty, - Temperature: props.Temperature, - TopP: props.TopP, - Tools: props.Tools, - ToolChoice: props.ToolChoice, - }, func(data string) error { - return hook(instance.Process(data)) - }) -} diff --git a/adapter/oneapi/processor.go b/adapter/oneapi/processor.go index cf73646..6eb8eca 100644 --- a/adapter/oneapi/processor.go +++ b/adapter/oneapi/processor.go @@ -72,7 +72,15 @@ func getChoices(form *ChatStreamResponse) string { return form.Data.Choices[0].Delta.Content } -func (c *ChatInstance) ProcessLine(buf, data string) (string, error) { +func getToolCalls(form *ChatStreamResponse) *globals.ToolCalls { + if len(form.Data.Choices) == 0 { + return nil + } + + return form.Data.Choices[0].Delta.ToolCalls +} + +func (c *ChatInstance) ProcessLine(obj utils.Buffer, buf, data string) (string, error) { item := processFormat(buf + data) if isDone(item) { return "", nil @@ -81,7 +89,7 @@ func (c *ChatInstance) ProcessLine(buf, data string) (string, error) { if form := processChatResponse(item); form == nil { // recursive call if len(buf) > 0 { - return c.ProcessLine("", buf+item) + return c.ProcessLine(obj, "", buf+item) } if err := processChatErrorResponse(item); err == nil { @@ -92,6 +100,7 @@ func (c *ChatInstance) ProcessLine(buf, data string) (string, error) { } } else { + obj.SetToolCalls(getToolCalls(form)) return getChoices(form), nil } } diff --git a/adapter/sparkdesk/chat.go b/adapter/sparkdesk/chat.go index 27a7045..da81be6 100644 --- a/adapter/sparkdesk/chat.go +++ b/adapter/sparkdesk/chat.go @@ -13,6 +13,7 @@ type ChatProps struct { Temperature *float32 TopK *int Tools *globals.FunctionTools + Buffer utils.Buffer } func GetToken(props *ChatProps) *int { @@ -65,6 +66,21 @@ func (c *ChatInstance) GetFunctionCalling(props *ChatProps) *FunctionsPayload { } } +func getChoice(form *ChatResponse, buffer utils.Buffer) string { + resp := form.Payload.Choices.Text + if len(resp) == 0 { + return "" + } + + buffer.SetToolCalls(&globals.ToolCalls{ + globals.ToolCall{ + Type: "text", + Id: globals.ToolCallId(form.Header.Sid), + }, + }) + return resp[0].Content +} + func (c *ChatInstance) CreateStreamChatRequest(props *ChatProps, hook globals.Hook) error { var conn *utils.WebSocket if conn = utils.NewWebsocketClient(c.GenerateUrl()); conn == nil { @@ -102,7 +118,7 @@ func (c *ChatInstance) CreateStreamChatRequest(props *ChatProps, hook globals.Ho return fmt.Errorf("sparkdesk error: %s (sid: %s)", form.Header.Message, form.Header.Sid) } - if err := hook(form.Payload.Choices.Text[0].Content); err != nil { + if err := hook(getChoice(form, props.Buffer)); err != nil { return err } } diff --git a/adapter/sparkdesk/types.go b/adapter/sparkdesk/types.go index f5bbe30..c2da792 100644 --- a/adapter/sparkdesk/types.go +++ b/adapter/sparkdesk/types.go @@ -34,8 +34,7 @@ type FunctionCall struct { } type MessagePayload struct { - Text []Message `json:"text"` - Functions FunctionsPayload `json:"functions"` + Text []Message `json:"text"` } type RequestParameter struct { diff --git a/addition/generation/prompt.go b/addition/generation/prompt.go index e35d45d..65a6cd9 100644 --- a/addition/generation/prompt.go +++ b/addition/generation/prompt.go @@ -21,6 +21,7 @@ func CreateGeneration(model string, prompt string, path string, plan bool, hook Message: message, Plan: plan, Infinity: true, + Buffer: *buffer, }, func(data string) error { buffer.Write(data) hook(buffer, data) diff --git a/app/.env.deeptrain b/app/.env.deeptrain new file mode 100644 index 0000000..539cc75 --- /dev/null +++ b/app/.env.deeptrain @@ -0,0 +1,2 @@ +VITE_USE_DEEPTRAIN=true +VITE_BACKEND_ENDPOINT=https://api.chatnio.net diff --git a/app/index.html b/app/index.html index 7954ec7..5cae1ab 100644 --- a/app/index.html +++ b/app/index.html @@ -9,7 +9,7 @@ - + diff --git a/app/src/api/connection.ts b/app/src/api/connection.ts index b740654..528c91e 100644 --- a/app/src/api/connection.ts +++ b/app/src/api/connection.ts @@ -8,6 +8,7 @@ export type StreamMessage = { quota?: number; message: string; end: boolean; + plan?: boolean; }; export type ChatProps = { diff --git a/app/src/api/conversation.ts b/app/src/api/conversation.ts index 647b893..9aceb2f 100644 --- a/app/src/api/conversation.ts +++ b/app/src/api/conversation.ts @@ -188,11 +188,13 @@ export class Conversation { keyword?: string, quota?: number, end?: boolean, + plan?: boolean, ) { this.data[idx].content += message; if (keyword) this.data[idx].keyword = keyword; if (quota) this.data[idx].quota = quota; this.data[idx].end = end; + this.data[idx].plan = plan; this.triggerCallback(); } @@ -209,6 +211,7 @@ export class Conversation { message.keyword, message.quota, message.end, + message.plan, ); if (message.end) { this.end = true; diff --git a/app/src/api/file.ts b/app/src/api/file.ts index 144c4bb..09610fe 100644 --- a/app/src/api/file.ts +++ b/app/src/api/file.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { blob_api } from "@/conf.ts"; +import { blobEndpoint } from "@/utils/env.ts"; export type BlobParserResponse = { status: boolean; @@ -18,7 +18,7 @@ export type FileArray = FileObject[]; export async function blobParser(file: File): Promise { try { const resp = await axios.post( - `${blob_api}/upload`, + `${blobEndpoint}/upload`, { file }, { headers: { "Content-Type": "multipart/form-data" }, diff --git a/app/src/api/types.ts b/app/src/api/types.ts index af3dc6a..cf3b317 100644 --- a/app/src/api/types.ts +++ b/app/src/api/types.ts @@ -6,6 +6,7 @@ export type Message = { keyword?: string; quota?: number; end?: boolean; + plan?: boolean; }; export type Model = { diff --git a/app/src/assets/globals.less b/app/src/assets/globals.less index 74cda8c..7ee984d 100644 --- a/app/src/assets/globals.less +++ b/app/src/assets/globals.less @@ -54,7 +54,7 @@ --model-card-background: rgba(222,214,200,.2); - --gold: 45, 100%, 50%; + --gold: 45 100% 50%; } .dark { diff --git a/app/src/assets/pages/chat.less b/app/src/assets/pages/chat.less index b5f8310..1b329da 100644 --- a/app/src/assets/pages/chat.less +++ b/app/src/assets/pages/chat.less @@ -111,6 +111,7 @@ .quota { font-size: 14px; color: hsl(var(--text-secondary)); + transition: .25s; } .icon { diff --git a/app/src/components/Message.tsx b/app/src/components/Message.tsx index 5d75d51..1ea4af6 100644 --- a/app/src/components/Message.tsx +++ b/app/src/components/Message.tsx @@ -47,7 +47,7 @@ function MessageSegment(props: MessageProps) { -
+
{(message.quota < 0 ? 0 : message.quota).toFixed(2)} diff --git a/app/src/components/admin/assemblies/BroadcastTable.tsx b/app/src/components/admin/assemblies/BroadcastTable.tsx index 0b66ec7..10046fd 100644 --- a/app/src/components/admin/assemblies/BroadcastTable.tsx +++ b/app/src/components/admin/assemblies/BroadcastTable.tsx @@ -10,26 +10,31 @@ import { useState } from "react"; import { useSelector } from "react-redux"; import { selectInit } from "@/store/auth.ts"; import { useEffectAsync } from "@/utils/hook.ts"; -import {BroadcastInfo, createBroadcast, getBroadcastList} from "@/api/broadcast.ts"; +import { + BroadcastInfo, + createBroadcast, + getBroadcastList, +} from "@/api/broadcast.ts"; import { useTranslation } from "react-i18next"; import { extractMessage } from "@/utils/processor.ts"; import { Button } from "@/components/ui/button.tsx"; -import {Plus, RotateCcw} from "lucide-react"; -import {useToast} from "@/components/ui/use-toast.ts"; +import { Plus, RotateCcw } from "lucide-react"; +import { useToast } from "@/components/ui/use-toast.ts"; import { Dialog, DialogContent, - DialogDescription, DialogFooter, + DialogDescription, + DialogFooter, DialogHeader, DialogTitle, - DialogTrigger + DialogTrigger, } from "@/components/ui/dialog.tsx"; -import {Textarea} from "@/components/ui/textarea.tsx"; -import {DialogClose} from "@radix-ui/react-dialog"; +import { Textarea } from "@/components/ui/textarea.tsx"; +import { DialogClose } from "@radix-ui/react-dialog"; type CreateBroadcastDialogProps = { onCreated?: () => void; -} +}; function CreateBroadcastDialog(props: CreateBroadcastDialogProps) { const { t } = useTranslation(); @@ -43,21 +48,20 @@ function CreateBroadcastDialog(props: CreateBroadcastDialogProps) { const resp = await createBroadcast(broadcast); if (resp.status) { toast({ - title: t('admin.post-success'), - description: t('admin.post-success-prompt'), + title: t("admin.post-success"), + description: t("admin.post-success-prompt"), }); setContent(""); setOpen(false); props.onCreated?.(); } else { toast({ - title: t('admin.post-failed'), - description: t('admin.post-failed-prompt', {reason: resp.error}), + title: t("admin.post-failed"), + description: t("admin.post-failed-prompt", { reason: resp.error }), }); } } - return ( @@ -90,7 +94,7 @@ function CreateBroadcastDialog(props: CreateBroadcastDialogProps) { - ) + ); } function BroadcastTable() { const { t } = useTranslation(); @@ -114,9 +118,9 @@ function BroadcastTable() {
- ( - setData(await getBroadcastList()) - )} /> + setData(await getBroadcastList())} + />
diff --git a/app/src/components/app/MenuBar.tsx b/app/src/components/app/MenuBar.tsx index 1787f22..1a150bf 100644 --- a/app/src/components/app/MenuBar.tsx +++ b/app/src/components/app/MenuBar.tsx @@ -27,6 +27,7 @@ import { openDialog as openInvitationDialog } from "@/store/invitation.ts"; import { openDialog as openSharingDialog } from "@/store/sharing.ts"; import { openDialog as openApiDialog } from "@/store/api.ts"; import router from "@/router.tsx"; +import { useDeeptrain } from "@/utils/env.ts"; type MenuBarProps = { children: React.ReactNode; @@ -58,10 +59,12 @@ function MenuBar({ children, className }: MenuBarProps) { {t("sub.title")} - dispatch(openPackageDialog())}> - - {t("pkg.title")} - + {useDeeptrain && ( + dispatch(openPackageDialog())}> + + {t("pkg.title")} + + )} dispatch(openInvitationDialog())}> {t("invitation.title")} diff --git a/app/src/components/home/ChatSpace.tsx b/app/src/components/home/ChatSpace.tsx index f536613..aaf1848 100644 --- a/app/src/components/home/ChatSpace.tsx +++ b/app/src/components/home/ChatSpace.tsx @@ -20,6 +20,7 @@ import { } from "@/components/ui/dialog.tsx"; import { getLanguage } from "@/i18n.ts"; import { selectAuthenticated } from "@/store/auth.ts"; +import { docsEndpoint, useDeeptrain } from "@/utils/env.ts"; function ChatSpace() { const [open, setOpen] = useState(false); @@ -31,11 +32,13 @@ function ChatSpace() { return (
- + {useDeeptrain && ( + + )} {subscription && (