2023-05-13 16:29:06 -04:00
|
|
|
const { google } = require('googleapis');
|
2025-09-08 11:35:29 -07:00
|
|
|
const { getModelMaxTokens } = require('@librechat/api');
|
2025-01-27 12:21:33 -05:00
|
|
|
const { concat } = require('@langchain/core/utils/stream');
|
2024-04-16 08:32:40 -04:00
|
|
|
const { ChatVertexAI } = require('@langchain/google-vertexai');
|
2025-06-25 15:14:33 -04:00
|
|
|
const { Tokenizer, getSafetySettings } = require('@librechat/api');
|
2023-12-15 02:18:07 -05:00
|
|
|
const { ChatGoogleGenerativeAI } = require('@langchain/google-genai');
|
2024-04-16 08:32:40 -04:00
|
|
|
const { GoogleGenerativeAI: GenAI } = require('@google/generative-ai');
|
2025-01-27 12:21:33 -05:00
|
|
|
const { HumanMessage, SystemMessage } = require('@langchain/core/messages');
|
2023-12-15 02:18:07 -05:00
|
|
|
const {
|
2025-01-27 12:21:33 -05:00
|
|
|
googleGenConfigSchema,
|
✨ feat: Assistants API, General File Support, Side Panel, File Explorer (#1696)
* feat: assistant name/icon in Landing & Header
* feat: assistname in textarea placeholder, and use `Assistant` as default name
* feat: display non-image files in user messages
* fix: only render files if files.length is > 0
* refactor(config -> file-config): move file related configuration values to separate module, add excel types
* chore: spreadsheet file rendering
* fix(Landing): dark mode style for Assistant Name
* refactor: move progress incrementing to own hook, start smaller, cap near limit \(1\)
* refactor(useContentHandler): add empty Text part if last part was completed tool or image
* chore: add accordion trigger border styling for dark mode
* feat: Assistant Builder model selection
* chore: use Spinner when Assistant is mutating
* fix(get/assistants): return correct response object `AssistantListResponse`
* refactor(Spinner): pass size as prop
* refactor: make assistant crud mutations optimistic, add types for options
* chore: remove assistants route and view
* chore: move assistant builder components to separate directory
* feat(ContextButton): delete Assistant via context button/dialog, add localization
* refactor: conditionally show use and context menu buttons, add localization for create assistant
* feat: save side panel states to localStorage
* style(SidePanel): improve avatar menu and assistant select styling for dark mode
* refactor: make NavToggle reusable for either side (left or right), add SidePanel Toggle with ability to close it completely
* fix: resize handle and navToggle behavior
* fix(/avatar/:assistant_id): await `deleteFile` and assign unique name to uploaded image
* WIP: file UI components from PR #576
* refactor(OpenAIMinimalIcon): pass className
* feat: formatDate helper fn
* feat: DataTableColumnHeader
* feat: add row selection, formatted row values, number of rows selected
* WIP: add files to Side panel temporarily
* feat: `LB_QueueAsyncCall`: Leaky Bucket queue for external APIs, use in `processDeleteRequest`
* fix(TFile): correct `source` type with `FileSources`
* fix(useFileHandling): use `continue` instead of return when iterating multiple files, add file type to extendedFile
* chore: add generic setter type
* refactor(processDeleteRequest): settle promises to prevent rejections from processing deletions, log errors
* feat: `useFileDeletion` to reuse file deletion logic
* refactor(useFileDeletion): make `setFiles` an optional param and use object as param
* feat: useDeleteFilesFromTable
* feat: use real `files` data and add deletion action to data table
* fix(Table): make headers sticky
* feat: add dynamic filtering for columns; only show to user Host or OpenAI storage type
* style(DropdownMenu): replace `slate` with `gray`
* style(DataTable): apply dark mode themes and other misc styling
* style(Columns): add color to OpenAI Storage option
* refactor(FileContainer): make file preview reusable
* refactor(Images): make image preview reusable
* refactor(FilePreview): make file prop optional for FileIcon and FilePreview, fix relative style
* feat(Columns): add file/image previews, set a minimum size to show for file size in bytes
* WIP: File Panel with real files and formatted
* feat: open files dialog from panel
* style: file data table mobile and general column styling fixes
* refactor(api/files): return files sorted by the most recently updated
* refactor: provide fileMap through context to prevent re-selecting files to map in different areas; remove unused imports commented out in PanelColumns
* refactor(ExtendFile): make File type optional, add `attached` to prevent attached files from being deleted on remove, make Message.files a partial TFile type
* feat: attach files through file panel
* refactor(useFileHandling): move files to the start of cache list when uploaded
* refactor(useDeleteFilesMutation): delete files from cache when successfully deleted from server
* fix(FileRow): handle possible edge case of duplication due to attaching recently uploaded file
* style(SidePanel): make resize grip border transparent, remove unnecessary styling on close sidepanel button
* feat: action utilities and tests
* refactor(actions): add `ValidationResult` type and change wording for no server URL found
* refactor(actions): check for empty server URL
* fix(data-provider): revert tsconfig to fix type issue resolution
* feat(client): first pass of actions input for assistants
* refactor(FunctionSignature): change method to output object instead of string
* refactor(models/Assistant): add actions field to schema, use searchParams object for methods, and add `getAssistant`
* feat: post actions input first pass
- create new Action document
- add actions to Assistant DB document
- create /action/:assistant_id POST route
- pass more props down from PanelSwitcher, derive assistant_id from switcher
- move privacy policy to ActionInput
- reset data on input change/validation
- add `useUpdateAction`
- conform FunctionSignature type to FunctionTool
- add action, assistant doc, update hook related types
* refactor: optimize assistant/actions relationship
- past domain in metadata as hostname and not a URL
- include domain in tool name
- add `getActions` for actions retrieval by user
- add `getAssistants` for assistant docs retrieval by user
- add `assistant_id` to Action schema
- move actions to own module as a subroute to `api/assistants`
- add `useGetActionsQuery` and `useGetAssistantDocsQuery` hooks
- fix Action type def
* feat: show assistant actions in assistant builder
* feat: switch to actions on action click, editing action styling
* fix: add Assistant state for builder panel to allow immediate selection of newly created assistants as well as retaining the current assistant when switching to a different panel within the builder
* refactor(SidePanel/NavToggle): offset less from right when SidePanel is completely collapsed
* chore: rename `processActions` -> `processRequiredActions`
* chore: rename Assistant API Action to RequiredAction
* refactor(actions): avoid nesting actual API params under generic `requestBody` to optimize LLM token usage
* fix(handleTools): avoid calling `validTool` if not defined, add optional param to skip the loading of specs, which throws an error in the context of assistants
* WIP: working first pass of toolCalls generated from openapi specs
* WIP: first pass ToolCall styling
* feat: programmatic iv encryption/decryption helpers
* fix: correct ActionAuth types/enums, and define type for AuthForm
* feat: encryption/decryption helpers for Action AuthMetadata
* refactor(getActions): remove sensitive fields from query response
* refactor(POST/actions): encrypt and remove sensitive fields from mutation response
* fix(ActionService): change ESM import to CJS
* feat: frontend auth handling for actions + optimistic update on action update/creation
* refactor(actions): use the correct variables and types for setAuth method
* refactor: POST /:assistant_id action can now handle updating an existing action, add `saved_auth_fields` to determine when user explicitly saves new auth creds. only send auth metadata if user explicitly saved fields
* refactor(createActionTool): catch errors and send back meaningful error message, add flag to `getActions` to determine whether to retrieve sensitive values or not
* refactor(ToolService): add `action` property to ToolCall PartMetadata to determine if the tool call was an action, fix parsing function name issue with actionDelimiter
* fix(ActionRequest): use URL class to correctly join endpoint parts for `execute` call
* feat: delete assistant actions
* refactor: conditionally show Available actions
* refactor: show `retrieval` and `code_interpreter` as Capabilities, swap `Switch` for `Checkbox`
* chore: remove shadow-stroke from messages
* WIP: first pass of Assistants Knowledge attachments
* refactor: remove AssistantsProvider in favor of FormProvider, fix selectedAssistant re-render bug, map Assistant file_ids to files via fileMap, initialize Knowledge component with mapped files if any exist
* fix: prevent deleting files on assistant file upload
* chore: remove console.log
* refactor(useUploadFileMutation): update files and assistants cache on upload
* chore: disable oauth option as not supported yet
* feat: cancel assistant runs
* refactor: initialize OpenAI client with helper function, resolve all related circular dependencies
* fix(DALL-E): initialization
* fix(process): openai client initialization
* fix: select an existing Assistant when the active one is deleted
* chore: allow attaching files for assistant endpoint, send back relevant OpenAI error message when uploading, deconstruct openAI initialization correctly, add `message_file` to formData when a file is attached to the message but not the assistant
* fix: add assistant_id on newConvo
* fix(initializeClient): import fix
* chore: swap setAssistant for setOption in useEffect
* fix(DALL-E): add processFileURL to loadTools call
* chore: add customConfig to debug logs
* feat: delete threads on convo delete
* chore: replace Assistants icon
* chore: remove console.dir() in `abortRun`
* feat(AssistantService): accumulate text values from run in openai.responseText
* feat: titling for assistants endpoint
* chore: move panel file components to appropriate directory, add file checks for attaching files, change icon for Attach Files
* refactor: add localizations to tools, plugins, add condition for adding/remove user plugins so tool selections don't affect this value
* chore: disable `import from url` action for now
* chore: remove textMimeTypes from default fileConfig for now
* fix: catch tool errors and send as outputs with error messages
* fix: React warning about button as descendant of button
* style: retrieval and cancelled icon
* WIP: pass isSubmitting to Parts, use InProgressCall to display cancelled tool calls correctly, show domain/function name
* fix(meilisearch): fix `postSaveHook` issue where indexing expects a mongo document, and join all text content parts for meili indexing
* ci: fix dall-e tests
* ci: fix client tests
* fix: button types in actions panel
* fix: plugin auth form persisting across tool selections
* fix(ci): update AppService spec with `loadAndFormatTools`
* fix(clearConvos): add id check earlier on
* refactor(AssistantAvatar): set previewURL dynamically when emtadata.avatar changes
* feat(assistants): addTitle cache setting
* fix(useSSE): resolve rebase conflicts
* fix: delete mutation
* style(SidePanel): make grip visible on active and hover, invisible otherwise
* ci: add data-provider tests to workflow, also update eslint/tsconfig to recognize specs, and add `text/csv` to fileConfig
* fix: handle edge case where auth object is undefined, and log errors
* refactor(actions): resolve schemas, add tests for resolving refs, import specs from separate file for tests
* chore: remove comment
* fix(ActionsInput): re-render bug when initializing states with action fields
* fix(patch/assistant): filter undefined tools
* chore: add logging for errors in assistants routes
* fix(updateAssistant): map actions to functions to avoid overwriting
* fix(actions): properly handle GET paths
* fix(convos): unhandled delete thread exception
* refactor(AssistantService): pass both thread_id and conversationId when sending intermediate assistant messages, remove `mapMessagesToSteps` from AssistantService
* refactor(useSSE): replace all messages with runMessages and pass latestMessageId to abortRun; fix(checkMessageGaps): include tool calls when syncing messages
* refactor(assistants/chat): invoke `createOnTextProgress` after thread creation
* chore: add typing
* style: sidepanel styling
* style: action tool call domain styling
* feat(assistants): default models, limit retrieval to certain models, add env variables to to env.example
* feat: assistants api key in EndpointService
* refactor: set assistant model to conversation on assistant switch
* refactor: set assistant model to conversation on assistant select from panel
* fix(retrieveAndProcessFile): catch attempt to download file with `assistant` purpose which is not allowed; add logging
* feat: retrieval styling, handling, and logging
* chore: rename ASSISTANTS_REVERSE_PROXY to ASSISTANTS_BASE_URL
* feat: FileContext for file metadata
* feat: context file mgmt and filtering
* style(Select): hover/rounded changes
* refactor: explicit conversation switch, endpoint dependent, through `useSelectAssistant`, which does not create new chat if current endpoint is assistant endpoint
* fix(AssistantAvatar): make empty previewURL if no avatar present
* refactor: side panel mobile styling
* style: merge tool and action section, optimize mobile styling for action/tool buttons
* fix: localStorage issues
* fix(useSelectAssistant): invoke react query hook directly in select hook as Map was not being updated in time
* style: light mode fixes
* fix: prevent sidepanel nav styling from shifting layout up
* refactor: change default layout (collapsed by default)
* style: mobile optimization of DataTable
* style: datatable
* feat: client-side hide right-side panel
* chore(useNewConvo): add partial typing for preset
* fix(useSelectAssistant): pass correct model name by using template as preset
* WIP: assistant presets
* refactor(ToolService): add native solution for `TavilySearchResults` and log tool output errors
* refactor: organize imports and use native TavilySearchResults
* fix(TavilySearchResults): stringify result
* fix(ToolCall): show tool call outputs when not an action
* chore: rename Prompt Prefix to custom instructions (in user facing text only)
* refactor(EditPresetDialog): Optimize setting title by debouncing, reset preset on dialog close to avoid state mixture
* feat: add `presetOverride` to overwrite active conversation settings when saving a Preset (relevant for client side updates only)
* feat: Assistant preset settings (client-side)
* fix(Switcher): only set assistant_id and model if current endpoint is Assistants
* feat: use `useDebouncedInput` for updating conversation settings, starting with EditPresetDialog title setting and Assistant instructions setting
* feat(Assistants): add instructions field to settings
* feat(chat/assistants): pass conversation settings to run body
* wip: begin localization and only allow actions if the assistant is created
* refactor(AssistantsPanel): knowledge localization, allow tools on creation
* feat: experimental: allow 'priming' values before assistant is created, that would normally require an assistant_id to be defined
* chore: trim console logs and make more meaningful
* chore: toast messages
* fix(ci): date test
* feat: create file when uploading Assistant Avatar
* feat: file upload rate limiting from custom config with dynamic file route initialization
* refactor: use file upload limiters on post routes only
* refactor(fileConfig): add endpoints field for endpoint specific fileconfigs, add mergeConfig function, add tests
* refactor: fileConfig route, dynamic multer instances used on all '/' and '/images' POST routes, data service and query hook
* feat: supportedMimeTypesSchema, test for array of regex
* feat: configurable file config limits
* chore: clarify assistants file knowledge prereq.
* chore(useTextarea): default to localized 'Assistant' if assistant name is empty
* feat: configurable file limits and toggle file upload per endpoint
* fix(useUploadFileMutation): prevent updating assistant.files cache if file upload is a message_file attachment
* fix(AssistantSelect): set last selected assistant only when timeout successfully runs
* refactor(queries): disable assistant queries if assistants endpoint is not enabled
* chore(Switcher): add localization
* chore: pluralize `assistant` for `EModelEndpoint key and value
* feat: show/hide assistant UI components based on endpoint availability; librechat.yaml config for disabling builder section and setting polling/timeout intervals
* fix(compactEndpointSchemas): use EModelEndpoint for schema access
* feat(runAssistant): use configured values from `librechat.yaml` for `pollIntervalMs` and `timeout`
* fix: naming issue
* wip: revert landing
* 🎉 happy birthday LibreChat (#1768)
* happy birthday LibreChat
* Refactor endpoint condition in Landing component
* Update birthday message in Eng.tsx
* fix(/config): avoid nesting ternaries
* refactor(/config): check birthday
---------
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
* fix: landing
* fix: landing
* fix(useMessageHelpers): hardcoded check to use EModelEndpoint instead
* fix(ci): convo test revert to main
* fix(assistants/chat): fix issue where assistant_id was being saved as model for convo
* chore: added logging, promises racing to prevent longer timeouts, explicit setting of maxRetries and timeouts, robust catching of invalid abortRun params
* refactor: use recoil state for `showStopButton` and only show for assistants endpoint after syncing conversation data
* refactor: optimize abortRun strategy using localStorage, refactor `abortConversation` to use async/await and await the result, refactor how the abortKey cache is set for runs
* fix(checkMessageGaps): assign `assistant_id` to synced messages if defined; prevents UI from showing blank assistant for cancelled messages
* refactor: re-order sequence of chat route, only allow aborting messages after run is created, cancel abortRun if there was a cancelling error (likely due already cancelled in chat route), and add extra logging
* chore(typedefs): add httpAgent type to OpenAIClient
* refactor: use custom implementation of retrieving run with axios to allow for timing out run query
* fix(waitForRun): handle timed out run retrieval query
* refactor: update preset conditions:
- presets will retain settings when a different endpoint is selected; for existing convos, either when modular or is assistant switch
- no longer use `navigateToConvo` on preset select
* fix: temporary calculator hack as expects string input when invoked
* fix: cancel abortRun only when cancelling error is a result of the run already being cancelled
* chore: remove use of `fileMaxSizeMB` and total counterpart (redundant)
* docs: custom config documentation update
* docs: assistants api setup and dotenv, new custom config fields
* refactor(Switcher): make Assistant switcher sticky in SidePanel
* chore(useSSE): remove console log of data and message index
* refactor(AssistantPanel): button styling and add secondary select button to bottom of panel
* refactor(OpenAIClient): allow passing conversationId to RunManager through titleConvo and initializeLLM to properly record title context tokens used in cases where conversationId was not defined by the client
* feat(assistants): token tracking for assistant runs
* chore(spendTokens): improve logging
* feat: support/exclude specific assistant Ids
* chore: add update `librechat.example.yaml`, optimize `AppService` handling, new tests for `AppService`, optimize missing/outdate config logging
* chore: mount docker logs to root of project
* chore: condense axios errors
* chore: bump vite
* chore: vite hot reload fix using latest version
* chore(getOpenAIModels): sort instruct models to the end of models list
* fix(assistants): user provided key
* fix(assistants): user provided key, invalidate more queries on revoke
---------
Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
2024-02-13 20:42:27 -05:00
|
|
|
validateVisionModel,
|
2023-12-15 02:18:07 -05:00
|
|
|
getResponseSender,
|
|
|
|
endpointSettings,
|
2025-04-07 19:16:56 -04:00
|
|
|
parseTextParts,
|
✨ feat: Assistants API, General File Support, Side Panel, File Explorer (#1696)
* feat: assistant name/icon in Landing & Header
* feat: assistname in textarea placeholder, and use `Assistant` as default name
* feat: display non-image files in user messages
* fix: only render files if files.length is > 0
* refactor(config -> file-config): move file related configuration values to separate module, add excel types
* chore: spreadsheet file rendering
* fix(Landing): dark mode style for Assistant Name
* refactor: move progress incrementing to own hook, start smaller, cap near limit \(1\)
* refactor(useContentHandler): add empty Text part if last part was completed tool or image
* chore: add accordion trigger border styling for dark mode
* feat: Assistant Builder model selection
* chore: use Spinner when Assistant is mutating
* fix(get/assistants): return correct response object `AssistantListResponse`
* refactor(Spinner): pass size as prop
* refactor: make assistant crud mutations optimistic, add types for options
* chore: remove assistants route and view
* chore: move assistant builder components to separate directory
* feat(ContextButton): delete Assistant via context button/dialog, add localization
* refactor: conditionally show use and context menu buttons, add localization for create assistant
* feat: save side panel states to localStorage
* style(SidePanel): improve avatar menu and assistant select styling for dark mode
* refactor: make NavToggle reusable for either side (left or right), add SidePanel Toggle with ability to close it completely
* fix: resize handle and navToggle behavior
* fix(/avatar/:assistant_id): await `deleteFile` and assign unique name to uploaded image
* WIP: file UI components from PR #576
* refactor(OpenAIMinimalIcon): pass className
* feat: formatDate helper fn
* feat: DataTableColumnHeader
* feat: add row selection, formatted row values, number of rows selected
* WIP: add files to Side panel temporarily
* feat: `LB_QueueAsyncCall`: Leaky Bucket queue for external APIs, use in `processDeleteRequest`
* fix(TFile): correct `source` type with `FileSources`
* fix(useFileHandling): use `continue` instead of return when iterating multiple files, add file type to extendedFile
* chore: add generic setter type
* refactor(processDeleteRequest): settle promises to prevent rejections from processing deletions, log errors
* feat: `useFileDeletion` to reuse file deletion logic
* refactor(useFileDeletion): make `setFiles` an optional param and use object as param
* feat: useDeleteFilesFromTable
* feat: use real `files` data and add deletion action to data table
* fix(Table): make headers sticky
* feat: add dynamic filtering for columns; only show to user Host or OpenAI storage type
* style(DropdownMenu): replace `slate` with `gray`
* style(DataTable): apply dark mode themes and other misc styling
* style(Columns): add color to OpenAI Storage option
* refactor(FileContainer): make file preview reusable
* refactor(Images): make image preview reusable
* refactor(FilePreview): make file prop optional for FileIcon and FilePreview, fix relative style
* feat(Columns): add file/image previews, set a minimum size to show for file size in bytes
* WIP: File Panel with real files and formatted
* feat: open files dialog from panel
* style: file data table mobile and general column styling fixes
* refactor(api/files): return files sorted by the most recently updated
* refactor: provide fileMap through context to prevent re-selecting files to map in different areas; remove unused imports commented out in PanelColumns
* refactor(ExtendFile): make File type optional, add `attached` to prevent attached files from being deleted on remove, make Message.files a partial TFile type
* feat: attach files through file panel
* refactor(useFileHandling): move files to the start of cache list when uploaded
* refactor(useDeleteFilesMutation): delete files from cache when successfully deleted from server
* fix(FileRow): handle possible edge case of duplication due to attaching recently uploaded file
* style(SidePanel): make resize grip border transparent, remove unnecessary styling on close sidepanel button
* feat: action utilities and tests
* refactor(actions): add `ValidationResult` type and change wording for no server URL found
* refactor(actions): check for empty server URL
* fix(data-provider): revert tsconfig to fix type issue resolution
* feat(client): first pass of actions input for assistants
* refactor(FunctionSignature): change method to output object instead of string
* refactor(models/Assistant): add actions field to schema, use searchParams object for methods, and add `getAssistant`
* feat: post actions input first pass
- create new Action document
- add actions to Assistant DB document
- create /action/:assistant_id POST route
- pass more props down from PanelSwitcher, derive assistant_id from switcher
- move privacy policy to ActionInput
- reset data on input change/validation
- add `useUpdateAction`
- conform FunctionSignature type to FunctionTool
- add action, assistant doc, update hook related types
* refactor: optimize assistant/actions relationship
- past domain in metadata as hostname and not a URL
- include domain in tool name
- add `getActions` for actions retrieval by user
- add `getAssistants` for assistant docs retrieval by user
- add `assistant_id` to Action schema
- move actions to own module as a subroute to `api/assistants`
- add `useGetActionsQuery` and `useGetAssistantDocsQuery` hooks
- fix Action type def
* feat: show assistant actions in assistant builder
* feat: switch to actions on action click, editing action styling
* fix: add Assistant state for builder panel to allow immediate selection of newly created assistants as well as retaining the current assistant when switching to a different panel within the builder
* refactor(SidePanel/NavToggle): offset less from right when SidePanel is completely collapsed
* chore: rename `processActions` -> `processRequiredActions`
* chore: rename Assistant API Action to RequiredAction
* refactor(actions): avoid nesting actual API params under generic `requestBody` to optimize LLM token usage
* fix(handleTools): avoid calling `validTool` if not defined, add optional param to skip the loading of specs, which throws an error in the context of assistants
* WIP: working first pass of toolCalls generated from openapi specs
* WIP: first pass ToolCall styling
* feat: programmatic iv encryption/decryption helpers
* fix: correct ActionAuth types/enums, and define type for AuthForm
* feat: encryption/decryption helpers for Action AuthMetadata
* refactor(getActions): remove sensitive fields from query response
* refactor(POST/actions): encrypt and remove sensitive fields from mutation response
* fix(ActionService): change ESM import to CJS
* feat: frontend auth handling for actions + optimistic update on action update/creation
* refactor(actions): use the correct variables and types for setAuth method
* refactor: POST /:assistant_id action can now handle updating an existing action, add `saved_auth_fields` to determine when user explicitly saves new auth creds. only send auth metadata if user explicitly saved fields
* refactor(createActionTool): catch errors and send back meaningful error message, add flag to `getActions` to determine whether to retrieve sensitive values or not
* refactor(ToolService): add `action` property to ToolCall PartMetadata to determine if the tool call was an action, fix parsing function name issue with actionDelimiter
* fix(ActionRequest): use URL class to correctly join endpoint parts for `execute` call
* feat: delete assistant actions
* refactor: conditionally show Available actions
* refactor: show `retrieval` and `code_interpreter` as Capabilities, swap `Switch` for `Checkbox`
* chore: remove shadow-stroke from messages
* WIP: first pass of Assistants Knowledge attachments
* refactor: remove AssistantsProvider in favor of FormProvider, fix selectedAssistant re-render bug, map Assistant file_ids to files via fileMap, initialize Knowledge component with mapped files if any exist
* fix: prevent deleting files on assistant file upload
* chore: remove console.log
* refactor(useUploadFileMutation): update files and assistants cache on upload
* chore: disable oauth option as not supported yet
* feat: cancel assistant runs
* refactor: initialize OpenAI client with helper function, resolve all related circular dependencies
* fix(DALL-E): initialization
* fix(process): openai client initialization
* fix: select an existing Assistant when the active one is deleted
* chore: allow attaching files for assistant endpoint, send back relevant OpenAI error message when uploading, deconstruct openAI initialization correctly, add `message_file` to formData when a file is attached to the message but not the assistant
* fix: add assistant_id on newConvo
* fix(initializeClient): import fix
* chore: swap setAssistant for setOption in useEffect
* fix(DALL-E): add processFileURL to loadTools call
* chore: add customConfig to debug logs
* feat: delete threads on convo delete
* chore: replace Assistants icon
* chore: remove console.dir() in `abortRun`
* feat(AssistantService): accumulate text values from run in openai.responseText
* feat: titling for assistants endpoint
* chore: move panel file components to appropriate directory, add file checks for attaching files, change icon for Attach Files
* refactor: add localizations to tools, plugins, add condition for adding/remove user plugins so tool selections don't affect this value
* chore: disable `import from url` action for now
* chore: remove textMimeTypes from default fileConfig for now
* fix: catch tool errors and send as outputs with error messages
* fix: React warning about button as descendant of button
* style: retrieval and cancelled icon
* WIP: pass isSubmitting to Parts, use InProgressCall to display cancelled tool calls correctly, show domain/function name
* fix(meilisearch): fix `postSaveHook` issue where indexing expects a mongo document, and join all text content parts for meili indexing
* ci: fix dall-e tests
* ci: fix client tests
* fix: button types in actions panel
* fix: plugin auth form persisting across tool selections
* fix(ci): update AppService spec with `loadAndFormatTools`
* fix(clearConvos): add id check earlier on
* refactor(AssistantAvatar): set previewURL dynamically when emtadata.avatar changes
* feat(assistants): addTitle cache setting
* fix(useSSE): resolve rebase conflicts
* fix: delete mutation
* style(SidePanel): make grip visible on active and hover, invisible otherwise
* ci: add data-provider tests to workflow, also update eslint/tsconfig to recognize specs, and add `text/csv` to fileConfig
* fix: handle edge case where auth object is undefined, and log errors
* refactor(actions): resolve schemas, add tests for resolving refs, import specs from separate file for tests
* chore: remove comment
* fix(ActionsInput): re-render bug when initializing states with action fields
* fix(patch/assistant): filter undefined tools
* chore: add logging for errors in assistants routes
* fix(updateAssistant): map actions to functions to avoid overwriting
* fix(actions): properly handle GET paths
* fix(convos): unhandled delete thread exception
* refactor(AssistantService): pass both thread_id and conversationId when sending intermediate assistant messages, remove `mapMessagesToSteps` from AssistantService
* refactor(useSSE): replace all messages with runMessages and pass latestMessageId to abortRun; fix(checkMessageGaps): include tool calls when syncing messages
* refactor(assistants/chat): invoke `createOnTextProgress` after thread creation
* chore: add typing
* style: sidepanel styling
* style: action tool call domain styling
* feat(assistants): default models, limit retrieval to certain models, add env variables to to env.example
* feat: assistants api key in EndpointService
* refactor: set assistant model to conversation on assistant switch
* refactor: set assistant model to conversation on assistant select from panel
* fix(retrieveAndProcessFile): catch attempt to download file with `assistant` purpose which is not allowed; add logging
* feat: retrieval styling, handling, and logging
* chore: rename ASSISTANTS_REVERSE_PROXY to ASSISTANTS_BASE_URL
* feat: FileContext for file metadata
* feat: context file mgmt and filtering
* style(Select): hover/rounded changes
* refactor: explicit conversation switch, endpoint dependent, through `useSelectAssistant`, which does not create new chat if current endpoint is assistant endpoint
* fix(AssistantAvatar): make empty previewURL if no avatar present
* refactor: side panel mobile styling
* style: merge tool and action section, optimize mobile styling for action/tool buttons
* fix: localStorage issues
* fix(useSelectAssistant): invoke react query hook directly in select hook as Map was not being updated in time
* style: light mode fixes
* fix: prevent sidepanel nav styling from shifting layout up
* refactor: change default layout (collapsed by default)
* style: mobile optimization of DataTable
* style: datatable
* feat: client-side hide right-side panel
* chore(useNewConvo): add partial typing for preset
* fix(useSelectAssistant): pass correct model name by using template as preset
* WIP: assistant presets
* refactor(ToolService): add native solution for `TavilySearchResults` and log tool output errors
* refactor: organize imports and use native TavilySearchResults
* fix(TavilySearchResults): stringify result
* fix(ToolCall): show tool call outputs when not an action
* chore: rename Prompt Prefix to custom instructions (in user facing text only)
* refactor(EditPresetDialog): Optimize setting title by debouncing, reset preset on dialog close to avoid state mixture
* feat: add `presetOverride` to overwrite active conversation settings when saving a Preset (relevant for client side updates only)
* feat: Assistant preset settings (client-side)
* fix(Switcher): only set assistant_id and model if current endpoint is Assistants
* feat: use `useDebouncedInput` for updating conversation settings, starting with EditPresetDialog title setting and Assistant instructions setting
* feat(Assistants): add instructions field to settings
* feat(chat/assistants): pass conversation settings to run body
* wip: begin localization and only allow actions if the assistant is created
* refactor(AssistantsPanel): knowledge localization, allow tools on creation
* feat: experimental: allow 'priming' values before assistant is created, that would normally require an assistant_id to be defined
* chore: trim console logs and make more meaningful
* chore: toast messages
* fix(ci): date test
* feat: create file when uploading Assistant Avatar
* feat: file upload rate limiting from custom config with dynamic file route initialization
* refactor: use file upload limiters on post routes only
* refactor(fileConfig): add endpoints field for endpoint specific fileconfigs, add mergeConfig function, add tests
* refactor: fileConfig route, dynamic multer instances used on all '/' and '/images' POST routes, data service and query hook
* feat: supportedMimeTypesSchema, test for array of regex
* feat: configurable file config limits
* chore: clarify assistants file knowledge prereq.
* chore(useTextarea): default to localized 'Assistant' if assistant name is empty
* feat: configurable file limits and toggle file upload per endpoint
* fix(useUploadFileMutation): prevent updating assistant.files cache if file upload is a message_file attachment
* fix(AssistantSelect): set last selected assistant only when timeout successfully runs
* refactor(queries): disable assistant queries if assistants endpoint is not enabled
* chore(Switcher): add localization
* chore: pluralize `assistant` for `EModelEndpoint key and value
* feat: show/hide assistant UI components based on endpoint availability; librechat.yaml config for disabling builder section and setting polling/timeout intervals
* fix(compactEndpointSchemas): use EModelEndpoint for schema access
* feat(runAssistant): use configured values from `librechat.yaml` for `pollIntervalMs` and `timeout`
* fix: naming issue
* wip: revert landing
* 🎉 happy birthday LibreChat (#1768)
* happy birthday LibreChat
* Refactor endpoint condition in Landing component
* Update birthday message in Eng.tsx
* fix(/config): avoid nesting ternaries
* refactor(/config): check birthday
---------
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
* fix: landing
* fix: landing
* fix(useMessageHelpers): hardcoded check to use EModelEndpoint instead
* fix(ci): convo test revert to main
* fix(assistants/chat): fix issue where assistant_id was being saved as model for convo
* chore: added logging, promises racing to prevent longer timeouts, explicit setting of maxRetries and timeouts, robust catching of invalid abortRun params
* refactor: use recoil state for `showStopButton` and only show for assistants endpoint after syncing conversation data
* refactor: optimize abortRun strategy using localStorage, refactor `abortConversation` to use async/await and await the result, refactor how the abortKey cache is set for runs
* fix(checkMessageGaps): assign `assistant_id` to synced messages if defined; prevents UI from showing blank assistant for cancelled messages
* refactor: re-order sequence of chat route, only allow aborting messages after run is created, cancel abortRun if there was a cancelling error (likely due already cancelled in chat route), and add extra logging
* chore(typedefs): add httpAgent type to OpenAIClient
* refactor: use custom implementation of retrieving run with axios to allow for timing out run query
* fix(waitForRun): handle timed out run retrieval query
* refactor: update preset conditions:
- presets will retain settings when a different endpoint is selected; for existing convos, either when modular or is assistant switch
- no longer use `navigateToConvo` on preset select
* fix: temporary calculator hack as expects string input when invoked
* fix: cancel abortRun only when cancelling error is a result of the run already being cancelled
* chore: remove use of `fileMaxSizeMB` and total counterpart (redundant)
* docs: custom config documentation update
* docs: assistants api setup and dotenv, new custom config fields
* refactor(Switcher): make Assistant switcher sticky in SidePanel
* chore(useSSE): remove console log of data and message index
* refactor(AssistantPanel): button styling and add secondary select button to bottom of panel
* refactor(OpenAIClient): allow passing conversationId to RunManager through titleConvo and initializeLLM to properly record title context tokens used in cases where conversationId was not defined by the client
* feat(assistants): token tracking for assistant runs
* chore(spendTokens): improve logging
* feat: support/exclude specific assistant Ids
* chore: add update `librechat.example.yaml`, optimize `AppService` handling, new tests for `AppService`, optimize missing/outdate config logging
* chore: mount docker logs to root of project
* chore: condense axios errors
* chore: bump vite
* chore: vite hot reload fix using latest version
* chore(getOpenAIModels): sort instruct models to the end of models list
* fix(assistants): user provided key
* fix(assistants): user provided key, invalidate more queries on revoke
---------
Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
2024-02-13 20:42:27 -05:00
|
|
|
EModelEndpoint,
|
2025-06-25 15:14:33 -04:00
|
|
|
googleSettings,
|
2025-02-06 18:13:18 -05:00
|
|
|
ContentTypes,
|
2024-04-16 08:32:40 -04:00
|
|
|
VisionModes,
|
2025-01-27 12:21:33 -05:00
|
|
|
ErrorTypes,
|
2024-07-17 10:47:17 -04:00
|
|
|
Constants,
|
2023-12-15 02:18:07 -05:00
|
|
|
AuthKeys,
|
|
|
|
} = require('librechat-data-provider');
|
2024-03-06 00:04:52 -05:00
|
|
|
const { encodeAndFormat } = require('~/server/services/Files/images');
|
2025-01-27 12:21:33 -05:00
|
|
|
const { spendTokens } = require('~/models/spendTokens');
|
2024-07-17 10:47:17 -04:00
|
|
|
const { sleep } = require('~/server/utils');
|
2023-12-14 07:49:27 -05:00
|
|
|
const { logger } = require('~/config');
|
2024-06-22 08:42:51 -07:00
|
|
|
const {
|
|
|
|
formatMessage,
|
|
|
|
createContextHandlers,
|
|
|
|
titleInstruction,
|
|
|
|
truncateText,
|
|
|
|
} = require('./prompts');
|
|
|
|
const BaseClient = require('./BaseClient');
|
2023-05-13 16:29:06 -04:00
|
|
|
|
2024-10-16 00:10:48 +02:00
|
|
|
const loc = process.env.GOOGLE_LOC || 'us-central1';
|
2023-12-10 14:54:13 -05:00
|
|
|
const publisher = 'google';
|
2025-06-14 05:51:02 +08:00
|
|
|
const endpointPrefix =
|
|
|
|
loc === 'global' ? 'aiplatform.googleapis.com' : `${loc}-aiplatform.googleapis.com`;
|
2023-05-13 16:29:06 -04:00
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
const settings = endpointSettings[EModelEndpoint.google];
|
2024-11-22 19:08:14 -05:00
|
|
|
const EXCLUDED_GENAI_MODELS = /gemini-(?:1\.0|1-0|pro)/;
|
2023-12-10 14:54:13 -05:00
|
|
|
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
class GoogleClient extends BaseClient {
|
2023-05-13 16:29:06 -04:00
|
|
|
constructor(credentials, options = {}) {
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
super('apiKey', options);
|
2023-12-15 02:18:07 -05:00
|
|
|
let creds = {};
|
|
|
|
|
|
|
|
if (typeof credentials === 'string') {
|
|
|
|
creds = JSON.parse(credentials);
|
|
|
|
} else if (credentials) {
|
|
|
|
creds = credentials;
|
|
|
|
}
|
|
|
|
|
|
|
|
const serviceKey = creds[AuthKeys.GOOGLE_SERVICE_KEY] ?? {};
|
|
|
|
this.serviceKey =
|
2025-02-19 14:53:22 -05:00
|
|
|
serviceKey && typeof serviceKey === 'string' ? JSON.parse(serviceKey) : (serviceKey ?? {});
|
2025-01-27 12:21:33 -05:00
|
|
|
/** @type {string | null | undefined} */
|
|
|
|
this.project_id = this.serviceKey.project_id;
|
2023-12-15 02:18:07 -05:00
|
|
|
this.client_email = this.serviceKey.client_email;
|
|
|
|
this.private_key = this.serviceKey.private_key;
|
2023-12-10 14:54:13 -05:00
|
|
|
this.access_token = null;
|
2023-12-15 02:18:07 -05:00
|
|
|
|
|
|
|
this.apiKey = creds[AuthKeys.GOOGLE_API_KEY];
|
|
|
|
|
2024-12-18 12:13:16 -05:00
|
|
|
this.reverseProxyUrl = options.reverseProxyUrl;
|
|
|
|
|
|
|
|
this.authHeader = options.authHeader;
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
/** @type {UsageMetadata | undefined} */
|
|
|
|
this.usage;
|
|
|
|
/** The key for the usage object's input tokens
|
|
|
|
* @type {string} */
|
|
|
|
this.inputTokensKey = 'input_tokens';
|
|
|
|
/** The key for the usage object's output tokens
|
|
|
|
* @type {string} */
|
|
|
|
this.outputTokensKey = 'output_tokens';
|
2025-02-06 18:13:18 -05:00
|
|
|
this.visionMode = VisionModes.generative;
|
2025-02-19 14:53:22 -05:00
|
|
|
/** @type {string} */
|
|
|
|
this.systemMessage;
|
2023-12-10 14:54:13 -05:00
|
|
|
if (options.skipSetOptions) {
|
|
|
|
return;
|
|
|
|
}
|
2023-05-13 16:29:06 -04:00
|
|
|
this.setOptions(options);
|
|
|
|
}
|
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
/* Google specific methods */
|
2023-05-13 16:29:06 -04:00
|
|
|
constructUrl() {
|
2024-12-18 12:13:16 -05:00
|
|
|
return `https://${endpointPrefix}/v1/projects/${this.project_id}/locations/${loc}/publishers/${publisher}/models/${this.modelOptions.model}:serverStreamingPredict`;
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
|
2023-07-05 14:00:12 -04:00
|
|
|
async getClient() {
|
|
|
|
const scopes = ['https://www.googleapis.com/auth/cloud-platform'];
|
|
|
|
const jwtClient = new google.auth.JWT(this.client_email, null, this.private_key, scopes);
|
|
|
|
|
|
|
|
jwtClient.authorize((err) => {
|
|
|
|
if (err) {
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.error('jwtClient failed to authorize', err);
|
2023-07-05 14:00:12 -04:00
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return jwtClient;
|
|
|
|
}
|
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
async getAccessToken() {
|
|
|
|
const scopes = ['https://www.googleapis.com/auth/cloud-platform'];
|
|
|
|
const jwtClient = new google.auth.JWT(this.client_email, null, this.private_key, scopes);
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
jwtClient.authorize((err, tokens) => {
|
|
|
|
if (err) {
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.error('jwtClient failed to authorize', err);
|
2023-12-10 14:54:13 -05:00
|
|
|
reject(err);
|
|
|
|
} else {
|
|
|
|
resolve(tokens.access_token);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-07-05 14:00:12 -04:00
|
|
|
/* Required Client methods */
|
2023-05-13 16:29:06 -04:00
|
|
|
setOptions(options) {
|
|
|
|
if (this.options && !this.options.replaceOptions) {
|
|
|
|
// nested options aren't spread properly, so we need to do this manually
|
|
|
|
this.options.modelOptions = {
|
|
|
|
...this.options.modelOptions,
|
2023-07-14 09:36:49 -04:00
|
|
|
...options.modelOptions,
|
2023-05-13 16:29:06 -04:00
|
|
|
};
|
|
|
|
delete options.modelOptions;
|
|
|
|
// now we can merge options
|
|
|
|
this.options = {
|
|
|
|
...this.options,
|
2023-07-14 09:36:49 -04:00
|
|
|
...options,
|
2023-05-13 16:29:06 -04:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
this.options = options;
|
|
|
|
}
|
|
|
|
|
2024-08-18 06:00:03 -04:00
|
|
|
this.modelOptions = this.options.modelOptions || {};
|
2023-05-13 16:29:06 -04:00
|
|
|
|
2024-03-19 20:54:30 -04:00
|
|
|
this.options.attachments?.then((attachments) => this.checkVisionRequest(attachments));
|
2024-03-06 00:04:52 -05:00
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
/** @type {boolean} Whether using a "GenerativeAI" Model */
|
2025-05-02 15:11:50 -04:00
|
|
|
this.isGenerativeModel = /gemini|learnlm|gemma/.test(this.modelOptions.model);
|
2023-05-13 16:29:06 -04:00
|
|
|
|
2024-05-09 13:27:13 -04:00
|
|
|
this.maxContextTokens =
|
|
|
|
this.options.maxContextTokens ??
|
|
|
|
getModelMaxTokens(this.modelOptions.model, EModelEndpoint.google);
|
|
|
|
|
2023-05-13 16:29:06 -04:00
|
|
|
// The max prompt tokens is determined by the max context tokens minus the max response tokens.
|
|
|
|
// Earlier messages will be dropped until the prompt is within the limit.
|
2023-12-10 14:54:13 -05:00
|
|
|
this.maxResponseTokens = this.modelOptions.maxOutputTokens || settings.maxOutputTokens.default;
|
2023-12-15 02:18:07 -05:00
|
|
|
|
|
|
|
if (this.maxContextTokens > 32000) {
|
|
|
|
this.maxContextTokens = this.maxContextTokens - this.maxResponseTokens;
|
|
|
|
}
|
|
|
|
|
2023-05-18 11:09:31 -07:00
|
|
|
this.maxPromptTokens =
|
|
|
|
this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
|
2023-05-13 16:29:06 -04:00
|
|
|
|
|
|
|
if (this.maxPromptTokens + this.maxResponseTokens > this.maxContextTokens) {
|
|
|
|
throw new Error(
|
|
|
|
`maxPromptTokens + maxOutputTokens (${this.maxPromptTokens} + ${this.maxResponseTokens} = ${
|
|
|
|
this.maxPromptTokens + this.maxResponseTokens
|
2023-07-14 09:36:49 -04:00
|
|
|
}) must be less than or equal to maxContextTokens (${this.maxContextTokens})`,
|
2023-05-13 16:29:06 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2025-06-25 15:14:33 -04:00
|
|
|
// Add thinking configuration
|
|
|
|
this.modelOptions.thinkingConfig = {
|
|
|
|
thinkingBudget:
|
|
|
|
(this.modelOptions.thinking ?? googleSettings.thinking.default)
|
|
|
|
? this.modelOptions.thinkingBudget
|
|
|
|
: 0,
|
|
|
|
};
|
|
|
|
delete this.modelOptions.thinking;
|
|
|
|
delete this.modelOptions.thinkingBudget;
|
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
this.sender =
|
|
|
|
this.options.sender ??
|
|
|
|
getResponseSender({
|
|
|
|
model: this.modelOptions.model,
|
|
|
|
endpoint: EModelEndpoint.google,
|
|
|
|
modelLabel: this.options.modelLabel,
|
|
|
|
});
|
|
|
|
|
2023-05-13 16:29:06 -04:00
|
|
|
this.userLabel = this.options.userLabel || 'User';
|
|
|
|
this.modelLabel = this.options.modelLabel || 'Assistant';
|
|
|
|
|
|
|
|
if (this.options.reverseProxyUrl) {
|
|
|
|
this.completionsUrl = this.options.reverseProxyUrl;
|
|
|
|
} else {
|
|
|
|
this.completionsUrl = this.constructUrl();
|
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
let promptPrefix = (this.options.promptPrefix ?? '').trim();
|
|
|
|
if (typeof this.options.artifactsPrompt === 'string' && this.options.artifactsPrompt) {
|
|
|
|
promptPrefix = `${promptPrefix ?? ''}\n${this.options.artifactsPrompt}`.trim();
|
|
|
|
}
|
2025-02-19 14:53:22 -05:00
|
|
|
this.systemMessage = promptPrefix;
|
2025-01-27 12:21:33 -05:00
|
|
|
this.initializeClient();
|
2023-05-13 16:29:06 -04:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2024-03-19 20:54:30 -04:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Checks if the model is a vision model based on request attachments and sets the appropriate options:
|
|
|
|
* @param {MongoFile[]} attachments
|
|
|
|
*/
|
|
|
|
checkVisionRequest(attachments) {
|
|
|
|
/* Validation vision request */
|
2025-04-01 15:21:45 -04:00
|
|
|
this.defaultVisionModel =
|
|
|
|
this.options.visionModel ??
|
|
|
|
(!EXCLUDED_GENAI_MODELS.test(this.modelOptions.model)
|
|
|
|
? this.modelOptions.model
|
|
|
|
: 'gemini-pro-vision');
|
2024-03-19 20:54:30 -04:00
|
|
|
const availableModels = this.options.modelsConfig?.[EModelEndpoint.google];
|
|
|
|
this.isVisionModel = validateVisionModel({ model: this.modelOptions.model, availableModels });
|
|
|
|
|
|
|
|
if (
|
|
|
|
attachments &&
|
|
|
|
attachments.some((file) => file?.type && file?.type?.includes('image')) &&
|
|
|
|
availableModels?.includes(this.defaultVisionModel) &&
|
|
|
|
!this.isVisionModel
|
|
|
|
) {
|
|
|
|
this.modelOptions.model = this.defaultVisionModel;
|
|
|
|
this.isVisionModel = true;
|
|
|
|
}
|
|
|
|
|
2024-04-21 08:31:54 -04:00
|
|
|
if (this.isVisionModel && !attachments && this.modelOptions.model.includes('gemini-pro')) {
|
2024-03-19 20:54:30 -04:00
|
|
|
this.modelOptions.model = 'gemini-pro';
|
|
|
|
this.isVisionModel = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
formatMessages() {
|
2025-02-06 18:13:18 -05:00
|
|
|
return ((message) => {
|
|
|
|
const msg = {
|
|
|
|
author: message?.author ?? (message.isCreatedByUser ? this.userLabel : this.modelLabel),
|
|
|
|
content: message?.content ?? message.text,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!message.image_urls?.length) {
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg.content = (
|
|
|
|
!Array.isArray(msg.content)
|
|
|
|
? [
|
2025-05-30 18:16:34 +02:00
|
|
|
{
|
|
|
|
type: ContentTypes.TEXT,
|
|
|
|
[ContentTypes.TEXT]: msg.content,
|
|
|
|
},
|
|
|
|
]
|
2025-02-06 18:13:18 -05:00
|
|
|
: msg.content
|
|
|
|
).concat(message.image_urls);
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
}).bind(this);
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
/**
|
|
|
|
* Formats messages for generative AI
|
|
|
|
* @param {TMessage[]} messages
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
async formatGenerativeMessages(messages) {
|
|
|
|
const formattedMessages = [];
|
|
|
|
const attachments = await this.options.attachments;
|
|
|
|
const latestMessage = { ...messages[messages.length - 1] };
|
|
|
|
const files = await this.addImageURLs(latestMessage, attachments, VisionModes.generative);
|
|
|
|
this.options.attachments = files;
|
|
|
|
messages[messages.length - 1] = latestMessage;
|
|
|
|
|
|
|
|
for (const _message of messages) {
|
|
|
|
const role = _message.isCreatedByUser ? this.userLabel : this.modelLabel;
|
|
|
|
const parts = [];
|
|
|
|
parts.push({ text: _message.text });
|
|
|
|
if (!_message.image_urls?.length) {
|
|
|
|
formattedMessages.push({ role, parts });
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const images of _message.image_urls) {
|
|
|
|
if (images.inlineData) {
|
|
|
|
parts.push({ inlineData: images.inlineData });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
formattedMessages.push({ role, parts });
|
|
|
|
}
|
|
|
|
|
|
|
|
return formattedMessages;
|
|
|
|
}
|
|
|
|
|
2024-03-19 20:54:30 -04:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Adds image URLs to the message object and returns the files
|
|
|
|
*
|
|
|
|
* @param {TMessage[]} messages
|
|
|
|
* @param {MongoFile[]} files
|
|
|
|
* @returns {Promise<MongoFile[]>}
|
|
|
|
*/
|
2024-04-16 08:32:40 -04:00
|
|
|
async addImageURLs(message, attachments, mode = '') {
|
2023-12-16 20:45:27 -05:00
|
|
|
const { files, image_urls } = await encodeAndFormat(
|
|
|
|
this.options.req,
|
2024-03-19 20:54:30 -04:00
|
|
|
attachments,
|
2023-12-16 20:45:27 -05:00
|
|
|
EModelEndpoint.google,
|
2024-04-16 08:32:40 -04:00
|
|
|
mode,
|
2023-12-16 20:45:27 -05:00
|
|
|
);
|
2024-03-19 20:54:30 -04:00
|
|
|
message.image_urls = image_urls.length ? image_urls : undefined;
|
|
|
|
return files;
|
|
|
|
}
|
2023-12-16 20:45:27 -05:00
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
/**
|
|
|
|
* Builds the augmented prompt for attachments
|
|
|
|
* TODO: Add File API Support
|
|
|
|
* @param {TMessage[]} messages
|
|
|
|
*/
|
|
|
|
async buildAugmentedPrompt(messages = []) {
|
2024-03-19 20:54:30 -04:00
|
|
|
const attachments = await this.options.attachments;
|
2023-12-16 20:45:27 -05:00
|
|
|
const latestMessage = { ...messages[messages.length - 1] };
|
2024-03-19 20:54:30 -04:00
|
|
|
this.contextHandlers = createContextHandlers(this.options.req, latestMessage.text);
|
|
|
|
|
|
|
|
if (this.contextHandlers) {
|
|
|
|
for (const file of attachments) {
|
|
|
|
if (file.embedded) {
|
|
|
|
this.contextHandlers?.processFile(file);
|
|
|
|
continue;
|
|
|
|
}
|
🧭 refactor: Modernize Nav/Header (#7094)
* refactor: streamline model preset handling in conversation setup
* refactor: integrate navigation and location hooks in chat functions and event handlers, prevent cache from fetching on final event handling
* fix: prevent adding code interpreter non-image output to file list on message attachment event, fix all unhandled edge cases when this is done (treating the file download as an image attachment, undefined fields, message tokenCount issues, use of `startsWith` on undefined "text") although it is now prevent altogether
* chore: remove unused jailbreak prop from MinimalIcon component in EndpointIcon
* feat: add new SVG icons (MobileSidebar, Sidebar, XAIcon), fix: xAI styling in dark vs. light modes, adjust styling of Landing icons
* fix: open conversation in new tab on navigation with ctrl/meta key
* refactor: update Nav & Header to use close/open sidebar buttons, as well as redesign "New Chat"/"Bookmarks" buttons to the top of the Nav, matching the latest design of ChatGPT for simplicity and to free up space
* chore: remove unused isToggleHovering state and simplify opacity logic in Nav component
* style: match mobile nav to mobile header
2025-04-27 14:03:25 -04:00
|
|
|
if (file.metadata?.fileIdentifier) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-03-19 20:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
this.augmentedPrompt = await this.contextHandlers.createContext();
|
2025-02-19 14:53:22 -05:00
|
|
|
this.systemMessage = this.augmentedPrompt + this.systemMessage;
|
2024-03-19 20:54:30 -04:00
|
|
|
}
|
2024-04-16 08:32:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
async buildVisionMessages(messages = [], parentMessageId) {
|
|
|
|
const attachments = await this.options.attachments;
|
|
|
|
const latestMessage = { ...messages[messages.length - 1] };
|
|
|
|
await this.buildAugmentedPrompt(messages);
|
2024-03-19 20:54:30 -04:00
|
|
|
|
|
|
|
const { prompt } = await this.buildMessagesPrompt(messages, parentMessageId);
|
|
|
|
|
|
|
|
const files = await this.addImageURLs(latestMessage, attachments);
|
2023-12-16 20:45:27 -05:00
|
|
|
|
|
|
|
this.options.attachments = files;
|
|
|
|
|
|
|
|
latestMessage.text = prompt;
|
|
|
|
|
|
|
|
const payload = {
|
|
|
|
instances: [
|
|
|
|
{
|
|
|
|
messages: [new HumanMessage(formatMessage({ message: latestMessage }))],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
return { prompt: payload };
|
|
|
|
}
|
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
/** @param {TMessage[]} [messages=[]] */
|
|
|
|
async buildGenerativeMessages(messages = []) {
|
|
|
|
this.userLabel = 'user';
|
|
|
|
this.modelLabel = 'model';
|
|
|
|
const promises = [];
|
|
|
|
promises.push(await this.formatGenerativeMessages(messages));
|
|
|
|
promises.push(this.buildAugmentedPrompt(messages));
|
|
|
|
const [formattedMessages] = await Promise.all(promises);
|
|
|
|
return { prompt: formattedMessages };
|
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
/**
|
|
|
|
* @param {TMessage[]} [messages=[]]
|
|
|
|
* @param {string} [parentMessageId]
|
|
|
|
*/
|
|
|
|
async buildMessages(_messages = [], parentMessageId) {
|
2023-12-15 02:18:07 -05:00
|
|
|
if (!this.isGenerativeModel && !this.project_id) {
|
2025-01-27 12:21:33 -05:00
|
|
|
throw new Error('[GoogleClient] PaLM 2 and Codey models are no longer supported.');
|
2024-04-16 08:32:40 -04:00
|
|
|
}
|
|
|
|
|
2025-02-19 14:53:22 -05:00
|
|
|
if (this.systemMessage) {
|
|
|
|
const instructionsTokenCount = this.getTokenCount(this.systemMessage);
|
2025-01-27 12:21:33 -05:00
|
|
|
|
|
|
|
this.maxContextTokens = this.maxContextTokens - instructionsTokenCount;
|
|
|
|
if (this.maxContextTokens < 0) {
|
|
|
|
const info = `${instructionsTokenCount} / ${this.maxContextTokens}`;
|
|
|
|
const errorMessage = `{ "type": "${ErrorTypes.INPUT_LENGTH}", "info": "${info}" }`;
|
|
|
|
logger.warn(`Instructions token count exceeds max context (${info}).`);
|
|
|
|
throw new Error(errorMessage);
|
|
|
|
}
|
2023-12-15 02:18:07 -05:00
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
for (let i = 0; i < _messages.length; i++) {
|
|
|
|
const message = _messages[i];
|
|
|
|
if (!message.tokenCount) {
|
|
|
|
_messages[i].tokenCount = this.getTokenCountForMessage({
|
|
|
|
role: message.isCreatedByUser ? 'user' : 'assistant',
|
|
|
|
content: message.content ?? message.text,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const {
|
|
|
|
payload: messages,
|
|
|
|
tokenCountMap,
|
|
|
|
promptTokens,
|
|
|
|
} = await this.handleContextStrategy({
|
|
|
|
orderedMessages: _messages,
|
|
|
|
formattedMessages: _messages,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!this.project_id && !EXCLUDED_GENAI_MODELS.test(this.modelOptions.model)) {
|
|
|
|
const result = await this.buildGenerativeMessages(messages);
|
|
|
|
result.tokenCountMap = tokenCountMap;
|
|
|
|
result.promptTokens = promptTokens;
|
|
|
|
return result;
|
2023-12-16 20:45:27 -05:00
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
if (this.options.attachments && this.isGenerativeModel) {
|
|
|
|
const result = this.buildVisionMessages(messages, parentMessageId);
|
|
|
|
result.tokenCountMap = tokenCountMap;
|
|
|
|
result.promptTokens = promptTokens;
|
|
|
|
return result;
|
2023-12-10 14:54:13 -05:00
|
|
|
}
|
2023-12-16 20:45:27 -05:00
|
|
|
|
2023-05-13 16:29:06 -04:00
|
|
|
let payload = {
|
|
|
|
instances: [
|
|
|
|
{
|
2023-12-16 20:45:27 -05:00
|
|
|
messages: messages
|
|
|
|
.map(this.formatMessages())
|
|
|
|
.map((msg) => ({ ...msg, role: msg.author === 'User' ? 'user' : 'assistant' }))
|
|
|
|
.map((message) => formatMessage({ message, langChain: true })),
|
2023-07-14 09:36:49 -04:00
|
|
|
},
|
2023-05-13 16:29:06 -04:00
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2025-02-19 14:53:22 -05:00
|
|
|
if (this.systemMessage) {
|
|
|
|
payload.instances[0].context = this.systemMessage;
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
|
2023-12-16 20:45:27 -05:00
|
|
|
logger.debug('[GoogleClient] buildMessages', payload);
|
2025-01-27 12:21:33 -05:00
|
|
|
return { prompt: payload, tokenCountMap, promptTokens };
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
async buildMessagesPrompt(messages, parentMessageId) {
|
|
|
|
const orderedMessages = this.constructor.getMessagesForConversation({
|
|
|
|
messages,
|
|
|
|
parentMessageId,
|
|
|
|
});
|
2023-12-16 20:45:27 -05:00
|
|
|
|
|
|
|
logger.debug('[GoogleClient]', {
|
|
|
|
orderedMessages,
|
|
|
|
parentMessageId,
|
|
|
|
});
|
2023-12-10 14:54:13 -05:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
const formattedMessages = orderedMessages.map(this.formatMessages());
|
2023-12-10 14:54:13 -05:00
|
|
|
|
|
|
|
let lastAuthor = '';
|
|
|
|
let groupedMessages = [];
|
|
|
|
|
|
|
|
for (let message of formattedMessages) {
|
|
|
|
// If last author is not same as current author, add to new group
|
|
|
|
if (lastAuthor !== message.author) {
|
|
|
|
groupedMessages.push({
|
|
|
|
author: message.author,
|
|
|
|
content: [message.content],
|
|
|
|
});
|
|
|
|
lastAuthor = message.author;
|
|
|
|
// If same author, append content to the last group
|
|
|
|
} else {
|
|
|
|
groupedMessages[groupedMessages.length - 1].content.push(message.content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let identityPrefix = '';
|
|
|
|
if (this.options.userLabel) {
|
|
|
|
identityPrefix = `\nHuman's name: ${this.options.userLabel}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.options.modelLabel) {
|
|
|
|
identityPrefix = `${identityPrefix}\nYou are ${this.options.modelLabel}`;
|
|
|
|
}
|
|
|
|
|
2025-02-19 14:53:22 -05:00
|
|
|
let promptPrefix = (this.systemMessage ?? '').trim();
|
2023-12-10 14:54:13 -05:00
|
|
|
|
|
|
|
if (identityPrefix) {
|
|
|
|
promptPrefix = `${identityPrefix}${promptPrefix}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prompt AI to respond, empty if last message was from AI
|
|
|
|
let isEdited = lastAuthor === this.modelLabel;
|
|
|
|
const promptSuffix = isEdited ? '' : `${promptPrefix}\n\n${this.modelLabel}:\n`;
|
|
|
|
let currentTokenCount = isEdited
|
|
|
|
? this.getTokenCount(promptPrefix)
|
|
|
|
: this.getTokenCount(promptSuffix);
|
|
|
|
|
|
|
|
let promptBody = '';
|
|
|
|
const maxTokenCount = this.maxPromptTokens;
|
|
|
|
|
|
|
|
const context = [];
|
|
|
|
|
|
|
|
// Iterate backwards through the messages, adding them to the prompt until we reach the max token count.
|
|
|
|
// Do this within a recursive async function so that it doesn't block the event loop for too long.
|
|
|
|
// Also, remove the next message when the message that puts us over the token limit is created by the user.
|
|
|
|
// Otherwise, remove only the exceeding message. This is due to Anthropic's strict payload rule to start with "Human:".
|
|
|
|
const nextMessage = {
|
|
|
|
remove: false,
|
|
|
|
tokenCount: 0,
|
|
|
|
messageString: '',
|
|
|
|
};
|
|
|
|
|
|
|
|
const buildPromptBody = async () => {
|
|
|
|
if (currentTokenCount < maxTokenCount && groupedMessages.length > 0) {
|
|
|
|
const message = groupedMessages.pop();
|
|
|
|
const isCreatedByUser = message.author === this.userLabel;
|
|
|
|
// Use promptPrefix if message is edited assistant'
|
|
|
|
const messagePrefix =
|
|
|
|
isCreatedByUser || !isEdited
|
|
|
|
? `\n\n${message.author}:`
|
|
|
|
: `${promptPrefix}\n\n${message.author}:`;
|
2025-01-27 12:21:33 -05:00
|
|
|
const messageString = `${messagePrefix}\n${message.content}\n`;
|
2023-12-10 14:54:13 -05:00
|
|
|
let newPromptBody = `${messageString}${promptBody}`;
|
|
|
|
|
|
|
|
context.unshift(message);
|
|
|
|
|
|
|
|
const tokenCountForMessage = this.getTokenCount(messageString);
|
|
|
|
const newTokenCount = currentTokenCount + tokenCountForMessage;
|
|
|
|
|
|
|
|
if (!isCreatedByUser) {
|
|
|
|
nextMessage.messageString = messageString;
|
|
|
|
nextMessage.tokenCount = tokenCountForMessage;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newTokenCount > maxTokenCount) {
|
|
|
|
if (!promptBody) {
|
|
|
|
// This is the first message, so we can't add it. Just throw an error.
|
|
|
|
throw new Error(
|
|
|
|
`Prompt is too long. Max token count is ${maxTokenCount}, but prompt is ${newTokenCount} tokens long.`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, ths message would put us over the token limit, so don't add it.
|
|
|
|
// if created by user, remove next message, otherwise remove only this message
|
|
|
|
if (isCreatedByUser) {
|
|
|
|
nextMessage.remove = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
promptBody = newPromptBody;
|
|
|
|
currentTokenCount = newTokenCount;
|
|
|
|
|
|
|
|
// Switch off isEdited after using it for the first time
|
|
|
|
if (isEdited) {
|
|
|
|
isEdited = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// wait for next tick to avoid blocking the event loop
|
|
|
|
await new Promise((resolve) => setImmediate(resolve));
|
|
|
|
return buildPromptBody();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
await buildPromptBody();
|
|
|
|
|
|
|
|
if (nextMessage.remove) {
|
|
|
|
promptBody = promptBody.replace(nextMessage.messageString, '');
|
|
|
|
currentTokenCount -= nextMessage.tokenCount;
|
|
|
|
context.shift();
|
|
|
|
}
|
|
|
|
|
2023-12-16 20:45:27 -05:00
|
|
|
let prompt = `${promptBody}${promptSuffix}`.trim();
|
2023-12-10 14:54:13 -05:00
|
|
|
|
|
|
|
// Add 2 tokens for metadata after all messages have been counted.
|
|
|
|
currentTokenCount += 2;
|
|
|
|
|
|
|
|
// Use up to `this.maxContextTokens` tokens (prompt + response), but try to leave `this.maxTokens` tokens for the response.
|
|
|
|
this.modelOptions.maxOutputTokens = Math.min(
|
|
|
|
this.maxContextTokens - currentTokenCount,
|
|
|
|
this.maxResponseTokens,
|
|
|
|
);
|
|
|
|
|
|
|
|
return { prompt, context };
|
|
|
|
}
|
|
|
|
|
2023-12-15 02:18:07 -05:00
|
|
|
createLLM(clientOptions) {
|
2024-04-16 08:32:40 -04:00
|
|
|
const model = clientOptions.modelName ?? clientOptions.model;
|
2024-10-16 00:10:48 +02:00
|
|
|
clientOptions.location = loc;
|
2024-12-18 12:13:16 -05:00
|
|
|
clientOptions.endpoint = endpointPrefix;
|
|
|
|
|
|
|
|
let requestOptions = null;
|
|
|
|
if (this.reverseProxyUrl) {
|
|
|
|
requestOptions = {
|
|
|
|
baseUrl: this.reverseProxyUrl,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.authHeader) {
|
|
|
|
requestOptions.customHeaders = {
|
|
|
|
Authorization: `Bearer ${this.apiKey}`,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
if (this.project_id != null) {
|
2024-06-22 08:42:51 -07:00
|
|
|
logger.debug('Creating VertexAI client');
|
2025-02-06 18:13:18 -05:00
|
|
|
this.visionMode = undefined;
|
2025-02-04 21:45:43 -05:00
|
|
|
clientOptions.streaming = true;
|
|
|
|
const client = new ChatVertexAI(clientOptions);
|
|
|
|
client.temperature = clientOptions.temperature;
|
|
|
|
client.topP = clientOptions.topP;
|
|
|
|
client.topK = clientOptions.topK;
|
|
|
|
client.topLogprobs = clientOptions.topLogprobs;
|
|
|
|
client.frequencyPenalty = clientOptions.frequencyPenalty;
|
|
|
|
client.presencePenalty = clientOptions.presencePenalty;
|
|
|
|
client.maxOutputTokens = clientOptions.maxOutputTokens;
|
|
|
|
return client;
|
2024-11-22 19:08:14 -05:00
|
|
|
} else if (!EXCLUDED_GENAI_MODELS.test(model)) {
|
2024-06-22 08:42:51 -07:00
|
|
|
logger.debug('Creating GenAI client');
|
2025-01-27 12:21:33 -05:00
|
|
|
return new GenAI(this.apiKey).getGenerativeModel({ model }, requestOptions);
|
2023-12-15 02:18:07 -05:00
|
|
|
}
|
|
|
|
|
2024-06-22 08:42:51 -07:00
|
|
|
logger.debug('Creating Chat Google Generative AI client');
|
2024-04-16 08:32:40 -04:00
|
|
|
return new ChatGoogleGenerativeAI({ ...clientOptions, apiKey: this.apiKey });
|
2023-12-15 02:18:07 -05:00
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
initializeClient() {
|
2025-02-04 21:45:43 -05:00
|
|
|
let clientOptions = { ...this.modelOptions };
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
if (this.project_id) {
|
2023-12-16 20:45:27 -05:00
|
|
|
clientOptions['authOptions'] = {
|
2023-12-10 14:54:13 -05:00
|
|
|
credentials: {
|
2023-12-15 02:18:07 -05:00
|
|
|
...this.serviceKey,
|
2023-12-10 14:54:13 -05:00
|
|
|
},
|
|
|
|
projectId: this.project_id,
|
2023-12-16 20:45:27 -05:00
|
|
|
};
|
|
|
|
}
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2024-04-16 08:32:40 -04:00
|
|
|
if (this.isGenerativeModel && !this.project_id) {
|
2023-12-16 20:45:27 -05:00
|
|
|
clientOptions.modelName = clientOptions.model;
|
|
|
|
delete clientOptions.model;
|
|
|
|
}
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
this.client = this.createLLM(clientOptions);
|
|
|
|
return this.client;
|
|
|
|
}
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
async getCompletion(_payload, options = {}) {
|
|
|
|
const { onProgress, abortController } = options;
|
2025-02-06 18:13:18 -05:00
|
|
|
const safetySettings = getSafetySettings(this.modelOptions.model);
|
2025-01-27 12:21:33 -05:00
|
|
|
const streamRate = this.options.streamRate ?? Constants.DEFAULT_STREAM_RATE;
|
|
|
|
const modelName = this.modelOptions.modelName ?? this.modelOptions.model ?? '';
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2023-12-10 14:54:13 -05:00
|
|
|
let reply = '';
|
2025-02-06 18:13:18 -05:00
|
|
|
/** @type {Error} */
|
|
|
|
let error;
|
2025-01-31 11:22:15 -05:00
|
|
|
try {
|
|
|
|
if (!EXCLUDED_GENAI_MODELS.test(modelName) && !this.project_id) {
|
2025-02-21 15:02:07 -05:00
|
|
|
/** @type {GenerativeModel} */
|
2025-01-31 11:22:15 -05:00
|
|
|
const client = this.client;
|
|
|
|
/** @type {GenerateContentRequest} */
|
|
|
|
const requestOptions = {
|
|
|
|
safetySettings,
|
|
|
|
contents: _payload,
|
|
|
|
generationConfig: googleGenConfigSchema.parse(this.modelOptions),
|
2024-04-16 08:32:40 -04:00
|
|
|
};
|
2025-01-31 11:22:15 -05:00
|
|
|
|
2025-02-19 14:53:22 -05:00
|
|
|
const promptPrefix = (this.systemMessage ?? '').trim();
|
2025-01-31 11:22:15 -05:00
|
|
|
if (promptPrefix.length) {
|
|
|
|
requestOptions.systemInstruction = {
|
|
|
|
parts: [
|
|
|
|
{
|
|
|
|
text: promptPrefix,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const delay = modelName.includes('flash') ? 8 : 15;
|
|
|
|
/** @type {GenAIUsageMetadata} */
|
|
|
|
let usageMetadata;
|
|
|
|
|
2025-02-21 15:02:07 -05:00
|
|
|
abortController.signal.addEventListener(
|
|
|
|
'abort',
|
|
|
|
() => {
|
|
|
|
logger.warn('[GoogleClient] Request was aborted', abortController.signal.reason);
|
|
|
|
},
|
|
|
|
{ once: true },
|
|
|
|
);
|
|
|
|
|
|
|
|
const result = await client.generateContentStream(requestOptions, {
|
|
|
|
signal: abortController.signal,
|
|
|
|
});
|
2025-01-31 11:22:15 -05:00
|
|
|
for await (const chunk of result.stream) {
|
|
|
|
usageMetadata = !usageMetadata
|
|
|
|
? chunk?.usageMetadata
|
|
|
|
: Object.assign(usageMetadata, chunk?.usageMetadata);
|
|
|
|
const chunkText = chunk.text();
|
|
|
|
await this.generateTextStream(chunkText, onProgress, {
|
|
|
|
delay,
|
|
|
|
});
|
|
|
|
reply += chunkText;
|
|
|
|
await sleep(streamRate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (usageMetadata) {
|
|
|
|
this.usage = {
|
|
|
|
input_tokens: usageMetadata.promptTokenCount,
|
|
|
|
output_tokens: usageMetadata.candidatesTokenCount,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply;
|
2024-04-16 08:32:40 -04:00
|
|
|
}
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2025-01-31 11:22:15 -05:00
|
|
|
const { instances } = _payload;
|
|
|
|
const { messages: messages, context } = instances?.[0] ?? {};
|
|
|
|
|
|
|
|
if (!this.isVisionModel && context && messages?.length > 0) {
|
|
|
|
messages.unshift(new SystemMessage(context));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @type {import('@langchain/core/messages').AIMessageChunk['usage_metadata']} */
|
2025-01-27 12:21:33 -05:00
|
|
|
let usageMetadata;
|
2025-02-04 21:45:43 -05:00
|
|
|
/** @type {ChatVertexAI} */
|
|
|
|
const client = this.client;
|
|
|
|
const stream = await client.stream(messages, {
|
2025-01-31 11:22:15 -05:00
|
|
|
signal: abortController.signal,
|
|
|
|
streamUsage: true,
|
|
|
|
safetySettings,
|
|
|
|
});
|
|
|
|
|
|
|
|
let delay = this.options.streamRate || 8;
|
|
|
|
|
|
|
|
if (!this.options.streamRate) {
|
|
|
|
if (this.isGenerativeModel) {
|
|
|
|
delay = 15;
|
|
|
|
}
|
|
|
|
if (modelName.includes('flash')) {
|
|
|
|
delay = 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for await (const chunk of stream) {
|
2025-02-04 21:45:43 -05:00
|
|
|
if (chunk?.usage_metadata) {
|
|
|
|
const metadata = chunk.usage_metadata;
|
|
|
|
for (const key in metadata) {
|
|
|
|
if (Number.isNaN(metadata[key])) {
|
|
|
|
delete metadata[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
usageMetadata = !usageMetadata ? metadata : concat(usageMetadata, metadata);
|
|
|
|
}
|
|
|
|
|
|
|
|
const chunkText = chunk?.content ?? '';
|
2024-05-15 09:02:48 -04:00
|
|
|
await this.generateTextStream(chunkText, onProgress, {
|
|
|
|
delay,
|
2024-04-16 08:32:40 -04:00
|
|
|
});
|
|
|
|
reply += chunkText;
|
|
|
|
}
|
2025-01-27 12:21:33 -05:00
|
|
|
|
|
|
|
if (usageMetadata) {
|
2025-01-31 11:22:15 -05:00
|
|
|
this.usage = usageMetadata;
|
2024-07-17 10:47:17 -04:00
|
|
|
}
|
2025-01-31 11:22:15 -05:00
|
|
|
} catch (e) {
|
2025-02-06 18:13:18 -05:00
|
|
|
error = e;
|
2025-01-31 11:22:15 -05:00
|
|
|
logger.error('[GoogleClient] There was an issue generating the completion', e);
|
2025-01-27 12:21:33 -05:00
|
|
|
}
|
2025-02-06 18:13:18 -05:00
|
|
|
|
|
|
|
if (error != null && reply === '') {
|
|
|
|
const errorMessage = `{ "type": "${ErrorTypes.GoogleError}", "info": "${
|
|
|
|
error.message ?? 'The Google provider failed to generate content, please contact the Admin.'
|
|
|
|
}" }`;
|
|
|
|
throw new Error(errorMessage);
|
|
|
|
}
|
2023-12-10 14:54:13 -05:00
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
2024-06-22 08:42:51 -07:00
|
|
|
/**
|
2025-01-27 12:21:33 -05:00
|
|
|
* Get stream usage as returned by this client's API response.
|
|
|
|
* @returns {UsageMetadata} The stream usage object.
|
2024-06-22 08:42:51 -07:00
|
|
|
*/
|
2025-01-27 12:21:33 -05:00
|
|
|
getStreamUsage() {
|
|
|
|
return this.usage;
|
|
|
|
}
|
2024-06-22 08:42:51 -07:00
|
|
|
|
2025-04-07 19:16:56 -04:00
|
|
|
getMessageMapMethod() {
|
|
|
|
/**
|
|
|
|
* @param {TMessage} msg
|
|
|
|
*/
|
|
|
|
return (msg) => {
|
|
|
|
if (msg.text != null && msg.text && msg.text.startsWith(':::thinking')) {
|
|
|
|
msg.text = msg.text.replace(/:::thinking.*?:::/gs, '').trim();
|
|
|
|
} else if (msg.content != null) {
|
|
|
|
msg.text = parseTextParts(msg.content, true);
|
|
|
|
delete msg.content;
|
|
|
|
}
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
/**
|
|
|
|
* Calculates the correct token count for the current user message based on the token count map and API usage.
|
|
|
|
* Edge case: If the calculation results in a negative value, it returns the original estimate.
|
|
|
|
* If revisiting a conversation with a chat history entirely composed of token estimates,
|
|
|
|
* the cumulative token count going forward should become more accurate as the conversation progresses.
|
|
|
|
* @param {Object} params - The parameters for the calculation.
|
|
|
|
* @param {Record<string, number>} params.tokenCountMap - A map of message IDs to their token counts.
|
|
|
|
* @param {string} params.currentMessageId - The ID of the current message to calculate.
|
|
|
|
* @param {UsageMetadata} params.usage - The usage object returned by the API.
|
|
|
|
* @returns {number} The correct token count for the current user message.
|
|
|
|
*/
|
|
|
|
calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage }) {
|
|
|
|
const originalEstimate = tokenCountMap[currentMessageId] || 0;
|
2024-06-22 08:42:51 -07:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
if (!usage || typeof usage.input_tokens !== 'number') {
|
|
|
|
return originalEstimate;
|
2024-06-22 08:42:51 -07:00
|
|
|
}
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
tokenCountMap[currentMessageId] = 0;
|
|
|
|
const totalTokensFromMap = Object.values(tokenCountMap).reduce((sum, count) => {
|
|
|
|
const numCount = Number(count);
|
|
|
|
return sum + (isNaN(numCount) ? 0 : numCount);
|
|
|
|
}, 0);
|
|
|
|
const totalInputTokens = usage.input_tokens ?? 0;
|
|
|
|
const currentMessageTokens = totalInputTokens - totalTokensFromMap;
|
|
|
|
return currentMessageTokens > 0 ? currentMessageTokens : originalEstimate;
|
|
|
|
}
|
2024-06-22 08:42:51 -07:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
/**
|
|
|
|
* @param {object} params
|
|
|
|
* @param {number} params.promptTokens
|
|
|
|
* @param {number} params.completionTokens
|
|
|
|
* @param {UsageMetadata} [params.usage]
|
|
|
|
* @param {string} [params.model]
|
|
|
|
* @param {string} [params.context='message']
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async recordTokenUsage({ promptTokens, completionTokens, model, context = 'message' }) {
|
|
|
|
await spendTokens(
|
|
|
|
{
|
|
|
|
context,
|
|
|
|
user: this.user ?? this.options.req?.user?.id,
|
|
|
|
conversationId: this.conversationId,
|
|
|
|
model: model ?? this.modelOptions.model,
|
|
|
|
endpointTokenConfig: this.options.endpointTokenConfig,
|
|
|
|
},
|
|
|
|
{ promptTokens, completionTokens },
|
|
|
|
);
|
|
|
|
}
|
2024-06-22 08:42:51 -07:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
/**
|
|
|
|
* Stripped-down logic for generating a title. This uses the non-streaming APIs, since the user does not see titles streaming
|
|
|
|
*/
|
|
|
|
async titleChatCompletion(_payload, options = {}) {
|
2024-06-22 08:42:51 -07:00
|
|
|
let reply = '';
|
2025-02-06 18:13:18 -05:00
|
|
|
const { abortController } = options;
|
2024-06-22 08:42:51 -07:00
|
|
|
|
2025-03-03 19:09:22 -05:00
|
|
|
const model =
|
|
|
|
this.options.titleModel ?? this.modelOptions.modelName ?? this.modelOptions.model ?? '';
|
2025-02-06 18:13:18 -05:00
|
|
|
const safetySettings = getSafetySettings(model);
|
2025-01-27 12:21:33 -05:00
|
|
|
if (!EXCLUDED_GENAI_MODELS.test(model) && !this.project_id) {
|
2024-11-22 19:08:14 -05:00
|
|
|
logger.debug('Identified titling model as GenAI version');
|
2024-06-22 08:42:51 -07:00
|
|
|
/** @type {GenerativeModel} */
|
2025-01-27 12:21:33 -05:00
|
|
|
const client = this.client;
|
2024-06-22 08:42:51 -07:00
|
|
|
const requestOptions = {
|
|
|
|
contents: _payload,
|
2025-01-27 12:21:33 -05:00
|
|
|
safetySettings,
|
|
|
|
generationConfig: {
|
|
|
|
temperature: 0.5,
|
|
|
|
},
|
2024-06-22 08:42:51 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const result = await client.generateContent(requestOptions);
|
|
|
|
reply = result.response?.text();
|
|
|
|
return reply;
|
|
|
|
} else {
|
2025-01-27 12:21:33 -05:00
|
|
|
const { instances } = _payload;
|
|
|
|
const { messages } = instances?.[0] ?? {};
|
|
|
|
const titleResponse = await this.client.invoke(messages, {
|
2024-06-22 08:42:51 -07:00
|
|
|
signal: abortController.signal,
|
|
|
|
timeout: 7000,
|
2025-01-27 12:21:33 -05:00
|
|
|
safetySettings,
|
2024-06-22 08:42:51 -07:00
|
|
|
});
|
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
if (titleResponse.usage_metadata) {
|
|
|
|
await this.recordTokenUsage({
|
|
|
|
model,
|
|
|
|
promptTokens: titleResponse.usage_metadata.input_tokens,
|
|
|
|
completionTokens: titleResponse.usage_metadata.output_tokens,
|
|
|
|
context: 'title',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-06-22 08:42:51 -07:00
|
|
|
reply = titleResponse.content;
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async titleConvo({ text, responseText = '' }) {
|
|
|
|
let title = 'New Chat';
|
|
|
|
const convo = `||>User:
|
|
|
|
"${truncateText(text)}"
|
|
|
|
||>Response:
|
|
|
|
"${JSON.stringify(truncateText(responseText))}"`;
|
|
|
|
|
|
|
|
let { prompt: payload } = await this.buildMessages([
|
|
|
|
{
|
|
|
|
text: `Please generate ${titleInstruction}
|
|
|
|
|
|
|
|
${convo}
|
|
|
|
|
|
|
|
||>Title:`,
|
|
|
|
isCreatedByUser: true,
|
|
|
|
author: this.userLabel,
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
try {
|
2025-01-27 12:21:33 -05:00
|
|
|
this.initializeClient();
|
2024-06-22 08:42:51 -07:00
|
|
|
title = await this.titleChatCompletion(payload, {
|
|
|
|
abortController: new AbortController(),
|
|
|
|
onProgress: () => {},
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
logger.error('[GoogleClient] There was an issue generating the title', e);
|
|
|
|
}
|
2024-06-25 03:02:38 -04:00
|
|
|
logger.debug(`Title response: ${title}`);
|
2024-06-22 08:42:51 -07:00
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
getSaveOptions() {
|
|
|
|
return {
|
2025-01-08 21:57:00 -05:00
|
|
|
endpointType: null,
|
2024-08-27 17:03:16 -04:00
|
|
|
artifacts: this.options.artifacts,
|
2023-07-13 23:59:44 -04:00
|
|
|
promptPrefix: this.options.promptPrefix,
|
2025-01-27 12:21:33 -05:00
|
|
|
maxContextTokens: this.options.maxContextTokens,
|
2023-07-13 23:59:44 -04:00
|
|
|
modelLabel: this.options.modelLabel,
|
🤖 feat: Model Specs & Save Tools per Convo/Preset (#2578)
* WIP: first pass ModelSpecs
* refactor(onSelectEndpoint): use `getConvoSwitchLogic`
* feat: introduce iconURL, greeting, frontend fields for conversations/presets/messages
* feat: conversation.iconURL & greeting in Landing
* feat: conversation.iconURL & greeting in New Chat button
* feat: message.iconURL
* refactor: ConversationIcon -> ConvoIconURL
* WIP: add spec as a conversation field
* refactor: useAppStartup, set spec on initial load for new chat, allow undefined spec, add localStorage keys enum, additional type fields for spec
* feat: handle `showIconInMenu`, `showIconInHeader`, undefined `iconURL` and no specs on initial load
* chore: handle undefined or empty modelSpecs
* WIP: first pass, modelSpec schema for custom config
* refactor: move default filtered tools definition to ToolService
* feat: pass modelSpecs from backend via startupConfig
* refactor: modelSpecs config, return and define list
* fix: react error and include iconURL in responseMessage
* refactor: add iconURL to responseMessage only
* refactor: getIconEndpoint
* refactor: pass TSpecsConfig
* fix(assistants): differentiate compactAssistantSchema, correctly resets shared conversation state with other endpoints
* refactor: assistant id prefix localStorage key
* refactor: add more LocalStorageKeys and replace hardcoded values
* feat: prioritize spec on new chat behavior: last selected modelSpec behavior (localStorage)
* feat: first pass, interface config
* chore: WIP, todo: add warnings based on config.modelSpecs settings.
* feat: enforce modelSpecs if configured
* feat: show config file yaml errors
* chore: delete unused legacy Plugins component
* refactor: set tools to localStorage from recoil store
* chore: add stable recoil setter to useEffect deps
* refactor: save tools to conversation documents
* style(MultiSelectPop): dynamic height, remove unused import
* refactor(react-query): use localstorage keys and pass config to useAvailablePluginsQuery
* feat(utils): add mapPlugins
* refactor(Convo): use conversation.tools if defined, lastSelectedTools if not
* refactor: remove unused legacy code using `useSetOptions`, remove conditional flag `isMultiChat` for using legacy settings
* refactor(PluginStoreDialog): add exhaustive-deps which are stable react state setters
* fix(HeaderOptions): pass `popover` as true
* refactor(useSetStorage): use project enums
* refactor: use LocalStorageKeys enum
* fix: prevent setConversation from setting falsy values in lastSelectedTools
* refactor: use map for availableTools state and available Plugins query
* refactor(updateLastSelectedModel): organize logic better and add note on purpose
* fix(setAgentOption): prevent reseting last model to secondary model for gptPlugins
* refactor(buildDefaultConvo): use enum
* refactor: remove `useSetStorage` and consolidate areas where conversation state is saved to localStorage
* fix: conversations retain tools on refresh
* fix(gptPlugins): prevent nullish tools from being saved
* chore: delete useServerStream
* refactor: move initial plugins logic to useAppStartup
* refactor(MultiSelectDropDown): add more pass-in className props
* feat: use tools in presets
* chore: delete unused usePresetOptions
* refactor: new agentOptions default handling
* chore: note
* feat: add label and custom instructions to agents
* chore: remove 'disabled with tools' message
* style: move plugins to 2nd column in parameters
* fix: TPreset type for agentOptions
* fix: interface controls
* refactor: add interfaceConfig, use Separator within Switcher
* refactor: hide Assistants panel if interface.parameters are disabled
* fix(Header): only modelSpecs if list is greater than 0
* refactor: separate MessageIcon logic from useMessageHelpers for better react rule-following
* fix(AppService): don't use reserved keyword 'interface'
* feat: set existing Icon for custom endpoints through iconURL
* fix(ci): tests passing for App Service
* docs: refactor custom_config.md for readability and better organization, also include missing values
* docs: interface section and re-organize docs
* docs: update modelSpecs info
* chore: remove unused files
* chore: remove unused files
* chore: move useSetIndexOptions
* chore: remove unused file
* chore: move useConversation(s)
* chore: move useDefaultConvo
* chore: move useNavigateToConvo
* refactor: use plugin install hook so it can be used elsewhere
* chore: import order
* update docs
* refactor(OpenAI/Plugins): allow modelLabel as an initial value for chatGptLabel
* chore: remove unused EndpointOptionsPopover and hide 'Save as Preset' button if preset UI visibility disabled
* feat(loadDefaultInterface): issue warnings based on values
* feat: changelog for custom config file
* docs: add additional changelog note
* fix: prevent unavailable tool selection from preset and update availableTools on Plugin installations
* feat: add `filteredTools` option in custom config
* chore: changelog
* fix(MessageIcon): always overwrite conversation.iconURL in messageSettings
* fix(ModelSpecsMenu): icon edge cases
* fix(NewChat): dynamic icon
* fix(PluginsClient): always include endpoint in responseMessage
* fix: always include endpoint and iconURL in responseMessage across different response methods
* feat: interchangeable keys for modelSpec enforcing
2024-04-30 22:11:48 -04:00
|
|
|
iconURL: this.options.iconURL,
|
|
|
|
greeting: this.options.greeting,
|
|
|
|
spec: this.options.spec,
|
2023-07-14 09:36:49 -04:00
|
|
|
...this.modelOptions,
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getBuildMessagesOptions() {
|
2023-12-14 07:49:27 -05:00
|
|
|
// logger.debug('GoogleClient doesn\'t use getBuildMessagesOptions');
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
|
2023-07-05 14:00:12 -04:00
|
|
|
async sendCompletion(payload, opts = {}) {
|
2023-05-13 16:29:06 -04:00
|
|
|
let reply = '';
|
2023-12-16 20:45:27 -05:00
|
|
|
reply = await this.getCompletion(payload, opts);
|
2023-07-05 14:00:12 -04:00
|
|
|
return reply.trim();
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
2024-08-04 20:53:11 -04:00
|
|
|
|
2025-01-03 18:11:14 -05:00
|
|
|
getEncoding() {
|
|
|
|
return 'cl100k_base';
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
}
|
2023-05-13 16:29:06 -04:00
|
|
|
|
2025-01-27 12:21:33 -05:00
|
|
|
async getVertexTokenCount(text) {
|
|
|
|
/** @type {ChatVertexAI} */
|
|
|
|
const client = this.client ?? this.initializeClient();
|
|
|
|
const connection = client.connection;
|
|
|
|
const gAuthClient = connection.client;
|
|
|
|
const tokenEndpoint = `https://${connection._endpoint}/${connection.apiVersion}/projects/${this.project_id}/locations/${connection._location}/publishers/google/models/${connection.model}/:countTokens`;
|
|
|
|
const result = await gAuthClient.request({
|
|
|
|
url: tokenEndpoint,
|
|
|
|
method: 'POST',
|
|
|
|
data: {
|
|
|
|
contents: [{ role: 'user', parts: [{ text }] }],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2025-01-03 18:11:14 -05:00
|
|
|
/**
|
|
|
|
* Returns the token count of a given text. It also checks and resets the tokenizers if necessary.
|
|
|
|
* @param {string} text - The text to get the token count for.
|
|
|
|
* @returns {number} The token count of the given text.
|
|
|
|
*/
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
getTokenCount(text) {
|
2025-01-03 18:11:14 -05:00
|
|
|
const encoding = this.getEncoding();
|
|
|
|
return Tokenizer.getTokenCount(text, encoding);
|
2023-05-13 16:29:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: Client Classes & Azure OpenAI as a separate Endpoint (#532)
* refactor: start new client classes, test localAi support
* feat: create base class, extend chatgpt from base
* refactor(BaseClient.js): change userId parameter to user
refactor(BaseClient.js): change userId parameter to user
feat(OpenAIClient.js): add sendMessage method
refactor(OpenAIClient.js): change getConversation method to use user parameter instead of userId
refactor(OpenAIClient.js): change saveMessageToDatabase method to use user parameter instead of userId
refactor(OpenAIClient.js): change buildPrompt method to use messages parameter instead of orderedMessages
feat(index.js): export client classes
refactor(askGPTPlugins.js): use req.body.token or process.env.OPENAI_API_KEY as OpenAI API key
refactor(index.js): comment out askOpenAI route
feat(index.js): add openAI route
feat(openAI.js): add new route for OpenAI API requests with support for progress updates and aborting requests.
* refactor(BaseClient.js): use optional chaining operator to access messageId property
refactor(OpenAIClient.js): use orderedMessages instead of messages to build prompt
refactor(OpenAIClient.js): use optional chaining operator to access messageId property
refactor(fetch-polyfill.js): remove fetch polyfill
refactor(openAI.js): comment out debug option in clientOptions
* refactor: update import statements and remove unused imports in several files
feat: add getAzureCredentials function to azureUtils module
docs: update comments in azureUtils module
* refactor(utils): rename migrateConversations to migrateDataToFirstUser for clarity and consistency
* feat(chatgpt-client.js): add getAzureCredentials function to retrieve Azure credentials
feat(chatgpt-client.js): use getAzureCredentials function to generate reverseProxyUrl
feat(OpenAIClient.js): add isChatCompletion property to determine if chat completion model is used
feat(OpenAIClient.js): add saveOptions parameter to sendMessage and buildPrompt methods
feat(OpenAIClient.js): modify buildPrompt method to handle chat completion model
feat(openAI.js): modify endpointOption to include modelOptions instead of individual options
refactor(OpenAIClient.js): modify getDelta property to use isChatCompletion property instead of isChatGptModel property
refactor(OpenAIClient.js): modify sendMessage method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify buildPrompt method to use saveOptions parameter instead of modelOptions parameter
refactor(OpenAIClient.js): modify ask method to include endpointOption parameter
* chore: delete draft file
* refactor(OpenAIClient.js): extract sendCompletion method from sendMessage method for reusability
* refactor(BaseClient.js): move sendMessage method to BaseClient class
feat(OpenAIClient.js): inherit from BaseClient class and implement necessary methods and properties for OpenAIClient class.
* refactor(BaseClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
feat(BaseClient.js): add buildMessages method to BaseClient class
fix(ChatGPTClient.js): use message.text instead of message.message
refactor(ChatGPTClient.js): rename buildPromptBody to buildMessagesBody
refactor(ChatGPTClient.js): remove console.debug statement and add debug log for prompt variable
refactor(OpenAIClient.js): move setOptions method to the bottom of the class
feat(OpenAIClient.js): add support for cl100k_base encoding
feat(OpenAIClient.js): add support for unofficial chat GPT models
feat(OpenAIClient.js): add support for custom modelOptions
feat(OpenAIClient.js): add caching for tokenizers
feat(OpenAIClient.js): add freeAndInitializeEncoder method to free and reinitialize tokenizers
refactor(OpenAIClient.js): rename getBuildPromptOptions to getBuildMessagesOptions
refactor(OpenAIClient.js): rename buildPrompt to buildMessages
refactor(OpenAIClient.js): remove endpointOption from ask function arguments in openAI.js
* refactor(ChatGPTClient.js, OpenAIClient.js): improve code readability and consistency
- In ChatGPTClient.js, update the roleLabel and messageString variables to handle cases where the message object does not have an isCreatedByUser property or a role property with a value of 'user'.
- In OpenAIClient.js, rename the freeAndInitializeEncoder method to freeAndResetEncoder to better reflect its functionality. Also, update the method calls to reflect the new name. Additionally, update the getTokenCount method to handle errors by calling the freeAndResetEncoder method instead of the now-renamed freeAndInitializeEncoder method.
* refactor(OpenAIClient.js): extract instructions object to a separate variable and add it to payload after formatted messages
fix(OpenAIClient.js): handle cases where progressMessage.choices is undefined or empty
* refactor(BaseClient.js): extract addInstructions method from sendMessage method
feat(OpenAIClient.js): add maxTokensMap object to map maximum tokens for each model
refactor(OpenAIClient.js): use addInstructions method in buildMessages method instead of manually building the payload list
* refactor(OpenAIClient.js): remove unnecessary condition for modelOptions.model property in buildMessages method
* feat(BaseClient.js): add support for token count tracking and context strategy
feat(OpenAIClient.js): add support for token count tracking and context strategy
feat(Message.js): add tokenCount field to Message schema and updateMessage function
* refactor(BaseClient.js): add support for refining messages based on token limit
feat(OpenAIClient.js): add support for context refinement strategy
refactor(OpenAIClient.js): use context refinement strategy in message sending
refactor(server/index.js): improve code readability by breaking long lines
* refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` for clarity
feat(BaseClient.js): add `refinePrompt` and `refinePromptTemplate` to handle message refinement
feat(BaseClient.js): add `refineMessages` method to refine messages
feat(BaseClient.js): add `handleContextStrategy` method to handle context strategy
feat(OpenAIClient.js): add `abortController` to `buildPrompt` method options
refactor(OpenAIClient.js): change `payload` and `tokenCountMap` to let variables in `handleContextStrategy` method
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `handleContextStrategy` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContextTokens` in `getMessagesWithinTokenLimit` method for consistency
refactor(BaseClient.js): change `remainingContext` to `remainingContext
* chore(openAI.js): comment out contextStrategy option in clientOptions
* chore(openAI.js): comment out debug option in clientOptions object
* test: BaseClient tests in progress
* test: Complete OpenAIClient & BaseClient tests
* fix(OpenAIClient.js): remove unnecessary whitespace
fix(OpenAIClient.js): remove unused variables and comments
fix(OpenAIClient.test.js): combine getTokenCount and freeAndResetEncoder tests
* chore(.eslintrc.js): add rule for maximum of 1 empty line
feat(ask/openAI.js): add abortMessage utility function
fix(ask/openAI.js): handle error and abort message if partial text is less than 2 characters
feat(utils/index.js): export abortMessage utility function
* test: complete additional tests
* feat: Azure OpenAI as a separate endpoint
* chore: remove extraneous console logs
* fix(azureOpenAI): use chatCompletion endpoint
* chore(initializeClient.js): delete initializeClient.js file
chore(askOpenAI.js): delete old OpenAI route handler
chore(handlers.js): remove trailing whitespace in thought variable assignment
* chore(chatgpt-client.js): remove unused chatgpt-client.js file
refactor(index.js): remove askClient import and export from index.js
* chore(chatgpt-client.tokens.js): update test script for memory usage and encoding performance
The test script in `chatgpt-client.tokens.js` has been updated to measure the memory usage and encoding performance of the client. The script now includes information about the initial memory usage, peak memory usage, final memory usage, and memory usage after a timeout. It also provides insights into the number of encoding requests that can be processed per second.
The script has been modified to use the `OpenAIClient` class instead of the `ChatGPTClient` class. Additionally, the number of iterations for the encoding loop has been reduced to 10,000.
A timeout function has been added to simulate a delay of 15 seconds. After the timeout, the memory usage is measured again.
The script now handles uncaught exceptions and logs any errors that occur, except for errors related to failed fetch requests.
Note: This is a test script and should not be used in production
* feat(FakeClient.js): add a new class `FakeClient` that extends `BaseClient` and implements methods for a fake client
feat(FakeClient.js): implement the `setOptions` method to handle options for the fake client
feat(FakeClient.js): implement the `initializeFakeClient` function to initialize a fake client with options and fake messages
fix(OpenAIClient.js): remove duplicate `maxTokensMap` import and use the one from utils
feat(BaseClient): return promptTokens and completionTokens
* refactor(gptPlugins): refactor ChatAgent to PluginsClient, which extends OpenAIClient
* refactor: client paths
* chore(jest.config.js): remove jest.config.js file
* fix(PluginController.js): update file path to manifest.json
feat(gptPlugins.js): add support for aborting messages
refactor(ask/index.js): rename askGPTPlugins to gptPlugins for consistency
* fix(BaseClient.js): fix spacing in generateTextStream function signature
refactor(BaseClient.js): remove unnecessary push to currentMessages in generateUserMessage function
refactor(BaseClient.js): remove unnecessary push to currentMessages in handleStartMethods function
refactor(PluginsClient.js): remove unused variables and date formatting in constructor
refactor(PluginsClient.js): simplify mapping of pastMessages in getCompletionPayload function
* refactor(GoogleClient): GoogleClient now extends BaseClient
* chore(.env.example): add AZURE_OPENAI_MODELS variable
fix(api/routes/ask/gptPlugins.js): enable Azure integration if PLUGINS_USE_AZURE is true
fix(api/routes/endpoints.js): getOpenAIModels function now accepts options, use AZURE_OPENAI_MODELS if PLUGINS_USE_AZURE is true
fix(client/components/Endpoints/OpenAI/Settings.jsx): remove console.log statement
docs(features/azure.md): add documentation for Azure OpenAI integration and environment variables
* fix(e2e:popup): includes the icon + endpoint names in role, name property
2023-07-03 16:51:12 -04:00
|
|
|
module.exports = GoogleClient;
|