accumulated cost

This commit is contained in:
2023-06-14 13:14:28 +08:00
parent 7ded1c8522
commit 280545c224
3 changed files with 57 additions and 17 deletions

View File

@@ -57,6 +57,24 @@ const newChatStore = (
const STORAGE_NAME = "chatgpt-api-web"; const STORAGE_NAME = "chatgpt-api-web";
const STORAGE_NAME_SELECTED = `${STORAGE_NAME}-selected`; const STORAGE_NAME_SELECTED = `${STORAGE_NAME}-selected`;
const STORAGE_NAME_INDEXES = `${STORAGE_NAME}-indexes`; const STORAGE_NAME_INDEXES = `${STORAGE_NAME}-indexes`;
const STORAGE_NAME_TOTALCOST = `${STORAGE_NAME}-totalcost`;
export function addTotalCost(cost: number) {
let totalCost = getTotalCost();
totalCost += cost;
localStorage.setItem(STORAGE_NAME_TOTALCOST, `${totalCost}`);
}
export function getTotalCost(): number {
let totalCost = parseFloat(
localStorage.getItem(STORAGE_NAME_TOTALCOST) ?? "0"
);
return totalCost;
}
export function clearTotalCost() {
localStorage.setItem(STORAGE_NAME_TOTALCOST, `0`);
}
export function App() { export function App() {
// init indexes // init indexes

View File

@@ -1,6 +1,6 @@
import { createRef } from "preact"; import { createRef } from "preact";
import { StateUpdater, useEffect, useState } from "preact/hooks"; import { StateUpdater, useEffect, useState } from "preact/hooks";
import type { ChatStore } from "./app"; import { ChatStore, addTotalCost } from "./app";
import ChatGPT, { import ChatGPT, {
calculate_token_length, calculate_token_length,
ChunkMessage, ChunkMessage,
@@ -84,9 +84,11 @@ export default function ChatBOX(props: {
// console.log("push to history", allChunkMessage); // console.log("push to history", allChunkMessage);
const content = allChunkMessage.join(""); const content = allChunkMessage.join("");
const token = calculate_token_length(content); const token = calculate_token_length(content);
// estimate cost // estimate cost
let cost = 0;
if (chatStore.responseModelName) { if (chatStore.responseModelName) {
chatStore.cost += cost +=
token * token *
(models[chatStore.responseModelName]?.price?.completion ?? 0); (models[chatStore.responseModelName]?.price?.completion ?? 0);
let sum = 0; let sum = 0;
@@ -95,9 +97,12 @@ export default function ChatBOX(props: {
.slice(chatStore.postBeginIndex)) { .slice(chatStore.postBeginIndex)) {
sum += msg.token; sum += msg.token;
} }
chatStore.cost += cost +=
sum * (models[chatStore.responseModelName]?.price?.prompt ?? 0); sum * (models[chatStore.responseModelName]?.price?.prompt ?? 0);
} }
chatStore.cost += cost;
addTotalCost(cost);
chatStore.history.push({ chatStore.history.push({
role: "assistant", role: "assistant",
content, content,
@@ -127,12 +132,15 @@ export default function ChatBOX(props: {
const data = (await response.json()) as FetchResponse; const data = (await response.json()) as FetchResponse;
chatStore.responseModelName = data.model ?? ""; chatStore.responseModelName = data.model ?? "";
if (data.model) { if (data.model) {
chatStore.cost += let cost = 0;
cost +=
(data.usage.prompt_tokens ?? 0) * (data.usage.prompt_tokens ?? 0) *
(models[data.model]?.price?.prompt ?? 0); (models[data.model]?.price?.prompt ?? 0);
chatStore.cost += cost +=
(data.usage.completion_tokens ?? 0) * (data.usage.completion_tokens ?? 0) *
(models[data.model]?.price?.completion ?? 0); (models[data.model]?.price?.completion ?? 0);
chatStore.cost += cost;
addTotalCost(cost);
} }
const content = client.processFetchResponse(data); const content = client.processFetchResponse(data);
@@ -230,13 +238,14 @@ export default function ChatBOX(props: {
const [showSettings, setShowSettings] = useState(false); const [showSettings, setShowSettings] = useState(false);
return ( return (
<div className="grow flex flex-col p-2 dark:text-black"> <div className="grow flex flex-col p-2 dark:text-black">
{showSettings && (
<Settings <Settings
chatStore={chatStore} chatStore={chatStore}
setChatStore={setChatStore} setChatStore={setChatStore}
show={showSettings}
setShow={setShowSettings} setShow={setShowSettings}
selectedChatStoreIndex={props.selectedChatIndex} selectedChatStoreIndex={props.selectedChatIndex}
/> />
)}
<p <p
className="cursor-pointer rounded bg-cyan-300 dark:text-white p-1 dark:bg-cyan-800" className="cursor-pointer rounded bg-cyan-300 dark:text-white p-1 dark:bg-cyan-800"
onClick={() => setShowSettings(true)} onClick={() => setShowSettings(true)}

View File

@@ -1,6 +1,6 @@
import { createRef } from "preact"; import { createRef } from "preact";
import { StateUpdater } from "preact/hooks"; import { StateUpdater, useState } from "preact/hooks";
import { ChatStore } from "./app"; import { ChatStore, clearTotalCost, getTotalCost } from "./app";
import models from "./models"; import models from "./models";
const Help = (props: { children: any; help: string }) => { const Help = (props: { children: any; help: string }) => {
@@ -116,11 +116,9 @@ const Choice = (props: {
export default (props: { export default (props: {
chatStore: ChatStore; chatStore: ChatStore;
setChatStore: (cs: ChatStore) => void; setChatStore: (cs: ChatStore) => void;
show: boolean;
setShow: StateUpdater<boolean>; setShow: StateUpdater<boolean>;
selectedChatStoreIndex: number; selectedChatStoreIndex: number;
}) => { }) => {
if (!props.show) return <div></div>;
const link = const link =
location.protocol + location.protocol +
"//" + "//" +
@@ -135,13 +133,28 @@ export default (props: {
)}`; )}`;
const importFileRef = createRef(); const importFileRef = createRef();
const [totalCost, setTotalCost] = useState(getTotalCost());
return ( return (
<div className="left-0 top-0 overflow-scroll flex justify-center absolute w-screen h-full bg-black bg-opacity-50 z-10"> <div className="left-0 top-0 overflow-scroll flex justify-center absolute w-screen h-full bg-black bg-opacity-50 z-10">
<div className="m-2 p-2 bg-white rounded-lg h-fit"> <div className="m-2 p-2 bg-white rounded-lg h-fit">
<h3 className="text-xl">Settings</h3> <h3 className="text-xl">Settings</h3>
<hr /> <hr />
<div className="flex justify-between">
<p className="m-2 p-2"> <p className="m-2 p-2">
Total cost in this section ${props.chatStore.cost.toFixed(4)} Accumulated cost in all sessions ${totalCost.toFixed(4)}
</p>
<button
className="p-2 m-2 rounded bg-emerald-500"
onClick={() => {
clearTotalCost();
setTotalCost(getTotalCost());
}}
>
Reset
</button>
</div>
<p className="m-2 p-2">
Total cost in this session ${props.chatStore.cost.toFixed(4)}
</p> </p>
<div className="box"> <div className="box">
<Input <Input