feat: add baidu cloud provider
This commit is contained in:
parent
762c3d4950
commit
2898215a00
19
.yarn/patches/@langchain-openai-npm-0.3.16-e525b59526.patch
Normal file
19
.yarn/patches/@langchain-openai-npm-0.3.16-e525b59526.patch
Normal file
@ -0,0 +1,19 @@
|
||||
diff --git a/dist/embeddings.js b/dist/embeddings.js
|
||||
index 1f8154be3e9c22442a915eb4b85fa6d2a21b0d0c..dc13ef4a30e6c282824a5357bcee9bd0ae222aab 100644
|
||||
--- a/dist/embeddings.js
|
||||
+++ b/dist/embeddings.js
|
||||
@@ -214,10 +214,12 @@ export class OpenAIEmbeddings extends Embeddings {
|
||||
* @returns Promise that resolves to an embedding for the document.
|
||||
*/
|
||||
async embedQuery(text) {
|
||||
+ const isBaiduCloud = this.clientConfig.baseURL.includes('baidubce.com')
|
||||
+ const input = this.stripNewLines ? text.replace(/\n/g, ' ') : text
|
||||
const params = {
|
||||
model: this.model,
|
||||
- input: this.stripNewLines ? text.replace(/\n/g, " ") : text,
|
||||
- };
|
||||
+ input: isBaiduCloud ? [input] : input
|
||||
+ }
|
||||
if (this.dimensions) {
|
||||
params.dimensions = this.dimensions;
|
||||
}
|
||||
@ -151,7 +151,9 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"pdf-parse@npm:1.1.1": "patch:pdf-parse@npm%3A1.1.1#~/.yarn/patches/pdf-parse-npm-1.1.1-04a6109b2a.patch",
|
||||
"@llm-tools/embedjs-utils@npm:0.1.25": "patch:@llm-tools/embedjs-utils@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-utils-npm-0.1.25-fd8fe8a193.patch"
|
||||
"@llm-tools/embedjs-utils@npm:0.1.25": "patch:@llm-tools/embedjs-utils@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-utils-npm-0.1.25-fd8fe8a193.patch",
|
||||
"@langchain/openai@npm:^0.3.16": "patch:@langchain/openai@npm%3A0.3.16#~/.yarn/patches/@langchain-openai-npm-0.3.16-e525b59526.patch",
|
||||
"@langchain/openai@npm:>=0.1.0 <0.4.0": "patch:@langchain/openai@npm%3A0.3.16#~/.yarn/patches/@langchain-openai-npm-0.3.16-e525b59526.patch"
|
||||
},
|
||||
"packageManager": "yarn@4.5.0"
|
||||
}
|
||||
|
||||
1
src/renderer/src/assets/images/providers/baidu-cloud.svg
Normal file
1
src/renderer/src/assets/images/providers/baidu-cloud.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>BaiduCloud</title><path d="M21.715 5.61l-3.983 2.31a.903.903 0 01-.896 0L12.44 5.384a.903.903 0 00-.897 0L7.156 7.92a.903.903 0 01-.896 0L2.276 5.617 12.002 0l9.713 5.61z" fill="#5BCA87"></path><path d="M18.641 9.467a.89.89 0 00-.438.77v5.072a.896.896 0 01-.445.77l-4.428 2.51a.884.884 0 00-.445.777v4.607l4.429-2.536 5.31-3.047V7.157l-3.983 2.31z" fill="#EC5D3E"></path><path d="M10.98 18.941a.936.936 0 00-.305-.352l-4.429-2.516a.903.903 0 01-.431-.764v-5.078a.89.89 0 00-.452-.757l-.451-.26L1.38 7.158V18.39l5.311 3.047L11.126 24v-4.608a.881.881 0 00-.146-.45z" fill="#2464F5"></path></svg>
|
||||
|
After Width: | Height: | Size: 717 B |
@ -991,6 +991,56 @@ export const SYSTEM_MODELS: Record<string, Model[]> = {
|
||||
name: 'Gemma 7B',
|
||||
group: 'Gemma'
|
||||
}
|
||||
],
|
||||
'baidu-cloud': [
|
||||
{
|
||||
id: 'deepseek-r1',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'DeepSeek R1',
|
||||
group: 'DeepSeek'
|
||||
},
|
||||
{
|
||||
id: 'deepseek-v3',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'DeepSeek V3',
|
||||
group: 'DeepSeek'
|
||||
},
|
||||
{
|
||||
id: 'ernie-4.0-8k-latest',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'ERNIE-4.0',
|
||||
group: 'ERNIE'
|
||||
},
|
||||
{
|
||||
id: 'ernie-4.0-turbo-8k-latest',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'ERNIE 4.0 Trubo',
|
||||
group: 'ERNIE'
|
||||
},
|
||||
{
|
||||
id: 'ernie-speed-8k',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'ERNIE Speed',
|
||||
group: 'ERNIE'
|
||||
},
|
||||
{
|
||||
id: 'ernie-lite-8k',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'ERNIE Lite',
|
||||
group: 'ERNIE'
|
||||
},
|
||||
{
|
||||
id: 'bge-large-zh',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'BGE Large ZH',
|
||||
group: 'Embedding'
|
||||
},
|
||||
{
|
||||
id: 'bge-large-en',
|
||||
provider: 'baidu-cloud',
|
||||
name: 'BGE Large EN',
|
||||
group: 'Embedding'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import AzureProviderLogo from '@renderer/assets/images/models/microsoft.png'
|
||||
import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.jpg'
|
||||
import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.png'
|
||||
import BaichuanProviderLogo from '@renderer/assets/images/providers/baichuan.png'
|
||||
import BaiduCloudProviderLogo from '@renderer/assets/images/providers/baidu-cloud.svg'
|
||||
import BailianProviderLogo from '@renderer/assets/images/providers/bailian.png'
|
||||
import BytedanceProviderLogo from '@renderer/assets/images/providers/bytedance.png'
|
||||
import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png'
|
||||
@ -91,6 +92,8 @@ export function getProviderLogo(providerId: string) {
|
||||
return MistralProviderLogo
|
||||
case 'jina':
|
||||
return JinaProviderLogo
|
||||
case 'baidu-cloud':
|
||||
return BaiduCloudProviderLogo
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
@ -418,5 +421,16 @@ export const PROVIDER_CONFIG = {
|
||||
docs: 'https://learn.microsoft.com/en-us/azure/ai-services/openai/',
|
||||
models: 'https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models'
|
||||
}
|
||||
},
|
||||
'baidu-cloud': {
|
||||
api: {
|
||||
url: 'https://qianfan.baidubce.com/v2/'
|
||||
},
|
||||
websites: {
|
||||
official: 'https://cloud.baidu.com/',
|
||||
apiKey: 'https://cloud.baidu.com/console/qianfan/apikey',
|
||||
docs: 'https://cloud.baidu.com/doc/index.html',
|
||||
models: 'https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,6 +253,9 @@
|
||||
"error.chunk_overlap_too_large": "Chunk overlap cannot be greater than chunk size",
|
||||
"error.invalid.proxy.url": "Invalid proxy URL",
|
||||
"error.invalid.webdav": "Invalid WebDAV settings",
|
||||
"error.invalid.enter.api.host": "Please enter a valid API host",
|
||||
"error.invalid.enter.api.key": "Please enter a valid API key",
|
||||
"error.invalid.enter.model": "Please select a model",
|
||||
"message.code_style": "Code style",
|
||||
"message.delete.content": "Are you sure you want to delete this message?",
|
||||
"message.delete.title": "Delete Message",
|
||||
@ -316,6 +319,7 @@
|
||||
"aihubmix": "AiHubMix",
|
||||
"anthropic": "Anthropic",
|
||||
"azure-openai": "Azure OpenAI",
|
||||
"baidu-cloud": "Baidu Cloud",
|
||||
"baichuan": "Baichuan",
|
||||
"dashscope": "Alibaba Cloud",
|
||||
"deepseek": "DeepSeek",
|
||||
|
||||
@ -247,6 +247,9 @@
|
||||
"error.chunk_overlap_too_large": "チャンクの重なりは、チャンクサイズを超えることはできません",
|
||||
"error.invalid.proxy.url": "無効なプロキシURL",
|
||||
"error.invalid.webdav": "無効なWebDAV設定",
|
||||
"error.invalid.enter.api.host": "APIホストを入力してください",
|
||||
"error.invalid.enter.api.key": "APIキーを入力してください",
|
||||
"error.invalid.enter.model": "モデルを選択してください",
|
||||
"message.code_style": "コードスタイル",
|
||||
"message.delete.content": "このメッセージを削除してもよろしいですか?",
|
||||
"message.delete.title": "メッセージを削除",
|
||||
@ -310,6 +313,7 @@
|
||||
"aihubmix": "AiHubMix",
|
||||
"anthropic": "Anthropic",
|
||||
"azure-openai": "Azure OpenAI",
|
||||
"baidu-cloud": "Baidu Cloud",
|
||||
"baichuan": "百川",
|
||||
"dashscope": "Alibaba Cloud",
|
||||
"deepseek": "DeepSeek",
|
||||
|
||||
@ -248,6 +248,9 @@
|
||||
"error.chunk_overlap_too_large": "Перекрытие фрагментов не может быть больше размера фрагмента.",
|
||||
"error.invalid.proxy.url": "Неверный URL прокси",
|
||||
"error.invalid.webdav": "Неверные настройки WebDAV",
|
||||
"error.invalid.enter.api.host": "Пожалуйста, введите правильный API хост",
|
||||
"error.invalid.enter.api.key": "Пожалуйста, введите правильный API ключ",
|
||||
"error.invalid.enter.model": "Пожалуйста, выберите модель",
|
||||
"message.code_style": "Стиль кода",
|
||||
"message.delete.content": "Вы уверены, что хотите удалить это сообщение?",
|
||||
"message.delete.title": "Удалить сообщение",
|
||||
@ -311,6 +314,7 @@
|
||||
"aihubmix": "AiHubMix",
|
||||
"anthropic": "Anthropic",
|
||||
"azure-openai": "Azure OpenAI",
|
||||
"baidu-cloud": "Baidu Cloud",
|
||||
"baichuan": "Baichuan",
|
||||
"dashscope": "Alibaba Cloud",
|
||||
"deepseek": "DeepSeek",
|
||||
|
||||
@ -254,6 +254,9 @@
|
||||
"error.chunk_overlap_too_large": "分段重叠不能大于分段大小",
|
||||
"error.invalid.proxy.url": "无效的代理地址",
|
||||
"error.invalid.webdav": "无效的 WebDAV 设置",
|
||||
"error.invalid.api.key": "无效的 API 密钥",
|
||||
"error.invalid.api.host": "无效的 API 地址",
|
||||
"error.invalid.enter.model": "请选择一个模型",
|
||||
"message.code_style": "代码风格",
|
||||
"message.delete.content": "确定要删除此消息吗?",
|
||||
"message.delete.title": "删除消息",
|
||||
@ -317,6 +320,7 @@
|
||||
"aihubmix": "AiHubMix",
|
||||
"anthropic": "Anthropic",
|
||||
"azure-openai": "Azure OpenAI",
|
||||
"baidu-cloud": "百度云千帆",
|
||||
"baichuan": "百川",
|
||||
"dashscope": "阿里云百炼",
|
||||
"deepseek": "深度求索",
|
||||
|
||||
@ -253,6 +253,9 @@
|
||||
"error.chunk_overlap_too_large": "分段重疊不能大於分段大小",
|
||||
"error.invalid.proxy.url": "無效的代理 URL",
|
||||
"error.invalid.webdav": "無效的 WebDAV 設定",
|
||||
"error.invalid.enter.api.host": "請輸入有效的 API 主機地址",
|
||||
"error.invalid.enter.api.key": "請輸入有效的 API 密鑰",
|
||||
"error.invalid.enter.model": "請選擇一個模型",
|
||||
"message.code_style": "程式碼風格",
|
||||
"message.delete.content": "確定要刪除此訊息嗎?",
|
||||
"message.delete.title": "刪除訊息",
|
||||
@ -316,6 +319,7 @@
|
||||
"aihubmix": "AiHubMix",
|
||||
"anthropic": "Anthropic",
|
||||
"azure-openai": "Azure OpenAI",
|
||||
"baidu-cloud": "百度云千帆",
|
||||
"baichuan": "百川",
|
||||
"dashscope": "阿里雲百鍊",
|
||||
"deepseek": "深度求索",
|
||||
|
||||
@ -42,7 +42,7 @@ const PopupContainer: React.FC<Props> = ({ title, provider, model, apiKeys, reso
|
||||
for (let i = 0; i < newStatuses.length; i++) {
|
||||
setKeyStatuses((prev) => prev.map((status, idx) => (idx === i ? { ...status, checking: true } : status)))
|
||||
|
||||
const valid = await checkApi({ ...provider, apiKey: newStatuses[i].key }, model)
|
||||
const { valid } = await checkApi({ ...provider, apiKey: newStatuses[i].key }, model)
|
||||
|
||||
setKeyStatuses((prev) =>
|
||||
prev.map((status, idx) => (idx === i ? { ...status, checking: false, isValid: valid } : status))
|
||||
|
||||
@ -128,13 +128,19 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
} else {
|
||||
setApiChecking(true)
|
||||
|
||||
const valid = await checkApi({ ...provider, apiKey, apiHost }, model)
|
||||
const { valid, error } = await checkApi({ ...provider, apiKey, apiHost }, model)
|
||||
|
||||
const errorMessage = error && error?.message ? ' ' + error?.message : ''
|
||||
|
||||
window.message[valid ? 'success' : 'error']({
|
||||
key: 'api-check',
|
||||
style: { marginTop: '3vh' },
|
||||
duration: valid ? 2 : 8,
|
||||
content: valid ? i18n.t('message.api.connection.success') : i18n.t('message.api.connection.failed')
|
||||
content: valid
|
||||
? i18n.t('message.api.connection.success')
|
||||
: i18n.t('message.api.connection.failed') + errorMessage
|
||||
})
|
||||
|
||||
setApiValid(valid)
|
||||
setApiChecking(false)
|
||||
setTimeout(() => setApiValid(false), 3000)
|
||||
|
||||
@ -3,7 +3,7 @@ import { isEmbeddingModel } from '@renderer/config/models'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { Provider } from '@renderer/types'
|
||||
import { Modal, Select } from 'antd'
|
||||
import { last, orderBy } from 'lodash'
|
||||
import { first, orderBy } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
|
||||
interface ShowParams {
|
||||
@ -18,7 +18,7 @@ interface Props extends ShowParams {
|
||||
const PopupContainer: React.FC<Props> = ({ provider, resolve, reject }) => {
|
||||
const models = orderBy(provider.models, 'group').filter((i) => !isEmbeddingModel(i))
|
||||
const [open, setOpen] = useState(true)
|
||||
const [model, setModel] = useState(last(models))
|
||||
const [model, setModel] = useState(first(models))
|
||||
|
||||
const onOk = () => {
|
||||
if (!model) {
|
||||
|
||||
@ -461,7 +461,7 @@ export default class OpenAIProvider extends BaseProvider {
|
||||
public async getEmbeddingDimensions(model: Model): Promise<number> {
|
||||
const data = await this.sdk.embeddings.create({
|
||||
model: model.id,
|
||||
input: 'hi'
|
||||
input: model?.provider === 'baidu-cloud' ? ['hi'] : 'hi'
|
||||
})
|
||||
return data.data[0].embedding.length
|
||||
}
|
||||
|
||||
@ -206,25 +206,37 @@ export async function checkApi(provider: Provider, model: Model) {
|
||||
if (provider.id !== 'ollama') {
|
||||
if (!provider.apiKey) {
|
||||
window.message.error({ content: i18n.t('message.error.enter.api.key'), key, style })
|
||||
return false
|
||||
return {
|
||||
valid: false,
|
||||
error: new Error('message.error.enter.api.key')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!provider.apiHost) {
|
||||
window.message.error({ content: i18n.t('message.error.enter.api.host'), key, style })
|
||||
return false
|
||||
return {
|
||||
valid: false,
|
||||
error: new Error('message.error.enter.api.host')
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmpty(provider.models)) {
|
||||
window.message.error({ content: i18n.t('message.error.enter.model'), key, style })
|
||||
return false
|
||||
return {
|
||||
valid: false,
|
||||
error: new Error('message.error.enter.model')
|
||||
}
|
||||
}
|
||||
|
||||
const AI = new AiProvider(provider)
|
||||
|
||||
const { valid } = await AI.check(model)
|
||||
const { valid, error } = await AI.check(model)
|
||||
|
||||
return valid
|
||||
return {
|
||||
valid,
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
function hasApiKey(provider: Provider) {
|
||||
|
||||
@ -63,6 +63,16 @@ const initialState: LlmState = {
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
id: 'baidu-cloud',
|
||||
name: 'Baidu Cloud',
|
||||
type: 'openai',
|
||||
apiKey: '',
|
||||
apiHost: 'https://qianfan.baidubce.com/v2/',
|
||||
models: SYSTEM_MODELS['baidu-cloud'],
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
id: 'ollama',
|
||||
name: 'Ollama',
|
||||
|
||||
@ -910,6 +910,16 @@ const migrateConfig = {
|
||||
},
|
||||
'64': (state: RootState) => {
|
||||
state.llm.providers = state.llm.providers.filter((provider) => provider.id !== 'qwenlm')
|
||||
state.llm.providers.push({
|
||||
id: 'baidu-cloud',
|
||||
name: 'Baidu Cloud',
|
||||
type: 'openai',
|
||||
apiKey: '',
|
||||
apiHost: 'https://qianfan.baidubce.com/v2/',
|
||||
models: SYSTEM_MODELS['baidu-cloud'],
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
})
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user