pref: simplified AI provider's settings
This commit is contained in:
172
.env.example
172
.env.example
@@ -1,103 +1,15 @@
|
|||||||
# Rename this file to .env once you have filled in the below environment variables!
|
# Rename this file to .env once you have filled in the below environment variables!
|
||||||
|
# Whether to enable file logging
|
||||||
# Get your GROQ API Key here -
|
USAGE_LOG_FILE=true
|
||||||
# https://console.groq.com/keys
|
|
||||||
# You only need this environment variable set if you want to use Groq models
|
|
||||||
GROQ_API_KEY=
|
|
||||||
|
|
||||||
# Get your HuggingFace API Key here -
|
|
||||||
# https://huggingface.co/settings/tokens
|
|
||||||
# You only need this environment variable set if you want to use HuggingFace models
|
|
||||||
HuggingFace_API_KEY=
|
|
||||||
|
|
||||||
|
|
||||||
# Get your Open AI API Key by following these instructions -
|
|
||||||
# https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key
|
|
||||||
# You only need this environment variable set if you want to use GPT models
|
|
||||||
OPENAI_API_KEY=
|
|
||||||
|
|
||||||
# Get your Anthropic API Key in your account settings -
|
|
||||||
# https://console.anthropic.com/settings/keys
|
|
||||||
# You only need this environment variable set if you want to use Claude models
|
|
||||||
ANTHROPIC_API_KEY=
|
|
||||||
|
|
||||||
# Get your OpenRouter API Key in your account settings -
|
|
||||||
# https://openrouter.ai/settings/keys
|
|
||||||
# You only need this environment variable set if you want to use OpenRouter models
|
|
||||||
OPEN_ROUTER_API_KEY=
|
|
||||||
|
|
||||||
# Get your Google Generative AI API Key by following these instructions -
|
|
||||||
# https://console.cloud.google.com/apis/credentials
|
|
||||||
# You only need this environment variable set if you want to use Google Generative AI models
|
|
||||||
GOOGLE_GENERATIVE_AI_API_KEY=
|
|
||||||
|
|
||||||
# You only need this environment variable set if you want to use oLLAMA models
|
|
||||||
# DONT USE http://localhost:11434 due to IPV6 issues
|
|
||||||
# USE EXAMPLE http://127.0.0.1:11434
|
|
||||||
OLLAMA_API_BASE_URL=
|
|
||||||
|
|
||||||
# You only need this environment variable set if you want to use OpenAI Like models
|
|
||||||
OPENAI_LIKE_API_BASE_URL=
|
|
||||||
|
|
||||||
# You only need this environment variable set if you want to use Together AI models
|
|
||||||
TOGETHER_API_BASE_URL=
|
|
||||||
|
|
||||||
# You only need this environment variable set if you want to use DeepSeek models through their API
|
|
||||||
DEEPSEEK_API_KEY=
|
|
||||||
|
|
||||||
# Get your OpenAI Like API Key
|
|
||||||
OPENAI_LIKE_API_KEY=
|
|
||||||
|
|
||||||
# Get your Together API Key
|
|
||||||
TOGETHER_API_KEY=
|
|
||||||
|
|
||||||
# You only need this environment variable set if you want to use Hyperbolic models
|
|
||||||
#Get your Hyperbolics API Key at https://app.hyperbolic.xyz/settings
|
|
||||||
#baseURL="https://api.hyperbolic.xyz/v1/chat/completions"
|
|
||||||
HYPERBOLIC_API_KEY=
|
|
||||||
HYPERBOLIC_API_BASE_URL=
|
|
||||||
|
|
||||||
# Get your Mistral API Key by following these instructions -
|
|
||||||
# https://console.mistral.ai/api-keys/
|
|
||||||
# You only need this environment variable set if you want to use Mistral models
|
|
||||||
MISTRAL_API_KEY=
|
|
||||||
|
|
||||||
# Get the Cohere Api key by following these instructions -
|
|
||||||
# https://dashboard.cohere.com/api-keys
|
|
||||||
# You only need this environment variable set if you want to use Cohere models
|
|
||||||
COHERE_API_KEY=
|
|
||||||
|
|
||||||
# Get LMStudio Base URL from LM Studio Developer Console
|
|
||||||
# Make sure to enable CORS
|
|
||||||
# DONT USE http://localhost:1234 due to IPV6 issues
|
|
||||||
# Example: http://127.0.0.1:1234
|
|
||||||
LMSTUDIO_API_BASE_URL=
|
|
||||||
|
|
||||||
# Get your xAI API key
|
|
||||||
# https://x.ai/api
|
|
||||||
# You only need this environment variable set if you want to use xAI models
|
|
||||||
XAI_API_KEY=
|
|
||||||
|
|
||||||
# Get your Perplexity API Key here -
|
|
||||||
# https://www.perplexity.ai/settings/api
|
|
||||||
# You only need this environment variable set if you want to use Perplexity models
|
|
||||||
PERPLEXITY_API_KEY=
|
|
||||||
|
|
||||||
# Get your AWS configuration
|
|
||||||
# https://console.aws.amazon.com/iam/home
|
|
||||||
# The JSON should include the following keys:
|
|
||||||
# - region: The AWS region where Bedrock is available.
|
|
||||||
# - accessKeyId: Your AWS access key ID.
|
|
||||||
# - secretAccessKey: Your AWS secret access key.
|
|
||||||
# - sessionToken (optional): Temporary session token if using an IAM role or temporary credentials.
|
|
||||||
# Example JSON:
|
|
||||||
# {"region": "us-east-1", "accessKeyId": "yourAccessKeyId", "secretAccessKey": "yourSecretAccessKey", "sessionToken": "yourSessionToken"}
|
|
||||||
AWS_BEDROCK_CONFIG=
|
|
||||||
|
|
||||||
# 是否开启文件日志
|
|
||||||
USAGE_LOG_FILE=false
|
|
||||||
# Include this environment variable if you want more logging for debugging locally
|
# Include this environment variable if you want more logging for debugging locally
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
|
# Operating environment, different from NODE_ENV. NODE_ENV is determined at build time, while this variable is used for enabling certain features in different environments
|
||||||
|
# development | production | test
|
||||||
|
OPERATING_ENV=production
|
||||||
|
# Resource file storage location
|
||||||
|
STORAGE_DIR=/public/uploads
|
||||||
|
# Maximum upload size for attachments
|
||||||
|
MAX_UPLOAD_SIZE_MB=5
|
||||||
|
|
||||||
# Example Context Values for qwen2.5-coder:32b
|
# Example Context Values for qwen2.5-coder:32b
|
||||||
#
|
#
|
||||||
@@ -107,45 +19,49 @@ LOG_LEVEL=debug
|
|||||||
# DEFAULT_NUM_CTX=6144 # Consumes 24GB of VRAM
|
# DEFAULT_NUM_CTX=6144 # Consumes 24GB of VRAM
|
||||||
DEFAULT_NUM_CTX=
|
DEFAULT_NUM_CTX=
|
||||||
|
|
||||||
|
# LLM Configuration Options
|
||||||
|
# Enabled model providers, currently supporting Anthropic, Cohere, Deepseek, Google, Groq, HuggingFace, Hyperbolic, Mistral, Ollama, OpenAI, OpenRouter, OpenAILike, Perplexity, xAI, Together, LMStudio, AmazonBedrock, Github
|
||||||
|
LLM_PROVIDER=
|
||||||
|
|
||||||
|
# BASE URL of the current model provider, some providers require this to be set, such as OpenAILike, Ollama, LMStudio
|
||||||
|
# DONT USE http://localhost:11434 due to IPV6 issues
|
||||||
|
# USE EXAMPLE http://127.0.0.1:11434
|
||||||
|
PROVIDER_BASE_URL=
|
||||||
|
|
||||||
|
# API KEY of the current provider, used to request the model API. Some providers do not require this to be set.
|
||||||
|
# Specifically, if the model provider is AmazonBedrock, this should be a JSON string, reference:
|
||||||
|
# https://console.aws.amazon.com/iam/home
|
||||||
|
# The JSON should include the following keys:
|
||||||
|
# - region: The AWS region where Bedrock is available.
|
||||||
|
# - accessKeyId: Your AWS access key ID.
|
||||||
|
# - secretAccessKey: Your AWS secret access key.
|
||||||
|
# - sessionToken (optional): Temporary session token if using an IAM role or temporary credentials.
|
||||||
|
# Example JSON:
|
||||||
|
# {"region": "us-east-1", "accessKeyId": "yourAccessKeyId", "secretAccessKey": "yourSecretAccessKey", "sessionToken": "yourSessionToken"}
|
||||||
|
PROVIDER_API_KEY=
|
||||||
|
|
||||||
|
# MODEL used for page generation (should correspond to LLM_DEFAULT_PROVIDER)
|
||||||
|
LLM_DEFAULT_MODEL=
|
||||||
|
|
||||||
|
# MODEL used for auxiliary page generation, such as summarization and pre-analysis. (should correspond to LLM_DEFAULT_PROVIDER)
|
||||||
|
LLM_MINOR_MODEL=
|
||||||
|
|
||||||
# Get your Serper API Key https://serper.dev/
|
# Get your Serper API Key https://serper.dev/
|
||||||
SERPER_API_KEY=
|
SERPER_API_KEY=
|
||||||
|
|
||||||
# Get your Weather API Key https://www.weatherapi.com/my/
|
# Get your Weather API Key https://www.weatherapi.com/my/
|
||||||
WEATHER_API_KEY=
|
WEATHER_API_KEY=
|
||||||
|
|
||||||
# LLM Configuration Options
|
# Environment variables required for Logto integration
|
||||||
|
# Logto endpoint
|
||||||
# Default LLM provider to use (e.g.,OpenAILike,OpenAI, Anthropic, Mistral)
|
|
||||||
LLM_DEFAULT_PROVIDER=
|
|
||||||
|
|
||||||
# 生成页面所使用的 MODEL(应该与 LLM_DEFAULT_PROVIDER 相对应)
|
|
||||||
LLM_DEFAULT_MODEL=
|
|
||||||
|
|
||||||
# 用于辅助页面生成所使用的 MODEL,例如总结和预分析。(应该与 LLM_DEFAULT_PROVIDER 相对应)
|
|
||||||
LLM_MINOR_MODEL=
|
|
||||||
|
|
||||||
# Comma-separated list of enabled providers (empty means all providers)
|
|
||||||
# Example: OpenAILike,OpenAI,Anthropic,Mistral
|
|
||||||
LLM_ENABLED_PROVIDERS=
|
|
||||||
|
|
||||||
# Logto 集成所需环境变量
|
|
||||||
# Logto 地址
|
|
||||||
LOGTO_ENDPOINT=
|
LOGTO_ENDPOINT=
|
||||||
# Logto 应用 ID
|
# Logto application ID
|
||||||
LOGTO_APP_ID=
|
LOGTO_APP_ID=
|
||||||
# Logto 应用密钥
|
# Logto application secret
|
||||||
LOGTO_APP_SECRET=
|
LOGTO_APP_SECRET=
|
||||||
# 应用基础 URL,根据实际部署环境修改
|
# Application base URL, modify according to actual deployment environment
|
||||||
LOGTO_BASE_URL=http://localhost:5173
|
LOGTO_BASE_URL=http://localhost:5173
|
||||||
# 随机任意的 36 位字符串,用于加密 Logto 的 cookie。
|
# Random 36-character string, used to encrypt Logto cookies.
|
||||||
LOGTO_COOKIE_SECRET=
|
LOGTO_COOKIE_SECRET=
|
||||||
# 是否在开发环境中启用 Logto 认证,设置为 false 则在开发环境不强制认证
|
# Whether to enable Logto authentication in development environment, set to false to not enforce authentication in development
|
||||||
LOGTO_ENABLE_DEV=false
|
LOGTO_ENABLE=false
|
||||||
# 运行环境,与 NODE_ENV 有所不同, NODE_ENV 在打包时就已确定,而此变量用于某些功能在不同环境下的开放
|
|
||||||
# development | production | test
|
|
||||||
OPERATING_ENV=production
|
|
||||||
|
|
||||||
# 资源文件存储位置
|
|
||||||
STORAGE_DIR=/public/uploads
|
|
||||||
# 附件上传的最大大小
|
|
||||||
MAX_UPLOAD_SIZE_MB=5
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ FROM node:20.18.0-alpine AS runtime
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV LOGTO_ENABLE_DEV=false
|
ENV LOGTO_ENABLE=false
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV HOST=0.0.0.0
|
ENV HOST=0.0.0.0
|
||||||
|
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -26,8 +26,9 @@ docker run -d \
|
|||||||
--name upage \
|
--name upage \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
-p 3000:3000 \
|
-p 3000:3000 \
|
||||||
-e LLM_DEFAULT_PROVIDER=OpenAILike \
|
-e LLM_PROVIDER=OpenAILike \
|
||||||
-e OPENAI_LIKE_API_KEY=your-openai-like-api-key \
|
-e PROVIDER_BASE_URL=your-provider-base-url \
|
||||||
|
-e PROVIDER_API_KEY=your-openai-like-api-key \
|
||||||
-e LLM_DEFAULT_MODEL=your-default-model \
|
-e LLM_DEFAULT_MODEL=your-default-model \
|
||||||
-e LLM_MINOR_MODEL=your-minor-model \
|
-e LLM_MINOR_MODEL=your-minor-model \
|
||||||
-v ./data:/app/data \
|
-v ./data:/app/data \
|
||||||
@@ -37,8 +38,9 @@ docker run -d \
|
|||||||
```
|
```
|
||||||
|
|
||||||
其中参数说明如下:
|
其中参数说明如下:
|
||||||
- `-e LLM_DEFAULT_PROVIDER=OpenAILike`:设置默认的 LLM 提供商为 OpenAILike,即兼容 OpenAI 的 API 接口。
|
- `-e LLM_PROVIDER=OpenAILike`:设置默认的 LLM 提供商为 OpenAILike,即兼容 OpenAI 的 API 接口。
|
||||||
- `-e OPENAI_LIKE_API_KEY=your-openai-like-api-key`:设置 OpenAILike 的 API 密钥。
|
- `-e PROVIDER_BASE_URL=your-provider-base-url`:设置 LLM 提供商的 API 基础 URL,部分提供商需要设置此项,例如 OpenAILike, Ollama, LMStudio。
|
||||||
|
- `-e PROVIDER_API_KEY=your-openai-like-api-key`:设置 LLM 提供商的 API 密钥,大部分提供商需要设置此项。
|
||||||
- `-e LLM_DEFAULT_MODEL=your-default-model`:设置默认的 LLM 模型,用于构建页面。
|
- `-e LLM_DEFAULT_MODEL=your-default-model`:设置默认的 LLM 模型,用于构建页面。
|
||||||
- `-e LLM_MINOR_MODEL=your-minor-model`:设置次要的 LLM 模型,用于执行其他任务。
|
- `-e LLM_MINOR_MODEL=your-minor-model`:设置次要的 LLM 模型,用于执行其他任务。
|
||||||
- `-v ./data:/app/data`:挂载数据目录
|
- `-v ./data:/app/data`:挂载数据目录
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useAuth } from '~/lib/hooks';
|
|||||||
import { aiState } from '~/lib/stores/ai-state';
|
import { aiState } from '~/lib/stores/ai-state';
|
||||||
import { HistorySwitch } from '../sidebar/HistorySwitch';
|
import { HistorySwitch } from '../sidebar/HistorySwitch';
|
||||||
import { ThemeSwitch } from '../ui/ThemeSwitch';
|
import { ThemeSwitch } from '../ui/ThemeSwitch';
|
||||||
import { ChatDescription } from './ChatDescription';
|
import { ChatDescription } from './ChatDescription.client';
|
||||||
import { HeaderActionButtons } from './HeaderActionButtons';
|
import { HeaderActionButtons } from './HeaderActionButtons';
|
||||||
import { MinimalAvatarDropdown } from './MinimalAvatarDropdown';
|
import { MinimalAvatarDropdown } from './MinimalAvatarDropdown';
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { sidebarStore } from '~/lib/stores/sidebar';
|
|||||||
import { cubicEasingFn } from '~/utils/easings';
|
import { cubicEasingFn } from '~/utils/easings';
|
||||||
import WithTooltip from '../ui/Tooltip';
|
import WithTooltip from '../ui/Tooltip';
|
||||||
import { binDates } from './date-binning';
|
import { binDates } from './date-binning';
|
||||||
import { HistoryItem } from './HistoryItem';
|
import { HistoryItem } from './HistoryItem.client';
|
||||||
|
|
||||||
const menuVariants = {
|
const menuVariants = {
|
||||||
closed: {
|
closed: {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ const config: LogtoConfig = {
|
|||||||
const originalLogto = makeLogtoRemix(config, { sessionStorage });
|
const originalLogto = makeLogtoRemix(config, { sessionStorage });
|
||||||
|
|
||||||
export function shouldEnforceAuth(): boolean {
|
export function shouldEnforceAuth(): boolean {
|
||||||
return process.env.LOGTO_ENABLE_DEV !== 'false';
|
return process.env.LOGTO_ENABLE === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMockDevUser(): MockUser {
|
function getMockDevUser(): MockUser {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { convertToModelMessages, type LanguageModel, streamText, type UIMessage } from 'ai';
|
import { convertToModelMessages, type LanguageModel, streamText, type UIMessage } from 'ai';
|
||||||
import { createScopedLogger } from '~/lib/.server/logger';
|
import { createScopedLogger } from '~/lib/.server/logger';
|
||||||
import { DEFAULT_PROVIDER } from '~/utils/constants';
|
import { DEFAULT_PROVIDER } from '~/lib/modules/constants';
|
||||||
import { stripIndents } from '~/utils/strip-indent';
|
import { stripIndents } from '~/utils/strip-indent';
|
||||||
|
|
||||||
const logger = createScopedLogger('stream-enhancer');
|
const logger = createScopedLogger('stream-enhancer');
|
||||||
|
|||||||
17
app/lib/modules/constants.ts
Normal file
17
app/lib/modules/constants.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { LLMManager } from '~/lib/modules/llm/manager.server';
|
||||||
|
|
||||||
|
const llmManager = LLMManager.getInstance();
|
||||||
|
|
||||||
|
export const DEFAULT_MODEL = llmManager.getDefaultModel();
|
||||||
|
export const MINOR_MODEL = llmManager.getMinorModel();
|
||||||
|
export const DEFAULT_PROVIDER = llmManager.getDefaultProvider();
|
||||||
|
|
||||||
|
export const DEFAULT_MODEL_DETAILS = DEFAULT_PROVIDER.staticModels.find((m) => m.name === DEFAULT_MODEL);
|
||||||
|
export const MINOR_MODEL_DETAILS = DEFAULT_PROVIDER.staticModels.find((m) => m.name === MINOR_MODEL);
|
||||||
|
|
||||||
|
export const getModel = (model: string) => {
|
||||||
|
return DEFAULT_PROVIDER.getModelInstance({
|
||||||
|
model,
|
||||||
|
providerSettings: llmManager.getConfiguredProviderSettings(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import { createOpenAI } from '@ai-sdk/openai';
|
import { createOpenAI } from '@ai-sdk/openai';
|
||||||
import type { LanguageModel } from 'ai';
|
import type { LanguageModel } from 'ai';
|
||||||
import type { IProviderSetting } from '~/types/model';
|
import type { IProviderSetting } from '~/types/model';
|
||||||
import type { ModelInfo, ProviderConfig, ProviderInfo } from './types';
|
import type { ModelInfo, ProviderInfo } from './types';
|
||||||
|
|
||||||
export abstract class BaseProvider implements ProviderInfo {
|
export abstract class BaseProvider implements ProviderInfo {
|
||||||
abstract name: string;
|
abstract name: string;
|
||||||
abstract staticModels: ModelInfo[];
|
abstract staticModels: ModelInfo[];
|
||||||
abstract config: ProviderConfig;
|
|
||||||
cachedDynamicModels?: {
|
cachedDynamicModels?: {
|
||||||
cacheId: string;
|
cacheId: string;
|
||||||
models: ModelInfo[];
|
models: ModelInfo[];
|
||||||
@@ -16,39 +15,21 @@ export abstract class BaseProvider implements ProviderInfo {
|
|||||||
labelForGetApiKey?: string;
|
labelForGetApiKey?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
getProviderBaseUrlAndKey(options: {
|
getProviderBaseUrlAndKey(providerSettings?: IProviderSetting) {
|
||||||
apiKeys?: Record<string, string>;
|
let baseUrl = providerSettings?.baseUrl;
|
||||||
providerSettings?: IProviderSetting;
|
|
||||||
defaultBaseUrlKey: string;
|
|
||||||
defaultApiTokenKey: string;
|
|
||||||
}) {
|
|
||||||
const { apiKeys, providerSettings, defaultBaseUrlKey, defaultApiTokenKey } = options;
|
|
||||||
let settingsBaseUrl = providerSettings?.baseUrl;
|
|
||||||
|
|
||||||
if (settingsBaseUrl && settingsBaseUrl.length == 0) {
|
|
||||||
settingsBaseUrl = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseUrlKey = this.config.baseUrlKey || defaultBaseUrlKey;
|
|
||||||
let baseUrl =
|
|
||||||
settingsBaseUrl || process?.env?.[baseUrlKey] || (import.meta.env as any)?.[baseUrlKey] || this.config.baseUrl;
|
|
||||||
|
|
||||||
if (baseUrl && baseUrl.endsWith('/')) {
|
if (baseUrl && baseUrl.endsWith('/')) {
|
||||||
baseUrl = baseUrl.slice(0, -1);
|
baseUrl = baseUrl.slice(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiTokenKey = this.config.apiTokenKey || defaultApiTokenKey;
|
const apiKey = providerSettings?.apiKey;
|
||||||
const apiKey = apiKeys?.[this.name] || process?.env?.[apiTokenKey] || (import.meta.env as any)?.[apiTokenKey];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
baseUrl,
|
baseUrl,
|
||||||
apiKey,
|
apiKey,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
getModelsFromCache(options: {
|
|
||||||
apiKeys?: Record<string, string>;
|
getModelsFromCache(options: { providerSettings?: Record<string, IProviderSetting> }): ModelInfo[] | null {
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): ModelInfo[] | null {
|
|
||||||
if (!this.cachedDynamicModels) {
|
if (!this.cachedDynamicModels) {
|
||||||
// console.log('no dynamic models',this.name);
|
// console.log('no dynamic models',this.name);
|
||||||
return null;
|
return null;
|
||||||
@@ -65,22 +46,13 @@ export abstract class BaseProvider implements ProviderInfo {
|
|||||||
|
|
||||||
return this.cachedDynamicModels.models;
|
return this.cachedDynamicModels.models;
|
||||||
}
|
}
|
||||||
getDynamicModelsCacheKey(options: {
|
getDynamicModelsCacheKey(options: { providerSettings?: Record<string, IProviderSetting> }) {
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}) {
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
apiKeys: options.apiKeys?.[this.name],
|
apiKeys: options.providerSettings?.[this.name]?.apiKey,
|
||||||
providerSettings: options.providerSettings?.[this.name],
|
providerSettings: options.providerSettings?.[this.name],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
storeDynamicModels(
|
storeDynamicModels(options: { providerSettings?: Record<string, IProviderSetting> }, models: ModelInfo[]) {
|
||||||
options: {
|
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
},
|
|
||||||
models: ModelInfo[],
|
|
||||||
) {
|
|
||||||
const cacheId = this.getDynamicModelsCacheKey(options);
|
const cacheId = this.getDynamicModelsCacheKey(options);
|
||||||
|
|
||||||
// console.log('caching dynamic models',this.name,cacheId);
|
// console.log('caching dynamic models',this.name,cacheId);
|
||||||
@@ -91,11 +63,10 @@ export abstract class BaseProvider implements ProviderInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Declare the optional getDynamicModels method
|
// Declare the optional getDynamicModels method
|
||||||
getDynamicModels?(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]>;
|
getDynamicModels?(settings?: IProviderSetting): Promise<ModelInfo[]>;
|
||||||
|
|
||||||
abstract getModelInstance(options: {
|
abstract getModelInstance(options: {
|
||||||
model: string;
|
model: string;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
providerSettings?: Record<string, IProviderSetting>;
|
||||||
}): LanguageModel;
|
}): LanguageModel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ import * as providers from './registry';
|
|||||||
import type { ModelInfo, ProviderInfo } from './types';
|
import type { ModelInfo, ProviderInfo } from './types';
|
||||||
|
|
||||||
const logger = createScopedLogger('LLMManager');
|
const logger = createScopedLogger('LLMManager');
|
||||||
|
|
||||||
export class LLMManager {
|
export class LLMManager {
|
||||||
private static _instance: LLMManager;
|
private static _instance: LLMManager;
|
||||||
private _providers: Map<string, BaseProvider> = new Map();
|
private _providers: Map<string, BaseProvider> = new Map();
|
||||||
private _modelList: ModelInfo[] = [];
|
private _modelList: ModelInfo[] = [];
|
||||||
|
|
||||||
private constructor() {
|
constructor() {
|
||||||
this._registerProvidersFromDirectory();
|
this._registerProvidersFromDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +23,6 @@ export class LLMManager {
|
|||||||
return LLMManager._instance;
|
return LLMManager._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从环境变量中读取配置的辅助方法
|
|
||||||
private _getEnvConfig<T>(key: string, defaultValue: T): T {
|
private _getEnvConfig<T>(key: string, defaultValue: T): T {
|
||||||
const value = process?.env?.[key] || (import.meta.env as any)?.[key];
|
const value = process?.env?.[key] || (import.meta.env as any)?.[key];
|
||||||
|
|
||||||
@@ -32,9 +32,13 @@ export class LLMManager {
|
|||||||
|
|
||||||
if (typeof defaultValue === 'boolean') {
|
if (typeof defaultValue === 'boolean') {
|
||||||
return (value === 'true' || value === true) as unknown as T;
|
return (value === 'true' || value === true) as unknown as T;
|
||||||
} else if (typeof defaultValue === 'number') {
|
}
|
||||||
|
|
||||||
|
if (typeof defaultValue === 'number') {
|
||||||
return Number(value) as unknown as T;
|
return Number(value) as unknown as T;
|
||||||
} else if (Array.isArray(defaultValue)) {
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(defaultValue)) {
|
||||||
return (value
|
return (value
|
||||||
? String(value)
|
? String(value)
|
||||||
.split(',')
|
.split(',')
|
||||||
@@ -45,19 +49,35 @@ export class LLMManager {
|
|||||||
return value as T;
|
return value as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getUnifiedProviderConfig() {
|
||||||
|
const providerName = this._getEnvConfig<string>('LLM_PROVIDER', '');
|
||||||
|
const baseUrl = this._getEnvConfig<string>('PROVIDER_BASE_URL', '');
|
||||||
|
const apiKey = this._getEnvConfig<string>('PROVIDER_API_KEY', '');
|
||||||
|
|
||||||
|
return {
|
||||||
|
providerName,
|
||||||
|
baseUrl,
|
||||||
|
apiKey,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultProvider(): BaseProvider {
|
||||||
|
const { providerName } = this._getUnifiedProviderConfig();
|
||||||
|
|
||||||
|
if (!providerName || !this._providers.has(providerName)) {
|
||||||
|
throw new Error(
|
||||||
|
`Provider ${providerName} not found, Effective Provider: ${Array.from(this._providers.values())
|
||||||
|
.map((p) => p.name)
|
||||||
|
.join(', ')}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._providers.get(providerName)!;
|
||||||
|
}
|
||||||
|
|
||||||
private _registerProvidersFromDirectory() {
|
private _registerProvidersFromDirectory() {
|
||||||
const allProviders: BaseProvider[] = Object.values(providers).map((providerClass) => new providerClass());
|
const allProviders: BaseProvider[] = Object.values(providers).map((providerClass) => new providerClass());
|
||||||
|
for (const provider of allProviders) {
|
||||||
// 获取环境变量中的启用提供商列表
|
|
||||||
const enabledProviders = this._getEnvConfig<string[]>('LLM_ENABLED_PROVIDERS', []);
|
|
||||||
|
|
||||||
// 过滤提供商,仅保留配置中启用的提供商
|
|
||||||
const filteredProviders =
|
|
||||||
enabledProviders.length > 0
|
|
||||||
? allProviders.filter((provider) => enabledProviders.includes(provider.name))
|
|
||||||
: allProviders;
|
|
||||||
|
|
||||||
for (const provider of filteredProviders) {
|
|
||||||
this.registerProvider(provider);
|
this.registerProvider(provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,24 +92,6 @@ export class LLMManager {
|
|||||||
this._modelList = [...this._modelList, ...provider.staticModels];
|
this._modelList = [...this._modelList, ...provider.staticModels];
|
||||||
}
|
}
|
||||||
|
|
||||||
getProvider(name: string): BaseProvider | undefined {
|
|
||||||
return this._providers.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllProviders(): BaseProvider[] {
|
|
||||||
return Array.from(this._providers.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultProvider(): BaseProvider {
|
|
||||||
const defaultProviderName = this._getEnvConfig<string>('LLM_DEFAULT_PROVIDER', '');
|
|
||||||
|
|
||||||
if (defaultProviderName && this._providers.has(defaultProviderName)) {
|
|
||||||
return this._providers.get(defaultProviderName)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(this._providers.values())[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultModel(): string {
|
getDefaultModel(): string {
|
||||||
return this._getEnvConfig<string>('LLM_DEFAULT_MODEL', '');
|
return this._getEnvConfig<string>('LLM_DEFAULT_MODEL', '');
|
||||||
}
|
}
|
||||||
@@ -98,58 +100,16 @@ export class LLMManager {
|
|||||||
return this._getEnvConfig<string>('LLM_MINOR_MODEL', '');
|
return this._getEnvConfig<string>('LLM_MINOR_MODEL', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfiguredApiKeys(): Record<string, string> {
|
|
||||||
const apiKeys: Record<string, string> = {};
|
|
||||||
|
|
||||||
const allProviders = this.getAllProviders();
|
|
||||||
|
|
||||||
for (const provider of allProviders) {
|
|
||||||
if (!provider.config.apiTokenKey) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiTokenKey = provider.config.apiTokenKey;
|
|
||||||
|
|
||||||
const apiKey = process?.env?.[apiTokenKey] || (import.meta.env as any)?.[apiTokenKey];
|
|
||||||
|
|
||||||
if (apiKey) {
|
|
||||||
apiKeys[provider.name] = apiKey;
|
|
||||||
logger.debug(`Found API key for provider ${provider.name} in environment variables`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfiguredProviderSettings(): Record<string, IProviderSetting> {
|
getConfiguredProviderSettings(): Record<string, IProviderSetting> {
|
||||||
const providerSettings: Record<string, IProviderSetting> = {};
|
const providerSettings: Record<string, IProviderSetting> = {};
|
||||||
|
|
||||||
// 获取所有注册的提供商
|
const { providerName, baseUrl, apiKey } = this._getUnifiedProviderConfig();
|
||||||
const allProviders = this.getAllProviders();
|
|
||||||
|
|
||||||
for (const provider of allProviders) {
|
|
||||||
const providerName = provider.name;
|
|
||||||
const settings: IProviderSetting = { enabled: true };
|
|
||||||
|
|
||||||
if (provider.config.baseUrlKey) {
|
|
||||||
const baseUrlKey = provider.config.baseUrlKey;
|
|
||||||
const baseUrl = process?.env?.[baseUrlKey] || (import.meta.env as any)?.[baseUrlKey];
|
|
||||||
|
|
||||||
if (baseUrl) {
|
|
||||||
settings.baseUrl = baseUrl;
|
|
||||||
logger.debug(`Found base URL for provider ${providerName} in environment variables: ${baseUrl}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const enabledKey = `${providerName.toUpperCase()}_ENABLED`;
|
|
||||||
const isEnabled = this._getEnvConfig<boolean>(enabledKey, true);
|
|
||||||
settings.enabled = isEnabled;
|
|
||||||
|
|
||||||
if (Object.keys(settings).length > 1 || settings.enabled === false) {
|
|
||||||
providerSettings[providerName] = settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
providerSettings[providerName] = {
|
||||||
|
enabled: true,
|
||||||
|
baseUrl,
|
||||||
|
apiKey,
|
||||||
|
};
|
||||||
return providerSettings;
|
return providerSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,11 +117,8 @@ export class LLMManager {
|
|||||||
return this._modelList;
|
return this._modelList;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateModelList(options: {
|
async updateModelList(options: { providerSettings?: Record<string, IProviderSetting> }): Promise<ModelInfo[]> {
|
||||||
apiKeys?: Record<string, string>;
|
const { providerSettings } = options;
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): Promise<ModelInfo[]> {
|
|
||||||
const { apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
let enabledProviders = Array.from(this._providers.values()).map((p) => p.name);
|
let enabledProviders = Array.from(this._providers.values()).map((p) => p.name);
|
||||||
|
|
||||||
@@ -185,7 +142,7 @@ export class LLMManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dynamicModels = await provider
|
const dynamicModels = await provider
|
||||||
.getDynamicModels(apiKeys, providerSettings?.[provider.name])
|
.getDynamicModels(providerSettings?.[provider.name])
|
||||||
.then((models) => {
|
.then((models) => {
|
||||||
logger.info(`Caching ${models.length} dynamic models for ${provider.name}`);
|
logger.info(`Caching ${models.length} dynamic models for ${provider.name}`);
|
||||||
provider.storeDynamicModels(options, models);
|
provider.storeDynamicModels(options, models);
|
||||||
@@ -218,7 +175,6 @@ export class LLMManager {
|
|||||||
async getModelListFromProvider(
|
async getModelListFromProvider(
|
||||||
providerArg: BaseProvider,
|
providerArg: BaseProvider,
|
||||||
options: {
|
options: {
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
providerSettings?: Record<string, IProviderSetting>;
|
||||||
},
|
},
|
||||||
): Promise<ModelInfo[]> {
|
): Promise<ModelInfo[]> {
|
||||||
@@ -234,10 +190,9 @@ export class LLMManager {
|
|||||||
return staticModels;
|
return staticModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { apiKeys, providerSettings } = options;
|
const { providerSettings } = options;
|
||||||
|
|
||||||
const cachedModels = provider.getModelsFromCache({
|
const cachedModels = provider.getModelsFromCache({
|
||||||
apiKeys,
|
|
||||||
providerSettings,
|
providerSettings,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -249,7 +204,7 @@ export class LLMManager {
|
|||||||
logger.info(`Getting dynamic models for ${provider.name}`);
|
logger.info(`Getting dynamic models for ${provider.name}`);
|
||||||
|
|
||||||
const dynamicModels = await provider
|
const dynamicModels = await provider
|
||||||
.getDynamicModels?.(apiKeys, providerSettings?.[provider.name])
|
.getDynamicModels?.(providerSettings?.[provider.name])
|
||||||
.then((models) => {
|
.then((models) => {
|
||||||
logger.info(`Got ${models.length} dynamic models for ${provider.name}`);
|
logger.info(`Got ${models.length} dynamic models for ${provider.name}`);
|
||||||
provider.storeDynamicModels(options, models);
|
provider.storeDynamicModels(options, models);
|
||||||
@@ -15,10 +15,6 @@ export default class AmazonBedrockProvider extends BaseProvider {
|
|||||||
name = 'AmazonBedrock';
|
name = 'AmazonBedrock';
|
||||||
getApiKeyLink = 'https://console.aws.amazon.com/iam/home';
|
getApiKeyLink = 'https://console.aws.amazon.com/iam/home';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'AWS_BEDROCK_CONFIG',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
name: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
||||||
@@ -91,19 +87,10 @@ export default class AmazonBedrockProvider extends BaseProvider {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'AWS_BEDROCK_CONFIG',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class AnthropicProvider extends BaseProvider {
|
|||||||
name = 'Anthropic';
|
name = 'Anthropic';
|
||||||
getApiKeyLink = 'https://console.anthropic.com/settings/keys';
|
getApiKeyLink = 'https://console.anthropic.com/settings/keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'ANTHROPIC_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'claude-3-7-sonnet-20250219',
|
name: 'claude-3-7-sonnet-20250219',
|
||||||
@@ -42,13 +38,8 @@ export default class AnthropicProvider extends BaseProvider {
|
|||||||
{ name: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku', provider: 'Anthropic', maxTokenAllowed: 8000 },
|
{ name: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku', provider: 'Anthropic', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'ANTHROPIC_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw `Missing Api Key configuration for ${this.name} provider`;
|
throw `Missing Api Key configuration for ${this.name} provider`;
|
||||||
@@ -74,22 +65,14 @@ export default class AnthropicProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance: (options: {
|
getModelInstance: (options: { model: string; providerSettings?: Record<string, IProviderSetting> }) => LanguageModel =
|
||||||
model: string;
|
(options) => {
|
||||||
apiKeys?: Record<string, string>;
|
const { providerSettings, model } = options;
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings);
|
||||||
}) => LanguageModel = (options) => {
|
const anthropic = createAnthropic({
|
||||||
const { apiKeys, providerSettings, model } = options;
|
apiKey,
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
});
|
||||||
apiKeys,
|
|
||||||
providerSettings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'ANTHROPIC_API_KEY',
|
|
||||||
});
|
|
||||||
const anthropic = createAnthropic({
|
|
||||||
apiKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
return anthropic(model);
|
return anthropic(model);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class CohereProvider extends BaseProvider {
|
|||||||
name = 'Cohere';
|
name = 'Cohere';
|
||||||
getApiKeyLink = 'https://dashboard.cohere.com/api-keys';
|
getApiKeyLink = 'https://dashboard.cohere.com/api-keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'COHERE_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'command-r-plus-08-2024', label: 'Command R plus Latest', provider: 'Cohere', maxTokenAllowed: 4096 },
|
{ name: 'command-r-plus-08-2024', label: 'Command R plus Latest', provider: 'Cohere', maxTokenAllowed: 4096 },
|
||||||
{ name: 'command-r-08-2024', label: 'Command R Latest', provider: 'Cohere', maxTokenAllowed: 4096 },
|
{ name: 'command-r-08-2024', label: 'Command R Latest', provider: 'Cohere', maxTokenAllowed: 4096 },
|
||||||
@@ -25,19 +21,10 @@ export default class CohereProvider extends BaseProvider {
|
|||||||
{ name: 'c4ai-aya-expanse-32b', label: 'c4AI Aya Expanse 32b', provider: 'Cohere', maxTokenAllowed: 4096 },
|
{ name: 'c4ai-aya-expanse-32b', label: 'c4AI Aya Expanse 32b', provider: 'Cohere', maxTokenAllowed: 4096 },
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'COHERE_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export default class DeepseekProvider extends BaseProvider {
|
|||||||
|
|
||||||
config = {
|
config = {
|
||||||
apiTokenKey: 'DEEPSEEK_API_KEY',
|
apiTokenKey: 'DEEPSEEK_API_KEY',
|
||||||
|
baseUrlKey: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
@@ -18,19 +19,10 @@ export default class DeepseekProvider extends BaseProvider {
|
|||||||
{ name: 'deepseek-reasoner', label: 'Deepseek-Reasoner', provider: 'Deepseek', maxTokenAllowed: 8000 },
|
{ name: 'deepseek-reasoner', label: 'Deepseek-Reasoner', provider: 'Deepseek', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'DEEPSEEK_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class GithubProvider extends BaseProvider {
|
|||||||
name = 'Github';
|
name = 'Github';
|
||||||
getApiKeyLink = 'https://github.com/settings/personal-access-tokens';
|
getApiKeyLink = 'https://github.com/settings/personal-access-tokens';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'GITHUB_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
// find more in https://github.com/marketplace?type=models
|
// find more in https://github.com/marketplace?type=models
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'gpt-4o', label: 'GPT-4o', provider: 'Github', maxTokenAllowed: 8000 },
|
{ name: 'gpt-4o', label: 'GPT-4o', provider: 'Github', maxTokenAllowed: 8000 },
|
||||||
@@ -23,19 +19,10 @@ export default class GithubProvider extends BaseProvider {
|
|||||||
{ name: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', provider: 'Github', maxTokenAllowed: 8000 },
|
{ name: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', provider: 'Github', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'GITHUB_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class GoogleProvider extends BaseProvider {
|
|||||||
name = 'Google';
|
name = 'Google';
|
||||||
getApiKeyLink = 'https://aistudio.google.com/app/apikey';
|
getApiKeyLink = 'https://aistudio.google.com/app/apikey';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'gemini-1.5-flash-latest', label: 'Gemini 1.5 Flash', provider: 'Google', maxTokenAllowed: 8192 },
|
{ name: 'gemini-1.5-flash-latest', label: 'Gemini 1.5 Flash', provider: 'Google', maxTokenAllowed: 8192 },
|
||||||
{
|
{
|
||||||
@@ -28,13 +24,8 @@ export default class GoogleProvider extends BaseProvider {
|
|||||||
{ name: 'gemini-exp-1206', label: 'Gemini exp-1206', provider: 'Google', maxTokenAllowed: 8192 },
|
{ name: 'gemini-exp-1206', label: 'Gemini exp-1206', provider: 'Google', maxTokenAllowed: 8192 },
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw `Missing Api Key configuration for ${this.name} provider`;
|
throw `Missing Api Key configuration for ${this.name} provider`;
|
||||||
@@ -59,19 +50,10 @@ export default class GoogleProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class GroqProvider extends BaseProvider {
|
|||||||
name = 'Groq';
|
name = 'Groq';
|
||||||
getApiKeyLink = 'https://console.groq.com/keys';
|
getApiKeyLink = 'https://console.groq.com/keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'GROQ_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'llama-3.1-8b-instant', label: 'Llama 3.1 8b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
|
{ name: 'llama-3.1-8b-instant', label: 'Llama 3.1 8b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
|
||||||
{ name: 'llama-3.2-11b-vision-preview', label: 'Llama 3.2 11b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
|
{ name: 'llama-3.2-11b-vision-preview', label: 'Llama 3.2 11b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
|
||||||
@@ -27,13 +23,8 @@ export default class GroqProvider extends BaseProvider {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'GROQ_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw `Missing Api Key configuration for ${this.name} provider`;
|
throw `Missing Api Key configuration for ${this.name} provider`;
|
||||||
@@ -59,19 +50,10 @@ export default class GroqProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'GROQ_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class HuggingFaceProvider extends BaseProvider {
|
|||||||
name = 'HuggingFace';
|
name = 'HuggingFace';
|
||||||
getApiKeyLink = 'https://huggingface.co/settings/tokens';
|
getApiKeyLink = 'https://huggingface.co/settings/tokens';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'HuggingFace_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
||||||
@@ -81,19 +77,10 @@ export default class HuggingFaceProvider extends BaseProvider {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'HuggingFace_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class HyperbolicProvider extends BaseProvider {
|
|||||||
name = 'Hyperbolic';
|
name = 'Hyperbolic';
|
||||||
getApiKeyLink = 'https://app.hyperbolic.xyz/settings';
|
getApiKeyLink = 'https://app.hyperbolic.xyz/settings';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'HYPERBOLIC_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
||||||
@@ -45,13 +41,8 @@ export default class HyperbolicProvider extends BaseProvider {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { baseUrl: fetchBaseUrl, apiKey } = this.getProviderBaseUrlAndKey({
|
const { baseUrl: fetchBaseUrl, apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'HYPERBOLIC_API_KEY',
|
|
||||||
});
|
|
||||||
const baseUrl = fetchBaseUrl || 'https://api.hyperbolic.xyz/v1';
|
const baseUrl = fetchBaseUrl || 'https://api.hyperbolic.xyz/v1';
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
@@ -76,19 +67,10 @@ export default class HyperbolicProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'HYPERBOLIC_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw `Missing Api Key configuration for ${this.name} provider`;
|
throw `Missing Api Key configuration for ${this.name} provider`;
|
||||||
|
|||||||
@@ -5,29 +5,21 @@ import type { ModelInfo } from '~/lib/modules/llm/types';
|
|||||||
import type { IProviderSetting } from '~/types/model';
|
import type { IProviderSetting } from '~/types/model';
|
||||||
import { logger } from '~/utils/logger';
|
import { logger } from '~/utils/logger';
|
||||||
|
|
||||||
|
export const BASE_URL = 'http://127.0.0.1:1234/';
|
||||||
export default class LMStudioProvider extends BaseProvider {
|
export default class LMStudioProvider extends BaseProvider {
|
||||||
name = 'LMStudio';
|
name = 'LMStudio';
|
||||||
getApiKeyLink = 'https://lmstudio.ai/';
|
getApiKeyLink = 'https://lmstudio.ai/';
|
||||||
labelForGetApiKey = 'Get LMStudio';
|
labelForGetApiKey = 'Get LMStudio';
|
||||||
icon = 'i-ph:cloud-arrow-down';
|
icon = 'i-ph:cloud-arrow-down';
|
||||||
|
|
||||||
config = {
|
|
||||||
baseUrlKey: 'LMSTUDIO_API_BASE_URL',
|
|
||||||
baseUrl: 'http://localhost:1234/',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [];
|
staticModels: ModelInfo[] = [];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
let { baseUrl } = this.getProviderBaseUrlAndKey({
|
let { baseUrl } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: 'LMSTUDIO_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
throw new Error('No baseUrl found for LMStudio provider');
|
logger.debug('No baseUrl found for LMStudio provider, using default: ', BASE_URL);
|
||||||
|
baseUrl = BASE_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
@@ -51,37 +43,30 @@ export default class LMStudioProvider extends BaseProvider {
|
|||||||
maxTokenAllowed: 8000,
|
maxTokenAllowed: 8000,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
getModelInstance: (options: {
|
getModelInstance: (options: { model: string; providerSettings?: Record<string, IProviderSetting> }) => LanguageModel =
|
||||||
model: string;
|
(options) => {
|
||||||
apiKeys?: Record<string, string>;
|
const { providerSettings, model } = options;
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
let { baseUrl } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
}) => LanguageModel = (options) => {
|
|
||||||
const { apiKeys, providerSettings, model } = options;
|
|
||||||
let { baseUrl } = this.getProviderBaseUrlAndKey({
|
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: 'LMSTUDIO_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
throw new Error('No baseUrl found for LMStudio provider');
|
logger.debug('No baseUrl found for LMStudio provider, using default: ', BASE_URL);
|
||||||
}
|
baseUrl = BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true';
|
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true';
|
||||||
|
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
|
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
|
||||||
baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
|
baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('LMStudio Base Url used: ', baseUrl);
|
logger.debug('LMStudio Base Url used: ', baseUrl);
|
||||||
|
|
||||||
const lmstudio = createOpenAI({
|
const lmstudio = createOpenAI({
|
||||||
baseURL: `${baseUrl}/v1`,
|
baseURL: `${baseUrl}/v1`,
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
return lmstudio(model);
|
return lmstudio(model);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class MistralProvider extends BaseProvider {
|
|||||||
name = 'Mistral';
|
name = 'Mistral';
|
||||||
getApiKeyLink = 'https://console.mistral.ai/api-keys/';
|
getApiKeyLink = 'https://console.mistral.ai/api-keys/';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'MISTRAL_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'open-mistral-7b', label: 'Mistral 7B', provider: 'Mistral', maxTokenAllowed: 8000 },
|
{ name: 'open-mistral-7b', label: 'Mistral 7B', provider: 'Mistral', maxTokenAllowed: 8000 },
|
||||||
{ name: 'open-mixtral-8x7b', label: 'Mistral 8x7B', provider: 'Mistral', maxTokenAllowed: 8000 },
|
{ name: 'open-mixtral-8x7b', label: 'Mistral 8x7B', provider: 'Mistral', maxTokenAllowed: 8000 },
|
||||||
@@ -24,19 +20,10 @@ export default class MistralProvider extends BaseProvider {
|
|||||||
{ name: 'mistral-large-latest', label: 'Mistral Large Latest', provider: 'Mistral', maxTokenAllowed: 8000 },
|
{ name: 'mistral-large-latest', label: 'Mistral Large Latest', provider: 'Mistral', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'MISTRAL_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -27,32 +27,26 @@ export interface OllamaApiResponse {
|
|||||||
models: OllamaModel[];
|
models: OllamaModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BASE_URL = 'http://127.0.0.1:11434';
|
||||||
|
|
||||||
export default class OllamaProvider extends BaseProvider {
|
export default class OllamaProvider extends BaseProvider {
|
||||||
name = 'Ollama';
|
name = 'Ollama';
|
||||||
getApiKeyLink = 'https://ollama.com/download';
|
getApiKeyLink = 'https://ollama.com/download';
|
||||||
labelForGetApiKey = 'Download Ollama';
|
labelForGetApiKey = 'Download Ollama';
|
||||||
icon = 'i-ph:cloud-arrow-down';
|
icon = 'i-ph:cloud-arrow-down';
|
||||||
|
|
||||||
config = {
|
|
||||||
baseUrlKey: 'OLLAMA_API_BASE_URL',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [];
|
staticModels: ModelInfo[] = [];
|
||||||
|
|
||||||
getDefaultNumCtx(): number {
|
getDefaultNumCtx(): number {
|
||||||
return process.env.DEFAULT_NUM_CTX ? parseInt(process.env.DEFAULT_NUM_CTX, 10) : 32768;
|
return process.env.DEFAULT_NUM_CTX ? parseInt(process.env.DEFAULT_NUM_CTX, 10) : 32768;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
let { baseUrl } = this.getProviderBaseUrlAndKey({
|
let { baseUrl } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: 'OLLAMA_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
throw new Error('No baseUrl found for OLLAMA provider');
|
logger.debug('No baseUrl found for OLLAMA provider, using default: ', BASE_URL);
|
||||||
|
baseUrl = BASE_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
@@ -79,35 +73,28 @@ export default class OllamaProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance: (options: {
|
getModelInstance: (options: { model: string; providerSettings?: Record<string, IProviderSetting> }) => LanguageModel =
|
||||||
model: string;
|
(options) => {
|
||||||
apiKeys?: Record<string, string>;
|
const { providerSettings, model } = options;
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}) => LanguageModel = (options) => {
|
|
||||||
const { apiKeys, providerSettings, model } = options;
|
|
||||||
|
|
||||||
let { baseUrl } = this.getProviderBaseUrlAndKey({
|
let { baseUrl } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: 'OLLAMA_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Backend: Check if we're running in Docker
|
// Backend: Check if we're running in Docker
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
throw new Error('No baseUrl found for OLLAMA provider');
|
logger.debug('No baseUrl found for OLLAMA provider, using default: ', BASE_URL);
|
||||||
}
|
baseUrl = BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true';
|
const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true';
|
||||||
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
|
baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
|
||||||
baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
|
baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
|
||||||
|
|
||||||
logger.debug('Ollama Base Url used: ', baseUrl);
|
logger.debug('Ollama Base Url used: ', baseUrl);
|
||||||
|
|
||||||
const ollama = createOllama({
|
const ollama = createOllama({
|
||||||
baseURL: `${baseUrl}/api`,
|
baseURL: `${baseUrl}/api`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return ollama(model);
|
return ollama(model);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,6 @@ export default class OpenRouterProvider extends BaseProvider {
|
|||||||
name = 'OpenRouter';
|
name = 'OpenRouter';
|
||||||
getApiKeyLink = 'https://openrouter.ai/settings/keys';
|
getApiKeyLink = 'https://openrouter.ai/settings/keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'OPEN_ROUTER_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'anthropic/claude-3.5-sonnet',
|
name: 'anthropic/claude-3.5-sonnet',
|
||||||
@@ -73,11 +69,7 @@ export default class OpenRouterProvider extends BaseProvider {
|
|||||||
{ name: 'cohere/command', label: 'Cohere Command (OpenRouter)', provider: 'OpenRouter', maxTokenAllowed: 4096 },
|
{ name: 'cohere/command', label: 'Cohere Command (OpenRouter)', provider: 'OpenRouter', maxTokenAllowed: 4096 },
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(
|
async getDynamicModels(_settings?: IProviderSetting, _serverEnv: Record<string, string> = {}): Promise<ModelInfo[]> {
|
||||||
_apiKeys?: Record<string, string>,
|
|
||||||
_settings?: IProviderSetting,
|
|
||||||
_serverEnv: Record<string, string> = {},
|
|
||||||
): Promise<ModelInfo[]> {
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('https://openrouter.ai/api/v1/models', {
|
const response = await fetch('https://openrouter.ai/api/v1/models', {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -101,19 +93,10 @@ export default class OpenRouterProvider extends BaseProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'OPEN_ROUTER_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -7,20 +7,10 @@ export default class OpenAILikeProvider extends BaseProvider {
|
|||||||
name = 'OpenAILike';
|
name = 'OpenAILike';
|
||||||
getApiKeyLink = undefined;
|
getApiKeyLink = undefined;
|
||||||
|
|
||||||
config = {
|
|
||||||
baseUrlKey: 'OPENAI_LIKE_API_BASE_URL',
|
|
||||||
apiTokenKey: 'OPENAI_LIKE_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [];
|
staticModels: ModelInfo[] = [];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey({
|
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: 'OPENAI_LIKE_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: 'OPENAI_LIKE_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl || !apiKey) {
|
if (!baseUrl || !apiKey) {
|
||||||
return [];
|
return [];
|
||||||
@@ -42,19 +32,10 @@ export default class OpenAILikeProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey({
|
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: 'OPENAI_LIKE_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: 'OPENAI_LIKE_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl || !apiKey) {
|
if (!baseUrl || !apiKey) {
|
||||||
throw new Error(`Missing configuration for ${this.name} provider`);
|
throw new Error(`Missing configuration for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
name = 'OpenAI';
|
name = 'OpenAI';
|
||||||
getApiKeyLink = 'https://platform.openai.com/api-keys';
|
getApiKeyLink = 'https://platform.openai.com/api-keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'OPENAI_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'gpt-4o', label: 'GPT-4o', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
{ name: 'gpt-4o', label: 'GPT-4o', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
||||||
{ name: 'gpt-4o-mini', label: 'GPT-4o Mini', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
{ name: 'gpt-4o-mini', label: 'GPT-4o Mini', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
||||||
@@ -20,13 +16,8 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
{ name: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
{ name: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', provider: 'OpenAI', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'OPENAI_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw `Missing Api Key configuration for ${this.name} provider`;
|
throw `Missing Api Key configuration for ${this.name} provider`;
|
||||||
@@ -56,19 +47,10 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'OPENAI_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ export default class PerplexityProvider extends BaseProvider {
|
|||||||
name = 'Perplexity';
|
name = 'Perplexity';
|
||||||
getApiKeyLink = 'https://www.perplexity.ai/settings/api';
|
getApiKeyLink = 'https://www.perplexity.ai/settings/api';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'PERPLEXITY_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'llama-3.1-sonar-small-128k-online',
|
name: 'llama-3.1-sonar-small-128k-online',
|
||||||
@@ -33,19 +29,10 @@ export default class PerplexityProvider extends BaseProvider {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'PERPLEXITY_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ export default class TogetherProvider extends BaseProvider {
|
|||||||
name = 'Together';
|
name = 'Together';
|
||||||
getApiKeyLink = 'https://api.together.xyz/settings/api-keys';
|
getApiKeyLink = 'https://api.together.xyz/settings/api-keys';
|
||||||
|
|
||||||
config = {
|
|
||||||
baseUrlKey: 'TOGETHER_API_BASE_URL',
|
|
||||||
apiTokenKey: 'TOGETHER_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{
|
{
|
||||||
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
||||||
@@ -33,13 +28,8 @@ export default class TogetherProvider extends BaseProvider {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async getDynamicModels(apiKeys?: Record<string, string>, settings?: IProviderSetting): Promise<ModelInfo[]> {
|
async getDynamicModels(settings?: IProviderSetting): Promise<ModelInfo[]> {
|
||||||
const { baseUrl: fetchBaseUrl, apiKey } = this.getProviderBaseUrlAndKey({
|
const { baseUrl: fetchBaseUrl, apiKey } = this.getProviderBaseUrlAndKey(settings);
|
||||||
apiKeys,
|
|
||||||
providerSettings: settings,
|
|
||||||
defaultBaseUrlKey: 'TOGETHER_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: 'TOGETHER_API_KEY',
|
|
||||||
});
|
|
||||||
const baseUrl = fetchBaseUrl || 'https://api.together.xyz/v1';
|
const baseUrl = fetchBaseUrl || 'https://api.together.xyz/v1';
|
||||||
|
|
||||||
if (!baseUrl || !apiKey) {
|
if (!baseUrl || !apiKey) {
|
||||||
@@ -65,19 +55,10 @@ export default class TogetherProvider extends BaseProvider {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey({
|
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: 'TOGETHER_API_BASE_URL',
|
|
||||||
defaultApiTokenKey: 'TOGETHER_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!baseUrl || !apiKey) {
|
if (!baseUrl || !apiKey) {
|
||||||
throw new Error(`Missing configuration for ${this.name} provider`);
|
throw new Error(`Missing configuration for ${this.name} provider`);
|
||||||
|
|||||||
@@ -8,28 +8,15 @@ export default class XAIProvider extends BaseProvider {
|
|||||||
name = 'xAI';
|
name = 'xAI';
|
||||||
getApiKeyLink = 'https://docs.x.ai/docs/quickstart#creating-an-api-key';
|
getApiKeyLink = 'https://docs.x.ai/docs/quickstart#creating-an-api-key';
|
||||||
|
|
||||||
config = {
|
|
||||||
apiTokenKey: 'XAI_API_KEY',
|
|
||||||
};
|
|
||||||
|
|
||||||
staticModels: ModelInfo[] = [
|
staticModels: ModelInfo[] = [
|
||||||
{ name: 'grok-beta', label: 'xAI Grok Beta', provider: 'xAI', maxTokenAllowed: 8000 },
|
{ name: 'grok-beta', label: 'xAI Grok Beta', provider: 'xAI', maxTokenAllowed: 8000 },
|
||||||
{ name: 'grok-2-1212', label: 'xAI Grok2 1212', provider: 'xAI', maxTokenAllowed: 8000 },
|
{ name: 'grok-2-1212', label: 'xAI Grok2 1212', provider: 'xAI', maxTokenAllowed: 8000 },
|
||||||
];
|
];
|
||||||
|
|
||||||
getModelInstance(options: {
|
getModelInstance(options: { model: string; providerSettings?: Record<string, IProviderSetting> }): LanguageModel {
|
||||||
model: string;
|
const { model, providerSettings } = options;
|
||||||
apiKeys?: Record<string, string>;
|
|
||||||
providerSettings?: Record<string, IProviderSetting>;
|
|
||||||
}): LanguageModel {
|
|
||||||
const { model, apiKeys, providerSettings } = options;
|
|
||||||
|
|
||||||
const { apiKey } = this.getProviderBaseUrlAndKey({
|
const { apiKey } = this.getProviderBaseUrlAndKey(providerSettings?.[this.name]);
|
||||||
apiKeys,
|
|
||||||
providerSettings: providerSettings?.[this.name],
|
|
||||||
defaultBaseUrlKey: '',
|
|
||||||
defaultApiTokenKey: 'XAI_API_KEY',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`Missing API key for ${this.name} provider`);
|
throw new Error(`Missing API key for ${this.name} provider`);
|
||||||
|
|||||||
@@ -23,6 +23,5 @@ export interface ProviderInfo {
|
|||||||
}
|
}
|
||||||
export interface ProviderConfig {
|
export interface ProviderConfig {
|
||||||
baseUrlKey?: string;
|
baseUrlKey?: string;
|
||||||
baseUrl?: string;
|
|
||||||
apiTokenKey?: string;
|
apiTokenKey?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ const logger = createScopedLogger('EditorProjects');
|
|||||||
*/
|
*/
|
||||||
export async function openEditorDatabase(): Promise<IDBDatabase | undefined> {
|
export async function openEditorDatabase(): Promise<IDBDatabase | undefined> {
|
||||||
if (typeof indexedDB === 'undefined') {
|
if (typeof indexedDB === 'undefined') {
|
||||||
logger.error('indexedDB 在当前环境中不可用');
|
logger.debug('indexedDB 在当前环境中不可用');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import { createScopedLogger } from '~/lib/.server/logger';
|
|||||||
import { getHistoryChatMessages, saveChatMessages, updateDiscardedMessage } from '~/lib/.server/message';
|
import { getHistoryChatMessages, saveChatMessages, updateDiscardedMessage } from '~/lib/.server/message';
|
||||||
import { getPageByMessageId } from '~/lib/.server/page';
|
import { getPageByMessageId } from '~/lib/.server/page';
|
||||||
import { CONTINUE_PROMPT } from '~/lib/common/prompts/prompts';
|
import { CONTINUE_PROMPT } from '~/lib/common/prompts/prompts';
|
||||||
|
import { DEFAULT_MODEL, DEFAULT_MODEL_DETAILS, getModel, MINOR_MODEL } from '~/lib/modules/constants';
|
||||||
import type { Page } from '~/types/actions';
|
import type { Page } from '~/types/actions';
|
||||||
import type { UPageUIMessage } from '~/types/message';
|
import type { UPageUIMessage } from '~/types/message';
|
||||||
import { DEFAULT_MODEL, DEFAULT_MODEL_DETAILS, getModel, MINOR_MODEL } from '~/utils/constants';
|
|
||||||
import { approximateUsageFromContent } from '~/utils/token';
|
import { approximateUsageFromContent } from '~/utils/token';
|
||||||
|
|
||||||
const logger = createScopedLogger('api.chat.chat');
|
const logger = createScopedLogger('api.chat.chat');
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import type { UIMessage } from 'ai';
|
|||||||
import { requireAuth } from '~/lib/.server/auth';
|
import { requireAuth } from '~/lib/.server/auth';
|
||||||
import { streamEnhancer } from '~/lib/.server/llm/stream-enhancer';
|
import { streamEnhancer } from '~/lib/.server/llm/stream-enhancer';
|
||||||
import { createScopedLogger } from '~/lib/.server/logger';
|
import { createScopedLogger } from '~/lib/.server/logger';
|
||||||
|
import { getModel, MINOR_MODEL } from '~/lib/modules/constants';
|
||||||
import { errorResponse } from '~/utils/api-response';
|
import { errorResponse } from '~/utils/api-response';
|
||||||
import { getModel, MINOR_MODEL } from '~/utils/constants';
|
|
||||||
|
|
||||||
export async function action(args: ActionFunctionArgs) {
|
export async function action(args: ActionFunctionArgs) {
|
||||||
const authResult = await requireAuth(args.request, { isApi: true });
|
const authResult = await requireAuth(args.request, { isApi: true });
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export type ProviderInfo = {
|
|||||||
export interface IProviderSetting {
|
export interface IProviderSetting {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
|
apiKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IProviderConfig = ProviderInfo & {
|
export type IProviderConfig = ProviderInfo & {
|
||||||
|
|||||||
@@ -1,31 +1,2 @@
|
|||||||
import { LLMManager } from '~/lib/modules/llm/manager';
|
|
||||||
|
|
||||||
export const WORK_DIR_NAME = 'project';
|
|
||||||
export const MODEL_REGEX = /^\[Model: (.*?)\]\n\n/;
|
export const MODEL_REGEX = /^\[Model: (.*?)\]\n\n/;
|
||||||
export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/;
|
export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/;
|
||||||
|
|
||||||
const llmManager = LLMManager.getInstance();
|
|
||||||
|
|
||||||
export const DEFAULT_MODEL = llmManager.getDefaultModel();
|
|
||||||
export const MINOR_MODEL = llmManager.getMinorModel();
|
|
||||||
export const PROVIDER_LIST = llmManager.getAllProviders();
|
|
||||||
export const DEFAULT_PROVIDER = llmManager.getDefaultProvider();
|
|
||||||
|
|
||||||
export const DEFAULT_MODEL_DETAILS = DEFAULT_PROVIDER.staticModels.find((m) => m.name === DEFAULT_MODEL);
|
|
||||||
export const MINOR_MODEL_DETAILS = DEFAULT_PROVIDER.staticModels.find((m) => m.name === MINOR_MODEL);
|
|
||||||
|
|
||||||
export const providerBaseUrlEnvKeys: Record<string, { baseUrlKey?: string; apiTokenKey?: string }> = {};
|
|
||||||
PROVIDER_LIST.forEach((provider) => {
|
|
||||||
providerBaseUrlEnvKeys[provider.name] = {
|
|
||||||
baseUrlKey: provider.config.baseUrlKey,
|
|
||||||
apiTokenKey: provider.config.apiTokenKey,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const getModel = (model: string) => {
|
|
||||||
return DEFAULT_PROVIDER.getModelInstance({
|
|
||||||
model,
|
|
||||||
apiKeys: llmManager.getConfiguredApiKeys(),
|
|
||||||
providerSettings: llmManager.getConfiguredProviderSettings(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -8,40 +8,21 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- OPERATING_ENV=${OPERATING_ENV:-production}
|
- OPERATING_ENV=${OPERATING_ENV:-production}
|
||||||
- NODE_ENV=${NODE_ENV:-production}
|
- NODE_ENV=${NODE_ENV:-production}
|
||||||
- GROQ_API_KEY=${GROQ_API_KEY}
|
|
||||||
- HuggingFace_API_KEY=${HuggingFace_API_KEY}
|
|
||||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
||||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
|
||||||
- OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY}
|
|
||||||
- GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY}
|
|
||||||
- OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL}
|
|
||||||
- OPENAI_LIKE_API_BASE_URL=${OPENAI_LIKE_API_BASE_URL}
|
|
||||||
- TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL}
|
|
||||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
|
||||||
- OPENAI_LIKE_API_KEY=${OPENAI_LIKE_API_KEY}
|
|
||||||
- TOGETHER_API_KEY=${TOGETHER_API_KEY}
|
|
||||||
- HYPERBOLIC_API_KEY=${HYPERBOLIC_API_KEY}
|
|
||||||
- HYPERBOLIC_API_BASE_URL=${HYPERBOLIC_API_BASE_URL}
|
|
||||||
- MISTRAL_API_KEY=${MISTRAL_API_KEY}
|
|
||||||
- COHERE_API_KEY=${COHERE_API_KEY}
|
|
||||||
- LMSTUDIO_API_BASE_URL=${LMSTUDIO_API_BASE_URL}
|
|
||||||
- XAI_API_KEY=${XAI_API_KEY}
|
|
||||||
- PERPLEXITY_API_KEY=${PERPLEXITY_API_KEY}
|
|
||||||
- AWS_BEDROCK_CONFIG=${AWS_BEDROCK_CONFIG}
|
|
||||||
- LOG_LEVEL=${LOG_LEVEL:-debug}
|
- LOG_LEVEL=${LOG_LEVEL:-debug}
|
||||||
- DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768}
|
- DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768}
|
||||||
- SERPER_API_KEY=${SERPER_API_KEY}
|
- LLM_PROVIDER=${LLM_DEFAULT_PROVIDER}
|
||||||
- WEATHER_API_KEY=${WEATHER_API_KEY}
|
- PROVIDER_BASE_URL=${PROVIDER_BASE_URL}
|
||||||
- LLM_DEFAULT_PROVIDER=${LLM_DEFAULT_PROVIDER}
|
- PROVIDER_API_KEY=${PROVIDER_API_KEY}
|
||||||
- LLM_DEFAULT_MODEL=${LLM_DEFAULT_MODEL}
|
- LLM_DEFAULT_MODEL=${LLM_DEFAULT_MODEL}
|
||||||
- LLM_MINOR_MODEL=${LLM_MINOR_MODEL}
|
- LLM_MINOR_MODEL=${LLM_MINOR_MODEL}
|
||||||
- LLM_ENABLED_PROVIDERS=${LLM_ENABLED_PROVIDERS}
|
- SERPER_API_KEY=${SERPER_API_KEY}
|
||||||
|
- WEATHER_API_KEY=${WEATHER_API_KEY}
|
||||||
- LOGTO_ENDPOINT=${LOGTO_ENDPOINT}
|
- LOGTO_ENDPOINT=${LOGTO_ENDPOINT}
|
||||||
- LOGTO_APP_ID=${LOGTO_APP_ID}
|
- LOGTO_APP_ID=${LOGTO_APP_ID}
|
||||||
- LOGTO_APP_SECRET=${LOGTO_APP_SECRET}
|
- LOGTO_APP_SECRET=${LOGTO_APP_SECRET}
|
||||||
- LOGTO_COOKIE_SECRET=${LOGTO_COOKIE_SECRET}
|
- LOGTO_COOKIE_SECRET=${LOGTO_COOKIE_SECRET}
|
||||||
- LOGTO_BASE_URL=${LOGTO_BASE_URL}
|
- LOGTO_BASE_URL=${LOGTO_BASE_URL}
|
||||||
- LOGTO_ENABLE_DEV=${LOGTO_ENABLE_DEV:-false}
|
- LOGTO_ENABLE=${LOGTO_ENABLE:-false}
|
||||||
- USAGE_LOG_FILE=true
|
- USAGE_LOG_FILE=true
|
||||||
- STORAGE_DIR=/app/storage
|
- STORAGE_DIR=/app/storage
|
||||||
- MAX_UPLOAD_SIZE_MB=${MAX_UPLOAD_SIZE_MB:-5}
|
- MAX_UPLOAD_SIZE_MB=${MAX_UPLOAD_SIZE_MB:-5}
|
||||||
|
|||||||
@@ -8,41 +8,23 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- OPERATING_ENV=${OPERATING_ENV:-production}
|
- OPERATING_ENV=${OPERATING_ENV:-production}
|
||||||
- NODE_ENV=${NODE_ENV:-production}
|
- NODE_ENV=${NODE_ENV:-production}
|
||||||
- GROQ_API_KEY=${GROQ_API_KEY}
|
|
||||||
- HuggingFace_API_KEY=${HuggingFace_API_KEY}
|
|
||||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
||||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
|
||||||
- OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY}
|
|
||||||
- GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY}
|
|
||||||
- OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL}
|
|
||||||
- OPENAI_LIKE_API_BASE_URL=${OPENAI_LIKE_API_BASE_URL}
|
|
||||||
- TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL}
|
|
||||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
|
||||||
- OPENAI_LIKE_API_KEY=${OPENAI_LIKE_API_KEY}
|
|
||||||
- TOGETHER_API_KEY=${TOGETHER_API_KEY}
|
|
||||||
- HYPERBOLIC_API_KEY=${HYPERBOLIC_API_KEY}
|
|
||||||
- HYPERBOLIC_API_BASE_URL=${HYPERBOLIC_API_BASE_URL}
|
|
||||||
- MISTRAL_API_KEY=${MISTRAL_API_KEY}
|
|
||||||
- COHERE_API_KEY=${COHERE_API_KEY}
|
|
||||||
- LMSTUDIO_API_BASE_URL=${LMSTUDIO_API_BASE_URL}
|
|
||||||
- XAI_API_KEY=${XAI_API_KEY}
|
|
||||||
- PERPLEXITY_API_KEY=${PERPLEXITY_API_KEY}
|
|
||||||
- AWS_BEDROCK_CONFIG=${AWS_BEDROCK_CONFIG}
|
|
||||||
- LOG_LEVEL=${LOG_LEVEL:-debug}
|
- LOG_LEVEL=${LOG_LEVEL:-debug}
|
||||||
- DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768}
|
- DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768}
|
||||||
- SERPER_API_KEY=${SERPER_API_KEY}
|
- LLM_PROVIDER=${LLM_DEFAULT_PROVIDER}
|
||||||
- WEATHER_API_KEY=${WEATHER_API_KEY}
|
- PROVIDER_BASE_URL=${PROVIDER_BASE_URL}
|
||||||
- LLM_DEFAULT_PROVIDER=${LLM_DEFAULT_PROVIDER}
|
- PROVIDER_API_KEY=${PROVIDER_API_KEY}
|
||||||
- LLM_DEFAULT_MODEL=${LLM_DEFAULT_MODEL}
|
- LLM_DEFAULT_MODEL=${LLM_DEFAULT_MODEL}
|
||||||
- LLM_MINOR_MODEL=${LLM_MINOR_MODEL}
|
- LLM_MINOR_MODEL=${LLM_MINOR_MODEL}
|
||||||
- LLM_ENABLED_PROVIDERS=${LLM_ENABLED_PROVIDERS}
|
- SERPER_API_KEY=${SERPER_API_KEY}
|
||||||
|
- WEATHER_API_KEY=${WEATHER_API_KEY}
|
||||||
- LOGTO_ENDPOINT=${LOGTO_ENDPOINT}
|
- LOGTO_ENDPOINT=${LOGTO_ENDPOINT}
|
||||||
- LOGTO_APP_ID=${LOGTO_APP_ID}
|
- LOGTO_APP_ID=${LOGTO_APP_ID}
|
||||||
- LOGTO_APP_SECRET=${LOGTO_APP_SECRET}
|
- LOGTO_APP_SECRET=${LOGTO_APP_SECRET}
|
||||||
- LOGTO_COOKIE_SECRET=${LOGTO_COOKIE_SECRET}
|
- LOGTO_COOKIE_SECRET=${LOGTO_COOKIE_SECRET}
|
||||||
- LOGTO_BASE_URL=${LOGTO_BASE_URL}
|
- LOGTO_BASE_URL=${LOGTO_BASE_URL}
|
||||||
- LOGTO_ENABLE_DEV=${LOGTO_ENABLE_DEV:-false}
|
- LOGTO_ENABLE=${LOGTO_ENABLE:-false}
|
||||||
- USAGE_LOG_FILE=${USAGE_LOG_FILE:-true}
|
- USAGE_LOG_FILE=true
|
||||||
|
- STORAGE_DIR=/app/storage
|
||||||
- MAX_UPLOAD_SIZE_MB=${MAX_UPLOAD_SIZE_MB:-5}
|
- MAX_UPLOAD_SIZE_MB=${MAX_UPLOAD_SIZE_MB:-5}
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# 简介
|
|
||||||
|
|
||||||
欢迎阅读 UPage 文档。UPage 是一个基于人工智能的可视化网页构建平台,支持多种 AI 提供商集成,能够轻松创建和定制网页内容。
|
|
||||||
|
|
||||||
## 目录
|
|
||||||
|
|
||||||
- [简介](#简介)
|
|
||||||
- [目录](#目录)
|
|
||||||
- [快速开始](#快速开始)
|
|
||||||
- [部署指南](#部署指南)
|
|
||||||
- [常见问题](#常见问题)
|
|
||||||
- [贡献指南](#贡献指南)
|
|
||||||
- [开发指南](#开发指南)
|
|
||||||
- [更新日志](#更新日志)
|
|
||||||
Reference in New Issue
Block a user