mirror of
https://github.com/voideditor/void
synced 2026-05-24 01:48:25 +00:00
models
This commit is contained in:
parent
2c2714273e
commit
fd5e523434
5 changed files with 73 additions and 573 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -113,7 +113,7 @@
|
|||
"files.insertFinalNewline": false
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "ms-vsliveshare.vsliveshare",
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascript]": {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export const toLLMChatMessage = (c: ChatMessage): LLMChatMessage => {
|
|||
}
|
||||
|
||||
|
||||
type _InternalSendFIMMessage = {
|
||||
export type LLMFIMMessage = {
|
||||
prefix: string;
|
||||
suffix: string;
|
||||
stopTokens: string[];
|
||||
|
|
@ -77,7 +77,7 @@ type SendLLMType = {
|
|||
tools?: InternalToolInfo[];
|
||||
} | {
|
||||
messagesType: 'FIMMessage';
|
||||
messages: _InternalSendFIMMessage;
|
||||
messages: LLMFIMMessage;
|
||||
tools?: undefined;
|
||||
}
|
||||
|
||||
|
|
@ -118,38 +118,6 @@ export type EventLLMMessageOnFinalMessageParams = Parameters<OnFinalMessage>[0]
|
|||
export type EventLLMMessageOnErrorParams = Parameters<OnError>[0] & { requestId: string }
|
||||
|
||||
|
||||
export type _InternalSendLLMChatMessageFnType = (
|
||||
params: {
|
||||
aiInstructions: string;
|
||||
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
providerName: ProviderName;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
modelName: string;
|
||||
_setAborter: (aborter: () => void) => void;
|
||||
|
||||
tools?: InternalToolInfo[],
|
||||
|
||||
messages: LLMChatMessage[];
|
||||
}
|
||||
) => void
|
||||
|
||||
export type _InternalSendLLMFIMMessageFnType = (
|
||||
params: {
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
providerName: ProviderName;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
modelName: string;
|
||||
_setAborter: (aborter: () => void) => void;
|
||||
|
||||
messages: _InternalSendFIMMessage;
|
||||
}
|
||||
) => void
|
||||
|
||||
// service -> main -> internal -> event (back to main)
|
||||
// (browser)
|
||||
|
||||
|
|
@ -190,10 +158,10 @@ export type OpenaiCompatibleModelResponse = {
|
|||
|
||||
|
||||
// params to the true list fn
|
||||
export type ModelListParams<modelResponse> = {
|
||||
export type ModelListParams<ModelResponse> = {
|
||||
providerName: ProviderName;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
onSuccess: (param: { models: modelResponse[] }) => void;
|
||||
onSuccess: (param: { models: ModelResponse[] }) => void;
|
||||
onError: (param: { error: string }) => void;
|
||||
}
|
||||
|
||||
|
|
@ -212,4 +180,3 @@ export type EventModelListOnErrorParams<modelResponse> = Parameters<ModelListPar
|
|||
|
||||
|
||||
|
||||
export type _InternalModelListFnType<modelResponse> = (params: ModelListParams<modelResponse>) => void
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ export const voidTools = {
|
|||
export type ToolName = keyof typeof voidTools
|
||||
export const toolNames = Object.keys(voidTools) as ToolName[]
|
||||
|
||||
const toolNamesSet = new Set<string>(toolNames)
|
||||
export const isAToolName = (toolName: string): toolName is ToolName => {
|
||||
const isAToolName = toolNamesSet.has(toolName)
|
||||
return isAToolName
|
||||
}
|
||||
|
||||
|
||||
export type ToolParamNames<T extends ToolName> = keyof typeof voidTools[T]['params']
|
||||
export type ToolParamsObj<T extends ToolName> = { [paramName in ToolParamNames<T>]: unknown }
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
import OpenAI from 'openai';
|
||||
import { Model as OpenAIModel } from 'openai/resources/models.js';
|
||||
import { _InternalModelListFnType, _InternalSendLLMFIMMessageFnType, _InternalSendLLMChatMessageFnType, OllamaModelResponse } from '../../common/llmMessageTypes.js';
|
||||
import { InternalToolInfo, ToolName, toolNames } from '../../common/toolsService.js';
|
||||
import { OllamaModelResponse, OnText, OnFinalMessage, OnError, LLMChatMessage, LLMFIMMessage, ModelListParams } from '../../common/llmMessageTypes.js';
|
||||
import { InternalToolInfo, isAToolName } from '../../common/toolsService.js';
|
||||
import { defaultProviderSettings, ProviderName, SettingsOfProvider } from '../../common/voidSettingsTypes.js';
|
||||
import { prepareMessages } from './preprocessLLMMessages.js';
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
|
|
@ -80,12 +80,13 @@ type ProviderSettings = {
|
|||
output: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
};
|
||||
}
|
||||
supportsSystemMessage: false | 'system-role' | 'developer-role' | 'separated';
|
||||
supportsTools: false | 'anthropic-style' | 'openai-style';
|
||||
};
|
||||
};
|
||||
};
|
||||
supportsFIM: false | 'TODO_FIM_FORMAT'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const openAIProviderSettings: ProviderSettings = {
|
||||
|
|
@ -97,21 +98,24 @@ const openAIProviderSettings: ProviderSettings = {
|
|||
FIMFormat: '',
|
||||
|
||||
modelOptions: {
|
||||
"o1": {
|
||||
'o1': {
|
||||
contextWindow: 128_000,
|
||||
cost: { input: 15.00, cache_read: 7.50, output: 60.00, },
|
||||
supportsFIM: false,
|
||||
supportsTools: false,
|
||||
supportsSystemMessage: 'developer-role',
|
||||
},
|
||||
"o3-mini": {
|
||||
'o3-mini': {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 1.10, cache_read: 0.55, output: 4.40, },
|
||||
supportsFIM: false,
|
||||
supportsTools: false,
|
||||
supportsSystemMessage: 'developer-role',
|
||||
},
|
||||
"gpt-4o": {
|
||||
'gpt-4o': {
|
||||
contextWindow: 128_000,
|
||||
cost: { input: 2.50, cache_read: 1.25, output: 10.00, },
|
||||
supportsFIM: false,
|
||||
supportsTools: 'openai-style',
|
||||
supportsSystemMessage: 'system-role',
|
||||
},
|
||||
|
|
@ -134,6 +138,7 @@ const anthropicProviderSettings: ProviderSettings = {
|
|||
"claude-3-5-sonnet-20241022": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 3.00, cache_read: 0.30, cache_write: 3.75, output: 15.00 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
|
||||
|
|
@ -141,17 +146,20 @@ const anthropicProviderSettings: ProviderSettings = {
|
|||
"claude-3-5-haiku-20241022": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 0.80, cache_read: 0.08, cache_write: 1.00, output: 4.00 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
},
|
||||
"claude-3-opus-20240229": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 15.00, cache_read: 1.50, cache_write: 18.75, output: 75.00 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
},
|
||||
"claude-3-sonnet-20240229": {
|
||||
contextWindow: 200_000, cost: { input: 3.00, output: 15.00 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
}
|
||||
|
|
@ -168,30 +176,13 @@ const grokProviderSettings: ProviderSettings = {
|
|||
FIMFormat: '',
|
||||
|
||||
modelOptions: {
|
||||
"claude-3-5-sonnet-20241022": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 3.00, cache_read: 0.30, cache_write: 3.75, output: 15.00 },
|
||||
"grok-2-latest": {
|
||||
contextWindow: 131_072,
|
||||
cost: { input: 2.00, output: 10.00 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
|
||||
supportsTools: 'openai-style',
|
||||
},
|
||||
"claude-3-5-haiku-20241022": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 0.80, cache_read: 0.08, cache_write: 1.00, output: 4.00 },
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
},
|
||||
"claude-3-opus-20240229": {
|
||||
contextWindow: 200_000,
|
||||
cost: { input: 15.00, cache_read: 1.50, cache_write: 18.75, output: 75.00 },
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
},
|
||||
"claude-3-sonnet-20240229": {
|
||||
contextWindow: 200_000, cost: { input: 3.00, output: 15.00 },
|
||||
supportsSystemMessage: 'system-role',
|
||||
supportsTools: 'anthropic-style',
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -199,14 +190,22 @@ const grokProviderSettings: ProviderSettings = {
|
|||
|
||||
|
||||
|
||||
// helpers
|
||||
|
||||
const toolNamesSet = new Set<string>(toolNames)
|
||||
const isAToolName = (toolName: string): toolName is ToolName => {
|
||||
const isAToolName = toolNamesSet.has(toolName)
|
||||
return isAToolName
|
||||
type InternalCommonMessageParams = {
|
||||
aiInstructions: string;
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
providerName: ProviderName;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
modelName: string;
|
||||
_setAborter: (aborter: () => void) => void;
|
||||
}
|
||||
|
||||
type SendChatParams_Internal = InternalCommonMessageParams & { messages: LLMChatMessage[]; tools?: InternalToolInfo[] }
|
||||
type SendFIMParams_Internal = InternalCommonMessageParams & { messages: LLMFIMMessage; }
|
||||
export type ListParams_Internal<ModelResponse> = ModelListParams<ModelResponse>
|
||||
|
||||
|
||||
// ------------ OPENAI-COMPATIBLE (HELPERS) ------------
|
||||
const toOpenAICompatibleTool = (toolInfo: InternalToolInfo) => {
|
||||
|
|
@ -251,7 +250,7 @@ const newOpenAICompatibleSDK = ({ settingsOfProvider, providerName }: { settings
|
|||
else throw new Error(`Invalid providerName ${providerName}`)
|
||||
}
|
||||
|
||||
export const _sendOpenAICompatibleChat: _InternalSendLLMChatMessageFnType = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName, aiInstructions, tools: tools_ }) => {
|
||||
export const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName, aiInstructions, tools: tools_ }: SendChatParams_Internal) => {
|
||||
const { messages } = prepareMessages({ messages: messages_, aiInstructions, supportsSystemMessage: '', supportsTools: '', })
|
||||
const tools = (supportsTools && ((tools_?.length ?? 0) !== 0)) ? tools_?.map(tool => toOpenAICompatibleTool(tool)) : undefined
|
||||
|
||||
|
|
@ -291,7 +290,7 @@ export const _sendOpenAICompatibleChat: _InternalSendLLMChatMessageFnType = ({ m
|
|||
}
|
||||
|
||||
|
||||
export const _openaiCompatibleList: _InternalModelListFnType<OpenAIModel> = async ({ onSuccess: onSuccess_, onError: onError_, settingsOfProvider, providerName }) => {
|
||||
export const _openaiCompatibleList = async ({ onSuccess: onSuccess_, onError: onError_, settingsOfProvider, providerName }: ListParams_Internal<OpenAIModel>) => {
|
||||
const onSuccess = ({ models }: { models: OpenAIModel[] }) => {
|
||||
onSuccess_({ models })
|
||||
}
|
||||
|
|
@ -320,7 +319,7 @@ export const _openaiCompatibleList: _InternalModelListFnType<OpenAIModel> = asyn
|
|||
|
||||
|
||||
// ------------ OPENAI ------------
|
||||
export const sendOpenAIChat: _InternalSendLLMChatMessageFnType = (params) => {
|
||||
export const sendOpenAIChat = (params: SendChatParams_Internal) => {
|
||||
return _sendOpenAICompatibleChat(params)
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +345,7 @@ const toolCallsFromAnthropicContent = (content: Anthropic.Messages.ContentBlock[
|
|||
}).filter(t => !!t)
|
||||
}
|
||||
|
||||
export const sendAnthropicChat: _InternalSendLLMChatMessageFnType = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, aiInstructions, tools: tools_ }) => {
|
||||
export const sendAnthropicChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, aiInstructions, tools: tools_ }: SendChatParams_Internal) => {
|
||||
const { messages, separateSystemMessageStr } = prepareMessages({ messages: messages_, aiInstructions, supportsSystemMessage: 'separated', supportsTools: 'anthropic-style', })
|
||||
|
||||
const thisConfig = settingsOfProvider.anthropic
|
||||
|
|
@ -405,7 +404,7 @@ const newOllamaSDK = ({ endpoint }: { endpoint: string }) => {
|
|||
return ollama
|
||||
}
|
||||
|
||||
export const ollamaList: _InternalModelListFnType<OllamaModelResponse> = async ({ onSuccess: onSuccess_, onError: onError_, settingsOfProvider }) => {
|
||||
export const ollamaList = async ({ onSuccess: onSuccess_, onError: onError_, settingsOfProvider }: ListParams_Internal<OllamaModelResponse>) => {
|
||||
const onSuccess = ({ models }: { models: OllamaModelResponse[] }) => {
|
||||
onSuccess_({ models })
|
||||
}
|
||||
|
|
@ -429,7 +428,7 @@ export const ollamaList: _InternalModelListFnType<OllamaModelResponse> = async (
|
|||
}
|
||||
}
|
||||
|
||||
export const sendOllamaFIM: _InternalSendLLMFIMMessageFnType = ({ messages, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
export const sendOllamaFIM = ({ messages, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }: SendFIMParams_Internal) => {
|
||||
const thisConfig = settingsOfProvider.ollama
|
||||
const ollama = newOllamaSDK({ endpoint: thisConfig.endpoint })
|
||||
|
||||
|
|
@ -462,7 +461,7 @@ export const sendOllamaFIM: _InternalSendLLMFIMMessageFnType = ({ messages, onFi
|
|||
|
||||
|
||||
// ollama's implementation of openai-compatible SDK dumps all reasoning tokens out with message, and supports tools, so we can use it for chat!
|
||||
export const sendOllamaMessage: _InternalSendLLMChatMessageFnType = (params) => {
|
||||
export const sendOllamaChat = (params: SendChatParams_Internal) => {
|
||||
return _sendOpenAICompatibleChat(params)
|
||||
// TODO!!! filter out reasoning <think> tags...
|
||||
}
|
||||
|
|
@ -470,24 +469,24 @@ export const sendOllamaMessage: _InternalSendLLMChatMessageFnType = (params) =>
|
|||
|
||||
|
||||
// ------------ OPENROUTER ------------
|
||||
export const sendOpenRouterFIM: _InternalSendLLMFIMMessageFnType = ({ messages, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
export const sendOpenRouterFIM = ({ messages, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }: SendFIMParams_Internal) => {
|
||||
// TODO!!!
|
||||
}
|
||||
|
||||
export const sendOpenRouterChat: _InternalSendLLMChatMessageFnType = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName, aiInstructions, tools: tools_ }) => {
|
||||
// payload should have {include_reasoning: true} https://openrouter.ai/announcements/reasoning-tokens-for-thinking-models
|
||||
// response.choices[0].delta.reasoning
|
||||
export const sendOpenRouterChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName, aiInstructions, tools: tools_ }: SendChatParams_Internal) => {
|
||||
// reasoning: response.choices[0].delta.reasoning : payload should have {include_reasoning: true} https://openrouter.ai/announcements/reasoning-tokens-for-thinking-models
|
||||
//
|
||||
}
|
||||
|
||||
// ------------ OPENAI-COMPATIBLE ------------
|
||||
export const openAICompatibleList: _InternalModelListFnType<OpenAIModel> = async (params) => {
|
||||
export const openAICompatibleList = async (params: ListParams_Internal<OpenAIModel>) => {
|
||||
return _openaiCompatibleList(params)
|
||||
}
|
||||
|
||||
// TODO!!! FIM
|
||||
|
||||
// using openai's SDK is not ideal (your implementation might not do tools, reasoning, FIM etc correctly), talk to us for a custom integration
|
||||
export const sendOpenAICompatibleChat: _InternalSendLLMChatMessageFnType = (params) => {
|
||||
export const sendOpenAICompatibleChat = (params: SendChatParams_Internal) => {
|
||||
return _sendOpenAICompatibleChat(params)
|
||||
}
|
||||
|
||||
|
|
@ -496,13 +495,23 @@ export const sendOpenAICompatibleChat: _InternalSendLLMChatMessageFnType = (para
|
|||
// TODO!!! FIM
|
||||
|
||||
// using openai's SDK is not ideal (your implementation might not do tools, reasoning, FIM etc correctly), talk to us for a custom integration
|
||||
export const sendVLLMChat: _InternalSendLLMChatMessageFnType = (params) => {
|
||||
export const sendVLLMChat = (params: SendChatParams_Internal) => {
|
||||
return _sendOpenAICompatibleChat(params)
|
||||
// response.choices[0].delta.reasoning_content // https://docs.vllm.ai/en/stable/features/reasoning_outputs.html#streaming-chat-completions
|
||||
// reasoning: response.choices[0].delta.reasoning_content // https://docs.vllm.ai/en/stable/features/reasoning_outputs.html#streaming-chat-completions
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------ DEEPSEEK API ------------
|
||||
export const sendDeepSeekAPIChat = (params: SendChatParams_Internal) => {
|
||||
return _sendOpenAICompatibleChat(params)
|
||||
// reasoning: response.choices[0].delta.reasoning_content // https://api-docs.deepseek.com/guides/reasoning_model
|
||||
}
|
||||
|
||||
|
||||
// ------------ GEMINI ------------
|
||||
// ------------ MISTRAL ------------
|
||||
// ------------ GROQ ------------
|
||||
// ------------ GROK ------------
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,483 +0,0 @@
|
|||
// /*--------------------------------------------------------------------------------------
|
||||
// * Copyright 2025 Glass Devtools, Inc. All rights reserved.
|
||||
// * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
// *--------------------------------------------------------------------------------------*/
|
||||
|
||||
// import Groq from 'groq-sdk';
|
||||
// import { _InternalSendLLMChatMessageFnType } from '../../common/llmMessageTypes.js';
|
||||
|
||||
// // Groq
|
||||
// export const sendGroqChat: _InternalSendLLMChatMessageFnType = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
// let fullText = '';
|
||||
|
||||
// const thisConfig = settingsOfProvider.groq
|
||||
|
||||
// const groq = new Groq({
|
||||
// apiKey: thisConfig.apiKey,
|
||||
// dangerouslyAllowBrowser: true
|
||||
// });
|
||||
|
||||
// await groq.chat.completions
|
||||
// .create({
|
||||
// messages: messages,
|
||||
// model: modelName,
|
||||
// stream: true,
|
||||
// })
|
||||
// .then(async response => {
|
||||
// _setAborter(() => response.controller.abort())
|
||||
// // when receive text
|
||||
// for await (const chunk of response) {
|
||||
// const newText = chunk.choices[0]?.delta?.content || '';
|
||||
// fullText += newText;
|
||||
// onText({ newText, fullText });
|
||||
// }
|
||||
|
||||
// onFinalMessage({ fullText, tools: [] });
|
||||
// })
|
||||
// .catch(error => {
|
||||
// onError({ message: error + '', fullError: error });
|
||||
// })
|
||||
|
||||
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// /*--------------------------------------------------------------------------------------
|
||||
// * Copyright 2025 Glass Devtools, Inc. All rights reserved.
|
||||
// * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
// *--------------------------------------------------------------------------------------*/
|
||||
|
||||
// import { Mistral } from '@mistralai/mistralai';
|
||||
// import { _InternalSendLLMChatMessageFnType } from '../../common/llmMessageTypes.js';
|
||||
|
||||
// // Mistral
|
||||
// export const sendMistralChat: _InternalSendLLMChatMessageFnType = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
// let fullText = '';
|
||||
|
||||
// const thisConfig = settingsOfProvider.mistral;
|
||||
|
||||
// const mistral = new Mistral({
|
||||
// apiKey: thisConfig.apiKey,
|
||||
// })
|
||||
|
||||
// await mistral.chat
|
||||
// .stream({
|
||||
// messages: messages,
|
||||
// model: modelName,
|
||||
// stream: true,
|
||||
// })
|
||||
// .then(async response => {
|
||||
// // Mistral has a really nonstandard API - no interrupt and weird stream types
|
||||
// _setAborter(() => { console.log('Mistral does not support interrupts! Further messages will just be ignored.') });
|
||||
// // when receive text
|
||||
// for await (const chunk of response) {
|
||||
// const c = chunk.data.choices[0].delta.content || ''
|
||||
// const newText = (
|
||||
// typeof c === 'string' ? c
|
||||
// : c?.map(c => c.type === 'text' ? c.text : c.type).join('\n')
|
||||
// )
|
||||
// fullText += newText;
|
||||
// onText({ newText, fullText });
|
||||
// }
|
||||
|
||||
// onFinalMessage({ fullText, tools: [] });
|
||||
// })
|
||||
// .catch(error => {
|
||||
// onError({ message: error + '', fullError: error });
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// export const recognizedModels = [
|
||||
// // chat
|
||||
// 'OpenAI 4o',
|
||||
// 'Anthropic Claude',
|
||||
// 'Llama 3.x',
|
||||
// 'Deepseek Chat', // deepseek coder v2 is now merged into chat (V3) https://api-docs.deepseek.com/updates#deepseek-coder--deepseek-chat-upgraded-to-deepseek-v25-model
|
||||
// 'xAI Grok',
|
||||
// // 'xAI Grok',
|
||||
// // 'Google Gemini, Gemma',
|
||||
// // 'Microsoft Phi4',
|
||||
|
||||
|
||||
// // coding (autocomplete)
|
||||
// 'Alibaba Qwen2.5 Coder Instruct', // we recommend this over Qwen2.5
|
||||
// 'Mistral Codestral',
|
||||
|
||||
// // thinking
|
||||
// 'OpenAI o1',
|
||||
// 'Deepseek R1',
|
||||
|
||||
// // general
|
||||
// // 'Mixtral 8x7b'
|
||||
// // 'Qwen2.5',
|
||||
|
||||
// ] as const
|
||||
|
||||
// type RecognizedModelName = (typeof recognizedModels)[number] | '<GENERAL>'
|
||||
|
||||
|
||||
// export function recognizedModelOfModelName(modelName: string): RecognizedModelName {
|
||||
// const lower = modelName.toLowerCase();
|
||||
|
||||
// if (lower.includes('gpt-4o'))
|
||||
// return 'OpenAI 4o';
|
||||
// if (lower.includes('claude'))
|
||||
// return 'Anthropic Claude';
|
||||
// if (lower.includes('llama'))
|
||||
// return 'Llama 3.x';
|
||||
// if (lower.includes('qwen2.5-coder'))
|
||||
// return 'Alibaba Qwen2.5 Coder Instruct';
|
||||
// if (lower.includes('mistral'))
|
||||
// return 'Mistral Codestral';
|
||||
// if (/\bo1\b/.test(lower) || /\bo3\b/.test(lower)) // o1, o3
|
||||
// return 'OpenAI o1';
|
||||
// if (lower.includes('deepseek-r1') || lower.includes('deepseek-reasoner'))
|
||||
// return 'Deepseek R1';
|
||||
// if (lower.includes('deepseek'))
|
||||
// return 'Deepseek Chat'
|
||||
// if (lower.includes('grok'))
|
||||
// return 'xAI Grok'
|
||||
|
||||
// return '<GENERAL>';
|
||||
// }
|
||||
|
||||
|
||||
// const developerInfoAtProvider: { [providerName in ProviderName]: DeveloperInfoAtProvider } = {
|
||||
// 'anthropic': {
|
||||
// overrideSettingsForAllModels: {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: true,
|
||||
// }
|
||||
// },
|
||||
// 'deepseek': {
|
||||
// overrideSettingsForAllModels: {
|
||||
// }
|
||||
// },
|
||||
// 'ollama': {
|
||||
// },
|
||||
// 'openRouter': {
|
||||
// },
|
||||
// 'openAICompatible': {
|
||||
// },
|
||||
// 'openAI': {
|
||||
// },
|
||||
// 'gemini': {
|
||||
// },
|
||||
// 'mistral': {
|
||||
// },
|
||||
// 'groq': {
|
||||
// },
|
||||
// 'xAI': {
|
||||
// },
|
||||
// 'vLLM': {
|
||||
// },
|
||||
// }
|
||||
// export const developerInfoOfProviderName = (providerName: ProviderName): Partial<DeveloperInfoAtProvider> => {
|
||||
// return developerInfoAtProvider[providerName] ?? {}
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
// // providerName is optional, but gives some extra fallbacks if provided
|
||||
// const developerInfoOfRecognizedModelName: { [recognizedModel in RecognizedModelName]: Omit<DeveloperInfoAtModel, '_recognizedModelName'> } = {
|
||||
// 'OpenAI 4o': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: true,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'Anthropic Claude': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: false,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'Llama 3.x': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'xAI Grok': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: true,
|
||||
// _maxTokens: 4096,
|
||||
|
||||
// },
|
||||
|
||||
// 'Deepseek Chat': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: false,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'Alibaba Qwen2.5 Coder Instruct': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'Mistral Codestral': {
|
||||
// supportsSystemMessage: true,
|
||||
// supportsTools: true,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'OpenAI o1': {
|
||||
// supportsSystemMessage: 'developer',
|
||||
// supportsTools: false,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: true,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
// 'Deepseek R1': {
|
||||
// supportsSystemMessage: false,
|
||||
// supportsTools: false,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
|
||||
|
||||
// '<GENERAL>': {
|
||||
// supportsSystemMessage: false,
|
||||
// supportsTools: false,
|
||||
// _supportsAutocompleteFIM: false,
|
||||
// _supportsStreaming: false,
|
||||
// _maxTokens: 4096,
|
||||
// },
|
||||
// }
|
||||
// export const developerInfoOfModelName = (modelName: string, overrides?: Partial<DeveloperInfoAtModel>): DeveloperInfoAtModel => {
|
||||
// const recognizedModelName = recognizedModelOfModelName(modelName)
|
||||
// return {
|
||||
// _recognizedModelName: recognizedModelName,
|
||||
// ...developerInfoOfRecognizedModelName[recognizedModelName],
|
||||
// ...overrides
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // creates `modelInfo` from `modelNames`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// export const modelInfoOfAutodetectedModelNames = (defaultModelNames: string[], options: { existingModels: VoidModelInfo[] }) => {
|
||||
// const { existingModels } = options
|
||||
|
||||
// const existingModelsMap: Record<string, VoidModelInfo> = {}
|
||||
// for (const existingModel of existingModels) {
|
||||
// existingModelsMap[existingModel.modelName] = existingModel
|
||||
// }
|
||||
|
||||
// return defaultModelNames.map((modelName, i) => ({
|
||||
// modelName,
|
||||
// isDefault: true,
|
||||
// isAutodetected: true,
|
||||
// isHidden: !!existingModelsMap[modelName]?.isHidden,
|
||||
// ...developerInfoOfModelName(modelName)
|
||||
// }))
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// export const anthropicMaxPossibleTokens = (modelName: string) => {
|
||||
// if (modelName === 'claude-3-5-sonnet-20241022'
|
||||
// || modelName === 'claude-3-5-haiku-20241022')
|
||||
// return 8192
|
||||
// if (modelName === 'claude-3-opus-20240229'
|
||||
// || modelName === 'claude-3-sonnet-20240229'
|
||||
// || modelName === 'claude-3-haiku-20240307')
|
||||
// return 4096
|
||||
// return 1024 // return a reasonably small number if they're using a different model
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // Ollama chat
|
||||
// export const sendOllamaChat: _InternalSendLLMChatMessageFnType = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
|
||||
// const thisConfig = settingsOfProvider.ollama
|
||||
// // if endpoint is empty, normally ollama will send to 11434, but we want it to fail - the user should type it in
|
||||
// if (!thisConfig.endpoint) throw new Error(`Ollama Endpoint was empty (please enter ${defaultProviderSettings.ollama.endpoint} if you want the default).`)
|
||||
|
||||
// let fullText = ''
|
||||
|
||||
// const ollama = new Ollama({ host: thisConfig.endpoint })
|
||||
|
||||
// ollama.chat({
|
||||
// model: modelName,
|
||||
// messages: messages,
|
||||
// stream: true,
|
||||
// // options: { num_predict: parseMaxTokensStr(thisConfig.maxTokens) } // this is max_tokens
|
||||
// })
|
||||
// .then(async stream => {
|
||||
// _setAborter(() => stream.abort())
|
||||
// // iterate through the stream
|
||||
// for await (const chunk of stream) {
|
||||
// const newText = chunk.message.content;
|
||||
|
||||
// // chunk.message.tool_calls[0].function.arguments
|
||||
|
||||
// fullText += newText;
|
||||
// onText({ newText, fullText });
|
||||
// }
|
||||
|
||||
// onFinalMessage({ fullText, tools: [] });
|
||||
|
||||
// })
|
||||
// // when error/fail
|
||||
// .catch((error) => {
|
||||
// onError({ message: error + '', fullError: error })
|
||||
// })
|
||||
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// type NewParams = Pick<Parameters<_InternalSendLLMChatMessageFnType>[0] & Parameters<_InternalSendLLMFIMMessageFnType>[0], 'settingsOfProvider' | 'providerName'>
|
||||
// const newOpenAI = ({ settingsOfProvider, providerName }: NewParams) => {
|
||||
|
||||
// if (providerName === 'openAI') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'ollama') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: `${thisConfig.endpoint}/v1`, apiKey: 'noop', dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'vLLM') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: `${thisConfig.endpoint}/v1`, apiKey: 'noop', dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'openRouter') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://openrouter.ai/api/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// defaultHeaders: {
|
||||
// 'HTTP-Referer': 'https://voideditor.com', // Optional, for including your app on openrouter.ai rankings.
|
||||
// 'X-Title': 'Void Editor', // Optional. Shows in rankings on openrouter.ai.
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'gemini') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'deepseek') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://api.deepseek.com/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'openAICompatible') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: thisConfig.endpoint, apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'mistral') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://api.mistral.ai/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'groq') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://api.groq.com/openai/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else if (providerName === 'xAI') {
|
||||
// const thisConfig = settingsOfProvider[providerName]
|
||||
// return new OpenAI({
|
||||
// baseURL: 'https://api.x.ai/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
// })
|
||||
// }
|
||||
// else {
|
||||
// console.error(`sendOpenAICompatibleMsg: invalid providerName: ${providerName}`)
|
||||
// throw new Error(`Void providerName was invalid: ${providerName}`)
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
Loading…
Reference in a new issue