diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md
index 73ae8ab..64d5eb2 100644
--- a/CHANGE_LOG.md
+++ b/CHANGE_LOG.md
@@ -13,6 +13,7 @@
- Move all Prisma variable definitions to .env.local
- Standardize the global logo style
- Multiple detailed optimizations
+- Optimize the token consumption calculation logic for more extreme cases.
## v0.4.3
diff --git a/CHANGE_LOG.zh_CN.md b/CHANGE_LOG.zh_CN.md
index 10f3412..86c8e52 100644
--- a/CHANGE_LOG.zh_CN.md
+++ b/CHANGE_LOG.zh_CN.md
@@ -13,6 +13,7 @@
- 将 prisma 变量定义全部移动到.env.local
- 统一全局 Logo 样式
- 多处细节优化
+- 优化更多极限情况下的 token 消耗计算逻辑
## v0.4.3
diff --git a/src/components/chatSection/chatFooter/index.tsx b/src/components/chatSection/chatFooter/index.tsx
index 2ca5e2a..dfee4d3 100644
--- a/src/components/chatSection/chatFooter/index.tsx
+++ b/src/components/chatSection/chatFooter/index.tsx
@@ -69,16 +69,18 @@ const ChatFooter: React.FC = () => {
(item) => item.channel_id === channel.activeId
);
- // stop generate or regenerate
const onGenerate = () => {
+ // stop generate
if (loadingResponseFinish) {
toast.error(t("canceled"));
chatAbort?.abort();
updateStart(false);
updateFinish(false);
+ calcToken();
return;
}
+ // regenerate
const findChannel = channel.list.find(
(item) => item.channel_id === channel.activeId
);
@@ -142,25 +144,7 @@ const ChatFooter: React.FC = () => {
};
// calc current conversation token
- const calcToken = (
- message_list: ChatItem[],
- model: string,
- isFunctional?: boolean
- ) => {
- let calcModel = model;
- const findAzureModel = azure.models.find((item) => item.value === model);
- if (findAzureModel) calcModel = findAzureModel.label;
-
- const tokenInfo = new GPTTokens({
- model: calcModel as supportModelType,
- messages: message_list.map((item) => ({
- role: item.role,
- content: item.content,
- })),
- });
-
- const { usedTokens, usedUSD } = tokenInfo;
-
+ const calcToken = (isFunctional?: boolean) => {
setChannel((channel) => {
const { list, activeId } = channel;
const findChannel = list.find((item) => item.channel_id === activeId);
@@ -177,6 +161,22 @@ const ChatFooter: React.FC = () => {
};
}
+ let calcModel = findChannel.channel_model.name;
+ const findAzureModel = azure.models.find(
+ (item) => item.value === calcModel
+ );
+ if (findAzureModel) calcModel = findAzureModel.label;
+
+ const tokenInfo = new GPTTokens({
+ model: calcModel as supportModelType,
+ messages: findChannel.chat_list.map((item) => ({
+ role: item.role,
+ content: item.content,
+ })),
+ });
+
+ const { usedTokens, usedUSD } = tokenInfo;
+
if (isFunctional) {
findChannel.channel_cost.function_tokens += usedTokens;
const function_usd = findChannel.channel_cost.function_usd + usedUSD;
@@ -324,7 +324,7 @@ const ChatFooter: React.FC = () => {
);
updateFinish(false);
// calc current conversation token
- calcToken(channel_chat_list, params.model);
+ calcToken();
// get gpt title
if (!channel_name) getChannelNameByGPT(channel_id, channel_chat_list);
@@ -395,7 +395,7 @@ const ChatFooter: React.FC = () => {
toast.error(tCommon("service-error"));
}
);
- calcToken(chat_list as ChatItem[], params.model, true);
+ calcToken(true);
});
};
@@ -473,6 +473,7 @@ const ChatFooter: React.FC = () => {
chatAbort?.abort();
updateStart(false);
updateFinish(false);
+ calcToken();
return;
}
setInputValue("");
@@ -507,7 +508,7 @@ const ChatFooter: React.FC = () => {
}
+ leftIcon={}
loading={loadingShare}
onClick={handleShare}
/>
diff --git a/src/components/chatSection/chatList/index.tsx b/src/components/chatSection/chatList/index.tsx
index 9f27b5d..a931ae7 100644
--- a/src/components/chatSection/chatList/index.tsx
+++ b/src/components/chatSection/chatList/index.tsx
@@ -5,6 +5,7 @@ import { useTranslations } from "next-intl";
import { useDateFormat } from "l-hooks";
import CopyIcon from "@/components/copyIcon";
import ChatContent from "@/components/chatContent";
+import Confirm from "@/components/ui/Confirm";
import { useScrollToBottom } from "@/components/scrollToBottoms";
import {
AiOutlineLoading,
@@ -12,14 +13,17 @@ import {
AiOutlineUser,
} from "react-icons/ai";
import { cn } from "@/lib";
-import { useChannel, useRevoke, useChat } from "@/hooks";
+import { GPTTokens } from "@/lib/gpt-tokens";
+import type { supportModelType } from "@/lib/gpt-tokens";
+import { useChannel, useChat, useLLM } from "@/hooks";
import type { ChatItem } from "@/hooks";
import Configure from "./configure";
const ChatList: React.FC = () => {
const session = useSession();
- const t = useTranslations("chat");
const { format } = useDateFormat();
+ const { azure } = useLLM();
+ const t = useTranslations("chat");
const user = session.data?.user;
@@ -32,12 +36,6 @@ const ChatList: React.FC = () => {
const chatList = findChannel?.chat_list || [];
- const { set } = useRevoke({
- revoke: (value) => onRevoke(value),
- tip: t("content-deleted") as string,
- btn: t("undo") as string,
- });
-
const scrollToBottom = useScrollToBottom();
const onDelete = (item: ChatItem) => {
@@ -46,17 +44,29 @@ const ChatList: React.FC = () => {
const { list, activeId } = channel;
const findChannel = list.find((item) => item.channel_id === activeId);
if (!findChannel) return channel;
- const findChatIndex = findChannel.chat_list.findIndex(
- (item) => item.id === id
- );
- set("chatItem", {
- id: activeId,
- index: findChatIndex,
- content: findChannel.chat_list[findChatIndex],
- });
findChannel.chat_list = findChannel.chat_list.filter(
(item) => item.id !== id
);
+
+ let calcModel = findChannel.channel_model.name;
+ const findAzureModel = azure.models.find(
+ (item) => item.value === calcModel
+ );
+ if (findAzureModel) calcModel = findAzureModel.label;
+
+ const tokenInfo = new GPTTokens({
+ model: calcModel as supportModelType,
+ messages: findChannel.chat_list.map((item) => ({
+ role: item.role,
+ content: item.content,
+ })),
+ });
+ // Only updates the tokens required to process the entire content of the current session,
+ // without affecting the tokens that have already been consumed,
+ // and therefore does not affect the value of total_tokens.
+ findChannel.channel_cost.tokens = tokenInfo.usedTokens;
+ findChannel.channel_cost.usd = Number(tokenInfo.usedUSD.toFixed(5));
+
return channel;
});
};
@@ -120,10 +130,18 @@ const ChatList: React.FC = () => {
className="transition-colors hover:text-black/90 dark:hover:text-sky-400/90"
content={item.content}
/>
- onDelete(item)}
- size={19}
+
+
+
+ }
+ onOk={() => onDelete(item)}
/>
diff --git a/src/components/navbar/index.tsx b/src/components/navbar/index.tsx
index 14cedb4..2b6039c 100644
--- a/src/components/navbar/index.tsx
+++ b/src/components/navbar/index.tsx
@@ -79,8 +79,8 @@ const Navbar: React.FC = () => {
"text-slate-700 hover:text-slate-900",
"dark:text-slate-400 dark:hover:text-slate-300",
{
- "top-2": !!activeCost?.total_usd,
- "top-[50%] translate-y-[-50%]": !activeCost?.total_usd,
+ "top-2": !!activeCost?.tokens,
+ "top-[50%] translate-y-[-50%]": !activeCost?.tokens,
}
)}
>
@@ -105,7 +105,7 @@ const Navbar: React.FC = () => {
/>
)}
- {!!activeCost?.total_usd && (
+ {!!activeCost?.tokens && (