Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ refactor: improve model fetch behavior #6055

Merged
merged 10 commits into from
Feb 14, 2025
9 changes: 9 additions & 0 deletions src/config/aiModels/spark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const sparkChatModels: AIChatModelCard[] = [
type: 'chat',
},
{
abilities: {
functionCall: true,
},
contextWindowTokens: 8192,
description:
'Spark Max 为功能最为全面的版本,支持联网搜索及众多内置插件。其全面优化的核心能力以及系统角色设定和函数调用功能,使其在各种复杂应用场景中的表现极为优异和出色。',
Expand All @@ -42,6 +45,9 @@ const sparkChatModels: AIChatModelCard[] = [
type: 'chat',
},
{
abilities: {
functionCall: true,
},
contextWindowTokens: 32_768,
description:
'Spark Max 32K 配置了大上下文处理能力,更强的上下文理解和逻辑推理能力,支持32K tokens的文本输入,适用于长文档阅读、私有知识问答等场景',
Expand All @@ -52,6 +58,9 @@ const sparkChatModels: AIChatModelCard[] = [
type: 'chat',
},
{
abilities: {
functionCall: true,
},
contextWindowTokens: 8192,
description:
'Spark Ultra 是星火大模型系列中最为强大的版本,在升级联网搜索链路同时,提升对文本内容的理解和总结能力。它是用于提升办公生产力和准确响应需求的全方位解决方案,是引领行业的智能产品。',
Expand Down
58 changes: 37 additions & 21 deletions src/libs/agent-runtime/ai360/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ModelProvider } from '../types';
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import type { ChatModelCard } from '@/types/llm';

export interface Ai360ModelCard {
id: string;
Expand All @@ -22,28 +22,44 @@ export const LobeAi360AI = LobeOpenAICompatibleFactory({
debug: {
chatCompletion: () => process.env.DEBUG_AI360_CHAT_COMPLETION === '1',
},
models: {
transformModel: (m) => {
const reasoningKeywords = [
'360gpt2-o1',
'360zhinao2-o1',
];
models: async ({ client }) => {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

const model = m as unknown as Ai360ModelCard;
const reasoningKeywords = [
'360gpt2-o1',
'360zhinao2-o1',
];

return {
contextWindowTokens: model.total_tokens,
displayName: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.displayName ?? undefined,
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.enabled || false,
functionCall: model.id === '360gpt-pro',
id: model.id,
maxTokens:
typeof model.max_tokens === 'number'
? model.max_tokens
: undefined,
reasoning: reasoningKeywords.some(keyword => model.id.toLowerCase().includes(keyword)),
};
},
const modelsPage = await client.models.list() as any;
const modelList: Ai360ModelCard[] = modelsPage.data;

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.id.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: model.total_tokens,
displayName: knownModel?.displayName ?? undefined,
enabled: knownModel?.enabled || false,
functionCall:
model.id === '360gpt-pro'
|| knownModel?.abilities?.functionCall
|| false,
id: model.id,
maxTokens:
typeof model.max_tokens === 'number'
? model.max_tokens
: undefined,
reasoning:
reasoningKeywords.some(keyword => model.id.toLowerCase().includes(keyword))
|| knownModel?.abilities?.reasoning
|| false,
vision:
knownModel?.abilities?.vision
|| false,
};
})
.filter(Boolean) as ChatModelCard[];
},
provider: ModelProvider.Ai360,
});
22 changes: 17 additions & 5 deletions src/libs/agent-runtime/anthropic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { buildAnthropicMessages, buildAnthropicTools } from '../utils/anthropicH
import { StreamingResponse } from '../utils/response';
import { AnthropicStream } from '../utils/streams';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import type { ChatModelCard } from '@/types/llm';

export interface AnthropicModelCard {
Expand Down Expand Up @@ -114,6 +113,8 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
}

async models() {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

const url = `${this.baseURL}/v1/models`;
const response = await fetch(url, {
headers: {
Expand All @@ -128,13 +129,24 @@ export class LobeAnthropicAI implements LobeRuntimeAI {

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.id.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.contextWindowTokens ?? undefined,
contextWindowTokens: knownModel?.contextWindowTokens ?? undefined,
displayName: model.display_name,
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.enabled || false,
functionCall: model.id.toLowerCase().includes('claude-3'),
enabled: knownModel?.enabled || false,
functionCall:
model.id.toLowerCase().includes('claude-3')
|| knownModel?.abilities?.functionCall
|| false,
id: model.id,
vision: model.id.toLowerCase().includes('claude-3') && !model.id.toLowerCase().includes('claude-3-5-haiku'),
reasoning:
knownModel?.abilities?.reasoning
|| false,
vision:
model.id.toLowerCase().includes('claude-3') && !model.id.toLowerCase().includes('claude-3-5-haiku')
|| knownModel?.abilities?.vision
|| false,
};
})
.filter(Boolean) as ChatModelCard[];
Expand Down
13 changes: 11 additions & 2 deletions src/libs/agent-runtime/baichuan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import OpenAI from 'openai';
import { ChatStreamPayload, ModelProvider } from '../types';
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import type { ChatModelCard } from '@/types/llm';

export interface BaichuanModelCard {
Expand Down Expand Up @@ -32,18 +31,28 @@ export const LobeBaichuanAI = LobeOpenAICompatibleFactory({
chatCompletion: () => process.env.DEBUG_BAICHUAN_CHAT_COMPLETION === '1',
},
models: async ({ client }) => {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

const modelsPage = await client.models.list() as any;
const modelList: BaichuanModelCard[] = modelsPage.data;

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.model.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: model.max_input_length,
displayName: model.model_show_name,
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.model === m.id)?.enabled || false,
enabled: knownModel?.enabled || false,
functionCall: model.function_call,
id: model.model,
maxTokens: model.max_tokens,
reasoning:
knownModel?.abilities?.reasoning
|| false,
vision:
knownModel?.abilities?.vision
|| false,
};
})
.filter(Boolean) as ChatModelCard[];
Expand Down
29 changes: 22 additions & 7 deletions src/libs/agent-runtime/cloudflare/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { debugStream } from '../utils/debugStream';
import { StreamingResponse } from '../utils/response';
import { createCallbacksTransformer } from '../utils/streams';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import { ChatModelCard } from '@/types/llm';

export interface CloudflareModelCard {
Expand Down Expand Up @@ -113,6 +112,8 @@ export class LobeCloudflareAI implements LobeRuntimeAI {
}

async models(): Promise<ChatModelCard[]> {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

const url = `${DEFAULT_BASE_URL_PREFIX}/client/v4/accounts/${this.accountID}/ai/models/search`;
const response = await fetch(url, {
headers: {
Expand All @@ -127,16 +128,30 @@ export class LobeCloudflareAI implements LobeRuntimeAI {

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.name.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: model.properties?.max_total_tokens
? Number(model.properties.max_total_tokens)
: LOBE_DEFAULT_MODEL_LIST.find((m) => model.name === m.id)?.contextWindowTokens ?? undefined,
displayName: LOBE_DEFAULT_MODEL_LIST.find((m) => model.name === m.id)?.displayName ?? (model.properties?.["beta"] === "true" ? `${model.name} (Beta)` : undefined),
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.name === m.id)?.enabled || false,
functionCall: model.description.toLowerCase().includes('function call') || model.properties?.["function_calling"] === "true",
: knownModel?.contextWindowTokens ?? undefined,
displayName: knownModel?.displayName ?? (model.properties?.["beta"] === "true" ? `${model.name} (Beta)` : undefined),
enabled: knownModel?.enabled || false,
functionCall:
model.description.toLowerCase().includes('function call')
|| model.properties?.["function_calling"] === "true"
|| knownModel?.abilities?.functionCall
|| false,
id: model.name,
reasoning: model.name.toLowerCase().includes('deepseek-r1'),
vision: model.name.toLowerCase().includes('vision') || model.task?.name.toLowerCase().includes('image-to-text') || model.description.toLowerCase().includes('vision'),
reasoning:
model.name.toLowerCase().includes('deepseek-r1')
|| knownModel?.abilities?.reasoning
|| false,
vision:
model.name.toLowerCase().includes('vision')
|| model.task?.name.toLowerCase().includes('image-to-text')
|| model.description.toLowerCase().includes('vision')
|| knownModel?.abilities?.vision
|| false,
};
})
.filter(Boolean) as ChatModelCard[];
Expand Down
42 changes: 29 additions & 13 deletions src/libs/agent-runtime/deepseek/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import OpenAI from 'openai';
import { ChatStreamPayload, ModelProvider } from '../types';
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import type { ChatModelCard } from '@/types/llm';

export interface DeepSeekModelCard {
id: string;
Expand Down Expand Up @@ -59,19 +59,35 @@ export const LobeDeepSeekAI = LobeOpenAICompatibleFactory({
debug: {
chatCompletion: () => process.env.DEBUG_DEEPSEEK_CHAT_COMPLETION === '1',
},
models: {
transformModel: (m) => {
const model = m as unknown as DeepSeekModelCard;
models: async ({ client }) => {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

return {
contextWindowTokens: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.contextWindowTokens ?? undefined,
displayName: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.displayName ?? undefined,
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.enabled || false,
functionCall: !model.id.toLowerCase().includes('deepseek-reasoner'),
id: model.id,
reasoning: model.id.toLowerCase().includes('deepseek-reasoner'),
};
},
const modelsPage = await client.models.list() as any;
const modelList: DeepSeekModelCard[] = modelsPage.data;

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.id.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: knownModel?.contextWindowTokens ?? undefined,
displayName: knownModel?.displayName ?? undefined,
enabled: knownModel?.enabled || false,
functionCall:
!model.id.toLowerCase().includes('reasoner')
|| knownModel?.abilities?.functionCall
|| false,
id: model.id,
reasoning:
model.id.toLowerCase().includes('reasoner')
|| knownModel?.abilities?.reasoning
|| false,
vision:
knownModel?.abilities?.vision
|| false,
};
})
.filter(Boolean) as ChatModelCard[];
},
provider: ModelProvider.DeepSeek,
});
48 changes: 30 additions & 18 deletions src/libs/agent-runtime/fireworksai/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ModelProvider } from '../types';
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';

import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
import type { ChatModelCard } from '@/types/llm';

export interface FireworksAIModelCard {
context_length: number;
Expand All @@ -15,25 +15,37 @@ export const LobeFireworksAI = LobeOpenAICompatibleFactory({
debug: {
chatCompletion: () => process.env.DEBUG_FIREWORKSAI_CHAT_COMPLETION === '1',
},
models: {
transformModel: (m) => {
const reasoningKeywords = [
'deepseek-r1',
'qwq',
];
models: async ({ client }) => {
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');

const model = m as unknown as FireworksAIModelCard;
const reasoningKeywords = [
'deepseek-r1',
'qwq',
];

return {
contextWindowTokens: model.context_length,
displayName: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.displayName ?? undefined,
enabled: LOBE_DEFAULT_MODEL_LIST.find((m) => model.id === m.id)?.enabled || false,
functionCall: model.supports_tools || model.id.toLowerCase().includes('function'),
id: model.id,
reasoning: reasoningKeywords.some(keyword => model.id.toLowerCase().includes(keyword)),
vision: model.supports_image_input,
};
},
const modelsPage = await client.models.list() as any;
const modelList: FireworksAIModelCard[] = modelsPage.data;

return modelList
.map((model) => {
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((m) => model.id.toLowerCase() === m.id.toLowerCase());

return {
contextWindowTokens: model.context_length,
displayName: knownModel?.displayName ?? undefined,
enabled: knownModel?.enabled || false,
functionCall:
model.supports_tools
|| model.id.toLowerCase().includes('function'),
id: model.id,
reasoning:
reasoningKeywords.some(keyword => model.id.toLowerCase().includes(keyword))
|| knownModel?.abilities?.reasoning
|| false,
vision: model.supports_image_input,
};
})
.filter(Boolean) as ChatModelCard[];
},
provider: ModelProvider.FireworksAI,
});
Loading