From 197258ae9131ca12c71de5b9eeddf943541fbc9f Mon Sep 17 00:00:00 2001 From: Junyan Qin Date: Tue, 30 Dec 2025 21:52:52 +0800 Subject: [PATCH] feat: add LangBot Space ChatCompletions requester and integrate with ModelsDialog and EmbeddingForm components --- src/langbot/pkg/persistence/mgr.py | 26 +++++++- .../provider/modelmgr/requesters/space.webp | Bin 0 -> 13922 bytes .../modelmgr/requesters/spacechatcmpl.py | 17 ++++++ .../modelmgr/requesters/spacechatcmpl.yaml | 32 ++++++++++ .../components/models-dialog/ModelsDialog.tsx | 57 +----------------- .../embedding-form/EmbeddingForm.tsx | 32 +++++++--- .../component/llm-form/LLMForm.tsx | 32 +++++++--- 7 files changed, 124 insertions(+), 72 deletions(-) create mode 100644 src/langbot/pkg/provider/modelmgr/requesters/space.webp create mode 100644 src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.py create mode 100644 src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.yaml diff --git a/src/langbot/pkg/persistence/mgr.py b/src/langbot/pkg/persistence/mgr.py index 53b20011..92be6a77 100644 --- a/src/langbot/pkg/persistence/mgr.py +++ b/src/langbot/pkg/persistence/mgr.py @@ -9,7 +9,7 @@ import sqlalchemy.ext.asyncio as sqlalchemy_asyncio import sqlalchemy from . import database, migration -from ..entity.persistence import base, pipeline, metadata +from ..entity.persistence import base, pipeline, metadata, model as persistence_model from ..entity import persistence from ..core import app from ..utils import constants, importutil @@ -79,6 +79,7 @@ class PersistenceManager: self.ap.logger.info(f'Successfully upgraded database to version {last_migration_number}.') await self.write_default_pipeline() + await self.write_space_model_providers() async def create_tables(self): # create tables @@ -123,7 +124,28 @@ class PersistenceManager: await self.execute_async(sqlalchemy.insert(pipeline.LegacyPipeline).values(pipeline_data)) - # ================================= + async def write_space_model_providers(self): + # write space model providers + result = await self.execute_async( + sqlalchemy.select(persistence_model.ModelProvider).where( + persistence_model.ModelProvider.requester == 'space-chat-completions' + ) + ) + if result.first() is None: + self.ap.logger.info('Creating space model providers...') + space_chat_completions_model_provider = { + 'uuid': str(uuid.uuid4()), + 'name': 'LangBot Models', + 'requester': 'space-chat-completions', + 'base_url': 'https://api.langbot.cloud/v1', + 'api_keys': [], + } + + await self.execute_async( + sqlalchemy.insert(persistence_model.ModelProvider).values(space_chat_completions_model_provider) + ) + + # ================================= async def execute_async(self, *args, **kwargs) -> sqlalchemy.engine.cursor.CursorResult: async with self.get_db_engine().connect() as conn: diff --git a/src/langbot/pkg/provider/modelmgr/requesters/space.webp b/src/langbot/pkg/provider/modelmgr/requesters/space.webp new file mode 100644 index 0000000000000000000000000000000000000000..09226adcf9fca2b8a51ff96f383b01be37f00089 GIT binary patch literal 13922 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 DyRYH2 literal 0 HcmV?d00001 diff --git a/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.py b/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.py new file mode 100644 index 00000000..91740a1f --- /dev/null +++ b/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +import typing +import openai + +from . import chatcmpl + + +class LangBotSpaceChatCompletions(chatcmpl.OpenAIChatCompletions): + """LangBot Space ChatCompletion API 请求器""" + + client: openai.AsyncClient + + default_config: dict[str, typing.Any] = { + 'base_url': 'https://api.langbot.cloud/v1', + 'timeout': 120, + } diff --git a/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.yaml b/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.yaml new file mode 100644 index 00000000..29c23a83 --- /dev/null +++ b/src/langbot/pkg/provider/modelmgr/requesters/spacechatcmpl.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: LLMAPIRequester +metadata: + name: space-chat-completions + label: + en_US: Space + zh_Hans: Space + icon: space.webp +spec: + config: + - name: base_url + label: + en_US: Base URL + zh_Hans: 基础 URL + type: string + required: true + default: https://api.langbot.cloud/v1 + - name: timeout + label: + en_US: Timeout + zh_Hans: 超时时间 + type: integer + required: true + default: 120 + support_type: + - llm + - text-embedding + provider_category: maas +execution: + python: + path: ./spacechatcmpl.py + attr: LangBotSpaceChatCompletions diff --git a/web/src/app/home/components/models-dialog/ModelsDialog.tsx b/web/src/app/home/components/models-dialog/ModelsDialog.tsx index 6579ca9c..4a9404b3 100644 --- a/web/src/app/home/components/models-dialog/ModelsDialog.tsx +++ b/web/src/app/home/components/models-dialog/ModelsDialog.tsx @@ -53,6 +53,7 @@ interface ModelsDialogProps { } const LANGBOT_MODELS_PROVIDER_NAME = 'LangBot Models'; +const LANGBOT_MODELS_PROVIDER_REQUESTER = 'space-chat-completions'; export default function ModelsDialog({ open, @@ -253,10 +254,10 @@ export default function ModelsDialog({ // Separate LangBot Models provider const langbotProvider = providers.find( - (p) => p.name === LANGBOT_MODELS_PROVIDER_NAME, + (p) => p.requester === LANGBOT_MODELS_PROVIDER_REQUESTER, ); const otherProviders = providers.filter( - (p) => p.name !== LANGBOT_MODELS_PROVIDER_NAME, + (p) => p.requester !== LANGBOT_MODELS_PROVIDER_REQUESTER, ); function renderProviderCard( @@ -501,58 +502,6 @@ export default function ModelsDialog({ if (langbotProvider) { return renderProviderCard(langbotProvider, true); } - return ( - - -

-
-
- LangBot -
-
- - {LANGBOT_MODELS_PROVIDER_NAME} - -

- {t('models.langbotModelsDescription')} -

-
-
- {accountType !== 'space' ? ( - - ) : ( - spaceCredits !== null && ( -
- - {(spaceCredits / 5000).toFixed(2)} {t('models.credits')} - - -
- ) - )} -
- - - ); } function handleFormClose() { diff --git a/web/src/app/home/components/models-dialog/component/embedding-form/EmbeddingForm.tsx b/web/src/app/home/components/models-dialog/component/embedding-form/EmbeddingForm.tsx index 5bd3b66a..3e7d942e 100644 --- a/web/src/app/home/components/models-dialog/component/embedding-form/EmbeddingForm.tsx +++ b/web/src/app/home/components/models-dialog/component/embedding-form/EmbeddingForm.tsx @@ -373,11 +373,15 @@ export default function EmbeddingForm({ /> - {providers.map((p) => ( - - {p.name} ({p.base_url || 'default'}) - - ))} + {providers + .filter( + (p) => p.requester !== 'space-chat-completions', + ) + .map((p) => ( + + {p.name} ({p.base_url || 'default'}) + + ))} @@ -413,7 +417,11 @@ export default function EmbeddingForm({ {t('models.modelManufacturer')} {requesterList - .filter((r) => r.category === 'manufacturer') + .filter( + (r) => + r.category === 'manufacturer' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label} @@ -425,7 +433,11 @@ export default function EmbeddingForm({ {t('models.aggregationPlatform')} {requesterList - .filter((r) => r.category === 'maas') + .filter( + (r) => + r.category === 'maas' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label} @@ -437,7 +449,11 @@ export default function EmbeddingForm({ {t('models.selfDeployed')} {requesterList - .filter((r) => r.category === 'self-hosted') + .filter( + (r) => + r.category === 'self-hosted' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label} diff --git a/web/src/app/home/components/models-dialog/component/llm-form/LLMForm.tsx b/web/src/app/home/components/models-dialog/component/llm-form/LLMForm.tsx index fb8a79ae..7d816d3a 100644 --- a/web/src/app/home/components/models-dialog/component/llm-form/LLMForm.tsx +++ b/web/src/app/home/components/models-dialog/component/llm-form/LLMForm.tsx @@ -385,11 +385,15 @@ export default function LLMForm({ /> - {providers.map((p) => ( - - {p.name} ({p.base_url || 'default'}) - - ))} + {providers + .filter( + (p) => p.requester !== 'space-chat-completions', + ) + .map((p) => ( + + {p.name} ({p.base_url || 'default'}) + + ))} @@ -425,7 +429,11 @@ export default function LLMForm({ {t('models.modelManufacturer')} {requesterList - .filter((r) => r.category === 'manufacturer') + .filter( + (r) => + r.category === 'manufacturer' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label} @@ -437,7 +445,11 @@ export default function LLMForm({ {t('models.aggregationPlatform')} {requesterList - .filter((r) => r.category === 'maas') + .filter( + (r) => + r.category === 'maas' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label} @@ -449,7 +461,11 @@ export default function LLMForm({ {t('models.selfDeployed')} {requesterList - .filter((r) => r.category === 'self-hosted') + .filter( + (r) => + r.category === 'self-hosted' && + r.value !== 'space-chat-completions', + ) .map((r) => ( {r.label}