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

🐛 fix: fix released at for undefined condition #5391

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion locales/ar/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "معرف فريد لمزود الخدمة، لا يمكن تعديله بعد الإنشاء",
"format": "يمكن أن يحتوي فقط على أحرف صغيرة، وشرطات (-) وشرطات سفلية (_)",
"format": "يمكن أن يحتوي فقط على أرقام، أحرف صغيرة، شرطات (-) وشرطات سفلية (_) ",
"placeholder": "يفضل أن يكون بالكامل بحروف صغيرة، مثل openai، لن يمكن تعديله بعد الإنشاء",
"required": "يرجى إدخال معرف المزود",
"title": "معرف المزود"
Expand Down
2 changes: 1 addition & 1 deletion locales/bg-BG/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Уникален идентификатор за доставчика на услуги, който не може да бъде променян след създаването му",
"format": "Може да съдържа само малки букви, тирета (-) и долни черти (_)",
"format": "Може да съдържа само цифри, малки букви, тирета (-) и долни черти (_) ",
"placeholder": "Препоръчително изцяло с малки букви, например openai, след създаването не може да се промени",
"required": "Моля, въведете ID на доставчика",
"title": "ID на доставчика"
Expand Down
2 changes: 1 addition & 1 deletion locales/de-DE/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Eindeutige Kennung des Anbieters, die nach der Erstellung nicht mehr geändert werden kann",
"format": "Darf nur aus Kleinbuchstaben, Bindestrichen (-) und Unterstrichen (_) bestehen",
"format": "Darf nur aus Zahlen, Kleinbuchstaben, Bindestrichen (-) und Unterstrichen (_) bestehen",
"placeholder": "Empfohlen in Kleinbuchstaben, z.B. openai, nach der Erstellung nicht mehr änderbar",
"required": "Bitte geben Sie die Anbieter-ID ein",
"title": "Anbieter-ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/en-US/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Unique identifier for the service provider, which cannot be modified after creation",
"format": "Can only contain lowercase letters, hyphens (-), and underscores (_) ",
"format": "Can only contain numbers, lowercase letters, hyphens (-), and underscores (_) ",
"placeholder": "Suggested all lowercase, e.g., openai, cannot be modified after creation",
"required": "Please enter the provider ID",
"title": "Provider ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/es-ES/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Identificador único del proveedor de servicios, no se puede modificar una vez creado",
"format": "Solo puede contener letras minúsculas, guiones (-) y guiones bajos (_)",
"format": "Solo puede contener números, letras minúsculas, guiones (-) y guiones bajos (_) ",
"placeholder": "Se recomienda en minúsculas, por ejemplo openai, no se puede modificar después de crear",
"required": "Por favor, introduce el ID del proveedor",
"title": "ID del proveedor"
Expand Down
2 changes: 1 addition & 1 deletion locales/fa-IR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "به عنوان شناسه منحصر به فرد ارائه‌دهنده خدمات، پس از ایجاد قابل ویرایش نخواهد بود",
"format": "فقط می‌تواند شامل حروف کوچک، خط تیره (-) و زیرخط (_) باشد",
"format": "فقط می‌تواند شامل اعداد، حروف کوچک، خط تیره (-) و زیرخط (_) باشد",
"placeholder": "توصیه می‌شود تماماً با حروف کوچک باشد، مانند openai، پس از ایجاد قابل ویرایش نخواهد بود",
"required": "لطفاً شناسه ارائه‌دهنده را وارد کنید",
"title": "شناسه ارائه‌دهنده"
Expand Down
2 changes: 1 addition & 1 deletion locales/fr-FR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Identifiant unique du fournisseur de services, qui ne peut pas être modifié après sa création",
"format": "Ne peut contenir que des lettres minuscules, des tirets (-) et des underscores (_) ",
"format": "Ne peut contenir que des chiffres, des lettres minuscules, des tirets (-) et des underscores (_) ",
"placeholder": "Utilisez uniquement des lettres minuscules, par exemple openai, non modifiable après création",
"required": "Veuillez entrer l'ID du fournisseur",
"title": "ID du fournisseur"
Expand Down
2 changes: 1 addition & 1 deletion locales/it-IT/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Identificatore unico del fornitore di servizi, non modificabile dopo la creazione",
"format": "Può contenere solo lettere minuscole, trattini (-) e underscore (_)",
"format": "Può contenere solo numeri, lettere minuscole, trattini (-) e underscore (_) ",
"placeholder": "Si consiglia di utilizzare solo lettere minuscole, ad esempio openai, non modificabile dopo la creazione",
"required": "Inserisci l'ID del fornitore",
"title": "ID del fornitore"
Expand Down
2 changes: 1 addition & 1 deletion locales/ja-JP/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "サービスプロバイダーの一意の識別子であり、作成後は変更できません",
"format": "小文字のアルファベット、ハイフン(-)、およびアンダースコア(_)のみを含むことができます",
"format": "数字、小文字のアルファベット、ハイフン(-)、およびアンダースコア(_)のみを含むことができます",
"placeholder": "小文字で入力してください(例: openai)。作成後は変更できません",
"required": "サービスプロバイダー ID を入力してください",
"title": "サービスプロバイダー ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/ko-KR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "서비스 제공자의 고유 식별자로, 생성 후에는 수정할 수 없습니다.",
"format": "소문자, 하이픈(-), 및 언더스코어(_)만 포함할 수 있습니다.",
"format": "숫자, 소문자, 하이픈(-), 및 언더스코어(_)만 포함할 수 있습니다.",
"placeholder": "소문자로 입력하세요, 예: openai, 생성 후 수정할 수 없습니다",
"required": "서비스 제공자 ID를 입력하세요",
"title": "서비스 제공자 ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/nl-NL/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Een unieke identificatie voor de dienstverlener, kan na creatie niet meer worden gewijzigd",
"format": "Mag alleen kleine letters, koppeltekens (-) en underscores (_) bevatten",
"format": "Mag alleen cijfers, kleine letters, koppeltekens (-) en onderstrepingstekens (_) bevatten",
"placeholder": "Gebruik alleen kleine letters, bijvoorbeeld openai, kan niet worden gewijzigd na aanmaak",
"required": "Vul de provider ID in",
"title": "Provider ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/pl-PL/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Unikalny identyfikator dostawcy usług, po utworzeniu nie można go zmienić",
"format": "Może zawierać tylko małe litery, myślniki (-) i podkreślenia (_)",
"format": "Może zawierać tylko cyfry, małe litery, myślniki (-) i podkreślenia (_) ",
"placeholder": "Zaleca się użycie małych liter, np. openai, po utworzeniu nie można edytować",
"required": "Proszę wpisać identyfikator dostawcy",
"title": "Identyfikator dostawcy"
Expand Down
2 changes: 1 addition & 1 deletion locales/pt-BR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Identificador único do provedor de serviços, não pode ser modificado após a criação",
"format": "Pode conter apenas letras minúsculas, hífens (-) e sublinhados (_)",
"format": "Só pode conter números, letras minúsculas, hífens (-) e sublinhados (_) ",
"placeholder": "Sugestão: tudo em minúsculas, por exemplo, openai, não poderá ser modificado após a criação",
"required": "Por favor, insira o ID do provedor",
"title": "ID do Provedor"
Expand Down
2 changes: 1 addition & 1 deletion locales/ru-RU/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Уникальный идентификатор для поставщика услуг, который нельзя изменить после создания",
"format": "Может содержать только строчные буквы, дефисы (-) и подчеркивания (_)",
"format": "Может содержать только цифры, строчные буквы, дефисы (-) и подчеркивания (_) ",
"placeholder": "Рекомендуется использовать строчные буквы, например, openai, после создания изменить нельзя",
"required": "Пожалуйста, введите ID провайдера",
"title": "ID провайдера"
Expand Down
2 changes: 1 addition & 1 deletion locales/tr-TR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Hizmet sağlayıcının benzersiz kimliği, oluşturulduktan sonra değiştirilemez",
"format": "Sadece küçük harfler, tire (-) ve alt çizgi (_) içerebilir",
"format": "Sadece rakamlar, küçük harfler, tire (-) ve alt çizgi (_) içerebilir",
"placeholder": "Küçük harflerle yazılması önerilir, örneğin openai, oluşturduktan sonra değiştirilemez",
"required": "Lütfen hizmet sağlayıcı ID'sini girin",
"title": "Hizmet Sağlayıcı ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/vi-VN/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "Là định danh duy nhất của nhà cung cấp dịch vụ, không thể sửa đổi sau khi tạo",
"format": "Chỉ có thể chứa chữ cái thường, dấu gạch ngang (-) và dấu gạch dưới (_)",
"format": "Chỉ có thể chứa số, chữ cái thường, dấu gạch ngang (-) và dấu gạch dưới (_) ",
"placeholder": "Nên viết toàn bộ bằng chữ thường, ví dụ openai, không thể sửa sau khi tạo",
"required": "Vui lòng nhập ID nhà cung cấp",
"title": "ID nhà cung cấp"
Expand Down
2 changes: 1 addition & 1 deletion locales/zh-CN/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "作为服务商唯一标识,创建后将不可修改",
"format": "只能包含小写字母、连字符(-)和下划线(_)",
"format": "只能包含数字、小写字母、连字符(-)和下划线(_)",
"placeholder": "例如 openai、gemini 等",
"required": "请填写服务商 ID",
"title": "服务商 ID"
Expand Down
2 changes: 1 addition & 1 deletion locales/zh-TW/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"id": {
"desc": "作為服務商唯一標識,創建後將不可修改",
"format": "只能包含小寫字母、連字符(-)和下劃線(_)",
"format": "只能包含數字、小寫字母、連字符(-)和底線(_)",
"placeholder": "建議全小寫,例如 openai,創建後將不可修改",
"required": "請填寫服務商 ID",
"title": "服務商 ID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const CreateNewProvider = memo<CreateNewProviderProps>(({ onClose, open }) => {
{ message: t('createNewAiProvider.id.required'), required: true },
{
message: t('createNewAiProvider.id.format'),
pattern: /^[_a-z-]+$/,
pattern: /^[\d_a-z-]+$/,
},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@ exports[`LobeOpenAI > models > should get models 1`] = `
},
{
"id": "gpt-3.5-turbo-16k",
"releasedAt": "2023-05-10",
},
{
"id": "gpt-3.5-turbo-16k-0613",
"releasedAt": "2023-05-30",
},
{
"id": "gpt-4-1106-vision-preview",
"releasedAt": "2024-03-26",
},
{
"id": "gpt-3.5-turbo-instruct-0914",
"releasedAt": "2023-09-07",
},
{
"contextWindowTokens": 128000,
Expand Down Expand Up @@ -63,9 +67,11 @@ exports[`LobeOpenAI > models > should get models 1`] = `
},
{
"id": "gpt-3.5-turbo-0301",
"releasedAt": "2023-03-01",
},
{
"id": "gpt-3.5-turbo-0613",
"releasedAt": "2023-06-12",
},
{
"contextWindowTokens": 16385,
Expand Down
117 changes: 94 additions & 23 deletions src/libs/agent-runtime/utils/openaiCompatibleFactory/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @vitest-environment node
import OpenAI from 'openai';
import type { Stream } from 'openai/streaming';

import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import {
Expand All @@ -11,6 +10,7 @@ import {
LobeOpenAICompatibleRuntime,
ModelProvider,
} from '@/libs/agent-runtime';
import officalOpenAIModels from '@/libs/agent-runtime/openai/fixtures/openai-models.json';
import { sleep } from '@/utils/sleep';

import * as debugStreamModule from '../debugStream';
Expand Down Expand Up @@ -802,26 +802,29 @@ describe('LobeOpenAICompatibleFactory', () => {

it('should use custom stream handler when provided', async () => {
// Create a custom stream handler that handles both ReadableStream and OpenAI Stream
const customStreamHandler = vi.fn((stream: ReadableStream | Stream<OpenAI.ChatCompletionChunk>) => {
const readableStream = stream instanceof ReadableStream ? stream : stream.toReadableStream();
return new ReadableStream({
start(controller) {
const reader = readableStream.getReader();
const process = async () => {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
controller.enqueue(value);
const customStreamHandler = vi.fn(
(stream: ReadableStream | Stream<OpenAI.ChatCompletionChunk>) => {
const readableStream =
stream instanceof ReadableStream ? stream : stream.toReadableStream();
return new ReadableStream({
start(controller) {
const reader = readableStream.getReader();
const process = async () => {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
controller.enqueue(value);
}
} finally {
controller.close();
}
} finally {
controller.close();
}
};
process();
},
});
});
};
process();
},
});
},
);

const LobeMockProvider = LobeOpenAICompatibleFactory({
baseURL: 'https://api.test.com/v1',
Expand Down Expand Up @@ -897,10 +900,10 @@ describe('LobeOpenAICompatibleFactory', () => {
choices: [
{
index: 0,
message: {
role: 'assistant',
message: {
role: 'assistant',
content: 'Test response',
refusal: null
refusal: null,
},
logprobs: null,
finish_reason: 'stop',
Expand Down Expand Up @@ -969,4 +972,72 @@ describe('LobeOpenAICompatibleFactory', () => {
});
});
});

describe('models', () => {
it('should get models with third party model list', async () => {
vi.spyOn(instance['client'].models, 'list').mockResolvedValue({
data: [
{ id: 'gpt-4o', object: 'model', created: 1698218177 },
{ id: 'claude-3-haiku-20240307', object: 'model' },
{ id: 'gpt-4o-mini', object: 'model', created: 1698318177 * 1000 },
{ id: 'gemini', object: 'model', created: 1736499509125 },
],
} as any);

const list = await instance.models();

expect(list).toEqual([
{
contextWindowTokens: 128000,
releasedAt: '2023-10-25',
description:
'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。',
displayName: 'GPT-4o',
enabled: true,
functionCall: true,
id: 'gpt-4o',
pricing: {
input: 2.5,
output: 10,
},
vision: true,
},
{
contextWindowTokens: 200000,
description:
'Claude 3 Haiku 是 Anthropic 的最快且最紧凑的模型,旨在实现近乎即时的响应。它具有快速且准确的定向性能。',
displayName: 'Claude 3 Haiku',
functionCall: true,
id: 'claude-3-haiku-20240307',
maxOutput: 4096,
pricing: {
input: 0.25,
output: 1.25,
},
releasedAt: '2024-03-07',
vision: true,
},
{
contextWindowTokens: 128000,
description:
'GPT-4o mini是OpenAI在GPT-4 Omni之后推出的最新模型,支持图文输入并输出文本。作为他们最先进的小型模型,它比其他近期的前沿模型便宜很多,并且比GPT-3.5 Turbo便宜超过60%。它保持了最先进的智能,同时具有显著的性价比。GPT-4o mini在MMLU测试中获得了 82% 的得分,目前在聊天偏好上排名高于 GPT-4。',
displayName: 'GPT-4o mini',
enabled: true,
functionCall: true,
id: 'gpt-4o-mini',
maxOutput: 16385,
pricing: {
input: 0.15,
output: 0.6,
},
releasedAt: '2023-10-26',
vision: true,
},
{
id: 'gemini',
releasedAt: '2025-01-10',
},
]);
});
});
});
26 changes: 20 additions & 6 deletions src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,20 +279,34 @@ export const LobeOpenAICompatibleFactory = <T extends Record<string, any> = any>
return models.transformModel(item);
}

const toReleasedAt = () => {
if (!item.created) return;

// guarantee item.created in Date String format
if (
typeof (item.created as any) === 'string' ||
// or in milliseconds
item.created.toFixed(0).length === 13
) {
return dayjs.utc(item.created).format('YYYY-MM-DD');
}

// by default, the created time is in seconds
return dayjs.utc(item.created * 1000).format('YYYY-MM-DD');
};

// TODO: should refactor after remove v1 user/modelList code
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((model) => model.id === item.id);

if (knownModel) {
dayjs.extend(utc);

return {
...knownModel,
releasedAt:
knownModel.releasedAt ?? dayjs.utc(item.created * 1000).format('YYYY-MM-DD'),
};
const releasedAt = knownModel.releasedAt ?? toReleasedAt();

return { ...knownModel, releasedAt };
}

return { id: item.id };
return { id: item.id, releasedAt: toReleasedAt() };
})

.filter(Boolean) as ChatModelCard[];
Expand Down
Loading
Loading