mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-21 19:00:13 +01:00
🪙 feat: Assistants Token Balance & other improvements (#2114)
* chore: add assistants to supportsBalanceCheck * feat(Transaction): getTransactions and refactor export of model * refactor: use enum: ViolationTypes.TOKEN_BALANCE * feat(assistants): check balance * refactor(assistants): only add promptBuffer if new convo (for title), and remove endpoint definition * refactor(assistants): Count tokens up to the current context window * fix(Switcher): make Select list explicitly controlled * feat(assistants): use assistant's default model when no model is specified instead of the last selected assistant, prevent assistant_id from being recorded in non-assistant endpoints * chore(assistants/chat): import order * chore: bump librechat-data-provider due to changes
This commit is contained in:
parent
f848d752e0
commit
a9d2d3fe40
13 changed files with 128 additions and 22 deletions
|
|
@ -1,6 +1,5 @@
|
|||
// file deepcode ignore HardcodedNonCryptoSecret: No hardcoded secrets
|
||||
|
||||
import React from 'react';
|
||||
import { ViolationTypes } from 'librechat-data-provider';
|
||||
import type { TOpenAIMessage } from 'librechat-data-provider';
|
||||
import { formatJSON, extractJson, isJson } from '~/utils/json';
|
||||
import CodeBlock from './CodeBlock';
|
||||
|
|
@ -15,7 +14,7 @@ type TMessageLimit = {
|
|||
};
|
||||
|
||||
type TTokenBalance = {
|
||||
type: 'token_balance';
|
||||
type: ViolationTypes;
|
||||
balance: number;
|
||||
tokenCost: number;
|
||||
promptTokens: number;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export default function Switcher({ isCollapsed }: SwitcherProps) {
|
|||
const currentAssistant = assistantMap?.[selectedAssistant ?? ''];
|
||||
|
||||
return (
|
||||
<Select defaultValue={selectedAssistant as string | undefined} onValueChange={onSelect}>
|
||||
<Select value={selectedAssistant as string | undefined} onValueChange={onSelect}>
|
||||
<SelectTrigger
|
||||
className={cn(
|
||||
'flex items-center gap-2 [&>span]:line-clamp-1 [&>span]:flex [&>span]:w-full [&>span]:items-center [&>span]:gap-1 [&>span]:truncate [&_svg]:h-4 [&_svg]:w-4 [&_svg]:shrink-0',
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ import type {
|
|||
TModelsConfig,
|
||||
TEndpointsConfig,
|
||||
} from 'librechat-data-provider';
|
||||
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField } from '~/utils';
|
||||
import {
|
||||
buildDefaultConvo,
|
||||
getDefaultEndpoint,
|
||||
getEndpointField,
|
||||
updateLastSelectedModel,
|
||||
} from '~/utils';
|
||||
import { useDeleteFilesMutation, useListAssistantsQuery } from '~/data-provider';
|
||||
import useOriginNavigate from './useOriginNavigate';
|
||||
import useSetStorage from './useSetStorage';
|
||||
|
|
@ -32,7 +37,8 @@ const useNewConvo = (index = 0) => {
|
|||
const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery();
|
||||
|
||||
const { data: assistants = [] } = useListAssistantsQuery(defaultOrderQuery, {
|
||||
select: (res) => res.data.map(({ id, name, metadata }) => ({ id, name, metadata })),
|
||||
select: (res) =>
|
||||
res.data.map(({ id, name, metadata, model }) => ({ id, name, metadata, model })),
|
||||
});
|
||||
|
||||
const { mutateAsync } = useDeleteFilesMutation({
|
||||
|
|
@ -81,10 +87,30 @@ const useNewConvo = (index = 0) => {
|
|||
conversation.endpointType = undefined;
|
||||
}
|
||||
|
||||
if (!conversation.assistant_id && defaultEndpoint === EModelEndpoint.assistants) {
|
||||
const assistant_id =
|
||||
const isAssistantEndpoint = defaultEndpoint === EModelEndpoint.assistants;
|
||||
|
||||
if (!conversation.assistant_id && isAssistantEndpoint) {
|
||||
conversation.assistant_id =
|
||||
localStorage.getItem(`assistant_id__${index}`) ?? assistants[0]?.id;
|
||||
conversation.assistant_id = assistant_id;
|
||||
}
|
||||
|
||||
if (
|
||||
conversation.assistant_id &&
|
||||
isAssistantEndpoint &&
|
||||
conversation.conversationId === 'new'
|
||||
) {
|
||||
const assistant = assistants.find(
|
||||
(assistant) => assistant.id === conversation.assistant_id,
|
||||
);
|
||||
conversation.model = assistant?.model;
|
||||
updateLastSelectedModel({
|
||||
endpoint: EModelEndpoint.assistants,
|
||||
model: conversation.model,
|
||||
});
|
||||
}
|
||||
|
||||
if (conversation.assistant_id && !isAssistantEndpoint) {
|
||||
conversation.assistant_id = undefined;
|
||||
}
|
||||
|
||||
const models = modelsConfig?.[defaultEndpoint] ?? [];
|
||||
|
|
|
|||
|
|
@ -56,3 +56,18 @@ export function mapEndpoints(endpointsConfig: TEndpointsConfig) {
|
|||
(a, b) => (endpointsConfig?.[a]?.order ?? 0) - (endpointsConfig?.[b]?.order ?? 0),
|
||||
);
|
||||
}
|
||||
|
||||
export function updateLastSelectedModel({
|
||||
endpoint,
|
||||
model,
|
||||
}: {
|
||||
endpoint: string;
|
||||
model: string | undefined;
|
||||
}) {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
const lastSelectedModels = JSON.parse(localStorage.getItem('lastSelectedModel') || '{}');
|
||||
lastSelectedModels[endpoint] = model;
|
||||
localStorage.setItem('lastSelectedModel', JSON.stringify(lastSelectedModels));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue