diff --git a/.bioserver.env.template b/.bioserver.env.template index be16aff..d38f45f 100644 --- a/.bioserver.env.template +++ b/.bioserver.env.template @@ -1,5 +1,6 @@ # If .bioserver.env doesn't provide OPENAI setup, customers need to set OPENAI API key in website # OPENAI_API_KEY= +# OPENAI_MODEL= # Optional (Azure), # Besides OPENAI_API_KEY, the following envs should be set for Azure @@ -11,3 +12,9 @@ # AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT_NAME= # AZURE_OPENAI_EMBEDDINGS_MODEL= +# data directory for sqlite3 db +DATA_DIR=/app/data + +# daily token limit for server +TOKEN_DAILY_LIMITATION=1_000_000 + diff --git a/CHANGELOG.md b/CHANGELOG.md index b33f548..7fc2ba0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.4.0](https://github.com/fengsh27/chatgse-next-sync/compare/v1.3.5...v1.4.0) (2025-01-06) + + +### Features + +* display token usage ([#14](https://github.com/fengsh27/chatgse-next-sync/issues/14)) ([a9565a4](https://github.com/fengsh27/chatgse-next-sync/commit/a9565a449b852123728651a8bbe816e664ec9668)) + ### [1.3.5](https://github.com/biocypher/biochatter-next/compare/v1.3.4...v1.3.5) (2024-08-26) diff --git a/app/api/rag/connectionstatus/route.ts b/app/api/rag/connectionstatus/route.ts index f10dc0c..342d287 100644 --- a/app/api/rag/connectionstatus/route.ts +++ b/app/api/rag/connectionstatus/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from "next/server"; -import { BioChatterServerResponse, getBaseUrl } from "../../common"; -import { BiochatterPath, ERROR_BIOSERVER_MILVUS_CONNECT_FAILED, ERROR_BIOSERVER_OK, ERROR_BIOSERVER_UNKNOWN } from "@/app/constant"; +import { getBaseUrl } from "../../common"; +import { BiochatterPath } from "@/app/constant"; import { prettyObject } from "@/app/utils/format"; async function handle(request: NextRequest) { diff --git a/app/api/tokenusage/route.ts b/app/api/tokenusage/route.ts new file mode 100644 index 0000000..36df2bc --- /dev/null +++ b/app/api/tokenusage/route.ts @@ -0,0 +1,37 @@ +import { NextRequest, NextResponse } from "next/server"; +import { getBaseUrl } from "../common"; +import { BiochatterPath} from "@/app/constant"; +import { prettyObject } from "@/app/utils/format"; + +async function handle(request: NextRequest) { + const AUTHORIZATION = "Authorization" + const authValue = request.headers.get(AUTHORIZATION) ?? ""; + const baseUrl = getBaseUrl(); + const data = await request.json(); + const path = BiochatterPath.TokenUsage; + const url = `${baseUrl}/${path}`; + try { + const res = await fetch( + url, + { + method: "POST", + headers: { + [AUTHORIZATION]: authValue, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: data.model ?? "gpt-3.5-turbo", + session_id: data.session_id ?? "", + }), + } + ); + const jsonBody = await res.json(); + return NextResponse.json(jsonBody); + } catch (e: any) { + console.error(e); + return NextResponse.json(prettyObject(e)); + } +} + +export const POST = handle; + diff --git a/app/client/api.ts b/app/client/api.ts index 7b7b669..1e38398 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -8,7 +8,7 @@ import { ChatGPTApi } from "./platforms/openai"; export const ROLES = ["system", "user", "assistant"] as const; export type MessageRole = (typeof ROLES)[number]; -export const Models = ["gpt-3.5-turbo", "gpt-4"] as const; +export const Models = ["gpt-3.5-turbo", "gpt-4", "gpt-4o"] as const; export type ChatModel = ModelType; export interface RequestMessage { diff --git a/app/client/datarequest.ts b/app/client/datarequest.ts index 00048c2..a668960 100644 --- a/app/client/datarequest.ts +++ b/app/client/datarequest.ts @@ -121,4 +121,26 @@ export const requestRemoveDocument = async ( } }); return res; +} + +export const requestTokenUsage = async ( + session_id?: string, + model?: string +) => { + const TokenUsage_URL = ApiPath.TokenUsage; + let url = TokenUsage_URL as string; + if (!url.endsWith('/')) { + url += '/'; + } + const res = await fetch(url, { + method: "POST", + body: JSON.stringify({ + "session_id": session_id ?? "", + "model": model ?? "gpt-3.5-turbo", + }), + headers: { + ...get_auth_header() + } + }); + return res; } \ No newline at end of file diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 221e1d2..d2a082b 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -2,11 +2,12 @@ import { ApiPath, DEFAULT_API_HOST, DEFAULT_MODELS, + ERROR_BIOSERVER_EXCEEDS_TOKEN_LIMIT, OpenaiPath, REQUEST_TIMEOUT_MS, ServiceProvider, } from "@/app/constant"; -import { ChatSession, useAccessStore, useAppConfig, useChatStore } from "@/app/store"; +import { useAccessStore, useAppConfig, useChatStore } from "@/app/store"; import { ChatOptions, getHeaders, LLMApi, LLMModel, LLMUsage } from "../api"; import Locale from "../../locales"; @@ -17,9 +18,6 @@ import { import { prettyObject } from "@/app/utils/format"; import { getClientConfig } from "@/app/config/client"; import { makeAzurePath } from "@/app/azure"; -import { useRAGStore } from "@/app/store/rag"; -import { useKGStore } from "@/app/store/kg"; -import { getKnowledgeGraphInfo, getOncoKBInfo, getVectorStoreInfo } from "@/app/utils/prodinfo"; export interface OpenAIListModelResponse { object: string; @@ -236,6 +234,10 @@ export class ChatGPTApi implements LLMApi { clearTimeout(requestTimeoutId); const resJson = await res.json(); + if (resJson.code === ERROR_BIOSERVER_EXCEEDS_TOKEN_LIMIT && options.onFinish) { + options.onFinish(Locale.Chat.TokenLimit(resJson.limitation)); + return; + } const message = this.extractMessage(resJson); options.onFinish(message, resJson.contexts); } diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 7962d46..372d291 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -42,31 +42,15 @@ export function AuthPage() { { accessStore.update( - (access) => (access.accessCode = e.currentTarget.value), + (access) => (access.openaiApiKey = e.currentTarget.value), ); }} /> - {!accessStore.hideUserApiKey ? ( - <> -