Compare commits

..

6 Commits

Author SHA1 Message Date
Junyan Qin
cef24d8c4b fix: linter errors 2025-11-11 18:24:06 +08:00
Copilot
7a10dfdac1 refactor: parallelize Docker multi-arch builds (arm64/amd64) (#1774)
* Initial plan

* refactor: parallelize Docker image builds for arm64 and amd64

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* security: add explicit GITHUB_TOKEN permissions to workflow jobs

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* refactor: use build cache instead of intermediate tags

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* ci: perf trigger

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>
Co-authored-by: Junyan Qin <rockchinq@gmail.com>
2025-11-11 18:19:35 +08:00
Junyan Qin
02892e57bb fix: default is able to be deleted 2025-11-11 18:10:31 +08:00
Copilot
524c56a12b feat(web): add hover card to embedding model selector in knowledge base form (#1772)
* Initial plan

* feat: Add hover card with model details to embedding model selector in KB form

- Updated KBForm.tsx to fetch full EmbeddingModel objects instead of simplified entities
- Added HoverCard component to show model details (icon, description, base URL, extra args) when hovering over embedding model options
- Removed unused IEmbeddingModelEntity import and embeddingModelNameList state
- Made the embedding model selector consistent with LLM model selector behavior

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>
2025-11-11 17:52:30 +08:00
Junyan Qin
0e0d7cc7b8 chore: add commit message format in AGENTS.md 2025-11-11 12:53:20 +08:00
Copilot
1f877e2b8e Optimize model provider selection with category grouping (#1770)
* Initial plan

* Add provider category field to requesters and implement grouped dropdown

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Fix TypeScript type and prettier formatting issues

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Rename provider categories: aggregator→maas, self_deployed→self-hosted

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Move provider_category from metadata to spec section

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* perf: adjust category

* perf: adjust data structure

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>
Co-authored-by: Junyan Qin <rockchinq@gmail.com>
2025-11-11 12:49:43 +08:00
37 changed files with 704 additions and 457 deletions

View File

@@ -1,15 +1,17 @@
name: Build Docker Image
on:
#防止fork乱用action设置只能手动触发构建
workflow_dispatch:
## 发布release的时候会自动构建
release:
types: [published]
jobs:
publish-docker-image:
prepare:
runs-on: ubuntu-latest
name: Build image
name: Prepare build metadata
permissions:
contents: read
outputs:
version: ${{ steps.check_version.outputs.version }}
is_prerelease: ${{ github.event.release.prerelease }}
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -37,13 +39,81 @@ jobs:
echo $GITHUB_REF
echo ::set-output name=version::${GITHUB_REF}
fi
build-images:
runs-on: ubuntu-latest
needs: prepare
name: Build ${{ matrix.platform }} image
permissions:
contents: read
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set platform tag
id: platform_tag
run: |
# Convert platform to tag suffix (e.g., linux/amd64 -> amd64)
PLATFORM_TAG=$(echo ${{ matrix.platform }} | sed 's/linux\///g')
echo ::set-output name=tag::${PLATFORM_TAG}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Registry
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Create Buildx
run: docker buildx create --name mybuilder --use
- name: Build for Release # only relase, exlude pre-release
if: ${{ github.event.release.prerelease == false }}
run: docker buildx build --platform linux/arm64,linux/amd64 -t rockchin/langbot:${{ steps.check_version.outputs.version }} -t rockchin/langbot:latest . --push
- name: Build for Pre-release # no update for latest tag
if: ${{ github.event.release.prerelease == true }}
run: docker buildx build --platform linux/arm64,linux/amd64 -t rockchin/langbot:${{ steps.check_version.outputs.version }} . --push
- name: Build and cache
run: |
docker buildx build \
--platform ${{ matrix.platform }} \
--cache-to type=registry,ref=rockchin/langbot:cache-${{ steps.platform_tag.outputs.tag }},mode=max \
--cache-from type=registry,ref=rockchin/langbot:cache-${{ steps.platform_tag.outputs.tag }} \
-t rockchin/langbot:${{ needs.prepare.outputs.version }} \
.
push-multiarch:
runs-on: ubuntu-latest
needs: [prepare, build-images]
name: Build and push multi-arch images
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Registry
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push for Release
if: ${{ needs.prepare.outputs.is_prerelease == 'false' }}
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--cache-from type=registry,ref=rockchin/langbot:cache-amd64 \
--cache-from type=registry,ref=rockchin/langbot:cache-arm64 \
-t rockchin/langbot:${{ needs.prepare.outputs.version }} \
-t rockchin/langbot:latest \
--push \
.
- name: Build and push for Pre-release
if: ${{ needs.prepare.outputs.is_prerelease == 'true' }}
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--cache-from type=registry,ref=rockchin/langbot:cache-amd64 \
--cache-from type=registry,ref=rockchin/langbot:cache-arm64 \
-t rockchin/langbot:${{ needs.prepare.outputs.version }} \
--push \
.

View File

@@ -64,6 +64,11 @@ Plugin Runtime automatically starts each installed plugin and interacts through
- LangBot is a global project, any comments in code should be in English, and user experience should be considered in all aspects.
- Thus you should consider the i18n support in all aspects.
- LangBot is widely adopted in both toC and toB scenarios, so you should consider the compatibility and security in all aspects.
- If you were asked to make a commit, please follow the commit message format:
- format: <type>(<scope>): <subject>
- type: must be a specific type, such as feat (new feature), fix (bug fix), docs (documentation), style (code style), refactor (refactoring), perf (performance optimization), etc.
- scope: the scope of the commit, such as the package name, the file name, the function name, the class name, the module name, etc.
- subject: the subject of the commit, such as the description of the commit, the reason for the commit, the impact of the commit, etc.
## Some Principles

View File

@@ -8,24 +8,25 @@ metadata:
icon: 302ai.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.302.ai/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.302.ai/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./302aichatcmpl.py
attr: AI302ChatCompletions
attr: AI302ChatCompletions

View File

@@ -8,22 +8,23 @@ metadata:
icon: anthropic.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.anthropic.com"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.anthropic.com
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./anthropicmsgs.py

View File

@@ -8,22 +8,23 @@ metadata:
icon: bailian.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://dashscope.aliyuncs.com/compatible-mode/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://dashscope.aliyuncs.com/compatible-mode/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: maas
execution:
python:
path: ./bailianchatcmpl.py

View File

@@ -8,24 +8,25 @@ metadata:
icon: openai.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.openai.com/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.openai.com/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: manufacturer
execution:
python:
path: ./chatcmpl.py
attr: OpenAIChatCompletions
attr: OpenAIChatCompletions

View File

@@ -8,23 +8,24 @@ metadata:
icon: compshare.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.modelverse.cn/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.modelverse.cn/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: maas
execution:
python:
path: ./compsharechatcmpl.py
attr: CompShareChatCompletions
attr: CompShareChatCompletions

View File

@@ -8,23 +8,24 @@ metadata:
icon: deepseek.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.deepseek.com"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.deepseek.com
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./deepseekchatcmpl.py
attr: DeepseekChatCompletions
attr: DeepseekChatCompletions

View File

@@ -8,22 +8,23 @@ metadata:
icon: gemini.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://generativelanguage.googleapis.com/v1beta/openai"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://generativelanguage.googleapis.com/v1beta/openai
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./geminichatcmpl.py

View File

@@ -8,24 +8,25 @@ metadata:
icon: giteeai.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://ai.gitee.com/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://ai.gitee.com/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./giteeaichatcmpl.py
attr: GiteeAIChatCompletions
attr: GiteeAIChatCompletions

View File

@@ -8,31 +8,32 @@ metadata:
icon: jiekouai.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.jiekou.ai/openai"
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.jiekou.ai/openai
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./jiekouaichatcmpl.py
attr: JieKouAIChatCompletions
attr: JieKouAIChatCompletions

View File

@@ -8,23 +8,24 @@ metadata:
icon: lmstudio.webp
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "http://127.0.0.1:1234/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: http://127.0.0.1:1234/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: self-hosted
execution:
python:
path: ./lmstudiochatcmpl.py

View File

@@ -8,29 +8,30 @@ metadata:
icon: modelscope.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api-inference.modelscope.cn/v1"
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api-inference.modelscope.cn/v1
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
support_type:
- llm
- llm
provider_category: maas
execution:
python:
path: ./modelscopechatcmpl.py

View File

@@ -8,22 +8,23 @@ metadata:
icon: moonshot.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.moonshot.ai/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.moonshot.ai/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./moonshotchatcmpl.py

View File

@@ -8,24 +8,25 @@ metadata:
icon: newapi.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "http://localhost:3000/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: http://localhost:3000/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./newapichatcmpl.py
attr: NewAPIChatCompletions
attr: NewAPIChatCompletions

View File

@@ -8,23 +8,24 @@ metadata:
icon: ollama.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "http://127.0.0.1:11434"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: http://127.0.0.1:11434
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: self-hosted
execution:
python:
path: ./ollamachat.py

View File

@@ -8,23 +8,24 @@ metadata:
icon: openrouter.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://openrouter.ai/api/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://openrouter.ai/api/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./openrouterchatcmpl.py

View File

@@ -3,36 +3,37 @@ kind: LLMAPIRequester
metadata:
name: ppio-chat-completions
label:
en_US: ppio
en_US: ppio
zh_Hans: 派欧云
icon: ppio.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.ppinfra.com/v3/openai"
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.ppinfra.com/v3/openai
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./ppiochatcmpl.py
attr: PPIOChatCompletions
attr: PPIOChatCompletions

View File

@@ -8,31 +8,32 @@ metadata:
icon: qhaigc.png
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.qhaigc.net/v1"
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.qhaigc.net/v1
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./qhaigcchatcmpl.py
attr: QHAIGCChatCompletions
attr: QHAIGCChatCompletions

View File

@@ -8,31 +8,32 @@ metadata:
icon: shengsuanyun.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://router.shengsuanyun.com/api/v1"
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://router.shengsuanyun.com/api/v1
- name: args
label:
en_US: Args
zh_Hans: 附加参数
type: object
required: true
default: {}
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: int
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./shengsuanyun.py
attr: ShengSuanYunChatCompletions
attr: ShengSuanYunChatCompletions

View File

@@ -8,23 +8,24 @@ metadata:
icon: siliconflow.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.siliconflow.cn/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.siliconflow.cn/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./siliconflowchatcmpl.py

View File

@@ -8,24 +8,25 @@ metadata:
icon: tokenpony.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.tokenpony.cn/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.tokenpony.cn/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- text-embedding
- llm
- text-embedding
provider_category: maas
execution:
python:
path: ./tokenponychatcmpl.py
attr: TokenPonyChatCompletions
attr: TokenPonyChatCompletions

View File

@@ -8,22 +8,23 @@ metadata:
icon: volcark.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://ark.cn-beijing.volces.com/api/v3"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://ark.cn-beijing.volces.com/api/v3
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: maas
execution:
python:
path: ./volcarkchatcmpl.py

View File

@@ -8,22 +8,23 @@ metadata:
icon: xai.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://api.x.ai/v1"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.x.ai/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./xaichatcmpl.py

View File

@@ -8,22 +8,23 @@ metadata:
icon: zhipuai.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: "https://open.bigmodel.cn/api/paas/v4"
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://open.bigmodel.cn/api/paas/v4
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
- llm
provider_category: manufacturer
execution:
python:
path: ./zhipuaichatcmpl.py

View File

@@ -13,7 +13,6 @@ import {
FormMessage,
FormDescription,
} from '@/components/ui/form';
import { IEmbeddingModelEntity } from './ChooseEntity';
import { httpClient } from '@/app/infra/http/HttpClient';
import {
Select,
@@ -23,8 +22,13 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { KnowledgeBase } from '@/app/infra/entities/api';
import { KnowledgeBase, EmbeddingModel } from '@/app/infra/entities/api';
import { toast } from 'sonner';
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/hover-card';
const getFormSchema = (t: (key: string) => string) =>
z.object({
@@ -63,9 +67,7 @@ export default function KBForm({
},
});
const [embeddingModelNameList, setEmbeddingModelNameList] = useState<
IEmbeddingModelEntity[]
>([]);
const [embeddingModels, setEmbeddingModels] = useState<EmbeddingModel[]>([]);
useEffect(() => {
getEmbeddingModelNameList().then(() => {
@@ -97,14 +99,7 @@ export default function KBForm({
const getEmbeddingModelNameList = async () => {
const resp = await httpClient.getProviderEmbeddingModels();
setEmbeddingModelNameList(
resp.models.map((item) => {
return {
label: item.name,
value: item.uuid,
};
}),
);
setEmbeddingModels(resp.models);
};
const onSubmit = (data: z.infer<typeof formSchema>) => {
@@ -216,10 +211,87 @@ export default function KBForm({
</SelectTrigger>
<SelectContent className="fixed z-[1000]">
<SelectGroup>
{embeddingModelNameList.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
{embeddingModels.map((model) => (
<HoverCard
key={model.uuid}
openDelay={0}
closeDelay={0}
>
<HoverCardTrigger asChild>
<SelectItem value={model.uuid}>
{model.name}
</SelectItem>
</HoverCardTrigger>
<HoverCardContent
className="w-80 data-[state=open]:animate-none data-[state=closed]:animate-none"
align="end"
side="right"
sideOffset={10}
>
<div className="space-y-2">
<div className="flex items-center gap-2">
<img
src={httpClient.getProviderRequesterIconURL(
model.requester,
)}
alt="icon"
className="w-8 h-8 rounded-full"
/>
<h4 className="font-medium">
{model.name}
</h4>
</div>
<p className="text-sm text-muted-foreground">
{model.description}
</p>
{model.requester_config && (
<div className="flex items-center gap-1 text-xs">
<svg
className="w-4 h-4 text-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M13.0607 8.11097L14.4749 9.52518C17.2086 12.2589 17.2086 16.691 14.4749 19.4247L14.1214 19.7782C11.3877 22.5119 6.95555 22.5119 4.22188 19.7782C1.48821 17.0446 1.48821 12.6124 4.22188 9.87874L5.6361 11.293C3.68348 13.2456 3.68348 16.4114 5.6361 18.364C7.58872 20.3166 10.7545 20.3166 12.7072 18.364L13.0607 18.0105C15.0133 16.0578 15.0133 12.892 13.0607 10.9394L11.6465 9.52518L13.0607 8.11097ZM19.7782 14.1214L18.364 12.7072C20.3166 10.7545 20.3166 7.58872 18.364 5.6361C16.4114 3.68348 13.2456 3.68348 11.293 5.6361L10.9394 5.98965C8.98678 7.94227 8.98678 11.1081 10.9394 13.0607L12.3536 14.4749L10.9394 15.8891L9.52518 14.4749C6.79151 11.7413 6.79151 7.30911 9.52518 4.57544L9.87874 4.22188C12.6124 1.48821 17.0446 1.48821 19.7782 4.22188C22.5119 6.95555 22.5119 11.3877 19.7782 14.1214Z"></path>
</svg>
<span className="font-semibold">
Base URL
</span>
{model.requester_config.base_url}
</div>
)}
{model.extra_args &&
Object.keys(model.extra_args).length >
0 && (
<div className="text-xs">
<div className="font-semibold mb-1">
{t('models.extraParameters')}
</div>
<div className="space-y-1">
{Object.entries(
model.extra_args as Record<
string,
unknown
>,
).map(([key, value]) => (
<div
key={key}
className="flex items-center gap-1"
>
<span className="text-gray-500">
{key}
</span>
<span className="break-all">
{JSON.stringify(value)}
</span>
</div>
))}
</div>
</div>
)}
</div>
</HoverCardContent>
</HoverCard>
))}
</SelectGroup>
</SelectContent>

View File

@@ -1,4 +1,5 @@
export interface IChooseRequesterEntity {
label: string;
value: string;
provider_category?: string;
}

View File

@@ -34,6 +34,7 @@ import {
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
@@ -186,6 +187,7 @@ export default function EmbeddingForm({
return {
label: extractI18nObject(item.label),
value: item.name,
provider_category: item.spec.provider_category || 'manufacturer',
};
}),
);
@@ -425,11 +427,44 @@ export default function EmbeddingForm({
</SelectTrigger>
<SelectContent>
<SelectGroup>
{requesterNameList.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
<SelectLabel>
{t('models.modelManufacturer')}
</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'manufacturer',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>
{t('models.aggregationPlatform')}
</SelectLabel>
{requesterNameList
.filter((item) => item.provider_category === 'maas')
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>{t('models.selfDeployed')}</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'self-hosted',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>

View File

@@ -34,6 +34,7 @@ import {
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
@@ -203,6 +204,7 @@ export default function LLMForm({
return {
label: extractI18nObject(item.label),
value: item.name,
provider_category: item.spec.provider_category || 'manufacturer',
};
}),
);
@@ -440,11 +442,44 @@ export default function LLMForm({
</SelectTrigger>
<SelectContent>
<SelectGroup>
{requesterNameList.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
<SelectLabel>
{t('models.modelManufacturer')}
</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'manufacturer',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>
{t('models.aggregationPlatform')}
</SelectLabel>
{requesterNameList
.filter((item) => item.provider_category === 'maas')
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>{t('models.selfDeployed')}</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'self-hosted',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>

View File

@@ -39,7 +39,6 @@ export default function PipelineDialog({
onOpenChange,
pipelineId: propPipelineId,
isEditMode = false,
isDefaultPipeline = false,
onFinish,
onNewPipelineCreated,
onDeletePipeline,
@@ -133,7 +132,6 @@ export default function PipelineDialog({
</DialogHeader>
<div className="flex-1 overflow-y-auto px-6 pb-6">
<PipelineFormComponent
isDefaultPipeline={isDefaultPipeline}
onFinish={handleFinish}
onNewPipelineCreated={handleNewPipelineCreated}
isEditMode={isEditMode}
@@ -197,7 +195,6 @@ export default function PipelineDialog({
>
{currentMode === 'config' && (
<PipelineFormComponent
isDefaultPipeline={isDefaultPipeline}
onFinish={handleFinish}
onNewPipelineCreated={handleNewPipelineCreated}
isEditMode={isEditMode}

View File

@@ -33,7 +33,6 @@ import { useTranslation } from 'react-i18next';
import { extractI18nObject } from '@/i18n/I18nProvider';
export default function PipelineFormComponent({
isDefaultPipeline,
onFinish,
onNewPipelineCreated,
isEditMode,
@@ -43,7 +42,6 @@ export default function PipelineFormComponent({
onCancel,
}: {
pipelineId?: string;
isDefaultPipeline: boolean;
isEditMode: boolean;
disableForm: boolean;
showButtons?: boolean;
@@ -54,6 +52,7 @@ export default function PipelineFormComponent({
}) {
const { t } = useTranslation();
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [isDefaultPipeline, setIsDefaultPipeline] = useState<boolean>(false);
const formSchema = isEditMode
? z.object({
@@ -133,6 +132,7 @@ export default function PipelineFormComponent({
httpClient
.getPipeline(pipelineId || '')
.then((resp: GetPipelineResponseData) => {
setIsDefaultPipeline(resp.pipeline.is_default ?? false);
form.reset({
basic: {
name: resp.pipeline.name,
@@ -353,7 +353,9 @@ export default function PipelineFormComponent({
.getPipeline(pipelineId)
.then((resp) => {
const originalPipeline = resp.pipeline;
newPipelineName = `${originalPipeline.name}${t('pipelines.copySuffix')}`;
newPipelineName = `${originalPipeline.name}${t(
'pipelines.copySuffix',
)}`;
const newPipeline: Pipeline = {
name: newPipelineName,
description: originalPipeline.description,

View File

@@ -22,9 +22,6 @@ export default function PluginConfigPage() {
const [isEditForm, setIsEditForm] = useState(false);
const [pipelineList, setPipelineList] = useState<PipelineCardVO[]>([]);
const [selectedPipelineId, setSelectedPipelineId] = useState('');
const [selectedPipelineIsDefault, setSelectedPipelineIsDefault] =
useState(false);
const [sortByValue, setSortByValue] = useState<string>('created_at');
const [sortOrderValue, setSortOrderValue] = useState<string>('DESC');
@@ -92,8 +89,6 @@ export default function PluginConfigPage() {
const handleCreateNew = () => {
setIsEditForm(false);
setSelectedPipelineId('');
setSelectedPipelineIsDefault(false);
setDialogOpen(true);
};
@@ -116,7 +111,6 @@ export default function PluginConfigPage() {
onOpenChange={setDialogOpen}
pipelineId={selectedPipelineId || undefined}
isEditMode={isEditForm}
isDefaultPipeline={selectedPipelineIsDefault}
onFinish={() => {
getPipelines();
}}

View File

@@ -29,6 +29,7 @@ export interface Requester {
icon?: string;
spec: {
config: IDynamicFormItemSchema[];
provider_category: string;
};
}

View File

@@ -141,6 +141,9 @@ const enUS = {
selectModelProvider: 'Select Model Provider',
modelProviderDescription:
'Please fill in the model name provided by the supplier',
modelManufacturer: 'Model Manufacturer',
aggregationPlatform: 'Aggregation Platform',
selfDeployed: 'Self-deployed',
selectModel: 'Select Model',
testSuccess: 'Test successful',
testError: 'Test failed, please check your model configuration',

View File

@@ -144,6 +144,9 @@ const jaJP = {
'リクエストボディに追加されるパラメータmax_tokens、temperature、top_p など)',
selectModelProvider: 'モデルプロバイダーを選択',
modelProviderDescription: 'プロバイダーが提供するモデル名をご入力ください',
modelManufacturer: 'モデルメーカー',
aggregationPlatform: 'アグリゲーションプラットフォーム',
selfDeployed: 'セルフデプロイ',
selectModel: 'モデルを選択してください',
testSuccess: 'テストに成功しました',
testError: 'テストに失敗しました。モデル設定を確認してください',

View File

@@ -138,6 +138,9 @@ const zhHans = {
boolean: '布尔值',
selectModelProvider: '选择模型供应商',
modelProviderDescription: '请填写供应商向您提供的模型名称',
modelManufacturer: '模型厂商',
aggregationPlatform: '中转平台',
selfDeployed: '自部署',
selectModel: '请选择模型',
testSuccess: '测试成功',
testError: '测试失败,请检查模型配置',

View File

@@ -138,6 +138,9 @@ const zhHant = {
boolean: '布林值',
selectModelProvider: '選擇模型供應商',
modelProviderDescription: '請填寫供應商向您提供的模型名稱',
modelManufacturer: '模型廠商',
aggregationPlatform: '中轉平台',
selfDeployed: '自部署',
selectModel: '請選擇模型',
testSuccess: '測試成功',
testError: '測試失敗,請檢查模型設定',