accumulated cost
This commit is contained in:
18
src/app.tsx
18
src/app.tsx
@@ -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
|
||||||
|
|||||||
@@ -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">
|
||||||
<Settings
|
{showSettings && (
|
||||||
chatStore={chatStore}
|
<Settings
|
||||||
setChatStore={setChatStore}
|
chatStore={chatStore}
|
||||||
show={showSettings}
|
setChatStore={setChatStore}
|
||||||
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)}
|
||||||
|
|||||||
@@ -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">
|
||||||
|
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">
|
<p className="m-2 p-2">
|
||||||
Total cost in this section ${props.chatStore.cost.toFixed(4)}
|
Total cost in this session ${props.chatStore.cost.toFixed(4)}
|
||||||
</p>
|
</p>
|
||||||
<div className="box">
|
<div className="box">
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
Reference in New Issue
Block a user