mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
Add openai o-series support (#1238)
This commit is contained in:
parent
7d4f0becd4
commit
a596ffc313
11 changed files with 188 additions and 96 deletions
85
package-lock.json
generated
85
package-lock.json
generated
|
|
@ -18,7 +18,7 @@
|
|||
"@langchain/core": "^0.3.27",
|
||||
"@langchain/google-genai": "^0.1.6",
|
||||
"@langchain/groq": "^0.1.2",
|
||||
"@langchain/openai": "^0.3.14",
|
||||
"@langchain/openai": "^0.4.2",
|
||||
"@orama/orama": "^3.0.0-rc-2",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.2",
|
||||
|
|
@ -4257,6 +4257,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/community/node_modules/@langchain/openai": {
|
||||
"version": "0.3.17",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.17.tgz",
|
||||
"integrity": "sha512-uw4po32OKptVjq+CYHrumgbfh4NuD7LqyE+ZgqY9I/LrLc6bHLMc+sisHmI17vgek0K/yqtarI0alPJbzrwyag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"openai": "^4.77.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": ">=0.3.29 <0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/community/node_modules/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
|
|
@ -4270,16 +4288,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/core": {
|
||||
"version": "0.3.27",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.27.tgz",
|
||||
"integrity": "sha512-jtJKbJWB1NPU1YvtrExOB2rumvUFgkJwlWGxyjSIV9A6zcLVmUbcZGV8fCSuXgl5bbzOIQLJ1xcLYQmbW9TkTg==",
|
||||
"version": "0.3.39",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.39.tgz",
|
||||
"integrity": "sha512-muXs4asy1A7qDtcdznxqyBfxf4N6qxofY/S0c95vbsWa0r9YAE2PttHIjcuxSy1q2jUiTkpCcgFEjNJRQRVhEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cfworker/json-schema": "^4.0.2",
|
||||
"ansi-styles": "^5.0.0",
|
||||
"camelcase": "6",
|
||||
"decamelize": "1.2.0",
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"langsmith": "^0.2.8",
|
||||
"langsmith": ">=0.2.8 <0.4.0",
|
||||
"mustache": "^4.2.0",
|
||||
"p-queue": "^6.6.2",
|
||||
"p-retry": "4",
|
||||
|
|
@ -4357,6 +4376,24 @@
|
|||
"@langchain/core": ">=0.2.21 <0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/groq/node_modules/@langchain/openai": {
|
||||
"version": "0.3.17",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.17.tgz",
|
||||
"integrity": "sha512-uw4po32OKptVjq+CYHrumgbfh4NuD7LqyE+ZgqY9I/LrLc6bHLMc+sisHmI17vgek0K/yqtarI0alPJbzrwyag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"openai": "^4.77.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": ">=0.3.29 <0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/ollama": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.1.1.tgz",
|
||||
|
|
@ -4387,13 +4424,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@langchain/openai": {
|
||||
"version": "0.3.14",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.14.tgz",
|
||||
"integrity": "sha512-lNWjUo1tbvsss45IF7UQtMu1NJ6oUKvhgPYWXnX9f/d6OmuLu7D99HQ3Y88vLcUo9XjjOy417olYHignMduMjA==",
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.4.2.tgz",
|
||||
"integrity": "sha512-Cuj7qbVcycALTP0aqZuPpEc7As8cwiGaU21MhXRyZFs+dnWxKYxZ1Q1z4kcx6cYkq/I+CNwwmk+sP+YruU73Aw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"openai": "^4.71.0",
|
||||
"openai": "^4.77.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
},
|
||||
|
|
@ -4401,7 +4438,7 @@
|
|||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": ">=0.2.26 <0.4.0"
|
||||
"@langchain/core": ">=0.3.29 <0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/textsplitters": {
|
||||
|
|
@ -14792,6 +14829,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/langchain/node_modules/@langchain/openai": {
|
||||
"version": "0.3.17",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.17.tgz",
|
||||
"integrity": "sha512-uw4po32OKptVjq+CYHrumgbfh4NuD7LqyE+ZgqY9I/LrLc6bHLMc+sisHmI17vgek0K/yqtarI0alPJbzrwyag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"openai": "^4.77.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": ">=0.3.29 <0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/langchain/node_modules/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
|
|
@ -17036,9 +17091,9 @@
|
|||
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ=="
|
||||
},
|
||||
"node_modules/openai": {
|
||||
"version": "4.73.1",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-4.73.1.tgz",
|
||||
"integrity": "sha512-nWImDJBcUsqrhy7yJScXB4+iqjzbUEgzfA3un/6UnHFdwWhjX24oztj69Ped/njABfOdLcO/F7CeWTI5dt8Xmg==",
|
||||
"version": "4.83.0",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-4.83.0.tgz",
|
||||
"integrity": "sha512-fmTsqud0uTtRKsPC7L8Lu55dkaTwYucqncDHzVvO64DKOpNTuiYwjbR/nVgpapXuYy8xSnhQQPUm+3jQaxICgw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
|
|
@ -17053,9 +17108,13 @@
|
|||
"openai": "bin/cli"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ws": {
|
||||
"optional": true
|
||||
},
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
"@langchain/core": "^0.3.27",
|
||||
"@langchain/google-genai": "^0.1.6",
|
||||
"@langchain/groq": "^0.1.2",
|
||||
"@langchain/openai": "^0.3.14",
|
||||
"@langchain/openai": "^0.4.2",
|
||||
"@orama/orama": "^3.0.0-rc-2",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.2",
|
||||
|
|
|
|||
|
|
@ -7,23 +7,19 @@ import {
|
|||
subscribeToModelKeyChange,
|
||||
} from "@/aiParams";
|
||||
import ChainFactory, { ChainType, Document } from "@/chainFactory";
|
||||
import {
|
||||
AI_SENDER,
|
||||
BUILTIN_CHAT_MODELS,
|
||||
USER_SENDER,
|
||||
VAULT_VECTOR_STORE_STRATEGY,
|
||||
} from "@/constants";
|
||||
import { BUILTIN_CHAT_MODELS, USER_SENDER, VAULT_VECTOR_STORE_STRATEGY } from "@/constants";
|
||||
import {
|
||||
ChainRunner,
|
||||
CopilotPlusChainRunner,
|
||||
LLMChainRunner,
|
||||
VaultQAChainRunner,
|
||||
} from "@/LLMProviders/chainRunner";
|
||||
import { logError, logInfo } from "@/logger";
|
||||
import { HybridRetriever } from "@/search/hybridRetriever";
|
||||
import VectorStoreManager from "@/search/vectorStoreManager";
|
||||
import { getSettings, getSystemPrompt, subscribeToSettingsChange } from "@/settings/model";
|
||||
import { ChatMessage } from "@/sharedState";
|
||||
import { findCustomModel, isSupportedChain } from "@/utils";
|
||||
import { findCustomModel, isOSeriesModel, isSupportedChain } from "@/utils";
|
||||
import {
|
||||
ChatPromptTemplate,
|
||||
HumanMessagePromptTemplate,
|
||||
|
|
@ -34,7 +30,6 @@ import { App, Notice } from "obsidian";
|
|||
import ChatModelManager from "./chatModelManager";
|
||||
import MemoryManager from "./memoryManager";
|
||||
import PromptManager from "./promptManager";
|
||||
import { logError, logInfo } from "@/logger";
|
||||
|
||||
export default class ChainManager {
|
||||
private static chain: RunnableSequence;
|
||||
|
|
@ -247,21 +242,19 @@ export default class ChainManager {
|
|||
this.validateChainInitialization();
|
||||
|
||||
const chatModel = this.chatModelManager.getChatModel();
|
||||
const modelName = (chatModel as any).modelName || (chatModel as any).model || "";
|
||||
const isO1Model = modelName.startsWith("o1");
|
||||
|
||||
// Handle ignoreSystemMessage
|
||||
if (ignoreSystemMessage || isO1Model) {
|
||||
if (ignoreSystemMessage || isOSeriesModel(chatModel)) {
|
||||
let effectivePrompt = ChatPromptTemplate.fromMessages([
|
||||
new MessagesPlaceholder("history"),
|
||||
HumanMessagePromptTemplate.fromTemplate("{input}"),
|
||||
]);
|
||||
|
||||
// TODO: hack for o1 models, to be removed when they support system prompt
|
||||
if (isO1Model) {
|
||||
// Temporary fix:for o1-xx model need to covert systemMessage to aiMessage
|
||||
// TODO: hack for o-series models, to be removed when langchainjs supports system prompt
|
||||
// https://github.com/langchain-ai/langchain/issues/28895
|
||||
if (isOSeriesModel(chatModel)) {
|
||||
effectivePrompt = ChatPromptTemplate.fromMessages([
|
||||
[AI_SENDER, getSystemPrompt() || ""],
|
||||
[USER_SENDER, getSystemPrompt() || ""],
|
||||
effectivePrompt,
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
extractYoutubeUrl,
|
||||
formatDateTime,
|
||||
getApiErrorMessage,
|
||||
getMessageRole,
|
||||
ImageContent,
|
||||
ImageProcessor,
|
||||
MessageContent,
|
||||
|
|
@ -357,10 +358,13 @@ class CopilotPlusChainRunner extends BaseChainRunner {
|
|||
"\n\nThe following is the relevant conversation history. Use this context to maintain consistency in your responses:";
|
||||
}
|
||||
|
||||
// Add the combined system message
|
||||
// Get chat model for role determination for O-series models
|
||||
const chatModel = this.chainManager.chatModelManager.getChatModel();
|
||||
|
||||
// Add the combined system message with appropriate role
|
||||
if (fullSystemMessage) {
|
||||
messages.push({
|
||||
role: "system",
|
||||
role: getMessageRole(chatModel),
|
||||
content: `${fullSystemMessage}\nIMPORTANT: Maintain consistency with previous responses in the conversation. If you've provided information about a person or topic before, use that same information in follow-up questions.`,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { CustomModel, getModelKey, ModelConfig, setModelKey } from "@/aiParams";
|
|||
import { BREVILABS_API_BASE_URL, BUILTIN_CHAT_MODELS, ChatModelProviders } from "@/constants";
|
||||
import { getDecryptedKey } from "@/encryptionService";
|
||||
import { getModelKeyFromModel, getSettings, subscribeToSettingsChange } from "@/settings/model";
|
||||
import { err2String, safeFetch } from "@/utils";
|
||||
import { err2String, isOSeriesModel, safeFetch } from "@/utils";
|
||||
import { HarmBlockThreshold, HarmCategory } from "@google/generative-ai";
|
||||
import { ChatAnthropic } from "@langchain/anthropic";
|
||||
import { ChatCohere } from "@langchain/cohere";
|
||||
|
|
@ -75,13 +75,11 @@ export default class ChatModelManager {
|
|||
private async getModelConfig(customModel: CustomModel): Promise<ModelConfig> {
|
||||
const settings = getSettings();
|
||||
|
||||
// Check if the model starts with "o1"
|
||||
const modelName = customModel.name;
|
||||
const isO1Model = modelName.startsWith("o1");
|
||||
const baseConfig: ModelConfig = {
|
||||
const isOSeries = isOSeriesModel(modelName);
|
||||
const baseConfig: Omit<ModelConfig, "maxTokens" | "maxCompletionTokens"> = {
|
||||
modelName: modelName,
|
||||
temperature: customModel.temperature ?? settings.temperature,
|
||||
maxTokens: customModel.maxTokens ?? settings.maxTokens,
|
||||
streaming: customModel.stream ?? true,
|
||||
maxRetries: 3,
|
||||
maxConcurrency: 3,
|
||||
|
|
@ -97,10 +95,9 @@ export default class ChatModelManager {
|
|||
configuration: {
|
||||
baseURL: customModel.baseUrl,
|
||||
fetch: customModel.enableCors ? safeFetch : undefined,
|
||||
organization: await getDecryptedKey(customModel.openAIOrgId || settings.openAIOrgId),
|
||||
},
|
||||
// @ts-ignore
|
||||
openAIOrgId: getDecryptedKey(customModel.openAIOrgId || settings.openAIOrgId),
|
||||
...this.handleOpenAIExtraArgs(isO1Model, settings.maxTokens, settings.temperature),
|
||||
...this.handleOpenAIExtraArgs(isOSeries, settings.maxTokens, settings.temperature),
|
||||
},
|
||||
[ChatModelProviders.ANTHROPIC]: {
|
||||
anthropicApiKey: await getDecryptedKey(customModel.apiKey || settings.anthropicApiKey),
|
||||
|
|
@ -113,17 +110,18 @@ export default class ChatModelManager {
|
|||
},
|
||||
},
|
||||
[ChatModelProviders.AZURE_OPENAI]: {
|
||||
azureOpenAIApiKey: await getDecryptedKey(customModel.apiKey || settings.azureOpenAIApiKey),
|
||||
azureOpenAIApiInstanceName:
|
||||
customModel.azureOpenAIApiInstanceName || settings.azureOpenAIApiInstanceName,
|
||||
azureOpenAIApiDeploymentName:
|
||||
customModel.azureOpenAIApiDeploymentName || settings.azureOpenAIApiDeploymentName,
|
||||
azureOpenAIApiVersion: customModel.azureOpenAIApiVersion || settings.azureOpenAIApiVersion,
|
||||
modelName: modelName,
|
||||
openAIApiKey: await getDecryptedKey(customModel.apiKey || settings.azureOpenAIApiKey),
|
||||
configuration: {
|
||||
baseURL: customModel.baseUrl,
|
||||
baseURL:
|
||||
customModel.baseUrl ||
|
||||
`https://${customModel.azureOpenAIApiInstanceName || settings.azureOpenAIApiInstanceName}.openai.azure.com/openai/deployments/${customModel.azureOpenAIApiDeploymentName || settings.azureOpenAIApiDeploymentName}`,
|
||||
defaultQuery: {
|
||||
"api-version": customModel.azureOpenAIApiVersion || settings.azureOpenAIApiVersion,
|
||||
},
|
||||
fetch: customModel.enableCors ? safeFetch : undefined,
|
||||
},
|
||||
...this.handleOpenAIExtraArgs(isO1Model, settings.maxTokens, settings.temperature),
|
||||
...this.handleOpenAIExtraArgs(isOSeries, settings.maxTokens, settings.temperature),
|
||||
},
|
||||
[ChatModelProviders.COHEREAI]: {
|
||||
apiKey: await getDecryptedKey(customModel.apiKey || settings.cohereApiKey),
|
||||
|
|
@ -186,9 +184,9 @@ export default class ChatModelManager {
|
|||
configuration: {
|
||||
baseURL: customModel.baseUrl,
|
||||
fetch: customModel.enableCors ? safeFetch : undefined,
|
||||
dangerouslyAllowBrowser: true,
|
||||
defaultHeaders: { "dangerously-allow-browser": "true" },
|
||||
},
|
||||
...this.handleOpenAIExtraArgs(isO1Model, settings.maxTokens, settings.temperature),
|
||||
...this.handleOpenAIExtraArgs(isOSeries, settings.maxTokens, settings.temperature),
|
||||
},
|
||||
[ChatModelProviders.COPILOT_PLUS]: {
|
||||
modelName: modelName,
|
||||
|
|
@ -203,11 +201,22 @@ export default class ChatModelManager {
|
|||
const selectedProviderConfig =
|
||||
providerConfig[customModel.provider as keyof typeof providerConfig] || {};
|
||||
|
||||
return { ...baseConfig, ...selectedProviderConfig };
|
||||
// Add token configuration separately to ensure they don't conflict
|
||||
const tokenConfig = this.handleOpenAIExtraArgs(
|
||||
isOSeries,
|
||||
customModel.maxTokens ?? settings.maxTokens,
|
||||
customModel.temperature ?? settings.temperature
|
||||
);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
...selectedProviderConfig,
|
||||
...tokenConfig,
|
||||
};
|
||||
}
|
||||
|
||||
private handleOpenAIExtraArgs(isO1Model: boolean, maxTokens: number, temperature: number) {
|
||||
return isO1Model
|
||||
private handleOpenAIExtraArgs(isOSeriesModel: boolean, maxTokens: number, temperature: number) {
|
||||
const config = isOSeriesModel
|
||||
? {
|
||||
maxCompletionTokens: maxTokens,
|
||||
temperature: 1,
|
||||
|
|
@ -216,6 +225,7 @@ export default class ChatModelManager {
|
|||
maxTokens: maxTokens,
|
||||
temperature: temperature,
|
||||
};
|
||||
return config;
|
||||
}
|
||||
|
||||
// Build a map of modelKey to model config
|
||||
|
|
@ -327,10 +337,14 @@ export default class ChatModelManager {
|
|||
const modelToTest = { ...model, enableCors };
|
||||
const modelConfig = await this.getModelConfig(modelToTest);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { streaming, temperature, ...pingConfig } = modelConfig;
|
||||
pingConfig.maxTokens = 10;
|
||||
const { streaming, maxTokens, maxCompletionTokens, ...pingConfig } = modelConfig;
|
||||
const isOSeries = isOSeriesModel(modelToTest.name);
|
||||
const tokenConfig = this.handleOpenAIExtraArgs(isOSeries, 10, modelConfig.temperature);
|
||||
|
||||
const testModel = new (this.getProviderConstructor(modelToTest))(pingConfig);
|
||||
const testModel = new (this.getProviderConstructor(modelToTest))({
|
||||
...pingConfig,
|
||||
...tokenConfig,
|
||||
});
|
||||
await testModel.invoke([{ role: "user", content: "hello" }], {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export default class EmbeddingManager {
|
|||
},
|
||||
[EmbeddingModelProviders.OPENAI]: {
|
||||
modelName,
|
||||
openAIApiKey: await getDecryptedKey(customModel.apiKey || settings.openAIApiKey),
|
||||
apiKey: await getDecryptedKey(customModel.apiKey || settings.openAIApiKey),
|
||||
timeout: 10000,
|
||||
configuration: {
|
||||
baseURL: customModel.baseUrl,
|
||||
|
|
@ -224,15 +224,15 @@ export default class EmbeddingManager {
|
|||
apiKey: await getDecryptedKey(settings.googleApiKey),
|
||||
},
|
||||
[EmbeddingModelProviders.AZURE_OPENAI]: {
|
||||
azureOpenAIApiKey: await getDecryptedKey(customModel.apiKey || settings.azureOpenAIApiKey),
|
||||
azureOpenAIApiInstanceName:
|
||||
customModel.azureOpenAIApiInstanceName || settings.azureOpenAIApiInstanceName,
|
||||
azureOpenAIApiDeploymentName:
|
||||
customModel.azureOpenAIApiEmbeddingDeploymentName ||
|
||||
settings.azureOpenAIApiEmbeddingDeploymentName,
|
||||
azureOpenAIApiVersion: customModel.azureOpenAIApiVersion || settings.azureOpenAIApiVersion,
|
||||
modelName,
|
||||
openAIApiKey: await getDecryptedKey(customModel.apiKey || settings.azureOpenAIApiKey),
|
||||
configuration: {
|
||||
baseURL: customModel.baseUrl,
|
||||
baseURL:
|
||||
customModel.baseUrl ||
|
||||
`https://${customModel.azureOpenAIApiInstanceName || settings.azureOpenAIApiInstanceName}.openai.azure.com/openai/deployments/${customModel.azureOpenAIApiEmbeddingDeploymentName || settings.azureOpenAIApiEmbeddingDeploymentName}`,
|
||||
defaultQuery: {
|
||||
"api-version": customModel.azureOpenAIApiVersion || settings.azureOpenAIApiVersion,
|
||||
},
|
||||
fetch: customModel.enableCors ? safeFetch : undefined,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export interface ModelConfig {
|
|||
maxRetries: number;
|
||||
maxConcurrency: number;
|
||||
maxTokens?: number;
|
||||
maxCompletionTokens?: number;
|
||||
openAIApiKey?: string;
|
||||
openAIOrgId?: string;
|
||||
anthropicApiKey?: string;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export async function getStandaloneQuestion(
|
|||
const response = await ChatModelManager.getInstance()
|
||||
.getChatModel()
|
||||
.invoke([
|
||||
{ role: "system", content: condenseQuestionTemplate },
|
||||
{
|
||||
role: "user",
|
||||
content: condenseQuestionTemplate
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ export enum ChatModels {
|
|||
COPILOT_PLUS_FLASH = "copilot-plus-flash",
|
||||
GPT_4o = "gpt-4o",
|
||||
GPT_4o_mini = "gpt-4o-mini",
|
||||
GPT_4_TURBO = "gpt-4-turbo",
|
||||
O1_mini = "o1-mini",
|
||||
O3_mini = "o3-mini",
|
||||
GEMINI_PRO = "gemini-1.5-pro",
|
||||
GEMINI_FLASH = "gemini-1.5-flash",
|
||||
AZURE_OPENAI = "azure-openai",
|
||||
|
|
@ -93,7 +94,13 @@ export const BUILTIN_CHAT_MODELS: CustomModel[] = [
|
|||
core: true,
|
||||
},
|
||||
{
|
||||
name: ChatModels.GPT_4_TURBO,
|
||||
name: ChatModels.O1_mini,
|
||||
provider: ChatModelProviders.OPENAI,
|
||||
enabled: true,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
name: ChatModels.O3_mini,
|
||||
provider: ChatModelProviders.OPENAI,
|
||||
enabled: true,
|
||||
isBuiltIn: true,
|
||||
|
|
@ -147,15 +154,12 @@ export enum EmbeddingModelProviders {
|
|||
OPENAI = "openai",
|
||||
COHEREAI = "cohereai",
|
||||
GOOGLE = "google",
|
||||
// AZURE_OPENAI = "azure_openai",
|
||||
AZURE_OPENAI = "azure openai",
|
||||
OLLAMA = "ollama",
|
||||
LM_STUDIO = "lm-studio",
|
||||
OPENAI_FORMAT = "3rd party (openai-format)",
|
||||
COPILOT_PLUS = "copilot-plus",
|
||||
COPILOT_PLUS_JINA = "copilot-plus-jina",
|
||||
// HUGGINGFACE = "huggingface",
|
||||
// VOYAGEAI = "voyageai",
|
||||
}
|
||||
|
||||
export enum EmbeddingModels {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,24 @@
|
|||
import React, { useState } from "react";
|
||||
import { useTab } from "@/contexts/TabContext";
|
||||
import { getSettings } from "@/settings/model";
|
||||
import { CustomModel } from "@/aiParams";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { PasswordInput } from "@/components/ui/password-input";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {
|
||||
ChatModelProviders,
|
||||
DisplayKeyProviders,
|
||||
|
|
@ -9,30 +27,12 @@ import {
|
|||
ProviderMetadata,
|
||||
ProviderSettingsKeyMap,
|
||||
} from "@/constants";
|
||||
import { CustomModel } from "@/aiParams";
|
||||
import { useTab } from "@/contexts/TabContext";
|
||||
import { getSettings } from "@/settings/model";
|
||||
import { err2String, getProviderInfo, getProviderLabel, omit } from "@/utils";
|
||||
import { Notice } from "obsidian";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ChevronDown, Loader2 } from "lucide-react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { PasswordInput } from "@/components/ui/password-input";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Notice } from "obsidian";
|
||||
import React, { useState } from "react";
|
||||
|
||||
interface FormFieldProps {
|
||||
label: string;
|
||||
|
|
@ -426,7 +426,7 @@ export const ModelAddDialog: React.FC<ModelAddDialogProps> = ({
|
|||
{Object.values(
|
||||
isEmbeddingModel
|
||||
? omit(EmbeddingModelProviders, ["COPILOT_PLUS", "COPILOT_PLUS_JINA"])
|
||||
: ChatModelProviders
|
||||
: omit(ChatModelProviders, ["COPILOT_PLUS"])
|
||||
).map((provider) => (
|
||||
<SelectItem key={provider} value={provider}>
|
||||
{getProviderLabel(provider)}
|
||||
|
|
|
|||
18
src/utils.ts
18
src/utils.ts
|
|
@ -7,6 +7,7 @@ import {
|
|||
USER_SENDER,
|
||||
} from "@/constants";
|
||||
import { ChatMessage } from "@/sharedState";
|
||||
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
||||
import { MemoryVariables } from "@langchain/core/memory";
|
||||
import { RunnableSequence } from "@langchain/core/runnables";
|
||||
import { BaseChain, RetrievalQAChain } from "langchain/chains";
|
||||
|
|
@ -867,3 +868,20 @@ export async function checkLatestVersion(): Promise<{
|
|||
return { version: null, error: errorMessage };
|
||||
}
|
||||
}
|
||||
|
||||
export function isOSeriesModel(model: BaseChatModel | string): boolean {
|
||||
if (typeof model === "string") {
|
||||
return model.startsWith("o1") || model.startsWith("o3");
|
||||
}
|
||||
|
||||
// For BaseChatModel instances
|
||||
const modelName = (model as any).modelName || (model as any).model || "";
|
||||
return modelName.startsWith("o1") || modelName.startsWith("o3");
|
||||
}
|
||||
|
||||
export function getMessageRole(
|
||||
model: BaseChatModel | string,
|
||||
defaultRole: "system" | "human" = "system"
|
||||
): "system" | "human" {
|
||||
return isOSeriesModel(model) ? "human" : defaultRole;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue