From c52bb47fefbb2612e182430e0c788421d5898132 Mon Sep 17 00:00:00 2001
From: Phantom <59059173+EurFelux@users.noreply.github.com>
Date: Sat, 2 Aug 2025 14:45:09 +0800
Subject: [PATCH] feat(llm): add provider Poe (#8758)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat(llm): 添加Poe作为新的LLM提供商
- 在SYSTEM_MODELS中添加Poe的GPT-4o模型
- 在INITIAL_PROVIDERS中新增Poe提供商配置
- 添加Poe提供商logo资源文件
- 更新migrate.ts处理版本127的迁移逻辑
- 增加Poe提供商的相关文档链接配置
* feat(provider): 添加对开发者角色支持提供商的检查功能
在OpenAI客户端中根据提供商支持情况动态设置角色
---
.../aiCore/clients/openai/OpenAIApiClient.ts | 3 ++-
.../clients/openai/OpenAIResponseAPIClient.ts | 7 ++++++-
.../src/assets/images/providers/poe.svg | 1 +
src/renderer/src/config/models.ts | 10 +++++++++-
src/renderer/src/config/providers.ts | 20 ++++++++++++++++++-
src/renderer/src/store/index.ts | 2 +-
src/renderer/src/store/llm.ts | 10 ++++++++++
src/renderer/src/store/migrate.ts | 9 +++++++++
8 files changed, 57 insertions(+), 5 deletions(-)
create mode 100644 src/renderer/src/assets/images/providers/poe.svg
diff --git a/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts b/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts
index b5d1954bc9..d4ad386a4a 100644
--- a/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts
+++ b/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts
@@ -62,6 +62,7 @@ import { ChatCompletionContentPart, ChatCompletionContentPartRefusal, ChatComple
import { GenericChunk } from '../../middleware/schemas'
import { RequestTransformer, ResponseChunkTransformer, ResponseChunkTransformerContext } from '../types'
import { OpenAIBaseClient } from './OpenAIBaseClient'
+import { isSupportDeveloperRoleProvider } from '@renderer/config/providers'
const logger = loggerService.withContext('OpenAIApiClient')
@@ -491,7 +492,7 @@ export class OpenAIAPIClient extends OpenAIBaseClient<
if (isSupportedReasoningEffortOpenAIModel(model)) {
systemMessage = {
- role: 'developer',
+ role: isSupportDeveloperRoleProvider(this.provider) ? 'developer' : 'system',
content: `Formatting re-enabled${systemMessage ? '\n' + systemMessage.content : ''}`
}
}
diff --git a/src/renderer/src/aiCore/clients/openai/OpenAIResponseAPIClient.ts b/src/renderer/src/aiCore/clients/openai/OpenAIResponseAPIClient.ts
index 2cc34ddb97..cc9dba7095 100644
--- a/src/renderer/src/aiCore/clients/openai/OpenAIResponseAPIClient.ts
+++ b/src/renderer/src/aiCore/clients/openai/OpenAIResponseAPIClient.ts
@@ -44,6 +44,7 @@ import { ResponseInput } from 'openai/resources/responses/responses'
import { RequestTransformer, ResponseChunkTransformer } from '../types'
import { OpenAIAPIClient } from './OpenAIApiClient'
import { OpenAIBaseClient } from './OpenAIBaseClient'
+import { isSupportDeveloperRoleProvider } from '@renderer/config/providers'
export class OpenAIResponseAPIClient extends OpenAIBaseClient<
OpenAI,
@@ -369,7 +370,11 @@ export class OpenAIResponseAPIClient extends OpenAIBaseClient<
type: 'input_text'
}
if (isSupportedReasoningEffortOpenAIModel(model)) {
- systemMessage.role = 'developer'
+ if (isSupportDeveloperRoleProvider(this.provider)) {
+ systemMessage.role = 'developer'
+ } else {
+ systemMessage.role = 'system'
+ }
}
// 2. 设置工具
diff --git a/src/renderer/src/assets/images/providers/poe.svg b/src/renderer/src/assets/images/providers/poe.svg
new file mode 100644
index 0000000000..1083effc31
--- /dev/null
+++ b/src/renderer/src/assets/images/providers/poe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts
index a93b6b1b18..45100719dc 100644
--- a/src/renderer/src/config/models.ts
+++ b/src/renderer/src/config/models.ts
@@ -2346,7 +2346,15 @@ export const SYSTEM_MODELS: Record = {
}
],
'new-api': [],
- 'aws-bedrock': []
+ 'aws-bedrock': [],
+ poe: [
+ {
+ id: 'gpt-4o',
+ name: 'GPT-4o',
+ provider: 'poe',
+ group: 'poe'
+ }
+ ]
}
export const TEXT_TO_IMAGES_MODELS = [
diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts
index 693f7a3988..85e53bef56 100644
--- a/src/renderer/src/config/providers.ts
+++ b/src/renderer/src/config/providers.ts
@@ -15,6 +15,7 @@ import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png
import DmxapiProviderLogo from '@renderer/assets/images/providers/DMXAPI.png'
import FireworksProviderLogo from '@renderer/assets/images/providers/fireworks.png'
import GiteeAIProviderLogo from '@renderer/assets/images/providers/gitee-ai.png'
+import PoeProviderLogo from '@renderer/assets/images/providers/poe.svg'
import GithubProviderLogo from '@renderer/assets/images/providers/github.png'
import GoogleProviderLogo from '@renderer/assets/images/providers/google.png'
import GPUStackProviderLogo from '@renderer/assets/images/providers/gpustack.svg'
@@ -53,6 +54,7 @@ import ZeroOneProviderLogo from '@renderer/assets/images/providers/zero-one.png'
import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png'
import { TOKENFLUX_HOST } from './constant'
+import { Provider } from '@renderer/types'
const PROVIDER_LOGO_MAP = {
ph8: Ph8ProviderLogo,
@@ -108,7 +110,8 @@ const PROVIDER_LOGO_MAP = {
lanyun: LanyunProviderLogo,
vertexai: VertexAIProviderLogo,
'new-api': NewAPIProviderLogo,
- 'aws-bedrock': AwsProviderLogo
+ 'aws-bedrock': AwsProviderLogo,
+ poe: PoeProviderLogo
} as const
export function getProviderLogo(providerId: string) {
@@ -702,5 +705,20 @@ export const PROVIDER_CONFIG = {
docs: 'https://docs.aws.amazon.com/bedrock/',
models: 'https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html'
}
+ },
+ poe: {
+ api: {
+ url: 'https://api.poe.com/v1'
+ },
+ websites: {
+ official: 'https://poe.com/',
+ apiKey: 'https://poe.com/api_key',
+ docs: 'https://creator.poe.com/docs/external-applications/openai-compatible-api',
+ models: 'https://poe.com/'
+ }
}
}
+
+export const isSupportDeveloperRoleProvider = (provider: Provider) => {
+ return provider.id !== 'poe'
+}
diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts
index f0912b24a3..88df884f74 100644
--- a/src/renderer/src/store/index.ts
+++ b/src/renderer/src/store/index.ts
@@ -60,7 +60,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
- version: 126,
+ version: 127,
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs'],
migrate
},
diff --git a/src/renderer/src/store/llm.ts b/src/renderer/src/store/llm.ts
index b54c8c67d7..2534b6cdae 100644
--- a/src/renderer/src/store/llm.ts
+++ b/src/renderer/src/store/llm.ts
@@ -552,6 +552,16 @@ export const INITIAL_PROVIDERS: Provider[] = [
models: SYSTEM_MODELS['aws-bedrock'],
isSystem: true,
enabled: false
+ },
+ {
+ id: 'poe',
+ name: 'Poe',
+ type: 'openai',
+ apiKey: '',
+ apiHost: 'https://api.poe.com/v1/',
+ models: SYSTEM_MODELS['poe'],
+ isSystem: true,
+ enabled: false
}
]
diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts
index 1a3313cbed..44ba1bcd01 100644
--- a/src/renderer/src/store/migrate.ts
+++ b/src/renderer/src/store/migrate.ts
@@ -1958,6 +1958,15 @@ const migrateConfig = {
logger.error('migrate 126 error', error as Error)
return state
}
+ },
+ '127': (state: RootState) => {
+ try {
+ addProvider(state, 'poe')
+ return state
+ } catch (error) {
+ logger.error('migrate 127 error', error as Error)
+ return state
+ }
}
}